systemd-oomd 杀进程优先级不生效的 systemd-oomd.conf 配置细节

4次阅读

systemd-oomd仅依据unit文件中的OOMScoreAdjust=值决策,忽略/proc/PID/oom_score_adj手动修改;需重启服务生效,并注意slice层级覆盖、容器/fork子进程导致的失效及ProtectProc影响。

systemd-oomd 杀进程优先级不生效的 systemd-oomd.conf 配置细节

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,但完全不参与进程打分排序。

  • oomd.conf 可配项极少:LogLevelManagedOOMManagedOOMMemPressureLimitManagedOOMSwap(建议设为 auto
  • 优先级决策全由 unit 配置驱动,oomd.conf 不影响 OOMScoreAdjust 解析逻辑
  • 想调高日志粒度看 oomd 怎么选进程?加 Environment=SYSTEMD_OOMD_LOG_LEVEL=4systemd-oomd service,再 journalctl -u systemd-oomd -f

容器、fork 子进程、ProtectProc 会直接让 OOMScoreAdjust 失效

java 应用启动后 fork 出多个 jvm 子进程,或 docker/runc 容器默认把 oom_score_adj 设为 -999,都会导致 systemd 单元设置的 OOMScoreAdjust 在子进程上丢失。

  • Java 类服务务必加:OOMScoreAdjust=-500 + ProtectProc=no(否则子进程被锁定为 0)
  • 容器场景慎用 ProtectProc,且确认 runtime 没覆盖 oom_score_adj(runc 默认设 -999,会压倒 unit 设置)
  • Type 必须匹配:若用 Type=forking,确保 PIDFile= 正确指向主进程 PID;Type=simple 更稳妥

真正卡住的点,往往不是配置写错,而是进程没落在你认为的那个 cgroup 里——cat /proc/PID/cgroupsystemctl show -p OOMScoreAdjust 这两行命令,比翻十页文档都管用。

text=ZqhQzanResources