systemd-oomd仅依据unit文件中的OOMScoreAdjust=值决策,忽略/proc/PID/oom_score_adj手动修改;需重启服务生效,并注意slice层级覆盖、容器/fork子进程导致的失效及ProtectProc影响。
systemd-oomd 不读 /proc/PID/oom_score_adj,只认 unit 静态配置
这是最常被误解的一点:你用 echo -500 > /proc/1234/oom_score_adj 手动改了值,systemd-oomd 完全无视。它只从 systemd unit 文件里读 OOMScoreAdjust= 这个字段——哪怕进程已运行,只要没重启服务,改动就白费。
- 必须执行
sudo systemctl daemon-reload && sudo systemctl restart myapp.service(仅daemon-reload不够) - 验证是否生效:
systemctl show -p OOMScoreAdjust myapp.service,输出应为OOMScoreAdjust=-500 - 若看到
OOMScoreAdjust=0,说明配置没加载、拼写错误(比如写成OOMScoreAdjustment)、或被父 slice 覆盖(见下一条)
slice 层级覆盖导致 OOMScoreAdjust 被静默重置
假设你给 myapp.service 设了 OOMScoreAdjust=-900,但它跑在 workload.slice 下,而该 slice 自己设了 OOMScoreAdjust=0,那么 oomd 实际采用的是 0 —— 因为 oomd 优先取“最近的、启用 MemoryAccounting 的 cgroup 级别”的值,不是取 service 最小值。
- 查进程真实归属:
cat /proc/PID/cgroup | grep -E '(slice|service)' - 统一管理策略:要么全在
myapp.service里设OOMScoreAdjust+MemoryAccounting=yes,要么在workload.slice级别统一设,不要混用 - 禁用 slice 级干扰:
sudo systemctl set-property workload.slice OOMScoreAdjust=(留空即清除继承)
/etc/systemd/oomd.conf 几乎不控制优先级逻辑
别在 oomd.conf 里找 DefaultOOMScoreAdjust 或类似字段——它根本不存在。这个文件只管全局开关和压力阈值,比如 ManagedOOMMemPressureLimit=60,但完全不参与进程打分排序。