我有一个python脚本。通常我会这样运行:
./make_graph data_directory "wonderful graph title"
我必须通过调度程序运行此脚本。我使用-v通过qsub传递python脚本的参数。
qsub make_graph.pbs -v ARGS="data_directory \"wonderful graph title\""
我尝试了许多组合',",\"逃避,我只是无法做到正确。围绕“精彩图表标题”的引用'总是丢失或损坏。
以下是pbs脚本的摘录
if [ -z "${ARGS+xxx}" ]; then
echo "NO ARGS SPECIFIED!"
exit 1
fi
CMD="/path/make_graph $ARGS"
echo "CMD: $CMD"
echo "Job started on `hostname` at `date`"
${CMD}
通过qsub作为环境变量传递包含空格的字符串参数的正确方法是什么?有一个更好的方法吗?也许这是一个更普遍的bash问题。
答案 0 :(得分:2)
更新:此答案基于SGE qsub
而非TORQUE qsub
,因此CLI略有不同。特别是,TORQUE qub
似乎不支持直接参数传递,所以第二种方法不起作用。
这主要是正确引用的问题,与Grid Engine提交本身没什么关系。如果您只想修复当前脚本,则应使用eval "${CMD}"
而不是${CMD}
。这里详细分析了当你单独${CMD}
时会发生什么(在我们假设的分析中path
没有什么好笑的):
处理了qsub
命令行并删除了引号,因此传递的ARGS
环境变量为data_directory "wonderful graph title"
。
您执行了CMD="/path/make_graph $ARGS"
,因此CMD
的值为/path/make_graph data_directory "wonderful graph title"
(我在没有引用的情况下显示字符串文字,也就是说,字面值包含引用字符)。
你做过${CMD}
。 Bash对此执行参数扩展,相当于:
${CMD}
展开为其值/path/make_graph data_directory "wonderful graph title"
; ${CMD}
,请执行分词,因此最后命令行有五个字:/path/make_graph
,data_directory
,"wonderful
,{{1} },graph
。最后四个被视为title"
的参数,这肯定不是你想要的。另一方面,如果您使用make_graph
,那就好像您在交互式shell中键入eval "${CMD}"
一样,这是所需的行为。
您应该在Bash Reference Manual中详细了解/path/make_graph data_directory "wonderful graph title"
,参数扩展等。
更正的脚本:
eval
顺便说一下,为了测试这个,你不需要将它提交给网格引擎;只是做
#!/usr/bin/env bash
[[ -z ${ARGS+xxx} ]] && { echo "NO ARGS SPECIFIED!" >&2; exit 1; }
CMD="/path/make_graph ${ARGS}"
echo "CMD: ${CMD}"
echo "Job started on $(hostname) at $(date)" # backticks are deprecated
eval "${CMD}"
好的,我只是指出了什么是错的并修补了它。但它真的是"正确的方式"将参数传递给Grid Engine作业?不,我不这么认为。参数是参数,不应与环境变量混淆。 ARGS="data_directory \"wonderful graph title\"" bash make_graph.pbs
允许您直接传递参数(qsub
概要:qsub
),那么为什么要在env var中对它们进行编码并最终担心引用呢?
这是编写提交脚本的更好方法:
qsub [ options ] [ command | -- [ command_args ]]
此处#!/usr/bin/env bash
[[ $# == 0 ]] && { echo "NO ARGS SPECIFIED!" >&2; exit 1; }
CMD="/path/make_graph $@"
echo "CMD: ${CMD}"
echo "Job started on $(hostname) at $(date)" # backticks are deprecated
/path/make_graph "$@"
相当于"$@"
- 忠实地传递所有参数(请参阅Bash参考手册中的relevant section)。
"$1" "$2" ...
然后执行的内容为qsub make_graph.pbs data_directory "wonderful graph title"
,但打印的make_graph.pbs data_directory "wonderful graph title"
为CMD
。据我所知,并没有简单的方法来解决这个问题,因为无论如何进行分词,引号总是从参数中删除。如果打印的命令对您来说非常重要,则有两种解决方案:
使用专用的" shell escaper" (很容易为自己编写一个)在打印前引用参数;
使用另一种脚本语言,其中可以使用shell引用,例如Python(make_graph.pbs data_directory wonderful graph title
)或Ruby(shlex.quote
)。