登录服务器,习惯性地敲了几个命令,发现系统负载才2.0,CPU空闲80%,带宽也没跑满。表面看起来一切正常。但当看到某个数字时,瞬间明白了问题所在:TIME_WAIT状态连接数超过了3万。这是一个典型的“连接耗尽”问题。TCP连接不是建立起来就完事了,它有11种状态,从SYN_SENT到ESTABLISHED再到TIME_WAIT,每一种状态都在告诉你系统正在经历什么。下面这五个命令,就是用来读懂这些“暗号”的工具。
一、 ss:现代Linux的首选,netstat的替代者
命令格式
ss [选项] [过滤条件]
为什么优先用ss?
很多老运维习惯了netstat,但在高并发服务器上,netstat有一个致命问题:当连接数达到几万甚至十几万时,它会慢到让你怀疑人生。
原因在于netstat需要遍历/proc文件系统,逐个读取socket信息,效率极低。而ss直接从内核的diag模块获取数据,速度是netstat的10到40倍。
实战用法
1. 查看所有TCP连接(带状态)
ss -t -a
# -t: TCP连接
# -a: 既有监听端口也有已建立的连接
2. 统计各状态连接数(最常用的组合)
ss -t -a | awk '{print $2}' | sort | uniq -c
输出示例:
15 CLOSE-WAIT
3245 ESTAB
2 FIN-WAIT-1
5 FIN-WAIT-2
127 LISTEN
12345 TIME-WAIT
3. 只看ESTABLISHED连接,并显示进程名
ss -t -p state established
# -p: 显示进程名和PID
# -p: 显示进程名和PID
这条命令在排查“哪个进程在疯狂建连”时极其有用。比如发现某个服务的连接数异常飙高,ss -t -p直接告诉你是哪个进程干的。
4. 查看连接队列溢出情况
ss -lnt
# -l: 监听端口
# -n: 不解析服务名,直接显示端口号
# -t: TCP
输出中的Send-Q和Recv-Q值得特别关注:
监听端口的Send-Q:表示全连接队列(accept队列)的大小
监听端口的Recv-Q:表示当前全连接队列中等待accept的连接数
如果Recv-Q一直大于0,说明你的应用来不及调用accept(),要么是程序处理太慢,要么是单线程accept成了瓶颈。
避坑提醒
ss命令在不同发行版中选项略有差异。建议使用ss -h确认一下当前版本支持的参数。
二、 netstat:老牌工具,诊断神器
虽然netstat速度不如ss,但我始终认为每个运维都应该掌握它。原因很简单:你永远不知道哪天会遇到一个没有安装iproute2套件的老系统。
命令格式
netstat [选项]
实战用法
1. 查看所有TCP连接(最常用)
netstat -tn
# -t: TCP
# -n: 显示数字IP和端口,不做域名解析
不加-n的后果是:它会试图把192.168.1.100:8080解析成域名,如果DNS配置有问题,这条命令能卡你十秒钟。
2. 查看连接对应的进程
netstat -tnp
# -p: 显示PID和进程名
这个组合在排查“哪个程序在占用某个端口”时是首选。
3. 定时监控连接变化
watch -n 1 'netstat -tn | grep 8080 | wc -l'
每秒检查一次8080端口上的连接数变化。
三、 lsof:列出打开的文件,包括socket
在Linux世界里,“一切皆文件”。socket也被当作文件来处理。lsof的精髓在于:它可以从文件描述符的角度看连接。
命令格式
lsof -i [协议]:[端口]
实战用法
1. 查看某个端口上的所有连接
lsof -i :8080
输出会显示哪个进程监听了8080,以及有哪些客户端连接到了这个端口。
2. 查看某个IP的连接
lsof -i @192.168.1.100
3. 查看某个用户的连接
lsof -i -u nobody
# 查看nobody用户打开的所有网络连接
场景:为什么端口被占用了?
启动某个服务时,报错“Address already in use”。这时候lsof比netstat更好用:
lsof -i :8888
直接告诉你PID 12345的java进程占用了这个端口。想进一步看这个进程在干什么,可以配合strace:
strace -p 12345
lsof的独特优势
netstat和ss看到的是“连接”本身,而lsof看到的是“哪个进程持有这个连接”。当你需要从进程维度反过来追溯时,lsof是唯一的选择。
四、 tcpdump:抓包分析,终极手段
前面的命令看的是系统层面的连接状态。但有时候,你觉得连接状态正常,业务就是不对。这时候就需要抓包看实际报文了。
命令格式
tcpdump [选项] [过滤表达式]
实战用法
1. 抓取特定端口的TCP包
tcpdump -i eth0 port 8080 -n
2. 抓取特定IP的包并保存到文件
tcpdump -i eth0 host 192.168.1.100 -w capture.pcap
3. 抓取TCP三次握手过程
tcpdump -i eth0 port 8080 -n -S | grep -E 'Flags \[S\]|Flags \[S.\]
Flags [S]表示SYN包,[S.]表示SYN-ACK包。通过观察这三步是否完成,可以判断连接建立是否正常。
五、 /proc/net/tcp:直接读内核,终极底层
前面几个命令都是从用户态获取信息。如果你在排查问题的路上发现ss和netstat都失效了(比如系统负载极高,命令执行卡死),那最后的手段就是直接去读内核暴露的接口。
直接查看
cat /proc/net/tcp
这个文件的内容看起来是一堆十六进制数字,需要解码。每一列对应一个TCP连接的信息,包括本地地址、远端地址、状态、发送队列、接收队列等。
什么时候用这个?
当服务器遭到DDoS攻击,系统负载达到几百甚至上千时,ss和netstat可能因为CPU被占满而无法执行。但/proc是内核直接暴露的虚拟文件系统,哪怕系统再卡,cat /proc/net/tcp大概率还是能执行的。
这个文件里的信息虽然原始,但它是系统能给你的最后一份遗嘱,记录了崩溃前那一刻的连接状态。
总结:这五个命令,每个命令都有它的适用场景,没有哪个是“最好”的,只有“最合适”的。
记住:工具的意义不在于你会敲多少命令,而在于你敲完命令后,能不能看懂系统在告诉你什么。
推荐文章
