mpstat 命令详解与参数实测(Ubuntu 22.04)

mpstat 逐参数实测详解:默认 all 汇总十列逐列解读、mpstat 2 3 间隔采样与 Average 语义、-P ALL 逐核与 -P 0 单核、-A 全量(NODE 与软中断)、busy loop 打满单核 100% %usr 实证与 dd 期间 %iowait 对照 vmstat wa,Ubuntu 22.04(sysstat 12.5.2)全部回显实测通过。

Linux命令Linux系统UbuntuUbuntu 22.04命令行系统信息2026/10/15

mpstat 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 mpstat 的每一个常用参数——默认单行 all 汇总逐列解读(%usr/%nice/%sys/%iowait/%irq/%soft/%steal/%guest/%idle)、-P ALL 逐核视图与 -P 0 单核视图、mpstat 2 3 间隔采样、-A 全量(含 NODE 与中断)、-u 显式开关,并用 busy loop 与 dd 压力实证 %usr 与 %iowait 的变化,全部命令与回显已在 Ubuntu 22.04(sysstat 12.5.2)实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • 内核:6.8.0-138-generic(mpstat 报告头首行可见)
  • mpstat 版本:sysstat 12.5.2(mpstat -V 实测)
  • CPU:12 核,Intel(R) Core(TM) i7-14700KF,单路单 NUMA 节点(lscpu 实测:Thread(s) per core: 1、Socket(s): 1、NUMA node(s): 1)
  • mpstat 与 iostat 同属 sysstat 包,本环境随 iostat 一并安装(安装过程与回显详见《iostat 命令详解与参数实测(Ubuntu 22.04)》2.1 节)
  • 演示目录:/root/demo/iostat/(dd 压力演示复用 iostat 篇的临时大文件,测完即删)

二、命令概览

2.1 安装(mpstat 属于 sysstat 包)

Ubuntu 22.04 默认不预装 mpstat,一条命令安装(与 iostat 同包):

$ apt-get install -y sysstat

实测安装完成后验证:

$ dpkg -l sysstat | tail -1
ii  sysstat        12.5.2-2ubuntu0.2 amd64        system performance tools for Linux

$ mpstat -V
sysstat version 12.5.2
(C) Sebastien Godard (sysstat <at> orange.fr)

2.2 语法与测试数据

mpstat 的语法是 mpstat [ options ] [ <interval> [ <count> ] ]:不给 interval 时输出一份「自系统启动以来」的累计平均;给了 interval(如 mpstat 1 3)则每隔 1 秒输出一份增量报告、共 3 份,并在最后追加一行 Average: 汇总。-P { <cpu_list> | ALL } 用于选择报告的处理器粒度。

CPU 压力测试用一个空转循环把单核打满(每个循环占用 1 个核,12 核机器单循环约占总算力 1/12≈8.3%):

$ while :; do :; done &        # 后台空转,占满被调度到的那个核

IO 压力测试复用 dd 直写生成的 2 GB 文件(oflag=direct 绕过页缓存,实测写入速度约 650 MB/s):

$ dd if=/dev/zero of=/root/demo/iostat/load.bin bs=1M count=2000 oflag=direct
2000+0 records in
2000+0 records out
2097152000 bytes (2.1 GB, 2.0 GiB) copied, 3.22064 s, 651 MB/s

全部演示结束后 kill 掉空转循环、rm -f /root/demo/iostat/load.bin 清理即可。

2.3 --help 全量输出

mpstat --help 输出全部参数清单(实测逐行照抄):

Usage: mpstat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]
[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]
[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]

💡 说明:mpstat 的参数很少——-P 选核、-I 看中断、-N 选 NUMA 节点、-A 全量、-u CPU 报告开关(默认即开)、-o JSON 输出格式。本文第三章逐项实测其中最常用的 6 个。

2.4 版本信息

$ mpstat -V
sysstat version 12.5.2
(C) Sebastien Godard (sysstat <at> orange.fr)

2.5 技术拓展:CPU 观测工具对比

💡 技术拓展:CPU 使用率观测不止 mpstat 一种,常见同类工具横向对比——

工具视角特点与适用场景
mpstatCPU(all/逐核/NODE)唯一原生支持逐核拆分与软中断细分,定位单核打满
top/htop进程+逐核实时交互,htop 顶部也有逐核条,但不可脚本化留档
vmstat系统总览汇总一行 us/sy/id/wa,粒度粗但够快
sar历史归档回放任意历史时段的 CPU 曲线
pidstat -u进程级定位「哪个进程」吃 CPU,配合 mpstat 使用

本文主角是 mpstat:需要回答「是不是某个核被打满」「软中断吃掉多少 CPU」时,它的逐核与中断视图不可替代;进程归属再交给 pidstat。

三、参数逐项实测

3.1 默认输出:单行 all 汇总十列解读

不带参数的 mpstat 只输出两行:表头与 all 汇总行,口径是「自系统启动以来」:

$ mpstat
Linux 6.8.0-138-generic (f1034b9326b2)  10/15/26        _x86_64_        (12 CPU)

13:56:50     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:56:50     all   19.56    0.00    3.57    0.77    0.00    1.40    0.00    0.00    0.00   74.70

十列逐一解读:

列含义
%usr用户态占比(不含 nice 调整过的进程)
%nice低优先级(nice)用户态占比
%sys内核态占比
%iowait空闲且有未完成磁盘 IO 的时间占比,与 vmstat 的 wa 列同源(实测对照见 3.6)
%irq处理硬中断的时间占比
%soft处理软中断(网络收发、定时器等)的时间占比
%steal虚拟化环境下被宿主抢走的时间占比
%guest运行虚拟机客户机的时间占比
%gnice运行 nice 调整过的虚拟机客户机的时间占比
%idle空闲且无 IO 等待的时间占比

上例读法:%usr 19.56 + %sys 3.57 + %soft 1.40 ≈ 24.5% 的真实负载,%iowait 0.77 说明磁盘几乎不拖后腿,%idle 74.70 余量充足。

💡 要点:mpstat 的所有百分比加起来恒等于 100%(同一统计口径下各状态互斥),看到哪列异常高就顺着查哪类资源。

3.2 mpstat 2 3:间隔采样与 Average 行

mpstat 2 3 每隔 2 秒采样、共 3 份,末尾自动追加 Average: 行。第一行数据(13:56:52 行)的口径仍是「自系统启动以来」的累计平均,第二行起才是相邻采样之间的实时窗口:

$ mpstat 2 3
Linux 6.8.0-138-generic (f1034b9326b2)  10/15/26        _x86_64_        (12 CPU)

13:56:50     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:56:52     all    1.77    0.00    0.51    0.00    0.00    0.51    0.00    0.00    0.00   97.22
13:56:54     all    1.47    0.00    0.51    0.00    0.00    0.42    0.00    0.00    0.00   97.60
13:56:56     all    5.02    0.00    2.24    0.30    0.00    0.89    0.00    0.00    0.00   91.56
Average:     all    2.75    0.00    1.08    0.10    0.00    0.60    0.00    0.00    0.00   95.46

三份实时窗口的 %usr 在 1.47~5.02 之间波动(空闲机器的瞬时噪音),Average 行是对实时窗口(不含首份开机快照)求的平均。对比 3.1 的开机平均 %usr 19.56,可以直观体会两种口径的差别。

💡 要点:与 iostat 一样,第一份是开机快照不是实时数据;后续压力实证(3.5)会展示「第一行没变、后面的行才动」的典型形态。

3.3 -P ALL 逐核视图与 -P 0 单核视图

-P ALL 在每个采样时刻先给 all 汇总行、再给 0~11 每个核一行(下例为节省篇幅保留第一窗口与 Average 段):

$ mpstat -P ALL 1 2
Linux 6.8.0-138-generic (f1034b9326b2)  10/15/26        _x86_64_        (12 CPU)

13:56:56     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:56:57     all    7.35    0.00    3.55    0.00    0.00    1.27    0.00    0.00    0.00   87.84
13:56:57       0    5.71    0.00    2.86    0.00    0.00    6.67    0.00    0.00    0.00   84.76
13:56:57       1    5.83    0.00    1.94    0.00    0.00    3.88    0.00    0.00    0.00   88.35
13:56:57       2    1.02    0.00    1.02    0.00    0.00    1.02    0.00    0.00    0.00   96.94
13:56:57       3    4.08    0.00    8.16    0.00    0.00    0.00    0.00    0.00    0.00   87.76
13:56:57       4    3.06    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   95.92
13:56:57       5    2.08    0.00    1.04    0.00    0.00    1.04    0.00    0.00    0.00   95.83
13:56:57       6   21.65    0.00   11.34    0.00    0.00    0.00    0.00    0.00    0.00   67.01
13:56:57       7    6.06    0.00    1.01    0.00    0.00    0.00    0.00    0.00    0.00   92.93
13:56:57       8    6.06    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   93.94
13:56:57       9    6.06    0.00    1.01    0.00    0.00    0.00    0.00    0.00    0.00   92.93
13:56:57      10   10.64    0.00    8.51    0.00    0.00    0.00    0.00    0.00    0.00   80.85
13:56:57      11   16.33    0.00    5.10    0.00    0.00    2.04    0.00    0.00    0.00   76.53

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:     all    7.38    0.00    3.04    0.34    0.00    1.22    0.00    0.00    0.00   88.03
Average:       0   12.98    0.00    3.37    0.00    0.00    5.77    0.00    0.00    0.00   77.88
Average:       1   12.75    0.00    2.94    0.00    0.00    2.94    0.00    0.00    0.00   81.37
Average:       2    1.52    0.00    0.51    0.00    0.00    1.02    0.00    0.00    0.00   96.95
Average:       3    8.63    0.00    4.57    0.00    0.00    0.00    0.00    0.00    0.00   86.80
Average:       4    3.05    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   95.94
Average:       5    1.54    0.00    4.10    0.00    0.00    2.56    0.00    0.00    0.00   91.79
Average:       6   12.76    0.00    7.14    1.53    0.00    0.00    0.00    0.00    0.00   78.57
Average:       7   12.12    0.00    3.54    2.53    0.00    0.00    0.00    0.00    0.00   81.82
Average:       8    3.57    0.00    0.51    0.00    0.00    0.00    0.00    0.00    0.00   95.92
Average:       9    3.57    0.00    0.51    0.00    0.00    0.00    0.00    0.00    0.00   95.92
Average:      10    6.25    0.00    4.69    0.00    0.00    0.00    0.00    0.00    0.00   89.06
Average:      11    9.18    0.00    3.57    0.00    0.00    2.04    0.00    0.00    0.00   85.20

逐核价值立刻显现:all 汇总 %usr 只有 7.35%,但 6 号核 %usr 21.65%、%sys 11.34%(%idle 67.01%),0 号核 %soft 6.67%(网络软中断常驻的核)——不拆核的话这些不均匀都被平均值抹平了。

-P 0 只看 0 号核:

$ mpstat -P 0 1 2
Linux 6.8.0-138-generic (f1034b9326b2)  10/15/26        _x86_64_        (12 CPU)

13:56:58     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:56:59       0    0.00    0.00    3.85    0.96    0.00    5.77    0.00    0.00    0.00   89.42

13:56:59     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:57:00       0    2.91    0.00    3.88    0.00    0.00    4.85    0.00    0.00    0.00   88.35

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:       0    1.45    0.00    3.86    0.48    0.00    5.31    0.00    0.00    0.00   88.89

-P 0 视图里只有 0 号核的行(没有 all 行),适合长期盯某个特定核(例如绑定了网卡中断的核)。-P 也支持列表与范围,如 -P 0,3,6 或 -P 0-5(语法同 cpu_list)。

💡 要点:-P ALL 是排查「单核瓶颈」的标准姿势——总负载不高但个别核 100% 时,应用往往已经因为抢占该核而卡顿。

3.4 -A 全量:逐核 + NODE + 中断一次看全

-A 等价于 -u -P ALL 再叠加中断统计,输出五个板块:逐核 CPU、NUMA 节点(NODE)、总中断速率(intr/s)、空板块(中断号细分位)、软中断分类(HI/s TIMER/s NET_TX/s NET_RX/s BLOCK/s TASKLET/s SCHED/s RCU/s 等)。下例 -A 1 1(间隔 1 秒采 1 份),节选关键板块:

$ mpstat -A 1 1
Linux 6.8.0-138-generic (f1034b9326b2)  10/15/26        _x86_64_        (12 CPU)

13:57:00     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:57:01     all    6.29    0.00    1.76    0.00    0.00    1.01    0.00    0.00    0.00   90.94
13:57:01       0    0.94    0.00    1.89    0.00    0.00    8.49    0.00    0.00    0.00   88.68
13:57:01       1    4.04    0.00    1.01    0.00    0.00    2.02    0.00    0.00    0.00   92.93
13:57:01       2   14.85    0.00    2.97    0.00    0.00    0.99    0.00    0.00    0.00   81.19
13:57:01       3   10.20    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   88.78
13:57:01       4   10.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00   88.00
13:57:01       5    0.00    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   98.98
13:57:01       6    2.02    0.00    5.05    0.00    0.00    0.00    0.00    0.00    0.00   92.93
13:57:01       7    5.10    0.00    2.04    0.00    0.00    0.00    0.00    0.00    0.00   92.86
13:57:01       8   20.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00   78.00
13:57:01       9    1.02    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   97.96
13:57:01      10    6.12    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   93.88
13:57:01      11    1.03    0.00    1.03    0.00    0.00    0.00    0.00    0.00    0.00   97.94

13:57:00    NODE    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
13:57:01     all    6.29    0.00    1.76    0.00    0.00    1.01    0.00    0.00    0.00   90.94
13:57:01       0    6.29    0.00    1.76    0.00    0.00    1.01    0.00    0.00    0.00   90.94

13:57:00     CPU    intr/s
13:57:01     all  11029.00
13:57:01       0    455.00
13:57:01       1    322.00
13:57:01       2    229.00
13:57:01       3    173.00
13:57:01       4    163.00
13:57:01       5    221.00
13:57:01       6    170.00
13:57:01       7    173.00
13:57:01       8    155.00
13:57:01       9    205.00
13:57:01      10    185.00
13:57:01      11    294.00

13:57:00     CPU       HI/s    TIMER/s   NET_TX/s   NET_RX/s    BLOCK/s IRQ_POLL/s  TASKLET/s    SCHED/s  HRTIMER/s      RCU/s
13:57:01       0       0.00      32.00       0.00       0.00       0.00       0.00       0.00     214.00       0.00     209.00
13:57:01       1       0.00      13.00       0.00      15.00       0.00       0.00       0.00      71.00       0.00     223.00
13:57:01       2       0.00       8.00       0.00       0.00       0.00       0.00       0.00      36.00       0.00     185.00
13:57:01       3       0.00       6.00       0.00       6.00       0.00       0.00       0.00      26.00       0.00     135.00
13:57:01       4       0.00       3.00       0.00       0.00       0.00       0.00       0.00       4.00       0.00     156.00
13:57:01       5       0.00       7.00       0.00       0.00       7.00       0.00       0.00      30.00       0.00     177.00
13:57:01       6       0.00      12.00       0.00      11.00       0.00       0.00       0.00       1.00       0.00     146.00
13:57:01       7       0.00       6.00       0.00       0.00       0.00       0.00       0.00      16.00       0.00     151.00
13:57:01       8       0.00       3.00       0.00       0.00       0.00       0.00       0.00      13.00       0.00     139.00
13:57:01       9       0.00      22.00       0.00       0.00       0.00       0.00       0.00      14.00       0.00     169.00
13:57:01      10       0.00      58.00       0.00       0.00       0.00       0.00       0.00      12.00       0.00     115.00
13:57:01      11       0.00      41.00       0.00     128.00       0.00       0.00       0.00       4.00       0.00     121.00

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:     all    6.29    0.00    1.76    0.00    0.00    1.01    0.00    0.00    0.00   90.94
Average:       0    0.94    0.00    1.89    0.00    0.00    8.49    0.00    0.00    0.00   88.68
Average:       1    4.04    0.00    1.01    0.00    0.00    2.02    0.00    0.00    0.00   92.93
Average:       2   14.85    0.00    2.97    0.00    0.00    0.99    0.00    0.00    0.00   81.19
Average:       3   10.20    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   88.78
Average:       4   10.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00   88.00
Average:       5    0.00    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   98.98
Average:       6    2.02    0.00    5.05    0.00    0.00    0.00    0.00    0.00    0.00   92.93
Average:       7    5.10    0.00    2.04    0.00    0.00    0.00    0.00    0.00    0.00   92.86
Average:       8   20.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00   78.00
Average:       9    1.02    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   97.96
Average:      10    6.12    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   93.88
Average:      11    1.03    0.00    1.03    0.00    0.00    0.00    0.00    0.00    0.00   97.94

Average:     CPU    intr/s
Average:     all  11029.00
Average:       0    455.00
Average:       1    322.00
Average:       2    229.00
Average:       3    173.00
Average:       4    163.00
Average:       5    221.00
Average:       6    170.00
Average:       7    173.00
Average:       8    155.00
Average:       9    205.00
Average:      10    185.00
Average:      11    294.00

Average:     CPU       HI/s    TIMER/s   NET_TX/s   NET_RX/s    BLOCK/s IRQ_POLL/s  TASKLET/s    SCHED/s  HRTIMER/s      RCU/s
Average:       0       0.00      32.00       0.00       0.00       0.00       0.00       0.00     214.00       0.00     209.00
Average:       1       0.00      13.00       0.00      15.00       0.00       0.00       0.00      71.00       0.00     223.00
Average:       2       0.00       8.00       0.00       0.00       0.00       0.00       0.00      36.00       0.00     185.00
Average:       3       0.00       6.00       0.00       6.00       0.00       0.00       0.00      26.00       0.00     135.00
Average:       4       0.00       3.00       0.00       0.00       0.00       0.00       0.00       4.00       0.00     156.00
Average:       5       0.00       7.00       0.00       0.00       7.00       0.00       0.00      30.00       0.00     177.00
Average:       6       0.00      12.00       0.00      11.00       0.00       0.00       0.00       1.00       0.00     146.00
Average:       7       0.00       6.00       0.00       0.00       0.00       0.00       0.00      16.00       0.00     151.00
Average:       8       0.00       3.00       0.00       0.00       0.00       0.00       0.00      13.00       0.00     139.00
Average:       9       0.00      22.00       0.00       0.00       0.00       0.00       0.00      14.00       0.00     169.00
Average:      10       0.00      58.00       0.00       0.00       0.00       0.00       0.00      12.00       0.00     115.00
Average:      11       0.00      41.00       0.00     128.00       0.00       0.00       0.00       4.00       0.00     121.00

读法:全机中断速率 intr/s 11029 次/秒;0 号核的 %soft 8.49% 主要由 SCHED(214 次/秒)与 RCU(209 次/秒)构成;11 号核的 NET_RX/s 高达 128——网络收发软中断集中在个别核是常态。本机单 NUMA,NODE 板块与 all 完全一致;多路服务器上 NODE 板块能看出跨节点的负载倾斜。

💡 要点:日常快速排查用 -P ALL 即可,-A 适合做一次性的完整体检或软中断专项分析。

3.5 -u:显式声明 CPU 报告(等价默认行为)

-u 是「输出 CPU 使用率报告」的显式开关,效果与默认完全相同;在 -A 输出太长、或与其他选项组合想控制板块时有用:

$ mpstat -u 1 1 | tail -2
13:57:02     all    5.65    0.00    2.19    0.42    0.00    1.10    0.00    0.00    0.00   90.63
Average:     all    5.65    0.00    2.19    0.42    0.00    1.10    0.00    0.00    0.00   90.63

💡 要点:-A 已经隐含 -u;单独使用时 -u 与默认无差别,但明确写出来可让脚本意图更清晰。

3.6 CPU 压力实证 1:busy loop 打满单核(逐核视角)

后台启动一个空转循环,随即 -P ALL 连续采样 3 秒,观察 Average 段(grep 只保留 Average 行):

$ while :; do :; done & sleep 0.5; mpstat -P ALL 1 3 | grep -E "Average"; kill $! 2>/dev/null
Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
Average:     all   14.27    0.00    1.37    0.00    0.00    1.37    0.00    0.00    0.00   82.99
Average:       0    1.50    0.00    0.90    0.00    0.00   12.28    0.00    0.00    0.00   85.33
Average:       1    6.35    0.00    0.33    0.00    0.00    1.00    0.00    0.00    0.00   92.31
Average:       2    4.07    0.00    0.34    0.00    0.00    0.34    0.00    0.00    0.00   95.25
Average:       3    2.04    0.00    1.36    0.00    0.00    0.00    0.00    0.00    0.00   96.60
Average:       4   15.10    0.00    1.01    0.00    0.00    0.00    0.00    0.00    0.00   83.89
Average:       5    2.74    0.00    0.34    0.00    0.00    0.34    0.00    0.00    0.00   96.58
Average:       6   11.78    0.00    2.36    0.00    0.00    0.00    0.00    0.00    0.00   85.86
Average:       7   11.78    0.00    3.37    0.00    0.00    0.00    0.00    0.00    0.00   84.85
Average:       8    9.12    0.00    3.04    0.00    0.00    0.00    0.00    0.00    0.00   87.84
Average:       9    0.00    0.00    0.68    0.00    0.00    0.00    0.00    0.00    0.00   99.32
Average:      10  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
Average:      11    6.85    0.00    2.74    0.00    0.00    1.03    0.00    0.00    0.00   89.38

最典型的一幕:10 号核 %usr 100.00、%idle 0.00——空转循环被调度到这个核上,把它整个吃满;其余核照常呼吸(9 号核甚至全程 99.32% 空闲)。这正是「总负载不高、单核已死」的现场,也是 -P ALL 存在的意义。

3.7 CPU 压力实证 2:busy loop 的汇总视图(默认 all)

同一个单循环在默认 all 汇总视角下的样子:

$ while :; do :; done & sleep 0.5; mpstat 1 4 | grep -E "all"; kill $! 2>/dev/null
13:57:07     all   13.50    0.00    3.00    0.08    0.00    2.08    0.00    0.00    0.00   81.33
13:57:08     all   10.19    0.00    1.68    0.59    0.00    1.01    0.00    0.00    0.00   86.52
13:57:09     all   12.99    0.00    2.01    0.67    0.00    1.42    0.00    0.00    0.00   82.90
13:57:10     all   10.22    0.00    0.50    0.00    0.00    1.09    0.00    0.00    0.00   88.19
Average:     all   11.73    0.00    1.80    0.34    0.00    1.40    0.00    0.00    0.00   84.73

对照 3.2 空闲时 %usr 1.475.02 的水位,启动单循环后 %usr 稳定在 10.1913.50——涨幅约 8.3 个百分点,恰是该循环占用的 1/12 核算力(100%/12≈8.33%)。单核 100% 在汇总视图里只显示为 +8%,这就是为什么要配合 3.6 的逐核视图。

3.8 %iowait 与 vmstat wa 对照(dd 压力,双工具同窗口并行采样)

dd 直写期间,把 mpstat 与 vmstat 同时挂起采样(vmstat 落到文件、mpstat 走前台,保证两者覆盖同一个时间窗),对照 %iowait 与 wa 两列:

$ dd if=/dev/zero of=/root/demo/iostat/load.bin bs=1M count=2000 oflag=direct & sleep 0.3; vmstat 1 4 > /tmp/vmstat-j2.log 2>&1 & mpstat 1 4 | grep -E "all"; wait; echo "--- vmstat 同窗口输出 ---"; cat /tmp/vmstat-j2.log; rm -f /root/demo/iostat/load.bin
2000+0 records in
2000+0 records out
2097152000 bytes (2.1 GB, 2.0 GiB) copied, 3.22064 s, 651 MB/s
14:02:10     all    1.87    0.00    7.91    1.11    0.00    0.77    0.00    0.00    0.00   88.34
14:02:11     all    3.59    0.00    9.49    2.22    0.00    1.11    0.00    0.00    0.00   83.59
14:02:12     all    1.35    0.00    5.58    2.70    0.00    0.59    0.00    0.00    0.00   89.77
14:02:13     all    1.36    0.00    0.34    0.00    0.00    0.42    0.00    0.00    0.00   97.88
Average:     all    2.04    0.00    5.82    1.51    0.00    0.72    0.00    0.00    0.00   89.91
--- vmstat 同窗口输出 ---
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 5  0 1596844 636404 826084 32797944    0    5    41  2490  115   67 19  5 75  1  0
 0  1 1596844 626356 826124 32798168   32    0    40 684416 11768 11731  2  9 88  1  0
 1  0 1596844 622716 826168 32798572   32    0    36 650392 21392 27098  4 11 84  2  0
 1  0 1596844 622596 826196 32798804    0    0    16 543936 11460 11455  1  6 90  3  0

逐秒对照:dd 存续的前三个窗口,mpstat 的 %iowait 为 1.11→2.22→2.70,vmstat 的 wa 列为 1→2→3,bo(每秒写出的块数)高达 684416/650392/543936——两个工具对同一 IO 压力的 CPU 侧响应完全同步;dd 结束后第四个窗口 %iowait 与 wa 同时归零。两者的差别只是采样口径与舍入粒度(mpstat 精确到 0.01%,vmstat 取整)。

💡 要点:%iowait 与 wa 是同一事件(CPU 空闲但有 IO 未完成)在两个工具里的各自表述;它升高代表存储层可能跟不上,但要确认设备侧状态还得看 iostat 的 %util/await。

3.9 错误用法与退出码

给 -P 传一个不存在的核号,mpstat 打印用法摘要并以状态码 1 退出:

$ mpstat -P 99 1 1; echo rc=$?
Usage: mpstat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]
[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]
[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]
rc=1

💡 要点:脚本里可以靠退出码判断 mpstat 是否执行成功(0 成功、1 参数或运行错误),避免把错误用法输出当数据解析。

四、实战示例

4.1 判断「整体慢」还是「单核瓶颈」

只看汇总(数据取自 3.7:all %usr 11.73、%idle 84.73)会以为机器很闲;加逐核视图(数据取自 3.6)立刻看到 10 号核 100%。组合套路:

$ mpstat 1 3 | grep Average        # 第一步:看整体水位
$ mpstat -P ALL 1 3 | grep -v all  # 第二步:整体有异常或怀疑不均时,逐核下钻

4.2 定位软中断吃 CPU 的核

多核服务器上网络吞吐上不去时,先看 %soft 分布(数据取自 3.3 与 3.4:0 号核 %soft 6.67%/8.49%,其余核多为 0~4%):软中断集中于少数核说明中断亲和性未调优,可用 cat /proc/interrupts 查看中断分布后调整 smp_affinity。

4.3 观察一批 CPU 密集任务对整机的影响

先采基线(3.2 的 1.47~5.02),再启动 N 个空转循环,用 mpstat 2 3 观察 %usr 阶梯上升(单循环 +8.3 个百分点,见 3.7 实测),由此可反推:实际 %usr 涨幅 ÷ 8.3 ≈ 打满的核数。

4.4 与 vmstat/iostat 组合做存储排查

存储卡顿排查三板斧(均已在本文与 iostat 篇实测):

$ mpstat 1 3        # %iowait 是否升高(本文 3.8:1.11→2.70)
$ vmstat 1 3        # wa 列交叉印证,bo 看写出量(3.8:684416 块/秒)
$ iostat -x 1 3     # %util/await/aqu-sz 确认设备侧瓶颈(iostat 篇 3.10)

五、注意事项与常见问题

Q1:为什么第一份报告的数字和后面不是一个量级?

mpstat 给了 interval 时,首份报告(时间戳为第一个采样区间结束时刻)的口径是「自系统启动以来」的累计平均(实测见 3.2:开机平均 %usr 19.56 对比实时窗口 1.47~5.02);第二份起才是实时窗口。排查当下问题只看第二份起的数据,Average: 行也只统计实时窗口。

Q2:%usr 高就一定是应用的问题吗?

不一定。先区分列归属:%usr 是用户态业务代码,%sys 是内核态(系统调用、锁、内存管理),%soft 是软中断(网络收发高峰时常见,实测 0 号核 %soft 8.49% 由 SCHED/RCU 软中断构成,见 3.4),%iowait 是等盘。对应处理方向完全不同。

Q3:所有列都接近 0,但机器明明很卡?

看三个隐藏方向:一是逐核拆分(-P ALL),单核 100% 被平均抹平(实测:单循环在 all 上只显示 +8.3%,见 3.7,但 10 号核 100%,见 3.6);二是 %steal(虚拟机被宿主抢占);三是卡顿可能根本不是 CPU,转 vmstat 的 b 列与 iostat 的 await 查 IO。

Q4:mpstat 的 %iowait 高说明什么?和 iostat 的 %util 什么关系?

%iowait 是 CPU 视角的「空闲但有 IO 没做完」时间占比,%util 是设备视角的「设备忙」时间占比。%iowait 高只是提示存储可能跟不上(实测 dd 期间 1.11→2.70,见 3.8);最终判定要用 iostat 的 %util/await/aqu-sz 三件套(iostat 篇 3.10 实测)。

Q5:-P ALL 的编号从 0 开始还是 1 开始?

从 0 开始(本机 12 核编号 0~11,实测见 3.3/3.4 输出)。引用核号时(如中断亲和性脚本里的 CPU 编号)以 mpstat//proc/cpuinfo 的编号为准,别按 1 计数。

Q6:脚本里解析 mpstat 输出有什么稳妥姿势?

固定用 Average: 行(给 interval 时必出现)作为稳定锚点;加 -o JSON 可直接得结构化输出(本版支持,见 2.3 帮助清单);--dec={0|1|2} 控制小数位。别按空格 split 表头行——列宽会随数值变宽。

六、参考链接