必须同时配置系统级限制、nginx主进程显式声明及进程继承三者一致,才能真正提升nginx句柄上限;仅改ulimit -n或worker_rlimit_nofile均无效。

只改 ulimit -n 或只配 worker_rlimit_nofile 都不能真正提升 Nginx 的实际句柄上限。必须让系统允许、Nginx 主动申请、进程成功继承,三者一致才生效。
先确认当前限制在哪卡住
很多问题出在“以为改了,其实没生效”。执行以下命令定位瓶颈点:
- 查 Nginx 运行用户:
ps -eo pid,comm,user | grep nginx | head -1(常见为nginx或www-data) - 查该用户软/硬限制:
sudo -u nginx bash -c 'ulimit -Sn; ulimit -Hn' - 查 systemd 是否覆盖:
systemctl show nginx | grep LimitNOFILE - 查内核总上限作参考:
cat /proc/sys/fs/file-max
同步配置系统级限制(关键一步)
不能只靠临时 ulimit -n,它只对当前 shell 有效,且 Nginx 启动后不继承。必须做永久配置:
- 若用 systemd(主流发行版):新建
/etc/systemd/system/nginx.service.d/override.conf,写入[Service]<br>LimitNOFILE=65536
然后运行sudo systemctl daemon-reload && sudo systemctl restart nginx - 若用传统方式启动:编辑
/etc/security/limits.conf,添加两行(用户名需匹配):nginx soft nofile 65536<br>nginx hard nofile 65536
并确认/etc/pam.d/common-session中有session required pam_limits.so
在 Nginx 中显式声明上限
这个值不是“自动获得”,而是 Nginx 主进程在 fork worker 前主动调用 setrlimit() 申请的。必须放在 nginx.conf 的最外层(main 上下文),例如:
user nginx;
worker_processes auto;
worker_rlimit_nofile 65536;
events { ... }
- 数值必须 ≤ 系统为 nginx 用户设置的 hard nofile,否则启动失败
- 不能写在
http、server或location块里,会报 “unknown directive” - 修改后必须
systemctl restart nginx(reload 不重设资源限制)
验证是否真正生效
重启后立即检查,别只看配置文件:
- 取一个 worker 进程 PID:
pgrep -f "nginx: worker" | head -1 - 查其实际限制:
cat /proc/<pid>/limits | grep "Max open files"</pid>
输出中 Soft Limit 应等于你设的65536,<strong>Hard Limit</strong> 应 ≥ 该值
- 翻看
error.log,不应出现 <code>setrlimit(RLIMIT_NOFILE)失败类警告











