1、问题现象
这是一个基于的应用系统,在后台添加数据时提示难以添加,于是登陆查看Tomcat日志,发觉如下异常信息:
java.io.IOException:Toomanyopenfiles
通过这个报错信息,基本判定是系统可用的文件描述符不够了,因为Tomcat服务是系统www用户启动的,于是以www用户登入系统,通过“ulimit-n”命令查看系统可以打开最大文件描述符的数目,输出如下:
[www@tomcatserver~]$ulimit-n
65535
可以看见这台服务器设置的最大可打开的文件描述符早已是65535了,那么大的值应当够用了,然而为何提示这样的错误呢?
2、解决思路
这个案例涉及下ulimit命令的使用,这儿简单介绍下ulimit的作用和使用方法。ulimit主要拿来限制对资源的使用情况,它支持各种类型的限制linux驱动下载,常用的有:
●内核文件的大小限制。
●数据块的大小限制。
创建文件大小限制。
●可加锁显存大小限制。
●常驻显存集的大小限制。
●打开文件句柄数限制。
●分配堆栈的最大大小限制。
●CPU占用时间限制用户最大可用的数限制。
●所能使用的最大虚拟显存限制。
ulimit使用的基本格式为:
ulimit[options][limit]
具体的ulimit参数(即options)含意如表1所示。
表1ulimit参数的涵义
在使用ulimit时,有以下几种使用方式。
(1)在用户环境变量中加入
假如用户使用的是bash,这么可以在用户目录的环境变量文件.bashrc或.bash_profile中加入“ulimit-u128”来限制用户最多可以使用128个进程。
(2)在应用程序的启动脚本中加入
倘若应用程序是Tomcat,这么可以在Tomcat的启动脚本startup.sh中加入“ulimit-n65535”来限制用户最多可以使用65535个文件描述符。
(3)直接在shell命令终端执行ulimit命令
这些技巧的资源限制仅仅在执行命令的终端生效,在退出或关掉终端后,设置失效,而且这个设置不影响其他shell终端。
有时侯为了便捷起见linux文件句柄数,也可以将用户资源的限制统一由一个文件来配置,这个文件就是/etc/security/limits.conf,该文件不但能对指定用户的资源进行限制,能够对指定组的资源进行限制。该文件的使用规则如下:
其中:
●domain表示用户或用户组的名子,还可以使用“*”作为键值,表示任何用户或用户组。
●type表示限制的类型,可以有两个值:soft和hard,分别表示软、硬资源限制。
●item表示须要限定的资源名称,常用的有nofile、cpu、stack等。分别表示最大打开句柄数、占用的CPU时间、最大的堆栈大小。
●value表示限制各类资源的具体数值。
不仅limits.conf文件之外,还有一个/etc/security/limits.d目录,可以将资源限制创建一个文件放在这个目录中,系统默认会首先读取这个目录下的所有文件,之后才去读取limits.conf文件。在所有资源限制设置完成后,退出终端,再度登陆终端后,ulimit设置即可手动生效。
3、解决问题
在了解ulimit知识后,接着里面的案例,既然ulimit设置没问题,这么一定是设置没有生效致使的。接出来检测下启动Tomcat的www用户环境变量下是否添加了ulimit限制,检测后发觉,www用户下并无ulimit资源限制。于是继续检测Tomcat启动脚本startup.sh文件是否添加了ulimit限制linux文件句柄数,检测后发觉也没有添加。最后考虑是否将限制加到了limits.conf文件中,于是检测limits.conf文件,操作如下:
[root@tomcatserver~]#cat/etc/security/limits.conf|grepwww
wwwsoftnofile65535
wwwhardnofile65535
从输出可知,ulimit限制加在了limits.conf文件中linux标准教程,既然限制早已加了,配置也没有错,为什么都会报错呢?经过长时间思索,判定只有一种可能,那就是Tomcat的启动时间早于ulimit资源限制的添加时间,于是首先查看下Tomcat的启动时间,操作如下:
[root@tomcatserver~]#more/etc/issue
CentOSrelease6.3(Final)
Kernelronanm
[root@tomcatserver~]#uptime
15:10:19up283days,5:37,4users,loadaverage:1.20,1.41,1.35
[root@tomcatserver~]#pgrep–ftomcat
4667
[root@tomcatserver~]#ps-eopid,lstart,etime|grep4667
4667SatJul609:33:39201377-05:26:02
从输出可以看出,这台服务器早已有283天没有重启过了,而Tomcat是在2013年7月6日9点多启动的,启动了近77天零5个半小时了,接着继续瞧瞧limits.conf文件的更改时间,操作如图1所示。
图1查看limits.conf文件的最后更改时间
通过stat命令可以很清楚地看出,limits.conf文件最后的更改时间是2013-07-12,通过查问相关的Linux系统管理人员,基本确认就是在这个时侯添加的ulimit资源限制,这样此案例的问题就很明晰了。因为ulimit限制的添加时间晚于Tomcat最后一次的启动时间,而在此期间内,Tomcat服务仍然未重启过,操作系统也始终未重启过,这么ulimit资源限制对于Tomcat来说仍然是不生效的,同时,因为此操作系统是CentOS6.3,系统默认的最大可用句柄数是1024,java进程采用的是Linux默认的这个值,因而出现“Toomanyopenfiles”的错误也是合乎情理的。