“僵死连接”指tcp连接卡在close_wait、fin_wait2或time_wait等异常状态长期不释放,导致端口耗尽和服务假死;根源多为应用未正确关闭socket或进程异常退出后内核残留tcb,需用ss定位连接与进程,结合ps、lsof、strace和/proc分析根因。

Linux 中所谓“僵死连接”,通常不是进程僵死(Z 状态),而是 TCP 连接卡在异常状态(如 CLOSE_WAIT、FIN_WAIT2、TIME_WAIT 长期不释放),导致端口耗尽、连接堆积、服务响应迟缓甚至假死。这类连接背后往往有业务进程未正确关闭 socket,或异常退出后内核残留连接状态。定位关键在于把网络连接与真实业务进程关联起来。
查出异常连接及其对应进程
优先使用 ss(比 netstat 更快、更准确):
- ss -tnp | grep -E '(CLOSE_WAIT|FIN_WAIT|TIME_WAIT)' —— 列出所有处于可疑状态的 TCP 连接,并显示所属进程(需 root 权限)
- ss -tnop state close-wait —— 专查 CLOSE_WAIT,这是最常见的“连接没关”信号(对端已断,本端未调用 close)
- ss -tnop sport = :8080 —— 指定端口过滤,快速定位某服务的连接状态
若 ss 显示 “users:(("java",pid=12345,fd=102))”,说明该连接由 PID 12345 的 java 进程持有,fd=102 是其文件描述符编号,可进一步分析。
确认进程是否仍在运行且行为异常
拿到 PID 后,不能只看进程是否存在,要验证它是否“活着但失能”:
- ps -o pid,ppid,stat,wchan:20,cmd -p 12345 —— 关键看 STAT(是否为 S/R/D)、WCHAN(等待哪个内核函数,如 tcp_sendmsg 表示卡在发包,sk_wait_data 表示卡在 recv)
- lsof -p 12345 -a -iTCP —— 查该进程打开的所有 TCP 连接,对比 ss 输出,确认哪些 fd 对应僵死连接
- cat /proc/12345/fd/102 2>/dev/null | head -c 100 —— 尝试读取对应 fd(谨慎操作),若阻塞或无输出,大概率 socket 已半关闭或对端失联
追踪连接卡住的具体原因
仅知道 PID 不够,需定位代码级问题点:
- strace -p 12345 -e trace=sendto,recvfrom,close,connect 2>&1 | tail -20 —— 实时观察 socket 相关系统调用,常见卡在 recvfrom(等数据不来)或 sendto(发不出去,可能对端 FIN 未处理)
- cat /proc/12345/stack —— 查看内核态调用栈,例如出现 tcp_recvmsg 或 inet_wait_for_connect,说明进程正阻塞在 TCP 层
- 结合业务日志:检查该进程最近是否有超时、重试、DNS 解析失败等记录;特别注意 /etc/hosts 主机名解析错误 导致的长期阻塞(如 InetAddress.getLocalHost() 卡住)
区分真僵死连接与正常 TIME_WAIT
并非所有非 ESTABLISHED 状态都需干预:
- CLOSE_WAIT:危险信号,表明对端已关闭,本端应用未调用 close(),必须修复代码或重启进程
- FIN_WAIT2:本端已发 FIN,等待对端 ACK+FIN;若持续数分钟,大概率对端崩溃或网络中断,需检查客户端行为
- TIME_WAIT:正常关闭后的必经阶段(默认 60 秒),大量存在说明服务短连接频繁;可通过 net.ipv4.tcp_tw_reuse=1 优化,但不可盲目禁用
- SYN_RECV:可能遭遇 SYN Flood 攻击,需配合防火墙排查











