系统最大文件描述符限制由fs.file-max决定,查看命令为cat /proc/sys/fs/file-max或sysctl fs.file-max;/proc/sys/fs/file-nr显示已分配、空闲和上限三值;systemd服务需在unit文件中配置LimitNOFILE才生效。

系统最大文件描述符限制由 fs.file-max 决定,不是 ulimit -n 能改出来的值,也不是进程自己的限制——它卡在内核层,所有进程加起来不能超过这个数。
怎么查当前系统的 fs.file-max 值
这是最常被误当成“进程限制”的地方。很多人看到 Too many open files 就去调 ulimit -n,结果没用,因为系统级已经满了。
- 实时查看命令:
cat /proc/sys/fs/file-max或sysctl fs.file-max - 输出就是一个纯数字,比如
1048576,这就是当前生效的上限 - 别去
/etc/sysctl.conf里翻——没配过的话,这行根本不存在;默认值由内核根据内存自动计算,重启后就恢复 - 验证是否真生效:改完必须运行
sysctl -p,否则只是改了配置文件,内核压根不知道
/proc/sys/fs/file-nr 三个数分别代表什么
这个文件暴露的是系统当前文件描述符的实际使用状态,比单纯看 file-max 更能定位瓶颈。
- 执行
cat /proc/sys/fs/file-nr,输出类似124560 0 1048576 - 第一个数
124560:已分配出去的 fd 总数(含已关闭但尚未回收的) - 第二个数
0:已分配但当前未使用的 fd 数(这部分可快速复用) - 第三个数
1048576:就是fs.file-max,硬上限 - 如果第一个数接近第三个数,说明系统级快耗尽了,再开新进程或新连接就会失败,此时调单个进程的
ulimit没意义
为什么改了 limits.conf 还是报错
因为 systemd 服务绕过了 PAM limits,/etc/security/limits.conf 对它们基本无效。
- 确认服务是否由 systemd 管理:
ps -p 1 -o comm=输出systemd就是 - 对 nginx、mysql 等服务,必须在 unit 文件里显式设:
LimitNOFILE=65535 - 全局生效可改
/etc/systemd/system.conf中的DefaultLimitNOFILE,但改完要systemctl daemon-reload - 注意:硬限制不能超过
/proc/sys/fs/nr_open(默认 1048576),否则服务启动时会静默失败
临时调高 vs 永久生效的关键动作
临时命令立竿见影,但重启就丢;永久配置写对位置只是第一步,漏掉加载步骤等于白干。
- 临时改系统级:
sudo sysctl -w fs.file-max=2097152 - 永久写入:
echo "fs.file-max = 2097152" | sudo tee -a /etc/sysctl.d/99-file-max.conf(推荐用.d/目录,避免污染主配置) - 必须 reload:
sudo sysctl --system(比sysctl -p更全面,会加载整个/etc/sysctl.d/) - 验证是否真持久:重启后立刻
cat /proc/sys/fs/file-max,别只信配置文件里有没有那行
真正容易被忽略的是:系统级 file-max 和单个进程的 ulimit -n 是两层独立限制,必须同时满足;而 systemd 服务又额外隔离了一层,不单独配置 LimitNOFILE 就永远走不到你设的值。











