Linux 内存不足排查:从 free 到 OOM Killer 的完整流程
服务器突然变慢、SSH 登录卡顿、进程莫名被杀,很可能就是内存不足。本文以一次真实排查为线索,从 free 到 OOM Killer 走完完整流程。
一、先看 free:别被数字骗了
free -h 是第一步,重点看 available,而不是 free:
$ free -h
total used free shared buff/cache available
Mem: 7.7Gi 6.9Gi 214Mi 512Mi 628Mi 312Mi
Swap: 2.0Gi 1.8Gi 214Mi
Linux 会把空闲内存用作 page cache,所以 free 很小不一定有问题;available 才是真正能分配给新进程的内存。available 持续走低、swap used 不断上涨,才是内存吃紧的信号。
二、找出吃内存的进程
ps aux --sort=-%mem | head -10
top -o %MEM
按 %MEM 排序,重点看 RES(常驻内存)而不是 VSZ(虚拟内存)。再结合应用日志确认:是正常增长,还是内存泄漏——比如请求量不变,RES 却每小时涨几百 MB。
也可以用 smem 看 PSS,把共享库按比例分摊,避免把共享内存重复计算:
smem -s pss | tail -10
三、确认内核视角:/proc/meminfo 与 vmstat
cat /proc/meminfo | grep -E 'MemTotal|MemAvailable|Active|Inactive|Dirty'
vmstat 1 5
关注 si/so(swap 换入换出):持续大于 0 说明系统已经在用磁盘换页,性能会断崖式下跌。Dirty 偏高则说明写缓存积压,可能是磁盘慢拖住了内存回收。
四、OOM Killer:谁被杀、为什么
当内存彻底耗尽,内核的 OOM Killer 会挑一个进程杀掉以自保。先看它杀了谁:
dmesg -T | grep -i 'oom-killer\|killed process' | tail -5
grep -i oom /var/log/messages
日志里会给出被杀进程的进程名、PID 和当时的内存占用,以及 oom_score。想让关键进程(比如数据库主进程)不被优先杀掉,可以调低它的 oom_score_adj:
echo -500 > /proc/<pid>/oom_score_adj
但这只是缓兵之计:被保护的进程不死,OOM Killer 就会去杀别的进程。
五、应急与根治
应急三板斧:重启泄漏的进程释放内存;扩 swap 临时顶一下(swapon);限制失控进程的内存(systemd 的 MemoryMax 或 cgroup):
systemctl set-property nginx.service MemoryMax=2G
根治要回到代码和容量:修复泄漏、给 JVM 这类运行时设合理的 -Xmx 上限、按业务峰值规划内存并配好监控告警(available 低于 10% 就告警)。记住:free 只是起点,available、swap 活动和 OOM 日志连起来看,才是一次完整的内存排查。
- 点赞
- 收藏
- 关注作者
评论(0)