top 显示 load average 12.5,CPU 使用率却只有 30%——这台机器到底是忙还是闲?free 显示 free 列只剩几百 M,服务却跑得好好的——内存到底够不够?监控命令谁都会敲,但输出里的指标读不懂,跑了也白跑。

这是 Linux 命令系列的一篇,承接 Linux 常见命令与工具地图服务器排查那篇 给了 ps/top/free 的基本用法,这篇专讲输出怎么读懂。

ps aux 的 STAT 列:进程现在处于什么状态

ps aux 输出里的 STAT 列是最有信息量、也最少人看懂的一列。第一个字符是进程的主状态,就五种:

1
2
3
4
5
6
7
R    运行中或在运行队列里排队等 CPU
S 可中断睡眠——在等某个事件(网络数据、锁、定时器),绝大多数进程平时都是这个状态
D 不可中断睡眠——通常是卡在磁盘 IO 上;这个状态的进程不响应任何信号,
连 kill -9 都杀不动,只能等 IO 完成或者重启机器
Z 僵尸进程——已经退出了,但父进程还没回收它的退出状态;
杀僵尸本身没用(它已经死了),要处理的是它的父进程
T 被暂停(收到 SIGTSTP/SIGSTOP,比如按了 Ctrl-Z)

主状态后面可能还挂着几个后缀:s 表示会话首进程,l 表示多线程,+ 表示在前台进程组。比如 Ss 读作”睡眠中的会话首进程”(守护进程的典型状态),R+ 读作”正在前台运行”。

排查时有两个状态要特别敏感:一堆进程卡在 D 状态,基本可以断定磁盘 IO 出了问题(盘太慢、NFS 挂了);Z 状态零星一两个无害,大量出现说明父进程的代码有 bug(没有 wait 子进程)。kill 对这两种状态都无能为力,原因在 kill 信号那篇 讲过——D 状态不响应信号,Z 已经死了没什么可杀的。

VSZ 和 RSS:两个”内存占用”差在哪

1
2
USER    PID  %CPU  %MEM     VSZ    RSS  ...  COMMAND
root 12345 15.2 8.4 2150432 342012 ... java -jar app.jar
  • VSZ(Virtual Set Size):进程的虚拟地址空间总大小,包括映射了但从没真正用过的内存、共享库等,通常大得吓人且没什么诊断价值
  • RSS(Resident Set Size):进程实际占用的物理内存

看一个进程”到底吃了多少内存”、判断有没有内存泄漏,盯 RSS——它持续上涨才是真的在吃内存;VSZ 大不代表任何问题。

load average:三个数字和核数一起看

top 第一行和 uptime 都会显示 load average,三个数字分别是最近 1 分钟、5 分钟、15 分钟的平均负载——粗略理解为”平均有多少个任务在使用或等待 CPU(Linux 还包括 D 状态等 IO 的进程)”。

关键在于:这个数字必须和 CPU 核数一起看。load 4.0 对单核机器是严重过载,对 16 核机器只是热身:

1
2
3
4
5
6
7
8
nproc
# 查看 CPU 核数,load average 除以这个数才是"每核负载"
# 经验法则:每核负载持续接近或超过 1,机器就开始排队了

uptime
# load average: 12.50, 8.20, 3.10
# 三个数字还能看趋势:1 分钟 > 15 分钟说明负载正在上升(事情正在恶化),
# 反过来说明高峰已经过去,正在恢复

开头那个问题的答案也在这:load 12.5 但 CPU 只用了 30%,多半是大量进程卡在 D 状态等 IO——load 算上了它们,CPU 却是闲的。这种”高 load 低 CPU”的组合,指向的是磁盘/网络存储瓶颈,不是 CPU 不够。

top:几个必会的交互键

top 进入后是实时刷新界面,这几个键日常够用:

1
2
3
4
5
P    按 CPU 占用排序(默认)
M 按内存占用排序
1 展开显示每个 CPU 核的占用——看负载是不是集中在单核上(单线程瓶颈的典型特征)
k 输入 PID 发信号杀进程
q 退出

一个常见困惑:单个进程 %CPU 显示 250% 不是 bug——多线程进程跑满多个核,百分比按单核 100% 累加,250% 就是占了两个半核。

free 怎么读:available 才是真正可用的

1
2
3
               total        used        free      shared  buff/cache   available
Mem: 15Gi 8.2Gi 1.1Gi 512Mi 6.2Gi 6.7Gi
Swap: 2.0Gi 0Gi 2.0Gi

最容易误读的就是 free 列:它只是”完全没被碰过的内存”。Linux 会把空闲内存尽量拿去做磁盘缓存(buff/cache),提高文件读写速度——这部分在应用需要时随时可以回收。所以:

  • 看 available,不看 free:available = 真正可分配给新程序的内存(含可回收的缓存),free 很小、available 充足是健康状态
  • Swap used 持续上涨才是真缺内存:物理内存实在不够,系统开始把内存页挪到磁盘上,性能会明显劣化——这才是需要处理的信号

组合实战:机器变慢了怎么定位

1
2
3
4
5
6
7
8
9
10
11
12
13
uptime
# 第 1 步:看 load average 和核数的比值,确认是不是真的过载,趋势是升是降

top
# 第 2 步:过载的话按 P 看谁吃 CPU;CPU 不高就怀疑 IO——
# 看进程列表里有没有一片 D 状态

free -h
# 第 3 步:看 available 是否枯竭、Swap 是否被大量使用
# 内存不足会连锁引发 CPU 和 IO 症状(频繁回收、swap 读写)

ps aux | awk '$8 ~ /^D/ {print}'
# 第 4 步:列出所有 D 状态的进程(第 8 列是 STAT),确认卡 IO 的是谁

指标速查表

指标/操作 怎么读
STAT R / S 运行中 / 正常睡眠等事件
STAT D 卡在 IO,不响应信号,成片出现 = 磁盘/存储瓶颈
STAT Z 僵尸,处理它的父进程才有用
VSZ / RSS 虚拟地址空间 / 实际物理内存,查泄漏看 RSS
load average 除以 nproc 核数看每核负载,1/5/15 分钟对比看趋势
高 load + 低 CPU 典型 IO 瓶颈信号,去找 D 状态进程
top 按 1 展开每核占用,识别单线程瓶颈
%CPU > 100% 多线程占多核的正常现象
free 的 available 真正可用内存(含可回收缓存),别看 free 列
Swap used 上涨 物理内存真不够的信号

写到这里

这三个命令的输出各有一个最值得记的点:ps 看 STAT(尤其警惕成片的 D)、load average 要除以核数再下结论、free 看 available 不看 free。把这几个指标读对,”机器慢”就能拆成 CPU、IO、内存三条线分头去查,而不是盯着满屏数字发懵。