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

hug*_*ghw 16 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)...
Run Code Online (Sandbox Code Playgroud)

以下是关键线/etc/security/limits.conf.他们将用户的最大文件设置为500k:

root                     soft    nofile          500000
root                     hard    nofile          500000
*                        soft    nofile          500000
*                        hard    nofile          500000
Run Code Online (Sandbox Code Playgroud)

我跑去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
Run Code Online (Sandbox Code Playgroud)

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

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

exec setuidgid username java $JAVA_OPTS -jar myprogram.jar
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

hug*_*ghw 17

事实证明问题是我的程序作为一个新手初始化脚本运行,并且该exec节不会调用shell.ulimitlimits.conf中的设置仅适用于shell中的用户进程.

我通过将exec节更改为来验证这一点

exec sudo -u username java $JAVA_OPTS -jar program.jar
Run Code Online (Sandbox Code Playgroud)

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

已经看到它提到你也可以ulimit -n在调用命令之前调用; 对于一个新手脚本我认为你会使用一个script节.

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