次のコマンドを使用して Sun Grid Engine (SGE) にバッチジョブの送信を実行しています。Python drmaaバインディング。
バッチジョブの送信の場合は、パラメータを受け入れ、shebangを介してコマンドラインから実行可能なPythonスクリプトを送信します。タスクバッチ送信を適切にパラメータ化するために、optionsを介してPythonスクリプトに伝播するように環境変数を設定しました-v
。ジョブの送信中にエクスポートされたSGE /環境変数に基づいて$TASK_ID
zsh環境で間接変数拡張を実行しようとしています。$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
他のシェルでは機能しません。bash
sh
-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",
...
}
...
気づく:必要に応じて調整する必要があります。