You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Paramiko获取远程服务器的无限循环数据?

解决Paramiko执行持续输出命令无返回的问题

你的判断没错,client.exec_command()配合stdout.read()会阻塞到命令执行结束才返回结果,而candump can0这类持续输出的命令不会主动终止,所以程序会一直卡住。以下是两种可行的解决方案:

方案1:逐行实时读取输出

利用stdout.readline()循环读取每一行输出,实现实时获取数据,同时支持手动终止程序:

import paramiko
import time

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
    client.connect(hostname='192.168.X.XXX', port='XX', username='XX', password='XX')
    stdin, stdout, stderr = client.exec_command('candump can0')
    
    # 循环读取每一行输出
    while True:
        line = stdout.readline()
        if not line:
            # 远程命令终止时退出循环
            break
        # 生成时间戳并打印内容
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
        print(f"{timestamp} {line.strip()}")
        
        # 同步读取错误输出
        err_line = stderr.readline()
        if err_line:
            print(f"{timestamp} [ERROR] {err_line.strip()}")
            
except KeyboardInterrupt:
    # 捕获Ctrl+C,发送终止信号给远程命令
    stdin.write('\x03')  # 发送Ctrl+C对应的ASCII码
    stdin.flush()
    print("程序已手动终止")
except Exception as e:
    print(str(e))
finally:
    client.close()

方案2:直接操作Channel对象(更灵活)

通过exec_command()返回的底层Channel对象,可精准控制数据读取时机,降低CPU占用:

import paramiko
import time

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
    client.connect(hostname='192.168.X.XXX', port='XX', username='XX', password='XX')
    # 获取命令对应的Channel对象
    channel = client.exec_command('candump can0')[0].channel
    
    while True:
        # 检查是否有标准输出可读
        if channel.recv_ready():
            data = channel.recv(1024).decode('utf-8')
            timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
            print(f"{timestamp} {data.strip()}")
        # 检查是否有错误输出可读
        if channel.recv_stderr_ready():
            err_data = channel.recv_stderr(1024).decode('utf-8')
            timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
            print(f"{timestamp} [ERROR] {err_data.strip()}")
        # 短暂休眠避免CPU空转
        time.sleep(0.1)
        
except KeyboardInterrupt:
    channel.send('\x03')  # 发送终止信号
    print("程序已手动终止")
except Exception as e:
    print(str(e))
finally:
    client.close()

关键说明

  • 两种方案均通过循环读取替代一次性阻塞读取,实现实时获取持续输出的数据。
  • 捕获KeyboardInterrupt是为了在手动终止程序时,同步终止远程命令进程,避免残留。
  • 原代码中未定义的TimeStamp,替换为time.strftime()生成可读时间戳。

内容的提问来源于stack exchange,提问作者JH KIM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:15:01