проблема
Котировки ("..."
) не оцениваются, когда вы делаете:
$($COMMAND)
Удаленный Bash видит два аргумента: "echo
и 'hello'"
, а не echo 'hello'
, как вы ожидаете.
Предлагаемое решение: массивы
В вашем случае я бы предложил использовать массив:
COMMAND=( ssh localhost "echo 'hello'" )
OUTPUT=$( "${COMMAND[@]}" )
Слова в (...)
являются элементами массива. В этом случае echo 'hello'
виден один элемент: кавычки оцениваются сразу во время назначения. Затем, когда вы выполните "${COMMAND[@]}"
, каждый элемент будет передан в качестве нетронутого аргумента.
Есть также несколько других способов решения этой проблемы, например, использование eval
, чтобы оценивать кавычки, но по моему опыту использование массивов - это самый безопасный и простой способ построения и выполнения команд. С помощью массивов легко предотвратить атаки с использованием оболочки, предотвратить нежелательное расширение, предотвратить разрыв слов при наличии пробела. Единственный недостаток - массивы доступны не в каждой оболочке.
Объяснение проблемы
Причина в том, что расширение (т.е. $COMMAND
) не оценивает кавычки.
Это демонстрируется на этом простом примере, где мы печатаем каждый аргумент по одному в строке:
$ COMMAND="ssh localhost \"echo 'hello'\""
$ for x in $COMMAND; do echo "$x"; done
ssh
localhost
"echo
'hello'"
Используя вместо этого массив:
$ COMMAND=( ssh localhost "echo 'hello'" )
$ for x in "${COMMAND[@]}"; do echo "$x"; done
ssh
localhost
echo 'hello'
В массиве echo 'hello'
находится в одной строке (т. Е. Это один аргумент), вместо простой строки "echo
и 'hello'"
разделяются.