欢迎光临
我们一直在努力

Linux报Too many open files怎么办

Linux服务器上的网站、接口或后台程序运行一段时间后,可能突然出现以下报错:

Too many open files

随后,程序可能无法打开文件、建立连接或接受新的请求。重启服务后暂时恢复,但运行一段时间又出现相同问题。

这类故障需要同时检查进程实际使用的文件描述符、资源限制和占用增长情况。本文以Debian、Ubuntu服务器为例,介绍一套可以逐步执行的排查方法。

1. Too many open files是什么意思?

Linux程序打开普通文件、网络套接字或管道时,通常会使用文件描述符,简称FD。

因此,“打开文件过多”不一定是程序打开了大量磁盘文件,也可能是网络连接、管道或其他对象占用了描述符。

在普通文件打开等场景中,可以先区分两类错误:

错误标识主要含义优先检查
EMFILE触及单个进程的文件描述符限制出错进程的限制与占用
ENFILE触及系统范围的打开文件上限系统文件句柄总量与上限

这两种情况的处理位置不同。只提高系统的fs.file-max,不能直接解决某个进程自身限制过低的问题。

如果日志只有一句英文提示,还应结合具体失败操作和程序上下文判断,不能只凭文字就修改全部系统参数。

2. 操作环境与准备

本文主要适用于使用systemd管理系统服务的Debian、Ubuntu服务器。

所有命令均在服务器终端执行。使用具有sudo权限的账户操作;如果已经使用root登录,可以去掉sudo。

以下内容中:

  • myapp.service是示例服务名,需要替换为实际服务。
  • 2468是示例PID,需要替换为出错进程的实际编号。
  • 配置中的限制数值用于演示,需要结合应用要求和现有配置确定。

本教程可在莱卡云Linux云服务器上操作,已有服务器的用户可以直接检查当前环境。

查看官网购买链接: https://www.lcayun.com

9折优惠码:bloglcayun

3. 先确认是哪个进程报错

如果程序由systemd管理,先查看服务状态:

sudo systemctl status myapp.service --no-pager -l

查看主进程PID:

sudo systemctl show myapp.service -p MainPID

查看本次开机期间,该服务最近的日志:

sudo journalctl -u myapp.service -b -n 100 --no-pager

重点记录报错时间、进程编号,以及错误发生在打开文件、接受连接还是其他操作中。

如果MainPID=0,说明当前没有可供查询的主进程,应先检查服务状态,不能继续使用PID 0进行后续排查。

多进程服务还需要检查实际报错的工作进程。 主进程的占用较低,不代表所有工作进程都正常。

找到目标PID后,可以核对进程身份:

ps -p 2468 -o pid,ppid,user,comm

如果程序已经自动重启,PID可能发生变化,应重新确认。

4. 检查进程的实际限制与占用

4.1 查看文件描述符限制

执行:

sudo cat /proc/2468/limits

在输出中找到:

Max open files

下面仅用于解释字段,不代表实际服务器输出:

Limit                     Soft Limit           Hard Limit           Units
Max open files            1024                 524288               files

其中:

  • Soft Limit: 当前执行的软限制。
  • Hard Limit: 软限制可以调整到的上限,普通进程不能自行突破它。

/proc/PID/limits反映目标进程当时的资源限制,应以这里的实际结果为依据。

4.2 查看当前占用了多少描述符

执行:

sudo ls -1U /proc/2468/fd | wc -l

该命令统计目标进程FD目录中的条目数量。

如果占用接近软限制,并且同一时间出现EMFILE错误,就应重点检查该进程的资源使用。

注意两点:

  • 进程不断打开和关闭文件,统计结果只是当时的快照。
  • 如果出现权限不足或目录不存在等错误,统计结果不能作为有效依据。

一次查询数量正常,也不能排除此前发生过短时峰值。

4.3 为什么ulimit显示很大,服务仍然报错?

在当前Bash终端执行:

ulimit -Sn
ulimit -Hn

这两条命令分别查看当前Shell的软限制和硬限制。

Shell的限制会影响它后续启动的进程,但不代表已经运行的systemd服务也采用相同数值。

排查服务时,应以出错PID的实际限制和占用为依据。

Linux当前终端、目标进程与系统文件句柄限制的区别

5. 找出描述符主要被什么占用

查看目标进程FD对应的对象:

sudo ls -l /proc/2468/fd

常见结果可以这样理解:

链接目标或形式对应对象
普通文件路径日志、配置、数据文件等
socket:[编号]网络套接字或Unix套接字
pipe:[编号]管道
anon_inode:[eventpoll]等epoll等内核对象

这些对象本身都可能正常存在,不能看到大量socket或某个特殊名称,就直接认定程序异常。

接下来,应在相近业务负载下观察占用变化:

  • 请求结束后,连接和描述符是否能够回落?
  • 是否持续打开相同类型的文件,却没有及时关闭?
  • 客户端连接池是否过大,或者反复创建新连接?
  • 异常分支、超时处理是否遗漏了资源释放?

如果占用随业务增长后保持稳定,可能需要结合正常峰值调整容量;如果长期持续上涨,则应进一步检查资源泄漏或回收逻辑。

如果链接目标出现(deleted),并且同时存在删除文件后磁盘空间没有释放的问题,可以参考本站文章:

Linux删除文件后磁盘空间不释放怎么办?

6. systemd服务如何调整文件描述符限制?

确认服务确实需要更高上限后,再修改对应服务的配置。

调整前应确认应用支持较高的文件描述符编号。 使用传统select()接口的程序,在Linux上处理超过1023的描述符可能存在兼容性问题,不能把调大限制作为所有程序的通用方案。

6.1 编辑服务覆盖配置

下面沿用第4节的示例:原软限制为1024、硬限制为524288,假设应用要求将软限制提高到65536,并保留原硬限制。

执行:

sudo systemctl edit myapp.service

在编辑器的可编辑区域加入:

[Service]
LimitNOFILE=65536:524288

如果已经存在[Service]段,应修改对应设置,并保留其他配置。

冒号前是软限制,后面是硬限制。示例数值不是所有服务器的推荐值,应根据实际查询结果和应用要求调整。

6.2 加载配置并重启对应服务

保存退出后,在允许短暂中断业务的维护时间执行:

sudo systemctl daemon-reload &&
sudo systemctl restart myapp.service

然后检查状态:

sudo systemctl status myapp.service --no-pager -l

daemon-reload用于重新加载服务定义;重启服务后,新启动的进程才会按照相应配置运行。仅修改文件或执行daemon-reload,不会改变旧进程的资源限制。

如果服务修改后无法启动,可以结合本站文章继续排查:

Linux程序手动运行正常,systemd启动失败怎么办?

6.3 检查新进程是否采用了配置

查看服务管理器中的相关属性:

sudo systemctl show myapp.service \
  -p MainPID \
  -p LimitNOFILESoft \
  -p LimitNOFILE

其中,LimitNOFILESoft对应软限制,LimitNOFILE对应硬限制。

再读取当前主进程的实际限制:

app_pid=$(sudo systemctl show myapp.service -p MainPID --value)

if [ "$app_pid" -gt 0 ] 2>/dev/null; then
  sudo cat "/proc/$app_pid/limits"
else
  printf '%s\n' '未找到运行中的主进程,请检查服务状态。'
fi

多进程服务还应重新确认工作进程PID,并按第4节的方法检查。部分应用会在启动过程中自行调整限制,因此只看服务管理器属性还不够。

最终应以实际运行进程的limits为准,并结合业务请求确认恢复情况。

7. 如果是系统文件句柄总量达到上限呢?

如果错误信息指向ENFILE,或者多个无关服务同时出现文件打开失败,可以检查系统范围的使用情况:

cat /proc/sys/fs/file-nr

这三个数字依次表示:

  1. 已分配的文件句柄数量。
  2. 已分配但未使用的数量。
  3. 系统允许的最大数量。

现代Linux中,第二个数字通常为0,这本身不代表异常。

继续查看:

sysctl fs.file-max fs.nr_open

两个参数的含义不同:

参数作用
fs.file-max系统范围的文件句柄分配上限
fs.nr_open单进程文件描述符硬限制可设置的内核上界

系统文件句柄统计与各进程FD数量并非简单的一一对应关系,不应直接把所有进程的FD数量相加后与file-max比较。

只有确认系统总量确实触及上限后,才应结合内存、业务规模和异常占用评估是否调整。当前查询值已经回落时,还需要结合故障时段的记录判断。

8. 如何确认问题真正解决?

修改完成后,建议检查以下三项:

  1. 限制是否生效: 新进程的Max open files符合预期。
  2. 业务是否恢复: 原先失败的文件操作、连接或请求能够正常完成。
  3. 占用是否稳定: 在相近负载下观察FD数量,确认没有持续异常增长。

同时检查修改后的服务日志:

sudo journalctl -u myapp.service \
  --since "10 minutes ago" \
  --no-pager

如果提高上限后,程序只是更晚出现同样的错误,说明还需要继续处理文件或连接的增长来源。

对于手动从Shell启动的程序、容器中的程序以及其他进程管理器启动的服务,应检查各自的启动配置。本文的systemd设置不能直接覆盖所有启动方式。

9. 写在最后

遇到Too many open files,先找到实际报错的进程,再核对它的限制、占用对象和增长趋势。

如果属于合理业务量超过现有限制,可以按照应用要求调整;如果存在资源未释放的问题,则需要修复连接或文件的管理逻辑。

把故障时间、实际PID、限制数值和处理结果记录下来,后续再次出现类似问题时,就能更快判断是容量变化还是程序异常。

赞(0)
未经允许不得转载:莱卡云 » Linux报Too many open files怎么办