jdk - java ubuntu
Demasiados errores de archivos abiertos, pero lsof muestra un nĂºmero legal de archivos abiertos (2)
Resulta que el problema era que mi programa se estaba ejecutando como un script de inicio de arranque, y que la stanza exec
no invoca un shell. ulimit
y la configuración en limits.conf se aplican solo a los procesos de usuario en un shell.
Verifiqué esto cambiando la estrofa ejecutiva a
exec sudo -u username java $JAVA_OPTS -jar program.jar
que ejecuta java en el shell predeterminado del nombre de usuario. Eso permitió que el programa utilizara tantos archivos abiertos como fuera necesario.
He visto que se menciona que también puede llamar a ulimit -n
antes de invocar el comando; para un script de inicio, creo que en su lugar usarías una stanza de script
.
Encontré un mejor diagnóstico que lsof
para ser ls /proc/{pid}/fd | wc -l
ls /proc/{pid}/fd | wc -l
, para obtener un recuento preciso del descriptor de archivo abierto. Al monitorear que pude ver que las fallas ocurrieron en 4096 fds abiertos. No sé de dónde viene ese 4096; no está en / etc en ninguna parte; Supongo que está compilado en el núcleo.
Mi programa de Java está fallando con
Caused by: java.io.IOException: Too many open files
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:883)...
Aquí están las líneas clave de /etc/security/limits.conf
. Establecieron los archivos máximos para un usuario en 500k:
root soft nofile 500000
root hard nofile 500000
* soft nofile 500000
* hard nofile 500000
lsof
para contar el número de archivos abiertos, tanto globalmente como por el proceso jvm. Examiné los contadores en /proc/sys/fs
. Todo parece bien. Mi proceso solo tiene 4301 archivos abiertos y el límite es de 500 k:
:~# 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
Este es un servidor Ubuntu 11.04. Incluso he reiniciado, así que estoy seguro de que se están utilizando estos parámetros.
No sé si es relevante, pero el proceso se inicia con un script de inicio, que inicia el proceso utilizando setuidgid, como esto:
exec setuidgid username java $JAVA_OPTS -jar myprogram.jar
¿Qué me estoy perdiendo?
Tengo este fragmento de bash en la parte superior de un script de creación de servidor:
# 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