oomscoreadjust=-1000可使服务主进程免遭oom killer误杀,但需配合cgroup v2、systemd-oomd启用及禁止cgroup移动三者同步生效,且应按服务类型差异化设值。

在 systemd 中,通过 OOMScoreAdjust 参数保护核心服务不被 OOM Killer 误杀,关键不是“阻止系统 OOM”,而是让内核在触发 OOM 时跳过该服务的主进程。最稳妥的做法是将 Master 进程的评分设为 -1000(完全豁免),但必须配合 cgroup v2 和 systemd-oomd 的协同配置,否则可能失效。
只调 Master 进程,别碰 Worker
systemd 管理的是服务单元(unit),OOMScoreAdjust 只作用于服务启动时的主进程(即 Master)。Nginx、PostgreSQL、API 网关等服务的 Master 进程负责热重载、worker 管理和信号响应——只要它活着,就能恢复服务能力。Worker 进程由 Master fork 出来,部分服务(如 Nginx)会主动重置其 oom_score_adj,无法依赖继承;手动逐个写 /proc/<pid>/oom_score_adj</pid> 不持久、不可靠。
- Nginx 主进程通常以 root 启动,worker 多用 www-data,权限与生命周期不同
- 数据库监听器(如 postgres -D)是 Master,实际处理请求的是子进程,保护 Master 才能维持连接入口
- systemd 的
OOMScoreAdjust设置不会自动扩散到子进程,也不应尝试覆盖所有 worker
用 drop-in 方式安全配置 OOMScoreAdjust
避免直接修改 /usr/lib/systemd/system/*.service(会被包管理器覆盖),使用 systemd 推荐的 drop-in 机制:
- 执行
sudo systemctl edit nginx.service(或对应服务名) - 填入:
[Service]<br>OOMScoreAdjust=-1000
- 保存后运行:
sudo systemctl daemon-reload && sudo systemctl restart nginx - 验证:获取 Master PID(如
pgrep -f "nginx: master"),再执行cat /proc/<pid>/oom_score_adj</pid>,应输出-1000
三个必须同步做的配套动作
仅设 OOMScoreAdjust=-1000 不足以保命。systemd-oomd、cgroup 移动、内核参数缺失都会导致保护失效:
- 确认启用 cgroup v2:
cat /proc/1/environ | tr '\0' '\n' | grep unified_cgroup_hierarchy=1;若无输出,需在内核启动参数加systemd.unified_cgroup_hierarchy=1 - 检查
systemd-oomd是否激活:sudo systemctl is-active systemd-oomd;未激活则sudo systemctl enable --now systemd-oomd - 禁止服务进程被移到其他 cgroup:
sudo systemctl set-property nginx.service AllowedCPUs=0-3类操作可能触发移动,应避免;确保服务 unit 未被 slice 或 scope 覆盖(如workload.slice自身设了OOMScoreAdjust=0,会覆盖子 service 设置)
不同服务推荐值与风险提示
不是所有服务都适合设 -1000。过度保护可能导致系统僵死(如 sshd 设 -1000 是合理,但数据库全设 -1000 可能在极端内存耗尽时阻塞 recovery):
-
sshd、journald、systemd-journald:建议-1000(保障基础运维通道) -
MySQL、PostgreSQL:推荐-500至-800(保留一定弹性,避免 OOM 后无法清理) -
Nginx、Envoy:常用-300~-500(兼顾高可用与系统整体稳定性) - 设
-1000前务必确认该服务不长期持有大量匿名内存(如未限制worker_rlimit_as的 Nginx worker),否则可能拖垮整个节点











