打开文件过多

问题现象:

日志出现大量“打开文件过多”异常信息

问题分析:

通过网上查询,发现是由于系统参数设置问题造成,因为应用并发量大,http连接多了,随之socket的消耗也多了,socket文件描述符也是Linux系统文件描述符的一种,Linux操作系统对此也有限制,所以需要调大参数fs.max-file和/etc/security /limits.conf的soft nofile和hard nofile值

解决方案:

通过设置以上参数,加大数值,重启应用。

问题再现:

设置了以上参数后,还以为问题可以解决,但是一段时间过后,问题继续出现。

问题分析:

通过对各服务器检测以上参数值发现有些服务器的设置不生效,回想当时设置后检查是发现生效的,但为什么忽然又一些服务器又不生效了。

问题思考:

现在的问题已经不是应用层上的问题,是操作系统级别的问题,测试发现,ssh登陆ulimit -n查询limit.conf不生效,但su登陆,limit.conf生效。

问题发现:

通过对Linux的一些学习,原来limit.conf配置文件是Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pam_limits.so 的配置文件。具体如何生效,还得看PAM如何配置。

继续研究:

应用进程的最大文件打开数是否跟当前会话的limit.conf参数值有关?如果通过ssh登陆启动应用是否跟ssh登陆会话时候额最大文件打开数有关,而su登陆启动应用,此时的应用进程是否就会跟当前的最大文件打开数关联,文件得到答复,写了一小段C代码测试:

#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include<sys/resource.h>

main()
{
        struct rlimit limit;
        while(1){
               getrlimit(RLIMIT_NOFILE,&limit);
                printf("the process canopen %d files\n",limit.rlim_cur);
                sleep(2);
        }
}

这块代码是通过打印当前进程最大的文件打开书。经过测试,su进去的用户打开进程,打印的确实是limit.conf设置的值,而通过ssh进去执行这代码打印的却是修改limit.conf参数前的值(就是limit.conf没有生效)。这可能跟linux系统的进程、用户会话方面有关系,因为知识面窄,所以在论坛上提问了一下,网友就给了我我这样一个连接:http://linux.die.net/man/8/pam_limits。原文有这样一句话:“The pam_limitsPAM module sets limits on the system resources that can be obtained in auser-session. Users of uid=0 are affected by this limits, too.”这个pam_limits PAM在用户会话上有效,对0号进程(内核进程)也有是有效的。

关联疑问:

我们平时的操作时都是通过终端去操作的,开启进程的父进程都是当前终端进程,例如ssh,但有一些进程是在后台运行的。当开启了后,关闭终端,那他们归属谁呢?通过观察发现。这些孤独的进程都是被1号进程接收了。这里可能就涉及到linux进程管理的问题了。暂不再深入研究。

我想到了一种情况,如果我用ssh进去开启进程,这父进程的ID是我这ssh进程。当我退出ssh后,那个子进程没有关闭就归1号进程管了(例如我们常见的java进程)。那这个子进程的最大文件打开数会不会就变回limit.conf文件设置的值呢?因为ssh进程进去的值是limit.conf修改前的值。ssh进去开启我那测试进程打印的确实是跟当前的limit.conf值不一样,就是没有生效。我又在网上找到了一个方法,直接把那测试代码的子进程直接赋予给1号进程:setsid。经过测试,打印出来的最大文件打开数没变。就像上面说的这个PAM设置跟用户会话有关系。

测试over。以后发现有问题,继续跟进。

时间: 2024-08-01 01:59:08

打开文件过多的相关文章

org.apache.tomcat.util.net.NioEndpoint,打开的文件过多

错误信息: 27-Mar-2019 04:20:20.430 严重 [http-nio-8100-Acceptor-0] org.apache.tomcat.util.net.NioEndpoint$Acceptor.run Socket accept failed java.io.IOException: 打开的文件过多 at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) at sun.nio.ch.ServerSocket

打开文件open()函数的使用方法详解--C语言函数

头文件:#include <sys/types.h>    #include <sys/stat.h>    #include <fcntl.h> 定义函数: int open(const char * pathname, int flags); int open(const char * pathname, int flags, mode_t mode); 函数说明: 参数 pathname 指向欲打开的文件路径字符串. 下列是参数flags 所能使用的旗标: O_R

Linux centos 下 eclipse 打开文件时关闭

原文地址:http://processors.wiki.ti.com/index.php/Linux_Host_Support#cairo-misc.c:380:_cairo_operator_bounded_by_source:_Assertion_.60NOT_REACHED.27_failed http://processors.wiki.ti.com/index.php/Linux_Host_Support 现象描述:在 centos 系统下,打开eclipse后,打开文件时,eclip

Unix文件系统学习笔记之二: 文件描述符、inode和打开文件表

Unix文件系统学习笔记之二: 文件描述符.inode和打开文件表 系统盘上数据的布局 文件系统无非是关于数据在磁盘上的组织以及存储空间管理的,为此,首先需要知道磁盘上数据的总体布局方式.以Unix为例,最重要的一张表如下: Unix 进程管理中和用户文件.io 最相关的数据结构:usr 数据结构 The procstructure does not record information related to file access.  However the userstructure con

Linux中的文件描述符与打开文件之间的关系

1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件.链接文件和设备文件.文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符.程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误.如果此时去打开一个新的文件,它的文件描述符会是3.POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号

打开文件和关闭文件

1 打开文件 在对文件进行读.写操作之前,首先要解决的问题是如何把程序中要读.写的文件与磁盘上实际的数据文件联系起来.在 C 语言中这并不困难,只需调用 C 语言提供的库函数 fopen “打开”文件就可实现这些联系.fopen 函数的一般调用形式为: fopen(文件名,文件使用方式); 函数返回一个指向 FILE 类型的指针.例如: FILE *fp; fp = fopen("file_a", "r"); fopen 函数调用中有两个字符串作为参数.第一个字符串

mac安装office2011,提示无法打开文件Normal.dotm,因为内容有错误

最近使用mac上的office,发现一个问题,每次打开office11都会报错,提示“无法打开文件Normal.dotm,因为内容有错误”,于是就在网络上搜索了一下,找到如下一段话, I just found out that my kids were playing on my computer and accidentally renamed my main drive to "]?[". After renaming it something appropriate, it op

文件描述符、文件描述符表、打开文件表、目录项、索引节点之间的联系

文件描述符.文件描述符表.打开文件表.目录项.索引节点之间的联系如下图所示: 每个进程在PCB(Process Control Block)中都保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针,已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体. 在file结构体中维护File Status Flag(file结构体的成员f_flags)和当前读写位置(file结构体的成员f_pos).在上图中,进程1和进程2都打开同一文件,

如何找到文件的家-打开文件对话框openFileDialog

private void button1_Click(object sender, EventArgs e) { openFileDialog1.Filter = "*.txt|*.txt";//设置文件 DialogResult dr = openFileDialog1.ShowDialog();//显示打开文件对话框 if (dr ==DialogResult.OK) { richTextBox1.Text = System.IO.File.ReadAllText(openFile