Torque PBS передает переменные окружения, которые содержат кавычки
У меня есть скрипт на Python. Обычно я бы запустил это так:
./make_graph data_directory "wonderful graph title"
Я должен запустить этот скрипт через планировщик. Я использую -v для передачи аргументов скрипта python через qsub.
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 ответ
Обновление: Этот ответ основан на SGE qsub
а не МОМЕНТ qsub
Таким образом, CLI несколько отличается. В частности, МОМЕНТ qub
кажется, не поддерживает прямую передачу аргументов, поэтому второй подход не работает.
Это в основном проблема правильного цитирования и имеет мало общего с представлением самого механизма сетки. Если вы просто хотите исправить свой текущий скрипт, вы должны использовать 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
,graph
,title"
, Последние четыре рассматриваются как аргументы вашегоmake_graph
что, конечно, не то, что вы хотите.
- расширяющийся
С другой стороны, если вы используете eval "${CMD}"
тогда это как если бы вы набрали /path/make_graph data_directory "wonderful graph title"
в интерактивную оболочку, которая является желаемым поведением.
Вы должны прочитать больше о eval
, расширение параметров и т. д. в Справочном руководстве Bash.
Исправленный скрипт:
#!/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}"
Кстати, чтобы проверить это, вам не нужно отправлять его в механизм сетки; просто делать
ARGS="data_directory \"wonderful graph title\"" bash make_graph.pbs
Хорошо, я просто указал, что не так, и исправил это. Но действительно ли это "правильный способ" передавать аргументы заданиям грид-движка? Нет, я так не думаю. Аргументы являются аргументами, и их не следует путать с переменными среды. qsub
позволяет передавать аргументы напрямую (qsub
синопсис: qsub [ options ] [ command | -- [ command_args ]]
), так зачем кодировать их в env var и беспокоиться о цитировании?
Вот лучший способ написать свой скрипт представления:
#!/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 "$@"
Вот "$@"
эквивалентно "$1" "$2" ...
- добросовестно передавая все аргументы как есть (см. Соответствующий раздел в Справочном руководстве Bash).
Однако прискорбно то, что хотя выполненная команда верна, напечатанная команда может не быть в кавычках. Например, если вы делаете
qsub make_graph.pbs data_directory "wonderful graph title"
то, что исполняется make_graph.pbs data_directory "wonderful graph title"
, но напечатано CMD
является make_graph.pbs data_directory wonderful graph title
, Насколько мне известно, простого способа исправить это не существует, поскольку кавычки всегда удаляются из аргументов независимо от того, как выполняется разбиение слов. Если напечатанная команда действительно важна для вас, есть два решения:
Используйте выделенную "оболочку" (довольно легко написать для себя), чтобы процитировать аргументы перед печатью;
Используйте другой язык сценариев, где легко доступны цитаты оболочки, например, Python (
shlex.quote
) или рубин (Shellwords.shellescape
).