我正在尝试创建一个函数来代替SLURM的srun
命令。这个包装函数的需要是,我希望在SLURM控制下启动时使用srun
编写脚本,但是仍然能够在没有SLURM的情况下运行脚本。
到目前为止,我具有此功能:
srun_wrap() {
if [ -z "$SLURM_JOB_ID" ]
then
# Not running under SLURM so start the code without srun
"${@:2}"
else
# A SLURM job ID found, so use srun
srun ${@:1:1} "${@:2}"
fi
}
这使我可以像这样变换一行
srun --job-name listing ls
到一行
srun_wrapper "--job-name listing" ls
非常接近插件,但还没有。
原因是:
$SLURM_JOB_ID
的值
srun
参数),并运行其余命令行。srun
。命令行由srun
(第一个参数未加引号)组成,以允许srun
正确地识别参数,最后是真实的命令行已被正确加引号。这种方法仍然有两个缺点:
srun
参数必须不带引号,否则不要
由srun
正确解析。srun
参数必须用引号引起来,以被视为单个参数。srun ls
将转换为srun_wrapper "" ls
。关于如何克服这三个缺点的任何想法?如何引用括号扩展,如何避免引用srun
参数以及如何避免需要空参数?
答案 0 :(得分:0)
这是我想出的。 Shell向导可能会做得更好。这样可以解决您所有的缺点吗?
这确实有我正在研究的新缺点。标志不能有空格。因此,您必须像这样使用它们:srun_wrap --ntasks=2 ls
或srun_wrap -n2 ls
。
对echo
的调用和最后的函数调用仅用于调试。
#!/bin/bash
function srun_wrap {
i=1
for var in "$@"; do
# args starting with '-' up to the first that doesn't are srun
# flags. The rest of the args are the command
if [[ $var == -* ]]; then
flags=( "${flags[@]}" "$var" )
else
cmd="${@:$i}"
break
fi
i=$((i+1))
done
echo "flags = $flags"
echo "cmd = $cmd"
if [ "x$SLURM_JOB_ID" != "x" ]; then
# run in slurm
eval "srun ${flags[@]} ${cmd[@]}"
else
# run outside slurm
eval "${cmd[@]}"
fi
}
srun_wrap "$@"
要解决标志问题,您可以自己定义一个标志(如--cmd
之类的),以将srun标志与可执行文件分开。
srun_wrap --ntasks 2 --exclusive --cmd ls -alh
或者您可以像sbatch这样更明确地创建自己解析的--wrap=<command>
标志。不过,您必须引用它。
srun_wrap --ntasks 2 --exclusive --wrap="ls -alh"
唯一的另一种选择是自己创建一个选项解析器,以检测有效的运行标志。那将是很多工作,并且可能会产生错误。