“Too many open files”错误源于系统文件描述符限制不足,需同步调整进程级、用户级、内核级三层配置;查真实限制用/proc/pid/limits,systemd服务须单独配LimitNOFILE,fs.file-max需按内存合理设置。

遇到“Too many open files”错误,本质不是程序写错了,而是系统没给够资源口子。文件描述符限制必须同步调三层:进程级、用户级、内核级,漏一层都可能白配。
查清当前实际限制值
别只信 ulimit -n,它只反映当前 shell 继承的软限制,不是进程真实能用的数。
- 查某进程真实限制:cat /proc/<pid>/limits | grep "Max open files"
- 查系统总上限:cat /proc/sys/fs/file-max
- 查某服务是否走 systemd 管理:systemctl status 服务名(如 nginx)
临时调整(快速验证用)
适合调试或上线前压测,退出终端即失效,不需重启服务。
- 先提硬限制(root 用户可操作):ulimit -Hn 65535
- 再设软限制(不能超硬限):ulimit -Sn 65535
- 合并写法(等效):ulimit -n 65535
永久生效的用户级配置
对普通登录用户、Web 服务运行用户(如 www-data、nginx)长期有效,依赖 PAM 加载。
- 编辑 /etc/security/limits.conf,追加两行(以 nginx 用户为例):
nginx soft nofile 65535
nginx hard nofile 65535 - 确认 PAM 模块已启用:grep "pam_limits.so" /etc/pam.d/common-session,若无则追加:session required pam_limits.so
- 改完必须重新登录用户,或重启对应非 systemd 服务才生效
systemd 服务必须单独配 LimitNOFILE
Nginx、Redis、MySQL 等由 systemd 启动的服务,完全不读 limits.conf,这是最常被忽略的一环。
- 推荐方式(不覆盖原 service 文件):sudo systemctl edit nginx.service
- 在编辑器中写入:
[Service]
LimitNOFILE=65535 - 重载并重启:sudo systemctl daemon-reload && sudo systemctl restart nginx
- 验证是否生效:systemctl show -p LimitNOFILE nginx.service
系统级总上限 fs.file-max 要合理设置
这个值不是越大越好,它占用内核内存(每个句柄约 1KB),设太高反而浪费或触发 OOM。
- 估算参考:fs.file-max ≈ 总内存(MB) × 10(例如 32GB 内存 → 设 327680)
- 临时修改:sudo sysctl -w fs.file-max=327680
- 永久生效:把 fs.file-max = 327680 追加到 /etc/sysctl.conf,再执行 sudo sysctl -p



















