《Linux 故障排查工具箱:从 strace 到火焰图》

系统梳理 Linux 故障排查工具链:排障方法论与 USE 模型、strace/ltrace 系统调用与库调用追踪、perf 性能分析与采样、sysdig 与 bpftrace 动态追踪、lsof/fuser 资源占用排查、tcpdump 抓包分析、sar 历史数据回看、火焰图生成,以及 CPU、内存、IO、网络四类问题的标准排查路径。

引言

线上告警响起时,最怕的不是问题复杂,而是手里没有工具、脑中没有路径:CPU 飙高却不知谁在烧、内存泄漏却找不到持有者、磁盘 IO 打满却分不清是应用还是内核。Linux 提供了一整套观测工具,从最底层的 strace 到可视化的火焰图,每一种都对应一类问题。

本文按「方法论 → 工具逐个精讲 → 四类问题排查路径」组织:先建立 USE 模型与「先看全局再看局部」的思路,再依次介绍 strace/ltrace、perf、sysdig/bpftrace、lsof/fuser、tcpdump、sar 与火焰图,最后给出 CPU、内存、IO、网络四类问题的标准排查流程图与命令清单。

前置:Linux 性能监控与调优。进程与调度见 进程管理与 CPU 调度,内存机制见 内存管理与 OOM,eBPF 深入见 eBPF 与可观测性。


目录


1. 排障方法论:从现象到根因

排障的核心是「缩小范围」:先用宏观指标定位资源维度,再用微观工具定位具体进程,最后用追踪工具定位代码路径。

现象(慢/卡/报错)
   ↓
宏观指标:top / vmstat / iostat / sar —— 是哪一类资源?
   ↓
定位进程:pidstat / lsof / ss —— 是哪个进程/连接?
   ↓
深入追踪:strace / perf / bpftrace —— 卡在哪一步?
   ↓
根因(配置/代码/硬件/容量)

USE 模型(Brendan Gregg 提出)是快速体检的框架——对每种资源检查使用率(Utilization)、饱和度(Saturation)、错误(Errors):

资源使用率饱和度错误
CPUtop、mpstatvmstat 的 r 列、runqlatdmesg MCE
内存free、vmstatswap 使用、OOMdmesg OOM
磁盘iostat -x 的 %utilawait、aqu-szdmesg IO error
网络sar -n DEV丢包、重传ss -s、netstat -s
# 一分钟体检
uptime                 # 负载
vmstat 1 5             # CPU/内存/IO 概览
iostat -xz 1 5         # 磁盘
sar -n DEV 1 5         # 网络
top -bn1 | head -20    # 进程

一句话:先「哪一类资源」,再「哪个进程」,最后「哪一行代码」——顺序颠倒会让你在错误的层级浪费大量时间。


2. strace 与 ltrace:系统调用与库调用追踪

strace 追踪「程序与内核的对话」,ltrace 追踪「程序与动态库的对话」——服务卡住或报奇怪错误时,它们能看到程序到底在等什么。

# 基本用法
strace ls                              # 追踪整个程序
strace -p 1234                         # 追踪运行中的进程
strace -f -p 1234                      # 追踪所有子进程/线程
strace -e trace=open,read,write ls     # 只追踪指定系统调用
strace -e trace=network -p 1234        # 只追踪网络相关
strace -T -tt -p 1234                  # 显示耗时与时间戳
strace -c ls                           # 统计各类调用次数与耗时
strace -o out.txt -p 1234              # 输出到文件
strace -s 256 -p 1234                  # 字符串最大显示长度
选项作用
-p PID附加到进程
-f跟随子进程/线程
-e trace=过滤系统调用类别
-T显示每个调用耗时
-c汇总统计
-s N字符串截断长度
-y显示文件描述符对应的路径
# 典型场景:服务卡住,看它在等什么
strace -f -T -tt -p $(pidof nginx) 2>&1 | grep -E '<[0-9.]+>' | sort -t'<' -k2 -rn | head
# 典型场景:找不到文件
strace -e trace=openat,stat -f ./app 2>&1 | grep -i 'ENOENT'
# 典型场景:库函数调用(ltrace)
ltrace -p 1234

注意开销:strace 会显著拖慢目标进程(尤其在 -f 下),生产环境慎用,且务必限定时间:

timeout 5 strace -f -p 1234 -o /tmp/trace.txt

一句话:「卡在哪」用 strace -T 找耗时最长的调用,「为什么失败」用 strace -e trace=... 找返回 -1 的调用——ENOENT、EACCES、ECONNREFUSED 往往就是根因。


3. perf:CPU 性能分析

perf 是内核自带的性能分析器,采样调用栈、统计硬件事件,是定位「CPU 被谁吃掉」的首选。

# 顶层视图:实时看热点函数
perf top
# 记录采样
perf record -F 99 -a -g -- sleep 30      # 全系统采样 30 秒
perf record -F 99 -p 1234 -g -- sleep 30 # 只采样某进程
# 查看报告
perf report
# 统计事件
perf stat -p 1234 sleep 5
perf stat -e cycles,instructions,cache-misses,context-switches -a sleep 5
子命令作用
perf top实时热点
perf record/report采样与离线分析
perf stat事件计数统计
perf sched调度延迟分析
perf script导出原始样本(供火焰图)
# 关键事件:判断 CPU 瓶颈类型
perf stat -a sleep 5
# 关注:IPC(instructions per cycle)< 1 说明受限于访存/分支
# cache-misses 高 → 内存访问瓶颈
# context-switches 高 → 锁竞争或调度频繁
# 查看调度延迟(runqlat 的 perf 版)
perf sched record -- sleep 5
perf sched latency

一句话:perf record -F 99 -g + perf report 是 CPU 分析的黄金组合——99Hz 采样、带调用栈,跑 30 秒就能看清热点函数及其调用来源。


4. bpftrace 与 sysdig:动态追踪

bpftrace 用一行脚本挂到任意内核/用户态函数上,sysdig 提供「类 tcpdump 的系统调用流」——两者都是低开销的生产级追踪工具。

# bpftrace:谁在打开文件
bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }'
# bpftrace:CPU 采样 + 内核栈
bpftrace -e 'profile:hz:99 { @[comm, kstack] = count(); }'
# bpftrace:统计各进程的系统调用次数
bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[comm] = count(); }'
# bpftrace:追踪慢 IO
bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; }
  kretprobe:vfs_read /@start[tid]/ {
    @us = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); }'
# sysdig:抓系统调用流
sysdig                                  # 实时流
sysdig -c topprocs_cpu                  # CPU 占用 Top
sysdig -c topfiles_bytes                # 文件读写 Top
sysdig -c topscalls_time                # 最慢的系统调用
sysdig proc.name=nginx and evt.type=open   # 过滤
sysdig -w trace.scap                    # 保存供离线分析
sysdig -r trace.scap -c topconns        # 离线:连接 Top
工具模型开销适用
strace系统调用追踪高单进程短时排障
perf采样 + 事件低CPU/调度分析
bpftraceeBPF 动态插桩低生产级自定义追踪
sysdig系统调用流中容器与主机全景

一句话:strace 是「一次性手术刀」,bpftrace 是「可编程的探针」——需要长期、低开销、自定义的观测时,优先 bpftrace 而不是 strace。


5. lsof 与 fuser:谁占用了资源

「端口被占用」「文件系统无法卸载」「磁盘空间没释放」——这些问题的答案都在 lsof 和 fuser 里。

# 谁占用了某端口
lsof -i :8080
ss -lntp | grep :8080
# 某进程打开了哪些文件
lsof -p 1234
# 谁在使用某目录(卸载失败时)
lsof +D /mnt/data
fuser -m /mnt/data
# 谁打开了某文件
lsof /var/log/app.log
# 查看已删除但仍被占用的文件(磁盘不释放的经典原因)
lsof | grep deleted
需求命令
端口占用lsof -i :PORT / ss -lntp
进程打开的文件lsof -p PID
目录被谁用lsof +D DIR / fuser -m DIR
文件被谁用fuser FILE
网络连接lsof -i / ss -tanp
# 经典问题:删了大文件但磁盘没释放
lsof | grep deleted
# 处理:重启持有该 fd 的进程,或
: > /proc/1234/fd/5      # 截断(谨慎)
# 经典问题:卸载失败
fuser -km /mnt/data      # 杀掉占用进程(危险)
umount /mnt/data

一句话:「磁盘满了却找不到大文件」十有八九是 lsof | grep deleted——文件被删除但进程仍持有文件描述符,空间要到进程关闭 fd 才真正释放。


6. tcpdump:网络抓包分析

网络问题的最终手段是抓包:连接不上看三次握手,速度慢看重传与窗口,数据错乱看载荷。

# 抓指定网卡、指定端口
tcpdump -i eth0 -nn port 80
# 抓指定主机
tcpdump -i any -nn host 10.0.0.5
# 抓 TCP 握手/挥手(只看标志位)
tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'
# 写文件供 Wireshark 分析
tcpdump -i eth0 -nn -s 0 -w /tmp/cap.pcap
# 限制数量与文件大小
tcpdump -i eth0 -c 1000 -W 5 -C 10 -w /tmp/cap.pcap
# 显示 ASCII 载荷(调试 HTTP)
tcpdump -i eth0 -nn -A port 80
选项作用
-i IFACE指定网卡(any 为全部)
-nn不做 DNS/端口名解析
-s 0抓完整包(不截断)
-w FILE写入 pcap
-A / -XASCII / hex+ASCII 显示
-C N -W M按 MB 轮转,保留 M 个文件
# 排障:看有没有 SYN 无 ACK(服务未监听或防火墙丢包)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'
# 排障:看重传(网络质量差)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'
# 配合 ss 看连接状态
ss -s
ss -tan state time-wait | wc -l

一句话:抓包前先想清楚「过滤条件」——host/port/tcpflags 组合能把 GB 级流量缩到几行;不加过滤地 tcpdump 在生产上是自找麻烦。


7. sar 与系统历史数据

「昨天这个点也卡吗?」——sar 记录了历史性能数据,是复盘与容量规划的依据。

# 安装与启用(sysstat)
apt install sysstat
systemctl enable --now sysstat
# CPU 历史
sar -u
# 内存历史
sar -r
# 磁盘 IO 历史
sar -b
# 网络历史
sar -n DEV
# 指定日期与时间范围
sar -u -f /var/log/sysstat/sa15 -s 09:00:00 -e 10:00:00
# 每秒采样,共 5 次(实时)
sar -u 1 5
选项监控对象
-uCPU 使用率
-r内存与 swap
-bIO 与传输速率
-n DEV网络接口
-n TCPTCP 连接统计
-q负载与队列
# 关键配置:/etc/sysstat/sysstat
# HISTORY=30       保留 30 天
# COMPRESSAFTER=10 10 天后压缩
# 数据目录
ls /var/log/sysstat/
# 定时采集由 cron/systemd timer 驱动
systemctl list-timers | grep sysstat

一句话:「事后复盘」只有 sar 能回答——top/iostat 只反映当下,sar 保存了历史,是排查「间歇性故障」和做容量趋势分析的唯一依据。


8. 火焰图:可视化的性能分析

火焰图把成千上万条采样栈折叠成一张图:横轴是占比、纵轴是调用深度——一眼看出「谁最宽就是谁最耗时」。

# 1. 用 perf 采样(带调用栈)
perf record -F 99 -a -g -- sleep 30
# 2. 导出折叠栈
perf script > out.perf
# 3. 用 FlameGraph 工具生成
git clone https://github.com/brendangregg/FlameGraph
cd FlameGraph
./stackcollapse-perf.pl out.perf > out.folded
./flamegraph.pl out.folded > flame.svg
# 或用 perf 内置
perf script report flamegraph

火焰图的读法:

特征含义
横轴宽该函数在采样中出现的比例(越宽越耗时)
纵轴深调用栈深度
顶部尖峰叶子函数(真正在干活的)
颜色随机,无语义(便于区分相邻帧)
# 生成 off-CPU 火焰图(分析阻塞/等待)
# 需要 bcc 的 offcputime
offcputime -df -p 1234 30 > offcpu.folded
./flamegraph.pl --color=io --title="Off-CPU" offcpu.folded > offcpu.svg
类型回答的问题工具
on-CPUCPU 花在哪perf + FlameGraph
off-CPU为什么在等(阻塞)offcputime
差异图两次采样哪里变了flamegraph.pl –diff

一句话:on-CPU 火焰图看「谁在烧 CPU」,off-CPU 火焰图看「谁在等」——两者结合才能完整解释「慢」:CPU 不高却慢,答案往往在 off-CPU 图里。


9. CPU/内存/IO/网络四类排查路径

把工具串成「路径」:每类问题都有一条从宏观到微观的固定排查顺序,照着走就不会漏。

CPU 高:

uptime                       # 1. 负载 vs CPU 核数
top -H -p $(pidof app)       # 2. 哪个线程
perf top                     # 3. 哪个函数
perf record -F 99 -p PID -g -- sleep 30; perf report   # 4. 调用栈

内存问题:

free -h                      # 1. 总量与 swap
vmstat 1                     # 2. si/so 换页
ps aux --sort=-%mem | head   # 3. 谁占内存
pmap -x PID | tail           # 4. 进程内存映射
dmesg | grep -i oom          # 5. 是否 OOM

IO 问题:

iostat -xz 1                 # 1. 设备 %util / await
pidstat -d 1                 # 2. 哪个进程在读写在
iotop -o                     # 3. 实时 IO 排行
biolatency                   # 4. IO 延迟分布(eBPF)

网络问题:

ss -s                        # 1. 连接状态汇总
ss -tanp | head              # 2. 谁连了谁
sar -n DEV 1                 # 3. 网卡吞吐与丢包
ss -ti                       # 4. TCP 重传/窗口细节
tcpdump -i eth0 -nn host X   # 5. 抓包定位
维度第一步(宏观)第二步(定位)第三步(深入)
CPUuptime / toptop -H / pidstatperf / 火焰图
内存free / vmstatps --sort=-%mempmap / memleak
IOiostat -xzpidstat -d / iotopbiolatency
网络ss -s / sar -n DEVss -tanp / ss -titcpdump

一句话:每条路径都是「宏观指标 → 定位进程 → 深入追踪」三步——记住这个骨架,任何一类问题都能在 5 分钟内锁定方向。


10. 速查表

需求命令
追踪系统调用strace -f -T -p PID
统计系统调用strace -c -p PID
追踪库调用ltrace -p PID
CPU 实时热点perf top
CPU 采样分析perf record -F 99 -g -a -- sleep 30
事件计数perf stat -a sleep 5
自定义追踪bpftrace -e '...'
系统调用流sysdig -c topprocs_cpu
端口占用lsof -i :8080 / ss -lntp
删除未释放文件lsof | grep deleted
目录被占用fuser -m /mnt
抓包tcpdump -i eth0 -nn port 80 -w cap.pcap
历史性能sar -u / sar -r / sar -b
火焰图perf script | stackcollapse-perf.pl | flamegraph.pl
OOM 检查dmesg | grep -i oom

一句话记忆:排障三步走「宏观指标 → 定位进程 → 深入追踪」;CPU 用 perf、内存用 pmap、IO 用 iostat+pidstat、网络用 ss+tcpdump;卡在哪用 strace -T,谁在等用 off-CPU 火焰图。


延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「linux」更多文章

  1. 《磁盘加密与 LUKS 密钥管理实战》
  2. 《文本处理三剑客:grep、sed、awk 与 jq 实战》
  3. 《Linux 时间同步:chrony、NTP 与高精度时间实践》