too-many-open-files

文件描述符耗尽的定位与修复

现象

应用报 Too many open files、EMFILE,新连接无法建立,日志写入失败。accept()、open()、socket() 都可能返回错误。

快速定位

ulimit -n
cat /proc/<pid>/limits | grep 'open files'
ls /proc/<pid>/fd | wc -l
lsof -p <pid> | wc -l
lsof -p <pid> | awk '{print $5}' | sort | uniq -c | sort -rn | head
cat /proc/sys/fs/file-nr
ss -s

systemd 服务:

systemctl show <service> -p LimitNOFILE
systemctl status <service>

常见根因

  1. 连接或文件句柄未关闭,常见于连接池、HTTP 客户端和日志句柄。
  2. ulimit -n 或 systemd LimitNOFILE 太小。
  3. 容器运行时默认 nofile 限制偏低。
  4. 大量短连接没有复用,或 TIME_WAIT 堆积。
  5. inotify、epoll 等也占用描述符,监控工具会放大占用。

修复

相关命令

读完自测

合上页面,先回答,再展开对照。

  1. 如何区分是文件描述符泄漏还是限制太小?
  2. 为什么修改 /etc/security/limits.conf 可能对 systemd 服务无效?
  3. 调整限制后如何确认真的生效?
答案
  1. 用 lsof -p <pid> 看 fd 类型和增长趋势。再对比 /proc/<pid>/fd 数量与 /proc/<pid>/limits,持续增长更像泄漏。
  2. 该文件只影响登录会话。systemd 服务要用 LimitNOFILE,可用 systemctl show <service> -p LimitNOFILE 查看。
  3. 重启进程后查看 /proc/<pid>/limits。确认 open files 已经是新值。