Могу ли я получить код завершения команды, выполняемой в подоболочке через ssh?
Я пытаюсь использовать Paramiko для написания сценария развертывания, и у меня возникают проблемы с кодами выхода из команд, которые я запускаю. В этом ответе я использую код, похожий на этот, но он немного сложнее. По сути, из наших блоков разработки нам нужно пройти через сервер переходов, а оттуда - к серии производственных машин. Оказавшись там, мы должны переключиться на системного пользователя (sudo su - systemuser), а затем мы можем запускать команды.
Проблема в том, что, насколько я понимаю, у меня есть 3 подоболочки - сессия ssh, вложенная команда ssh и затем подоболочка su. Я не могу заставить Paramiko вернуть мне код завершения команд во внутренней подоболочке - думаю, код возврата, который он в конечном итоге вернет, будет кодом команды ssh. Я подозреваю, что эта проблема на самом деле не специфична для Paramiko - поддерживает ли протокол SSH такого рода использование?
В настоящее время я всегда выполняю:
(my command); echo "Process terminated with exit code $?"
и затем анализировать это на клиенте, но это довольно уродливо - есть ли лучший способ?
2 ответа
Я предполагаю, что код выхода, который он в конечном итоге вернет, будет кодом команды ssh. Я подозреваю, что эта проблема на самом деле не специфична для Paramiko - поддерживает ли протокол SSH такого рода использование?
И да и нет.
Статус выхода всегда возвращается, но он может быть не там, где вы думаете. Как только вы позвоните invoke_shell()
, ваш удаленный процесс - это оболочка, вероятно bash. exit_status
вы получите тот из этой оболочки, а не какой-либо из процессов, которые он запускал. Paramiko (как и любая реализация ssh) может когда-либо возвращать состояние выхода ваших команд, потому что состояния выхода никогда не видны за пределами этой удаленной оболочки. Вам решать, каким должен быть ваш статус выхода, и выходить из оболочки с exit $EXIT_STATUS
(довольно часто exit $?
достаточно)
Если вы можете разбить ваши команды или обернуть их в сценарий, то используйте exec_command()
метод, вы будете иметь доступ к правильному состоянию выхода напрямую.
Кроме того, вы можете использовать команду оболочки exec
в удаленной оболочке, и процесс оболочки будет заменен командой, вызванной exec, и будет возвращен статус ее выхода.
Все три из этих методов установят channel.exit_status
атрибут, как и ожидалось.
У меня возникла проблема, когда на странице man для 'ssh' написано, что она возвращает код завершения процесса, который она запускает, но я не могу заставить ее вернуть ненулевой код ошибки. Со страницы руководства ssh:
The session terminates when the command or shell on the remote machine
exits and all X11 and TCP/IP connections have been closed. The exit sta‐
tus of the remote program is returned as the exit status of ssh.
Это не похоже на правду.
Но я бы попробовал что-то подобное и посмотрел, что происходит в вашей системе.
% ssh localhost bash -c "exit 3" ; echo $?
0
Когда я запускаю подобную команду локально, bash возвращает код выхода.
% bash -c 'exit 3' ; echo $?
3
Однако двойные кавычки будут удалены до того, как ssh покажет команды. Итак, давайте попробуем больше цитат.
% ssh localhost bash -c "'exit 3'" ; echo $?
3
Бинго. "Выход 3" превращался в "выход", за которым следовало игнорируемое слово в командной строке bash. Таким образом, bash выполнял команду "выход".
К сожалению для меня, я думаю, что весь этот ответ является отступлением от оригинальных вопросов и не содержит достаточных заслуг как вопроса в отдельности. Спасибо всем за помощь в ответе на второстепенный вопрос (не связанный с оригинальным вопросом).