Linux文件句柄耗尽表现为“Too many open files”,根源常是限制配置不当而非资源真用尽;需从使用量、限制阈值、应用行为三方面排查,合理设置ulimit与file-max,并识别修复fd泄漏。

Linux文件句柄(file descriptor,简称fd)耗尽会导致进程无法打开新文件、建立网络连接或写日志,典型表现是报错 Too many open files。问题根源常在于系统级或进程级限制未合理配置,而非真的用光了内核资源。排查和优化需从当前使用量、限制阈值、应用行为三方面入手。
查清当前fd使用情况
先确认是否真“耗尽”,而不是某进程卡死或泄漏:
- 查看系统级已分配fd总数:
cat /proc/sys/fs/file-nr,输出三列:已分配但未使用的fd数、已使用的fd数、系统最大fd数(fs.file-max) - 查看某进程打开的fd数量:
ls -l /proc/,或用/fd/ | wc -l lsof -p| wc -l - 快速统计各进程fd占用排名:
lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head -10
理解ulimit限制层级
Linux中fd限制分三层,优先级由高到低:进程启动时继承的ulimit -n → 用户级/etc/security/limits.conf → 系统级/proc/sys/fs/file-max。常见误区是只调大file-max,却忽略用户级限制导致应用仍受限。
- 临时修改当前shell会话限制:
ulimit -n 65536(仅对后续启动的子进程生效) - 永久设置用户级限制:在
/etc/security/limits.conf中添加(注意替换username或用*):
username soft nofile 65536
username hard nofile 65536 - systemd服务需额外配置:
/etc/systemd/system.conf或服务单元文件中加LimitNOFILE=65536,然后执行systemctl daemon-reload
识别并修复fd泄漏
即使限制调高,若程序存在fd泄漏(如打开文件/Socket后未close),迟早再次耗尽。关键看fd类型分布:
- 用
lsof -p查看具体打开哪些fd:大量REG(普通文件)、IPv4/IPv6(socket)、anon_inode(eventfd、timerfd等)都可能指向不同问题 - 常见泄漏场景:日志框架反复open文件未复用FileHandler;HTTP客户端未关闭response body;数据库连接池未正确归还连接;异步IO未清理完成事件
- Java应用可配合
jstack+lsof交叉分析线程堆栈与fd归属;Go程序用pprof的/debug/pprof/goroutine?debug=2辅助定位阻塞点
合理设置fd上限值
盲目设为unlimited或百万级反而有风险:内存开销上升、内核查找fd变慢、掩盖真实泄漏。推荐按场景分级设置:
- 普通Web服务(Nginx/Redis):soft/hard均设为
65536,覆盖大多数并发连接需求 - 高并发网关或消息中间件:可设为
262144(256K),但需同步调整net.core.somaxconn和net.ipv4.ip_local_port_range - 开发测试机可适当降低(如
8192),便于早期暴露泄漏问题 - 始终保证
fs.file-max ≥ 所有进程hard nofile之和 × 1.2,留出内核自身开销余量










