Linux ss 命令详解
ss(Socket Statistics)是 Linux 系统中功能极其强大的网络套接字统计工具。它是现代 Linux 系统中 netstat 命令的完美替代者。
与 netstat 相比,ss 能够直接利用 Linux 内核的 tcp_diag 模块通过 netlink 接口提取网络状态数据,不需要读取和解析复杂的 /proc 虚拟文件系统,因此在面对数万、数十万的高并发或海量连接时,它的运行速度和资源消耗都具有无可比拟的绝对优势。
本文将为您全面、详尽地拆解 ss 命令的所有参数及其高级过滤语法,帮助您将其打造成排查网络故障、优化系统性能的绝对利器。
1. 输出字段含义详解
在不加任何过滤选项时,ss 会默认列出当前所有已建立连接(established connections,且非监听状态)的套接字(TCP/UDP/UNIX)。其默认输出格式如下:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
u_str ESTAB 0 0 * 19283 * 0
tcp ESTAB 0 0 192.168.1.100:22 192.168.1.50:52345
其中各列字段的含义解析如下:
| 字段名称 | 英文全称 | 含义说明 |
|---|---|---|
| Netid | Network Identifier | 套接字协议类型(例如:tcp、udp、raw、u_str【UNIX 字节流】、u_dgr【UNIX 数据报】、nl【Netlink】等)。 |
| State | Socket State | 套接字当前的连接状态(对于 TCP 来说是具体的 TCP 状态,如 ESTAB、LISTEN、TIME-WAIT 等;对于非连接协议如 UDP,则可能是 UNCONN 或 ESTAB)。 |
| Recv-Q | Receive Queue | 接收队列: - 对于非监听状态的连接(如 ESTAB):表示已接收到但尚未被用户进程读取(通过 read() 或 recv())的字节数。- 对于监听状态的套接字( LISTEN):表示当前已经完成三次握手、正在等待被应用程序 accept() 的连接数量。 |
| Send-Q | Send Queue | 发送队列: - 对于非监听状态的连接:表示已发送但尚未收到对端确认(ACK)的字节数。 - 对于监听状态的套接字:表示该监听套接字所允许的最大三次握手队列(backlog)上限。 |
| Local Address:Port | Local Address & Port | 本地 IP 地址(或主机名)以及绑定的本地端口号(或服务名)。 |
| Peer Address:Port | Peer Address & Port | 对端(远程)IP 地址以及绑定的远程端口号。 |
2. 核心参数大全(分类详述)
ss 的参数极其丰富。为了便于查阅,以下将所有支持的参数按照功能逻辑进行分类讲解,并对每个参数的底语义和输出影响做深度剖析。
2.1 基础与常规参数
| 短选项 | 长选项 | 功能描述与深度剖析 |
|---|---|---|
-h | --help | 显示命令的参数帮助手册摘要。 |
-V | --version | 显示 ss 的版本信息(来自 iproute2 工具集)。 |
-H | --no-header | 隐藏表头。在编写 Shell 脚本需要对输出做解析时极其有用,避免表头行干扰过滤逻辑。 |
-O | --oneline | 单行模式。强制将每个套接字的所有详细指标(即使启用了 -i 或 -m 这种会换行的详细模式)全部输出在同一行内,便于配合 grep、awk 等文本工具进行流式处理。 |
-n | --numeric | 数字显示。直接显示 IP 地址和端口号,不尝试通过 /etc/services 或 DNS 逆向解析为服务名/主机名(例如将 22 显示为数字而非 ssh)。这不仅能极大提升在大网络环境下的查询速度(避免 DNS 查询超时),还会让带宽等内部指标以字节数原始格式呈现。 |
-r | --resolve | 解析名字。尝试将数字格式的 IP 和端口解析为主机名和服务名。默认不启用。 |
2.2 状态与检索范围参数
| 短选项 | 长选项 | 功能描述与深度剖析 |
|---|---|---|
-a | --all | 显示所有套接字。包括处于监听(Listening)状态和非监听(Non-listening,如已连接的 Established、TIME-WAIT 等)状态的所有套接字。 |
-l | --listening | 仅显示监听状态的套接字。在日常服务排错中,通常用来确认自己的服务(如 Nginx、MySQL)是否成功在对应端口上启动并监听。 |
-s | --summary | 输出统计摘要。不列出具体的单个连接,而是输出一个汇总统计表,包含当前系统中 TCP、UDP、RAW、IP 及 Unix Domain 等各类套接字在各种状态下的总量。该功能性能消耗极低,非常适合作为系统监控的日常抓取指标。 |
-E | --events | 持续监控套接字销毁事件。运行该选项后,ss 会保持前台阻塞运行,并在系统中有套接字被关闭销毁时实时打印出来。适合用来观测短连接高频断开的场景。 |
2.3 协议过滤参数
通过以下参数,你可以限定 ss 只列出特定网络协议或类型的套接字。
| 短选项 | 长选项 | 功能描述与深度剖析 |
|---|---|---|
-4 | --ipv4 | 仅显示 IPv4 协议族的套接字。 |
-6 | --ipv6 | 仅显示 IPv6 协议族的套接字。 |
-0 | --packet | 仅显示 PACKET 类型的套接字(即直接在链路层/网络设备驱动层收发原始数据包的套接字,常用于抓包工具如 tcpdump,或者底层路由协议)。 |
-t | --tcp | 仅显示 TCP 协议套接字。 |
-u | --udp | 仅显示 UDP 协议套接字。由于 UDP 是无连接的,默认不带参数的 ss 可能不会显示空闲的 UDP 绑定,建议结合 -a 使用。 |
-w | --raw | 仅显示 RAW(原始套接字)类型。RAW 套接字允许直接构建 IP 头部或不经传输层协议封装,常用于 Ping、ICMP 检测等程序。 |
-x | --unix | 仅显示 UNIX Domain Sockets(本地进程间通信套接字)。在单机内部微服务、PHP-FPM、Redis 与 Nginx 之间等本地高性能通信场景中大量使用。 |
-d | --dccp | 仅显示 DCCP(数据报拥塞控制协议)套接字。 |
-S | --sctp | 仅显示 SCTP(流控制传输协议)套接字,多用于电信骨干网和高可靠并发数据传输。 |
-M | --mptcp | 仅显示 MPTCP(多路径 TCP)套接字。多路径 TCP 允许终端设备在多个物理网卡(如 Wi-Fi 和 5G)上同时传输同一个 TCP 会话的数据。 |
| 无 | --tipc | 仅显示 TIPC(透明进程间通信协议)套接字,常用于集群内部节点之间的高效无缝通信。 |
| 无 | --vsock | 仅显示 vsock 套接字,用于 Hypervisor(宿主机)与虚拟机(VM)之间的超高速无网络协议栈本地通信。 |
| 无 | --xdp | 仅显示 XDP(eXpress Data Path)套接字。配合 eBPF 使用,可以在网卡驱动层实现极高带宽的报文旁路和极低延迟处理。 |
-f | --family=FAMILY | 指定要显示的协议族。FAMILY 的可选值包括:inet(IPv4)、inet6(IPv6)、link(PACKET)、unix、netlink、vsock、tipc、xdp 以及 help。 |
2.4 详细指标与扩展信息参数
这部分参数是 ss 相比 netstat 最强大的地方,它能够输出极深的网络协议层和系统层监控指标。
| 短选项 | 长选项 | 功能描述与深度剖析 |
|---|---|---|
-p | --processes | 显示进程信息。展示哪个进程(进程名、PID、文件描述符 File Descriptor)持有了这个套接字。需要 root 或 sudo 权限才能查看到其他用户的进程套接字映射。 |
-T | --threads | 显示线程信息。不仅展示拥有套接字的进程,还会精准展示到该进程下的哪一个特定线程(Thread ID)。此选项隐含了 -p 的效果。 |
-e | --extended | 显示扩展系统信息。输出包括进程的 UID(属于哪个系统用户)、Inode 节点号、以及内核中该套接字的唯一 64 位 Cookie(哈希标识符)。 |
-m | --memory | 显示套接字内存使用细节。输出 skmem 指标,极具分析价值。详细结构见下文深度剖析。 |
-i | --info | 显示 TCP 内部指标。输出当前连接的各种内核 TCP 控制信息,如 RTT(往返时延)、Cwnd(拥塞窗口)、Ssthresh、重传计数等。详细指标见下文。 |
| 无 | --tipcinfo | 仅显示 TIPC 套接字的内部特有细节信息。 |
| 无 | --tos | 显示 TOS(Type of Service)信息。输出 IPv4 头部中的 TOS 字段值以及其在 Linux 内核中的服务级别/优先级。 |
| 无 | --cgroup | 显示 cgroup 归属信息。展示该网络套接字所对应的进程处于 Linux 内核哪一个控制组(cgroup v1/v2)路径下。对于排查容器化(Docker/Kubernetes)环境中的网络控制非常有用。 |
-b | --bpf | 显示套接字绑定的 BPF 过滤器信息。若有 eBPF 或经典 socket filter 附加在此套接字上,该参数会展示对应的过滤代码或引用。 |
-Z | --context | 显示进程 SELinux 上下文。展示进程对应的安全上下文标签。 |
-z | --contexts | 显示进程与套接字的 SELinux 上下文。比 -Z 更进一步,同时打印出进程和套接字两者的 SELinux 安全属性。 |
| 无 | --inet-sockopt | 展示 Inet 套接字选项。输出各种处于生效状态的底层套接字特定选项。 |
2.5 高级操作与过滤参数
| 短选项 | 长选项 | 功能描述与深度剖析 |
|---|---|---|
-K | --kill | 强制杀掉匹配的套接字。它是管理员紧急切断恶意连接、黑客攻击或僵尸连接的终极武器。你可以结合后面的过滤语法来批量、精确地销毁 TCP 连接(例如强制断开来自某个特定 IP 的所有 TCP 传输)。只有部分高版本 Linux 内核支持对特定类型套接字的强行 Kill 操作。 |
-N | --net | 切换网络命名空间。允许直接在当前的 shell 中查看指定的 Network Namespace(网络命名空间)内的网络状态。例如 -N ns1 可以让你不用执行 ip netns exec ns1 ss 就能查看到 ns1 内部的端口情况。 |
-A | --query / --socket | 联合查询选择。通过用逗号分隔的列表指定需要查询的类型组合。支持的关键字极广,如:all、inet、tcp、udp、raw、unix_stream、unix_dgram、packet 等。 |
-D | --diag=FILE | 导出原始诊断数据。将内核中 TCP 套接字的原始原始二进制诊断信息转储(Dump)到指定的文件中。这主要用于内核底层调试或离线分析。 |
-F | --filter=FILE | 从文件中读取过滤规则。如果你的过滤表达式非常复杂,或者需要批量高频执行,可以把过滤表达式写在一个文本文件中,通过 -F 引入执行。 |
3. 关键高级指标深度剖析
在使用 -m(内存)和 -i(TCP 信息)等参数时,ss 会输出极其底层的性能调优指标。理解这些指标对于网络应用(例如 Netty、Nginx、Redis、Web 服务器)的吞吐量调优至关重要。
3.1 -m, --memory 内存分配细节剖析
当你运行 ss -tm 时,输出中会带有形如 skmem:(...) 的细节。这些字段反映了内核为该套接字所开辟的缓冲区状态:
skmem:(r0,rb131072,t0,tb16384,f3072,w0,o0,bl0,d0)
具体字段定义如下:
r<rmem_alloc>(r0): 当前已被内核接收但尚未被应用程序读取的数据包实际占用的内存大小(字节)。rb<rcv_buf>(rb131072): 该套接字当前接收缓冲区的最大容量限制。可以通过sysctl中的net.ipv4.tcp_rmem或是套接字选项SO_RCVBUF进行动态调节。t<wmem_alloc>(t0): 当前已经发送到网络协议栈第三层(网络层,如 IP 层),正等待物理网卡发送并得到确认(ACK)的数据包所占用的内存。tb<snd_buf>(tb16384): 该套接字发送缓冲区的最大容量限制。可以通过sysctl的net.ipv4.tcp_wmem或者是套接字选项SO_SNDBUF调节。f<fwd_alloc>(f3072): 预分配/缓存内存。内核为该套接字提前向系统内存页面池申请的、当前尚未使用的空闲预分配空间。当套接字需要发送/接收新数据时,会直接从该空间中扣减,避免了频繁触发内核内存分配操作的开销,提升了性能。w<wmem_queued>(w0): 已经在发送队列中(例如被应用层调用了send()),但尚未被内核正式发送到网络第三层的报文所占用的内存。o<opt_mem>(o0): 用于存放套接字选项、辅助控制数据(如 TCP MD5 签名密钥、IP 选项包信息等)占用的额外内存空间。bl<back_log>(bl0): 处于进程上下文积压队列中的数据包大小。当进程正在用户态读取数据时,如果此时网卡又收到了新包,内核不会立即将其上送应用,而是先放在 backlog 队列中,等当前读取调用结束后立即传送。d<sock_drop>(d0): 丢包计数器。由于当前套接字缓冲区空间被占满,在分流(de-multiplexed)并注入此套接字前,被内核直接丢弃的报文包总数。如果此数值大于 0,说明接收缓冲区太小,或者系统处理性能太差,导致了应用层“爆仓”丢包。
3.2 -i, --info 内核 TCP 信息详解
执行 ss -ti 会展示连接的各项底层 TCP 统计参数,这是识别“慢连接”和网络拥塞的绝佳方法:
ts sack cubic wscale:7,7 rto:200 rtt:0.12/0.05 ato:40 mss:1460 rcvspace:14600 ssthresh:10 cwnd:10
主要内部指标含义:
ts: 启用了 TCP 时间戳(TCP Timestamps, RFC 1323)。sack: 启用了选择性确认(Selective ACK),允许接收端只确认缺失的片段,避免大量不必要的重传。cubic/bbr: 指明当前 TCP 连接所采用的拥塞控制算法。wscale:7,7: 双方协商的窗口扩大因子(Window Scale Value)。本地为 7,对端也为 7,意味着实际 TCP 窗口大小需要在头部窗口值的基础上向左位移 7 位(即乘以 $2^7 = 128$ 倍)。rto:200: 重传超时时间(Retransmission Timeout),单位为毫秒(ms)。如果超过 200ms 未收到确认,将触发报文重传。rtt:0.12/0.05: 往返时延(Round-Trip Time)。平均往返时延为 0.12ms,其均方差(rttvar)为 0.05ms。RTT 是衡量网络物理延迟的最关键指标。ato:40: 延迟确认定时器(Ack Timeout)时间,单位为毫秒。mss:1460: 最大报文段大小(Maximum Segment Size)。决定了在不发生 IP 分片的情况下,单个 TCP 报文段最多能承载的应用层数据字节数(通常在以太网中,1500 字节 MTU 减去 40 字节 TCP/IP 头部后,MSS 默认为 1460)。rcvspace:14600: 套接字为了让接收端能充分利用带宽而向对端宣告的可用窗口大小上限。cwnd:10: 拥塞窗口(Congestion Window)大小。表示发送端在未经对端确认的情况下,最多可以同时在网络中传输的 MSS 包个数。ssthresh:10: 慢启动阈值(Slow Start Threshold)。当 cwnd 小于此值时,TCP 处于慢启动指数增长阶段;大于此值时,进入拥塞避免线性增长阶段。
3.3 -o, --options 定时器信息详解
运行 ss -to 时,输出中会附加 timer:(...) 信息。
它的格式为:
timer:(<timer_name>,<expire_time>,<retrans>)
<timer_name>: 定时器名称,当前支持以下 5 种:on: 重传定时器(retransmit timer)、快速重传定时器(early retrans timer)或尾部丢包探测定时器(tail loss probe timer)。keepalive: TCP 连接保活定时器。timewait: TIME_WAIT 状态回收定时器。persist: 零窗口探测定时器(Zero window probe timer,当对端宣告接收窗口为 0 时触发,用于定期探测对端窗口是否释放)。unknown: 未知或上述以外的定时器。
<expire_time>: 还有多长时间该定时器会超时触发。<retrans>: 该定时器关联的重传或探测行为已经发生了多少次。
4. 状态过滤语法(STATE-FILTER)
ss 允许你直接在命令行参数后通过 state 或 exclude 语法指定要检索的连接状态,这在排查由于过多处于特定状态(如 TIME_WAIT 或 CLOSE_WAIT)的连接导致端口耗尽的问题时十分便捷。
4.1 语法格式
ss [ options ] [ state STATE-FILTER ] [ exclude STATE-FILTER ]
4.2 支持的状态标识
标准 TCP 状态:
established(已建立连接)syn-sent(SYN 已发送,等待握手)syn-recv(收到 SYN,已发送 SYN-ACK,等待第三次握手)fin-wait-1(主动关闭连接,发送了 FIN)fin-wait-2(收到对端对 FIN 的 ACK,等待对端的 FIN)time-wait(连接已关闭,等待 2MSL 时间以确保对端收到 ACK)closed(连接完全释放)close-wait(收到对端的 FIN,并发送了 ACK;等待本地程序关闭连接并发送 FIN)last-ack(收到对端的 FIN 并发送了 ACK,本地关闭也发送了 FIN,正在等待最后的 ACK)listening(正在监听端口)closing(双方同时主动关闭连接并发送了 FIN,正在等待最后的 ACK)
预定义的状态别名(集合):
all: 包含所有状态。connected: 处于连接状态的所有套接字(除listening和closed之外的所有状态)。synchronized: 处于同步建立状态的套接字(所有connected状态中剔除掉syn-sent后的状态)。bucket: 处于极简轻量级维护阶段的套接字,专门指time-wait和syn-recv(在内核中作为 mini-sockets 存在)。big: 所有的“大套接字”,与bucket互补(包含established,syn-sent,fin-wait-1,fin-wait-2,closed,close-wait,last-ack,listening,closing)。
4.3 过滤示例
- 仅显示处于
TIME_WAIT状态的 TCP 连接:ss -t state time-wait - 显示除
listening之外的所有 TCP 连接:ss -t exclude listening - 显示所有处于已连接(Connected)状态的连接:
ss -t state connected
5. 表达式过滤语法(EXPRESSION)
除了简单的状态过滤,ss 还配备了功能等同于 tcpdump 的极强的表达式语法,能够根据端口、目标/源 IP、网卡接口、fwmark 防火墙标记等进行精细过滤。
5.1 语法基础
- 逻辑操作符(按优先级从低到高):
or(可以写成or、|、||)and(可以写成and、&、&&)。若两个连续表达式之间没有写任何操作符,默认隐式等同于and。not(可以写成not、!)
- 括号分组:可以使用
(和)来编组复杂子条件,但是在 shell 中使用时必须使用反斜杠转义或用单引号包裹,以防被 shell 提前解析。
5.2 核心过滤谓词及实例
1) 端口过滤(sport / dport)
比较源端口(sport)或目的端口(dport)的值。
支持的比较操作符包括:=(或 ==、eq)、!=(或 ne、neq)、<(或 lt)、<=(或 le)、>(或 gt)、>=(或 ge)。
- 匹配源端口为 80 或 443 的连接:
ss -t 'sport = :80 or sport = :443' - 匹配目的端口大于 1024 的所有连接:
ss -t 'dport > :1024' - 匹配非 22 端口的 TCP 监听连接:
ss -tl 'sport != :22' - 注意:端口号前必须有冒号
:(例如:80),或者你也可以直接写对应的服务名称,例如'sport = :http'。
2) 主机与网络过滤(src / dst)
检查源 IP/名称(src)或目的 IP/名称(dst)。支持 CIDR 网段表示。
- 匹配目的 IP 为 192.168.1.100 的连接:
ss -t 'dst 192.168.1.100' - 匹配源 IP 属于 10.0.0.0/8 网段的所有连接:
ss -t 'src 10.0.0.0/8' - 排除目标 IP 为本地回环地址(127.0.0.1)的连接:
ss -t 'not dst 127.0.0.1'
3) 网络接口过滤(dev)
根据套接字绑定的网卡接口过滤。支持 = 和 !=。
- 仅匹配通过以太网卡
eth0传输的连接:ss -t 'dev = eth0'
4) 防火墙标记与 cgroup 过滤(fwmark / cgroup)
- 根据防火墙标记(fwmark)过滤:
ss -t 'fwmark = 1' ss -t 'fwmark = 0x01/0x03' # 掩码匹配最末两位 - 根据 cgroup 目录过滤(适用于容器或 systemd 服务的流量划分):
ss -t 'cgroup = "/sys/fs/cgroup/unified/system.slice/nginx.service"'
5) 自动分配端口过滤(autobound)
- 匹配那些端口由系统临时动态分配(ephemeral port),而不是应用主动显式绑定的套接字。
ss -t autobound
5.3 组合拳:复杂混合过滤示例
在真实运维场景中,我们需要将协议参数、状态参数和表达式过滤组合在一起使用。请务必注意在 shell 中使用单引号 ' 包裹复杂的表达式!
场景 1:查找所有来自外部 IP(排除本地 10.x.x.x 网段及本地环回),且连接到我们本地 80/443 端口、状态为
ESTABLISHED的 TCP 连接:ss -t -p state established 'dport = :80 or dport = :443 and not src 10.0.0.0/8 and not src 127.0.0.1'场景 2:找出所有连接数异常、目标地址不是私有网段的、端口为 80 的短连接(如处于
TIME_WAIT的连接):ss -t state time-wait 'dport = :80 and not dst 192.168.0.0/16 and not dst 10.0.0.0/8'场景 3:强行杀掉来自 IP 198.51.100.50 访问本机的 TCP 连接(紧急安全响应):
sudo ss -K 'src 198.51.100.50'
6. ss 与 netstat 常用命令无缝转换表
如果您习惯于使用老旧的 netstat,以下对照表可帮助您快速平滑过渡到 ss:
| 运维排查目标 | 老旧 netstat 命令 | 现代高效 ss 命令 |
|---|---|---|
| 列出所有监听状态的 TCP 和 UDP 端口 | netstat -tunl | ss -tunl |
| 显示所有套接字,并展示对应的进程/PID | netstat -anp | ss -anp |
| 仅查看 TCP 的 Established 活跃连接 | netstat -at (手动配合 grep 过滤) | ss -t (默认即为 established) |
| 快速获取网络套接字整体统计情况 | netstat -s | ss -s (速度快百倍,摘要更清晰) |
| 查看进程及其线程持有的套接字 | 无法做到 | ss -tT |
| 查看特定端口(如 3306)的占用进程 | netstat -anp | grep 3306 | ss -tanp 'sport = :3306 or dport = :3306' |
7. 生产环境实战高频示例
最后,为您精选 5 个在生产服务器日常巡检、性能调优和故障排查中最高频实用的 ss 经典命令:
1) 找出当前服务器上连接数最多的前 10 个外部 IP
通过对 Established 连接进行分析、统计和排序,快速识别是否有异常的恶意扫描或单 IP 高频访问。
ss -ntu state established | awk '{print $6}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -n 10
2) 实时查看系统的 TCP 握手队列积压情况(排查半连接/全连接队列爆满)
检查 LISTEN 状态下的 Recv-Q 是否接近或等于 Send-Q。如果 Recv-Q 值很大,说明应用程序(如 Tomcat、Nginx)处理过慢,导致 Linux 的全连接队列(Accept Queue)堆积溢出。
ss -lnt 'sport = :80 or sport = :443'
3) 诊断特定的客户端连接是否存在网络拥塞与高延迟
使用 -i 查看具体的往返延迟(rtt)、拥塞窗口(cwnd)以及是否有重传。如果 rtt 很高,说明两端网络延迟大;如果有较多的重传和较低的 cwnd,可能发生了丢包。
ss -ti 'dst 203.0.113.88'
4) 查看本地进程间通过 Unix Sockets 通信的活跃详情
展示所有活跃的、由于 Unix 域套接字通信产生的本地管道连接,同时显示对应的进程 PID 极其连接路径。
ss -x -p -a
5) 强行阻断针对特定高危端口(如 RDP 3389 / SMB 445 / SSH 22)的未知 IP 暴力破解
在防火墙尚未下发拦截策略前,通过 ss -K 直接强行切断现有的非法会话。
sudo ss -tx -K 'dport = :22'
ss 工具不仅是 netstat 在速度和资源开销上的全面升级,更通过强大的状态过滤、表达式查询和深度的套接字内存与 TCP 性能指标探测,成为了现代 Linux 运维与架构设计中不可或缺的底层诊断神器。熟练掌握并灵活运用 ss,能让您在复杂的网络故障面前瞬间洞察本质,成倍提升工作效率。