Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Передача вывода ssh sudo

Автор вопроса: Richard SmithОтветов: 1

Иногда мне нужно запускать команды от имени пользователя root на удаленном сервере и анализировать вывод команды на моем локальном сервере. Удаленный сервер не разрешает вход в систему root с помощью ssh, но sudo настроен таким образом, что требуется пароль. Упрощенный пример того, что мне нужно сделать, это

ssh remote sudo echo bar | tr bar foo

(Очевидно, что в этом упрощенном примере нет веских причин запускать echo на другой машине, чем tr: это просто игрушечный пример, объясняющий, что я пытаюсь сделать.)

Если я запускаю приведенную выше команду, я получаю сообщение об ошибке, что sudo не может запросить пароль:

richard@local:~$ ssh remote sudo echo bar | tr bar foo
sudo: no tty present and no askpass program specified

Один из способов исправить это - добавить параметр -t к ssh. Если я это сделаю, sudo будет ожидать и принять пароль, но вывод псевдотерминала ssh пойдет на стандартный вывод, что означает, что подсказка sudo передается на tr и не отображается пользователю. Если пользователь не знает, что sudo ожидает ввода пароля, он решит, что скрипт завис, и передача подсказки в конвейер, вероятно, нарушит дальнейшую обработку:

richard@local:~$ ssh -t remote sudo echo bar | tr bar foo
[sudo] posswood foo oichood:
foo

(Этот заведомо глупый пример показывает, что приглашение было обработано командой tr, на которую передаются выходные данные.)

Другой способ, который я вижу, чтобы попытаться исправить это, - добавить параметр -S к sudo. Если я это сделаю, sudo запрашивает пароль на stderr, поэтому запрос не передается по конвейеру. Это хорошо, но sudo также принимает пароль при стандартном вводе, что означает, что он отображается на терминале, где любой, кто смотрит через плечо пользователя, может его прочитать:

richard@local:~$ ssh remote sudo -S echo bar | tr bar foo
[sudo] password for richard: p8ssw0rd
foo

Я нашел неэлегантные способы обойти проблемы с этими двумя вариантами, но мои обходные пути столкнулись с проблемой, если пользователь в первый раз неправильно ввел свой пароль. Это само по себе является проблемой. Примеры этого:

richard@local:~$ echo "[sudo] password for $USER:"; \
  ssh -t remote sudo echo bar | tail +2 | tr bar foo

richard@local:~$ (read -s password; echo $password; echo >&2) \
  | ssh remote sudo -S echo bar | tr bar foo

Я уверен, что должно быть хорошее решение для этого, поскольку это не кажется необычным. Есть идеи?

  • Почему вы используете sudo вместо ssh в первую очередь? jww 10.05.2019
  • Как еще вы предлагаете мне выполнить код от имени пользователя root на удаленном сервере, который не позволяет войти в систему с правами root (т. е. имеет PermitRootLogin no в /etc/ssh/sshd_config), @jww? Может быть, есть лучшее решение, но я не могу сразу придумать его. Richard Smith 10.05.2019

sshsudotty

Ответы

Ответ 1 · рейтинг 2 · SystemParadox

Лучшее решение, которое я придумал, - использовать sudo -S и отключить локальное эхо, чтобы пароль не отображался при его вводе:

$ { stty -echo; ssh remote sudo -S echo hello; stty echo; echo 1>&2; }
[sudo] password for user:
hello

Это оставляет sudo ответственным за запрос пароля, поэтому он работает правильно, если пользователь вводит пароль неправильно.

Я не думаю, что любое решение, использующее ssh -t, когда-либо сможет работать должным образом, поскольку оно сочетает в себе stderr и stdout.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы