报错场景:使用socket做文件传输,运行中报错   too many open file

Too many open files是Linux系统中常见的错误,从字面意思上看就是说程序打开的文件数过多,不过这里的files不单是文件的意思,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle),这个错误通常也可以叫做句柄数超出系统限制。引起的原因就是进程在某个时刻打开了超过系统限制的文件数量以及通讯链接数。

linux 服务器上执行程序down机,查看log日志发现panic :too many open file

1、linux 句柄查看命令参考:

当你的服务器在大并发达到极限时,就会报出“too many open files”。

1.1  查看线程占句柄数 

运行  ulimit -a   查看我们open file的文件数量

其中
open files                      (-n) 1024         代表每个

1.2 查看系统打开句柄最大数量
more /proc/sys/fs/file-max

1.3  查看打开句柄总数
lsof|awk '{print $2}'|wc -l

1.4 根据打开文件句柄的数量降序排列,其中第二列为进程ID:

lsof|awk '{print $2}'|sort|uniq -c|sort -nr|more

1.5  查看某个进程目前打开的句柄数量
lsof -p 进程ID | wc  -l

1.6  根据获取的进程ID查看进程的详情
ps -ef |grep

2、修改句柄参数

2.1.修改“系统级”的 file-max

1

2

3

4

# 临时修改

# echo  6553560 > /proc/sys/fs/file-max 

# 或  sysctl -w "fs.file-max=6553560"

前面2种重启机器后会恢复为默认值

# 永久修改

# vim /etc/sysctl.conf, 加入以下内容,重启生效

fs.file-max = 6553560

2.2. 修改“进程级”的 ulimit 的open file,系统默认的ulimit对文件打开数量的限制是1024

1

2

3

4

5

# ulimit -HSn 65535  //这只是在当前终端有效,退出之后,open files又变为默认值。当然也可以写到/etc/profile中,因为每次登录终端时,都会自动执行/etc/profile

# 永久修改

# vim /etc/security/limits.conf  //加入以下配置,重启即可生效

* soft nofile 65535

* hard nofile 65535

修改以后保存,注销当前用户,重新登录,执行ulimit -a  查看是否生效

注意:
附录1.
为了让一个程序的open files数目扩大,可以在启动脚本前面加上ulimit -HSn 102400命令。但当程序是一个daemon时,可能这种方法无效,因为没有终端。

附录2.
如果某项服务已经启动,再动态调整ulimit是无效的,特别是涉及到线上业务就更麻烦了。
这时,可以考虑通过修改/proc/’程序pid’/limits来实现动态修改!!!

3、supervisor托管下的open file设置

此外,如果用supervisor托管和启动项目,会遇到这个配置无法生效的问题,原因在于supervisor会默认配置打开的句柄数量是1024,

如果要查看某个进程最大open files,可以通过这个进程的进程号对应的limits查看

cat /proc/进程ID/limits

其中有一行是:

Max open files 1024 1024 bytes

supervisor托管的程序这一行默认都是supervisor配置的最大数量1024,这时需要手动改一下supervisor的配置文件,修改方式如下,以Ubuntu系统为例,找到supervisor的配置文件supervisord.conf

在[supervisord]选项中,增加minfds选项的配置

[supervisord]
minfds=65535                  ; min. avail startup file descriptors; default 1024

配置完毕后,需要重启supervisor(以systemctl为例)

systemctl restart supervisor

即可生效


二、【深入了解】:

1、open file 修改原则

为什么需要修改两个参数和open file报错发生的根本原因? file-max和limits.conf中的两个参数?

我们已经了解到想要解决用户出现“too many open files”的问题需要同时修改用户级参数文件limits.conf及系统级参数文件sysctl.conf,那么怎么修改才合理呢?怎么修改才能万无一失呢?文章开始我提到,在最初出现“too many open files”问题的时候,我们只是简单粗暴的在nofile默认值和fs.file-max默认值后面加一个零甚至几个零,为什么会出现有时能解决问题,有时又无济于事的情况呢?我根据日常维护经验总结出了参数值设置需要遵循的以下几个原则:
1、根据limits.conf 中的soft nofile和hard nofile的定义:soft 指的是当前系统生效的设置值;hard 表明系统中所能设定的最大值,可以看出,soft nofile必须小于等于hard nofile值。

2、用户级打开文件数参数nofile必须小于等于系统级打开文件数参数fs.file-max。目前X86平台linux默认nofile为5000,fs.file-max为4096,在我们简单粗暴的在nofile默认值后增加几个零,一旦nofile值大于fs.file-max值时,打开文件数仍然会以fs.file-max值为准,也就是4096,仍然小于应用程序所需要的打开文件数,这就合理解释了为什么已经扩大了nofile值却仍然无法解决“too many open files”的问题了。

3、fs.file-max*4k 必须小于内存(字节数)。看到这个公式也许你会有些头晕,那么我来拿4G内存来举个简单的例子。如一台虚拟机内存为4G(4*1024*1024字节),根据公式算出fs.file-max必须小于1024*1024,约100万。也就是说拿一台4G内存的虚拟机来说,fs.file-max值设置低于100万是基于硬件条件下合理的数值;如果设置超出了100万的值,那么相当于对系统打开文件数无限制,没有预警机制,当系统打开文件数超过100万个时,系统将会夯死。换句话说,如果在当前内存下允许的最大文件打开数还是无法符合应用程序要求的话,只能使用增加内存的方式来提高性能了。

4、nofile最大值不可设置大于102万,大于102万的话会造成用户无法登陆。这个原则来自资深红帽系统工程师的口述,大家记住就好了。

注意:修改limits.conf 文件时候要根据“ 系统核数 ”进行修改,不能随便写,一般按照4核算的话 (4*1024*1024) 虚拟内存就这么大,大约一百万左右,你的file-max limit.conf中的那两个值就不能比这个大

如果写的比虚拟内存还打的后果就是sudo 登陆不上,系统无法打开新的文件,因为linux系统一切皆文件,所以后果会很难受,一般执行sudo的时候会有这个报错

sudo: pam_open_session: Permission denied
sudo: policy plugin failed session initialization

详情如下:

一次修改limits.conf 引发的血案

起因:
在重启nginx 过程中,发现有报 open file 限制的警告,于是没考虑太多,直接去修改/etc/security/limits.conf

修改前

*                soft    nofile          65536
*                hard    nofile          65536

修改后

*                soft    nofile          6553600
*                hard    nofile          6553600

保存退出,发现无论是复制窗口还是重新登录都会失败,因为是使用的普通账号,在执行sudo 和su 的时候也会报错如下

sudo: pam_open_session: Permission denied
sudo: policy plugin failed session initialization

原因:

/etc/security/ulimits.conf 文件中nofile 的软硬限制的值不能超过内核参数 /proc/sys/fs/nr_open ,否则就有问题

解决方案

  1. 如果已经重启启动,那没有没法了,只能重启,进入单用户模式,然后将limits.conf 修改为正常的
  2. 如果只有一个普通账号还登录着,也没有办法了,因为sudo也用不了,只能重启,单用户
  3. 如果还有会话使用root 用户登录着,可以直接用root修改回来,或者root把 /proc/sys/fs/nr_open 内核参数调大

关于linux上默认资源限制的一些参考知识

ulimit

ulimit 是用来限制用户在当前会话的资源限制的,若新开一个会话,则用户的会话级资源限制又会回复到默认值。如果要想让用户的资源限制的修改同步到用户的每个限制,有两种做法

  • 写入用户家目录的 profile or bashrc 中
  • 修改limits.conf

limits.conf

关于limits.conf 中nofile 的修改需要慎重,虽然根据man 手册,可以设置值为 -1,unlimited or infinity indicating no limit,但如果设置为-1,则会出现文章之前出现的问题。我这里还只是将nofile的值修改的太大就出现问题。

内核参数

具体的内核参数的解释可以查看http://man7.org/linux/man-pages/man5/proc.5.html

/proc/sys/fs/file-max

  • 操作系统级别的限制,所有进程打开的文件数之和不能超过这个值

/proc/sys/fs/file-nr

  • 操作系统级别的参数,查看当前已经打开的文件数以及操作系统允许的最大值

/proc/sys/fs/nr_open

  • 进程级别的参数,限制每个进程能打开的最大文件数

一次修改limits.conf 引发的血案 - 简书(来源)

2、单节点ES文件句柄数问题

请教下各位老哥,我有一个单节点的ES,总共有将近一千万条数据,索引有42个。
然后最近测试的同事反映ES占用文件句柄数太大:

但是我执行 /_nodes/stats/process 后,发现打开的文件数又很少:
 
"open_file_descriptors" : 1447,
"max_file_descriptors" : 1024000
 
1447对比70万,也差了太远了吧……
 
究竟哪一个才是正确的呢?
 另外如果70万是正确的,单节点ES为什么会有这么大的文件句柄占用呢?请教下各位有没有什么可以考虑优化的点。
 segments的数量我有定期合并,目前看segements的数量大概200多个。

解决方案:
 
使用lsof -n命令获得的结果是非常不准确的,它会把一些并没有占用句柄数的文件也一并计算在内。
 
使用ES API查到的数据是准确的。
 
再补充一下在linux查询进程占用fd比较准确的方法吧:ls -l /proc/<pid>/fd | wc -l

【Linux】报错 too many open file相关推荐

  1. linux 安装包 在此作用域中尚未声明_Linux运行go项目报错:copy_file_range: bad file descriptor...

    这两天在 Linux 环境部署一个 Go 项目遇到一个报错:copy_file_range: bad file descriptor.网上查找各种方法,花了两天的时间,经过一番折腾后才解决,觉得非常有 ...

  2. LINUX 报错:使用scp复制文件No such file or directory 及主机名注意事项

    在进行Linux文件传输的时候使用 scp /var/lib/rabbitmq/.erlang.cookie root@localhost:clone2:/var/lib/rabbitmq/ 报错: ...

  3. linux poi只有一列,poi linux 报错

    当前位置:我的异常网» 热门搜索 » poi linux 报错 poi linux 报错 www.myexceptions.net  网友分享于:2013-12-10   搜索量:135次 场景:小弟 ...

  4. py sel采集部署linux报错

    问题处理原因 py 使用driver 采集时,在windows正常采集:但是程序丢到linux中,报得异常处理问题 报错设置权限问题 File "/usr/local/python3.8/l ...

  5. scp 报错 not a regular file

    cnblogs中最新更新地址 scp 报错  not a regular file 两台 linux 服务器之间拷贝文件: 从 A 服务器(192.168.1.113) 拷贝到 B 服务器: 命令:  ...

  6. 【致敬嵌入式攻城狮第2期活动预热征文】解决瑞萨RA2E1开发板在RT-Thread的版本中编译报错 error: ‘board_cfg.h‘ file not found

    解决瑞萨RA2E1开发板在RT-Thread的版本中编译报错 error: 'board_cfg.h' file not found 继上上周在RA2E1开发板上跑通了RT-Thread最新版本的代码 ...

  7. pandas.read_csv() 报错 OSError: Initializing from file failed

    Python版本:Python 3.6 pandas.read_csv() 报错 OSError: Initializing from file failed,一般由两种情况引起:一种是函数参数为路径 ...

  8. 在NVIDIA Jetson Xavier NX上安装llvmlite报错:No such file or directory: ‘llvm-config‘: ‘llvm-config‘

    文章目录: 1 问题说明 2 解决问题方式 1 问题说明 1.在安装llvmlite的时候报错:No such file or directory: 'llvm-config': 'llvm-conf ...

  9. Keil编译报错:Cannot open include file: 'stdbool.h': No such file or directory问题解决

    Keil编译出现报错:Cannot open include file: 'stdbool.h': No such file or directory,或者出现Error: L6411E: No co ...

  10. pandas.read_csv() 报错 OSError: Initializing from file failed,报错原因分析和解决方法

    今天调用pandas读取csv文件时,突然报错" OSError: Initializing from file failed ",我是有点奇怪的,以前用的好好的,read_csv ...

最新文章

  1. struts2 iterator list中对象的list 双层迭代
  2. (0104)iOS开发之在Mac上用Charles给iPhone抓包
  3. rabbitmq集群报错
  4. VTK:Utilities之ShepardMethod
  5. 111. Minimum Depth of Binary Tree 二叉树的最小深度
  6. 2篇CIKM详解阿里妈妈搜索广告CTR模型如何低碳瘦身
  7. Vue+Electron下Vuex的Dispatch没有效果的解决方案
  8. 第5章 演绎推理与归纳推理
  9. Excel取消合并单元格后自动填写内容
  10. Unity制作AR小程序
  11. Excel计算BOM物料数量的公式
  12. 阿里云客服机器人人工服务配置文档
  13. 二叉树的层次遍历 II - LeetCode
  14. android网络音乐播放器
  15. c++期末考试样例(vm)
  16. MySQL(学习笔记)
  17. HTML报错 Malformed markup: Attribute “xxx“ appears more than once in element
  18. R语言快速制作学术论文三线表
  19. 推荐一款M1电脑可用的虚拟机软件
  20. C#实现DLT直接线性变换(Direct Linear Transform)算法

热门文章

  1. 零售银行的“制胜秘籍”:大数据驱动营销及管理
  2. 塞梅普雷斯 如是说 (第一部/8.烧纸的记忆) (草)
  3. Springboot响应结果仲裁机制怎么解决?!
  4. 云服务器搭建ThinkPHP框架图文教程
  5. 学习视频处理(三),前端播放器
  6. html中滚动条的代码是什么?如何设置html滚动条? 滚动条标签<marquee />自动滚动、花式滚动sao得一批
  7. 计算机二级Web(1):Web技术基础
  8. Kobe- python数据类型的学习
  9. 星球大战尤达(Baby Yoda)
  10. USound发布高性能ASIC线性音频放大器,提高真无线立体声装置、助听器和智能眼镜的电池寿命