在 Linux 服务器上第一回遇见 OOM(Out of Memory),往往是从一行 "Killed" 开始的——你明明没手动杀进程,Java 服务却凭空消失,SSH 偶尔还能卡到连命令都敲不动。我当年第一次碰到这情况,第一反应是系统被人入侵了,后来翻内核日志才明白,这是 Linux 在内存耗尽时启动的自杀式保护机制。
这篇指南不会停留在"OOM 就是内存不够"这种正确废话上。我会从新手最容易困惑的几个点讲起:OOM 到底怎么触发、日志去哪看、内核为什么专杀"好人"、线上出问题怎么快速定位,最后给出从应急到治本的一整套处置顺序。每个环节都会附带我实际踩过坑之后的判断逻辑,尽量让零基础的人也能照着手动一遍。
1. 从"进程突然消失"说起:OOM 到底是什么
1.1 那句让新手慌乱的 "Killed" 是怎么来的
Linux 内核里有个模块叫 OOM Killer,全称 Out Of Memory Killer。它的职责是:当系统物理内存和 swap 加在一起都不够用,内核又没法再回收出新的内存页时,它会主动挑选一个进程,直接发送 SIGKILL 信号把它杀掉,从而释放内存,保住整个系统还能运转。
这个机制可以类比成宿舍电路跳闸——宿管阿姨没法让所有人都留下,只能挑一个用电大户请出去,其他人才能正常开灯。问题在于,宿管阿姨挑人的标准不一定符合你的预期,她看的是"谁用电多",而不是"谁更重要"。
关键点在于:被杀进程不会收到任何"优雅退出"的机会,SIGKILL 信号也没法被捕获和拦截。所以你在应用日志里往往什么都看不到,只会在系统日志里留下一条类似这样的痕迹:
code复制Out of memory: Killed process 31800 (java) total-vm:2457600kB, anon-rss:1536000kB, file-rss:0kB, shmem-rss:0kB
看到这行日志,基本就可以确认是 OOM 了,跟什么病毒、黑客、数据库崩溃都没关系。
1.2 内存明明没用满,为什么还是 OOM
新手最容易懵的地方在于:我明明跑着 free -h,内存还剩好几 G,怎么系统就 OOM 了?
这里有一个重要的概念区分:Linux 使用是"乐观分配"的内存策略(overcommit)。一个进程调用 malloc() 申请虚拟内存时,内核通常会直接批准,并不立即分配真实的物理内存页。真正物理页的占用发生在进程实际写入数据的那一刻。
所以会出现这种情况:系统里所有进程累计声明的虚拟内存(Committed_AS)已经大大超过物理内存 + swap 的总和,但物理内存表面上还有余量。当某次写入请求需要一个真实物理页,而内核回收了一圈发现实在挤不出来,OOM 就会触发。
打开 /proc/meminfo 能看到两个关键字段:
CommitLimit:内核允许的累计内存提交上限,通常等于swap + 物理内存 × overcommit_ratioCommitted_AS:当前系统已经"承诺"出去的虚拟内存总量
如果 Committed_AS 长期接近甚至超过 CommitLimit,说明系统已经处于随时可能 OOM 的紧绷状态。另外我强烈建议新手养成看 MemAvailable 而不是 MemFree 的习惯。MemFree 只是完全空闲的物理页,而 MemAvailable 还包括可回收的 page cache、slab 等,它才是系统真正"还能再分配多少"的底线。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 第一现场:OOM 日志去哪找、怎么看
2.1 三条日志路径,总有一条能看到
OOM 发生时,内核会在环形缓冲区写下日志记录。查看方式有三种,我按通用程度排序:
bash复制# 方式一:dmesg 查看内核环形缓冲区(推荐,注意需要 root)
sudo dmesg -T | grep -iE "out of memory|oom-killer|killed process"
# 方式二:journalctl 查看本次或上次启动的内核日志
sudo journalctl -k -b | grep -iE "out of memory|oom-killer|killed process"
sudo journalctl -k -b -1 | grep -iE "out of memory|oom-killer|killed process"
# 方式三:查看传统日志文件
# CentOS/RHEL 用 /var/log/messages
sudo grep -iE "out of memory|oom-killer|killed process" /var/log/messages
# Ubuntu/Debian 用 /var/log/kern.log
sudo grep -iE "out of memory|oom-killer|killed process" /var/log/kern.log
`
