expect脚本连接FortiClient SSL VPN时如何检测隧道关闭自动退出
问题根因
- 原脚本全程使用
-exact做刚性字符串匹配,一旦FortiClient的状态输出和硬编码字符串存在换行、空格差异就会匹配失效 - 脚本spawn的是交互式shell,原逻辑最后直接执行
expect eof,只要shell没有主动退出就永远不会触发eof;脚本没有主动监听FortiClient输出的隧道关闭状态,自然会卡在后台持续运行
调整后的完整脚本
#!/usr/bin/expect -f set force_conservative 0 if {$force_conservative} { set send_slow {1 .1} proc send {ignore arg} { sleep .1 exp_send -s -- $arg } } set timeout -1 spawn $env(SHELL) match_max 100000 send -- "cd /home/forticlientsslvpn/64bit/\r" send -- "./forticlientsslvpn --server ip:port --vpnuser UN\r" expect { -re "forticlientsslvpn --server.*--vpnuser.*" { send -- "\r" } timeout { puts "启动VPN命令超时,退出" exit 1 } } expect { "Password for VPN:" { send -- "PW\r" } timeout { puts "未收到密码提示,退出" exit 1 } } expect { -re "STATUS::Setting up the tunnel.*Connecting..." { send -- "Y\r" } } # 替换原逻辑直接等待eof的部分,新增状态监听分支 expect { -re "STATUS::Tunnel closed.*" { puts "检测到隧道已关闭,脚本退出" send -- "\x04" exit 0 } -re "STATUS::Tunnel running.*" { exp_continue } } expect eof
核心调整点
- 用正则模糊匹配替代原有的
-exact刚性匹配,消除输出格式微小差异带来的匹配失效问题 - 新增专门的状态监听分支:一旦捕获到
STATUS::Tunnel closed标识,立即执行退出逻辑,同时发送Ctrl+D信号清理残留的交互式shell进程,避免后台进程驻留 - 补充原脚本缺失的回车符
\r,确保shell能正常接收并执行输入的命令 - 匹配到
STATUS::Tunnel running正常运行状态时,通过exp_continue保持持续监听,不会提前终止等待逻辑
内容的提问来源于stack exchange,提问作者Anjan
相关产品推荐
相关产品推荐

