linux文件描述符限制需协同调整系统级(fs.file-max)、用户级(limits.conf)和进程级(systemd limitnofile),三者缺一不可;定位瓶颈需依次检查file-nr、进程limits及启动上下文,验证须实测ulimit与/proc/pid/limits。

Linux 调整内核文件描述符限制,核心是分层控制:单个进程能开多少(ulimit -n)、所有用户加起来最多能用多少(/etc/security/limits.conf)、整个系统最多分配多少(fs.file-max)。只调其中一项往往无效,必须协同设置才能真正防住句柄耗尽。
查清当前瓶颈在哪
先别急着改,用三步定位真实限制点:
- 运行
cat /proc/sys/fs/file-nr,看第二列数值——这是已分配但未释放的句柄数;再对比cat /proc/sys/fs/file-max,如果两者接近,说明系统级全局池快满了 - 对出问题的进程(比如 nginx 或 java),执行
cat /proc/$(pidof nginx)/limits | grep "Max open files",重点看 Soft Limit 是否远低于预期(常见默认值是 1024) - 检查该进程启动时的上下文:如果是 systemd 服务,
systemctl show -p LimitNOFILE nginx.service显示的值可能和ulimit不一致,说明 limits.conf 没生效
永久提升系统级全局上限
这个值决定内核能分配的总句柄数,是所有进程的“天花板”。设太低,再多用户级优化也白搭。
- 临时提高(重启失效):
sudo sysctl -w fs.file-max=2097152 - 永久生效:往
/etc/sysctl.conf末尾追加一行fs.file-max = 2097152,然后执行sudo sysctl -p - 注意:该值不宜盲目设得过高,每增加一个句柄会占用少量内核内存,一般建议按并发连接峰值 × 1.5 预留,例如支撑 50 万并发,设为 100 万左右较稳妥
固化用户与进程级限制
即使系统有足够句柄,单个进程也可能被卡在默认 1024。需确保它启动时就拿到足够配额。
- 编辑
/etc/security/limits.conf,添加两行(以运行服务的用户为例,如www-data):www-data soft nofile 65535www-data hard nofile 65535 - 确认 PAM 加载了 limits 模块:检查
/etc/pam.d/common-session是否含session required pam_limits.so,没有就加上 - 对 systemd 服务(Nginx、Redis 等),limits.conf 常不生效,必须单独配置:
创建/etc/systemd/system/nginx.service.d/override.conf,写入:[Service]LimitNOFILE=65535
然后执行sudo systemctl daemon-reload && sudo systemctl restart nginx
验证是否真正生效
改完不能只信配置文件,要实测:
- 重新登录目标用户,运行
ulimit -n,应显示 65535 - 重启对应服务后,查其实际限制:
cat /proc/$(pidof nginx)/limits | grep "Max open files",Soft 和 Hard 都应匹配设定值 - 观察运行中句柄增长:
lsof -p $(pidof nginx) | wc -l,结合业务压力测试,确认不再触发 “Too many open files” 错误











