Tutoriais de VPS
Too many open files no VPS: o que fazer (2026) — diagnóstico de ulimit, nofile e LimitNOFILE
Quando o Nginx, o Node, um banco de dados ou um serviço auto-hospedado em um VPS exibe Too many open files, as causas comuns incluem esgotamento dos descritores de arquivo do processo, systemd LimitNOFILE sem efeito, /etc/security/limits.conf afetando apenas sessões de login, incompatibilidade em Nginx worker_connections, vazamento de conexões da aplicação ou excesso de logs/sockets. Este artigo diagnostica camada por camada com ulimit -n, /proc/PID/limits, lsof, systemctl show e sysctl.

Ver Too many open files em um VPS normalmente não acontece porque há arquivos demais no disco, mas porque o processo não consegue abrir descritores de arquivo suficientes ao mesmo tempo.
Aqui, "arquivos" não significa apenas arquivos reais; também inclui:
- conexões TCP;
- sockets Unix;
- arquivos de log;
- conexões com banco de dados;
- pipes e arquivos temporários;
- descritores de arquivo (fd) abertos internamente por serviços como Nginx, Node, Java, Redis e PostgreSQL.
Por isso você pode ver sintomas como estes:
EMFILE: too many open files
socket: Too many open files
accept4() failed (24: Too many open files)
open() failed: Too many open files
Este artigo segue um roteiro prático de diagnóstico em VPS: primeiro confirme qual processo esgotou os descritores, depois diferencie o ulimit do shell, o LimitNOFILE do systemd, o fs.file-max global, os limites dos workers do Nginx e os vazamentos de conexão da aplicação. Não presuma que o problema está resolvido só porque você alterou um lugar.
Na sessão SSH atual, verifique:
ulimit -n
ulimit -Sn
ulimit -Hn
Significado:
-Sn: soft limit, o limite flexível em vigor no momento;-Hn: hard limit, o limite rígido que um usuário comum não pode ultrapassar;ulimit -n: normalmente mostra o soft limit.
Mas atenção: o ulimit que você vê no SSH não é necessariamente igual ao limite dentro de um serviço systemd. É aqui que muita gente erra o diagnóstico.
Primeiro veja o PID do serviço que reporta o erro:
systemctl status nginx --no-pager
systemctl status app --no-pager
Você também pode usar:
pidof nginx
pidof node
pidof mysqld
pidof postgres
Para ver quantos arquivos um processo já abriu:
sudo ls /proc/PID/fd | wc -l
Para ver os limites dele:
cat /proc/PID/limits | grep -i 'open files'
Se a saída for parecida com:
Max open files 1024 4096 files
e /proc/PID/fd já estiver próximo de 1024, é muito provável que esse processo tenha atingido o limite.
Conte o número de arquivos abertos por um processo:
sudo lsof -p PID | wc -l
Veja a primeira parte:
sudo lsof -p PID | head -n 30
Se quiser ver um tipo específico de conexão, combine com ss:
sudo ss -antp | grep PID
Interpretações comuns:
- Muitos
TCP ESTAB: muitas conexões, possivelmente alta concorrência ou vazamento de conexões; - Muitos
CLOSE-WAIT: a aplicação não está fechando as conexões corretamente; - Muitos arquivos de log: problemas de rotação de logs ou o programa abrindo arquivos sem liberá-los;
- Muitos sockets: o proxy reverso, o WebSocket ou o pool de conexões do banco de dados podem estar grandes demais;
- Muitos arquivos deleted: arquivos foram excluídos, mas o processo ainda mantém os descritores.
Encontrar arquivos deleted:
sudo lsof | grep deleted | head
Se houver muitos arquivos deleted, reiniciar o processo correspondente é a única forma de liberar os descritores e o espaço.
Se o serviço é gerenciado pelo systemd, alterar apenas /etc/security/limits.conf normalmente não basta.
Primeiro veja os limites atuais do serviço:
systemctl show nginx -p LimitNOFILE
systemctl show app -p LimitNOFILE
Recomenda-se usar um override:
sudo systemctl edit app
Escreva:
[Service]
LimitNOFILE=65535
Depois:
sudo systemctl daemon-reload
sudo systemctl restart app
systemctl show app -p LimitNOFILE
Em seguida, confirme se teve efeito dentro do processo:
cat /proc/$(pidof app)/limits | grep -i 'open files'
Se houver vários nomes de processo ou uma estrutura master/worker, como o Nginx, confirme que os processos worker também receberam o novo limite.
Muitos tutoriais mandam alterar:
sudo nano /etc/security/limits.conf
Por exemplo:
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
Isso é útil para sessões de shell que fazem login via PAM, como comandos executados após um login SSH. Mas os serviços systemd não necessariamente seguem essa configuração.
Se depois de alterar você perceber que:
ulimit -n
ainda mostra o valor antigo, verifique:
grep pam_limits /etc/pam.d/common-session
No entanto, para serviços de longa duração em um VPS, prefira alterar LimitNOFILE em vez de depender apenas do limits.conf.
Veja o estado global de arquivos abertos do sistema:
cat /proc/sys/fs/file-nr
sysctl fs.file-max
file-nr geralmente tem três números; a primeira coluna é a quantidade de descritores de arquivo alocados e a terceira coluna é o máximo do sistema.
Se o valor global também estiver próximo do limite, você pode ajustá-lo temporariamente:
sudo sysctl -w fs.file-max=2097152
Configuração permanente:
echo 'fs.file-max = 2097152' | sudo tee /etc/sysctl.d/99-file-max.conf
sudo sysctl --system
Mas na maioria dos VPS o limite nofile por processo de Too many open files é atingido primeiro, e não o fs.file-max global. Veja primeiro /proc/PID/limits; não altere o valor global de cara.
Erro comum do Nginx:
accept4() failed (24: Too many open files)
worker_connections are not enough
Além do LimitNOFILE do systemd, verifique também a configuração do próprio Nginx:
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
}
Verifique a configuração:
sudo nginx -t
sudo systemctl reload nginx
Em termos aproximados: uma conexão do Nginx pode ocupar mais de um descritor de arquivo, e um proxy reverso também se conecta aos upstreams, então não defina worker_connections exatamente igual ao limite de descritores de arquivo.
Se antes do Nginx também houver WebSocket, conexões persistentes ou proxy reverso para aplicações, o número de conexões tende a se multiplicar ainda mais.
Se um serviço Node, Java, Python ou Go reportar EMFILE, não apenas aumente o nofile. Primeiro confirme se a aplicação não está fechando arquivos ou conexões.
Veja os estados das conexões:
sudo ss -antp | grep PID | awk '{print $1}' | sort | uniq -c
Se houver muitos CLOSE-WAIT, normalmente significa que a aplicação não está fechando os sockets corretamente.
O pool de conexões do banco de dados também precisa ser verificado:
- se o número máximo de conexões do pool é grande demais;
- se as conexões são devolvidas após uma requisição falhar;
- se uma nova conexão é criada a cada requisição;
- se há consultas lentas mantendo conexões ocupadas por muito tempo;
- se os números de conexões das três camadas Nginx / aplicação / banco de dados são compatíveis.
Se você apenas mudar LimitNOFILE de 1024 para 65535 mas o vazamento continuar, ele vai se esgotar de novo depois de um tempo.
Os limites vistos dentro de um contêiner podem ser diferentes dos do host.
Entre no contêiner:
docker exec -it 容器名 sh
ulimit -n
O Docker Compose pode definir:
services:
app:
ulimits:
nofile:
soft: 65535
hard: 65535
Se o contêiner for gerenciado pelo systemd, verifique também ao mesmo tempo os limites do serviço Docker no host:
systemctl show docker -p LimitNOFILE
Para problemas de permissão e montagem com Docker, consulte: Docker Permission Denied no VPS: o que fazer.
Quando os erros já estão acontecendo em produção, a recuperação temporária normalmente é:
sudo systemctl restart app
Isso libera os descritores de arquivo abertos pelo processo, mas apenas estanca o sangramento.
A correção de longo prazo exige três coisas:
- Elevar o limite nofile no lugar correto;
- Descobrir por que a quantidade de fd está crescendo;
- Adicionar alertas de uso de fd ao monitoramento.
Você pode verificar periodicamente:
ls /proc/PID/fd | wc -l
cat /proc/PID/limits | grep -i 'open files'
Se a quantidade de fd sobe de forma monotônica com o tempo e nunca cai, é basicamente vazamento ou conexões que não são liberadas.
Ao encontrar Too many open files, verifique nesta ordem:
systemctl status 服务名 --no-pagerpara encontrar o serviço que reporta o erro.journalctl -u 服务名 -n 100 --no-pagerpara ver o erro específico.pidof 服务名para encontrar o PID.ls /proc/PID/fd | wc -lpara ver a quantidade de fd abertos.cat /proc/PID/limits | grep -i 'open files'para ver os limites do processo.lsof -p PIDpara ver se o que está aberto são arquivos, sockets ou arquivos deleted.- Para serviços systemd, use
systemctl edit 服务名para definirLimitNOFILE=65535. - Para o Nginx, verifique tanto
worker_rlimit_nofilequantoworker_connections. - Para contêineres Docker, verifique o
ulimitsdo compose. - Se a quantidade de fd continuar crescendo, investigue vazamentos de conexão, arquivos de log não liberados e o pool de conexões do banco de dados.
O cerne de Too many open files não é "arquivos demais", mas uma incompatibilidade entre o limite de descritores de arquivo do processo e o uso real de conexões/arquivos.
Primeiro veja /proc/PID/limits para confirmar o Max open files que o processo recebeu; depois veja /proc/PID/fd e lsof para confirmar quem está realmente ocupando os fd. Para serviços systemd, prefira alterar LimitNOFILE; para o Nginx, também é preciso configurar worker_rlimit_nofile; para contêineres Docker, é preciso definir ulimits separadamente. Se a quantidade de fd continuar subindo, aumentar o limite não basta; é preciso continuar investigando vazamentos de conexão ou de descritores de arquivo.