必须同时配置tmout和sshd_config中的clientaliveinterval与clientalivecountmax,因为tmout仅监控shell输入空闲,无法感知tcp连接中断、客户端崩溃或防火墙静默丢包等网络层异常,而clientaliveinterval×clientalivecountmax才真正实现对僵尸连接的探测与强制断连。

必须同时配置 TMOU 和 sshd_config 中的 ClientAliveInterval 与 ClientAliveCountMax,只设一个会漏掉“假活跃”连接或本地终端空闲场景。
为什么单靠 TMOU 不够用
很多用户只改 /etc/profile 里的 TMOU=1800,结果发现 SSH 连接明明 30 分钟没动,却没断开——这是因为 TMOU 只监控 shell 输入空闲,对网络层“卡住但进程还在”的情况完全无效。比如笔记本休眠后重连、客户端崩溃、中间防火墙静默丢包,sshd 进程仍认为连接正常,TMOU 根本不触发。
常见错误现象:
- SSH 登录后保持静默 30 分钟,终端没退出,ps aux | grep sshd 仍能看到对应子进程
- echo $TMOU 显示正确值,但超时就是不生效
- 用 tmux 或 screen 启动的会话完全不受 TMOU 影响(它们接管了 stdin)
-
TMOU是 shell 层控制,仅作用于交互式 Bash/Zsh/Ksh - 它无法感知 TCP 连接状态,纯靠读取键盘输入判断“空闲”
- 普通用户执行
unset TMOU或在~/.bashrc里覆盖就能绕过
怎么配 sshd_config 让 SSH 真正 30 分钟断连
这是强制清理僵尸连接的关键。不是“保活”,而是“探测+断连”:
- 编辑
/etc/ssh/sshd_config,确保这三行启用且值匹配目标时长:ClientAliveInterval 600(每 10 分钟发一次心跳)ClientAliveCountMax 3(连续 3 次无响应就 kill 连接)MaxStartups 10:30:60(可选,防暴力连接耗尽资源) - 注意:
ClientAliveInterval×ClientAliveCountMax= 总超时秒数,600×3=1800 秒(30 分钟) - 别和
LoginGraceTime混:后者管“登录前等待时间”,和已建立连接的空闲无关 - 改完必须 reload,不是 restart:
sudo systemctl reload sshd(避免中断正在运行的会话)
验证是否生效:sudo sshd -T | grep -E "clientalive",输出应为小写 clientaliveinterval 600 和 clientalivecountmax 3。
怎么让 TMOU 生效且难绕过
如果要兼顾本地 tty 和 SSH 的 shell 层退出,且防止用户轻易关闭,推荐用 /etc/profile.d/ + 只读方式:
- 创建脚本:
sudo tee /etc/profile.d/autologout.sh写入三行:TMOU=1800readonly TMOUexport TMOU - 设执行权限:
sudo chmod +x /etc/profile.d/autologout.sh - 验证只读:
declare -p TMOU输出中必须含readonly字样;尝试unset TMOU会报错 - 不建议全局禁用:
TMOU=0虽可临时绕过,但运维脚本里应显式加前缀,如TMOU=0 tail -f /var/log/syslog
注意:图形终端(GNOME Terminal)、tmux、screen 默认不继承 TMOU,需在会话内单独设置或依赖 SSH 层保活。
容易被忽略的兼容性细节
不同发行版和 OpenSSH 版本对参数支持有差异:
- RHEL/CentOS 7 的
sshd不支持ClientAliveCountMax 0,设为 0 会被忽略,必须 ≥1 - Debian/Ubuntu 的
sshd -T输出全小写,而旧版可能保留大写,grep 时注意大小写 - csh/tcsh 用户需用
autologout而非TMOU,配置文件是/etc/csh.cshrc -
sudo操作期间若无输入,TMOU仍会计时,可能中途登出;建议设为 900–1800 秒平衡安全与可用性
真正起作用的是两层机制的叠加:shell 层负责“人没动”,SSH 层负责“线断了但进程还活着”。缺一不可,且各自有绕过路径,生产环境必须双控。











