Linux 服务提示 Too many open files?文件描述符、systemd 限制与连接泄漏排查

Linux 服务无法打开文件或建立连接时,需要检查报错进程的文件描述符和实际资源限制。本文说明如何读取运行中进程的限制、观察连接与文件占用,区分业务高峰和资源泄漏,并介绍 systemd LimitNOFILE、系统级句柄限制及配置回退与恢复验收,避免仅提高上限掩盖故障。
Linux 服务提示 Too many open files?文件描述符、systemd 限制与连接泄漏排查

网站突然无法建立新连接,应用日志里反复出现 Too many open files,但磁盘空间和内存看起来都够用。这时需要检查文件描述符。Linux 中的普通文件、网络套接字、管道等都可能占用描述符;连接没有释放,也会让服务走到限制边界。

处理这种故障,先确定报错进程及其实际限制,再判断资源增长是否符合业务负载。只修改登录终端里的 ulimit,通常影响不到已经运行的 systemd 服务;把上限调大,也可能仅仅延后下一次故障。

本文命令适用于常见 Linux 主机,以 systemd 管理的服务为例。服务名、PID 和路径均需替换为现场值。容器还需检查容器内进程和运行时配置。本文没有连接生产服务器执行测试。

报错发生在哪个进程,决定检查范围

应用日志中的 Too many open files 通常对应进程达到文件描述符限制,即 EMFILE。系统范围文件句柄耗尽对应 ENFILE,错误文字可能包含 Too many open files in system。包装库可能改写错误消息,不能只凭网页上的一行提示定性。[1]

先从服务日志中找到报错时间、进程和失败操作。数据库、反向代理和业务应用都有独立限制,前端返回 502 并不代表 Nginx 自己耗尽了描述符。

下面是只读检查示例,将 example.service 替换为实际单元名。

systemctl status example.service --no-pager
journalctl -u example.service --since '30 minutes ago' --no-pager
systemctl show example.service -p MainPID -p LimitNOFILE -p LimitNOFILESoft

MainPID 只能作为入口。采用主进程加 worker 模型的应用,故障可能发生在某个 worker;需要结合进程树及日志检查子进程。MainPID 为 0 时,先确认服务是否已经退出,不能拿 0 当作待检查的业务 PID。

读取运行中进程的限制和描述符数量

以下示例使用 PID 1234,执行前务必换成已核实的 PID。读取其他用户的进程信息可能需要相应权限。

cat /proc/1234/limits
ls -1U /proc/1234/fd | wc -l
ls -l /proc/1234/fd | head -n 40

在 limits 中找到 Max open files,分别查看软限制与硬限制。软限制是当前生效边界;硬限制约束进程提高软限制的能力,特权进程还受相关内核规则约束。[1]

描述符目录中的条目数可用于观察占用,但计数发生时进程仍在运行,因此只是瞬时快照。权限不足、进程退出或 PID 被复用都可能使结果失真。不要把错误输出当作“占用为零”。

还需注意,RLIMIT_NOFILE 定义的是可分配描述符编号的上界加一,条目总数适合日常趋势判断,却不等同于所有情况下的严格剩余额度。[1]

如果系统安装了 lsof,可以进一步查看类型和目标。

sudo lsof -nP -p 1234
sudo ss -tanp

lsof 输出行数不能直接等同于描述符数量,其中可能包含工作目录、程序映像和内存映射等记录。ss 用于检查 TCP 状态和关联进程,也不能覆盖普通文件、Unix 套接字或全部描述符类型。两者应与 /proc/PID/fd 交叉判断。

区分正常连接高峰与持续泄漏

单次高占用无法证明泄漏。记录同一个进程在高峰前、高峰中和流量回落后的数量,并保留进程启动时间,避免跨重启比较失去意义。

通常可以从目标类型缩小范围:

  • 套接字随并发上升,流量下降后逐渐回落,可能是正常容量需求,需要结合连接池、长连接和超时配置评估。
  • 流量已回落,占用仍逐次攀升,需检查响应体、数据库连接、文件对象和异常分支是否正确关闭。
  • 大量 CLOSE-WAIT 连接值得检查本地应用关闭连接的逻辑,但仅凭该状态还不能确认具体代码缺陷。
  • 同一批文件反复打开,可能与日志处理、文件监控、插件行为或业务任务有关,应追溯实际持有者。

不要用 TIME-WAIT 数量推导某个进程的打开文件数。这类 TCP 状态通常已经不再由原应用持有文件描述符。

全量收集 lsof、连接表或高频扫描进程目录,在连接规模很大时也有成本。线上可先短时采样,再对可疑进程细查。输出中可能含内部路径、远端地址等信息,分享日志前需要脱敏。

systemd 服务的上限需要在正确位置修改

当前终端运行 ulimit -n,看到的是这个 shell 的软限制。它不能证明后台服务采用了同一数值。登录会话的 PAM 限制与 systemd 系统服务的启动路径也不能混为一谈。

对于 systemd 服务,检查单元配置和 drop-in,明确 LimitNOFILE 的来源。

systemctl cat example.service
systemctl show example.service -p LimitNOFILE -p LimitNOFILESoft

如确认需要调整,应先记录旧值、保存现有 drop-in,并安排维护或滚动重启。下面只展示语法,32768 是示例值,不能直接作为所有应用的推荐配置。

[Service]
LimitNOFILE=32768:32768

可通过 systemctl edit example.service 添加覆盖配置。冒号前后分别为软限制和硬限制。systemd 文档明确提醒,提高软限制时要留意旧程序对 select(2) 的依赖;这类程序可能无法处理大于 1023 的描述符编号。应用是否采用兼容机制,需要查应用文档和运行条件。[2]

修改后重新加载单元配置,并在批准的窗口重启服务。

sudo systemctl daemon-reload
sudo systemctl restart example.service

daemon-reload 不会改变已运行进程的限制。普通业务配置 reload 也不能保证更新资源限制。重启可能中断请求、后台任务或长连接,需要提前排空流量并准备回退。

服务重新启动后,从新 PID 的 /proc/PID/limits 核实生效值,再检查 worker;仅看到配置文件里写了新数字还不够。有些程序启动后会自行调整限制,实际进程状态仍需单独确认。

容器场景要检查 Compose 或运行时传入的 nofile 限制,以及容器内实际进程的限制。修改宿主机某个登录会话的 ulimit 不会自动改好现有容器,配置变更往往需要按平台流程重建或重启工作负载。

系统级句柄耗尽有不同的证据

如果多个互不相关的服务同时无法打开文件,或者日志指向 ENFILE,再检查系统范围状态。

cat /proc/sys/fs/file-nr
cat /proc/sys/fs/file-max
cat /proc/sys/fs/nr_open

file-nr 给出已分配文件句柄数、已分配但未使用数及最大值。现代 Linux 的第二项通常为 0,解释时需要考虑内核版本。系统文件句柄数量与各进程描述符数量并非简单的一对一总和。[3]

file-max 控制系统范围可分配的文件句柄数量;nr_open 与单进程可设置的描述符限制上界有关。提高其中一个参数,不能替代对另一个层级的检查。[1][3]

系统级调参会影响整机。没有确认耗尽范围、内存预算和应用行为时,不应直接复制一组很大的 sysctl 数字。临时恢复要同步记录原值、有效期和撤销条件,后续仍需处理异常增长来源。

恢复后要验证能否稳定承接原有业务

重启可释放进程持有的描述符,却会抹掉一部分故障现场。情况允许时,重启前保留限制、类型分布、连接状态和日志;已经影响业务时则按应急预案决定取证与恢复的优先级。

验收至少覆盖新建连接、文件读写、数据库访问、后台任务和原先失败的接口。持续观察描述符占用能否随负载回落,确认错误日志不再增长,并核对延迟和失败率,避免“网站首页打开了”掩盖后台任务仍失败。

如果提高限制后占用继续单向增长,就需要回到连接生命周期或文件释放逻辑。新增容量可以缓解故障,但不能作为泄漏修复的验收结果。回退时恢复本次修改的 drop-in 和原有限制,再按同样流程加载、重启与复核;不要为回退一个参数而删除其他已有覆盖配置。

长期监控可以同时记录进程描述符数量、生效软限制、进程启动时间和业务并发。告警阈值应结合基线与增长速度设置。持续上升且流量已经回落的趋势,比一次孤立峰值更值得追查。

参考资料

资料核验日期:2026 年 10 月 28 日。文中命令是排查示例,调整前需核对发行版、systemd 版本及应用文档。

[1] Linux man-pages:getrlimit(2),RLIMIT_NOFILE、EMFILE 与限制规则。https://man7.org/linux/man-pages/man2/getrlimit.2.html

[2] systemd.exec:LimitNOFILE、软硬限制及 select 兼容性说明。https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html

[3] Linux man-pages:proc_sys_fs(5),file-nr、file-max 与 nr_open。https://man7.org/linux/man-pages/man5/proc_sys_fs.5.html

Linux运维

Linux 定时任务手动执行正常,cron 却不运行?环境变量、路径与日志排查

2026-10-26 10:07:36

实操指南知识库

智能网卡如何重塑现代服务器网络性能

2025-1-10 16:00:27