Linux 服务器性能监控命令速查与结果解读
适用场景:在 Linux 服务器(物理机 / 虚拟机 / Docker 宿主机)上排查 CPU、内存、磁盘、负载问题;
也适用于共享 / 生产服务器——判断"我跑的任务是否影响了别人、机器还扛不扛得住"。
本文不绑定任何具体业务,命令与解读均可通用。
目录
- 命令速查表
- 总体体检:uptime 与负载 load average
- CPU 使用:mpstat / top / ps / pidstat
- 内存与 Swap:free / vmstat
- 综合快照:vmstat 全列逐项解读
- 磁盘 I/O:iostat
- 容器视角:docker stats
- 历史回溯:sar(可选)
- 常用命令组合与持续记录
- 判断基准表与常见误区
- 实战排查套路
- 参考来源
一、命令速查表
| 命令 | 看什么 | 一句话要点 |
|---|---|---|
uptime |
整机负载 | 看 load,但要除以 CPU 核数才有意义 |
free -h |
内存 | 只看 available,别被 used 吓到 |
vmstat 1 5 |
综合 | CPU/内存/Swap/IO/中断 一屏看全 |
mpstat -P ALL 1 3 |
CPU | 每核占用、iowait、steal |
top |
进程/线程 CPU、内存 | 交互式,P 按 CPU 排、1 看每核 |
ps -eLf |
线程级 | 查一个进程到底开了多少线程 |
pidstat 1 |
单进程 CPU | 精确到进程/线程的 CPU 占用 |
iostat -x 1 |
磁盘 | %util、await 判断磁盘是否瓶颈 |
sar -u -r 1 3 |
历史/当前 | 回溯过去任意时刻的状态(需 sysstat) |
docker stats |
容器 | 每个容器的 CPU/内存/PIDS,LIMIT 判是否限内存 |
nproc / lscpu |
核数 | 解读 load、线程数前的必查项 |
watch -n 2 <cmd> |
持续观察 | 每 2 秒刷新一次,盯变化 |
二、总体体检:uptime 与负载
命令
uptime
示例输出
13:53:44 up 598 days, 23:30, 3 users, load average: 48.15, 37.76, 28.08
输出逐段解释
| 字段 | 含义 |
|---|---|
13:53:44 |
当前系统时间 |
up 598 days, 23:30 |
系统已连续开机 598 天 23 小时(没重启过) |
3 users |
当前有 3 个会话登录 |
load average: 48.15, 37.76, 28.08 |
最近 1 / 5 / 15 分钟的平均负载 |
load average 怎么理解
- 负载 = 平均有多少个任务"正在用 CPU 或在排队等 CPU"(还包括少量不可中断的磁盘等待任务)。可粗略理解为"收银台前的排队人数"。
- 关键:负载没有按核数归一化。N 核机器上 load = N 表示"每个核刚好一直有人用"。
- 判断方法:负载 ÷ 核数。
load < 核数(如 128 核机 load=48):还很空,CPU 只用了约 3 成;load ≈ 核数:CPU 已被占满,开始排队;load 持续 > 核数:任务在排队等 CPU,系统过载。
先查核数再解读:
nproc # 逻辑核数(最直接)
lscpu | grep -E '^CPU\(s\)|Core|Thread|Socket' # 更详细的核数信息
三个时间点的含义
48.15, 37.76, 28.08 中 1 分钟 > 5 分钟 > 15 分钟 = 负载正在上升(刚才有任务启动或流量变大);
反之 1 分钟 < 15 分钟 = 负载在回落。这能帮你判断"是刚发生的还是长期现象"。
三、CPU 使用:mpstat / top / ps / pidstat
3.1 mpstat —— 每个核都在干什么
来自 sysstat 包,CentOS/RHEL:yum install sysstat;Ubuntu:apt install sysstat。
mpstat 1 5 # 每 1 秒采样 1 次,共 5 次,看"全部核平均"
mpstat -P ALL 1 3 # 逐核看(-P ALL = 所有 CPU)
示例输出
13时53分45秒 all 36.29 0.00 2.45 0.00 0.46 0.20 0.00 0.00 0.00 60.61
13时53分46秒 all 33.97 0.00 3.09 0.00 0.56 0.23 0.00 0.00 0.00 62.16
平均时间: all 34.05 0.00 2.43 0.00 0.49 0.22 0.00 0.00 0.00 62.79
列含义
| 列 | 含义 | 正常 | 异常信号 |
|---|---|---|---|
%usr |
跑用户程序(业务/应用/脚本)的时间占比 | 看业务 | 持续很高 = 应用在算 |
%sys |
跑内核代码(系统调用、内存管理等)占比 | < 10% | 很高 = 内核忙(如大量中断/调度) |
%iowait |
CPU 空等磁盘 I/O 的时间占比 | 低 | 持续高 = 磁盘是瓶颈(应用在等读盘/写盘) |
%irq / %soft |
硬件 / 软件中断处理占比 | 低 | 高 = 网卡/磁盘中断风暴 |
%steal |
虚拟机的 CPU 时间被宿主机抢走的占比 | 0~1% | 持续 > 5% = 宿主机超卖,性能被邻居拖累 |
%idle |
空闲占比 | 越高越好 | 长期为 0 = CPU 满负荷 |
这些百分比是相对全部核的总时间(
all行),不是"占满几个核"。
例如 128 核机%usr=34%、%idle=62%≈ 128×0.38 ≈ 48 核在忙,其余空闲。
3.2 top —— 进程级别找"谁在吃 CPU"
top # 进入交互界面
top -bn1 # 非交互,只输出一次就退出(适合脚本/日志)
示例输出(头部)
top - 03:12:38 up 1:53, 3 users, load average: 1.72, 0.62, 0.25
Tasks: 198 total, 1 running, 197 sleeping, 0 stopped, 0 zombie
%Cpu(s): 29.2 us, 22.0 sy, 0.0 ni, 48.5 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
MiB Mem : 7697.8 total, 3672.6 free, 576.6 used, 3448.5 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 6838.4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
17038 root 20 0 8476 2984 1984 D 3.7 0.0 0:00.77 dd
16979 root 20 0 0 0 0 D 1.3 0.0 0:00.14 kworker...
关键行解释
| 行/列 | 含义 |
|---|---|
| 第 1 行 | 同 uptime(时间 / 运行时长 / 负载) |
Tasks: 行 |
进程总数;running 正在跑、sleeping 睡眠、zombie 僵尸进程(应警惕) |
%Cpu(s): 行 |
整机 CPU 分布,列含义同 mpstat(us=用户、sy=内核、wa=等磁盘、st=被抢) |
MiB Mem/Swap: 行 |
同 free,末尾 avail Mem 就是 available |
PID USER PR NI |
进程号 / 用户 / 优先级 |
VIRT RES SHR |
虚拟内存 / 实际占用的物理内存 RES / 共享内存 |
S |
状态:R运行、S睡眠、D不可中断(常在等磁盘)、Z僵尸 |
%CPU |
该进程相对"1 个核"的占用:100% = 占满 1 核;多线程进程可 >100%(如 400% = 4 核) |
%MEM |
占物理内存百分比(按 RES 算) |
TIME+ |
累计消耗的 CPU 时间(可识别偷跑的常驻任务) |
COMMAND |
命令名 |
top 常用交互键
| 键 | 作用 |
|---|---|
P |
按 CPU 降序(默认就是) |
M |
按内存降序 |
1 |
展开 / 收起每个核的占用 |
H |
切换线程级视图(看多线程进程内部) |
c |
显示完整命令行 |
q |
退出 |
注意
%CPU的意义:是相对 1 个核的百分比。容器监控里docker stats也沿用这个口径,
所以一台 128 核机器上出现4000%表示"用了约 40 个核",不是占了机器 4000%。
3.3 ps —— 线程级 / 内存大户排查
ps -eLf # 每个进程的每一行是一个"线程"(可数线程数)
ps -eLf | wc -l # 系统总线程数
ps aux --sort=-%mem | head -n 15 # 内存占用最高的 15 个进程
ps aux --sort=-%cpu | head -n 15 # CPU 占用最高的 15 个进程
ps -eLf 输出的 NLWP 列 = 该进程的线程数;LWP = 线程 ID。
常用于确认"一个进程为什么占了很多 CPU/内存"或"线程是否异常增多(泄漏)"。
3.4 pidstat —— 精确到进程/线程的 CPU
pidstat 1 5 # 每秒一次,看每个进程的 CPU
pidstat -t 1 3 # -t 看每个线程(同 top 的 H 视图)
pidstat -r 1 3 # -r 看内存
四、内存与 Swap:free / vmstat
4.1 free —— 内存体检表
free -h # -h 人类可读单位(G/M);-m 按 MB 显示更精确
示例输出
total used free shared buff/cache available
Mem: 251Gi 198Gi 17Gi 8.1Gi 35Gi 42Gi
Swap: 63Gi 40Gi 23Gi
列含义
| 列 | 含义 | 要点 |
|---|---|---|
total |
物理内存总量 | |
used |
已被程序占用的 | 别被它吓到,见下方误区 |
free |
完全没人用的 | Linux 会尽量把它拿来当缓存,所以通常很小 |
shared |
共享内存(tmpfs 等) | |
buff/cache |
磁盘读写缓存 | 需要时可随时让出给程序 |
available |
真正还能给新程序用的内存 | 只看这一列 ≈ free + 可回收 cache |
| Swap 行 | 硬盘当内存的"备用内存" | used 大 = 历史/当前内存吃紧过 |
结论口诀:
used大 ≠ 内存不足;available持续下降才是警报。
Swap 的used很大会拖慢性能(硬盘比内存慢几个数量级),但只要"此刻没有在换入换出"(见 vmstat 的 si/so),影响可控。
4.2 vmstat —— 内存与 Swap 是否在折腾
vmstat 1 5
见下一节的完整解读;内存相关的关键列是:
| 列 | 含义 | 判断 |
|---|---|---|
swpd |
当前被换到 swap 的量(KB) | 存量高但稳定通常无害 |
si / so |
每秒从磁盘换入内存 / 从内存换出磁盘的量 | 长期 > 0 = 内存不足,在疯狂 swap,性能暴跌 |
si/so 都是 0 = 内存虽然紧但没有活跃交换,属于"紧张但不恶化"。
五、综合快照:vmstat 全列逐项解读
vmstat 一条命令覆盖 进程/内存/Swap/IO/中断/CPU,适合第一眼定位"瓶颈在 CPU 还是磁盘还是内存"。
vmstat 1 5 # 每 1 秒输出 1 次,共 5 次(次数可改)
vmstat 2 # 每 2 秒一次,Ctrl+C 退出
示例输出
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
43 0 42386452 18717224 1068 37089000 0 0 0 0 530 456231 32 3 65 0 0
45 0 42386452 18717724 1068 37087680 0 0 0 0 530 37043 34 6 60 0 0
分组解读
procs(进程/线程队列)
| 列 | 含义 | 判断 |
|---|---|---|
r |
正在跑 + 排队等 CPU 的任务数 | 结合核数看:r ≈ 忙碌核数 → 平衡;r 持续远超核数 → CPU 排队超订 |
b |
阻塞在磁盘 I/O 上的任务数 | 长期 > 0 = 磁盘瓶颈,任务都在等读盘/写盘 |
经验:
r > 核数 + 3偏高、r > 核数 + 5很高、r > 核数 + 10异常(参考社区经验)。
但 128 核大机器上r=45若忙核约 48,二者匹配,属正常并行,不是过载。
memory(内存)
| 列 | 含义 |
|---|---|
swpd |
换出到 swap 的量(KB) |
free |
空闲内存(不含缓存) |
buff / cache |
缓冲区 / 文件缓存(可回收) |
swap(换页) —— 最重要的一对
| 列 | 含义 | 判断 |
|---|---|---|
si |
每秒从磁盘换入内存(KB/s) | 长期 > 0 = 物理内存不够 |
so |
每秒从内存换出到磁盘(KB/s) | 同上 |
io(块设备读写)
| 列 | 含义 | 判断 |
|---|---|---|
bi / bo |
每秒从磁盘读/写的块数(1 块 ≈ 1KB 量级) | 结合 CPU 的 wa 看磁盘压力 |
system(系统)
| 列 | 含义 | 判断 |
|---|---|---|
in |
每秒中断次数 | 异常飙高查网卡/磁盘中断 |
cs |
每秒上下文切换次数(线程之间切来切去) | 高 = 线程多/并行活跃;异常高(如几十万)可能锁竞争过度 |
cs高不一定坏:多进程多线程的并行任务(如大数据计算)自然切换频繁。
只有当"cs 极高 + us 却不高"时才要怀疑线程空转/锁竞争。
cpu(最后 5 列,含义同 mpstat)
| 列 | 含义 |
|---|---|
us |
用户程序占比 |
sy |
内核占比 |
id |
空闲占比 |
wa |
空等磁盘 I/O 占比 |
st |
被虚拟机管理程序偷走占比 |
第一个坑:
vmstat 1 5的第一行是"开机以来的平均值",不代表当前状态,要看从第二行起的数据。
第二个坑:wa高且bi/bo也高 → 磁盘在忙;wa高但bi/bo低 → 可能是大量进程同时争抢、或外接存储(网络盘)延迟。
六、磁盘 I/O:iostat
iostat -x 1 5 # -x 扩展模式;每 1 秒 1 次共 5 次
iostat -x -d sda 1 # 只看指定盘
示例输出
Device r/s w/s rkB/s wkB/s await %util
sda 12.50 45.60 1024.0 4096.0 8.20 45.30
关键列
| 列 | 含义 | 判断 |
|---|---|---|
r/s w/s |
每秒读写请求数 | |
rkB/s wkB/s |
每秒读写数据量 | |
await |
每个请求平均等待时间(毫秒) | 高 = 盘慢或排队 |
%util |
磁盘忙碌占比 | 接近 100% = 磁盘已到吞吐上限,是瓶颈 |
注意:
%util对机械盘/SSD/阵列/云盘的"饱和点"不同,需结合await一起看。
七、容器视角:docker stats
共享 Docker 宿主机上,除了看整机,还要看每个容器占了什么、有没有设限制。
docker stats # 实时刷新所有容器
docker stats --no-stream # 只看当前一屏就退出(适合脚本)
docker stats --no-stream ocr-extract # 只看某个容器
docker stats --no-stream --format "{{.Name}} CPU={{.CPUPerc}} MEM={{.MemUsage}} PIDS={{.PIDs}}"
示例输出
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % PIDS
347bd454f4bd my-app 2924.40% 3.782GiB / 251.8GiB 1.50% 61
列含义
| 列 | 含义 | 要点 |
|---|---|---|
CPU % |
相对 1 个核 = 100% | 400% = 用了 4 个核;要占整机几成需 ÷ 宿主机核数 |
MEM USAGE / LIMIT |
已用 / 上限 | LIMIT = 宿主机总内存 = 该容器没设内存上限(危险);LIMIT 是 10GiB 之类 = 设了限制 |
MEM % |
已用占上限比例 | |
PIDS |
该容器内进程 + 线程总数 | 可快速判断"容器里到底开了多少线程" |
判断"我的容器是否影响别人"三步法
- 跑之前记基线:
uptime、free -h、docker stats --no-stream; - 跑的时候对比:
mpstat 1 5(整机 idle 别掉到太低)、free -h(available 别持续下降)、vmstat 1 5(si/so 别起来)、再docker stats看邻居容器 CPU 有无异常变化; - 收尾:确认机器恢复了基线水平。
CPU 层面 Docker 用配额(
--cpus/compose 的cpus:)设"时间上限",超了只会节流自己(变慢),一般不会抢别人;
真正会波及全机的是内存——不设mem_limit的容器可以吃满宿主机内存、触发全局 swap/OOM,这才是共享机大忌。
八、历史回溯:sar(可选)
sar 属于 sysstat 包,默认每 10 分钟自动记录一次历史,可回溯"当时发生了什么"。
sar -u 1 3 # CPU:每秒 1 次共 3 次
sar -u -f /var/log/sa/sa15 # 回看 15 号那天的 CPU(文件名对应当天日期)
sar -r 1 3 # 内存
sar -S 1 3 # Swap
sar -b 1 3 # 磁盘 I/O
sar -q # 负载队列
sar -n DEV 1 3 # 网卡流量
列含义与 vmstat/mpstat 一致,只是多带时间戳,方便对齐故障时间点。
九、常用命令组合与持续记录
盯一段时间的负载、跑完看峰值,推荐把输出落到文件:
# 每 5 秒记一次 CPU/内存快照,Ctrl+C 停止后查看
while true; do date +%F\ %T; mpstat 1 1 | tail -1; free -h | sed -n '2p'; done | tee perf.log
# 每 10 秒记一次某容器的 CPU/内存
while true; do date +%T; docker stats --no-stream --format "CPU={{.CPUPerc}} MEM={{.MemUsage}} PIDS={{.PIDs}}" my-app; sleep 10; done | tee container.log
实时刷新用 watch:
watch -n 2 'free -h && uptime' # 每 2 秒刷新内存与负载
watch -n 5 'docker stats --no-stream' # 每 5 秒刷新容器
十、判断基准表与常见误区
判断基准速查(经验值,按需微调)
| 指标 | 正常 | 注意 | 危险 |
|---|---|---|---|
| load ÷ 核数 | < 0.7 | 0.7 ~ 1.0 | 持续 > 1.0 |
| %usr + %sys | < 70% | 70 ~ 90% | 接近 100% 且持续 |
| %iowait / 磁盘 %util | < 30% | 30 ~ 60% | > 60% 持续(磁盘瓶颈) |
| %steal(虚拟机) | 0~1% | 2~5% | 持续 > 5%(宿主机超卖) |
| available 内存 | > 30% total | 10~30% | < 10% 且持续下降 |
| si / so | 0 | 偶发 | 长期 > 0(在 swap,性能暴跌) |
| r(运行队列) | ≤ 核数 | 核数~核数+5 | 持续 > 核数+10 |
| b(阻塞任务) | 0 | 少量 | 持续 > 0(等磁盘) |
| 僵尸进程 | 0 | 少量 | 持续增长(父进程没回收) |
常见误区
- "free 的 used 198G,内存爆了!"
→ 错。要缓存能吐出来,看available才准。 - "load 48 太高了!"
→ 错。48 核机器 load 48 = 满载;128 核机器 load 48 = 只用了 3 成。必须除以核数。 - "docker stats 显示 2924%,占满机器了!"
→ 错。那是"占了 29 个核",128 核机器才用了 2 成多。CPU% 是相对 1 核的。 - "多线程进程 400%,机器要冒烟了"
→ 400% = 4 个核同时算,先看机器总共几核再说。 - "%iowait 高 = CPU 不行"
→ 相反,wa高说明 CPU 在空等磁盘,瓶颈是磁盘。 - "si/so 大数字可怕" —— 看的是"每秒速率",持续为 0 就没事;
swpd存量高只是历史。 - "vmstat 第一行就是当前状态"
→ 第一行是开机累计平均,看第二行起的数据。
十一、实战排查套路
场景 A:CPU 高,找"谁在吃"
top -bn1 | head -n 20 # 找大 %CPU 进程
ps -eLf | grep <PID> # 看该进程开了多少线程
pidstat -t 1 5 | grep <PID> # 看具体哪个线程在烧 CPU
场景 B:内存不足 / 疯狂 swap
free -h # available 是否告急
vmstat 1 5 # si/so 是否长期 > 0
ps aux --sort=-%mem | head # 谁占内存最多
场景 C:慢得像卡死,分不清瓶颈
vmstat 1 5 # 一屏定方向:
# b>0 或 wa 高 → 磁盘问题 → iostat -x 1
# r 远大于核数 → CPU 排队 → top 找进程
# si/so > 0 → 内存不足 → free -h + 找大内存进程
场景 D:共享/生产机上,确认自己没影响别人
# 跑前基线
uptime; mpstat 1 3 | tail -1; free -h; docker stats --no-stream
# 跑中(自己 + 邻居)
while true; do date +%T; mpstat 1 1 | tail -1; docker stats --no-stream --format "{{.Name}} {{.CPUPerc}} {{.MemUsage}}"; sleep 5; done
# 观察重点:整机 idle 别掉太低;available 别持续跌;邻居容器 CPU 无明显突增;
# si/so 保持 0;docker stats 里邻居 LIMIT=宿主机内存的裸奔容器尤其要留意(你的内存上涨会挤到它们)。
十二、参考来源
- Baeldung – Get Overall CPU Usage on Linux
- Microsoft Learn – Troubleshoot CPU performance issues in Linux
- Microsoft Learn – Collect performance metrics from a Linux system
- Linux Vox – Understanding Load Average vs. CPU Usage
- Oracle Learn – Monitor system resources on Linux
- man7.org – vmstat(8)、uptime(1)
- SUSE System Analysis and Tuning Guide
- CSDN – Linux 服务器的性能监控常用命令及工具