进程半夜被 OOM killer 杀掉:从 dmesg 到 cgroup 上限的排查顺序

举报
yd_217417492 发表于 2026/11/04 08:41:08 2026/11/04
【摘要】 服务半夜消失、日志没有异常退出,多半是被内核 OOM killer 杀了。本文说明怎么确认、怎么看它选谁下手,以及容器和 systemd 环境下内存上限该查哪一层。

先确认是不是 OOM

进程被 OOM killer 杀掉时不会留下自己的错误日志,退出码通常是 137(128 + SIGKILL)。先看内核日志:

dmesg -T | grep -i -E "out of memory|oom-kill|killed process"
# [Tue Nov  4 02:13:07 2026] Out of memory: Killed process 18422 (python3) total-vm:4123568kB, anon-rss:3891200kB

journalctl -k --since "2026-11-04 00:00" | grep -i oom

如果 dmesg 已经被刷掉,可以看 /var/log/kern.log 或 journalctl -k --since yesterday。云主机还可能在控制台的「系统事件」里留一条记录。

没有 OOM 记录但进程确实没了,再往别的方向查:systemctl status 看是不是被 systemd 重启、docker inspect 看 OOMKilled 字段、或者程序自己 exit(1)。

内核为什么选它

OOM 日志里有一个 oom_score_adj 和一段任务列表。内核按 oom_score 打分,分最高的先被杀;分数大致和进程占用的物理内存成正比。可以手动调:

cat /proc/18422/oom_score
cat /proc/18422/oom_score_adj

# 让关键进程尽量不被杀(范围 -1000 ~ 1000)
echo -500 > /proc/$(pidof nginx)/oom_score_adj

注意 oom_score_adj 只是降低概率,不是豁免;系统真没内存时该杀还是会杀。

分清是整机内存还是 cgroup 限制

现在大多数服务跑在容器或 systemd scope 里,触发 OOM 的往往不是整机内存,而是这一层 cgroup 的上限:

# 整机
free -h
cat /proc/meminfo | grep -E "MemTotal|MemAvailable|Committed_AS"

# 某个 cgroup v2 路径
cat /sys/fs/cgroup/system.slice/myapp.service/memory.max
cat /sys/fs/cgroup/system.slice/myapp.service/memory.current
cat /sys/fs/cgroup/system.slice/myapp.service/memory.events

memory.events 里的 oom_kill 计数会直接告诉你这一层有没有杀过进程。容器里则是 /sys/fs/cgroup/memory.max(cgroup v2)或 /sys/fs/cgroup/memory/memory.limit_in_bytes(v1)。

整机还有 MemAvailable 却频繁 OOM,基本就是 cgroup 上限太小,或者 vm.overcommit_memory=2 配了过小的 overcommit_ratio。

常见的三个误判

  • 看 free 的 free 列:Linux 会把空闲内存拿去做 page cache,free 很小是正常的,要看 available。
  • 以为 swap 能兜底:容器里通常没有 swap,云主机也常关;vm.swappiness 调到 0 不等于不用 swap。
  • 只盯 RSS:top 的 RES 不含 page cache 和共享内存映射,定位内存大户时 smem -r 或 /proc//smaps_rollup 更准。

怎么避免再次发生

# systemd 服务限制内存,并给出明确的重启策略
[Service]
MemoryMax=2G
MemoryHigh=1800M
Restart=on-failure
RestartSec=5s

再配合应用侧的限制:JVM 的 -Xmx、Python 处理大文件时流式读写、Nginx 的 client_max_body_size 和缓冲区上限。最后加监控:memory.current / memory.max 超过 85% 告警,比等 OOM 发生后再查日志省事得多。

一句话:先 dmesg 确认 OOM,再看 oom_score_adj 和 cgroup 的 memory.max,最后才谈调参;只加内存不查泄漏,通常只是把问题推迟几天。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。