ssh保活核心是客户端与服务端协同发心跳包:客户端设serveraliveinterval 60和serveralivecountmax 3,服务端设clientaliveinterval 300和clientalivecountmax 6,并匹配中间设备超时策略。

核心是让 SSH 主动“说话”,而不是等网络设备先动手断开。重点不在延长超时,而在持续发心跳包——客户端和服务端各管一段,配合中间设备策略才真正稳。
客户端配置:本地生效、无需权限、推荐优先做
编辑 ~/.ssh/config,为具体主机添加保活参数(别用 Host *,VSCode 等工具可能不识别通配):
- ServerAliveInterval 60:每 60 秒向服务器发一次探测包(SSH_MSG_IGNORE),轻量且可被日志记录
- ServerAliveCountMax 3:允许连续 3 次无响应,即最多容忍约 3 分钟链路中断
- 确保文件权限为
600:chmod 600 ~/.ssh/config,否则 SSH 直接忽略 - 如果走跳板机(ProxyCommand),这段心跳只作用于本机→跳板机;跳板机→目标机仍需单独配置
服务端配置:全局兜底、适合有 root 权限的场景
登录远程服务器,修改 /etc/ssh/sshd_config:
- ClientAliveInterval 300:服务端每 5 分钟探测一次客户端是否在线(比客户端心跳稍长,避免冲突)
- ClientAliveCountMax 6:最多容忍 6 次无响应,即约 30 分钟后断开,兼顾稳定性与资源释放
- TCPKeepAlive yes:启用底层 TCP 探活,作为辅助手段,不替代应用层心跳
- 改完必须重启服务:
sudo systemctl restart sshd;当前连接会断开,勿在单会话里改完就关终端
绕不开的中间环节:防火墙、网关、云厂商策略
很多掉线不是 SSH 自己的问题,而是卡在半路:
- 家用光猫、企业 NAT 网关常见空闲超时为 300–600 秒,你的
ServerAliveInterval必须比它短至少 2 秒(例如设为 298 或 59) - 阿里云 SLB 默认 900 秒、AWS ELB 是 60 秒、腾讯云部分镜像默认
ClientAliveInterval 10——先grep ClientAlive /etc/ssh/sshd_config查清现状再改 - 确认终端复用工具没干扰:
tmux set -g idle-timeout 0关闭 tmux 自身超时 - 检查 Shell 层变量:
echo $TMOUT,若输出非空(如 600),说明 Bash/Zsh 会在 10 分钟后强制退出,和 SSH 无关
验证与调试:别猜,要看实际行为
连上后执行命令确认配置是否生效:
- 在 VSCode 终端中运行:
ps aux | grep ssh,看到类似-o ServerAliveInterval=60才算读进去了 - 临时测试用命令行加参数:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@host - 加
-vvv观察日志:ssh -o ServerAliveInterval=60 -vvv user@host,等待 60 秒后出现debug3: send packet: type 80表示心跳已发出 - 注意 Host 名匹配:VSCode 连的是
my-server,配置里Host字段就必须严格一致,大小写、空格都不能错











