ulimit -n 仅对当前shell会话有效,永久生效需配置/etc/security/limits.conf(用户级)或systemd服务文件中的LimitNOFILE(服务级),并重载验证。

为什么 ulimit -n 修改后不生效
直接在终端执行 ulimit -n 65536 只对当前 shell 及其子进程有效,重启终端或新登录用户就恢复默认值。系统级限制还受 /etc/security/limits.conf 和 systemd 服务单元配置双重约束,尤其当服务由 systemd 管理(如 nginx、redis)时,limits.conf 的设置可能被忽略。
- 普通用户修改需注销重登录才生效;root 用户也需注意 PAM 模块是否启用
limits.so - systemd 服务默认不读取
limits.conf,必须显式在 service 文件中用LimitNOFILE=设置 - 检查是否启用 PAM limits:确认
/etc/pam.d/common-session或/etc/pam.d/sshd中有session required pam_limits.so
systemd 服务如何永久提高 Open Files 限制
现代 Linux 发行版(CentOS 7+、Ubuntu 16.04+)中,大部分后台服务由 systemd 启动,其资源限制独立于用户会话。仅改 limits.conf 对这些服务无效。
- 编辑服务文件:
sudo systemctl edit nginx(以 nginx 为例),然后添加:
[Service] LimitNOFILE=65536
- 保存后重载配置:
sudo systemctl daemon-reload,再重启服务:sudo systemctl restart nginx - 验证是否生效:
cat /proc/$(pidof nginx)/limits | grep "Max open files" - 若使用
sysctl.conf调整全局内核参数(如fs.file-max),它只影响系统总文件句柄上限,不改变单个进程限制
检查当前进程实际生效的 limits
不要依赖 ulimit -n 输出判断服务真实限制——它显示的是当前 shell 的软限制,而非目标进程的实际值。
- 查某进程 PID 的硬/软限制:
cat /proc/PID/limits | grep "Max open files" - 软限制(Soft Limit)可运行时调整,但不能超过硬限制(Hard Limit);硬限制需 root 权限或启动前设定
- 若看到
Max open files 1024 1024 files,说明未正确配置,即使ulimit -n显示 65536 也没用 - 对于 fork 多进程模型(如 Apache prefork),每个子进程都受该限制约束,总并发连接数 = 进程数 × 单进程文件描述符上限
常见高并发报错与定位路径
“Too many open files” 不一定意味着真的打开了太多文件,更可能是连接未及时关闭、日志轮转异常、或异步 I/O 回调堆积导致 fd 泄漏。
- 错误示例:
accept() failed (24: Too many open files)(nginx)、java.io.IOException: Too many open files(Java 应用) - 快速排查:
lsof -p PID | wc -l查当前打开 fd 数;lsof -u username | awk '{print $9}' | sort | uniq -c | sort -nr | head看哪些路径占最多 fd - 注意:TCP 连接、管道、eventfd、timerfd 都占用文件描述符,不限于磁盘文件
- Go 程序若用
net/http默认配置,空闲连接保留在连接池中,长期高负载下易触发该错误,需调http.Transport.MaxIdleConns等参数
/proc/PID/limits 看一眼,别信命令行里回显的数字。










