autossh建立远程SSH隧道遇端口占用无法自动恢复问题咨询
问题解答
1 为什么autossh遇到端口占用报错不会主动断开重试
autossh的核心逻辑仅监控底层ssh进程的退出状态,不会检测隧道的实际转发可用性,也不会解析ssh进程的运行时日志。
当出现远程端口绑定失败的错误时,ssh默认行为仅输出错误日志但维持SSH主连接正常运行,不会主动退出进程,因此autossh会判定ssh进程运行正常,不会触发重连逻辑。
2 重连时强制释放占用端口的方案
核心解决方法是给ssh添加ExitOnForwardFailure yes配置项,修改后的autossh命令如下:
autossh -M 0 -o "ServerAliveInterval 5" -o "ServerAliveCountMax 3" -o "ExitOnForwardFailure yes" -f -T -N -i /root/.ssh/id_rsa -R 1602:localhost:443 root@123.123.123.123
该参数的作用是:只要远程端口转发绑定失败,ssh进程就会主动异常退出,autossh检测到进程退出后会自动发起重连,等待服务端旧连接释放端口后,下一次重连即可成功绑定端口。
如果使用OpenSSH 7.7及以上版本,还可以将端口转发配置修改为-R :1602:localhost:443,允许ssh请求服务端强制解绑之前占用该端口的旧连接,进一步降低竞态概率。
3 无效隧道检测清理方案
可以通过客户端定时任务检测隧道连通性,异常时自动重启进程,实现步骤如下:
- 新建检测脚本
/opt/check_autossh.sh,内容如下:
#!/bin/bash # 检测隧道连通性,超时时间3秒 if ! nc -zv 123.123.123.123 1602 -w 3; then # 杀掉现有异常进程 pkill -f "autossh.*-R 1602" pkill -f "ssh.*-R 1602" # 等待端口释放后重启 sleep 2 autossh -M 0 -o "ServerAliveInterval 5" -o "ServerAliveCountMax 3" -o "ExitOnForwardFailure yes" -f -T -N -i /root/.ssh/id_rsa -R 1602:localhost:443 root@123.123.123.123 fi
- 给脚本添加执行权限:
chmod +x /opt/check_autossh.sh - 新增定时任务,每分钟执行一次检测:
执行crontab -e,添加如下规则:* * * * * /opt/check_autossh.sh > /dev/null 2>&1
补充:为什么该竞态条件很少被公开提及
该问题的触发门槛较高:需要网络中断时长恰好落在客户端保活超时(15秒,ServerAliveInterval * ServerAliveCountMax)和服务端保活超时(60秒,ClientAliveInterval * ClientAliveCountMax)的区间内。大部分场景下要么中断时间极短,双方都未感知到断连;要么中断时间较长,服务端已经释放端口后客户端才发起重连,因此很少有用户遇到并专门反馈该边界问题。
内容的提问来源于stack exchange,提问作者Stackraven
相关产品推荐
相关产品推荐

