Передача Torque PBS переменных среды, содержащих кавычки

У меня есть скрипт на питоне. Обычно я бы запускал это так:

./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.


person cs_alumnus    schedule 21.03.2015    source источник


Ответы (1)


Обновление: этот ответ основан на SGE qsub, а не на TORQUE qsub, поэтому интерфейс командной строки несколько отличается. В частности, TORQUE qub, похоже, не поддерживает прямую передачу аргументов, поэтому второй подход не работает.


В основном это проблема правильного цитирования и имеет мало общего с самой отправкой движка сетки. Если вы просто хотите исправить текущий скрипт, вам следует использовать 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. Expanding ${CMD} to its value /path/make_graph data_directory "wonderful graph title";
    2. Поскольку ${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

Хорошо, я просто указал, что не так, и исправил это. Но действительно ли это «правильный способ» передавать аргументы заданиям grid engine? Нет, я так не думаю. Аргументы есть аргументы, и их не следует путать с переменными среды. 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. И, насколько я знаю, нет простого способа исправить это, поскольку кавычки всегда удаляются из аргументов, независимо от того, как выполняется разбиение на слова. Если напечатанная команда действительно важна для вас, есть два решения:

  1. Используйте специальный «экран-экран» (довольно легко написать его для себя), чтобы процитировать аргументы перед печатью;

  2. Используйте другой язык сценариев, где кавычки оболочки легко доступны, например, Python (shlex.quote) или Ruby (Shellwords.shellescape).

person 4ae1e1    schedule 21.03.2015
comment
Спасибо за это подробное объяснение. Я хотел бы, чтобы это было правильно. Пробую предложенный вами патч. К сожалению, хотя он работает правильно с предложенным вами методом тестирования bash, кавычки по-прежнему удаляются при запуске с помощью планировщика. - person cs_alumnus; 21.03.2015
comment
когда я печатаю аргументы с помощью метода bash, кавычки сохраняются. когда я печатаю их с помощью qsub, они исчезают. Таким образом, он удаляется перед добавлением в CMD #!/bin/bash echo $0 USAGE=USAGE: qsub make_graph.pbs -v ARGS=\...\ if [ ! -z ${PBS_O_WORKDIR+xxx}]; затем cd $PBS_O_WORKDIR fi [[ -z ${ARGS+xxx} ]] && { echo NO ARGS SPECIFIED! › выход 1; } echo ARGS: ${ARGS} echo команда сборки CMD=/path/make_graph.py ${ARGS} echo CMD: ${CMD} - person cs_alumnus; 21.03.2015
comment
если я все еще не вызываю это неправильно bash test ARGS=/path/ \wonderful title\ bash make_graph.pbs scheduler test qsub make_graph.pbs -v ARGS=/path/ \wonderful title\ - person cs_alumnus; 21.03.2015
comment
Это неожиданно, но, честно говоря, я не часто использую параметр -v и уж точно не использую его для передачи аргументов. Не могли бы вы дать мне несколько минут, чтобы посмотреть на эту проблему (моя очередь сейчас сильно забита)? А пока не могли бы вы попробовать мой второй сценарий? Это более естественный способ передачи аргументов. - person 4ae1e1; 21.03.2015
comment
Я ценю помощь. Не торопись. Я потратил на это слишком много времени, поэтому сейчас я просто буду использовать _ вместо пробелов. - person cs_alumnus; 21.03.2015
comment
Подождите секунду, я только что заметил, что вы называете qsub не так. Вы должны использовать qsub -v ARGS="data_directory \"wonderful graph title\"" make_graph.pbs. Все параметры после вашего файла сценария принимаются в качестве аргументов вашего сценария, а не параметров qsub. - person 4ae1e1; 21.03.2015
comment
И мои локальные тесты говорят, что мой сценарий отправки работает правильно, когда вы вызываете qsub правильно. - person 4ae1e1; 21.03.2015
comment
К сожалению, здесь это не имеет значения. У меня версия 3.03 крутящего момента pbs, возможно, это ошибка. Текущий 4,27 я думаю. Вызов этого как qsub -v ARGS=data_directory \прекрасное название\ make_graph.pbs - person cs_alumnus; 21.03.2015
comment
просматривая журнал изменений для крутящего момента, github.com/adaptivecomputing/torque/blob/master /CHANGELOG#L303 похоже, что это могло быть исправлено в 4.2.0. Я собираюсь отметить этот ответ как правильный. - person cs_alumnus; 21.03.2015
comment
Хм дерьмо. Я применяю здесь свои знания qsub от SGE и думал, что интерфейсы будут одинаковыми, но похоже, что они несколько отличаются. И запись в журнале изменений ясно дает понять, что цитирование значения просто не будет работать в вашей старой версии :( - person 4ae1e1; 21.03.2015
comment
Я прочитал справочную страницу TORQUE PBS qsub и, к сожалению, она не поддерживает прямую передачу аргументов (в отличие от SGE qsub). Извините за путаницу. - person 4ae1e1; 21.03.2015
comment
Кстати, поскольку ARGS не работает, я думаю, вам лучше использовать подход param1=value1,param2=value2,..., то есть использовать -v directory=some_directory,title=some_title и разобрать $directory и $title в вашем сценарии отправки. - person 4ae1e1; 21.03.2015