Tecnología · GUÍA PRÁCTICA
¿Too many open files aunque subiste ulimit? Demuestra qué límite alcanzó el servicio Linux
El ulimit de tu shell no describe un servicio ya iniciado. Usa el PID fallido para separar RLIMIT_NOFILE, la tabla global y inotify antes de cambiar límites.

El mensaje “Too many open files” de Linux no demuestra qué límite falló. EMFILE suele apuntar al RLIMIT_NOFILE del proceso, ENFILE a la tabla global de archivos, e inotify también puede devolver EMFILE al agotar instancias del usuario.
Un ulimit alto en la shell actual tampoco prueba el límite de un servicio ya iniciado. Conserva el PID y la hora del fallo, lee los límites heredados por ese proceso, mide sus descriptores y comprueba las ramas global e inotify.
1. Captura el proceso que falla, no tu shell
Antes de reiniciar, registra hora y PID. En systemd usa systemctl show UNIT -p MainPID -p LimitNOFILE, lee /proc/PID/limits y cuenta /proc/PID/fd. Un ulimit -n posterior describe esa shell, no el servicio existente.
Separa soft y hard, compara el recuento con soft e inspecciona destinos con readlink. No uses lsof -u USER | wc -l como recuento por proceso: mezcla procesos y duplicados.
2. Separa EMFILE, ENFILE e inotify
Si hay errno, EMFILE suele indicar RLIMIT_NOFILE y ENFILE la tabla global. Compara file-nr con file-max y busca la señal file-max reached en el kernel. No subas file-max por una frase genérica.
Si falla la creación de watches o el registro los menciona, prueba inotify. EMFILE en inotify_init puede venir del límite de instancias o del límite de FD; max_user_instances y max_user_watches son contadores distintos.
3. Rastrea de dónde heredó el servicio
PAM, shell, contenedor, lanzador y systemd son rutas distintas. En systemd inspecciona unidad y drop-ins cargados; LimitNOFILE acepta un valor o soft:hard.
No copies una cifra enorme a todos los servicios. systemd advierte que select no maneja FD mayores de 1023. Confirma compatibilidad, usa un drop-in local y conserva el valor anterior para revertir.
4. Distingue concurrencia normal de una fuga
Una sola medición no prueba normalidad. Muestrea el mismo PID bajo carga comparable, agrupa sockets, pipes, archivos y FD anónimos, y compáralos con métricas. Crecer sin bajar tras terminar el trabajo es una pista de fuga.
Reiniciar puede bajar el número sin arreglar la causa. Conserva evidencia previa y busca un estado acotado. Si una clase crece de forma extraña, arregla su dueño antes de subir el límite.
5. Cambia un solo dueño y prueba el nuevo hijo
Cambia solo la capa demostrada: servicio o lanzador para límite de proceso, aplicación para fuga, host tras revisar capacidad para tabla global, o consumidor confirmado para inotify. Reinicia una vez si hace falta y vuelve a leer PID y límites.
Éxito significa que el proceso heredó el límite deseado, conserva margen con carga real y desaparece el error original. Detente si falta errno, el dueño no está claro, el valor supera nr_open o la modificación ocultaría una fuga sin límite.
