Shell 05_ss网络工具命令详解

一、ss命令 与 netstat命令

1.1 ss命令与 netstat命令概述

‌ss 命令是 Linux 系统中用于查看网络套接字信息的工具,全称 Socket Statistics,属于 iproute2 工具集,主要用于查看端口占用、网络连接状态和排查网络问题‌。‌‌‌

在没有 ss 命令以前,netstat 一直是 Linux 网络监控和故障排查中最常用的命令之一。当用户想要检查监听端口、查看 TCP 连接、查找占用某个端口的进程或者查看网络统计信息时,netstat 往往是首先想到的命令:

1
netstat -tulnp

不过,如今很多现代 Linux 系统推荐使用另一个命令(逐渐取代 netstat 命令):

1
ss -tulnp

为什么已经有了 netstat 命令还要开发 ss 新命令呢?答案并不只是 ss 是一个更新的命令。它实际上是 Linux 网络工具从旧的 net-tools集合 向 iproute2工具集 转变的一部分。

1.2 netstat 和 ss 是什么?

netstat 是一个传统的 Linux 网络工具,来自 net-tools 项目。它可以显示网络连接、路由表、接口统计信息、多播成员关系以及协议统计信息。

例如:

1
netstat -an

可以显示活动的网络 socket。 还可以使用:

1
netstat -tulnp

查看 TCP 和 UDP 监听 socket 以及对应的进程信息。

Linux netstat 的 man page 现在将这个程序描述为“mostly obsolete”,并明确推荐使用 ss 作为替代工具。

ss 通常被理解为“socket statistics”,它属于 iproute2 网络工具集。它的用途更加集中:用于查看 socket 以及显示 socket 统计信息。

二者对比如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
netstat
    |
    +-- sockets
    +-- routing
    +-- interfaces
    +-- statistics
    +-- multicast
    |
    +-- net-tools

ss
    |
    +-- sockets
    +-- TCP/UDP state
    +-- socket statistics
    +-- filtering
    |
    +-- iproute2

ss 并不是用来替代 netstat 原来提供的所有功能。例如,路由信息现在主要由 ip route 处理,而接口统计信息则由 ip -s link 等命令处理。

如果看看 Linux 的网络工具集,这件事情会更加清楚。较老的 Linux 系统通常使用这些命令:

1
2
3
4
ifconfig
route
arp
netstat

这些命令来自 net-tools 家族。

现代 Linux 系统越来越多地使用 iproute2 工具集:

1
2
3
4
5
6
ip addr
ip link
ip route
ip neigh
ss
tc

其目标是通过更加统一的工具来提供现代 Linux 网络功能。这意味着 netstat 被 ss 替代,是整个迁移过程的一部分。

例如:

1
netstat -r

通常替换为:

1
ip route

而:

1
netstat -i

通常替换为:

1
ip -s link

对于 socket 查看,对应的现代工具就是:

1
ss

Linux netstat 的 man page 明确记录了这些替代关系。

1.3 二者最重要的区别:socket 信息是如何获取的?

两个工具之间一个关键的技术区别,是它们从内核获取信息的方式不同。传统的 netstat 使用 /proc 提供的信息,包括:

1
2
3
/proc/net/tcp
/proc/net/udp
/proc/net/unix

而 ss 使用基于 Netlink 的 Linux socket diagnostic 机制。

内核中的 sock_diag 子系统提供了一种从内核获取 socket 信息的机制。它可以请求 socket 信息,并在获取 socket 列表时应用过滤条件。

当系统中存在大量 socket 时,这种区别就变得很重要。想象一下,一台繁忙的服务器上存在数千甚至数万个活动连接。如果一个工具需要通过传统接口处理大量 socket 信息,随着 socket 数量增加,其开销也可能越来越大。

最初的 ss 文档就是针对这个问题编写的。文档解释了,当 socket 数量较大时,读取 /proc/net/tcp 可能会变得非常麻烦,因此引入 ss,以提供更好的扩展能力。

当前的 netstat man page 也从另一个角度说明了这一点:在繁忙服务器上,当需要列出大量 socket 时,netstat 的性能可能比较差,因此推荐使用基于 Netlink 的 ss。

因此,性能优势并不只是一个实现细节。它来自一种专门为 socket 诊断设计的不同内核接口。

1.4 ss 查询更快

考虑一个简单的命令:

1
netstat -tan

以及它常见的现代替代形式:

1
ss -tan

两者都可以列出 TCP socket。在只有少量连接的机器上,两者之间的差异可能很难察觉。但在高负载服务器上,情况可能不同。

Web 服务器、反向代理、数据库服务器或者负载均衡器可能存在数千个活动连接或者最近关闭的连接。

Linux 的 sock_diag 接口允许更加直接地从内核请求 socket 信息。它还可以在内核中执行一些简单的过滤操作,从而减少需要传输到用户空间的 socket 数据量。更加复杂的布尔过滤仍然可以由 ss 在用户空间处理。

这也是 ss 在 socket 查看方面具有更好扩展能力的原因之一。

不过,需要避免简单地说“ss 总是更快”。当 socket 数量较少时,两者的差异可能几乎感觉不到。当系统中存在大量 socket,并且命令需要处理大量 socket 信息时,这种优势会更加明显。 \

1.5 ss 取代 netstat 的真正原因

为什么 ss 正在逐渐取代 netstat?主要有几个原因。

  • ss 属于现代 iproute2 网络工具集。
  • 它使用基于 Netlink 的 Linux socket diagnostic 基础设施,而不是依赖传统的 /proc/net 方式。
  • 当系统存在大量 socket 时,它具有更好的扩展能力。
  • 它可以提供更加详细的 TCP 和 socket 信息。
  • 它的 filtering 语言可以更加方便地查询你真正关心的连接。
  • Linux 网络生态本身也已经逐渐转向 iproute2。

因此,这种变化并不只是某一个命令变得流行了。它反映的是 Linux 暴露和管理网络信息的方式发生了变化。

二、ss命令功能介绍

2.1 ss 可以提供更详细的 TCP 信息

ss 的另一个重要优势,是它可以提供更多 TCP 信息。

例如:

1
ss -ti

可以显示 TCP 内部信息。根据内核版本和命令选项的不同,这些信息可能包括:

1
2
3
4
rtt
cwnd
retransmission information
TCP timers

当排查一些无法通过简单的 IP 地址和端口列表发现的问题时,这些信息非常有用。例如,假设某个应用程序报告连接速度很慢。如果看到:ESTABLISHED实际上并不能说明太多问题。你可能还想知道这个连接是否存在 retransmission、round-trip time 是多少,或者 TCP 的 congestion-control 状态是什么。相比 netstat 提供的传统 socket 列表,ss 可以提供更加详细的 TCP 和连接状态信息。

2.2 Filtering 是 ss 最有用的功能之一

另一个重要功能是 filtering 语法。使用 netstat 时,管理员经常需要使用类似下面的命令:

1
netstat -ant | grep ESTABLISHED

而使用 ss 时,可以直接把连接状态作为查询条件:

1
ss -tn state ESTABLISHED

也可以按照端口进行过滤:

1
ss -tn sport = :8080

或者:

1
ss -tn dport = :443

还可以按照地址进行过滤:

1
ss -tn dst 192.168.1.100

ss 支持根据源地址、目标地址、源端口、目标端口、设备名称、连接状态以及布尔运算符进行过滤。例如:

1
ss -tn state established '( dport = :22 or sport = :22 )'

可以查看已经建立的 SSH 相关连接。

这里外层的引号很重要,因为括号属于 ss 的过滤表达式。如果不使用引号,括号可能会被 shell 解释。

当服务器存在大量连接时,这一点尤其有用。与其先把所有连接输出出来,再进行文本过滤,不如直接表达你真正想查询的连接。

2.3 常见 netstat 命令与对应的 ss 命令

对于很多开发者来说,从 netstat 切换到 ss 最简单的方法,就是记住几个常见的替代命令。

  • 列出所有 TCP socket 旧:
1
netstat -at

新:

1
ss -ta
  • 列出所有 UDP socket 旧:
1
netstat -au

新:

1
ss -ua
  • 列出监听 socket

旧:

1
netstat -l

新:

1
ss -l
  • 列出 TCP 和 UDP 监听端口 旧:
1
netstat -tuln

新:

1
ss -tuln
  • 显示使用监听端口的进程

旧:

1
sudo netstat -tulnp

新:

1
sudo ss -tulpn
  • 显示已经建立的 TCP 连接 旧:
1
netstat -ant | grep ESTABLISHED

新:

1
ss -tn state ESTABLISHED

这些常见的协议和显示选项保持了相似的形式,因此迁移起来相对容易。

使用 -p 时,如果没有足够的权限,或者无法访问相关的进程信息,进程信息可能无法正常显示。

具体输出格式也与 netstat 不同,因此解析旧文本格式的脚本可能需要进行修改。尤其要避免依赖固定列位置,例如:

1
awk '{print $7}'

来提取 PID 信息。ss 的输出格式可能存在差异,直接替换命令很容易导致现有生产脚本失效。

2.4 ss 特别适合排查 TCP 状态

TCP 故障排查通常从连接状态开始。例如:

1
2
3
4
5
6
7
8
9
LISTEN
SYN-SENT
SYN-RECV
ESTABLISHED
FIN-WAIT-1
FIN-WAIT-2
CLOSE-WAIT
TIME-WAIT
LAST-ACK

可以使用:

1
ss -tan

查看 TCP socket 及其状态。

也可以查询特定状态:

1
ss -tan state TIME-WAIT

当排查以下情况时,这些信息会非常有用:

  • 大量 TIME-WAIT socket
  • 长时间处于 CLOSE-WAIT 的连接
  • SYN-RECV 数量异常增长
  • 应用程序似乎停止接受连接
  • 已建立连接数量异常多

不过,TIME-WAIT 是 TCP 正常的连接关闭状态。大量 TIME-WAIT socket 通常意味着较高的连接周转率,例如服务处理了大量短连接。不能自动将其理解为 socket 泄漏。

这个命令不会自动告诉你根本原因。它提供的是内核中的 socket 状态,可以结合应用日志、packet capture、metrics 以及其他诊断工具进行分析。

理解这一点对于正确解读网络故障排查命令非常重要。

2.5 ss 不仅可以查看 TCP

虽然 ss 经常用于 TCP 故障排查,但它并不只支持 TCP。例如:

1
ss -u

显示 UDP socket。

1
ss -x

显示 Unix domain socket。

1
ss -w

显示 raw socket。根据可用的内核功能和 ss 版本,其他支持的 socket family 还包括 SCTP、DCCP、packet socket、TIPC 和 VSOCK。

这使得 ss 成为了一个通用的 socket 查看工具,而不仅仅是某个 netstat 命令的替代品。

2.6 ss 值得记住的命令

学习现代 Linux 网络,以下这些命令可以覆盖日常故障排查中的很大一部分场景:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 查看 TCP 和 UDP 监听 socket
ss -tuln

# 查看带进程信息的监听 socket
sudo ss -tulpn

# 查看所有 TCP socket
ss -tan

# 查看已经建立的 TCP 连接
ss -tn state ESTABLISHED

# 查看 TCP 内部信息
ss -ti

# 按本地端口过滤
ss -tn sport = :8080

# 按远端端口过滤
ss -tn dport = :443

# 查看 socket 汇总信息
ss -s

# 查看 IP 地址
ip addr

# 查看路由表
ip route

# 查看接口统计信息
ip -s link

对于现代 Linux 系统来说,与其围绕 netstat 建立新的工作流程,不如优先学习这些命令。

2.7 实际的 Linux 网络故障排查流程

知道具体命令很有用。

知道什么时候使用这些命令更加重要。

假设某个应用程序无法接受 8080 端口的连接。

首先执行:

1
ss -ltnp 'sport = :8080'

它可以回答:

1
2
TCP 8080 端口上是否有监听?
哪个进程拥有这个 socket?

如果没有任何程序监听,就继续检查应用程序。

如果有程序监听,但客户端仍然无法连接,可以检查网络配置:

1
2
ip addr
ip route

如果连接已经存在,但行为异常,可以检查 TCP 状态:

1
ss -ti

如果需要了解实际有哪些 packet 经过网络接口,可以使用 packet capture 工具,例如:

1
tcpdump

这些工具回答的是不同的问题:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
ss
    存在哪些 socket?

ip addr
    配置了哪些地址?

ip route
    packet 将通过什么路径进行路由?

tcpdump
    网络上实际传输了哪些 packet?

相比使用一个命令处理所有网络问题,这样的故障排查流程更加有效。\

三、netstat 的其他功能去

3.1 netstat 的其他功能去哪了?

一个常见误解是,ss 完全替代了 netstat。实际上并不是这样。netstat 历史上将多个互不相关的网络功能集中在一个命令中。

例如:

1
netstat -r

用于显示路由信息。现代对应命令是:

1
ip route

类似地:

1
netstat -i

用于显示接口统计信息。

现代命令是:

1
ip -s link

而:

1
netstat -g

可以替换为:

1
ip maddr

这些功能属于 iproute2 工具集的其他部分,而不是 ss 的范畴。

这是现代 Linux 网络工具发生变化时最大的概念变化之一。

过去,一个大型命令负责处理多个互不相关的领域;现在,网络栈的不同部分由不同的专用命令负责。

简单的对应关系如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
netstat - socket information
        ↓
        ss

netstat - routing information
        ↓
        ip route

netstat - interface statistics
        ↓
        ip -s link

netstat - multicast information
        ↓
        ip maddr

3.2 netstat 完全没用了吗?

不是。在较老的系统、legacy 环境,或者维护现有脚本和文档时,netstat 仍然可能有用。

在一些系统上,它也可能仍然处于安装状态,管理员也已经习惯了使用它。

问题在于,对于现代 Linux socket 诊断来说,它已经不再是首选接口。

当前的 man page 明确将它描述为 mostly obsolete,并推荐使用 ss。同时还指出,在繁忙服务器上列出大量 socket 时,它的性能可能比较差。

因此,如果你主要使用当前的 Linux 系统,就没有太多必要继续学习新的、专门针对 netstat 的 socket 操作方式。

对于新的文档和故障排查流程,ss 通常是更值得学习的命令。

3.3 总结

netstat 在 Linux 网络的发展历史中发挥了重要作用。直到今天,它仍然很容易被认出来,因为一代又一代开发者都学习过这样的命令:

1
netstat -tulnp

但 Linux 网络已经发生了很大的变化。

内核提供了更新的接口来暴露网络状态,而 iproute2 工具集正是围绕这些接口设计的。

ss 利用了 socket diagnostic 基础设施,可以提供更加详细的 socket 和 TCP 信息,支持灵活的过滤,并且在处理大量连接时具有更好的性能。

与此同时,netstat 的其他功能也已经转移到专用命令,例如:

1
2
3
ip route
ip -s link
ip maddr

因此,从 netstat 转向 ss,更准确地说是 Linux 网络工具现代化的一部分。

如果你现在仍然习惯输入:

1
netstat -tulnp

那么现代 Linux 中通常可以使用:

1
ss -tulnp

命令发生了变化,更重要的是,底层 Linux 网络模型也在不断发展。