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

2022-09-03 06:16:05

我的 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)...

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

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

我跑去计算打开的文件数 - 无论是全局还是jvm进程。我检查了 中的计数器。一切似乎都还好。我的进程只打开了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

我错过了什么?


答案 1

事实证明,问题在于我的程序是作为新贵的初始化脚本运行的,并且该节没有调用shell。 并且 limits.conf 中的设置仅适用于 shell 中的用户进程。execulimit

我通过将执行节更改为

exec sudo -u username java $JAVA_OPTS -jar program.jar

它在用户名的默认shell中运行java。这允许程序根据需要使用任意数量的打开文件。

我看到提到您也可以在调用命令之前调用;对于一个新兴的脚本,我认为你会使用一个节来代替。ulimit -nscript

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


答案 2

我在服务器创建脚本的顶部有这个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

推荐