ElIauk

Linux 磁盘、内存、CPU 排查命令

先看整体,再钻细节 服务变慢时,最忌讳上来就 top 看一眼然后猜。CPU 高、内存高、磁盘满、IO 卡住,表现都是"接口慢",但处理方式完全不同。正确的顺序是:先看整体负载和资源水位,判断瓶颈在 CPU、内存还是磁盘,再定位到具体进程和线程。 这篇文章按 CPU、内存、磁盘三块整理常用命令,最后给

评论
Linux 磁盘、内存、CPU 排查命令

先看整体,再钻细节

服务变慢时,最忌讳上来就 top 看一眼然后猜。CPU 高、内存高、磁盘满、IO 卡住,表现都是"接口慢",但处理方式完全不同。正确的顺序是:先看整体负载和资源水位,判断瓶颈在 CPU、内存还是磁盘,再定位到具体进程和线程。

这篇文章按 CPU、内存、磁盘三块整理常用命令,最后给一条完整的排查路径。命令不用背,知道每个工具回答什么问题就行。

CPU 与负载

uptime
# 12:00:00 up 30 days, load average: 8.20, 6.10, 4.30

nproc        # 逻辑核数
top          # 动态观察,按 1 展开每个核,按 P 按 CPU 排序

load average 的三个数字是 1 分钟、5 分钟、15 分钟的平均负载。判断标准是和核数比较:4 核机器 load 长期在 8 以上,说明任务在排队;但 load 高不一定是 CPU 忙,也可能是大量进程卡在 IO 上。

top 里重点看这几列:

  • %us:用户态 CPU,业务代码消耗;
  • %sy:内核态 CPU,系统调用、上下文切换;
  • %wa:等待 IO 的 CPU 比例,高说明磁盘是瓶颈;
  • %si:软中断,网络流量大时可能升高。

进一步拆到每个核和每个进程:

mpstat -P ALL 1          # 每个核的使用率,看是否单核打满
pidstat -u 1 5           # 每 1 秒采样,共 5 次,按进程看 CPU
pidstat -w 1 5           # 上下文切换

单核打满、其他核空闲,常见于 GC 线程、单线程任务、锁竞争。这种情况加机器没用,得看代码。

内存

free -h
#               total        used        free      shared  buff/cache   available
# Mem:           15Gi       9.0Gi       0.5Gi       0.2Gi       6.0Gi       5.8Gi

cat /proc/meminfo | head -20

看内存不要只盯 free。Linux 会把空闲内存拿去做页缓存,free 很小是正常的,关键看 available——它表示"还能给新进程用多少"。available 长期低于总量的 10%,才需要警惕。

如果怀疑内存泄漏或者被 OOM 杀过进程:

dmesg -T | grep -i "out of memory"
journalctl -k | grep -i oom

被 OOM Killer 选中的进程会在内核日志里留下记录,包括进程名、PID 和当时的 memory 使用情况。容器环境还要看 docker inspect 里的 OOMKilled。

磁盘与 IO

df -h                 # 分区使用率
df -i                 # inode 使用率
du -sh /data/* | sort -rh | head -20
iostat -x 1           # 磁盘 IO,重点看 %util、await、aqu-sz
iotop -oP             # 按进程看 IO

df 显示磁盘满但 du 加起来对不上,通常是文件被删除但进程还持有句柄:

lsof +L1              # 列出已删除但仍被打开的文件

重启对应进程或者清空句柄,空间才会释放。inode 满也会导致"写不进去",df -h 看起来还有空间,df -i 已经 100%,常见于大量小文件。

iostat -x 1 里关注三个指标:%util 接近 100% 说明磁盘饱和;await 是平均等待时间,机械盘超过 20ms、SSD 超过 5ms 就偏慢;aqu-sz 是排队长度,持续大于 2 说明请求在排队。

常见坑

1. 把 load 高当成 CPU 高

load 统计的是可运行和不可中断状态的进程数,IO 阻塞(D 状态)也会计入。load 很高但 CPU 空闲,先看 vmstat 的 b 列和 %wa。

2. 看 free 判断内存不足

free 小、buff/cache 大是正常现象。判断内存压力看 available,或者看有没有发生 swap(vmstat 的 si、so 持续非零)。

3. 被 top 的 %CPU 误导

top 里单个进程的 %CPU 可以超过 100%,因为是所有核累计。一个进程 400% 在 8 核机器上只占一半,不要看到超过 100 就以为异常。

4. 只采样一次就下结论

CPU、IO、内存都是动态的。top 按一次 q 退出看到的只是一个瞬间,用 vmstat 1、pidstat 1 连续观察几十秒,才能看出趋势。

5. 容器里看到的是宿主机数据

容器默认共享宿主机的 /proc,top、free 显示的是整台机器的资源。要看容器自身的限制,用 docker stats 或者 cgroup 文件。Kubernetes 环境同理。

6. df 和 du 不一致

前面说过,删除未释放的文件、挂载覆盖、namespace 隔离都会导致两者不一致。先 lsof +L1,再检查挂载点。

7. iostat 第一次输出不准

iostat 第一次输出的是自开机以来的平均值,不是当前值。加 1 参数后看第二次及以后的结果。

排查步骤

一条比较稳的路径:

  1. uptime 和 top 看整体负载、CPU、内存水位;
  2. vmstat 1 区分是 CPU 忙、IO 等待还是内存交换;
  3. CPU 高用 pidstat -u 定位进程,再 top -Hp <pid> 定位线程;
  4. IO 高用 iostat -x 确认哪块盘,iotop -oP 定位进程;
  5. 内存紧张看 dmesg 有没有 OOM,free -h 看 available;
  6. 磁盘写不进去看 df -h、df -i、lsof +L1;
  7. Java 应用把线程 ID 转成十六进制,去 jstack 里找对应栈。

命令只是工具,关键是先判断瓶颈类型,再往下钻。最怕的是一上来就重启,把现场毁了。

参考

评论

推荐阅读

订阅邮件

订阅更新,及时收到最新文章。

作者