ss -tn state time-wait或close-wait可查对应状态套接字,状态名须小写带连字符,否则静默失效;加-o显示定时器,加-p需sudo且受内核版本与权限限制。

ss 怎么看 TIME_WAIT、CLOSE_WAIT 这些状态的套接字详情
直接用 ss -tn state time-wait 或 ss -tn state close-wait 就能列出对应状态的 TCP 套接字,但要注意:状态名必须小写、带连字符,且 state 后面不能跟多个状态(比如 state time-wait close-wait 会报错)。
常见错误是把状态写成大写(如 TIME-WAIT)或漏掉连字符(timewait),ss 会静默忽略该条件,返回空结果,容易误判为“没有这类连接”。
-
ss -tn state time-wait:只查 IPv4 的 TIME_WAIT 连接,不解析地址和服务名,速度快 - 加
-o可显示定时器信息(如timer:(keepalive,119min,0)),对判断连接是否卡在回收阶段很有用 - 加
-p需要sudo,否则看不到进程字段;即使有权限,某些内核版本(如 5.10+)对非 root 进程的fd映射可能受限,users:(())里 pid 可能为空
/proc/net/tcp 里怎么识别 ESTABLISHED 和 LISTEN 状态
/proc/net/tcp 是内核原始输出,第4列是十六进制状态码,不是文字。比如 01 表示 ESTABLISHED,0A 表示 LISTEN,08 是 CLOSE_WAIT —— 这些值固定不变,但得查文档或记熟几个常用码,否则容易看错。
用 awk 过滤更可靠:awk ' == "01" {print ,,}' /proc/net/tcp 输出本地/远程地址(十六进制)和状态码。注意地址列是十六进制 IP:PORT,比如 0100007F:0016 对应 127.0.0.1:22(0016 是十进制 22)。
- IPv6 状态在
/proc/net/tcp6,字段结构一致,但地址长度不同 - 该文件无需权限即可读,适合无 sudo 权限时做轻量排查
- 字段顺序固定,但不同内核版本列数可能微调(如新增 timestamp 列),建议始终用 `$n` 而非 `NF-1` 类动态索引
为什么 ss -tulnp 显示不了某些监听端口的进程名
最常见原因是权限不足:-p 需要能读取目标进程的 /proc/[pid]/fd/ 目录,而普通用户默认只能访问自己启动的进程。哪怕你看到某端口在监听,只要不是你 own 的进程,ss -tulnp 就会显示 - 或完全不显示 users:(()) 字段。
- 用
sudo ss -tulnp是标准解法,但生产环境有时禁用 sudo,此时可尝试lsof -i :端口号(需装 lsof,且同样受权限限制) - 某些容器化环境(如 rootless Podman)中,即使加了 sudo,
ss也可能因 PID 命名空间隔离而无法关联到宿主进程 - 如果
ss -tulnp显示了users:(("nginx",pid=1234,fd=6)),但ps aux | grep 1234找不到进程,大概率是该进程已退出但 socket 还在 TIME_WAIT 中未释放
netstat 和 ss 在状态过滤上有什么关键差异
netstat 不支持按状态筛选(如 netstat -tn | grep ESTABLISHED 是靠 shell 过滤,不是命令原生能力),而 ss 的 state 是内建谓词,直接走内核 socket 子系统路径,不经过用户态拼接,性能高、结果准。
-
netstat -tn默认包含所有状态(LISTEN/ESTABLISHED/TIME_WAIT 等混在一起),想筛特定状态只能靠grep,但grep LISTEN可能误匹配到字符串 “listen” 出现在其他列(比如进程名里有 listen) -
ss -tn state established是原子操作,不会漏行也不会多行,尤其在连接数过万时,ss耗时通常不到netstat的 1/5 - 部分旧版 netstat(如 RHEL 6 自带)不支持
-p显示进程,而 ss 从诞生起就原生支持,且兼容性更好
真正容易被忽略的是:状态码含义在不同协议下不通用 —— 比如 UDP 没有 ESTABLISHED,ss -un state established 永远返回空;查 UDP 绑定端口,只能用 ss -unl 看 LISTEN,别试图用 state 过滤。











