Відповідно до 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…