Длительно выполняющиеся ssh-команды в модуле python paramiko (и как их завершить)

StackOverflow https://stackoverflow.com/questions/760978

  •  09-09-2019
  •  | 
  •  

Вопрос

Я хочу запустить tail -f logfile команда на удаленном компьютере с использованием модуля paramiko на python.До сих пор я пытался сделать это следующим образом:

interface = paramiko.SSHClient()
#snip the connection setup portion
stdin, stdout, stderr = interface.exec_command("tail -f logfile")
#snip into threaded loop
print stdout.readline()

Я бы хотел, чтобы команда выполнялась столько, сколько необходимо, но у меня есть 2 проблемы:

  1. Как мне остановить это чисто?Я подумал о том, чтобы создать Канал, а затем использовать shutdown() команда на канале, когда я закончу с этим - но это кажется запутанным.Можно ли сделать что-то вроде отправленного Ctrl-C к stdin канала?
  2. readline() блоки, и я мог бы избежать потоков, если бы у меня был неблокирующий метод получения выходных данных - есть какие-нибудь мысли?
Это было полезно?

Решение

1) Вы можете просто закрыть клиент, если хотите.Сервер на другом конце остановит конечный процесс.

2) Если вам нужно сделать это неблокирующим способом, вам придется напрямую использовать объект channel.Затем вы можете отслеживать как stdout, так и stderr с помощью channel.recv_ready() и channel.recv_stderr_ready() или использовать select.select.

Другие советы

Вместо вызова exec_command на клиенте, получите доступ к транспорту и сгенерируйте свой собственный канал.В канал может использоваться для выполнения команды, и вы можете использовать его в инструкции 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)

Объект channel можно считывать и записывать, подключаясь с помощью stdout и stdin удаленной команды.Вы можете получить доступ к stderr, позвонив channel.makefile_stderr(...).

Я установил тайм-аут на 0.0 секунд, потому что было запрошено неблокирующее решение.В зависимости от ваших потребностей, вы можете захотеть заблокировать с ненулевым таймаутом.

Просто небольшое обновление решения Эндрю Эйлетта.Следующий код фактически прерывает цикл и завершается, когда внешний процесс завершается:

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)

Чтобы закрыть процесс, просто запустите:

interface.close()

С точки зрения неблокирующего, вы не можете получить неблокирующее чтение.Лучшее, что вы могли бы сделать, это анализировать его по одному "блоку" за раз, "stdout.read(1)" будет блокироваться только тогда, когда в буфере не останется символов.

Просто для информации, есть решение сделать это с помощью channel.get_pty().Для получения более подробной информации взгляните на: https://stackoverflow.com/a/11190727/1480181

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top