SSH刚连上时一切正常,放置几分钟后终端突然卡住,再敲命令只看到 Broken pipe、Connection reset 或超时退出。最常见的处理是把保活时间调得很短,但连接断开可能来自客户端网络、路由器NAT、云端防火墙、服务器负载或sshd策略,保活只能帮助确认部分路径。
我排查这类问题时,会先记录断开是否与空闲时间有关,再用客户端调试日志、服务端日志和连续网络采样对齐同一个时间点。只看重连成功容易忽略根因,因为短时丢包、进程被杀和会话策略都可能在下一次重复出现。
下面以OpenSSH客户端和Linux服务端为例。Windows终端、PuTTY、堡垒机、Web控制台与移动网络的配置入口不同,但判断逻辑相同。修改服务端配置前应保留当前会话,并确认还有云平台控制台或VNC等备用登录方式。

先记录断开的规律和错误文字
连续记录几次故障,重点写下连接开始时间、最后一次正常交互、断开时间、是否一直空闲、客户端网络和服务器地址。固定在5分钟、10分钟或30分钟空闲后断开,通常比随机断开更像中间设备或策略超时。
重新连接时开启详细日志:
ssh -vvv -o ConnectTimeout=10 user@SERVER_IP
-vvv 会输出密钥路径、算法、认证方式和连接阶段,分享日志前必须删除用户名、主机名、IP、密钥文件路径与认证相关信息。它不会自动持续记录数小时,可以使用终端日志功能或把标准错误保存到受控文件。
断开时常见提示方向不同:
Broken pipe常表示连接写入时发现通道已经失效,不能仅凭这一句判断是哪一端先关闭。Connection reset by peer表示收到RST,可能来自服务器进程、中间设备或安全策略。Connection timed out更接近持续没有响应,需要结合丢包和路由采样。Timeout, server not responding可能是客户端保活达到失败阈值。
同一客户端连接其他服务器稳定,而多台客户端连接目标服务器都断开,优先检查服务端和云端链路;只有某个办公网络或某台电脑受影响,则更偏向本地网络、代理和NAT。
判断是空闲断开还是活跃时也断开
建立两个会话,一个保持空闲,另一个每隔一段时间输出时间:
while true; do date -Is; sleep 30; done
这条命令只用于短时测试,结束时按 Ctrl+C。只有空闲会话断开,活跃会话稳定,说明空闲超时或NAT回收的可能性更高。两个会话同时中断,应继续检查网络、sshd重启、服务器卡顿或实例状态变化。
不要把 TMOUT 与网络断开混为一谈。Shell可以设置自动注销:
echo "$TMOUT"
readonly -p 2>/dev/null | grep TMOUT
出现固定秒数,并且终端先显示自动退出信息,可能是Shell策略。还要检查 /etc/profile、/etc/profile.d/ 和用户启动文件。企业环境中的堡垒机也可能有自己的会话时长限制,需要管理员核对审计策略。
在客户端配置应用层保活
OpenSSH客户端的 ServerAliveInterval 表示一段时间未收到服务器数据后,通过加密通道发送保活消息;ServerAliveCountMax 控制连续多少次未得到响应后断开。可以先单次测试:
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 user@SERVER_IP
这个配置意味着客户端在无数据时每30秒探测,连续3次没有响应后退出。它不是把所有连接永久保持,也不会修复真实丢包。间隔设成1秒会增加无意义流量,还可能在短暂抖动时过早断开。
确认有效后再写入客户端 ~/.ssh/config:
Host production-example
HostName SERVER_IP
User USERNAME
ServerAliveInterval 30
ServerAliveCountMax 3
使用别名能把设置限制在目标服务器,避免全局影响所有SSH连接。检查最终生效参数:
ssh -G production-example | grep -Ei 'serveralive|tcpkeepalive'
ServerAliveInterval 与 TCPKeepAlive 不同。前者在加密通道内发送应用层消息,后者依赖系统TCP保活,时间尺度和对中间设备的表现都不同。排查空闲NAT回收时,应用层保活通常更容易控制。
检查服务端是否主动结束会话
在服务器读取sshd日志。Debian、Ubuntu常用:
sudo journalctl -u ssh --since '2 hours ago' --no-pager
sudo tail -n 200 /var/log/auth.log
RHEL、Rocky Linux、AlmaLinux常用:
sudo journalctl -u sshd --since '2 hours ago' --no-pager
sudo tail -n 200 /var/log/secure
围绕准确断开时间查找session closed、timeout、fatal、reset、sshd重启和认证失败。日志没有任何关闭记录,不等于服务端完全正常,内核丢包、系统卡死和实例网络中断可能来不及写入应用日志。
查看sshd最终配置:
sudo sshd -T | grep -Ei 'clientalive|tcpkeepalive|maxsessions|maxstartups'
ClientAliveInterval 是服务端向客户端发送加密通道保活消息的间隔,ClientAliveCountMax 是无响应阈值。它们主要用于发现失效客户端,不应为了避免任何断开就设置成极大值。MaxStartups 管的是未认证连接,并非已经登录的空闲会话;MaxSessions 则影响单个网络连接可承载的会话数量。
修改 /etc/ssh/sshd_config 或包含目录后先检查语法:
sudo sshd -t
语法通过再按发行版使用 systemctl reload ssh 或 systemctl reload sshd。保持原会话不退出,用第二个终端验证新连接和sudo权限。直接重启sshd并关闭唯一会话,配置错误时可能把自己锁在服务器外。
排查客户端到服务器的网络抖动
从受影响客户端对服务器持续采样:
ping -c 120 SERVER_IP
mtr -rwzc 100 SERVER_IP
部分服务器和中间路由会限制ICMP,最后一跳不响应不代表SSH一定不可达。重点看故障时段的终点丢包、延迟突增和多个连续超时。某个中间跳显示高丢包,但后续跳与终点正常,常是该路由器降低了ICMP响应优先级,不能直接认定它就是故障点。
再对SSH端口做TCP测试:
nc -vz -w 5 SERVER_IP 22
自定义端口要替换22。短时连通测试正常,只说明当前可以建立连接,无法证明长连接稳定。可在故障复现窗口同时运行 mtr、客户端详细日志和服务器日志,按时间戳对齐。
公司Wi-Fi、家用路由器、移动热点和代理软件可能对空闲TCP连接设置不同超时。切换到另一条合法网络做对照,比反复修改服务器参数更能快速缩小范围。测试时保持同一客户端、同一服务器和同一SSH配置,只改变网络变量。
检查服务器负载、内存和sshd进程
连接断开前服务器明显卡顿,输入延迟越来越高,再突然退出,要检查系统资源:
uptime
free -h
vmstat 1 10
sudo journalctl -k --since '2 hours ago' --no-pager
负载高但CPU空闲,可能是磁盘I/O等待;可用内存耗尽并出现OOM记录,sshd子进程或网络服务可能被终止。内核日志中的网卡重置、连接跟踪表满、文件系统错误也会影响会话。
systemctl status sshd --no-pager
systemctl show sshd -p ActiveEnterTimestamp -p NRestarts
Ubuntu服务名可能是 ssh。NRestarts 增长或活动时间与断开时间一致,说明服务被重启,需要继续查配置管理、更新任务、监控自愈和管理员操作。仅把服务再次启动不能解释为什么所有会话被中断。
核对防火墙、NAT和云端会话路径
服务器本机防火墙通常允许或拒绝新连接,但连接跟踪表压力、状态规则和自动封禁也可能重置已有会话:
sudo nft list ruleset
sudo conntrack -S 2>/dev/null
sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
没有安装conntrack工具时不要为了一个命令临时改动生产环境。nf_conntrack_count 接近上限,并伴随内核日志 table full,才支持连接跟踪压力判断。盲目调大上限会增加内存占用,应先找到连接暴涨来源。
云端防火墙、负载均衡、堡垒机和NAT网关可能位于SSH路径中。直连公网IP稳定、经过堡垒机断开,应检查堡垒机的空闲策略和容量;同一服务器换公网入口后稳定,则继续核对云端路径和线路,而不是修改sshd。
现有服务器难以区分本地网络与实例环境时,可以在 萤光云 建立同地区、同系统版本的最小SSH环境,或使用按小时计费的 LightNode 做另一条服务器路径对照。只创建测试账号和普通会话,不复制生产私钥、密码文件或业务数据。
长时间任务不要完全依赖终端连接
即使SSH链路已经稳定,升级、编译和数据处理等长任务也不应把生命周期绑定到一个终端。可以使用tmux或systemd托管:
tmux new -s maintenance
断开后重新登录并执行:
tmux attach -t maintenance
tmux能保留服务器端会话,但不能修复网络,也不能替代任务日志和回滚方案。数据库升级、磁盘修复等高风险操作仍要在维护窗口执行,并确认断线后不会停在危险的交互步骤。
修复后按原场景验收
空闲时断开的连接,要保持超过原来的超时时长;活跃时随机断开的连接,要覆盖原来容易出现问题的网络时段。验收期间保存客户端保活日志、服务器sshd日志、系统资源和网络采样。
不要只验证终端看起来没断。还应确认没有持续重传、保活探测失败、sshd重启或OOM记录。切换网络、重启客户端和服务器维护后再做一次复测,确认配置不是只在当前进程中临时生效。
最终结论应能说明连接由哪一端或哪一层结束、断开与空闲时间或资源压力的关系,以及哪项最小改动改善了原来的场景。
常见问题
ServerAliveInterval设置为多少合适?
没有适用于所有网络的固定值。可先用30到60秒做受控测试,并配合合理的失败次数。间隔过短会增加探测,也会让短暂抖动更快触发退出。
SSH断开后,正在运行的命令一定会停止吗?
取决于命令、Shell和信号处理方式。交互前台任务通常有中断风险,tmux、systemd或专用任务队列更适合长时间工作。
改sshd配置会断开现有连接吗?
优雅重载通常不会主动结束现有会话,但错误配置和服务操作仍有风险。先执行 sshd -t,保留当前会话,并从第二个终端验证。


