DevOps

Gestão de Processos com PM2

Guia completo de gestão de processos com PM2 no Linux: instalação, configuração, cluster mode, monitorização e manutenção.

Já te aconteceu uma aplicação Node.js cair em produção às 3 da manhã e só dares por isso no dia seguinte? Ou teres um bot em Python que precisa de estar sempre online mas não sabes como o manter vivo?

É aqui que entra o PM2 (Process Manager 2).

O PM2 é um gestor de processos para Node.js (e não só) que mantém as tuas aplicações online 24/7. Ele faz o auto-restart quando algo falha, gere logs, expõe métricas e ainda permite escalar em cluster com poucos comandos.


O que é o PM2?

PM2 é um daemon (processo em background) que gere as tuas aplicações. Podes pensar nele como um systemd para as tuas apps Node.js, mas mais simples e com features específicas para developers.

Porquê PM2 em vez de…

Alternativa Quando usar
systemd Quando queres integração profunda com o SO. Mas é mais verboso
screen/tmux Fixe para sessões ad-hoc, mas não faz auto-restart
Docker Excelente para ambientes isolados. Mas PM2 é mais leve para uma app simples
nohup & Funcional, mas zero monitorização

PM2 dá-te o meio-termo: simples de configurar, com monitorização, restart automático e logs.


Instalação

Instalar é direto com npm:

npm install pm2@latest -g

Ou se usas Yarn:

yarn global add pm2

Depois de instalado, confirma que está tudo certo:

pm2 --version

Dica: Se ainda não tens Node.js instalado, usa o NVM (Node Version Manager). É a forma mais limpa de gerir versões do Node.


Primeiros Passos — Iniciar uma Aplicação

A forma mais simples de começar:

pm2 start app.js

Isto diz ao PM2 para:

  1. Executar o ficheiro
  2. Daemonizar (correr em background)
  3. Monitorizar e fazer restart se cair

Mas o PM2 não se limita a Node.js. Consegues gerir qualquer tipo de processo:

# Script bash
pm2 start backup.sh

# App Python com watch mode (restart automático se alterares o código)
pm2 start bot.py --watch

# Binário compilado com argumentos extra
pm2 start ./meu-binary -- --port 1520 --config prod

Opções úteis no arranque
pm2 start app.js \
  --name "minha-api" \
  --watch \
  --max-memory-restart 200M \
  --log /var/log/app.log \
  --time \
  --restart-delay 3000 \
  --cron-restart "0 4 * * *"
  • --name — nome amigável do processo
  • --watch — reinicia quando os ficheiros mudam (útil em desenvolvimento, não em produção)
  • --max-memory-restart 200M — reinicia se a memória passar os 200 MB
  • --log — caminho do ficheiro de log
  • --time — prefixa cada linha do log com a data e a hora
  • --restart-delay 3000 — espera 3 s antes de reiniciar
  • --cron-restart "0 4 * * *" — reinício forçado todos os dias às 4h

Existe ainda o --no-autorestart, para o PM2 não reiniciar o processo quando este cai.


Ecosystem File — A Configuração a Sério

Linha de comandos é fixe para testes. Mas em produção vais querer um ficheiro de configuração declarativa.

Cria um ficheiro ecosystem.config.js na raiz do projeto:

module.exports = {
  apps: [
    {
      name: "api-prod",
      script: "dist/server.js",
      instances: "max",          // cluster mode (usa todos os CPUs)
      exec_mode: "cluster",
      env: {
        NODE_ENV: "production",
        PORT: 3000,
      },
      node_args: "--env-file=.env",  // carrega o .env (Node 20.6 ou superior)
      max_memory_restart: "300M",
      log_date_format: "YYYY-MM-DD HH:mm:ss",
      error_file: "./logs/err.log",
      out_file: "./logs/out.log",
      merge_logs: true,
      autorestart: true,
      watch: false,
      max_restarts: 10,           // reinícios instáveis seguidos antes de ficar "errored"
      restart_delay: 5000,        // espera 5s entre restarts
    },
    {
      name: "bot-worker",
      script: "workers/bot.py",
      interpreter: "python3",
      instances: 1,
      exec_mode: "fork",
    },
  ],
};

Depois é só:

# Iniciar todas as apps do ficheiro
pm2 start ecosystem.config.js

# Apenas uma app específica
pm2 start ecosystem.config.js --only api-prod

Isto é muito mais reproduzível e versionável que dezenas de flags na CLI.


Gestão de Processos

Comandos básicos do dia-a-dia:

pm2 restart api-prod          # Reinicia a app
pm2 reload api-prod           # Reload com zero downtime (cluster mode)
pm2 stop api-prod             # Para a app (mas mantém no PM2)
pm2 delete api-prod           # Remove do PM2 por completo

Podes usar all para atuar em todos os processos:

pm2 restart all
pm2 stop all

Ou usar o ID do processo (vê no pm2 list):

pm2 stop 0
pm2 delete 3

Monitorização — Vê o que se Passa


Listar processos
pm2 list
# ou
pm2 ls
# ou
pm2 status

pm2_ls

Vês o nome, ID, estado (online/stopped/errored), uso de CPU/memória, e há quanto tempo está ativo.


Logs em tempo real
pm2 logs                    # Logs de todas as apps
pm2 logs api-prod           # Logs de uma app específica
pm2 logs --lines 200        # Últimas 200 linhas

Dashboard no terminal
pm2 monit

pm2_monit

Isto dá-te um htop-like com CPU, memória, e logs por processo. Uso isto constantemente quando estou a debuggar alguma coisa.


Informação detalhada
pm2 show api-prod

Mostra versão do Node, path, variáveis de ambiente, tempo de atividade, restarts.


Cluster Mode — Escalar para Todos os CPUs

Uma das melhores features do PM2: cluster mode.

Em vez de correr uma única instância do Node.js (que é single-threaded), o PM2 cria várias instâncias — uma por CPU — e faz load balancing entre elas.

# Usando todos os CPUs
pm2 start app.js -i max

# Ou um número específico
pm2 start app.js -i 4

No ecosystem file:

{
  name: "api",
  script: "app.js",
  instances: "max",
  exec_mode: "cluster",
}

Nota: O pm2 reload em cluster mode faz zero-downtime restart. Ele reinicia as instâncias uma de cada vez, garantindo que há sempre processos a responder a pedidos.

Se a tua app mantém estado em memória (sessions, etc.), precisas de um mecanismo partilhado (Redis, base de dados). Cada instância é um processo independente.


Startup & Persistência — Manter Vivo Após Reboot

Um dos maiores problemas de usar node app.js diretamente: quando o servidor reinicia, a aplicação morre.

O PM2 resolve isto com o sistema startup:

# Gerar script de auto-arranque
pm2 startup

# Guardar o estado atual dos processos
pm2 save

O pm2 startup deteta o teu init system (systemd, launchd, etc.) e imprime um comando que tens de copiar e correr (começa por sudo env PATH=…): é esse comando que cria o serviço de arranque. Corre o pm2 startup sem sudo e depois o comando que ele mostrar. O pm2 save guarda a lista de processos ativos.

Quando o servidor reiniciar, o PM2 restaura automaticamente todos os processos.

# Desativar (se deixares de usar PM2)
pm2 unstartup

Log Rotation — Logs Não Enchem o Disco

Por defeito, o PM2 escreve logs para ficheiros que podem crescer sem limite. Usa o módulo de log rotation:

pm2 install pm2-logrotate

Configuração (via PM2):

pm2 set pm2-logrotate:max_size 10M      # Rotação quando chega a 10MB
pm2 set pm2-logrotate:retain 7           # Manter 7 ficheiros de log
pm2 set pm2-logrotate:compress true      # Comprimir logs antigos (gzip)

Isto é obrigatório em produção. Acredita, não queres descobrir que /var/log está cheio às 3 da manhã.


Graceful Shutdown — Parar sem Partir Tudo

Quando o PM2 faz restart, ele envia um sinal SIGINT ao processo. A tua app deve apanhar esse sinal e fazer cleanup:

// Numa app Node.js
process.on("SIGINT", () => {
  console.log("A encerrar graciosamente...");
  server.close(() => {
    // Fechar ligações à BD
    // Terminar workers
    process.exit(0);
  });
});

No ecosystem file, podes configurar:

{
  name: "api",
  script: "app.js",
  kill_timeout: 5000,          // timeout para graceful shutdown (5s)
  listen_timeout: 3000,        // tempo a esperar que a app fique "ready"
}

Resumo de Comandos Úteis

Comando O que faz
pm2 list Lista processos
pm2 start app.js Inicia app
pm2 start ecosystem.config.js Inicia config
pm2 stop app Para processo
pm2 restart app Reinicia
pm2 reload app Zero-downtime reload
pm2 delete app Remove do PM2
pm2 logs Logs em tempo real
pm2 monit Dashboard terminal
pm2 show app Detalhes do processo
pm2 startup Auto-arranque no boot
pm2 save Guarda lista de processos
pm2 status Estado dos processos

Conclusão

O PM2 é uma ferramenta que uso em todos os meus servidores. Não é só para Node.js — já o usei para gerir bots Python, scripts bash, e até binários Go.

A beleza está na simplicidade: com pm2 start tens uma app monitorizada e persistente. Com ecosystem.config.js tens uma configuração reproduzível e versionável.

Próximos passos que recomendo:

  1. Cria um ecosystem.config.js no teu projeto atual
  2. Testa o cluster mode (-i max)
  3. Configura o pm2 startup para persistência
  4. Instala o pm2-logrotate se fores usar em produção

Já usas PM2? Ou preferes outra abordagem? Deixa um comentário ou manda mensagem — gosto de saber como outros developers resolvem estes problemas.


Recursos

Partilhar

Comentários 0

Ainda sem comentários — sê o primeiro.