运维知识
悠悠
2026年7月22日

90% 运维只会 top+free:真正救命的是这 20 个工具(建议收藏)

为什么光会 strace 远远不够

先说个大实话。很多刚入行的兄弟一提排查就上 strace,觉得这玩意儿万能。

strace 确实好用,追系统调用和信号一把好手。可它有个致命毛病——性能开销太大了。你在一个每秒几万请求的高并发服务上直接 strace,好家伙,进程直接被你拖慢好几倍,本来没崩的可能被你 strace 崩了。我早年就干过这种蠢事,线上抓 strace 把一个本来只是慢的服务直接搞到超时雪崩,被组长在群里点名,社死现场。

而且 strace 只能看系统调用。程序卡在用户态的库函数里、卡在锁上、卡在某个死循环里,strace 是看不出来的,它只会显示进程一直卡在某个 read 或者 futex 上,然后你就懵了。

排查故障的核心逻辑就一句话:先定位是哪一类资源出了问题,再用对应的专项工具往下钻。 别一上来就闷头抓包、闷头 strace,那是没头苍蝇。

下面我按场景拆开讲。

追踪剖析类:strace 的那些「兄弟」

ltrace —— 看库函数调用

strace 追内核调用,ltrace 追用户态的动态库函数,俩是互补的。

比如你怀疑程序疯狂 malloc 内存、或者在某个字符串处理函数里死循环,strace 是看不见的,这时候 ltrace 就派上用场了:

ltrace -p 12345          # attach 到进程
ltrace -c ./your_app     # 统计各库函数调用次数和耗时

那个 -c 参数特别有用,能给你统计出哪个库函数被调用了几十万次、占了多少时间,一眼就能看出程序在哪儿磨蹭。

不过说句实话,ltrace 在生产上我用得也少,开销跟 strace 半斤八两,一般是测试环境或者能接受短暂影响的时候才上。

eBPF 全家桶(bpftrace / bcc-tools)—— 生产环境的救命稻草

重点来了,这个我要多说两句。

前面提到我凌晨那次故障,最后就是靠 eBPF 里的工具定位的。eBPF 这东西现在是真香,基于内核的 BPF 虚拟机跑,性能损耗极低,低到你可以在生产高并发环境直接开,几乎感觉不到影响。

bcc-tools 里一堆现成脚本,拿来就用:

execsnoop        # 实时追踪谁在启动新进程,排查异常启动、定时任务乱跑神器
opensnoop        # 追踪谁在打开哪些文件
ext4slower 10    # 揪出超过 10ms 的慢磁盘 I/O,直接告诉你哪个进程哪个文件慢
biolatency       # 磁盘 I/O 延迟直方图
tcpconnect       # 追踪 TCP 主动连接

image-20260722231850939

我那次就是用 ext4slower 发现某个进程在疯狂读一个小文件,一秒好几万次,磁盘 await 被它顶爆了。后来查出来是代码里配置读取没做缓存,每个请求都去磁盘捞一次配置文件。

bpftrace 更灵活,能写单行脚本自定义追踪,比如统计某个系统调用的分布:

bpftrace -e 'tracepoint:syscalls:sys_enter_read { @[comm] = count(); }'

这行意思是统计各进程调用 read 的次数,跑几秒 Ctrl+C,直接给你排好序。学会 bpftrace,很多以前要写复杂脚本才能干的事,一行搞定。

安装嘛,yum install bcc-tools 或者 apt install bpfcc-tools,脚本一般在 /usr/share/bcc/tools/ 下面。内核版本得 4.9 以上,太老的内核用不了,这是唯一的门槛。

perf —— CPU 热点分析的标准答案

CPU 飙高但你不知道飙在哪个函数上,perf 就是干这个的。

perf top                       # 实时看当前占 CPU 最多的函数
perf record -F 99 -p 12345 -g -- sleep 30   # 采样 30 秒
perf report                    # 看结果

perf 最强的搭配是火焰图(FlameGraph)。把采样数据生成火焰图,一张图上哪个函数占 CPU 一目了然,越宽的越占。我强烈建议每个运维都把火焰图这套流程练熟,定位 CPU 问题效率翻好几倍:

perf record -F 99 -p 12345 -g -- sleep 30
perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > cpu.svg

生成的 svg 用浏览器打开,能交互,点哪块放大哪块。

gdb —— 程序卡死了就靠它

服务卡死、疑似死锁,进程还在但就是不响应,这时候 gdb attach 上去看堆栈:

gdb -p 12345
(gdb) bt          # 看当前调用栈
(gdb) thread apply all bt   # 看所有线程的栈

thread apply all bt 这个命令排查死锁贼好用,能把所有线程卡在哪儿全打出来,你一眼就能看到两个线程互相等对方的锁。

不过 gdb attach 会短暂暂停进程,生产上慎用,最好在能接受短暂卡顿的时候操作。

系统资源全景:先搞清楚是谁在闹

排查第一步,永远是先定性——到底是 CPU 满了、内存爆了、还是 I/O 堵了。别急着钻细节。

htop / glances / dstat

top 那界面看着累,我平时都用 htop,彩色的、能鼠标操作、能看每个核的负载。glances 更全,CPU 内存磁盘网络进程一屏全给你。

dstat 我个人最爱,因为它能把好几类指标横着排一行滚动输出,特别适合观察趋势:

dstat -tcmndy 1
# 时间 CPU 内存 网络 磁盘 系统状态,一秒刷一次

image-20260722232915455

vmstat —— 上下文切换和 swap 的照妖镜

vmstat 我几乎每次排查都要跑一下,因为它能看到几个 top 看不到的关键指标:

vmstat 1

image-20260722232951307

重点盯这几列:

  • cs:上下文切换次数。这个如果异常高,可能是线程太多、锁竞争激烈
  • in:中断数,网络流量大或者硬件问题会飙
  • si / so:swap 换入换出。这俩只要不是 0,你的内存基本就出问题了,机器慢得像卡了

我碰到过一次机器莫名其妙巨慢,CPU 内存看着都正常,最后 vmstat 一看 si/so 一直在跳,原来是某进程内存泄漏把物理内存吃光开始用 swap 了,一用 swap 性能直接崩盘。

pidstat —— 精确到进程和线程

前面工具告诉你「系统级」哪块有问题,pidstat 帮你锁定「具体哪个进程」:

pidstat 1              # 各进程 CPU
pidstat -d 1           # 各进程磁盘 I/O,谁在刷盘一目了然
pidstat -r 1           # 各进程内存
pidstat -t -p 12345 1  # 细化到线程级别

那个 pidstat -d 1 我用得最多,磁盘 I/O 高的时候直接告诉你是哪个进程在读写,比翻半天日志快多了。

image-20260722233159990

image-20260722233235888

磁盘 I/O:慢和满是两回事

iostat —— 磁盘忙不忙

iostat -x 1

两个指标必看:

  • %util:磁盘繁忙程度,接近 100% 说明磁盘快到极限了
  • await:I/O 平均响应时间,这个飙高说明磁盘扛不住了

不过提醒一句,现在很多 SSD 和 NVMe 盘,%util 到 100% 也不一定是瓶颈,因为它们能并发处理多个 I/O,这个指标在新硬件上要结合 await 一起看,别被单一指标骗了。

iotop —— 谁在疯狂读写

跟 top 一样的操作逻辑,按 I/O 排序:

iotop -oP

-o 只显示真正有 I/O 的进程,-P 按进程显示。找刷盘元凶就靠它。

lsof —— 「磁盘满了但找不到大文件」的经典解法

这个场景我敢说八成运维都遇到过:df -h 显示磁盘满了,du 一顿找却找不到大文件,急得跳脚。

原因十有八九是——有进程在写一个大文件,然后这个文件被删了,但进程句柄还占着,空间没释放。这种「幽灵文件」du 看不到,得用 lsof:

lsof | grep deleted

找到那个 deleted 但还占着空间的文件,对应的进程 kill 掉或者重启,空间瞬间回来。我第一次遇到这问题查了俩小时,知道这招之后再也没被难住过。

lsof 还能查端口占用、查进程打开了哪些文件:

lsof -i :8080          # 谁占了 8080 端口
lsof -p 12345          # 进程打开了哪些文件

fuser —— 强制解除占用

想卸载某个目录结果提示 device is busy,就是有进程还占着:

fuser -m /data         # 谁在用这个挂载点
fuser -k /data         # 直接把占用的进程干掉

四、网络排查:从连接到抓包

ss —— 别再用 netstat 了

真心建议把 netstat 忘了,用 ss。ss 直接读内核,netstat 是遍历 /proc,连接数一多 netstat 慢得要死,ss 快好几个数量级。

ss -s                  # TCP 连接状态统计总览
ss -tan | awk '{print $1}' | sort | uniq -c   # 统计各状态连接数
ss -tnp state time-wait   # 看 TIME_WAIT 连接

重点关注两个状态:

  • TIME_WAIT 过多:通常是短连接太多,可以调内核参数优化
  • CLOSE_WAIT 过多:这个更危险,一般是程序 bug,连接没正常关闭,会把文件句柄耗尽。看到 CLOSE_WAIT 堆积赶紧查代码

tcpdump —— 抓包大杀器

网络层面的疑难杂症,最终都得靠抓包说话。tcpdump 负责在服务器上抓,抓完丢给 Wireshark 可视化分析:

tcpdump -i eth0 host 10.0.0.1 and port 8080 -w capture.pcap

抓包记得加过滤条件,不然一秒能抓几个 G,硬盘扛不住。抓完把 pcap 文件下载到本地用 Wireshark 打开,追踪 TCP 流、看握手挥手、看重传,问题基本无所遁形。

nethogs —— 哪个进程在偷跑流量

带宽被打满,想知道是哪个进程干的:

nethogs eth0

按进程显示实时带宽占用,一目了然,抓「偷跑流量」的进程神器。

ip / tc —— 配置查看和故障模拟

ifconfig 也建议退休了,现在都用 iproute2 里的 ip 命令:

ip a               # 看网卡地址
ip r               # 看路由

tc 更高级,能模拟网络延迟丢包,测试系统在弱网下的表现:

tc qdisc add dev eth0 root netem delay 100ms loss 5%

这条命令给网卡加 100ms 延迟和 5% 丢包,测完记得删掉,别忘了,不然自己坑自己。

curl / nc / telnet —— 连通性快速验证

排查连通性,这三个够用了:

curl -v http://xxx        # 看 HTTP 响应头和完整过程
nc -zv 10.0.0.1 8080      # 测端口通不通
telnet 10.0.0.1 8080      # 老办法测端口

curl -v 我用得最勤,加个 -w 还能看各阶段耗时,判断是 DNS 慢、连接慢还是响应慢。

五、内核和底层:日志里藏着真相

dmesg / journalctl -k —— OOM 和硬件报错第一现场

服务莫名其妙被杀了、进程凭空消失了,第一件事就是看内核日志:

dmesg -T | tail -50           # -T 显示可读时间
journalctl -k --since "10 min ago"

最常见的就是 OOM Killer。内存不够了,内核会挑一个进程杀掉腾内存,被杀的往往是占内存最多的那个,也就是你的核心服务。dmesg 里会明明白白写着「Out of memory: Killed process xxx」。

我见过太多人服务被 OOM 杀了还一脸懵,到处找日志找不到,其实答案就在 dmesg 里躺着。除了 OOM,网卡 Link Down、磁盘变只读、硬件报错,全在这儿能看到。

numactl / numastat —— NUMA 架构的坑

这个偏冷门,但在多路服务器上很关键。NUMA 架构下 CPU 访问本地内存快、访问其他节点内存慢,如果内存分配不均,会出现 CPU 不忙但性能就是上不去的诡异情况:

numastat              # 看各 NUMA 节点内存分配
numactl --hardware    # 看 NUMA 拓扑

数据库这类内存敏感的服务,跑在多路机器上时特别要注意 NUMA 绑定,不然性能可能白白损失一大截。

一份排查避坑清单

踩过的坑总结成几条,你直接记住:

  • 别在高并发生产环境无脑上 strace / ltrace,开销太大能把服务拖崩,优先用 eBPF
  • 别只看 CPU 使用率,vmstat 的上下文切换、swap 换页同样致命
  • 磁盘满找不到文件,先 lsof | grep deleted,别傻乎乎地 du 半天
  • %util 100% 别急着下结论,SSD/NVMe 上要结合 await 判断
  • CLOSE_WAIT 堆积一定是程序 bug,别指望调内核参数解决
  • tcpdump 抓包务必加过滤条件,不然硬盘分分钟被打满
  • tc 模拟故障测完记得删规则,别把自己坑了
  • 服务被杀先看 dmesg,八成是 OOM

写在最后

排查故障说到底,拼的不是你会背多少命令,而是你脑子里有没有一套「分场景往下钻」的思路。CPU 有问题就 perf、火焰图;I/O 有问题就 iostat、iotop、lsof;网络有问题就 ss、tcpdump;服务莫名死了先看 dmesg。工具是死的,思路是活的。

我把这些工具按场景整理成了一张速查表和一份火焰图部署脚本,需要的兄弟在公众号后台回复 「排查工具」 就能领。以后再遇到线上故障,对着表挨个排,比抓瞎强一百倍。

下一期我打算专门讲讲 eBPF 实战,从零搭一套生产可用的动态追踪体系,感兴趣的记得追更。

觉得有用的话,点个赞、转发到你们运维群里,说不定哪天就帮兄弟们少熬一个通宵。有你自己压箱底的排查神器,也欢迎评论区甩出来,咱们互相学习。


公众号:耕云躬行录
个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码