如何用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
相关产品推荐
相关产品推荐

