installing - python ssh client
Comandos ssh de larga duración en el módulo python paramiko(y cómo finalizarlos) (5)
1) Puede cerrar el cliente si lo desea. El servidor en el otro extremo matará el proceso de cola.
2) Si necesita hacer esto de forma no bloqueante, tendrá que usar el objeto de canal directamente. Luego puede ver tanto stdout como stderr con channel.recv_ready () y channel.recv_stderr_ready (), o use select.select.
Quiero ejecutar un comando tail -f logfile
en una máquina remota usando el módulo paramiko de python. Lo he intentado hasta ahora de la siguiente manera:
interface = paramiko.SSHClient()
#snip the connection setup portion
stdin, stdout, stderr = interface.exec_command("tail -f logfile")
#snip into threaded loop
print stdout.readline()
Me gustaría que el comando se ejecute todo el tiempo que sea necesario, pero tengo 2 problemas:
- ¿Cómo detengo esto limpiamente? Pensé en hacer un canal y luego usar el comando
shutdown()
en el canal cuando termine, pero parece desordenado. ¿Es posible hacer algo así como enviarCtrl-C
al stdin del canal? -
readline()
bloques, y podría evitar hilos si tuviera un método no bloqueante para obtener resultados, ¿algún pensamiento?
En lugar de llamar a exec_command en el cliente, obtenga el transporte y genere su propio canal. El channel se puede usar para ejecutar un comando, y puede usarlo en una declaración de selección para averiguar cuándo se pueden leer los datos:
#!/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)
El objeto de canal puede leerse y escribirse en, conectando con stdout y stdin del comando remoto. Puede obtener stderr llamando a channel.makefile_stderr(...)
.
Establecí el tiempo de espera en 0.0
segundos porque se solicitó una solución sin bloqueo. Dependiendo de sus necesidades, es posible que desee bloquear con un tiempo de espera distinto de cero.
Para cerrar el proceso simplemente ejecute:
interface.close()
En términos de no bloqueo, no se puede obtener una lectura no bloqueante. Lo mejor que sería capaz de analizar un "bloque" a la vez, "stdout.read (1)" solo se bloqueará cuando no queden caracteres en el búfer.
Solo para obtener información, hay una solución para hacer esto usando channel.get_pty (). Para obtener más detalles, consulte: https://.com/a/11190727/1480181
Solo una pequeña actualización de la solución de Andrew Aylett. El siguiente código realmente rompe el ciclo y se cierra cuando finaliza el proceso externo:
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)