Linux 内存占用高排查:从 free 到 OOM 的完整路径

举报
云上小栈 发表于 2026/10/25 01:09:47 2026/10/25
【摘要】 先看 free,但别只看 free 的第一行 发现内存占用高时,第一步执行 free -m,重点看第二行 available 而不是第一行 free。Linux 会把空闲内存用于 page cache,第一行 free 数值小是正常现象。真正需要关注的是 available,它表示在不触发 swap 的前提下还能分配给新进程的内存量。如果 available 低于总内存的 10%,例如 16...

先看 free,但别只看 free 的第一行

发现内存占用高时,第一步执行 free -m,重点看第二行 available 而不是第一行 free。Linux 会把空闲内存用于 page cache,第一行 free 数值小是正常现象。真正需要关注的是 available,它表示在不触发 swap 的前提下还能分配给新进程的内存量。如果 available 低于总内存的 10%,例如 16G 机器上低于 1.6G,才需要继续往下排查。

接着查看 cat /proc/meminfo 中的几个关键字段:

  • MemAvailable:可用内存,以它为准
  • Slab 与 SReclaimable:内核对象占用,如果 Slab 很大而 SReclaimable 很小,通常是内核泄漏
  • Dirty:待写回磁盘的脏页,持续超过 200MB 说明磁盘 IO 跟不上
  • SwapUsed:已经在用 swap 说明物理内存确实紧张

按进程排序,定位到具体进程

使用 ps aux --sort=-rss | head -20 按常驻内存排序。注意 RSS 会重复计算共享库和共享内存,多进程程序累计 RSS 往往远大于实际占用,这时用 PSS 更准确:

cat /proc/<pid>/smaps_rollup | grep -E 'Rss|Pss|Private'

如果怀疑是线程泄漏而非进程级增长,看 /proc/<pid>/status 中的 VmRSS 与 Threads 字段随时间的变化。实际环境中常见的是 Java 进程 RSS 持续上涨但堆内存稳定,这属于堆外内存问题,需要用 pmap -x <pid> | sort -k3 -n | tail 看具体是哪个内存段在增长。

坑一:page cache 被误判为内存泄漏

曾遇到一台 32G 的服务器 free 显示只剩 800M,监控告警持续触发,但业务无异常。实际是日志写入量大,page cache 吃掉了 20G。判断方法:执行 echo 3 > /proc/sys/vm/drop_caches(生产环境慎用,会引发 IO 抖动),如果释放后 MemAvailable 大幅回升,说明只是缓存。

根本解决是调整内核参数,让脏页更及时地回写:

vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50

默认 dirty_ratio 为 20,意味着最多允许 20% 内存变成脏页后才强制同步回写,大内存机器上这个值会拖出很大的回写峰值。调到 10 可以降低单次回写量。

坑二:容器内 free 看到的是宿主机内存

在 Docker 容器里执行 free 拿到的是宿主机数据,无法反映 cgroup 限制。容器内存超限时直接触发 OOM Killer,进程无故消失。正确做法是读 cgroup 文件:

cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.current
cat /sys/fs/cgroup/memory.stat | grep -E 'anon|file|slab'

cgroup v1 下对应 memory.limit_in_bytes 和 memory.usage_in_bytes。如果 memory.current 接近 memory.max,需要看 memory.stat 里 anon(匿名页,即进程实际申请的内存)占多少。日志里如果看到 Memory cgroup out of memory: Killed process,用 dmesg -T | grep -i oom 可以查到被杀进程和当时的 total-vm、anon-rss 数值。

排查顺序总结

  • free -m 看 available,低于总内存 10% 再继续
  • /proc/meminfo 区分 Slab、Dirty、Swap 的占比
  • ps 按 RSS 排序,容器内改用 cgroup 文件
  • 进程级异常用 smaps_rollup 的 PSS 确认,避免共享内存重复计算
  • dmesg -T | grep -i oom 确认是否已经发生过 OOM

小结

内存排查的关键是分清 available 与 free、RSS 与 PSS、宿主机与 cgroup 这三组容易混淆的指标。page cache 高不是问题,容器内误读宿主机数据才是真正容易漏掉的坑。按 free、meminfo、进程、cgroup 的顺序逐层收敛,大部分问题能在五分钟内定位到具体的进程或内核参数。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。