Linux文件句柄耗尽表现为“Too many open files”,根源常是限制配置不当而非资源真用尽;需从使用量、限制阈值、应用行为三方面排查,合理设置ulimit与file-max,并识别修复fd泄漏。
linux文件句柄耗尽排查教程_ulimit与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,覆盖大多数并发连接需求
omega.watchhdle.cn
beijingomega.watchhdle.cn
shanghaiomega.watchhdle.cn
guangzhouomega.watchhdle.cn
shenzhenomega.watchhdle.cn
shenyangomega.watchhdle.cn
zhengzhouomega.watchhdle.cn
chengduomega.watchhdle.cn
nanjingomega.watchhdle.cn
tianjinomega.watchhdle.cn
shijiazhuangomega.watchhdle.cn
wuhanomega.watchhdle.cn
kunmingomega.watchhdle.cn
hefeiomega.watchhdle.cn
wuxiomega.watchhdle.cn
高并发网关或消息中间件:可设为262144(256K),但需同步调整net.core.somaxconn和net.ipv4.ip_local_port_range
开发测试机可适当降低(如8192),便于早期暴露泄漏问题
始终保证fs.file-max ≥ 所有进程hard nofile之和 × 1.2,留出内核自身开销余量