Torque PBS传递包含引号的环境变量

时间:2015-03-21 06:05:09

标签: bash pbs quoting torque

我有一个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问题。

1 个答案:

答案 0 :(得分:2)

更新:此答案基于SGE qsub而非TORQUE qsub,因此CLI略有不同。特别是,TORQUE qub似乎不支持直接参数传递,所以第二种方法不起作用。


这主要是正确引用的问题,与Grid Engine提交本身没什么关系。如果您只想修复当前脚本,则应使用eval "${CMD}"而不是${CMD}。这里详细分析了当你单独${CMD}时会发生什么(在我们假设的分析中path没有什么好笑的):

  1. 处理了qsub命令行并删除了引号,因此传递的ARGS环境变量为data_directory "wonderful graph title"

  2. 您执行了CMD="/path/make_graph $ARGS",因此CMD的值为/path/make_graph data_directory "wonderful graph title"(我在没有引用的情况下显示字符串文字,也就是说,字面值包含引用字符)。

  3. 你做过${CMD}。 Bash对此执行参数扩展,相当于:

    1. ${CMD}展开为其值/path/make_graph data_directory "wonderful graph title";
    2. 由于未引用${CMD},请执行分词,因此最后命令行有五个字:/path/make_graphdata_directory"wonderful,{{1} },graph。最后四个被视为title"的参数,这肯定不是你想要的。
  4. 另一方面,如果您使用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。据我所知,并没有简单的方法来解决这个问题,因为无论如何进行分词,引号总是从参数中删除。如果打印的命令对您来说非常重要,则有两种解决方案:

    1. 使用专用的" shell escaper" (很容易为自己编写一个)在打印前引用参数;

    2. 使用另一种脚本语言,其中可以使用shell引用,例如Python(make_graph.pbs data_directory wonderful graph title)或Ruby(shlex.quote)。