Сбой при выводе удаленной команды ssh - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь зафиксировать вывод удаленно выполняемой команды в сценарии bash, чтобы сценарий мог выполнить некоторую обработку результата, и результат меня смущает:

$ COMMAND="ssh localhost \"echo 'hello'\""
$ OUTPUT=$($COMMAND)
bash: echo 'hello': command not found

Использование обратных кавычек дает немного другой результат:

$ `ssh localhost "echo 'hello'"`
-bash: hello: command not found

Но команда выполняется так, как я и ожидал, без какой-либо оболочки:

$ ssh localhost "echo 'hello'"
hello

Я подозреваю, что неправильно понимаю нечто довольно простое о том, как выполняются эти команды. Я здесь что-то делаю неправильно или есть лучший способ сделать это?

1 Ответ

0 голосов
/ 16 января 2019

проблема

Котировки ("...") не оцениваются, когда вы делаете:

$($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'" разделяются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...