服务器变慢、CPU 飙高、磁盘打满,怎么定位?Linux 自带全家桶监控命令:top、vmstat、iostat、free、sar。这篇全部实战演示。

top# 按 1 看每个 CPU 核# 按 P 按CPU排序 按 M 按内存排序 按 q 退出
关键信息解读:
%Cpu(s): us 用户态占用(高说明在跑业务) sy 系统态占用(高说明系统调用多) id 空闲(越低越忙) wa 等待IO(高说明磁盘是瓶颈) si/so 换入换出(大于0说明内存不足)%MEM 那一列是进程内存占用,RES 是实际物理内存
# 只刷新关键进程top -p 12345# 输出重定向到文件排查历史top -b -n 1 > top_snapshot.txt
vmstat 1 5 # 每1秒采样,共5次
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 0 208188 2140 4561260 0 0 0 0 1880 3720 1 1 98 0 0
关键字段:
| 字段 | 含义 | 异常值 |
|---|---|---|
| r | 运行队列长度(等待CPU的进程数) | 持续 > CPU核数 → CPU 不够 |
| b | 阻塞进程数(等待IO) | 持续 > 0 → 磁盘瓶颈 |
| si/so | 交换内存换入换出 | > 0 → 物理内存不足 |
| bi/bo | 块设备读写 | 大 → 磁盘繁忙 |
| cs | 上下文切换次数 | 突然变高 → 检查是否线程过多 |
| wa | CPU 等待 IO | > 30% → 磁盘是瓶颈 |
# 判断是否 CPU 瓶颈vmstat 1# 看 r 列:如果经常 >= CPU核数,说明 CPU 处理不过来# 判断是否内存瓶颈# 看 si/so 列:只要持续大于0,先加内存
free -h
total used free shared buff/cache availableMem: 7.6G 2.1G 208M 845M 5.3G 5.2GSwap: 2.0G 0B 2.0G
注意:available 才是真正可用内存,free 空闲那栏很小但 buff/cache 可以随时释放给业务用,不用慌。
# 清理缓存(慎用,仅测试环境)sync && echo 3 > /proc/sys/vm/drop_caches
iostat -x 1 # 扩展模式,每秒一次
Device r/s w/s rkB/s wkB/s await %utilsda 12.5 18.2 512.3 901.2 8.5 35.2
| 字段 | 含义 | 异常值 |
|---|---|---|
| await | IO 平均等待时间(ms) | > 50ms → 磁盘太慢 |
| %util | 设备忙的时间占比 | > 80% → 磁盘瓶颈 |
| r/s w/s | 每秒读写次数 | 结合 IOPS 判断 |
# 检查是否磁盘瓶颈iostat -x 1# %util 长期 > 80%,或 await > 50ms → 该上 SSD / 加读写分离了
top 只能看当下,排查线上问题需要看历史:
# 查看昨天全天 CPU 使用率sar -u -f /var/log/sa/sa10# 实时查看网络流量sar -n DEV 1# 查看内存历史sar -r -f /var/log/sa/sa10
服务器变慢第一步,按顺序看:1. top → 谁在占 CPU/内存(按 P / 按 M 排序)2. vmstat 1 → 是 CPU(r) 还是磁盘(b/wa) 还是内存(si/so) 瓶颈3. free -h → available 是否告急4. iostat -x → 磁盘 %util / await5. sar → 回看历史,找突变时间点定位到进程后: ps aux | grep <pid> 看进程详情 top -Hp <pid> 看线程占用 jstack <pid> 如果是Java程序,看线程栈
监控命令搭配记忆:
CPU 问题 → top(us/sy)+ vmstat(r)内存问题 → free(available)+ vmstat(si/so)磁盘问题 → iostat(%util/await)+ vmstat(wa)历史问题 → sar 回看
生产环境建议把 sar 采集开着,出问题时先看历史曲线,再结合当下命令定位,效率翻倍。