python paramiko模块中长时间运行的ssh命令(以及如何结束它们)

use*_*925 22 python ssh 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()
Run Code Online (Sandbox Code Playgroud)

我希望命令在必要时运行,但我有两个问题:

  1. 我该如何干净利落地停下来?我考虑制作一个频道,然后shutdown()在我通过时使用频道上的命令 - 但这看起来很混乱.有可能做一些像发送Ctrl-C到频道的标准输入的东西吗?
  2. readline() 块,如果我有一个非阻塞的输出方法,我可以避免线程 - 任何想法?

And*_*ett 21

不要在客户端上调用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)
Run Code Online (Sandbox Code Playgroud)

可以读取和写入通道对象,与远程命令的stdout和stdin连接.你可以通过电话联系stderr channel.makefile_stderr(...).

我已将超时设置为0.0秒,因为请求了非阻塞解决方案.根据您的需要,您可能希望使用非零超时进行阻止.


Jim*_*imB 14

1)如果您愿意,您可以关闭客户端.另一端的服务器将终止尾部进程.

2)如果您需要以非阻塞方式执行此操作,则必须直接使用通道对象.然后,您可以使用channel.recv_ready()和channel.recv_stderr_ready()来查看stdout和stderr,或使用select.select.

  • 我迟到了,但是“exec_command”本身不是非阻塞的吗? (2认同)
  • 在某些较新的服务器上,即使终止客户端,您的进程也不会被杀死。您必须在exec_command()中设置get_pty = True,以便在退出客户端后清理进程。 (2认同)

Ant*_*zov 8

只是Andrew Aylett对解决方案的一个小更新.以下代码实际上打破了循环并在外部进程完成时退出:

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)
Run Code Online (Sandbox Code Playgroud)

  • 为什么不做`而不是channel.exit_status_ready():`? (4认同)