drmaa를 통한 qsub 명령의 쉘 변수 확장

drmaa를 통한 qsub 명령의 쉘 변수 확장

다음 명령을 사용하여 SGE(Sun Grid Engine)에 일괄 작업 제출을 실행 중입니다.파이썬 drmaa 바인딩.

일괄 작업 제출의 경우 매개 변수를 허용하고 shebang을 통해 명령줄에서 실행 가능한 Python 스크립트를 제출합니다. 작업 배치 제출을 적절하게 매개변수화하기 위해 options 를 통해 Python 스크립트에 전파되도록 환경 변수를 설정했습니다 -v. 작업 제출 중에 내보낸 SGE/환경 변수를 기반으로 $TASK_IDzsh 환경에서 간접 변수 확장을 수행 하려고 합니다.$SGE_TASK_ID

간접 변수 확장의 최소한의 재현 가능한 예로서 비슷한 작업을 시도하고 있으며 내 셸에서 작동합니다.

export foo1=2
export num=1

echo $(tmp=foo$num; echo ${(P)tmp})

생산하다2

샘플 스크립트job_script.py

#! /usr/bin/python
import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument("input_path", type=os.path.realpath)

def main(input_path):
    # do stuff
    ...

if __name__ == "__main__":
    args = parser.parse_args
    input_path = args.input_path
    main(input_path)

drmaa 제출 스크립트 예


import os

# add path to libs
os.environ["DMRAA_LIBRARY_PATH"] = "path to DMRAA shared object"
os.environ["SGE_ROOT"] = "path to SGE root directory"
import drmaa

input_dir_suffixes = [1, 2, 5, 7, 10, 11]

INPUT_BASE_DIR = "/home/mel/input_data"

base_qsub_options = {
    "P": "project",
    "q": "queue",
    "b": "y", # means is an executable
    "shell": "y", # start up shell
}
native_specification = " ".join(f"-{k} {v}" for k,v in base_qsub_options.items())
remote_command = "job_script.py"

num_task_ids = len(input_dir_suffixes)
task_start = 1
task_stop = num_task_ids + 1
task_step = 1
task_id_zip = zip(range(1, num_task_ids + 1), input_dir_suffixes) 
task_id_env_vars = {
   f"TASK_ID_{task_id}_SUFFIX": str(suffix) for task_id, suffix in task_id_zip 
}

io_task_id = r"$(tmp=SUFFIX_TASK_ID_$TASK_ID; echo ${(P)tmp)})"
arg_task_id = r"$(tmp=SUFFIX_TASK_ID_$SGE_TASK_ID; echo ${(P)tmp)})"

with drmaa.Session() as session:
    
    template = session.createJobTemplate()
    template.nativeSpecification = native_specification
    template.remoteCommand = remote_command
    template.jobEnvironment = task_id_env_vars
    template.outputPath = f":{INPUT_BASE_DIR}/output/{io_task_id}.o"
    template.outputPath = f":{INPUT_BASE_DIR}/error/{io_task_id}.e"

    args_list = [f"{INPUT_BASE_DIR}/data{arg_task_id}"]
    template.args = args_list
    session.runBulkJobs(template, task_start, task_stop - 1, task_step)
    session.deleteJobTemplate(template)

구문 오류가 있는 경우 죄송합니다. 다른 시스템에 있으므로 수동으로 복사해야 했습니다.

제출 완료 후

내가 직장 qstat -j전화번호 라면

다음 설정이 표시됩니다

sge_o_shell:         /usr/bin/zsh
stderr_path_list:    NONE:<node>:/home/mel/input_data/error_log/$(tmp=SUFFIX_TASK_ID_$TASK_ID; echo ${(P)tmp}).e
stdout_path_list:    NONE:<node>:/home/mel/input_data/output_log/$(tmp=SUFFIX_TASK_ID_$TASK_ID; echo ${(P)tmp}).o
job_args:            /home/mel/input_data/data$(tmp=SUFFIX_TASK_ID$SGE_TASK_ID; echo ${(P)tmp})
script_file:         job_script.py

env_list: 
SUFFIX_TASK_ID_1=1,SUFFIX_TASK_ID_2=2,SUFFIX_TASK_ID_3=5,SUFFIX_TASK_ID_4=7,SUFFIX_TASK_ID_5=10,SUFFIX_TASK_ID_6=11

오류 로그와 출력 로그는 별도로 생성되지만 부분적으로만 확장됩니다.

$(tmp=SUFFIX_TASK_ID1; echo ${(P)tmp}).e
$(tmp=SUFFIX_TASK_ID1; echo ${(P)tmp}).o

cat오류 로그를 보면Illegal variable name

내가 하고 싶은 일이 가능한 일인가?

그래서 어딘가에서 내 zsh가 올바르게 활성화되지 않는다고 가정합니다.

답변1

SGE는 Bourne 셸( /bin/sh)을 작업 스크립트의 기본 셸로 사용합니다. 이로 인해 다른 셸의 특정 기능이나 구문에 의존하는 스크립트에 문제가 발생할 수 있습니다. 귀하의 경우에는 zsh기능(을 사용한 매개변수 확장 ) 을 사용하려고 합니다 ${(P)tmp}.

문제는 DRMAA 작업에서 수행하려는 쉘 변수 확장과 관련된 것 같습니다. ${(P)tmp}작업이 SGE에 제출될 때 간접 변수 확장( )이 올바르게 인식되지 않는 것 같습니다 .

여기서는 로그인 쉘이 zsh( sge_o_shell: /usr/bin/zsh)일 수 있지만 쉘은설명하다qsub 명령줄 매개변수 및 DRMAA 작업 제출 매개변수는 zsh. 이 ${(P)tmp}구문은 에만 적용되며 이러한 인수를 해석하는 셸일 수 있는 또는 zsh등의 다른 셸에서는 작동하지 않습니다 .bashsh

-v따라서 DRMAA 스크립트에서 옵션(환경 변수 전달) 및 명령 대체( )를 사용하여 작업을 제출할 때 $(...)SGE는 명령의 해당 부분을 해석하는 데 사용되지 않을 수 있으며 zsh이로 zsh인해 특정 구문이 작동하지 않습니다.

이는 변수 확장을 수행하기 위해 래퍼 스크립트를 생성한 zsh다음 결과와 함께 Python 스크립트를 호출해야 할 수도 있음을 의미합니다. 래퍼 스크립트는 작업 스크립트로 제출되며 zsh를 통해 실행할 때 기능을 사용할 수 있습니다 zsh.

#!/usr/bin/env zsh

# use zsh for variable expansion
suffix=$(tmp=SUFFIX_TASK_ID_$TASK_ID; echo ${(P)tmp})

# call the python script with the result(s)
exec /path/to/job_script.py /home/mel/input_data/data$suffix

DRMAA 스크립트 내의 작업으로 래퍼 스크립트를 제출하고 다음을 사용하여 실행되도록 지정합니다 zsh.

...
# path to the wrapper script
remote_command = "/path/to/wrapper_script.zsh"

...
# specify that the job should be run with zsh
base_qsub_options = {
    ...
    "shell": "/usr/bin/zsh",
    ...
}
...

알아채다:필요에 따라 이를 조정해야 할 수도 있습니다.

관련 정보