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

日志里只显示“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=xxx或comm=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 '\0' ' ',注意 \0 分隔,用tr转成空格可读 - 查所属用户和服务单元(如果是 systemd 管理):
systemctl status --no-pager 12345 2>/dev/null | head -n 10
结合时间戳交叉验证业务日志
OOM 触发时刻非常精确(dmesg 输出带秒级甚至毫秒级时间)。利用这个时间点,去比对其他日志源:
- Java 应用:查 GC 日志中同一秒附近的
Full GC或Allocation 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 重定向的日志文件,搜索
terminated、signal 9、exit 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










