在 Systemd 管理的服务中配置 LimitNOFILE,需直接修改服务单元文件的 [Service] 段落,适用于所有由 systemctl 启动的后台服务,风险在于设置过高可能触及内核 fs.file-max 上限。
先说结论:Systemd 服务不继承 shell 的 limits.conf 限制,必须在 unit 文件中显式声明 LimitNOFILE。
- 适合:所有通过 systemctl 启动的 Linux 后台服务
- 先准备:确认服务单元文件路径及当前运行状态
- 验收:通过 /proc/[pid]/limits 验证软限制与硬限制是否变更
命令速用版
使用 systemctl edit 创建覆盖配置,避免直接修改原始单位文件。
systemctl edit <service-name>
# 在编辑器中输入以下内容
[Service]
LimitNOFILE=65535
# 保存退出后执行
systemctl daemon-reload
systemctl restart <service-name>
为什么会这样
Systemd 启动的服务进程独立于登录 Shell,不受 /etc/security/limits.conf 控制。
Linux 传统通过 PAM 模块在用户登录时应用 limits.conf,但 Systemd 作为 init 系统直接启动服务,不经过 PAM 登录流程。因此,全局或用户级的 ulimit 设置对 systemd 服务无效,必须在 unit 文件中单独定义资源限制。
分步处理
第一步:查找服务文件路径。
systemctl show -p FragmentPath <service-name>
第二步:创建覆盖配置。
推荐使用 systemctl edit 命令,它会在 /etc/systemd/system/<service-name>.d/ 目录下创建 override.conf 文件,升级软件包时不会丢失配置。
systemctl edit <service-name>
第三步:写入限制参数。
在编辑器中输入 [Service] 段落和 LimitNOFILE 值,数值可以是整数或 infinity。
[Service]
LimitNOFILE=65535
第四步:重载并重启。
修改 unit 文件后必须重载守护进程配置,否则新参数不生效。
systemctl daemon-reload
systemctl restart <service-name>
怎么验证是否生效
查看进程 limits 文件确认当前运行值。
cat /proc/$(pidof <process-name>)/limits | grep "Max open files"
或使用 systemctl show 查看单元配置值。
systemctl show <service-name> | grep LimitNOFILE
注意:systemctl show 显示的是配置值,/proc 显示的是实际运行值,两者应一致。
常见坑
- 修改了 /etc/security/limits.conf 但未重启服务:该文件对已运行的 systemd 服务无效。
- 数值超过内核上限:需检查 /proc/sys/fs/file-max,设置值不应超过此内核参数。
- 忘记 daemon-reload:修改 unit 文件后未重载配置,重启服务仍沿用旧限制。
- 使用 ulimit 命令验证:在 Shell 中运行 ulimit -n 仅显示当前 Shell 环境,不代表服务进程限制。
常见问题
limits.conf 对 systemd 服务生效吗?
不生效。limits.conf 仅作用于通过 PAM 登录的 Shell 会话,systemd 服务需通过 unit 文件配置 LimitNOFILE。
LimitNOFILE 设置 infinity 可以吗?
可以。Systemd 支持将 LimitNOFILE 设置为 infinity,但实际值受内核 fs.file-max 限制。
修改后需要重启服务器吗?
不需要。执行 systemctl daemon-reload 并重启对应服务即可生效,无需重启操作系统。
参考来源
- freedesktop.org, systemd.exec — Execution environment configuration, https://www.freedesktop.org/software/systemd/man/systemd.exec.html
- Red Hat Customer Portal, Setting limit values for systemd services, https://access.redhat.com/solutions/616613