dmesg 是排查 oom killer 杀进程的首选入口,因其日志直写内核环形缓冲区,不经过用户态日志系统;dmesg -t | grep -a5 -b2 "killed process" 可获取含内存快照的完整上下文,关键看 score、anon-rss 和 swap 状态。

直接看 dmesg,重点找 Killed process 和 Out of memory 这两行——90% 以上的内核强制杀进程都源于 OOM Killer,而它只写进内核日志,不进 syslog 或 journal。
为什么 dmesg 是第一入口?
OOM Killer 是内核模块,它的动作不会走用户态日志系统(如 rsyslog 或 journald),而是直接刷到内核环形缓冲区。哪怕你开了 auditd 或配置了完整 journal,Killed process XXX 这类记录也只出现在 dmesg 输出里。
-
journalctl -k看的是内核日志的“镜像”,但可能被截断或延迟;dmesg -T才是原始、实时、带时间戳的真数据 - 如果系统启用了
kmsg日志持久化(如 systemd 默认关闭),/dev/kmsg可能比dmesg更全,但普通排查没必要绕路 - 别依赖
grep "killed process" /var/log/syslog:Ubuntu/Debian 可能转发部分记录,CentOS/RHEL 默认不转,且转发有延迟,容易漏掉关键上下文
dmesg -T | grep -A5 -B2 "Killed process" 怎么读?
这一行命令不是为了“找到被杀进程”,而是为了提取出带内存快照的完整上下文。典型输出长这样:
[Thu Jul 10 00:42:13 2026] Out of memory: Kill process 18923 (java) score 987 or sacrifice child [Thu Jul 10 00:42:13 2026] Killed process 18923 (java) total-vm:12456780kB, anon-rss:11890232kB, file-rss:124kB, shmem-rss:0kB [Thu Jul 10 00:42:13 2026] pgpgin 24567890, pgpgout 23456789, swapents 0, swaptotal 0, swapfree 0
关键字段含义:
-
score 987:OOM 分数,越高越容易被选中;oom_score_adj值 + 内存占比共同决定 -
total-vm:进程虚拟内存总量(单位 kB),Java 应用常超 10G,但不等于真实压力 -
anon-rss:真正占用物理内存的匿名页(堆、栈、DirectByteBuffer 等),这才是 OOM 的罪魁 -
swapents/swaptotal全为 0:说明没开 swap,物理内存耗尽即触发 OOM
查不到 Killed process?可能根本不是 OOM
如果 dmesg 里没有匹配项,说明进程不是被内核主动杀的,得换方向:
- 检查是否被
kill -9:查auditctl -a always,exit -F arch=b64 -S kill(需提前开启 auditd);没开就基本没法追溯 - 看退出码:
echo $?若为137,几乎可断定是SIGKILL(9),但无法区分是手动 kill 还是 OOM;若为139,则是SIGSEGV,属于程序崩溃,非内核强制杀 - 容器环境要额外看:
docker inspect CONTAINER_ID | grep -i oom或crictl inspect POD_ID,runtime 层可能拦截并伪造退出原因
真正难的不是找到那行 Killed process,而是看懂它后面跟着的 Mem-Info 快照和 anon-rss 数值——这决定了你是该加内存、调 JVM 参数,还是去查 Java 里的 ByteBuffer.allocateDirect() 泄漏。日志只告诉你“谁倒下了”,不告诉你“子弹从哪来”。











