Согласно ответу 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
будет передан обратно в захваченную интерполированную строку
<<
начинается Bash 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}"
ssh user@server /bin/bash <<EOT…