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)
核心要点:
- 使用
channel.get_pty()获取伪终端,确保实时流式输出 - 通过
select.select()非阻塞检查通道状态 - 分别处理标准输出(
recv_ready)和错误输出(recv_stderr_ready) - 循环读取直到
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 和我需要的还是有点区别。多谢!
#3 顺序错了,现在可以了


