引言
说实话,我用了十几年 netstat。从最早的 Red Hat 9,到后来的 CentOS、Ubuntu,只要查端口、看连接,手指头就会自动敲出 netstat -tulnp。这命令熟得就像早上刷牙,闭着眼都能打出来。
直到有一天,我连上一台连接数爆满的 Web 服务器,想看看谁在占着连接不放。敲下 netstat -an | grep ESTABLISHED | wc -l,然后……我就去泡了杯茶。等我喝完茶回来,命令还没跑完。
那一刻我意识到:我老了
为什么 netstat 慢得像老牛拉车?
netstat 的问题不在于功能,而在于它的工作方式。它要读取 /proc 目录下每个进程的信息,再拼出网络状态。连接越多,它要翻的“文件夹”就越多,自然越慢。
而 ss(Socket Statistics)不一样。它直接从内核的 netlink 接口拿数据,相当于走内部通道,速度快得不是一星半点。
来个实测对比:
# 在一台有上万连接的服务器上
$ time netstat -an | grep :80 | wc -l
real 0m15.234s
$ time ss -o state all '( dport = :80 )' | wc -l
real 0m0.045s
ss 基本用法:从 netstat 过来的人怎么上手
1. 查看所有监听的端口(替代 netstat -tuln)
$ ss -tuln
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 128 *:22 *:*
tcp LISTEN 0 511 *:80 *:*
-tTCP-uUDP-l只看监听中的-n别给我转服务名,直接出数字
2. 查看所有 TCP 连接(替代 netstat -tan)
ss -tan
想看状态?加个 a 就行,a 就是 all
3. 看看到底是哪个进程在用端口(替代 netstat -tulnp)
关键在 -p,它能告诉你哪个进程 PID 占着端口:
ss -tulnp
tcp LISTEN 0 511 *:80 *:* users:(("nginx",pid=1,fd=1))
常用选项
-a:显示所有套接字。-n:不解析服务名称(即不转换服务端口号为服务名称)。-t:显示TCP套接字。-u:显示UDP套接字。-r:显示路由套接字。-l:显示监听状态的套接接字。-x:显示更多信息,包括UNIX域套接字。-i:显示更多信息,包括接口信息。-o:显示更多信息,包括定时器信息。
ss 厉害的地方
netstat 想按连接状态过滤?得靠 grep,又慢又不准。
ss 原生支持状态过滤:
# 看看有多少连接已经建好了
ss -o state established
# 查查 TIME-WAIT 有没有泛滥
ss -o state time-wait
# 找找谁还在 FIN-WAIT-1
ss -o state fin-wait-1
结合端口一起查:
# 查 80 和 443 端口的已建立连接
ss -o state established '( dport = :http or dport = :https )'
按 IP 和端口范围过滤
有时候你只想看某个 IP 的连接,ss 也能轻松搞定:
# 来自 192.168.1.100 的所有连接
ss dst 192.168.1.100
# 目标端口大于 1024 的 UDP 连接
ss -u dport \> :1024
# 来自 10.0.0 网段的 TCP 连接
ss -t dst 10.0.0.0/24
看整体网络情况:
想快速了解服务器网络负载?来一发:ss -s
Total: 445644
TCP: 814 (estab 771, closed 16, orphaned 0, timewait 14)
Transport Total IP IPv6
RAW 3 2 1
UDP 8 6 2
TCP 798 639 159
INET 809 647 162
FRAG 0 0 0
别再让 netstat 浪费你的时间
我知道,习惯最难改。我也是从 netstat 一路过来的。但当你在深夜排查线上问题,netstat 卡在那里转圈时,你会后悔没早点换 ss。
ss 不是未来,它已经是现在。
小提醒:大多数 Linux 发行版都自带
ss(属于iproute2包)如果真没有,CentOS 下
yum install iproute,Ubuntu 下apt install iproute2就行。工具会老,人也会老,但解决问题的效率,永远值得追求。