Linux 中 vmstat 命令详解:内存、CPU 与 I/O 统计实时监控

当服务器变慢时,首先要问的问题就是它在等待什么。是 CPU 饱和了吗?内存耗尽、系统正在交换吗?是磁盘 I/O 拖住了进程吗?vmstat 命令把每种资源的线索集中在一张紧凑的表格里,是在你转向更专业的监控工具之前很有用的第一步检查。

vmstat 是 virtual memory statistics(虚拟内存统计)的缩写,由 procps-ng 提供。大多数完整的 Linux 安装都会通过一个名为 procps 或 procps-ng 的包包含它。

本指南讲解如何阅读 vmstat 的输出,以及使用它最实用的选项。

语法

vmstat [OPTIONS] [delay [count]]
  • delay - 报告之间的间隔秒数。不指定时,vmstat 打印一份报告后退出。
  • count - 要打印的报告数量。设置了 delay 但没设 count 时,vmstat 会一直运行到按下 Ctrl+C。

解读默认输出

不带参数运行 vmstat 会打印一份报告:

vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st gu
 1  0      0 362824  94368 1207160    0    0    12     5   48  112  1  0 99  0  0  0

进程列和内存列显示的是命令运行时刻的值。在第一份报告中,交换、I/O、系统和 CPU 活动是自上次启动以来的平均值。输出分为六个部分。

procs(进程)

  • r - 可运行进程数,包括正在运行或等待 CPU 时间的进程。将持续偏高的值与 nproc 得到的逻辑 CPU 数比较;繁忙的运行队列加上很少的空闲 CPU 暗示 CPU 争用。
  • b - 等待 I/O 完成而被阻塞的进程数。

memory(内存,默认 KiB)

  • swpd - 当前已使用的交换空间。
  • free - 当前未被使用的空闲内存。
  • buff - 用作缓冲区的内存。
  • cache - 用作缓存的内存。Linux 会用原本空闲的 RAM 缓存数据,因此数值较大是正常的。

仅看 free 列并不能说明应用程序可以立即使用多少内存。需要这个数字时,请用 free 命令查看 available 值。

swap(交换,KiB/s)

  • si - 每秒从磁盘换入的内存(KiB/s)。
  • so - 每秒换出到磁盘的内存(KiB/s)。

偶尔的交换活动不足以诊断问题。持续的 si 或 so 活动,伴随着 free 和 cache 内存下降,才是内存压力更强的信号。

io(输入/输出,KiB/s)

  • bi - 每秒从块设备接收的 KiB 数。
  • bo - 每秒发送到块设备的 KiB 数。

system(系统)

  • in - 每秒中断次数,包括时钟中断。
  • cs - 每秒上下文切换次数。将该值与系统的正常负载比较,而不是用固定阈值。

cpu(占总 CPU 时间的百分比)

  • us - 运行用户空间代码(含 nice 时间)所占的时间。
  • sy - 运行内核代码所占的时间。
  • id - 空闲时间。
  • wa - CPU 因等待 I/O 而空闲的时间。持续上升是排查 I/O 的线索,但它不能指出具体设备,也不能证明存储就是瓶颈。
  • st - 被 hypervisor 从虚拟机拿走的时间。
  • gu - 运行 KVM 客户机代码(含客户机 nice 时间)所占的时间。

较旧的 procps-ng 版本可能在 st 列处结束 CPU 列。前面各列的含义不变。

持续监控

单份报告对实时问题的信息有限。传入一个延迟参数,可以观察连续间隔内的活动:

vmstat 2

这会每两秒打印一个新行,直到你按下 Ctrl+C。第一行仍然包含自启动以来的活动平均值,而后面的行覆盖每个两秒间隔。加上 -y 可以省略第一份报告:

vmstat -y 2

要采集十次间隔报告后停止,加上一个计数:

vmstat -y 2 10
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st gu
 0  0      0 360988  94504 1208068    0    0     0     0   92  198  0  0 100  0  0  0
 1  0      0 360744  94504 1208068    0    0     0    16  104  231  1  0 99  0  0  0
 0  0      0 360720  94504 1208080    0    0     0     0   89  190  0  0 100  0  0  0

这里只显示前三行。因为 -y 跳过了即时的启动平均值报告,命令会等待并记录十个两秒间隔,耗时约 20 秒。

当你想稍后复查时,可以添加时间戳并把报告重定向到文件:

vmstat -y -t 2 10 > vmstat.log

活跃与非活跃内存

-a 标志会用 inact(非活跃内存)和 active(活跃内存)两列替换 buff 和 cache 列:

vmstat -a
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st gu
 0  0      0 358900 921048 490836    0    0    12     5   48  112  1  0 99  0  0  0

活跃内存包含最近使用、很可能再次被引用的页面。非活跃内存最近未被访问,在系统需要空间时包含可回收的候选页。当多个工作负载竞争内存时,这种视图很有用。

添加时间戳

-t 标志会在每行后面追加一个时间戳列,在把输出捕获到日志文件时很有用:

vmstat -y -t 2 5
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu------- -----timestamp-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st gu                 EEST
 0  0      0 362824  94368 1207160    0    0     0     0   88  195  0  0 100  0  0  0 2026-09-07 10:30:02
 0  0      0 362700  94368 1207160    0    0     0    12   94  207  1  0 99  0  0  0 2026-09-07 10:30:04

时间戳使用系统的本地时区。示例只显示了所请求五次报告中的前两次。

宽输出模式

在拥有很多 CPU 核心或计数器值很高的系统上,默认的列宽可能导致数字被截断或列之间重叠。-w 标志切换到更宽的格式,避免截断:

vmstat -w 2

内存事件计数器

-s 标志会打印当前内存总量,后跟自启动以来累计的 CPU 和事件计数器:

vmstat -s
      2023560 K total memory
       417148 K used memory
       493280 K active memory
       921048 K inactive memory
       362824 K free memory
        94368 K buffer memory
      1207160 K swap cache
      2097148 K total swap
            0 K used swap
      2097148 K free swap
        48712 non-nice user cpu ticks
          952 nice user cpu ticks
        12836 system cpu ticks
      5181148 idle cpu ticks
         5984 IO-wait cpu ticks
            0 IRQ cpu ticks
         3268 softirq cpu ticks
            0 stolen cpu ticks
            0 non-nice guest cpu ticks
            0 nice guest cpu ticks
       621264 K paged in
       247908 K paged out
            0 pages swapped in
            0 pages swapped out
      2518704 interrupts
      5884112 CPU context switches
   1788713671 boot time
        52364 forks

确切的列表随内核和 procps-ng 版本而不同。这种视图对检查当前交换总量和累计分页活动很有用。事件计数器和 CPU 滴答在重启后会重新计数。

磁盘统计

-d 标志显示按磁盘设备拆分的累计读、写统计:

vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
       total merged sectors      ms  total merged sectors      ms    cur    sec
sda    12486    983  956342   34208  18402   4682  920612  142104      0     42
sdb      142      0    9168     252      0      0       0       0      0      0
  • total - 已完成的读或写操作总数。
  • merged - 被合并为单个 I/O 操作的相邻请求数。
  • sectors - 读写的扇区总数。
  • ms - 读或写耗费的总毫秒数。
  • cur - 当前正在进行的 I/O 操作数。
  • sec - 做 I/O 耗费的总秒数。

要查看特定分区的统计而非整个磁盘:

vmstat -p /dev/sda1
sda1          reads   read sectors  writes    requested writes
               12384    948812        18320    910484

更改输出单位

默认情况下,内存和交换值使用 1024 字节的 kibibyte(KiB)。-S 标志改变它们的显示单位:

vmstat -S M 2

可接受的值是 k(1000 字节)、K(1024 字节)、m(1,000,000 字节)和 M(1,048,576 字节)。该选项不会改变交换(si、so)或 I/O(bi、bo)字段,它们仍以 KiB/s 为单位。

选项参考

  • -a - 显示活跃与非活跃内存,而不是缓冲和缓存值。
  • -d - 显示每个设备的磁盘统计。
  • -D - 显示磁盘统计汇总。
  • -f - 显示自启动以来的 fork 次数。
  • -m - 显示 slab 内存信息。
  • -n - 只打印一次表头。
  • -p device - 显示分区级别的磁盘统计。
  • -s - 显示内存统计和事件计数器。
  • -S unit - 将内存和交换输出单位设为 k、K、m 或 M。
  • -t - 在每行追加时间戳。
  • -w - 使用更宽的列,避免不想要的列断裂。
  • -y - 省略包含自启动以来活动平均值的第一份报告。

速查表

任务命令
单次快照vmstat
每 2 秒刷新vmstat 2
跳过启动平均值报告vmstat -y 2
10 次间隔报告,间隔 2 秒vmstat -y 2 10
活跃/非活跃内存视图vmstat -a 2
带时间戳的输出vmstat -t 2
宽输出vmstat -w 2
内存事件计数器vmstat -s
磁盘统计vmstat -d
分区统计vmstat -p /dev/sda1
以兆字节输出vmstat -S M 2

故障排查

为何所有数值看起来都像平均值而不是实时活动? 第一行包含自启动以来的活动平均值,不过其进程和内存字段是当前值。运行 vmstat -y 2 可跳过该行,只显示两秒间隔的报告。

为何 shell 报错 vmstat: command not found? 在 Ubuntu 和 Debian 上用 sudo apt install procps 安装 procps 包。Fedora 和 RHEL 用 sudo dnf install procps-ng,Arch Linux 用 sudo pacman -S procps-ng。

为何 vmstat 无法读取 /proc 下的数据? 命令需要访问 /proc 下的文件。以限制性 /proc 选项挂载的容器和系统可能隐藏部分统计信息。vmstat -m 视图还需要访问 /proc/slabinfo,普通用户可能无权访问。

结语

当系统变慢时,先运行 vmstat -y 2 做第一步检查,然后顺着信号深入:用 top 或 htop 查看每个进程的 CPU 和内存占用,或用 iostat -xz 2 查看设备延迟和队列。