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