Fedora下FortiClient VPN自动重连及Expect脚本故障排查
修复FortiClient VPN自动重连的Expect脚本及Python替代方案
修复Expect脚本
你的脚本存在几个关键问题,直接导致无法正确响应输入提示:
spawn命令语法错误:不能将整个命令用引号包裹,Expect会把它当作单个可执行文件路径,需分开传递命令与参数- 错误使用
echo:Expect中向终端输出信息需用send_user,而非shell的echo命令 - 多余的
sleep:expect会自动等待目标输出,强制sleep可能错过输入提示时机 - 确认提示匹配逻辑:重复的提示可通过正则表达式匹配,且发送确认指令后需添加回车
\r - 断开命令执行方式:直接写
forticlient vpn disconnect在Expect中无法正确执行,需用exec调用外部命令
修复后的完整脚本:
#!/usr/bin/expect -d set timeout -1 # 断开现有VPN连接 exec forticlient vpn disconnect # 配置变量 set username "{{USER-NAME}}" set password "{{USER-PASSWORD}}" set vpn_name "{{VPN-NAME}}" # 启动VPN连接命令 spawn forticlient vpn connect $vpn_name -u $username send_user "命令已执行\n" # 匹配密码提示并发送密码 expect "password:" send "$password\r" # 匹配确认提示(兼容重复输出的情况) expect -re "Confirm \\(y/n\\) \\[default=n\\]:" send "y\r" # 等待连接流程结束(可选,根据实际输出调整) expect eof
使用说明:替换{{USER-NAME}}、{{USER-PASSWORD}}、{{VPN-NAME}}为实际值,添加执行权限后直接运行。
Python实现方案(基于pexpect)
如果更熟悉Python生态,可以用pexpect库实现交互式连接,还能轻松加入状态监控与自动重连逻辑:
- 安装依赖:
sudo dnf install python3-pexpect
- 编写自动重连脚本(
vpn_auto_reconnect.py):
import pexpect import time import subprocess # 配置参数 VPN_NAME = "{{VPN-NAME}}" USERNAME = "{{USER-NAME}}" PASSWORD = "{{USER-PASSWORD}}" CHECK_INTERVAL = 60 # 每60秒检查一次VPN状态 def check_vpn_status(): """检查VPN是否处于连接状态""" try: result = subprocess.run( ["forticlient", "vpn", "status"], capture_output=True, text=True, check=True ) return "Connected" in result.stdout except subprocess.CalledProcessError: return False def connect_vpn(): """执行VPN完整连接流程""" # 先断开现有连接 subprocess.run(["forticlient", "vpn", "disconnect"], capture_output=True) time.sleep(2) try: child = pexpect.spawn(f"forticlient vpn connect {VPN_NAME} -u {USERNAME}") # 匹配密码提示并发送 child.expect("password:") child.sendline(PASSWORD) # 匹配确认提示并发送 child.expect(r"Confirm \(y/n\) \[default=n\]:") child.sendline("y") # 等待连接完成 child.expect(pexpect.EOF, timeout=30) print("VPN连接成功") except pexpect.TIMEOUT: print("VPN连接超时") except pexpect.EOF: print("VPN连接进程意外退出") def main(): while True: if not check_vpn_status(): print("VPN已断开,尝试重新连接...") connect_vpn() time.sleep(CHECK_INTERVAL) if __name__ == "__main__": main()
- 后台运行方案:
可以用nohup让脚本后台运行:
nohup python3 vpn_auto_reconnect.py &
或者配置systemd服务实现开机自启与自动重启:
创建服务文件/etc/systemd/system/vpn-auto-reconnect.service:
[Unit] Description=FortiClient VPN Auto Reconnect Service After=network.target [Service] User=你的用户名 ExecStart=/usr/bin/python3 /脚本绝对路径/vpn_auto_reconnect.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
启用并启动服务:
sudo systemctl daemon-reload sudo systemctl enable --now vpn-auto-reconnect.service
内容的提问来源于stack exchange,提问作者David Fager
相关产品推荐
相关产品推荐

