必须同时修改/etc/sysctl.conf、/etc/security/limits.conf和/etc/systemd/system.conf三处,并执行sysctl -p与systemctl daemon-reload,否则systemd服务句柄数仍为默认值。

CentOS 7 修改句柄数不能只改 /etc/security/limits.conf,否则 systemd 启动的服务(比如 nginx、redis、java 应用)完全不受影响——这是最常踩的坑。
为什么 ulimit -n 和 limits.conf 对服务进程无效
systemd 从 v219 开始绕过了 PAM 的 limits.conf 加载逻辑,所有通过 systemctl start 启动的服务默认继承 systemd 自身的资源限制,而非用户登录 shell 的 ulimit 值。
- 执行
cat /proc/$(pgrep -f "nginx|redis|java")/limits | grep "Max open files",看到的往往是4096或1024,哪怕你已改过limits.conf -
ulimit -n只作用于当前 shell 及其子进程,重启终端或重新登录就还原 -
/etc/security/limits.conf只对 PAM 登录会话生效(如 ssh 登录后执行的命令),不穿透到 systemd service context
必须同时修改三个地方才能真正生效
缺一不可,顺序无关,但建议按以下顺序操作:
-
系统级总上限:编辑
/etc/sysctl.conf,添加一行fs.file-max = 6553560,然后运行sysctl -p生效。这个值要 ≥ 单进程最大值 × 预期并发进程数 -
用户级软硬限制:在
/etc/security/limits.conf末尾加两行(*表示所有用户;若只针对某用户,把*换成用户名):* soft nofile 1048576* hard nofile 1048576 -
systemd 全局默认限制:编辑
/etc/systemd/system.conf,取消注释并修改这两行:DefaultLimitNOFILE=1048576DefaultLimitNPROC=1048576
改完必须执行systemctl daemon-reload,否则重启服务也不加载新值
注意 nr_open 内核上限这个隐藏关卡
即使你设了 hard nofile 2000000,如果内核参数 /proc/sys/fs/nr_open 小于该值,root 用户也会登录失败或服务启动报错 Operation not permitted。
- 先查当前上限:
cat /proc/sys/fs/nr_open(CentOS 7 默认是1048576) - 若需突破此值,编辑
/etc/sysctl.conf,追加fs.nr_open = 2097152,再sysctl -p - 这个值不能设得过大(比如超过 4M),否则可能引发内核内存分配失败,尤其在低内存机器上
验证是否真生效
别信配置文件写了就算数,必须检查运行中的进程:
- 查系统总上限:
cat /proc/sys/fs/file-max - 查某服务 PID 的实际限制:
cat /proc/$(pidof nginx)/limits | grep "Max open files"(输出应为两列数字,且都等于你设的值) - 查当前 shell 限制:
ulimit -n(应反映limits.conf设置) - 重启服务后仍不生效?确认是否用了
systemctl edit xxx.service覆盖了全局设置,这种 per-service override 优先级更高
最后提醒:改完 system.conf 或 sysctl.conf 后,systemctl daemon-reload 和 sysctl -p 这两步漏掉任何一个,前面全白干。而且 nr_open 设太高又没调大 file-max,反而会导致新进程无法 fork。











