某linux服务器的日志每隔几天就会报错。内容如下:
[2012-02-22 09:50:00,119] ERROR ipnet.dc.pmprobe.SnmpScalarQueryJoe.execute()(146) – Too many open files java.net.SocketException: Too many open files
向同事咨询了一下,一般报Too many open files的错,表示文件句柄数超出最大。对linux系统来说,默认的最大值为1024,在系统并发比较大的时候,这个很容易超过该值。文件句柄数大小可以通过命令ulimit -a查看。
用命令ulimit -a查看
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 256751 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 256751 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
为避免因程序任务过多导致文件句柄数不够的问题,在linux系统下部署程序的时候可以调大用户文件句柄数。用root用户修改/etc/security/limits.conf 配置,在文件末尾添加如下内容:
user soft nofile 2048
user hard nofile 65536
其中user为报错程序部署目录的用户名,根据部署环境配置。注意”nofile”项有两个可能的限制措施。就是<type>项下的hard和soft。硬限制表明soft限制中所能设定的最大值。soft限制指的是当前系统生效的设置值。hard限制值可以被普通用户降低。但是不能增加。soft限制不能设置的比hard限制更高。只有root用户才能够增加hard限制值。
修改完成后切换到user用户下再执行ulimit -a查看文件句柄数是否修改成功。
改完后,验证,发现用户的文件句柄数已变成2048.应该可以应对大并发数啦。
这里只是修改最大句柄数,另外一个问题,如何知道当前进程打开了多少个文件句柄呢?可以通过下面一段小脚本可以帮你查看:
[root@VM192168200201 etc]# lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more 738 26249 164 16540 154 16538 150 16581 135 16640 135 16638 134 16990 131 16615 121 16095 119 16617 118 16510 116 16600 115 16548 110 16636 104 16545 94 3684 90 20160
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。
通过这个命令可以按照从大到小的顺序查看各进程共打开了多少文件句柄数。第一列为数量,第二列为进程号。然后再用pwdx 进程号 查看最大的进程路径,ps -ef|grep 进程号 查看程序名称。