Відповідно до zanco , ви не надаєте віддалену команду ssh, враховуючи, як оболонка аналізує командний рядок. Щоб вирішити цю проблему, змініть синтаксис sshвиклику вашої команди так, щоб віддалена команда складалася з синтаксично правильного багаторядкового рядка.
Існують різноманітні синтаксиси, які можна використовувати. Наприклад, оскільки команди можуть бути вкладені в bashі sh, можливо, і в інші оболонки, найпростішим рішенням є просто поєднання sshвиклику оболонки з гередоками:
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розпізнає гередок як теперішній документ , вимикаючи локальну змінну інтерполяцію, так що текст команди буде передано як є 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буде переданий назад у захоплюючий інтерпольований рядок
<<починається баш гередок
'EOT'вказує, що ім'я гередок - EOT. Єдині цитати 'навколо EOT вказують, що гередок повинен бути проаналізований як теперішній документ , що є особливою формою гередока, в якій вміст не інтерполюється башем, а передається у прямому форматі
Будь-який вміст, який зустрічається між собою <<'EOT'та <newline>EOT<newline>буде доданий до виводу nowdoc
EOTзавершує команду nowdoc, в результаті чого створюється тимчасовий файл nowdoc і передається назад до викликової catкоманди. catвиводить nowdoc і передає результат назад в захоплюючу інтерпольовану рядок
) завершує команду, яку потрібно виконати
"завершує захоплення інтерпольованого рядка. Вміст інтерпольованого рядка буде передано назад sshяк єдиний аргумент командного рядка, який sshінтерпретуватиме як віддалену команду для виконання якuser@server
Якщо вам потрібно уникати використання зовнішніх інструментів, таких як cat, і не заперечуйте, щоб мати два оператори замість одного, використовуйте readвбудований гередок для створення команди 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…