打开文件太多错误,但lsof显示合法数量的打开文件

时间:2012-01-25 23:08:07

标签: java linux

我的Java程序失败了

Caused by: java.io.IOException: Too many open files
        at java.io.UnixFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(File.java:883)...

以下是/etc/security/limits.conf的主要内容。他们将用户的最大文件设置为500k:

root                     soft    nofile          500000
root                     hard    nofile          500000
*                        soft    nofile          500000
*                        hard    nofile          500000

我运行lsof来计算打开的文件数 - 全局和jvm进程。我检查了/proc/sys/fs中的计数器。一切似乎都好。我的进程只打开4301个文件,限制为500k:

:~# lsof | wc -l
5526
:~# lsof -uusername | wc -l
4301
:~# cat /proc/sys/fs/file-max
744363
:~# cat /proc/sys/fs/file-max
744363
:~# cat /proc/sys/fs/file-nr
4736    0       744363

这是一个Ubuntu 11.04服务器。我甚至重新启动,所以我很肯定这些参数正在被使用。

我不知道它是否相关,但是这个过程是由一个upstart脚本启动的,它使用setuidgid启动进程,如下所示:

exec setuidgid username java $JAVA_OPTS -jar myprogram.jar

我缺少什么?

2 个答案:

答案 0 :(得分:16)

事实证明问题是我的程序是作为一个暴发初始化脚本运行的,并且exec节没有调用shell。 ulimit和limits.conf中的设置仅适用于shell中的用户进程。

我通过将exec节更改为

来验证这一点
exec sudo -u username java $JAVA_OPTS -jar program.jar

在用户名的默认shell中运行java。这使得程序可以根据需要使用尽可能多的打开文件。

have seen it mentioned你也可以在调用命令之前调用ulimit -n;对于一个新手脚本,我认为你会使用script节。

我找到了比lsof更好的诊断ls /proc/{pid}/fd | wc -l,以获得打开文件描述符的精确计数。通过监控我可以看到故障发生在4096开放fds。我不知道4096来自哪里;它不在/ etc中;我猜它已编译到内核中。

答案 1 :(得分:4)

我在服务器创建脚本的顶部有这个bash片段:

# Jack up the max number of open file descriptors at the kernel
echo "fs.file-max = 1000000" >> /etc/sysctl.conf
invoke-rc.d procps start

# Increase max open file descriptors for this process
ulimit -n 1000000

# And for future ones as well
cat >> /etc/profile <<LIMITS
ulimit -n 1000000
LIMITS
cat >> /etc/security/limits.conf <<LIMITS
root - nofile 1000000
LIMITS