Linux ss命令排查指南
一、前言:为什么你应该忘掉netstat
如果你还在用 netstat -antp 排查服务器端口占用,是时候切换到 ss 了。
ss(Socket Statistics)是 iproute2 工具包中的一员,能直接查询内核 socket 统计信息,速度远超 netstat。两者的性能差异在遇到高并发连接时极其明显------一台十万连接的服务器,netstat 可能卡死半天出不来结果,ss 却可以秒出。
简单来说:netstat 读 /proc 遍历所有 pid,ss 直接调用 netlink 跟内核对话。路径不同,效率天差地别。
本文从日常使用的角度出发,把参数和排查场景串起来,读完你可以直接在工作中用起来。
二、基础三连:最常用的参数组合
2.1 查看所有 TCP 连接
bash
ss -tan
-t:只看 TCP-a:所有状态(包括 LISTEN 和 非 LISTEN)-n:以数字形式显示端口,不做 DNS 反向解析(生产环境必带,否则卡死)
输出示例:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
ESTAB 0 0 192.168.1.10:22 10.0.0.5:51824
TIME-WAIT 0 0 192.168.1.10:443 10.0.0.6:60231
2.2 只看监听端口
bash
ss -tln
-l:只看 LISTEN 状态
这一条是日常开发中最常用的命令------"我这个服务到底起来了没有?端口有没有被占用?"一行搞定。
2.3 显示进程信息
bash
ss -tanp
-p:显示占用该 socket 的进程名和 PID
这是排错利器。端口被哪个进程占了,一眼就知道。
三、状态过滤:精准定位连接问题
TCP 连接有多种状态,生产环境排查时,我们通常只关心特定状态的连接。
3.1 查看所有 TIME-WAIT 连接
bash
ss -tan state time-wait
state 参数支持的 TCP 状态有:
established、syn-sent、syn-recv、fin-wait-1、fin-wait-2、time-wait、closed、close-wait、last-ack、listen、closing
3.2 实战场景:服务端口被占用
你的 Java 服务启动报 Address already in use,快速查谁在占用 8080:
bash
ss -tlnp | grep :8080
# 或者更精准
ss -tlnp 'sport = :8080'
输出会直接告诉你 PID 和进程名,接着 kill 就行。
3.3 实战场景:统计各状态连接数
服务器上连接池突然满了,先看TIME-WAIT和CLOSE-WAIT各有多少:
bash
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
输出类似:
324 ESTAB
156 TIME-WAIT
12 LISTEN
3 CLOSE-WAIT
1 State
如果 CLOSE-WAIT 数量很高,说明你的应用没有正确关闭连接(通常是代码里忘了调 close()),这是应用层bug,不是网络问题。
如果 TIME-WAIT 很高(比如上千),说明短连接过多,可以考虑开启 tcp_tw_reuse。
3.4 实战场景:查看指定端口的连接数
想知道 Nginx 的 443 端口扛了多少连接:
bash
ss -tan 'sport = :443' | wc -l
# 或者只看 ESTABLISHED
ss -tan state established 'sport = :443' | wc -l
四、进阶过滤:源/目的地址组合
ss 的过滤表达式非常强大,格式为 expr [ expr ...],支持的 key 包括 sport、dport、src、dst 等。
4.1 看某个客户端连了多少连接
怀疑某个 IP 在疯狂请求你的服务:
bash
ss -tan state established 'dport = :443' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head
4.2 看本机到某个远程地址的连接
排查服务调用外部 API 的情况:
bash
ss -tan 'dst 10.0.0.100 and dport = :3306'
这条命令能直接定位到本机哪些进程在连接目标 MySQL。
4.3 过滤与统计组合
查看本机 6379(Redis)端口被哪些客户端连接:
bash
ss -tan 'sport = :6379 or dport = :6379'
五、UDP 也别忘了
ss 不只管 TCP,UDP 也一样:
bash
# 所有 UDP socket
ss -uan
# 只看监听的 UDP
ss -uln
# 带进程信息
ss -uanp
排查 DNS 问题时(53端口),可以这样看:
bash
ss -uanp 'sport = :53 or dport = :53'
六、Unix Domain Socket
容器化环境里,php-fpm、MySQL、Docker daemon 经常通过 Unix socket 通信:
bash
ss -xln # 只看 LISTEN 的 Unix socket
ss -xanp # 全部 Unix socket 带进程信息
排查 MySQL 时,除了看 TCP 3306,也别忘了看 /var/run/mysqld/mysqld.sock 在不在、有没有进程在听。
七、实战案例合集
案例一:线上服务假死------大量 CLOSE-WAIT
现象:用户反馈页面打不开,Nginx 返回 502。
排查过程:
bash
# 1. 看服务端口还在不在
ss -tlnp | grep :8080
# 端口在,进程在
# 2. 看连接状态分布
ss -tan state established 'sport = :8080' | wc -l
ss -tan state close-wait 'sport = :8080' | wc -l
# CLOSE-WAIT 有 2000+,ESTABLISHED 只有几十
结论 :下游服务已经关闭了连接(发了 FIN),但本端应用没有调用 close(),导致大量 CLOSE-WAIT,文件描述符耗尽,新请求无法处理。
修复方向:检查 HTTP 客户端的连接关闭逻辑,确认 response body 是否每次都正确关闭。
案例二:端口被占用但 lsof 找不到
现象 :启动服务报 Address already in use,但 lsof -i:8080 查不到。
排查:
bash
ss -tlnp 'sport = :8080'
如果 ss 能看到 LISTEN 但 lsof 看不到,常见原因:
- Docker 端口映射残留(docker-proxy 进程)
- 容器里的进程在监听
- 内核态模块绑定的端口(比如某些 eBPF 程序)
可以用 ss -tlnpe(-e 扩展信息)看看更多细节。
案例三:TCP 重传排查
bash
ss -tine
-i 显示 TCP 内部信息,包括 RTT、重传次数、拥塞窗口等。这个输出比较长,但排查丢包问题时非常有用。
关键字段:
retrans:重传次数,持续增长说明链路丢包严重rtt:往返延迟cwnd:拥塞窗口大小,如果很小说明 TCP 认为网络拥堵unacked:已发送未确认的包数量
可以针对特定连接看:
bash
ss -tine 'sport = :443 and dst 10.0.0.5'
案例四:内存占用分析
bash
ss -tam
-m 显示 socket 内存使用情况:
skmem:(r0,rb37440,t0,tb87040,f0,w0,o0,bl0,d0)
rb:接收缓冲区大小tb:发送缓冲区大小r:已使用的接收缓冲区t:已使用的发送缓冲区
如果 r 持续接近 rb,说明应用读取速度跟不上接收速度,可能需要调整 net.core.rmem_max。
八、参数速查表
| 参数 | 含义 |
|---|---|
-t |
TCP |
-u |
UDP |
-x |
Unix Domain Socket |
-l |
仅 LISTEN |
-a |
所有 socket |
-n |
不解析服务名/DNS(生产必带) |
-p |
显示进程信息 |
-e |
扩展信息 |
-i |
TCP内部信息(RTT/重传/窗口) |
-m |
socket内存使用 |
-s |
汇总统计 |
-r |
解析主机名 |
-4 |
仅 IPv4 |
-6 |
仅 IPv6 |
-K |
关闭慢启动探测 |
state |
按TCP状态过滤 |
sport/dport |
源/目的端口过滤 |
src/dst |
源/目的地址过滤 |
九、常用组合记忆法
不用死记硬背,记住这几个场景就行:
| 场景 | 命令 |
|---|---|
| 我服务起了没 | ss -tlnp |
| 谁在连我的服务 | ss -tan 'sport = :端口' |
| 端口被谁占了 | ss -tlnp 'sport = :端口' |
| 我的服务在连谁 | ss -tan 'dport = :端口' |
| 连接数统计 | ss -s |
| TIME-WAIT多不多 | `ss -tan state time-wait |
| 网络是不是在丢包 | ss -tine |
| 内存是不是不够 | ss -tam |
十、总结
ss 是 Linux 系统工程师的瑞士军刀之一。它的优势在于:
- 快:直接与内核通信,高并发场景下几乎无感
- 表达式过滤:不用像 netstat 那样管道给 grep awk,ss 自带强大的过滤语法
- 信息全:TCP 内部状态、内存使用、重传统计一应俱全
日常排查记住三板斧:ss -tlnp 看监听、ss -tan 看连接全貌、ss -tine 看 TCP 细节,基本能覆盖 80% 的网络排查场景。
剩下的 20%,靠你对 TCP 状态机的理解和表达能力把 state、sport、dport 组合出花样来。
本文写于 2026 年 6 月,基于 Linux 内核 5.x/6.x 环境。不同发行版的 ss 版本可能有细微差异,以 ss --version 为准。