CPU 峰值并不意味着你的机器在死亡,它只是意味着有变化发生了。

区分初级管理员和专家的,不是他们知道多少命令,而是他们如何解释系统告诉他们的信息。

2026.02 山东·威海·荣成·天鹅湖

原文

“CPU 达到 90%!立即检查!”

如果你是 Linux 管理员,你肯定听说到过这句话。在警报触发的瞬间,所有人一瞬间突然记起了你的名字,然后,一连串的炮弹向你飞来:

  • “系统宕机了吗?”
  • “这会影响生产吗?”
  • “什么时候能修复?”

你登录系统,打开 top 命令,盯着每秒刷新的屏幕……,仍然不知道为什么 CPU 使用率那么高,CPU 看起来像是在燃烧,但真相往往隐藏在别处。

找不到原因的原因

大多数管理员犯了同样的错误,他们把 top 当作唯一的真相来源。他们看到一个高的 %CPU,然后立即假设:

  • “机器过载了。”
  • “我们需要扩展。”
  • “有什么东西在消耗 CPU 周期。”

top 只显示 症状 ,不显示原因。在真实事件中,CPU 问题往往根本不是 CPU 问题。它们是有可能是由以下原因引起的:

  • I/O 等待 (CPU 空闲,卡在等待慢速磁盘/NAS/云存储)
  • 上下文切换风暴 (太多线程争夺时间片)
  • 在虚拟化环境中窃取时间
  • 一个行为异常的进程,在几秒钟内突然爆发然后消失

所以这种沮丧是完全可以理解的,你们被问到“为什么?”而你们的工具只告诉你“是什么。”


三步 CPU 诊断流程

这就是我在 CPU 突然飙升时使用的确切流程。它快速、系统化,适用于任何 Linux 服务器或云虚拟机。

步骤 1 — 确定“高 CPU”是什么类型

运行:

1
vmstat 1 5

这能立刻告诉你峰值背后的真正原因

  • us high → 用户进程确实繁忙
  • sy 高 → 内核繁忙(系统调用、中断)
  • wa 高 → CPU 正在等待磁盘 I/O
  • st 高 → 虚拟机正在窃取 CPU 时间

大多数人忽略了 wa——但问题的一半就隐藏在那里。

真实故事:

我之前曾有一个虚拟机 CPU 使用率达到 95%,结果发现,问题不在于应用程序——而是云硬盘后端被限流了,CPU 使用率“高”仅仅是因为它卡在 等待 状态。


步骤2 — 在你登录之前重建发生了什么

当你通过 ssh 登录到虚拟机时,峰值可能已经过去了,这时,sar 就变得非常关键。

检查历史 CPU 状态:

1
sar -u 1 5

或者从每日日志中加载数据:

1
sar -u -f /var/log/sa/sa10

这很重要:

大多数监控系统每1-5分钟采样一次。如果峰值发生在 20 秒前,如果没有 sar,你将看不到它。

你会得到一个时间线:

  • CPU 是什么时候飙升的?
  • 是一次性的突发吗?
  • 这是由用户负载、系统负载还是 I/O 等待引起的?

这让你从“猜测管理员”转变为“调查管理员”。


第3步 — 确定哪个进程实际上导致了问题

现在你知道了 CPU 为何繁忙,找出是责任人。

从开始:

1
ps -eo pcpu,pid,user,args | sort -k1 -r | head

如果 CPU 正在忙于切换任务或线程,请使用:

1
pidstat -wt 2 5

为什么 pidstat

因为它暴露了 top 无法显示的东西: 上下文切换

一个具有高 cswch/s 的进程可以使整个系统感觉缓慢

—even 当其 %CPU 看起来正常时。

这就是你如何捕捉“幽灵瓶颈”。


一个真实案例

我们的一台生产虚拟机收到了一个严重警报:CPU 使用率:98% 平均负载:12.0,业务团队陷入了恐慌,应用团队要求立即找出根本原因。然而,当SA登录的时候,CPU 仅在 40% 左右。那到底发生了什么?

以下是工具揭示的内容:

  • vmstatwa %大于 60%
  • sar:峰值正好在备份作业触发时开始
  • pidstat:备份进程导致大量 I/O
  • 磁盘指标:由于云磁盘限制导致 IOPS 被限制

根本原因:

磁盘后端限流,导致 I/O 等待,导致 CPU 看起来“繁忙”,尽管实际上它是空闲的。我们将备份移到了非高峰时段,CPU 警报完全停止了。这就是为什么理解 CPU 正在忙于处理什么比了解其繁忙程度更为重要。


警报并非问题,它们是信号

CPU 峰值并不意味着你的机器在死亡,它只是意味着有变化发生了。区分初级管理员和专家的,不是他们知道多少命令,而是他们如何解释系统告诉他们的信息。

下次你看到“CPU 100%”:

  • 检查类型ussywast
  • 检查时间线sar
  • 识别罪魁祸首ps / pidstat

保持冷静,关注信号,系统会告诉你确切要查看的位置。


附录

vmstat

vmstat 是一个用于报告系统进程、内存、分页、块 IO、陷阱(中断)和 CPU 活动情况的工具,它能帮助管理员快速了解系统的整体负载和资源瓶颈。通过灵活使用 vmstat,你可以快速诊断系统性能问题,为调优提供依据。

基本语法为:“ vmstat [options] [delay [count]]”

  • options:命令选项,用于控制输出内容。
  • delay:两次刷新之间的间隔时间(秒)。如果不指定,则只显示一次自启动以来的平均值。
  • count:刷新次数。如果指定了 delay 而不指定 count,则会无限次输出。

执行 vmstat 后,会输出类似以下内容(第一行是自启动以来的平均值,后续行是间隔内的数据):

1
2
3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 256000 102400 20480 1024000 0 1 10 20 100 150 5 2 93 0 0
1. procs(进程)
  • r:正在运行或等待 CPU 的进程数(运行队列长度)。若长期大于 CPU 核心数,表示 CPU 繁忙。
  • b:处于不可中断睡眠状态的进程数(通常等待 I/O)。
2. memory(内存)
  • swpd:已使用的虚拟内存(交换分区)大小。
  • free:空闲内存大小。
  • buff:用作缓冲区(buffer)的内存大小。
  • cache:用作文件缓存(cache)的内存大小。
  • (使用 -a 可额外显示 inactactive
3. swap(交换)
  • si:每秒从磁盘交换入内存的数据量(swap in)。
  • so:每秒从内存交换出到磁盘的数据量(swap out)。
  • siso 长期非零,说明物理内存不足。
4. io(块设备 I/O)
  • bi:每秒从块设备接收到的块数(读磁盘)。
  • bo:每秒发送给块设备的块数(写磁盘)。
  • 这些值反映磁盘 I/O 负载。
5. system(系统)
  • in:每秒的中断次数(包括时钟中断)。
  • cs:每秒的上下文切换次数。过高可能表示线程/进程过多或锁竞争。
6. cpu(CPU 使用率)
  • us:用户空间程序占用的 CPU 时间百分比。
  • sy:内核空间占用的 CPU 时间百分比。
  • id:空闲 CPU 时间百分比。
  • wa:等待 I/O 完成的时间百分比。若此值高,表示磁盘或网络 I/O 是瓶颈。
  • st:被虚拟机偷走的时间(仅用于虚拟机环境)。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 显示自系统启动以来的平均统计。
vmstat

# 每隔 2 秒刷新一次,共输出 5 次
vmstat 2 5

# 输出中会多出 `inact` 和 `active` 两列。
vmstat -a 2 5

# 列出每个磁盘的读写次数、合并次数、扇区数等
vmstat -d

# 显示指定分区(如 /dev/sda1)的统计
vmstat -p /dev/sda1

# 以表格形式展示内存总量、使用量、缓存等
vmstat -s

# 显示 slab 信息(内核对象缓存)
sudo vmstat -m

注意事项

  • 第一次输出的数据是系统启动以来的平均值,后续才是间隔内的实际数据,通常更关注后续数据。
  • 某些字段(如 si/so)的单位是 KB(部分系统可能是块,通常 1 块 = 1024 字节),具体可查看 man 手册。
  • 对于更详细的磁盘 I/O 分析,可结合 iostat 命令。

sar

sar 是 Linux 上最全面的系统性能分析工具之一,由 sysstat 软件包提供。它不仅能实时查看系统状态,更重要的是,它会在后台定期(通常每10分钟)收集CPU、内存、I/O、网络等数据,并将其保存到日志文件中。这使得我们可以回顾过去任意时刻的系统表现,这对于排查那些稍纵即逝的性能问题至关重要。

sar 的基本语法是 sar [options] [<间隔> [<次数>]]。如果不指定间隔和次数,则显示当天从凌晨开始保存的历史数据。

CPU 性能

  • 查看CPU整体使用率sar -u 。输出包括 %user(用户态)、%system(内核态)、%iowait(等待I/O)、%idle(空闲)等关键指标。
  • 查看每个CPU核心的使用情况sar -P ALL 。可以替换 ALL 为具体的核心ID(如 -P 0)来监控单个核心。
  • 查看CPU负载情况sar -q 。通过 runq-sz(运行队列长度)和 ldavg-1/5/15(1/5/15分钟平均负载)来判断系统是否繁忙。

内存性能

  • 查看内存和交换分区使用情况sar -r 。关注 kbmemused(已用内存)、%memused(内存使用百分比)、kbbuffers(缓冲区)和 kbcached(缓存)。
  • 查看页面交换活动sar -W 。如果 pswpin/s(每秒换入的页面数)和 pswpout/s(每秒换出的页面数)长期不为0,说明物理内存可能不足,系统正在频繁使用交换分区,这通常会严重影响性能。

I/O 性能

  • 查看I/O和传输速率统计sar -b 。输出 tps(每秒I/O请求总数)、rtps(读请求数)、wtps(写请求数)等。
  • 查看每个块设备的使用情况sar -d -p-p 选项可以让设备显示为熟悉的名称(如 sda),而非主次设备号。关注 await(I/O请求平均处理时间,包含等待时间)和 %util(设备利用率),这两项是判断磁盘是否为瓶颈的关键指标。

网络性能

  • 查看网络设备状态sar -n DEV 。这是最常用的网络监控方式,可以查看 eth0lo 等网络接口的 rxpck/s(每秒接收包数)、txpck/s(每秒发送包数)、rxkB/s(每秒接收千字节数)和 txkB/s(每秒发送千字节数)。
  • 查看网络错误sar -n EDEV 可以查看网络接口的通信错误信息。
  • 查看Socket连接信息sar -n SOCK 可以查看正在使用的socket总数、TCP socket数等。

实战技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 每2秒监控一次CPU,共监控5次
sar -u 2 5

# 使用 `-f` 选项指定历史数据文件。例如,查看本月6号的内存使用情况
sar -r -f /var/log/sa/sa06

# 使用 `-s` (开始时间)和 `-e` (结束时间)选项,精准定位问题时段。例如,查看上周二(数据文件 `sa16`)上午9点到12点的CPU负载:
sar -q -s 09:00:00 -e 12:00:00 -f /var/log/sa/sa16

# 将实时采集的数据保存到二进制文件,以便日后分析:
sar -u -o cpu_recording 2 10

# 随后可使用 `-f` 从 `cpu_recording` 文件中读取数据:
sar -u -f cpu_recording

pidstat

pidstat 是 sysstat 软件包中的一员,主要用于监控和管理单个或全部进程的资源使用情况。与 vmstat 查看系统整体不同,pidstat 能够精确输出每个进程的 CPU、内存、I/O、上下文切换等统计信息,是深入分析和定位问题进程的利器。

核心用法详解

pidstat 的基本语法是 pidstat [options] [interval] [count]。如果不带任何选项,默认显示所有进程的 CPU 统计信息。

1. CPU 使用监控

  • 命令pidstat -u 1 或简写为 pidstat 1
  • 关键字段
    • %usr:进程在用户态运行的 CPU 时间占比。
    • %system:进程在内核态运行的 CPU 时间占比。
    • %CPU:进程总的 CPU 使用率。
    • Command:进程的命令名称。

2. 内存使用监控

  • 命令pidstat -r 1
  • 关键字段
    • minflt/s:每秒发生的次要缺页错误(无需从磁盘加载内存页)。
    • majflt/s:每秒发生的主要缺页错误(需要从磁盘加载内存页,对性能影响较大)。
    • VSZ:进程使用的虚拟内存大小(KB)。
    • RSS:进程使用的常驻物理内存大小(KB)。
    • %MEM:进程使用的物理内存百分比。

3. I/O 统计监控

  • 命令pidstat -d 1
  • 关键字段
    • kB_rd/s:进程每秒从磁盘读取的数据量(KB)。
    • kB_wr/s:进程每秒向磁盘写入的数据量(KB)。
    • iodelay:进程因等待块 I/O 而阻塞的时钟滴答数。

4. 上下文切换监控

  • 命令pidstat -w 1
  • 关键字段
    • cswch/s自愿上下文切换次数(通常因等待资源而主动放弃 CPU)。
    • nvcswch/s非自愿上下文切换次数(因时间片耗尽或被更高优先级任务抢占)。

实战技巧

1
2
3
4
5
6
7
8
9
10
11
# 每2秒监控PID为1234的进程的CPU和内存,共监控5次,使用 `-p` 参数跟上 PID(进程ID)
pidstat -ur 2 5 -p 1234

# 监控所有名字包含"java"的进程
pidstat -C java 1

# 默认情况下,`Command` 列只显示简短的进程名。使用 `-l` 可以显示完整的命令和参数:
pidstat -l 1

# 使用 `-t` 参数可以查看进程内部各个线程的资源使用情况,`TGID` 显示主线程ID,`TID` 显示线程ID
pidstat -t 1

与 vmstat、sar 的协同

这三个工具可以形成一个从”全局”到”局部”的黄金组合,帮你层层递进地定位问题:

  • 先用 vmstat 看全局:发现系统 r(运行队列)很高,或 wa(I/O等待)很大,确认存在性能瓶颈。
  • 再用 pidstat 找进程:执行 pidstat -u 1 找出哪个进程在消耗 CPU,或用 pidstat -d 1 定位哪个进程在大量读写磁盘。
  • 最后用 sar 回溯历史:如果问题是间歇性出现的,用 sar 查看历史记录,确认问题发生的时间规律和趋势。

简单来说,vmstat 让你知道”系统出问题了”,而 pidstat 则能帮你回答”到底是哪个程序搞的鬼”。


原文链接:“CPU Spiked—Can You Check?”- A Practical Guide for Linux Admins to Diagnose High CPU Without Panic