系统级文件描述符上限由fs.file-max定义,代表全系统可分配的FD总数,可通过cat /proc/sys/fs/file-max、sysctl fs.file-max或/proc/sys/fs/file-nr第三列查看;其值需远高于单进程ulimit限制,否则高并发服务易因总量耗尽报“Too many open files”。

查看系统级文件描述符上限用 cat /proc/sys/fs/file-max
这个值代表整个系统能分配的文件描述符总数,不是单个进程能用多少。它由内核参数 fs.file-max 控制,和你跑多少个服务直接相关。比如 MySQL、Nginx 并发高了就容易撞到这个墙。
常见错误是看到 ulimit -n 返回 65536 就以为够了,结果服务日志里反复报 Too many open files —— 实际可能是系统总量早被耗尽,新进程连申请都失败。
-
cat /proc/sys/fs/file-max看当前生效值 -
sysctl fs.file-max效果一样,但更符合 sysctl 风格 - 如果值低于 200000,对中高并发服务(如 Redis、Elasticsearch)通常偏小
sysctl -a 会列出所有可调参数,但别直接扫屏找 file-max
sysctl -a 输出太长(常超 300 行),而且默认不按字母或语义分组,fs.file-max 很可能混在一堆网络或虚拟内存参数里被忽略。真要查,加 grep 过滤更可靠:
-
sysctl -a | grep file-max—— 最快定位 -
sysctl -a | grep '^fs\.'—— 查看所有 fs.* 相关项,顺带看到fs.nr_open(单进程上限)和fs.file-nr(当前已用/未用/总量) - 注意:
sysctl -a不显示只读参数,比如fs.file-nr就不会出现,得用cat /proc/sys/fs/file-nr
fs.file-nr 的三个数字分别是什么意思
cat /proc/sys/fs/file-nr 返回类似 12345 0 500000 的三列数字,容易误解成“已用 / 空闲 / 总量”。实际是:
- 第一列:已分配的文件描述符总数(含已关闭但未回收的)
- 第二列:已分配但当前未使用的数量(内核保留池,一般长期为 0)
- 第三列:等于
fs.file-max,即系统硬上限
真正值得关注的是第一列是否持续接近第三列。如果差值小于 10%,说明系统 FD 资源吃紧,得查哪个进程在泄漏句柄(可用 lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head -10 快速定位 top 10 句柄占用进程)。
为什么改了 fs.file-max 但服务还是报错
因为系统级限制只是第一道门,后面还有两道卡口没过:
- 用户级限制:由
ulimit -n控制,写在/etc/security/limits.conf里,影响所有该用户启动的进程 - 进程级限制:由
fs.nr_open决定单个进程最多能拿到多少 FD,默认 1048576,但如果你把fs.file-max设得比它还大,新进程依然会被截断 - 服务管理器限制:systemd 服务还要额外检查
LimitNOFILE,即使 ulimit 改了,systemctl show nginx | grep LimitNOFILE可能显示仍是 4096
最典型的漏掉环节是:改完 /etc/sysctl.conf 忘了 sysctl -p,或者改了 limits.conf 没重新登录,导致新 shell 还带着旧限制启动服务。


















