![Невозможно выполнить команду через ssh](https://rvso.com/image/1711437/%D0%9D%D0%B5%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%20%D0%B2%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D1%8C%20%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%83%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20ssh.png)
Я запускаю команду на машине FreeBSD (xxx.yyy.zzz.net) и получаю вывод
команда
sudo camcontrol devlist | grep -o 'ada[0-9]' | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done
выход
media RPM non-rotating
media RPM non-rotating
media RPM non-rotating
Я пытаюсь запустить ту же команду через ssh с другой машины.
команда
ssh xxx.yyy.zzz.net sudo camcontrol devlist | grep -o 'ada[0-9]' | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done
ошибка
sudo: camcontrol: command not found
решение1
В вашей команде каждый |
интерпретируется вашей локальной оболочкой. Последний аргумент ssh
видит devlist
. ssh
вызывается локально (это неудивительно), но так же и все после первого |
.
Ошибка, которую вы получили, возникла из sudo
этого фрагмента: do sudo camcontrol identify $a
Он запускается локально и, по-видимому, camcontrol
недоступен на локальной машине.
Вам нужно правильное экранирование или кавычки. В этом случае вы можете захотеть заключить всю удаленную команду в одинарные кавычки:
ssh xxx.yyy.zzz.net 'sudo camcontrol devlist | grep -o "ada[0-9]" | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done'
Обратите внимание, что я изменил одинарные кавычки, которые у вас уже были. (Добавленные) одинарные кавычки не только группируют всю строку, так что ssh
получают ее; они также предотвращают локальное расширение $a
.
Если sudo
собирается запросить ваш пароль, ему понадобится псевдотерминал. Вы можете принудительно выделить псевдотерминал с -t
опцией ssh
(чтобы это выглядело как ssh -t xxx.yyy.zzz.net …
). Примечание ssh -t
выделяет псевдотерминал на удаленной стороне. Удаленные sudo
приглашения в его stderr, но затем stdout и stderr «выводятся» этим псевдотерминалом (как они обычно выводятся на консоль), и в этот момент вы больше не можете их различать; объединенный поток захватывается и передается на локальную сторону, где он идет в stdout. Без удаленного stdout и stderr, которые передаются -t
отдельно, перейдите в stdout и stderr на локальной стороне, и они в конечном итоге объединяются (или нет, если перенаправлены) в то, что вы видите. Это означает, что с -t
вы не можете (на локальной стороне) отличить удаленный stderr от удаленного stdout. Если вам нужно локально обработать (перенаправить) вывод дальше, и вы используете, -t
то любое приглашение из sudo
будет мешать.
Также вам, вероятно, захочется использовать двойные кавычки $a
(даже в первой команде, которая не использует ssh
). СмотритеПочему мой скрипт оболочки тормозит пробелы и другие специальные символы?