Слишком много ошибок открытых файлов, но lsof показывает законное количество открытых файлов - программирование
Подтвердить что ты не робот

Слишком много ошибок открытых файлов, но lsof показывает законное количество открытых файлов

Моя программа 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 файлов, а предел 500 тыс.:

:~# 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. Я даже перезагрузился, поэтому я уверен, что эти параметры используются.

Я не знаю, соответствует ли это, но процесс запускается выскочкой script, которая запускает процесс с помощью setuidgid, например:

exec setuidgid username java $JAVA_OPTS -jar myprogram.jar

Что мне не хватает?

4b9b3361

Ответ 1

Оказывается, проблема заключалась в том, что моя программа выполнялась как upstart init script, и что строфа exec не вызывает оболочку. ulimit, а настройки в limits.conf применяются только к пользовательским процессам в оболочке.

Я проверил это, изменив строфу exec на

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

который запускает java в командной строке по умолчанию. Это позволило программе использовать как можно больше открытых файлов.

I уже упоминал об этом, что вы также можете вызвать ulimit -n до вызова команды; для upstart script Я думаю, что вместо этого вы использовали бы строчку script.

Я нашел лучшую диагностику, чем lsof, чтобы быть ls /proc/{pid}/fd | wc -l, чтобы получить точный счет дескриптора открытого файла. Наблюдая за тем, что я видел, что ошибки произошли прямо на 4096 открытых фс. Я не знаю, откуда этот 4096; он не находится в /etc в любом месте; Я думаю, он скомпилирован в ядро.

Ответ 2

У меня есть этот фрагмент bash в верхней части создания сервера script:

# 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