dmesg -t | grep -i "killed process"是诊断oom killer的首选方法,因其直接读取内核ring buffer中唯一一次的关键记录,-t提供可读时间戳,且需root权限才能在rhel 8+/centos 8+等系统查看完整日志。

直接看 dmesg -T | grep -i "killed process",有输出基本就是 OOM Killer 干的;没输出不等于没发生,可能是日志被刷掉、权限受限,或根本不是 OOM 导致的“Killed”。
为什么优先用 dmesg -T 而不是 journalctl -k
dmesg 读的是内核 ring buffer,OOM Killer 触发时只写一次关键记录,这是唯一原样保留的原始证据。journalctl -k 虽然内容来源相同,但依赖 journald 持久化机制——如果服务未启用持久存储、日志轮转过快,或系统刚重启,journalctl -k 可能为空或不全。-T 参数必须加,否则时间戳是内核启动后的相对秒数(如 [ 12345.678901]),没法和业务告警时间对齐。
- 必须用 root 权限:RHEL 8+/CentOS 8+ 等系统默认开启
kernel.dmesg_restrict=1,非 root 用户看不到完整内容 - ring buffer 是环形的,容量固定(通常几 MB),旧日志会被新日志覆盖;OOM 发生在几天前的话,
dmesg很可能已丢失 -
journalctl -k更适合结合时间范围查历史(比如--since "2 hours ago"),但不能替代dmesg的“第一手现场感”
dmesg 输出里哪些字段真正有用
典型行:[Wed Sep 25 14:32:11 2026] Killed process 12345 (java) total-vm:12345678kB, anon-rss:8765432kB, file-rss:12345kB。关键不是 total-vm(虚拟内存,JVM 类应用常虚高),而是 anon-rss:它代表进程实际占用的物理内存页(不含 page cache 和文件映射),单位 kB。如果这个值接近机器总内存(比如 64G 机器上出现 anon-rss:62000000),基本坐实它是压垮系统的最后一根稻草。
-
score或oom_score字段(如Kill process 12345 (java) score 894)反映内核打分结果,分数越高越容易被选中,但不是单纯看内存大小——oom_score_adj值、是否 root、运行时长都会影响 - 若看到
Memory cgroup out of memory,说明是容器或 systemd service 的内存限额触发,不是整机内存耗尽;得去对应 cgroup 路径查memory.usage_in_bytes和memory.limit_in_bytes - 单靠这一行不够,OOM 是个过程,前后几秒的日志才揭示原因:重点扫
page allocation failure、low memory、free:(显示各 zone 剩余页数)、slab_reclaimable等提示
查不到 "killed process" 时该试什么
别急着下结论说“没发生 OOM”。先检查三件事:
- 运行
sudo sysctl kernel.dmesg_restrict,若返回1,说明权限被锁死;临时放开:sudo sysctl kernel.dmesg_restrict=0 - 查传统日志文件:
sudo grep -i "out of memory\|killed process" /var/log/messages(RHEL/CentOS)或/var/log/syslog(Debian/Ubuntu);部分发行版会由 rsyslog 把 dmesg 内容转存到这些文件 - 用
journalctl -k --grep="oom\|out.of.memory" --since="24 hours ago"扩大时间范围再试;注意--grep是 journalctl 3.5+ 才支持的参数,老版本得用管道:journalctl -k --since "24 hours ago" | grep -i "oom"
确认被杀进程后,怎么快速定位“谁才是真凶”
被杀进程往往只是替罪羊。比如一个 python3 进程因 anon-rss:3.2G 被杀,但它可能只是加载了某个大模型权重,而真正持续申请内存的是上游的 nginx worker 或数据库连接池。这时候要:
- 立刻执行
ps -eo pid,comm,%mem,vsz,rss --sort=-%mem | head -10,看当前内存大户是谁;注意%mem是按物理内存占比算的,比 RSS 绝对值更可比 - 查被杀进程当时的
oom_score_adj:cat /proc/12345/oom_score_adj(替换 PID);若为0是默认值,若为1000(Docker 默认)则说明它被刻意“标红”了 - 用
cat /proc/pressure/memory查内存压力状态;持续高于some avg10=10.00就说明系统长期处于内存高压,不是突发 spike
最易被忽略的一点:OOM 日志本身不会告诉你“为什么那个进程突然吃这么多内存”,它只记录结果。真正的原因藏在应用日志、监控曲线、甚至代码逻辑里——比如一个未限制分页大小的 SQL 查询,或一个没做流式处理的大文件上传。取证必须快,但归因不能只盯内核日志。











