Ubuntu环境下Pexpect无法等待网络交换机命令完整输出的问题
解决pexpect执行长延迟命令时无法捕获完整输出的问题
我完全懂你碰到的这个糟心问题——用pexpect写的SSH脚本跑普通即时命令没问题,但一执行sh iproute这种要卡个5、6秒才分批输出的命令,就抓不到完整内容。靠sleep硬等虽然能解决,但要跑一堆命令的话效率实在太低,给你几个更靠谱的优化方案:
方案1:针对性延长超时时间,确保等待到真正的提示符
你的脚本一开始把全局timeout设成了5秒,而sh iproute光启动输出就要5-6秒,这直接导致expect提前触发超时,根本没等命令执行完就截了输出。你可以给全局会话或者特定的expect调用设置更长的超时时间:
str_prompt = ' # ' command = "sh iproute" device_name = "switch1.test.com" # 创建SSH会话时把全局timeout设长(比如30秒),给慢命令留足时间 ssh_command = 'ssh {}@{}'.format(username, device_name) session = pexpect.spawn(ssh_command, timeout=30) # 发送密码并等待登录提示符 session.sendline(password) expect_index = session.expect([pexpect.TIMEOUT, str_prompt]) if expect_index == 1: # 关闭分页功能,确保输出一次性返回 session.sendline('disable clip') # 这里单独给关闭分页的命令设置10秒超时,确保生效 expect_index = session.expect([pexpect.TIMEOUT, str_prompt], timeout=10) if expect_index == 1: session.sendline(command) try: # 给sh iproute设置60秒超时,足够它完成分批输出 session.expect(str_prompt, timeout=60) # 捕获输出,同时清理掉开头的命令回显(比如"sh iproute"那一行) output = session.before.replace(command + '\r\n', '', 1).decode('utf-8') # 用with语句自动关闭文件,更安全简洁 with open(f"{device_name}-route.txt", "w") as fp: fp.write(output) except pexpect.TIMEOUT: print(f"执行{command}超时啦,要么检查命令,要么再延长点超时时间~")
方案2:同时监听EOF和提示符,覆盖更多设备场景
有些交换机在输出完所有内容后会先发送EOF,再返回提示符。只监听提示符可能会因为设备的特殊行为报错,同时监听两个标记会更可靠:
# 发送sh iproute命令后,同时等待EOF或提示符 session.sendline(command) # 设置60秒超时,确保命令执行完成 expect_index = session.expect([pexpect.EOF, str_prompt], timeout=60) # 不管是先收到EOF还是提示符,都能捕获到完整输出 output = session.before.replace(command + '\r\n', '', 1).decode('utf-8') with open(f"{device_name}-route.txt", "w") as fp: fp.write(output)
方案3:先验证分页功能是否真的关闭
有时候输出不完整可能是因为disable clip命令没生效,你可以先跑个短命令确认分页已经关闭:
session.sendline('disable clip') session.expect(str_prompt) # 跑个短命令比如sh version,检查输出里有没有分页标记(比如--More--) session.sendline('sh version') session.expect(str_prompt) version_output = session.before.decode('utf-8') if '--More--' not in version_output: # 分页确实关闭了,再执行sh iproute session.sendline(command) session.expect(str_prompt, timeout=60) output = session.before.replace(command + '\r\n', '', 1).decode('utf-8') with open(f"{device_name}-route.txt", "w") as fp: fp.write(output) else: print("糟了,分页功能没关掉!检查下disable clip命令是不是写错了?")
这些方案都是利用pexpect的原生等待机制,避免了固定sleep的低效问题,还能确保抓全所有输出~
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

