Como resolver erro 'Too many open files' no Linux em servidores PHP‑FPM durante picos de acesso

Por · Publicado em · 8 min de leitura

Técnico manipulando vários cabos e conexões em equipamento de rack
Infraestrutura física com muitos cabos — metáfora visual adequada para exaustão de descritores Foto: cottonbro studio / Pexels

Como resolver erro 'Too many open files' no Linux em servidores PHP‑FPM durante picos de acesso: entenda o que causa a exaustão de descritores de arquivo (FDs), como diagnosticar em produção e quais ajustes aplicar por camada (systemd, kernel, FPM e Nginx). Abaixo você encontra passos práticos para estabilizar sem prometer milagres.

Sintomas reais e quando o erro aparece

Ocorre em pico de tráfego, quando PHP‑FPM aceita conexões novas enquanto mantém FDs abertos: sockets, logs, arquivos temporários e conexões a upstreams. Os sintomas incluem 502/504 no Nginx, falhas intermitentes em APIs e mensagens de erro nos logs do FPM e do web server.

Não confunda com exaustão de portas efêmeras. Aqui o problema é o teto de descritores de arquivo do processo, do serviço ou do kernel.

  • 502/504 e quedas momentâneas sob carga.
  • Mensagens 'Too many open files' nos logs do PHP‑FPM.
  • Aumento de latência e filas no web server.
  • Conexões ao banco e a caches falhando por falta de FDs.

Diagnóstico imediato em produção (sem pânico)

Faça três checagens: 1) confirme o erro no log; 2) veja o limite efetivo de FDs do master do FPM; 3) conte FDs abertos para entender o gap. Isso orienta o ajuste correto por camada. Se você já expõe métricas, correlacione filas de FPM com o uso de FDs — veja como expor métricas do PHP‑FPM.

# 1) Confirme no log do FPM
sudo grep -i "too many open files" /var/log/php*-fpm*.log || true

# 2) Descubra o PID do master do PHP-FPM
pgrep -x "php-fpm" || pgrep -x "php-fpm8.2" || pgrep -x "php-fpm7.4"
PID=<<coloque_o_pid_aqui>>

# Limites efetivos do processo (procfs)
cat /proc/$PID/limits | grep -i "open files"

# Também veja o LimitNOFILE do unit systemd correspondente
systemctl show php-fpm --property=LimitNOFILE 2>/dev/null || \
  systemctl show php8.2-fpm --property=LimitNOFILE 2>/dev/null

# 3) Quantos FDs o master mantém abertos agora?
lsof -p $PID | wc -l

# Tipos mais comuns de FDs (visão rápida)
lsof -p $PID | awk '{print $5}' | sort | uniq -c | sort -nr | head -n 10

De onde vem o limite: camadas que controlam FDs

O teto de FDs é a combinação de kernel, service manager e app. Ajustar só o ulimit do shell não afeta serviços gerenciados pelo systemd. Entenda a pilha antes de alterar.

Camada Onde ajustar Parâmetro principal Como verificar
Kernel (global) /etc/sysctl.d/*.conf fs.file-max sysctl fs.file-max
Systemd (serviço) override do unit LimitNOFILE systemctl show <unit> --property=LimitNOFILE
PHP-FPM (pool) www.conf (ou pool) rlimit_files /proc/$PID/limits (Open files)
Nginx (worker) nginx.conf worker_rlimit_nofile nginx -T | grep rlimit
Shell/PAM (login) /etc/security/limits*.conf nofile ulimit -n (em sessão interativa)
Containers (Docker) compose.yaml / run ulimits: nofile docker inspect ... | jq '.[0].HostConfig.Ulimits'

Correção rápida focada no serviço (systemd + FPM)

Aumente o LimitNOFILE no unit do PHP‑FPM e, opcionalmente, o rlimit_files no pool. Exige restart do serviço, pois os limites são aplicados na criação do processo. Para reduzir impacto no usuário, considere uma troca de tráfego com padrão deploy blue‑green antes do restart.

  • Use um valor com folga para o pico previsto.
  • Verifique logs após o restart para confirmar.
  • Não ultrapasse a capacidade do kernel (fs.file-max).
# 1) Override no systemd
sudo systemctl edit php-fpm || sudo systemctl edit php8.2-fpm
# Adicione no editor que abrir:
# [Service]
# LimitNOFILE=131072

sudo systemctl daemon-reload
sudo systemctl restart php-fpm || sudo systemctl restart php8.2-fpm

# 2) (Opcional) rlimit_files no pool do FPM
# Em /etc/php/*/fpm/pool.d/www.conf ou similar:
# rlimit_files = 131072
# Depois, reinicie o PHP-FPM novamente.

# Valide
systemctl show php-fpm --property=LimitNOFILE 2>/dev/null || \
  systemctl show php8.2-fpm --property=LimitNOFILE 2>/dev/null
cat /proc/$(pgrep -x php-fpm | head -n1)/limits | grep -i "open files"

Ajustes persistentes e dimensionamento seguro

Garanta que o kernel e o serviço comportem o novo teto. Ajuste o fs.file-max e revise parâmetros do pool do FPM para evitar crescer sem controle. Evite aumentar limites sem acompanhar CPU, memória e I/O, senão você pode apenas deslocar o gargalo.

  • Kernel: aumente fs.file-max de forma persistente.
  • FPM: revise pm.max_children e pm.process_idle_timeout.
  • Logs: rotação adequada evita excesso de FDs abertos.
# Kernel: persistir um teto global mais alto
echo 'fs.file-max = 1000000' | sudo tee /etc/sysctl.d/99-fd.conf
sudo sysctl --system

# PHP-FPM (pool): além de rlimit_files, confira a capacidade de workers
# Ex.: pm = dynamic; pm.max_children = <valor_compatível_com_recursos>
# Consulte a documentação oficial do PHP-FPM para detalhes dos parâmetros.

Nginx, conexões e interplay com containers (Docker)

Se Nginx faz proxy para o FPM, os workers também precisam de teto maior. Em containers, defina ulimits por serviço. Lembre que limites do container não herdam do host por padrão. Se você está escolhendo o proxy reverso, veja critérios em Traefik vs Nginx.

  • Nginx: ajuste worker_rlimit_nofile e worker_connections.
  • Docker: defina ulimits:nofile no compose/run.
  • Orquestradores aplicam limites próprios; revise manifests.
# docker-compose.yml (exemplo)
services:
  php-fpm:
    image: php:8.2-fpm
    ulimits:
      nofile:
        soft: 131072
        hard: 131072
  nginx:
    image: nginx:stable
    ulimits:
      nofile:
        soft: 131072
        hard: 131072

Prevenção: métricas, logs e testes de carga

Estabilize a operação com visibilidade e ensaios de pico. Meça FDs e fila do FPM, centralize logs e teste mudanças antes do horário crítico. Combine alertas de FDs altos com gráficos de tráfego para antecipar saturação.

Checklist de verificação pós‑correção

Confirme que os novos limites estão ativos e que a aplicação sustenta o pico simulado. Não execute testes de carga em produção sem controle. Use janela de manutenção, limites e monitoramento em tempo real.

  • LimitNOFILE do unit está correto.
  • /proc/$PID/limits reflete o novo teto.
  • lsof sob carga permanece abaixo do limite.
  • Nginx e containers também ajustados.
  • Logs sem novos 'Too many open files'.
systemctl show php-fpm --property=LimitNOFILE 2>/dev/null || \
  systemctl show php8.2-fpm --property=LimitNOFILE 2>/dev/null
PID=$(pgrep -x php-fpm | head -n1)
cat /proc/$PID/limits | grep -i "open files"
# Simule carga leve e observe:
watch -n2 "lsof -p $PID | wc -l"

Perguntas frequentes

O que causa 'Too many open files' no PHP‑FPM?

O processo atingiu o teto de descritores de arquivo. Isso inclui sockets, arquivos de log e temporários. Em picos, cada worker mantém múltiplos FDs, somando-se ao limite do serviço (LimitNOFILE), do pool (rlimit_files) e do kernel (fs.file-max).

Basta aumentar o ulimit no shell para resolver?

Não. Serviços gerenciados pelo systemd ignoram o ulimit da sua sessão interativa. É preciso ajustar LimitNOFILE no unit do serviço e, opcionalmente, rlimit_files no pool do PHP‑FPM, além de garantir um fs.file-max adequado no kernel.

Preciso reiniciar o PHP‑FPM após alterar os limites?

Sim. Limites como LimitNOFILE e rlimit_files são aplicados na criação do processo. Um reload não altera esses valores. Planeje reiniciar o FPM de forma segura, drenando conexões via proxy reverso para evitar erros ao usuário final.

Quais riscos de definir limites muito altos?

Se o limite ficar alto demais sem capacidade real (CPU/RAM/I/O), o servidor pode aceitar trabalho em excesso e degradar. Além disso, o kernel tem teto global (fs.file-max). Ajuste com folga razoável e monitore uso para calibrar.

Como ajustar em ambientes com Docker Compose?

Defina ulimits:nofile por serviço no compose ou ao executar containers. Ajuste Nginx e PHP‑FPM separadamente. Lembre que limites do host não se aplicam automaticamente aos containers. Verifique com docker inspect e monitore sob carga.

Quer apoio para estabilizar seu PHP‑FPM sob picos?

Diagnóstico guiado, ajustes de limites por camada e validações com observabilidade. Vamos conversar sobre seu cenário e próximos passos práticos.

Falar sobre meu ambiente

Veja também