За ответ zanco , вы не предоставляете удаленную команду для ssh
, учитывая, как оболочка анализирует командную строку. Чтобы решить эту проблему, измените синтаксис вызова ssh
, чтобы удаленная команда состояла из синтаксически правильной многострочной строки.
Существует множество синтаксисов, которые можно использовать. Например, поскольку команды могут быть переданы в bash
и sh
, а также, возможно, и в другие оболочки, самое простое решение - просто объединить вызов оболочки ssh
с heredocs:
ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
Обратите внимание, что выполнение вышеуказанного без /bin/bash
приведет к предупреждению Pseudo-terminal will not be allocated because stdin is not a terminal
. Также обратите внимание, что EOT
заключен в одинарные кавычки, поэтому bash
распознает heredoc как nowdoc , отключая интерполяцию локальной переменной, так что текст команды будет передаваться как есть в ssh
.
Если вы являетесь поклонником труб, вы можете переписать вышесказанное следующим образом:
cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
То же самое относится к /bin/bash
и выше.
Другой верный подход - передать многострочную удаленную команду в виде одной строки, используя несколько слоев bash
переменной интерполяции следующим образом:
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
Приведенное выше решение устраняет эту проблему следующим образом:
ssh user@server
анализируется bash и интерпретируется как команда ssh
, за которой следует аргумент user@server
для передачи в команду ssh
"
начинает интерполированную строку, которая после завершения будет содержать аргумент, который будет передан команде ssh
, которая в этом случае будет интерпретироваться ssh
как удаленная команда для выполнения как user@server
$(
начинает выполнение команды с вывода, захваченного окружающей интерполированной строкой
cat
- это команда для вывода содержимого любого файла. Вывод cat
будет передан обратно в интерполированную строку захвата
<<
начинается удар heredoc
'EOT'
указывает, что именем heredoc является EOT. Одинарные кавычки '
, окружающие EOT, указывают, что heredoc должен быть проанализирован как nowdoc , который представляет собой особую форму heredoc, в которой содержимое не интерполируется bash, а передается в буквальном формате
Любой контент, который встречается между <<'EOT'
и <newline>EOT<newline>
, будет добавлен к выводу nowdoc
EOT
завершает действие nowdoc, в результате чего создается временный файл nowdoc и передается обратно вызывающей команде cat
. cat
выводит nowdoc и передает вывод обратно в интерполированную строку захвата
)
завершает выполнение команды
"
завершает ввод интерполированной строки. Содержимое интерполированной строки будет передано обратно в ssh
как один аргумент командной строки, который ssh
будет интерпретироваться как удаленная команда для выполнения как user@server
Если вам нужно избегать использования внешних инструментов, таких как cat
, и не против иметь два оператора вместо одного, используйте встроенный read
с heredoc для генерации команды SSH:
IFS='' read -r -d '' SSH_COMMAND <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
ssh user@server "${SSH_COMMAND}"