使用Paramiko读取SSH stdout:REPL与脚本行为差异问题
Paramiko在REPL与脚本中读取MUD输出差异的原因及解决办法
核心原因
- 缓冲模式不同:Python交互式REPL运行时,会模拟终端环境,让Paramiko的SSH通道自动采用行缓冲,MUD的每一行输出都会被及时推送到读取端;而脚本执行时默认是块缓冲,MUD的输出会被暂存,直到缓冲区满才会发送,导致脚本只读到第一块内容(通常是第一行)。
- 执行速度差异:脚本是一次性快速执行,MUD服务器在SSH登录后需要时间加载初始化内容、输出登录提示序列,脚本可能在MUD还没输出完所有内容时就完成了读取操作;而REPL中是手动分步执行代码,给了服务器足够的输出时间。
解决办法
1. 强制模拟终端环境,启用行缓冲
MUD这类文本交互程序依赖终端环境来调整输出模式,通过get_pty()模拟真实终端,就能让MUD采用行缓冲输出:
import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("你的服务器地址", username="用户名", password="密码") # 打开带伪终端的shell通道 channel = ssh.invoke_shell() channel.get_pty(term="vt100") # 循环读取所有输出,直到没有新内容 while channel.recv_ready(): # 每次读取1024字节,解码后输出 content = channel.recv(1024).decode("utf-8") print(content, end="") ssh.close()
2. 增加等待时间,匹配MUD输出节奏
如果MUD加载初始化内容有延迟,可在读取前短暂等待,确保服务器输出完所有内容:
import paramiko import time ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("你的服务器地址", username="用户名", password="密码") channel = ssh.invoke_shell() time.sleep(2) # 根据MUD加载速度调整等待时间 # 持续读取直到无新输出 while channel.recv_ready(): content = channel.recv(4096).decode("utf-8") print(content) ssh.close()
3. 循环监听输出,避免提前终止读取
不要用单次read()或readline(),而是用循环持续监听通道的recv_ready()状态,确保读完所有输出:
import paramiko import time ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("你的服务器地址", username="用户名", password="密码") channel = ssh.invoke_shell() # 循环监听,直到通道关闭或无输出 while not channel.closed: if channel.recv_ready(): content = channel.recv(1024).decode("utf-8") print(content, end="") # 短暂休眠减少CPU占用 time.sleep(0.1) ssh.close()
内容的提问来源于stack exchange,提问作者buhtz
相关产品推荐
相关产品推荐

