工具卡

每张卡说一件事:这个工具能回答什么问题、看哪几列、什么样的数算不正常、装哪个包、要不要 root、嵌入式板子上用什么代替,以及书里在哪一节讲它。包名按 Debian/Ubuntu;BCC 工具在 Debian 上名字带 -bpfcc 后缀(runqlat-bpfcc)。卡片是本站写的,命令的完整选项看各自的 man 页。

全局统计

uptimeprocps

回答负载在涨还是在落。

看1、5、15 分钟三个负载平均的走向。Linux 上含等磁盘的任务,不能单独当 CPU 指标。直接读 /proc/loadavg 是同一组数。

ARM 板busybox 一般带 uptime;/proc/loadavg 总在。

§6.6.1

vmstatprocps

回答全系统 CPU 忙不忙、有没有在排队、有没有在换页。

看r(在跑加排队,长期大于核数是饱和)、b(不可中断睡眠)、si/so(换入换出,持续不为零就是在换页)、us/sy/id/wa/st。第一行是开机以来的平均,从第二行看。

ARM 板busybox 可能带 vmstat;没有就读 /proc/stat 和 /proc/vmstat。

§6.6.2 §7.5.1

mpstatsysstat

回答每个 CPU 各忙在哪:用户态、内核态、中断、等 IO、被偷走。

看mpstat -P ALL 1:单个核 %usr+%sys 接近 100% 而别的闲着,是单线程或中断集中;%soft、%irq 集中在某个核说明中断没摊开;%steal 是虚拟机被宿主拿走的时间。

ARM 板读 /proc/stat 每个 cpuN 行,隔一秒相减。

§6.6.3

sarsysstat

回答和 mpstat、iostat、网络统计一样的数,但能看历史(开了 sysstat 的定时采集之后)。

看sar -u、-q(运行队列和负载)、-r(内存)、-d(磁盘)、-n DEV/EDEV/TCP/ETCP(网络);sar -f 文件 回看某一天。

ARM 板sysstat 可以交叉编译;历史数据要定时任务和存储空间。

§4.4 §6.6.4 §10.6.6

dmesgutil-linux

回答内核刚才报了什么:OOM、硬件错误、降频、丢包、文件系统错误。

看dmesg -T | tail;搜 Out of memory、Killed process、I/O error。

ARM 板busybox 带 dmesg(没有 -T 时间换算)。

§1.10.1

/proc/pressure内核接口

回答任务因为等 CPU、内存、IO 而停顿了多少时间。

看cat /proc/pressure/cpu(还有 memory、io):some avg10 是最近 10 秒里至少一个任务在等的时间比例;full 是所有非空闲任务都在等的比例。

ARM 板内核要开 CONFIG_PSI(4.20 起)。

§6.6.1 §7.5.2 §9.6.3

sadfsysstat

回答把 sar 存下的历史数据导出成 CSV、JSON、SVG 图,方便画图或交给别的工具。

看sadf -d 文件 -- -u 导出 CPU 数据;-g 出 SVG。数据要先由 sysstat 的定时采集(或 sadc)写下来。

权限读数据文件不要 root。

ARM 板sysstat 交叉编译后可用。

§4.4

systemd-analyzesystemd

回答开机慢在哪个服务。

看systemd-analyze blame 按耗时排序;critical-chain 给出决定总时长的那条依赖链,先优化链上的。

权限看启动时间不用 root。

ARM 板不用 systemd 的 BSP 没有它;可以用内核的 initcall_debug 加 dmesg 时间戳看内核阶段。

§3.4.2

进程和线程

topprocps

回答现在谁最占 CPU、内存。

看按 1 看每个核,按 H 看线程。%CPU 在 Linux 上不除以核数,两个线程跑满是 200%。top 会漏掉短命的进程,自己的开销也不小。

ARM 板busybox top 字段较少。

§6.6.6

psprocps

回答进程和线程的状态、累计 CPU、内存。

看Linux 上 %CPU 是进程从启动到现在的平均,不是当前值;状态列 D 是不可中断睡眠。ps -eLo pid,tid,stat,comm 看线程。

ARM 板busybox ps 字段少,读 /proc/PID/status、/proc/PID/task/*/stat。

§6.6.5 §7.5.7

pidstatsysstat

回答每个进程、线程的 CPU、内存、IO、上下文切换,按秒滚动。

看pidstat 1:%usr/%system/%wait(等 CPU);-t 线程;-r 缺页和 RSS;-d 读写字节;-w 自愿和非自愿上下文切换。

ARM 板读 /proc/PID/stat、/proc/PID/io、/proc/PID/status 自己差分。

§6.6.7 §9.6.4

stracestrace

回答进程在做哪些系统调用、每个花了多久。

看strace -c -f -p PID 汇总;-T 显示每次调用的耗时。开销很大,会让被跟踪的程序明显变慢,生产上只短时间用;只用 -e 选几种调用也一样慢,因为每个系统调用都要停一次。strace 5.3 起有 --seccomp-bpf(要配 -f):只在选中的调用上停,选中的调用少时开销小得多,但只对 strace 自己启动的进程有效,-p 挂上去的用不上。本站在 WSL2 上实测:dd 小块拷贝只跟踪 openat,普通 strace 慢了三百多倍,加 --seccomp-bpf 后几乎不慢。

权限跟踪自己启动的程序不要 root。kernel.yama.ptrace_scope 为 1 时(本站 WSL2 就是 1),-p 挂已经在跑、又不是自己子进程的进程,哪怕是自己的进程,也要 root 或 CAP_SYS_PTRACE。

ARM 板strace 容易交叉编译,Buildroot、Yocto 里都有。

§5.5.4 §8.6.7

execsnoopbpfcc-tools

回答有哪些短命的进程在不停地被启动(top 看不到它们)。

看每一行一次 exec,带参数。频繁调用 shell 脚本、外部命令的服务常因此费 CPU。要 root。

ARM 板没有 BPF 时,可以用 ftrace 的 sched_process_exec 跟踪点。

§5.5.5

syscountbpfcc-tools

回答全系统或某个进程,哪些系统调用最多、各花了多少时间。开销比 strace 小得多。

看syscount-bpfcc;-P 按进程,-L 带上耗时。某个调用每秒几十万次(比如很小的 read、write),就是可以合并的信号。

权限要 root。

ARM 板没有现成替代;/proc/PID/io 的 syscr、syscw 能数读写类调用;能交叉编译 strace 时用 strace -c -p PID 挂几秒。

§5.5.6 §15.1.3

lsnsutil-linux

回答机器上有哪些命名空间、各有多少进程。

看看 TYPE、NPROCS;同一类型出现好几个 ID,说明有容器或被隔离的进程。

权限不用 root 只列自己的进程,看全部要 root。

ARM 板手工比对 ls -l /proc/*/ns/。

§11.3.1

nsenterutil-linux

回答在宿主上进入某个进程的命名空间,用宿主上的工具查容器。

看nsenter -t PID -n 进容器的网络栈跑 ss、tcpdump;-m -p 只看到容器的进程,但 top 头部的汇总仍是宿主的。

权限要 root。

ARM 板busybox 可能编进了 nsenter(看裁剪配置)。

§11.3.4

systemd-cgtopsystemd

回答按 cgroup(容器、服务)看谁在用 CPU、内存、IO。

看按 %CPU、Memory 排;某个容器的 %CPU 贴着它的限额(限 2 颗就是 200%)就是到顶了。

权限读自己能读的 cgroup 不用 root,看全部要 root。

ARM 板没有 systemd 时直接读 /sys/fs/cgroup 下各目录的 cpu.stat、memory.current。

§11.3.4

xentopXen 工具(包名随版本)

回答Xen 宿主上每个客户机的 CPU、内存、网络、块设备。

看CPU(%) 是几个 vCPU 加起来的;VBD_OO 不为零说明块设备请求在排队。

权限在 dom0 用 root 跑。

ARM 板无。

§11.2.4

CPU 剖析和调度

perflinux-perf(Ubuntu 上是 linux-tools-$(uname -r))

回答CPU 时间花在哪些函数上(采样剖析);周期、指令、缓存未命中有多少(计数);跟踪点和动态探针。

看perf record -F 99 -g -p PID -- sleep 30 再 perf report;perf stat 看 IPC。看到十六进制地址是缺符号,栈只有一两层是缺帧指针。

权限非 root 时受 kernel.perf_event_paranoid 限制,默认值因发行版和内核而异,有的发行版内核默认不许非特权用户用 perf。为 2 时只能剖析自己这个用户的进程(自己启动的,或者用 -p 挂上去的),基本只看用户态(本站 WSL2 实测)。

ARM 板从内核源码 tools/perf 交叉编译,或在 Buildroot、Yocto 里选上。

§6.6.13 §13.1

profilebpfcc-tools

回答和 perf record 一样的 CPU 剖析,但栈在内核里汇总,开销更低。

看profile-bpfcc -F 49 30;-f 输出折叠格式,能直接画火焰图。要 root。

§6.6.14 §5.5.2

runqlatbpfcc-tools

回答线程每次在运行队列里等了多久(调度延迟的分布)。

看runqlat-bpfcc 10 1 的直方图:毫秒级的桶里有数,多半是 CPU 不够或被限流。跟踪每次调度,繁忙的机器上开销可观。要 root。

§6.6.16

runqlenbpfcc-tools

回答运行队列有多长(采样)。比 runqlat 便宜。

看runqlen-bpfcc 10 1:长度为 0 的比例越高越好;-C 按 CPU 分开。要 root。

§6.6.17

softirqs / hardirqsbpfcc-tools

回答软中断、硬中断各花了多少 CPU 时间(剖析器常看不到这部分)。

看softirqs-bpfcc 10 1、hardirqs-bpfcc 10 1。要 root。不用 BPF 时,/proc/softirqs、/proc/interrupts 给出次数,mpstat 的 %soft、%irq 给出占比。

§6.6.18 §6.6.19

offcputimebpfcc-tools

回答线程不在 CPU 上的时候在等什么、等了多久(锁、IO、睡眠),带调用栈。

看offcputime-bpfcc -p PID 10;可以画成 off-CPU 火焰图。要 root,开销比 CPU 剖析大。

§5.5.3 §5.4.2

cpudistbpfcc-tools

回答线程每次上 CPU 连续跑了多久(分布)。

看cpudist-bpfcc -p PID 10 1:大量落在几微秒,说明线程刚上 CPU 就被换走(常是 CPU 饱和、非自愿切换);-O 看离开 CPU 的时间。

权限要 root。

ARM 板粗看可以读 /proc/PID/status 里两种上下文切换的次数。

§6.6.15

内存

freeprocps

回答还有多少内存可用,文件缓存占了多少。

看free -m 的 available(还能给新程序用的估计值),不是 free;buff/cache 大通常是好事。

ARM 板busybox free 可能没有 available 列,读 /proc/meminfo 的 MemAvailable。

§8.6.2

pmapprocps

回答一个进程的内存都映射了什么:堆、栈、共享库、映射的文件,各占多少。

看pmap -x PID 的 RSS 列,按大小排;匿名内存(堆)在涨还是文件映射在涨。/proc/PID/smaps_rollup 是汇总。

§7.5.9

slabtopprocps

回答内核对象缓存(slab)占了多少内存,哪一类最大。

看按大小排的缓存名;dentry、inode 很大常因为文件很多。要能读 /proc/slabinfo(通常要 root)。

§7.5.5 §8.6.6

memleakbpfcc-tools

回答一段时间里分配了却没释放的内存,以及分配它的调用路径。

看memleak-bpfcc -p PID;它分不清泄漏和正常增长,要看代码判断。开销不小。要 root。

§7.4.6

numastatnumactl

回答多插槽机器上,内存分配有多少落在本地节点。

看numa_miss、numa_foreign 相对 numa_hit 偏高,说明远程访问多;只有一个节点就不用看。

权限不要 root。

ARM 板ARM 板多为单节点;读 /sys/devices/system/node/node*/numastat。

§7.5.6

drsnoopbpfcc-tools

回答直接回收发生在哪个进程、每次卡了多久。

看LAT(ms) 和出现的频率;频繁出现几毫秒的,就是内存紧张在拖慢应用。

权限要 root。

ARM 板没有替代;退而看 /proc/vmstat 的 allocstall_*、pgscan_direct 在不在涨。

§7.5.11

文件和磁盘

iostatsysstat

回答每块盘的 IOPS、吞吐、平均延迟、队列长度、利用率。

看iostat -xz 1:r/s、w/s、rkB/s、wkB/s、r_await、w_await、aqu-sz、%util。%util 在 SSD 和阵列上会误导(它们能并行),以延迟和队列为准。

ARM 板读 /proc/diskstats 自己差分;busybox 可能带 iostat。

§9.6.1

cachestatbpfcc-tools

回答页缓存(文件缓存)的命中率。

看cachestat-bpfcc 1 的命中、未命中和命中率。命中率低说明读在打到盘上。要 root。

§8.6.12

ext4slower / ext4distbpfcc-tools

回答文件系统这一层的操作有多慢:哪些读、写、打开、同步慢于某个阈值,延迟分布如何。从应用感到的延迟量起。

看ext4slower-bpfcc 10 列出慢于 10 毫秒的操作;ext4dist-bpfcc 给直方图。xfs、btrfs 等有对应版本。要 root。

§8.6.13 §8.6.14

biolatencybpfcc-tools

回答块设备 IO 的延迟分布。

看biolatency-bpfcc 10 1 的直方图:双峰(缓存命中和未命中、读和写)、长尾。-D 按盘分开。要 root。

§9.6.6

biosnoopbpfcc-tools

回答每一次块 IO:哪个进程、哪块盘、读还是写、多大、多久。

看按延迟找出最慢的那几次,再看它们的共同点。输出量大,短时间用。要 root。

§9.6.7

opensnoopbpfcc-tools

回答谁在打开哪些文件、哪些打开失败了。

看同一个文件反复出现,说明在重复打开;-x 只列失败的,找缺失的配置和库;-n 按进程名过滤。

权限要 root。

ARM 板对单个进程用 strace -e trace=openat -p PID;内核开了 ftrace 时可以挂 openat 的跟踪点。

§8.6.10 §15.1.3

filetopbpfcc-tools

回答哪个文件读写最多。

看按读写字节排序的 READS、R_Kb 等列,找出意外忙碌的文件;-C 不清屏。

权限要 root。

ARM 板看 /proc/PID/io 的 rchar、wchar,粗看进程级。

§8.6.11

fatracefatrace

回答全系统的文件访问事件(基于 fanotify)。

看O 打开、R 读、W 写、C 关闭;忙的系统上输出极多、开销不小。

权限要 root。

ARM 板内核开了 fanotify 时可以交叉编译。

§8.6.8

biotopbpfcc-tools

回答哪个进程在发磁盘 IO、发了多少、平均多慢。

看I/O、Kbytes、AVGms 三列;PID 是尽力而为的,IO 由内核线程下发时可能对不上。

权限要 root。

ARM 板读 /proc/PID/io。

§9.6.8

iotopiotop(或 iotop-c)

回答按线程排序的磁盘读写速率和等 IO 的时间比例。

看DISK READ、DISK WRITE、IO%;Linux 5.14 起 delay accounting 默认关闭,要用启动参数 delayacct 或 sysctl kernel.task_delayacct=1 打开,IO% 才有数(用 sysctl 打开时,之前已经在跑的进程不计)。书里提醒它的计数要用已知负载验证。

权限要 root。

ARM 板无。

§9.6.8

biostacksbpftrace(biostacks.bt)

回答磁盘 IO 是哪条内核调用路径发出来的,各条路径的延迟分布。

看看栈里是哪种文件系统操作(路径查找、日志、后台回写),哪条栈的延迟偏高。

权限要 root。

ARM 板内核开了 ftrace 时,用 tracefs 的 block 跟踪点加栈。

§9.6.9

blktrace / bttblktrace

回答每个 IO 在块层各阶段(排队、合并、下发、完成)的时间。

看btt 的 D2C(在盘上的时间)、Q2C(块层全程);最大值大说明有离群值。

权限要 root。

ARM 板内核开了 CONFIG_BLK_DEV_IO_TRACE 时可以交叉编译。

§9.6.10

smartctlsmartmontools

回答盘的健康:纠正过的错误、重映射扇区、温度、自检结果。

看纠错次数、重映射扇区数在涨,说明盘快坏了;单个慢 IO 它回答不了。

权限要 root。

ARM 板eMMC 可以看 mmc-utils 读出的寿命字段(看你的 BSP)。

§9.6.13

iopingioping

回答单次 IO 有多慢,施加的负载很轻。

看每次请求的 time,最后的 min/avg/max/mdev;生产机上也能跑。

权限读普通文件不要 root。

ARM 板可以交叉编译。

§9.8.5

fiofio

回答文件系统或磁盘在给定 IO 大小、随机比例、并发下的 IOPS、吞吐和延迟分布。

看IOPS、带宽、延迟百分位(clat percentiles);不加 --direct=1 测到的是页缓存。测的时候开着 iostat 对照。

权限测普通文件不要 root,测裸设备要。

ARM 板可以编进 Buildroot、Yocto;没有时用 dd 加 oflag=direct 粗测。

§9.8.6 §12.2.1

网络

ssiproute2

回答套接字的状态和每个 TCP 连接的内部指标。

看ss -tin:rtt、cwnd、retrans、发送和接收队列;ss -lnt:监听套接字的 Recv-Q(当前排队的连接)和 Send-Q(队列上限)。

ARM 板busybox 有 netstat,没有 ss 时读 /proc/net/tcp。

§10.6.1

nstatiproute2

回答内核网络计数器的增量:重传、丢包、监听队列溢出。

看nstat -z:不带 -a 时显示上次运行以来的增量(第一次跑是开机以来的累计),-a 总是给累计值,-z 连为零的也列出。关心 TcpRetransSegs、TcpExtListenOverflows、TcpExtListenDrops、TcpExtTCPTimeouts。

ARM 板数据来自 /proc/net/snmp 和 /proc/net/netstat,可以直接读。

§10.6.4

ipiproute2

回答网卡的状态和收发统计、错误、丢包。

看ip -s link 的 errors、dropped、overrun。

§10.6.2

ethtoolethtool

回答网卡协商的速率和双工、驱动层的统计、队列和卸载设置。

看ethtool 网卡名 的 Speed、Duplex;ethtool -S 网卡名 驱动计数器(名字因驱动而异)。

§10.6.8

tcpdumptcpdump

回答线上到底收发了哪些包,握手、重传、窗口长什么样。

看tcpdump -i 网卡名 -w 文件 port 端口 抓下来再用 Wireshark 看。包多时开销大,用过滤器、写文件。要 root。

§10.6.13

tcpretransbpfcc-tools

回答每一次 TCP 重传:哪个连接、什么状态。

看重传集中在哪些对端地址。只在重传时触发,开销低。要 root。

§10.6.11

netstatnet-tools

回答各种网络计数和套接字列表(老工具)。

看netstat -s 看 listen queue overflowed、segments retransmitted;-i 看各网卡的 RX-DRP、RX-OVR。都是累计值,隔几秒看增量。书里提到内核网络开发者认为 net-tools 已经过时(§10.6 开头),iproute2 的 ss、ip、nstat 对新内核特性支持得最好。

权限不要 root。

ARM 板busybox 可能编进了 netstat(字段少);没有就读 /proc/net/snmp、/proc/net/netstat。

§10.6.5

tcplifebpfcc-tools

回答每条 TCP 连接活了多久、收发多少、属于哪个进程。

看MS 列是寿命,TX_KB、RX_KB 是收发量;短命连接太多,说明没做连接复用。开销小,可以常开。

权限要 root。

ARM 板要内核支持 BPF,板子上通常没有。

§10.6.9

tcpsynblbpfcc-tools;bpftrace(tcpsynbl.bt)

回答监听队列离满还有多远。

看每个 backlog 上限一张队列长度的直方图,贴近上限说明快要丢 SYN 了;bpftrace 的 tcpsynbl.bt 在队列超过上限时还会打印 dropping a SYN(BCC 版不打印)。

权限要 root。

ARM 板用 ss -lnt 的 Recv-Q、Send-Q,或读 /proc/net/netstat 的 ListenOverflows。

§10.6.12

iperf3iperf3

回答两台机器之间 TCP、UDP 的最大吞吐。

看单向吞吐和重传数(Retr);同时在接收端开 mpstat -P ALL 1,看是不是某个核的 %soft 先满。

权限不要 root。

ARM 板可以交叉编译,体积小。

§10.7.4 §12.2.1

wrkwrk

回答HTTP 服务的吞吐和延迟分布。

看加 --latency 看延迟分布;有错误响应先查错误再看吞吐;压测端单个线程 100% 时,测到的是 wrk 自己。

权限不要 root。

ARM 板一般在另一台机器上跑,不在板子上跑。

§12.2.2

跟踪框架

bpftracebpftrace

回答任何具体问题,现场写一行:某个函数被谁调用、耗时分布、按进程计数。

看单行命令输出的计数和直方图。要 root,内核要支持 BPF(有 BTF 更省事)。

§15.2 §6.6.20

Ftrace(tracefs)内核接口

回答内核函数和跟踪点的事件、调用图、计数,不需要装任何东西。

看/sys/kernel/tracing 下的 current_tracer、set_ftrace_filter、trace_pipe。要 root,内核要开 ftrace。板子上没有 BPF 时最后的依靠。

§14.2

trace-cmdtrace-cmd

回答和直接操作 tracefs 一样,但用命令行包装好了:记录、报告、function_graph。

看trace-cmd record -p function_graph -g 函数名,再 trace-cmd report。要 root。

§14.11

funccountbpfcc-tools(funccount-bpfcc);perf-tools-unstable(funccount-perf)

回答内核函数、用户函数或跟踪点每秒被调用多少次。

看BCC 版 -i 1 每秒一行,和请求速率比,看本该只调一次的函数是不是每个请求都在调。perf-tools 版基于 Ftrace 的函数剖析器,内核要开 CONFIG_FUNCTION_PROFILER。

权限都要 root。

ARM 板在跟踪点上挂 hist:keys=… 数次数。

§14.13.5 §15.1.4

funclatencybpfcc-tools

回答一个函数的耗时分布(直方图)。

看有两个峰说明有快慢两条路径;-u 用微秒;函数很快时探针自己的开销会把数字拉高,用户函数的 uprobe 尤其明显。

权限要 root。

ARM 板无。

§15.1.4

argdistbpfcc-tools

回答函数参数或返回值的分布。

看-H 出直方图、-C 计数;比如 write 一堆几字节的小写,往往是没加缓冲。

权限要 root。

ARM 板无。

§15.1.4

stackcountbpfcc-tools

回答哪些调用栈触发了某个事件或函数。

看排在前面的栈就是调用最多的路径;-U 只看用户栈、-K 只看内核栈;栈断了先查帧指针。

权限要 root。

ARM 板无。

§15.1.4

trace(BCC)bpfcc-tools(trace-bpfcc)

回答逐次打印某个函数的调用、参数和调用栈。

看一次调用一行,格式仿 printf;事件多时会刷屏,只适合低频函数。

权限要 root。

ARM 板tracefs 的 kprobe、uprobe 事件。

§15.1.6

funcgraphperf-tools-unstable(funcgraph-perf)

回答某个内核函数里调了哪些子函数、每层花了多久。

看左边的耗时列,带 # 的超过 1 毫秒、! 的超过 100 微秒;-m 限层数,-p 限 PID。

权限要 root。

ARM 板直接写 tracefs:set_graph_function,再 echo function_graph > current_tracer。

§14.13.3 §14.8

KernelSharkkernelshark

回答trace-cmd 录下的 trace.dat 里,各 CPU、各线程是怎么交错运行的。

看上方是每个 CPU 的时间线,下方是事件表;看线程之间的等待和抢占。

权限看图不要 root,录制要 root。

ARM 板在板子上用 trace-cmd record 录,拿到桌面上看。

§14.11.5