Согласно ответу 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…