如何让Expect脚本正确匹配pfSense路由器的多行响应?
解决Expect脚本匹配pfSense登录菜单的问题
核心问题分析
- 登录流程逻辑错误:输入密码后,pfSense首先返回控制台菜单(以
Enter an option:结尾),而非shell提示符,原脚本直接等待提示符导致匹配超时。 - 正则匹配精度不足:
.*Enter an option:的写法无法适配多行文本的缓冲区读取逻辑,容易匹配失败。 - 缺少流程续听机制:处理完密码或菜单后未保留监听,导致后续shell提示符无法被捕获。
修正后的脚本
# Main script set prompt {[$>?#]: } puts "Connecting to pfSense router..." spawn ssh -p $ssh_port -o StrictHostKeyChecking=no $username@$pfsense_router expect { # 匹配各类密码提示(兼容大小写和不同格式的提示文本) -re {[Pp]assword.*:} { send "$password\r" exp_continue ;# 继续监听后续输出 } # 精确匹配菜单的最后一行,确保捕获到完整菜单输出 -re {\nEnter an option: $} { send "8\r" ;# 输入选项8进入shell环境 exp_continue ;# 继续监听shell提示符 } # 匹配shell提示符,确认进入目标环境 -re $prompt { puts "SSH login successful." check_gateway_status $target_host } # 权限验证失败处理 "Permission denied" { send_user "Authentication failed. Please check your credentials.\n" exit 1 } # 连接超时处理 timeout { send_user "Timeout while trying to connect to the router.\n" exit 1 } }
关键调整说明
- 梳理匹配顺序:按照实际登录流程(密码提示→菜单→shell提示符)调整匹配规则顺序,符合设备输出逻辑。
- 优化菜单匹配规则:用
\nEnter an option: $精准定位菜单的最后一行,避免多行文本干扰匹配结果。 - 添加
exp_continue:处理完密码和菜单后保持监听状态,确保后续shell提示符能被捕获。 - 统一换行符:将
替换为标准的\r,适配pfSense控制台的输入格式要求。
额外调试建议
- 临时添加
log_user 1开启调试日志,可查看Expect实际接收的设备输出,快速定位匹配问题。 - 若菜单文本存在版本差异,可简化正则为
-re {Enter an option:},降低匹配精度以提升兼容性。
内容的提问来源于stack exchange,提问作者Unpossible
相关产品推荐
相关产品推荐

