Linux报Too many open files怎么查
网站无法接收新连接、程序打不开日志,并不一定是磁盘满了。Too many open files 常与文件描述符有关:普通文件、网络连接、管道等都可能占用它。先找出报错进程,再区分进程限制与系统压力,不能只把一个上限改大就结束。
以下适用于 Linux,命令示例使用 Bash、GNU find 与已挂载的 proc 文件系统。demo.service、PID 1234 都是示例;查看其他账户进程需要相应权限。
先看正在报错的进程,不看登录终端
如果程序由系统级 systemd 服务启动,可先查主进程和服务配置:
systemctl show demo.service -p MainPID -p LimitNOFILE -p LimitNOFILESoft
一个服务可能有多个工作进程,报错的未必是 MainPID。结合服务状态、日志时间和进程树,找到实际失败的 PID;MainPID 为 0 时也不能拿它继续查询。随后读取该进程的实际限制和当前 FD 数量:
target_pid=1234
cat "/proc/$target_pid/limits"
if fd_marks=$(find "/proc/$target_pid/fd" -mindepth 1 -maxdepth 1 -printf '.'); then
printf '当前FD目录项数:%s\n' "${#fd_marks}"
fi
在 limits 输出里找到 Max open files,分别看 Soft Limit 与 Hard Limit。软限制是当前执行的约束,硬限制限制普通进程能把软限制提高到哪里。FD 目录项数只是一个会变化的快照,不等于最大编号;应间隔一段时间对同一进程观察趋势。出现权限错误或进程已退出时,本例不会打印一个误导性的计数。
当前终端执行 ulimit -n 看到的是该 Shell 的限制,不能代表已经运行的服务;在终端改值,也不会自动修改那个服务。进程还可能自行调整软限制,因此以实际 PID 的 limits 为准。
分清两层限制
| 证据 | 下一步 |
|---|---|
| EMFILE,单个进程FD持续上涨或接近自身限制 | 检查该进程的连接、打开文件和关闭行为,确认是否泄漏或并发过高。 |
| ENFILE,或内核出现 file-max limit reached | 进一步检查系统级文件句柄使用及其他进程,不能只改某个服务的配置。 |
| No space left on device | 转查容量、inode或其他对应资源,不能仅凭“文件”二字归为同一故障。 |
cat /proc/sys/fs/file-nr
cat /proc/sys/fs/file-max
cat /proc/sys/fs/nr_open
file-nr 的三个数依次是已分配、已分配但未使用、最大文件句柄数;现代 Linux 的中间项通常为 0,这本身不是故障。它统计的是系统文件句柄,不能简单等同于所有进程 FD 数量之和。nr_open 则约束每进程可设置的相关上限,与系统 file-max 不是一个值。
先找增长原因,再决定是否调整
先限制异常重试、失控任务或明显超出预期的并发,观察 FD 是否回落。需要看类型时,由管理员在本机查看 /proc/实际PID/fd 的链接,区分 socket、管道和普通文件。文件名、连接和路径可能涉及业务信息,不要整份粘贴到公开页面。
FD 随请求量上涨但任务结束后能释放,可能是容量需求;低峰仍不断增长,更应查未关闭连接、文件或异常重试。重启可能暂时释放资源,也会丢失部分现场并中断业务,不能代替修复泄漏。
确需改服务限制时,留好恢复路径
仅在确认真实需求、资源余量和应用兼容后,再调整目标服务。下面只展示 soft:hard 的写法,8192/16384 不是通用推荐值。仍使用 select() 的程序可能无法处理大于 1023 的描述符,不能盲目提高软限制。
[Service]
LimitNOFILE=8192:16384
管理员先保存已有覆盖配置,再通过 systemctl edit demo.service 合并必要一项;重新加载配置后,在维护窗口重启受影响的服务。核对新 PID 的 limits、错误日志和实际请求结果,并观察代表性负载下是否稳定。
无改善时恢复本次变更前的配置,再按维护安排重新加载和启动,不清除其他既有覆盖项。容器及用户级服务还受各自启动器与父进程限制,需要在相应层配置;不要顺手修改全局上限。