“Too many open files”是系统级文件描述符四层限制未对齐所致,必须同步配置内核fs.file-max、用户limits.conf(含PAM启用)、systemd LimitNOFILE(如适用)及nginx.conf中worker_rlimit_nofile与worker_connections关系,缺一不可。

看到 Nginx 日志里反复出现 “accept() failed (24: Too many open files)”,不能直接改 worker_rlimit_nofile 就完事。真正卡住的,往往是四层限制中某一层没对齐,而这一层恰好被你忽略了。
看错进程,误判限制来源
Nginx 启动后有 master 和多个 worker 进程,它们的文件描述符限制可能完全不同:
- master 进程继承的是启动用户(如
nginx)的 ulimit 值,可通过cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files"查看 - worker 进程受
worker_rlimit_nofile控制,但该值不能超过 master 继承到的硬限制(hard nofile),否则会被静默截断 - 常见盲点:用
ulimit -n查的是当前 shell 的限制,不是 nginx 用户的;必须切到 nginx 用户下验证:sudo -u nginx bash -c 'ulimit -Hn'
limits.conf 修改后不生效的三大隐性条件
写进 /etc/security/limits.conf 不等于立刻生效,缺一不可:
- 必须明确指定用户,比如
nginx soft nofile 65535和nginx hard nofile 65535;用*全局匹配在 systemd 场景下常失效 - PAM 模块必须启用:检查
/etc/pam.d/common-session(Ubuntu/Debian)或/etc/pam.d/system-auth(RHEL/CentOS)是否含session required pam_limits.so - systemd 服务会绕过 limits.conf:即使配置了 limits.conf,若 Nginx 由 systemd 管理,
LimitNOFILE会覆盖它——必须同时在systemctl edit nginx中显式设置
systemd LimitNOFILE 被 silently override 的情况
很多人加了 LimitNOFILE=65535 却发现没起作用,原因常是:
- 未执行
systemctl daemon-reload,修改的服务配置根本没加载 - 使用了
sysconfig或环境变量方式启动(如/etc/sysconfig/nginx中设置了NGINX_LIMIT_NOFILE),会覆盖 service 文件中的 LimitNOFILE - 某些发行版(如较新版本的 Alibaba Cloud Linux)默认启用了
DefaultLimitNOFILE在/etc/systemd/system.conf中,若其值更低,会成为兜底限制
内核 fs.file-max 不足却误以为是进程问题
当所有 worker 几乎同步报错,且 dmesg | grep -i "file.*max" 显示 VFS: file-max limit reached,说明系统级瓶颈已到:
-
cat /proc/sys/fs/file-nr返回三列数字,第三列是当前系统允许的最大值(即fs.file-max),建议设为 ≥ 200000 - 临时调高:
sysctl -w fs.file-max=262144;永久生效需写入/etc/sysctl.conf并运行sysctl -p - 注意:
fs.file-max是全局上限,所有进程 FD 总和不能超它;哪怕每个 worker 都只开 65535,4 个 worker 就逼近 26 万,再加其他服务就容易触顶











