通过expect执行SSH,到达提示符后发送首个字符就卡住如何解决
expect脚本对接IoT诊断Shell执行命令卡住解决方案
核心问题原因
IoT设备的诊断类Shell通常为精简实现,依赖伪终端(PTY)处理交互输入,且硬件处理能力较弱,输入速率过快会导致丢包。原脚本缺少伪终端分配配置,且命令发送策略不适配IoT设备特性。
需修改的配置项
- 给SSH命令添加
-tt参数:强制分配伪终端,即使运行在非交互脚本环境下也能让诊断Shell正常识别行输入、回显及命令执行逻辑 - 调整提示符匹配规则:使用正则匹配兼容
DEBUG>后可能存在的不可见空白符、控制字符,避免匹配失败导致超时 - 替换普通send为慢发策略:适配IoT设备弱输入处理能力,避免输入过快导致字符丢失
修改后完整脚本
#!/usr/bin/expect set timeout 30 # 排查问题时可打开下方调试开关,打印完整交互匹配日志 # exp_internal 1 set ip [lindex $argv 0] set port [lindex $argv 1] set passphrase [lindex $argv 2] set ssh_key_file [lindex $argv 3] # 新增-tt参数强制分配伪终端 spawn /usr/bin/sudo -u sftp /usr/bin/ssh -tt -ldiag_user -i $ssh_key_file $ip -p $port -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" expect "passphrase for" send "$passphrase\r" # 正则匹配提示符,兼容后缀空白字符 expect -re "DEBUG>\\s*" # 每100ms发送1个字符,适配IoT设备处理速率 send_slow 0.1 "ls -l\r" expect -re "DEBUG>\\s*" # 打印命令执行结果到标准输出 puts $expect_out(buffer)
可选补充验证
如果调整后仍有异常,可临时打开脚本中的exp_internal 1调试开关,查看expect的实际交互字符流,确认是否存在提示符隐藏字符、命令回显异常等问题,针对性调整匹配规则即可。
内容的提问来源于stack exchange,提问作者markcnx
相关产品推荐
相关产品推荐

