Tutoriales de VPS
Too many open files en un VPS: qué hacer (2026) — diagnóstico de ulimit, nofile y LimitNOFILE
Cuando Nginx, Node, una base de datos o un servicio autoalojado en un VPS muestra Too many open files, las causas habituales incluyen el agotamiento de los descriptores de archivo del proceso, que systemd LimitNOFILE no surta efecto, que /etc/security/limits.conf solo afecte a las sesiones de inicio de sesión, un desajuste en Nginx worker_connections, fugas de conexiones de la aplicación o demasiados logs/sockets. Este artículo diagnostica capa por capa con ulimit -n, /proc/PID/limits, lsof, systemctl show y sysctl.

Que aparezca Too many open files en un VPS normalmente no se debe a que haya demasiados archivos en el disco, sino a que el proceso no puede abrir suficientes descriptores de archivo al mismo tiempo.
Aquí "archivos" no significa solo archivos reales, sino que también incluye:
- conexiones TCP;
- sockets Unix;
- archivos de log;
- conexiones a bases de datos;
- pipes y archivos temporales;
- descriptores de archivo (fd) abiertos internamente por servicios como Nginx, Node, Java, Redis o PostgreSQL.
Por eso puedes ver síntomas como estos:
EMFILE: too many open files
socket: Too many open files
accept4() failed (24: Too many open files)
open() failed: Too many open files
Este artículo sigue un recorrido práctico de diagnóstico en VPS: primero confirma qué proceso ha agotado sus descriptores, y después distingue el ulimit del shell, el LimitNOFILE de systemd, el fs.file-max global, los límites de los workers de Nginx y las fugas de conexiones de la aplicación. No des por hecho que el problema está resuelto solo porque hayas cambiado un sitio.
En la sesión SSH actual, comprueba:
ulimit -n
ulimit -Sn
ulimit -Hn
Significado:
-Sn: soft limit, el límite blando actualmente efectivo;-Hn: hard limit, el límite duro que un usuario normal no puede superar;ulimit -n: normalmente muestra el soft limit.
Pero atención: el ulimit que ves en SSH no tiene por qué ser igual al límite dentro de un servicio systemd. Aquí es donde mucha gente se equivoca al diagnosticar.
Primero mira el PID del servicio que informa del error:
systemctl status nginx --no-pager
systemctl status app --no-pager
También puedes usar:
pidof nginx
pidof node
pidof mysqld
pidof postgres
Para ver cuántos archivos ha abierto ya un proceso:
sudo ls /proc/PID/fd | wc -l
Para ver sus límites:
cat /proc/PID/limits | grep -i 'open files'
Si la salida se parece a:
Max open files 1024 4096 files
y /proc/PID/fd ya está cerca de 1024, es muy probable que este proceso haya alcanzado su límite.
Cuenta el número de archivos abiertos por un proceso:
sudo lsof -p PID | wc -l
Mira la primera parte:
sudo lsof -p PID | head -n 30
Si quieres ver un tipo concreto de conexión, puedes combinarlo con ss:
sudo ss -antp | grep PID
Interpretaciones habituales:
- Muchos
TCP ESTAB: muchas conexiones, posiblemente alta concurrencia o una fuga de conexiones; - Muchos
CLOSE-WAIT: la aplicación no está cerrando las conexiones correctamente; - Muchos archivos de log: problemas de rotación de logs o el programa abre archivos sin liberarlos;
- Muchos sockets: el proxy inverso, WebSocket o el pool de conexiones de la base de datos pueden ser demasiado grandes;
- Muchos archivos deleted: se han borrado archivos pero el proceso sigue manteniendo los descriptores.
Buscar archivos deleted:
sudo lsof | grep deleted | head
Si hay muchos archivos deleted, reiniciar el proceso correspondiente es la única forma de liberar los descriptores y el espacio.
Si el servicio lo gestiona systemd, cambiar solo /etc/security/limits.conf normalmente no es suficiente.
Primero mira los límites actuales del servicio:
systemctl show nginx -p LimitNOFILE
systemctl show app -p LimitNOFILE
Se recomienda usar un override:
sudo systemctl edit app
Escribe:
[Service]
LimitNOFILE=65535
Después:
sudo systemctl daemon-reload
sudo systemctl restart app
systemctl show app -p LimitNOFILE
Y luego confirma si ha surtido efecto dentro del proceso:
cat /proc/$(pidof app)/limits | grep -i 'open files'
Si hay varios nombres de proceso o una estructura master/worker, como Nginx, confirma que los procesos worker también han recibido el nuevo límite.
Muchos tutoriales te dicen que cambies:
sudo nano /etc/security/limits.conf
Por ejemplo:
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
Esto es útil para sesiones de shell que inician sesión mediante PAM, como los comandos que se ejecutan tras un inicio de sesión SSH. Pero los servicios systemd no necesariamente siguen esta configuración.
Si después de cambiarlo ves que:
ulimit -n
sigue mostrando el valor antiguo, comprueba:
grep pam_limits /etc/pam.d/common-session
No obstante, para servicios de larga duración en un VPS, es preferible cambiar LimitNOFILE en lugar de depender solo de limits.conf.
Mira el estado global de archivos abiertos del sistema:
cat /proc/sys/fs/file-nr
sysctl fs.file-max
file-nr normalmente tiene tres números; la primera columna es el número de descriptores de archivo asignados y la tercera columna es el máximo del sistema.
Si el valor global también está cerca de su límite, puedes ajustarlo temporalmente:
sudo sysctl -w fs.file-max=2097152
Configuración permanente:
echo 'fs.file-max = 2097152' | sudo tee /etc/sysctl.d/99-file-max.conf
sudo sysctl --system
Pero en la mayoría de los VPS se alcanza primero el límite nofile por proceso de Too many open files, no el fs.file-max global. Mira primero /proc/PID/limits; no cambies el valor global de entrada.
Error habitual de Nginx:
accept4() failed (24: Too many open files)
worker_connections are not enough
Además del LimitNOFILE de systemd, revisa también la configuración propia de Nginx:
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
}
Comprueba la configuración:
sudo nginx -t
sudo systemctl reload nginx
En términos aproximados: una conexión de Nginx puede ocupar más de un descriptor de archivo, y un proxy inverso también se conecta a los upstreams, así que no pongas worker_connections exactamente igual al límite de descriptores de archivo.
Si delante de Nginx también hay WebSocket, conexiones persistentes o proxy inverso hacia aplicaciones, el número de conexiones es aún más propenso a multiplicarse.
Si un servicio Node, Java, Python o Go informa EMFILE, no te limites a aumentar nofile. Primero confirma si la aplicación no está cerrando archivos o conexiones.
Mira los estados de conexión:
sudo ss -antp | grep PID | awk '{print $1}' | sort | uniq -c
Si hay muchos CLOSE-WAIT, normalmente significa que la aplicación no está cerrando los sockets correctamente.
También hay que revisar el pool de conexiones de la base de datos:
- si el número máximo de conexiones del pool es demasiado grande;
- si las conexiones se devuelven después de que falle una petición;
- si se crea una conexión nueva en cada petición;
- si hay consultas lentas que mantienen conexiones ocupadas durante mucho tiempo;
- si los números de conexiones de las tres capas Nginx / aplicación / base de datos coinciden.
Si solo cambias LimitNOFILE de 1024 a 65535 pero la fuga sigue, se volverá a agotar pasado un tiempo.
Los límites que se ven dentro de un contenedor pueden ser distintos de los del host.
Entra en el contenedor:
docker exec -it 容器名 sh
ulimit -n
Docker Compose puede configurar:
services:
app:
ulimits:
nofile:
soft: 65535
hard: 65535
Si el contenedor lo gestiona systemd, revisa también al mismo tiempo los límites del servicio Docker en el host:
systemctl show docker -p LimitNOFILE
Para problemas de permisos y montajes con Docker, consulta: Docker Permission Denied en un VPS: qué hacer.
Cuando ya se están produciendo errores en producción, la recuperación temporal suele ser:
sudo systemctl restart app
Esto libera los descriptores de archivo abiertos por el proceso, pero solo detiene la hemorragia.
La corrección a largo plazo requiere tres cosas:
- Elevar el límite nofile en el lugar correcto;
- Averiguar por qué crece el número de descriptores de archivo;
- Añadir alertas de uso de descriptores de archivo al monitoreo.
Puedes comprobar periódicamente:
ls /proc/PID/fd | wc -l
cat /proc/PID/limits | grep -i 'open files'
Si el número de descriptores de archivo sube de forma monótona con el tiempo y nunca baja, básicamente es una fuga o conexiones que no se liberan.
Cuando te encuentres con Too many open files, revisa en este orden:
systemctl status 服务名 --no-pagerpara encontrar el servicio que informa del error.journalctl -u 服务名 -n 100 --no-pagerpara ver el error concreto.pidof 服务名para encontrar el PID.ls /proc/PID/fd | wc -lpara ver el número de descriptores de archivo abiertos.cat /proc/PID/limits | grep -i 'open files'para ver los límites del proceso.lsof -p PIDpara ver si lo abierto son archivos, sockets o archivos deleted.- Para servicios systemd, usa
systemctl edit 服务名para establecerLimitNOFILE=65535. - Para Nginx, revisa tanto
worker_rlimit_nofilecomoworker_connections. - Para contenedores Docker, revisa el
ulimitsde compose. - Si el número de descriptores de archivo sigue creciendo, investiga fugas de conexiones, archivos de log no liberados y el pool de conexiones de la base de datos.
El núcleo de Too many open files no es "demasiados archivos", sino un desajuste entre el límite de descriptores de archivo del proceso y el uso real de conexiones/archivos.
Primero mira /proc/PID/limits para confirmar el Max open files que ha recibido el proceso; después mira /proc/PID/fd y lsof para confirmar quién está ocupando realmente los fd. Para servicios systemd, es preferible cambiar LimitNOFILE; para Nginx, también hay que configurar worker_rlimit_nofile; para contenedores Docker, hay que establecer ulimits por separado. Si el número de descriptores de archivo sigue subiendo, aumentar el límite no basta; hay que seguir investigando fugas de conexiones o de descriptores de archivo.