OOM killer 杀进程但日志里没写被杀进程名怎么自己追溯

2次阅读

可通过 dmesg 完整日志、PID 反查 /proc 信息、时间戳交叉验证业务日志、cgroup 内存分析四步定位被杀进程:先用 dmesg -T | grep -A10 -B5“Killed process”找 comm 字段;再用 /proc/PID/exe、cmdline 等查进程详情;结合 dmesg 时间戳比对 GC、access.log 等;最后检查 cgroup usage 及 tasks 确认 OOM 层级。

OOM killer 杀进程但日志里没写被杀进程名怎么自己追溯

日志里只显示“Killed process”但没写进程名,通常是因为内核日志被截断、日志轮转丢失、或系统启用了精简日志模式(如某些云镜像或容器环境默认关闭详细 OOM 上下文)。别急,你可以通过几个关键线索反向锁定真实被杀进程。

优先查 dmesg 完整内核日志

很多情况下 /var/log/messages/var/log/syslog 会丢掉关键字段,而 dmesg 缓存的是原始内核环形缓冲区,信息最全:

  • 运行 dmesg -T | grep -A 10 -B 5 "Killed process" —— -T 加上本地时间戳,-A 10 -B 5 向后看 10 行、向前看 5 行,常能捕获到紧邻的 name=xxxcomm=xxx 字段
  • 如果输出为空,试试 dmesg -c 清空后复现问题(仅限测试环境),或检查是否开启了 log_buf_len 限制(cat /proc/sys/kernel/log_buf_len,太小会导致日志覆盖)

从 PID 反查进程名和启动命令

日志中一般仍会保留 PID(例如 Killed process 12345 (java) 中的 12345 即使括号内容被截,PID 往往还在)。哪怕只有 PID,也能追溯:

  • 查该 PID 对应的可执行文件:ls -l /proc/12345/exe 2>/dev/null,软链接目标就是真实二进制路径
  • 查完整启动命令:cat /proc/12345/cmdline 2>/dev/null | tr '' ' ',注意 分隔,用 tr 转成空格可读
  • 查所属用户和服务单元(如果是 systemd 管理):systemctl status --no-pager 12345 2>/dev/null | head -n 10

结合时间戳交叉验证业务日志

OOM 触发时刻非常精确(dmesg 输出带秒级甚至毫秒级时间)。利用这个时间点,去比对其他日志源:

  • Java 应用:查 GC 日志中同一秒附近的 Full GCAllocation Failure 记录;tail -n 100 gc.log | grep "$(date -d'@$(dmesg | grep 'Killed process' | head -1 | awk '{print $1}' | sed 's/[//;s/]//')''+%Y-%m-%d %H:%M:%S')"
  • Nginx/Apache:查 access.log 或 error.log 中该秒内请求激增、502/503 错误集中出现
  • 自定义服务:查其 stdout/stderr 重定向的日志文件,搜索 terminatedsignal 9exit code 137(Docker 和多数 shell 中,137 = 128 + 9,即被 SIGKILL 杀死)

确认是否是 cgroup 级别 OOM 导致信息缺失

在容器或 systemd service 场景下,OOM 可能发生在 cgroup 子层级,此时内核日志只写父 cgroup 名称(如 memory: mm_test),不列具体进程。这时要:

  • 查触发时刻各 cgroup 内存使用:find /sys/fs/cgroup/memory -name "memory.usage_in_bytes" 2>/dev/null | xargs -I{} sh -c 'echo {}; cat {}' | sort -k2 -nr | head -10
  • 定位到超限的 cgroup 后,列出其进程:cat /sys/fs/cgroup/memory/[path]/tasks,再逐个用上面 PID 反查法确认
  • 检查该 cgroup 的 memory.limit_in_bytes 和 memory.oom_control,确认是否启用 OOM killer
text=ZqhQzanResources