首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >“too many open files”的原理和解决方案

“too many open files”的原理和解决方案

原创
作者头像
cutd
修改于 2020-01-21 08:06:34
修改于 2020-01-21 08:06:34
13.7K30
代码可运行
举报
文章被收录于专栏:后台开发专栏后台开发专栏
运行总次数:0
代码可运行

错误原理:

“too many open files”这个错误大家经常会遇到,因为这个是Linux系统中常见的错误,也是云服务器中经常会出现的,而网上的大部分文章都是简单修改一下打开文件数的限制,根本就没有彻底的解决问题。

本文就是帮助开发者理解这个问题的来龙去脉,确保大家读完本文之后能够彻底明白和解决这个问题。首先一定要明确机器为什么会报这个错误,其次才好更加深入的去解决这个问题,正如错误信息的字面意思,就是打开了过多文件,系统无法继续打开文件句柄了。这里的file更准确的意思文件句柄(file handle),出现这个报错的大多数情况都是文件句柄(file handle)泄露,通俗的说就是文件句柄在不断的被打开,但是在使用完成之后却没有正常的关闭导致文件打开数不断的增加。

文件句柄泄露有多种原因,而不仅仅是打开文件,常见的来源有:套接字,管道,数据库连接,文件。正常情况下服务器本身是不会突然报这个错误的,一定是我们部署到云服务器上面的业务程序打开了太多文件没有关闭导致同时打开的文件数超出了系统的限制

一种情况是程序本身就需要打开很多的文件句柄,这种情况就是打开的文件数大于系统本身的打开文件数限制,这时需要我们将系统的限制调高,后面会给出具体的方法;

另外一种情况就是我们的程序存在文件句柄使用完成之后没有正常的关闭的情况,通常是网络连接没关闭,文件打开没关闭等等,这时就需要我们修复程序中的bug,确保打开的文件最后都会关闭,网络连接也会关闭。

分析问题:

为了准确的定位到具体问题在哪里,我们就需要使用lsof命令,下面就lsof相关信息做一个基本的介绍:

文件描述符:fd(file descriptor),在Linux系统中一切皆可以看成是文件,文件描述符是内核为了高效管理已被打开的文件所创建的索引,是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。

linux命令lsof(list system open files):列出系统打开的文件,在终端下输入lsof即可显示系统打开的文件。lsof各个字段的含义:

COMMAND

PID

TID

USER

FD

TYPE

DEVICE

SIZE

NODE

NAME

程序的名称

进程标识符

线程标识符

进程所有者

文件描述符

文件类型

设备编号

文件的大小(bytes)

索引节点

打开文件的确切名称

FD 列中的常见内容有 cwd、rtd、txt、mem 和一些数字等等。其中 cwd 表示当前的工作目录;rtd 表示根目录;txt 表示程序的可执行文件;mem 表示内存映射文件。所以一般文件句柄打开的FD都是数字开头的,比如"0u","1u","2u"。

这里我们先使用lsof找出打开文件数较多的进程,然后再挨个排查其打开文件数的具体情况:

下面这个命令可以看到当前进程文件打开数的数量排序,第一列是打开文件数,第二列是pid,由于lsof的结果会包含线程和系统默认类型的FD,和实际的FD打开数区别较大,所以还需要根据这个命令的排序拿对应的pid再去排查真实的FD打开数量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
lsof -n |awk '{print $2}'|sort|uniq -c|sort -nr|more

[root@linux]# lsof -n |awk '{print $2}'|sort|uniq -c|sort -nr|more
   1652 17336
   1376 3577
   1296 17335
   1247 9380
    944 17329
    912 17330
    910 4576
    800 26693
    .........
    more

上面的结果虽然和实际有区别,但是排序基本上是比较一致的,然后再使用下面这个命令查看对应pid进程真实打开的fd数量,看看是否过高,通常来说超过1000就算过高了,如果定位到了具体的进程,然后就要检查对应的程序了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
lsof -p <pid>| awk '{print $4}' |grep "^[0-9]" |wc -l 
[root@linux]# lsof -p 17336| awk '{print $4}' |grep "^[0-9]" |wc -l 
47

可以看到实际进程pid 17336 的打开FD数为47,那1652个计数是因为有很多线程都共用了这47个打开的文件,所以最后计算的结果与实际的结果区别较大。我们还可以根据 ls /proc/<pid>/fd 这个命令来确认一下最终的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@linux]# ls /proc/17336/fd
0  10  12  14  16  18  2   21  23  25  27  29  30  32  34  36  38  4   41  43  45  5  7  9
1  11  13  15  17  19  20  22  24  26  28  3   31  33  35  37  39  40  42  44  46  6  8

可以看到进程17336 目录下就是只打开了47个fd,属于正常的打开文件数量。另外,硬盘文件删除后没有释放磁盘空间也是这个原因,因为删除文件的文件句柄未关闭,也可以使用上面的方法去排查

命令拓展:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ulimit -n是1024的意思是由root用户执行的某个进程最多只能打开1024个文件,并非root总共只能打开1024个文件。

ls /proc/<pid>/fd | wc -l  统计pid对应进程打开的fd数量。

lsof -p <pid>| awk '{print $4}' |grep "^[0-9]" |wc -l 这个命令的结果和上面的命令应该是一样大。

lsof -u root 这个命令是查看用户粒度的文件打开信息,lsof的结果包含memory mapped .so-files,这些在原理上并不是一般的应用程序控制的fd,所以通常要把这一部分的过滤掉。

lsof -u root| awk '{print $4}' |grep "^[0-9]" |wc -l 查看用户粒度的fd打开数。

cat /proc/pid/limits  这个文件记录了pid进程的所有的limits值,一般以这个为准。



修改配置提高用户的系统打开文件数限制:

vi /etc/security/limits.conf

root soft nofile 8192
root hard nofile 8192

第一列为用用户名,*表示所有用户。 * - nofile 8192 是最简单的全局设置。


cat /proc/sys/fs/file-max 表示当前内核可以打开的最大的文件句柄数,一般为内存大小(KB)的10%,一般我们不需要主动设置这个值,除非这个值确实较小。

cat /proc/sys/fs/file-nr  第一个数字表示当前系统打开的文件数。第三个数字和cat /proc/sys/fs/file-max结果一样表示当前内核可以打开的最大的文件句柄数。

拓展阅读:

如何诊断 'TOO MANY OPEN FILES' 问题?

Linux lsof命令详解

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
3 条评论
热度
最新
lsof -p 15103| awk '{print $4}' |grep "^[0-9]" |wc -l 对应的数字直线上涨,是不是可以判断为泄露了,然后我再打印文件列表 lsof -p 15103,是不是可以看出来是哪些了
lsof -p 15103| awk '{print $4}' |grep "^[0-9]" |wc -l 对应的数字直线上涨,是不是可以判断为泄露了,然后我再打印文件列表 lsof -p 15103,是不是可以看出来是哪些了
11点赞举报
是的
是的
回复回复点赞举报
请教下,报这个错的时候,需要比较哪两个命令对应的数值
请教下,报这个错的时候,需要比较哪两个命令对应的数值
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
File Descriptor问题总结
在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。 文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。 程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号码,因此,在网络通信过程中稍不注意就有可能造成串话。标准文件描述符图如下:
mingjie
2022/05/12
1.2K0
File Descriptor问题总结
file_handle_windows句柄
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
全栈程序员站长
2022/11/07
7870
文件句柄与文件描述符
1.概述 在实际工作中会经常遇到一些bug,有些就需要用到文件句柄,文件描述符等概念,比如报错: too many open files, 如果你对相关知识一无所知,那么debug起来将会异常痛苦。在Linux操作系统中,文件句柄(包括Socket句柄)、打开文件、文件指针、文件描述符的概念比较绕,而且windows的文件句柄又与此有何关联和区别?这一系列的问题是我们不得不面对的。 这里先笼统的将一下自己对上面的问题的一些理解: 句柄,熟悉Windows编程的人知道:句柄是Windows用来标识被应用程序
用户1263954
2018/01/30
5.3K0
文件句柄与文件描述符
Too many open files (CLOSE_WAIT过多)的解决方案:修改打开文件数的上限值、调整TCP/IP的参数
close_wait 状态出现的原因:客户端要与服务端断开连接,先发一个FIN表示自己要主动断开连接了,服务端会先回一个ACK,这时表示客户端没数据要发了,但有可能服务端数据还没发完,所以要经历一个close_wait,等待服务端数据发送完,再回一个FIN和ACK。
公众号iOS逆向
2022/08/22
2.7K0
Too many open files (CLOSE_WAIT过多)的解决方案:修改打开文件数的上限值、调整TCP/IP的参数
解决Linux错误:"too many open files"问题
查看打开文件的最大限制命令 ulimit-a, open files(-n)1024即为最大打开的文件数,修改限制使用命令 ulimit-n2048,2048为修改到最大打开文件数为2048;
Qt君
2019/07/15
3.4K0
解决 Swoole 服务报错 Too many open files 文件句柄超出系统限制
如果在 Swoole 的日志中遇到了 Too many open files 这种报错,不要慌,在开发 TCP 网络应用的过程中,经常会遇到Too many open files这个问题。
沈唁
2021/09/14
1.8K0
Docker报错 too many open files
在Linux系统内默认对所有进程打开的文件数量有限制(也可以称为文件句柄,包含打开的文件,套接字,网络连接等都算是一个文件句柄)
程哲
2021/10/09
5K0
[ubutnu]too many open files问题解决方法
一、产生原因 too many open files(打开的文件过多)是Linux系统中常见的错误,从字面意思上看就是说程序打开的文件数过多,不过这里的files不单是文件的意思,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle),这个错误通常也可以叫做句柄数超出系统限制。 引起的原因就是进程在某个时刻打开了超过系统限制的文件数量以及通讯链接数,通过命令ulimit -a可以查看当前系统设置的最大句柄数是多少:
云未归来
2025/07/21
1200
limit资源限制ulimit 详解
系统性能一直是一个受关注的话题,如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件下保证程序的运作,ulimit 是我们在处理这些问题时,经常使用的一种简单手段。ulimit 是一种 Linux 系统的内键功能,它具有一套参数集,用于为由它生成的 shell进程及其子进程的资源使用设置限制。
黄规速
2022/04/15
8K0
limit资源限制ulimit 详解
Linux下查看进程打开的文件句柄数
在 Linux 平台上运行的进程都会从系统资源申请一定数量的句柄,而且系统控制了进程能够申请的最大句柄数量。用户程序如果不及时释放无用的句柄,将会引起句柄泄露,从而可能造成申请资源失败,导致系统文件句柄用光连接不能建立。本文主要介绍Linux下如何查看和修改进程打开的文件句柄数,避免这类问题的发生。
九州暮云
2019/08/21
57.2K2
K8s云原生环境下文件描述符占用过高查询思路
在K8s云环境下,如何查询某一Linux系统进程ID与Pod对应关系需要一定的技巧。本文利用在K8s集群中某一机器的文件描述符占用过高的问题,排查定位到对应Pod的一次经验记录Linux系统进程ID与Pod对应关系查询思路。
莲子心
2025/07/14
1010
linux文件句柄数上限_怎么清除文件句柄
网上说什么的也有,你抄我的我抄你的,也是醉了,故自己综合查阅的资料,根据自己的理解和判断以及部分的实践整理下吧,也不敢保证都是对的,如果有比较大的错误,希望看到这篇文章的你提出来,大家共同进步!
全栈程序员站长
2022/11/02
5.4K0
Linux下各种连接数配置
使 /etc/sysctl.conf 的配置生效,根据实际情况来决定是否添加此命令
码客说
2021/11/24
3K0
刨根问底,看我如何处理 Too many open files 错误!
如果你的项目中支持高并发,或者是测试过比较多的并发连接。那么相信你一定遇到过“Too many open files”这个错误。
Bug开发工程师
2021/03/03
3.8K0
刨根问底,看我如何处理 Too many open files 错误!
文件句柄和文件句柄泄漏解决「建议收藏」
通常的分析手法如下(转自:https://blog.csdn.net/xiaolli/article/details/56012228): (1). 确定是哪类文件打开太多,没有关闭.
全栈程序员站长
2022/11/02
3.6K0
一则open files的故障
某套应用,部署在Linux下的中间件上,在某个时刻开始报警,从日志看是无法获取JDBC连接,
bisal
2019/08/18
9100
使用ulimit 命令、/etc/security/limits.conf、proc 调整系统参数
Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用其实很容易就达到这个数量 系统总限制是在这里,/proc/sys/fs/file-max.可以通过cat查看目前的值,修改/etc/sysctl.conf 中也可以控制. /proc/sys/fs/file-nr,可以看到整个系统目前使用的文件句柄数量 linux 中数据的含义 /proc/sys/fs/file-nr [root@localhost logs]# cat /proc/sys/fs/fi
sunsky
2020/08/20
2.1K0
RLIMIT_NOFILE设置陷阱:容器应用高频异常的元凶
我们在Fedora系统上将containerd.io从1.4.13版本升级到了1.5.10之后,发现多个项目中所有MySQL 容器实例消耗内存暴涨超过20GB,而在此之前它们仅消耗不到300MB。同事直接上了重启大招,但重启后问题依旧存在。最后选择回滚到1.4.13版本,该现象也随之消失。
zouyee
2024/06/19
8660
RLIMIT_NOFILE设置陷阱:容器应用高频异常的元凶
解决Nginx出现“Too many open files”的问题
最近发现https://imgurl.org/ 自建CDN节点偶尔出现无法打开的情况,查看服务器负载不高,nginx连接数大概在1024后就无法处理,按理说nginx处理1024左右的并发还是绰绰有余的,但就是出现无法打开的情况,查看nginx错误日志,出现大量的“Too many open files”错误,大致意思就是说nginx无法打开更多的文件,看来问题并不在并发数上面。
星哥玩云
2022/08/13
2.9K0
解决Nginx出现“Too many open files”的问题
关于I/O模型,和select、poll、epoll的区别
I/O模型主要包括:阻塞IO、非阻塞IO、I/O 多路复用、异步I/O和信号I/O;
呱牛笔记
2023/05/02
4510
关于I/O模型,和select、poll、epoll的区别
推荐阅读
相关推荐
File Descriptor问题总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验