Como lidar com eventos do OOM Killer - Quando processos sao encerrados por esgotamento de memoria

Como lidar com eventos do OOM Killer - Quando processos sao encerrados por esgotamento de memoria

O que e o OOM killer?

O OOM killer (Out-Of-Memory killer) e um mecanismo do kernel Linux que encerra processos a forca quando tanto a memoria fisica quanto o swap estao esgotados. Seu objetivo e prevenir uma falha completa do sistema. Quando um processo desaparece sem explicacao — sem log de crash no nivel da aplicacao, exit code SIGKILL no systemctl status — o OOM killer e a primeira coisa a verificar.

Sintomas a observar

  • Um processo falha sem erro no nivel da aplicacao
  • systemctl status mostra exit-code=SIGKILL
  • dmesg contem Out of memory: Killed process

Como confirmar um evento do OOM killer nos logs

Quando o OOM killer atua, o kernel sempre escreve um registro no buffer de anel do kernel e no log do sistema. Comece por aqui.

Verificar com dmesg

sudo dmesg | grep -i "out of memory"
sudo dmesg | grep -i "oom"
[1234567.890] Out of memory: Killed process 12345 (nginx) total-vm:512000kB, anon-rss:256000kB, file-rss:8000kB, shmem-rss:0kB, UID:0 pgtables:512kB oom_score_adj:0

Buscar no log do kernel com journalctl

sudo journalctl -k --since "2 hours ago" | grep -i oom
sudo journalctl -k -g "Out of memory"

A flag -k filtra apenas mensagens do kernel. Use --since para restringir a janela de tempo.

Verificar syslog / kern.log

sudo grep -i "out of memory" /var/log/syslog
sudo grep -i "oom_killer" /var/log/kern.log

Os timestamps do dmesg sao em segundos desde o boot. Use dmesg -T para exibir timestamps legiveis.

Identificando qual processo foi encerrado

O log registra informacoes detalhadas sobre o processo encerrado.

sudo dmesg | grep "Killed process"
[1234567.890] Killed process 12345 (nginx) total-vm:512000kB, anon-rss:256000kB

Lendo a saida:

Campo Significado
12345 PID do processo
(nginx) Nome do processo
total-vm Total de memoria virtual alocada
anon-rss Paginas anonimas efetivamente na RAM
file-rss Paginas com arquivo de apoio na RAM
oom_score_adj Ajuste de prioridade de kill (0 e o padrao)

Para ver o estado da memoria no momento do evento, imprima o contexto ao redor da mensagem OOM:

sudo dmesg | grep -A 30 "Out of memory" | head -50

Como funcionam os scores OOM

O kernel atribui a cada processo um oom_score (0-1000). Score mais alto significa maior prioridade de encerramento. O score e baseado principalmente no uso de memoria relativo ao total de RAM fisica.

Verificar o score atual

cat /proc/<PID>/oom_score

Listar todos os processos ordenados por score OOM (maior primeiro):

awk '{print $1}' /proc/*/status 2>/dev/null | \
  xargs -I{} sh -c 'echo "$(cat /proc/{}/oom_score 2>/dev/null) {} $(cat /proc/{}/comm 2>/dev/null)"' | \
  sort -rn | head -20

Ajustando o score com oom_score_adj

Escreva um valor de -1000 a 1000 em /proc/<PID>/oom_score_adj para influenciar o score.

Valor Efeito
-1000 Completamente excluido do OOM kill
-500 Muito mais dificil de encerrar
0 Comportamento padrao
500 Mais facil de encerrar
1000 Encerrado primeiro
# Tornar nginx muito mais dificil de ser encerrado pelo OOM (temporario)
echo -500 | sudo tee /proc/$(pgrep nginx)/oom_score_adj

Um processo definido como -1000 nunca pode ser encerrado pelo OOM killer. Se esse processo tem um vazamento de memoria, o proprio sistema pode falhar. Restrinja isso a servicos criticos do sistema.

Resposta imediata — reiniciar e recuperar memoria

Apos o OOM killer atuar, a memoria disponivel deve ser restaurada. Porem, a causa raiz provavelmente persiste e o evento vai se repetir.

Reiniciar o servico encerrado

sudo systemctl restart <service-name>

Liberar page cache manualmente

sync
echo 3 | sudo tee /proc/sys/vm/drop_caches

Encontrar os maiores consumidores de memoria

ps aux --sort=-%mem | head -20
free -h

Tornando oom_score_adj persistente

O valor de oom_score_adj e redefinido quando um processo reinicia. Para persisti-lo, adicione a configuracao ao arquivo de unidade do systemd.

sudo systemctl edit <service-name>

Adicione o seguinte:

[Service]
OOMScoreAdjust=-500

Aplique a alteracao:

sudo systemctl daemon-reload
sudo systemctl restart <service-name>

Verifique:

cat /proc/$(pgrep <service>)/oom_score_adj

Adicionando swap para reduzir pressao de memoria

Swap ausente ou insuficiente torna eventos do OOM killer mais provaveis. Adicionar um arquivo de swap fornece um buffer para picos repentinos de memoria.

Criar um arquivo de swap

# Criar um arquivo de swap de 2 GB
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Confirme que esta ativo:

free -h
swapon --show
              total        used        free      shared  buff/cache   available
Mem:           3.8G        3.1G        100M         50M        600M        600M
Swap:          2.0G          0B        2.0G

Persistir entre reboots

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Swap nao e uma correcao permanente

Swap amortece picos de memoria, mas nao corrige a causa subjacente. Se o uso de memoria cresce continuamente ao longo do tempo, investigue se ha um vazamento de memoria. Considere tambem ajustar o swappiness (padrao 60; 10-20 e comum para servidores).

Causa raiz — auditar configuracao de memoria

Eventos recorrentes do OOM killer significam que o sistema esta genuinamente ficando sem memoria. Ajuste de score e swap sao mitigacoes, nao correcoes.

Causas raiz comuns

  1. Vazamento de memoria — RSS cresce ao longo do tempo sem liberacao
  2. Configuracao de memoria superdimensionada — JVM -Xmx, innodb_buffer_pool_size ou similar excede a RAM fisica
  3. Muitos workers simultaneos — Apache MaxRequestWorkers, PHP-FPM pm.max_children, etc.

Monitorar crescimento de RSS ao longo do tempo

# Amostrar memoria a cada 5 segundos
watch -n 5 "ps -p <PID> -o pid,rss,vsz,comm"

Limitar memoria do servico com cgroup (via systemd)

Definir um teto explicito de memoria por servico isola falhas e previne que um processo descontrolado derrube o sistema.

sudo systemctl edit <service-name>
[Service]
MemoryMax=512M
MemorySwapMax=0

Quando o limite e atingido, apenas aquele servico e encerrado — os outros processos nao sao afetados.

Proximas leituras