适用于 Linux 5.4+、cgroup v2、systemd 247+。示例单元 app.service 要替换;读取内核日志和其他服务的 cgroup 通常需要 root 或对应权限。先别急着重启,退出状态、OOM 计数和日志很容易被后续现场覆盖。
先确认服务退出方式和实际 cgroup:
date -u
uname -r
stat -fc %T /sys/fs/cgroup
systemctl status app.service --no-pager -l
systemctl show app.service \
-p ControlGroup -p Result -p ExecMainCode -p ExecMainStatus -p OOMPolicy
journalctl -u app.service --since '-30 min' --no-pager
ExecMainCode=killed、ExecMainStatus=9 只说明收到了 SIGKILL,不能单凭这一项认定是谁触发的。拿到 ControlGroup 后,再看 cgroup v2 的限制和事件:
CG=$(systemctl show app.service -p ControlGroup --value)
cat "/sys/fs/cgroup${CG}/memory.current"
cat "/sys/fs/cgroup${CG}/memory.max"
cat "/sys/fs/cgroup${CG}/memory.high"
cat "/sys/fs/cgroup${CG}/memory.events"
memory.events 里的 oom 表示该 cgroup 发生过分配失败,oom_kill 增长才表示内核 OOM killer 在这个层级杀过任务;这些是累计计数,最好和故障前基线比较。memory.max 为 max 时也不能排除上层 cgroup 或整机 OOM。
再对齐同一时间窗:
journalctl -k --since '-30 min' --no-pager \
| grep -E 'oom-kill|Out of memory|Killed process|Memory cgroup'
journalctl -u systemd-oomd --since '-30 min' --no-pager
oomctl --no-pager
内核日志有 Killed process 或 memory cgroup 记录,通常沿内核 OOM 分支查;systemd-oomd 日志明确记录被选中的 cgroup,而内核 OOM 记录缺失时,则沿 PSI、ManagedOOMMemoryPressure 和 ManagedOOMSwap 配置查。不要只因为看到状态 9 就直接扩大 MemoryMax。
调整应用峰值、并发或内存策略后,在受控负载下同时观察 memory.current、memory.events 和服务日志;至少确认服务保持 active、oom_kill 不再增长,且业务延迟和吞吐仍符合预期。