Python中如何通过Paramiko的SSH连接实时输出命令执行结果?

import paramiko

trans = paramiko.Transport((‘x.x.x.x’, 22))
trans.connect(username=‘root’, password=‘123123’)
ssh = paramiko.SSHClient()
ssh._transport = trans
stdin, stdout, stderr = ssh.exec_command(‘tcpdump -i any -nne -c 10’)
print(stdout.read().decode())
ssh.close()

这里打印出 stdout 的时候已经是命令执行的所有结果,如何每收到一次数据就打印出来,比如我执行的 tcpdump 命令,我想实现每捕获到一个报文就实时的显示出来,而不是等抓了 10 个以后再一起显示。
Python中如何通过Paramiko的SSH连接实时输出命令执行结果?


8 回复
import paramiko
import select

def realtime_ssh_command(hostname, username, password, command):
    """
    通过SSH执行命令并实时输出结果
    """
    # 创建SSH客户端
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    try:
        # 连接服务器
        client.connect(hostname, username=username, password=password)
        
        # 创建交互式会话
        transport = client.get_transport()
        channel = transport.open_session()
        
        # 设置伪终端,支持交互式命令
        channel.get_pty()
        
        # 执行命令
        channel.exec_command(command)
        
        # 实时读取输出
        while True:
            # 检查通道是否可读
            rl, wl, xl = select.select([channel], [], [], 0.0)
            
            if channel.recv_ready():
                # 读取标准输出
                output = channel.recv(1024).decode('utf-8')
                if output:
                    print(output, end='', flush=True)
            
            if channel.recv_stderr_ready():
                # 读取错误输出
                error = channel.recv_stderr(1024).decode('utf-8')
                if error:
                    print(error, end='', flush=True)
            
            # 检查命令是否执行完成
            if channel.exit_status_ready():
                # 读取最后可能残留的输出
                while channel.recv_ready():
                    output = channel.recv(1024).decode('utf-8')
                    if output:
                        print(output, end='', flush=True)
                break
        
        # 获取退出状态码
        exit_status = channel.recv_exit_status()
        print(f"\n命令执行完成,退出状态码: {exit_status}")
        
    finally:
        client.close()

# 使用示例
if __name__ == "__main__":
    # 配置连接参数
    HOST = "your_server_ip"
    USER = "your_username"
    PASSWORD = "your_password"
    COMMAND = "ping -c 5 localhost"  # 示例命令
    
    # 执行命令并实时输出
    realtime_ssh_command(HOST, USER, PASSWORD, COMMAND)

核心要点:

  1. 使用channel.get_pty()获取伪终端,确保实时流式输出
  2. 通过select.select()非阻塞检查通道状态
  3. 分别处理标准输出(recv_ready)和错误输出(recv_stderr_ready)
  4. 循环读取直到exit_status_ready()返回True

替代方案(更简洁):

def realtime_ssh_simple(hostname, username, password, command):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    client.connect(hostname, username=username, password=password)
    stdin, stdout, stderr = client.exec_command(command)
    
    # 实时读取输出
    for line in iter(stdout.readline, ""):
        print(line, end='', flush=True)
    
    client.close()

一句话总结:用channel.get_pty()配合select实现真正的实时输出。

用消息通道,提示你:invoke_shell()

谢谢,昨天我也自己看到了,测试了可以。

谢谢你,invoke_shell 和我需要的还是有点区别。多谢!

#4 大佬,这个问题你后来怎么解决了,我目前也遇到此问题,试了 stackoverflow 里的,貌似也不行

#3 顺序错了,现在可以了

#3 hello,你的中文怎么处理的?

回到顶部