我的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:
/etc/security/limits.conf
root soft nofile 500000 root hard nofile 500000 * soft nofile 500000 * hard nofile 500000
我跑去lsof统计打开的文件数- 包括全局和jvm进程。我检查了中的柜台/proc/sys/fs。一切似乎还可以。我的进程仅打开了4301个文件,限制为500k:
lsof
/proc/sys/fs
:~# 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
我缺少什么?
事实证明,问题在于我的程序正在作为新贵的初始化脚本运行,并且该exec节未调用shell。ulimitlimits.conf中的设置仅适用于Shell中的用户进程。
exec
ulimit
我通过将exec节更改为
exec sudo -u username java $JAVA_OPTS -jar program.jar
它在用户名的默认外壳中运行java。这使程序可以使用所需数量的打开文件。
我已经看到它提到您也可以ulimit -n在调用命令之前先进行调用。对于新贵的脚本,我认为您应该改用script节。
ulimit -n
script
我发现了一个更好的诊断比lsof是ls /proc/{pid}/fd | wc -l,获得打开的文件描述符的精确计数。通过监视,我可以看到失败是在4096个打开的fds处发生的。我不知道4096的来源。它不在/ etc中的任何地方;我猜它已经编译进内核了。
ls /proc/{pid}/fd | wc -l