Существует несколько способов использования SSH из Python. Общие подходы:
- Вызов локального
ssh
двоичного файла с использованием subprocess.Popen () или аналогичного (подходит только для сбора результатов в пакете)
- Вызов и управление локальным
ssh
двоичным файлом с использованием pexpect или аналогичного механизма управления процессом pty (psuedo-TTY) (для порождения и взаимодействия с процессом в терминальной сессии в автоматическом режиме)
- Используйте модуль / библиотеку Python, например Paramiko или Twisted conch , который реализует протоколы SSH (либо непосредственно в собственном Python, либо путем предоставления привязок к некоторой базовой разделяемой библиотеке). .so или DLL).
SSHController входит во вторую из этих широких категорий. Моя собственная скромная утилита, classh , относится к первой категории.
Ваш вопрос говорит о том, что вам лучше всего будет изучить Paramiko , потому что звучит так, как будто вы хотите установить состояние локальной переменной на основе результатов удаленного выполнения процесса. Я предполагаю, что вам не нужен какой-либо шанс связать какой-либо вывод локального терминала или сообщения об ошибках с результатами удаленной команды.
Другими словами, звучит так, будто вы хотите использовать SSH в качестве API, а не ssh
в качестве командной утилиты. Это существенное различие.
Команда ssh
пытается быть настолько прозрачной, насколько позволяют среды UNIX (и аналогичные среды MS Windows и т. Д.). ssh
открывает соединение с удаленной системой и создает несколько каналов, по которым связывается удаленное выполнение задания. Таким образом, локальный ssh
stdout будет от удаленных команд ' stdout , а локальный ssh
stderr будет представлять собой смесь пульта дистанционного управления. stderr и любые собственные сообщения об ошибках команды ssh
(и другие выходные данные, такие как отладочная информация, которую вы увидите при добавлении параметров -v, --verbose к вашему вызову ssh
). Аналогично, состояние выхода команды ssh
обычно отражает состояние выхода из удаленной оболочки. Однако это может быть также собственный код выхода локального ssh
процесса из локальной ошибки, который, по моему опыту, всегда равен значению 255. Я не знаю, как можно было бы различить значение выхода удаленной команды 255 против «аварийного завершения» (аварийного завершения процесса) из локального процесса - и я подозреваю, что нет никакого портативного, стандартного способа сделать это).
Суть в том, что использование команды ssh
из вашего кода обязательно не даст вам отделить вывод от локальных процессов (сам двоичный файл ssh
и, возможно, в зависимости от того, как вы его выполняете) локальная оболочка для этого) и те, которые исходят от удаленного процесса (и, возможно, оболочка, в которой запущен предполагаемый удаленный процесс). ssh
не является API .
С другой стороны, если вы используете что-то вроде Paramiko, вы устанавливаете сеанс по протоколу SSH и можете использовать и повторно использовать , чтобы выполнять команды, передавать файлы, выполнять некоторые другие функции файловой системы. и создавать туннели.
В этом случае вы создаете экземпляр SSHClient
и вызываете его метод .exec_command()
для каждой команды, которую вы выполняете на удаленном хосте. Концептуально это похоже на локальный вызов функции ... это вызовет исключение, если команда не может быть выполнена по какой-либо причине ... и любые результаты, которые вы получите из ее stdout или stderr нельзя отождествлять с возможным выводом каких-либо промежуточных процессов (таких как двоичный файл ssh
, который в этом случае вообще не выполняется).
Вот почему я рекомендую этот подход.Звучит так, будто вы хотите выполнить несколько отдельных команд для каждой удаленной цели таким образом, чтобы избежать возможных сложностей, возникающих при запуске их всех за один вызов утилиты ssh
, без каких-либо сложностей и снижения производительности при выполнении нескольких вызовов ssh
.Похоже, ваш код будет намного проще и надежнее, если вы сможете установить сеанс и использовать его в качестве API.