正确命令是 ssh -o ServerAliveInterval=45 -o ServerAliveCountMax=3 -o TCPKeepAlive=yes,需配合使用以应对NAT静默回收;单设ServerAliveInterval无效,必须搭配ServerAliveCountMax及时断连。

直接用 ssh -O ServerAliveInterval=60 是无效的——-O 是用于控制已存在的 multiplexing 连接(如挂起、恢复、退出),不是配置参数的开关。你真正需要的是 -o ServerAliveInterval=60,带等号、小写 o,且必须配合 ServerAliveCountMax 使用。
为什么单靠 ServerAliveInterval 不够?
跨多重动态 NAT 和企业防火墙时,连接中断不是“断开”,而是“静默回收”:中间设备在 3–5 分钟无数据流后直接从连接表中删除会话,不发 FIN/RST。此时客户端 TCP 还以为连着,但发包已无人响应。仅设心跳间隔,若服务器不回应或回应被丢,客户端仍会卡住或延迟断连。
关键要满足三点:
-
客户端主动探测:用
ServerAliveInterval定期发 SSH 层心跳(type 80 包),绕过部分只检测应用层活跃度的策略 -
及时判定失效:配
ServerAliveCountMax(建议 2–3),避免无限等待 -
防止底层 TCP 被清空:启用
TCPKeepAlive yes(默认开启,但某些云环境被改)
推荐命令行组合(无需改服务端)
适用于临时调试、跳板机、无 root 权限场景:
ssh -o ServerAliveInterval=45 -o ServerAliveCountMax=3 -o TCPKeepAlive=yes -o ConnectTimeout=10 user@host
说明:
- 45 秒发一次心跳:比常见 NAT 300 秒超时窗口更保守,留出网络抖动余量
- 连续 3 次无响应即断连(约 2 分 15 秒),快速失败,便于上层重连
-
ConnectTimeout=10避免 DNS 或路由问题导致初始连接挂死 - 务必用
=,写成空格(-o ServerAliveInterval 45)会报错
进阶:搭配 autossh 实现自动续连
对隧道类长期任务(如反向代理、端口转发),单次 ssh 不可靠。用 autossh 自动兜底:
autossh -M 0 -N -f -o ServerAliveInterval=45 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -L 8080:localhost:80 user@host
要点:
-
-M 0:禁用 autossh 自带的监控端口(避免端口冲突),完全依赖 SSH 层心跳判断 -
-N:不执行远程命令,专注端口转发 -
-f:后台运行,适合守护场景 -
ExitOnForwardFailure=yes:转发失败立即退出,触发 autossh 重试
别忽略 Shell 层干扰
即使 SSH 连接活着,TMOUT 可能让终端提示符卡住、显示 “connection closed” 假象:
- 登录后立刻运行
echo $TMOUT,若输出数字(如 600),说明 Bash/Zsh 自己会在 10 分钟后退出 - 临时解决:
unset TMOUT - 永久解决:在
~/.bashrc末尾加unset TMOUT,再source ~/.bashrc











