Linux进程句柄泄漏排查核心是观察FD数量是否持续增长且不释放,需用watch监控变化趋势,结合lsof分析类型与路径,定位deleted文件、高频路径及未关闭资源,最后验证重启后FD回归正常并配置LimitNOFILE等系统限制。

排查Linux进程句柄泄露,核心是确认“打开的文件描述符(FD)是否持续增长且未释放”。这不是看单次快照,而是观察变化趋势,并结合进程行为定位异常源头。
确认是否存在句柄泄漏
先判断问题性质,避免盲目操作:
- 用watch -n 1 'ls /proc/[PID]/fd | wc -l'实时监控目标进程的fd数量变化。如果数值随时间稳定上升(尤其在无新业务请求时仍在涨),基本可判定泄漏
- 对比lsof -p [PID] | wc -l输出行数与ls /proc/[PID]/fd | wc -l结果,二者应基本一致;若差异大,说明有内核级或特殊fd未被lsof识别,需进一步查/proc/[PID]/fd内容
- 观察图形趋势:平稳锯齿型→正常;初期上涨后稳定→高负载但非泄漏;持续线性/阶梯式上涨→典型泄漏
定位泄漏源进程和文件类型
找到谁在开、开的是什么:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 执行lsof -p [PID],重点看FD列(如0u、1u、2u是标准流;3r、4w、5u是普通文件;socket、anon_inode、eventfd等需特别留意)
- 按文件类型统计:lsof -p [PID] | awk '{print $5}' | sort | uniq -c | sort -nr,若发现大量REG(普通文件)、IPv4/IPv6(连接)、inotify或eventfd,就对应到日志写入、网络连接、文件监听或异步通知等常见泄漏点
- 检查是否有大量已删除但仍被占用的文件:lsof -p [PID] | grep deleted,这类条目NAME列会显示“/path/to/file (deleted)”,说明文件被rm但进程没close
分析具体泄漏路径
缩小范围,直击代码逻辑:
- 查看进程打开的文件路径分布:lsof -p [PID] | awk '{if($9 ~ /^\/.*/) print $9}' | sort | uniq -c | sort -nr | head -10,高频出现的路径(如/tmp、/var/log、/dev/shm)往往指向临时文件、日志或共享内存使用不当
- 结合应用日志与时间戳,比对fd增长时刻是否对应某类操作(如定时任务触发、批量导入、异常重试等),很多泄漏只在特定业务路径下复现
- 若为Java/Netty等服务,注意检查是否遗漏Channel.close()、FileInputStream.close()、ExecutorService.shutdown()等资源释放调用,尤其是异常分支和finally块
验证与收尾
确认修复有效,防止复发:
- 重启进程后重新监控fd数量,确认初始值回归合理水平(如几百以内),且长时间运行不再爬升
- 检查系统级限制是否匹配业务需求:cat /proc/sys/fs/file-max(系统总上限)和ulimit -n(当前shell软限制),对于systemd服务,必须在.service文件中配置LimitNOFILE=65535,否则limits.conf无效
- 在测试环境模拟长期运行+压力注入,用脚本定时采集/proc/[PID]/fd数量并绘图,形成基线监控能力

















