Expect Telnet脚本报spawn id exp6 not open及expect_before误触发问题
Expect脚本Telnet断连规则误触发修复方案
问题根因
*expect_before*配置的匹配规则默认全局生效,声明之后所有expect调用都会优先匹配这些规则。你主动发送exit命令触发的正常Telnet断连,一样会输出Connection closed by foreign host.字符串,这个输出会被全局前置规则优先捕获,根本走不到后续expect eof的正常分支,自然就会出现命令执行完成后误报异常断连的问题。
另外你最初的脚本本身存在逻辑缺陷:Telnet连接建立后直接硬等#提示符,没有配置超时、登录失败的匹配逻辑,遇到网络波动、远端响应慢的场景就会匹配失败,这也是最早偶发send: spawn id exp6 not open报错的核心原因。
规范修复方案
不需要删除expect eof,任选以下一种方案即可解决问题,两种实现均符合Expect编码规范,不会产生僵尸进程或异常报错:
- 方案1:执行最终eof等待前清空前置规则
Expect提供了*expect_before -reset*命令,可以直接清空之前配置的所有全局前置匹配规则,清空后再执行eof等待就不会触发异常捕获逻辑。
修改后完整可运行脚本如下:
expect << EOS log_user 0; spawn telnet 192.168.1.51 -l root # 配置全局异常断连、超时捕获 expect_before { timeout {puts "连接超时,退出"; exit} "Connection closed by foreign host." { puts "Telnet session closed unexpectedly." puts "Please try again." exit } } # 等待登录shell提示符 expect "#" send "ls; pwd;\r" log_user 1; expect "#" log_user 0; send "exit\r" # 主动退出前清空全局前置规则,避免误判正常断连 expect_before -reset expect eof EOS
- 方案2:在最终eof匹配块中显式处理正常断连场景
Expect的匹配规则遵循「就近优先」原则,写在当前expect块内的匹配规则优先级高于expect_before的全局规则。直接在最后等待退出的逻辑里显式匹配断连字符串,把主动触发的断连判定为正常流程即可。
对应修改的代码片段如下:
send "exit\r" # 当前块内的匹配优先级高于全局expect_before expect { "Connection closed by foreign host." { # 主动exit触发的断连属于正常情况,继续等待进程退出即可 exp_continue } eof }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

