linux 内存溢出(OOM)排查指南
答案:dmesg 看 OOM Killer 日志确认谁被杀了,free -h 看内存是否耗尽,ps 找内存大户;常见原因是内存泄漏、cgroup 限制、一次性大分配。临时加 swap/调 overcommit,根治要定位增长进程。
一、确认是否 OOM
# 1. 看 OOM 日志
dmesg | grep -i "killed process"
journalctl -k | grep -i oom
# 2. 典型输出
# "Out of memory: Killed process 1234 (mysqld) total-vm:..., anon-rss:..."
# "Memory cgroup out of memory: Killed process ..." ← cgroup/容器限制被杀的进程退出码通常是 SIGKILL(9)。
二、判断内存到底够不够
free -h # 看 available(不是 used!page cache 会占 used)
ps -eo pid,rss,comm --sort=-rss | head # 内存大户关键:free 的 used 高不代表不够——Linux 会把空闲内存当 page cache,真正要看 available。
三、常见原因与应对
| 原因 | 特征 | 应对 |
|---|---|---|
| 内存泄漏 | 某进程 RSS 持续增长 | 定位泄漏点(内存泄漏排查) |
| cgroup/容器限制 | 日志带 "cgroup out of memory" | 调 cgroup 内存上限、docker stats 观察 |
| 一次性大分配 | OOM 前有超大 malloc | 分批加载、限制并发 |
| 系统整体内存不足 | 全机 available 接近 0 | 加内存/swap、优化常驻进程 |
四、临时缓解
# 加 swap(临时)
fallocate -l 4G /swapfile && chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
# 调 overcommit(谨慎,会改变内存语义)
sysctl vm.overcommit_memory=1根治:overcommit/swap 只是拖延,找到内存增长进程才是正解。
五、常见坑
- 被杀的不一定是"罪魁":OOM Killer 挑 oom_score 高的,可能是受害者;
used高 ≠ OOM:看available;- 容器 OOM ≠ 宿主机 OOM:cgroup 限制内被杀,宿主机内存可能充足;
- OOM 不等于内存泄漏:一次性大分配也会 OOM。
深度入口
- 内存泄漏定位:linux 内存泄漏排查
- 内存统计口径:free 命令详解
- 共享内存统计:smem
- 崩溃信号背景:信号与退出码
FAQ
Q: linux 内存溢出(OOM)怎么排查? A: dmesg 确认 OOM 日志 → free -h 看 available → ps 找内存大户;常见原因:泄漏、cgroup 限制、大分配。
Q: OOM Killer 是什么? A: 内存耗尽时内核选一个进程杀掉释放内存,按 oom_score 挑选;被杀的不一定是元凶。
Q: 怎么看进程被 OOM 杀掉? A: dmesg | grep -i "killed process"、journalctl -k | grep -i oom,退出码常为 9。
Q: linux 内存溢出和内存泄漏的区别? A: 泄漏是持续占用不释放;溢出是内存不足触发 OOM Killer。泄漏是病因、OOM 是症状。
Q: 怎么防止/解决 OOM? A: 临时加 swap/调 overcommit;根治是定位增长进程(泄漏排查)、限制大分配。
Q: cgroup 内存限制导致 OOM 怎么看? A: 日志带 "Memory cgroup out of memory",容器常见;docker stats 观察容器占用。
一句话总结:OOM 排查从 dmesg 的 OOM 日志开始确认"谁被杀了",再 free -h(看 available)判断是否真不够、ps 找内存大户;常见病根是内存泄漏,swap/overcommit 只是拖延,定位增长进程才是根治。