ss —— socket statistics(替代 netstat)
一句话定义
ss 是现代化的 netstat 替代品,用来看本机的网络套接字(socket):谁在监听哪个端口、谁连到了谁、连接状态是什么。比 netstat 快几个数量级(直接读内核 netlink 而不是 /proc)。
典型场景
- 装机后:
ss -lntp看监听端口,确认只有 sshd 在监听(22)+ systemd-resolved(53),没有意料之外的服务 - 排查"端口被占用":
ss -lntp | grep :8080找谁占着 8080 - 看 K8s 节点和 control plane 的连接:
ss -tnp | grep 6443 - 看 kube-proxy 创建的连接:
ss -tn | head -100
netstat 在 Ubuntu 22 / RHEL 8+ 默认已经不预装。先学 ss、忘了 netstat 也没事。
5 个核心 flag(90% 够用)
ss -lntp # 看 TCP 监听
ss -tn # 看所有 TCP 连接(含已建立的)
ss -tunap # TCP + UDP,全部,所有状态,含进程
ss -s # 概览统计
ss -t state established # 按状态过滤
| flag | 含义 | 备注 |
|---|---|---|
-l | listening 只看监听 | 不加 -l 会列已建立的连接 |
-n | numeric 不解析名字 | 关键:不加这个会做 DNS 反解,慢且会卡住 |
-t | TCP | |
-u | UDP | |
-p | process 显示哪个进程占用 | 需要 root(看别人进程要 root) |
-a | all 含 listening + established | |
-4 / -6 | 只 IPv4 / 只 IPv6 | |
-s | summary 概览统计 |
"必加 -n" —— 不加的话 ss 会反向解析 IP 和端口号成主机名/服务名,慢、可能卡住、且对运维没用。养成 ss -lntp 这个肌肉记忆,不要 ss -ltp。
看监听端口(最常用)
$ ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=890,fd=14))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1234,fd=4))
读法:
LISTEN—— 这个 socket 在监听Local Address:Port—— 监听在哪0.0.0.0:22—— 所有 IPv4 地址的 22 端口127.0.0.1:9100—— 只监听本机[::]:22—— 所有 IPv6 地址192.168.1.5:80—— 只监听这个具体 IP
Recv-Q/Send-Q—— 队列长度,对 LISTEN socket 是 backlog 上限Process—— 哪个进程在监听(需要 root 看完整)
装机健康检查
ss -lntp
# 干净的 Ubuntu 22 应该只看到:
# :22 sshd
# 127.0.0.53:53 systemd-resolve
# 如果还有别的(agent / xrdp / mysqld 等),先查清楚是什么再决定
Day0 §1 用这个命令排除 IDC 预装的乱七八糟的"agent"。
找谁占了某个端口
ss -lntp | grep :8080
ss -lntp '( sport = :8080 )' # 更精准的 ss 自身过滤语法
grep :8080 简单粗暴;但如果想精确(避免匹配到 :80800、:18080),用 ss 自带的过滤语法:
ss -lntp sport = :8080
注意 sport(source port)对应监听端口,对端连接的话用 dport。
看已建立的连接
ss -tn # 不加 -l,显示已建立 + 各种状态
ss -tn state established # 只看 ESTABLISHED
ss -tn state time-wait # 看 TIME_WAIT(防止连接耗尽用)
输出:
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 10.0.24.28:43210 10.0.24.29:6443
ESTAB 0 0 10.0.24.28:48772 10.0.24.30:2379
K8s 节点上 :6443 是 apiserver、:2379 是 etcd。可以快速看出节点都连到了哪些控制面组件。
TCP 状态速查
| 状态 | 含义 |
|---|---|
LISTEN | 监听中 |
ESTAB (ESTABLISHED) | 连接建立、数据可流 |
TIME-WAIT | 主动关闭方等待 2*MSL,避免连接错乱 |
CLOSE-WAIT | 对端发了 FIN、本端还没 close —— 数量大说明应用有 bug |
FIN-WAIT-1 / FIN-WAIT-2 | 关闭过程中 |
SYN-SENT | 等服务端响应 SYN-ACK |
SYN-RECV | 服务端收到 SYN 等 ACK |
CLOSE-WAIT 堆积是经典 bug 信号 —— 应用代码没正确关 socket。netstat -tn | grep CLOSE-WAIT | wc -l 数一下,几百以上要查。
进程视角:某进程开了哪些 socket
ss -tnp | grep "pid=1234," # 按 PID 找
ss -tnp | grep '"nginx"' # 按进程名找
或者结合 lsof:
lsof -nP -iTCP -p 1234
概览统计
$ ss -s
Total: 234
TCP: 45 (estab 12, closed 18, orphaned 0, timewait 12)
Transport Total IP IPv6
RAW 0 0 0
UDP 8 5 3
TCP 45 38 7
INET 53 43 10
FRAG 0 0 0
快速判断"是不是连接太多了"。一台正常工作的 K8s 节点 TCP 数百到几千是正常的。
ss 自带的强大过滤语法
netstat 时代靠 grep 拼,ss 内置了表达式:
ss -tn dst 10.0.24.0/24 # 目的地址在某网段
ss -tn dport = :6443 # 目的端口 6443
ss -tn '( sport = :22 )' # 源端口 22
ss -tn 'sport = :22 or dport = :22' # 复合条件
ss -tn 'src 10.0.24.28 and dport :2379' # 复合
不过 90% 场景用 grep 就够。表达式语法记不住就别强求。
看 unix socket(K8s 排错常用)
ss -x # unix sockets
ss -xa | grep docker
ss -xa | grep crio
K8s + containerd / docker 大量靠 unix socket 通信(/var/run/docker.sock、/run/containerd/containerd.sock、kubelet 的 socket)。排查"kubelet 连不上 containerd" 这种问题:
ss -xan | grep containerd
ls -l /run/containerd/containerd.sock
ss vs netstat 对应关系
如果你以前用 netstat 的肌肉记忆:
| netstat | ss |
|---|---|
netstat -tnlp | ss -tnlp |
netstat -tnp | ss -tnp |
netstat -an | grep :80 | ss -an | grep :80 或 ss -an sport = :80 |
netstat -s | ss -s(但 ss 简单很多,看完整协议栈用 nstat -a) |
ss 还能做的(netstat 不能):
- 按地址段、端口范围过滤
-K干掉一个 socket(运维硬手段)
常见踩坑
坑 1:忘加 -n,ss 卡住
ss -ltp # 卡半天
不加 -n 会做 DNS 反解 / /etc/services 服务名解析。万一你的网络反向 DNS 慢、或者 /etc/services 巨大,ss 会卡。
永远加 -n。
坑 2:看不到进程名
ss -lntp
# Process 列是空的
非 root 跑的话只能看到自己进程的信息。sudo ss -lntp 或者 ssh root@... 'ss -lntp'。
坑 3:把"看监听"和"看连接"搞混
ss -lntp # 加 -l 只看 listening
ss -ntp # 不加 -l 看所有已建立连接
ss -lntp + ss -ntp 不会有重复 # listening 不是 established
混淆点:很多人记着 -a(all),但 -a 是"含 listening"的意思,不是默认行为。ss -tn 默认就是非 listening 的所有状态。
坑 4:端口看起来没人监听,但程序说被占用
ss -lntp | grep :8080 # 啥也没有
# 但 nc -lk 8080 报 Address already in use
可能:
- 监听在 IPv6 但你只查了 IPv4(去掉
-4、或加-6看看) - socket 在 TIME_WAIT,端口暂时占用(
SO_REUSEADDR一般能复用) - 监听的是 unix socket,不是 TCP(用
ss -x查)
坑 5:Recv-Q 持续涨
LISTEN 状态下 Recv-Q 是已建立但未被 accept 的连接数。如果持续大,说明应用 accept 不过来 —— 应用没启动、卡死、或者 accept 线程数不够。
ESTABLISHED 状态下 Recv-Q 是收到但应用没 read 的字节数;Send-Q 是要发但对端没 ACK 的字节数。两个都堆积 → 排查应用消费速度或网络丢包。
关联命令
lsof -i :8080—— 另一种"找占端口的进程",更详细但更慢netstat—— 老的等价物,可能没装nstat—— 协议栈级统计iftop—— 看哪些连接在跑流量tcpdump—— 抓包看具体内容- systemctl —— 停掉占端口的服务