Долгосрочные команды ssh в модуле python paramiko (и как их закончить)
Я хочу запустить команду tail -f logfile
на удаленном компьютере с использованием модуля python paramiko. Я делаю это до сих пор следующим образом:
interface = paramiko.SSHClient()
#snip the connection setup portion
stdin, stdout, stderr = interface.exec_command("tail -f logfile")
#snip into threaded loop
print stdout.readline()
Я бы хотел, чтобы команда выполнялась столько, сколько необходимо, но у меня есть две проблемы:
- Как я могу прекратить это чисто? Я подумал о создании канала, а затем с помощью команды
shutdown()
на канале, когда я закончил с ним, но это кажется беспорядочным. Возможно ли сделать что-то вроде отправки Ctrl-C
на канал stdin?
-
readline()
, и я мог бы избежать потоков, если бы у меня был неблокирующий метод получения вывода - любые мысли?
Ответы
Ответ 1
1) Вы можете просто закрыть клиента, если хотите. Сервер с другого конца убьет хвостовой процесс.
2) Если вам нужно сделать это неблокирующим способом, вам придется напрямую использовать объект канала. Затем вы можете смотреть как stdout, так и stderr с каналами .recv_ready() и channel.recv_stderr_ready() или использовать select.select.
Ответ 2
Вместо вызова exec_command на клиенте возьмите транспорт и создайте собственный канал. channel можно использовать для выполнения команды, и вы можете использовать ее в инструкции select, чтобы узнать, когда данные могут быть прочитаны:
#!/usr/bin/env python
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('host.example.com')
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command("tail -f /var/log/everything/current")
while True:
rl, wl, xl = select.select([channel],[],[],0.0)
if len(rl) > 0:
# Must be stdout
print channel.recv(1024)
Объект канала можно считывать и записывать, подключаясь к stdout и stdin удаленной команды. Вы можете получить stderr, вызвав channel.makefile_stderr(...)
.
Я установил таймаут на 0.0
секунды, потому что было запрошено неблокирующее решение. В зависимости от ваших потребностей вы можете блокировать с ненулевым тайм-аутом.
Ответ 3
Просто небольшое обновление для решения Эндрю Айлетта. Следующий код фактически прерывает цикл и завершает работу, когда внешний процесс завершается:
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('host.example.com')
channel = client.get_transport().open_session()
channel.exec_command("tail -f /var/log/everything/current")
while True:
if channel.exit_status_ready():
break
rl, wl, xl = select.select([channel], [], [], 0.0)
if len(rl) > 0:
print channel.recv(1024)
Ответ 4
Чтобы закрыть процесс, просто запустите:
interface.close()
В терминах неблокирования вы не можете получить неблокирующее чтение. Лучшее, что вы могли бы сделать, - разобрать на нем один "блок" за раз, "stdout.read(1)" будет блокироваться только тогда, когда в буфере нет символов.
Ответ 5
Просто для информации есть решение сделать это с помощью channel.get_pty(). Более подробная информация приведена ниже: fooobar.com/info/241655/...