“Too many open files”源于系统四层文件描述符限制未对齐:内核、用户、进程启动环境、Nginx自身;须逐层检查/proc/sys/fs/file-max、ulimit -Sn/Hn、master及worker进程的/proc/*/limits,并同步配置limits.conf、PAM模块、systemd的LimitNOFILE及nginx.conf中worker_rlimit_nofile与worker_connections。

“Too many open files”不是 Nginx 自身写错了配置,而是系统对文件描述符(file descriptor, FD)的层层限制没对齐——内核、用户、进程启动环境、Nginx 四层中任一环卡在默认 1024,就会触发该报错。只改 nginx.conf 或只运行 ulimit 命令,基本无效。
确认当前哪一层真正卡住了
别猜,直接查进程实际生效值:
- 系统全局上限:cat /proc/sys/fs/file-max(建议 ≥ 200000)
- nginx 用户软硬限制:sudo -u nginx bash -c 'ulimit -Sn && ulimit -Hn'
- Nginx master 进程限制:cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files"
- Nginx worker 进程限制:ps --ppid $(cat /var/run/nginx.pid) -o %p | sed '1d' | xargs -I{} cat /proc/{}/limits | grep "Max open files"
如果 worker 显示仍是 1024/4096,而其他层已调高,说明 Nginx 启动时根本没拿到新限制。
/etc/security/limits.conf 修改后不生效?重点检查三处
这是最常被忽略的失效原因:
- 没指定 nginx 用户:用 * soft nofile 65535 不够稳妥,必须加明确行:nginx soft nofile 65535 和 nginx hard nofile 65535
- PAM 模块未启用:Debian/Ubuntu 查 /etc/pam.d/common-session,CentOS/RHEL 查 /etc/pam.d/login,确认含 session required pam_limits.so
- 没用新会话验证:改完 limits.conf 后,必须用 sudo -u nginx bash 新启 shell,再执行 ulimit -n 看是否为 65535;systemd 启动还需额外处理
systemd 启动的 Nginx 必须额外设置 LimitNOFILE
即使 limits.conf 生效,systemd 服务也会覆盖它:
- 编辑服务文件:sudo systemctl edit nginx
- 填入:
[Service] LimitNOFILE=65535
- 重载并重启:sudo systemctl daemon-reload && sudo systemctl restart nginx
之后再查 master 进程的 /proc/*/limits,应显示 65535。
nginx.conf 中两个关键参数的配合逻辑
worker_rlimit_nofile 不是并发数,它是每个 worker 进程能打开的**总文件描述符上限**(含连接、日志、SSL 缓存等):
- 在 main 块设:worker_rlimit_nofile 65535;
- 在 events 块设:worker_connections 4096;
- 确保公式成立:worker_rlimit_nofile ≥ worker_connections × worker_processes(例如 4 核 auto 启 4 个 worker,则 4096×4 = 16384,65535 完全满足)
改完 reload 配置,再验证 worker 进程的 /proc/*/limits,数值应与 worker_rlimit_nofile 一致。











