linux

Criar swapfile no Ubuntu: parar o OOM killer de matar o MySQL

VPS de 2 GB, quatro da manhã, e o site amanhece com “Error establishing a database connection”. Você reinicia o MySQL, volta tudo, e na madrugada seguinte de novo. Antes de culpar a hospedagem, olhe o log do kernel: em máquina sem swap é quase sempre o OOM killer escolhendo o mysqld pra morrer.

Confirme que foi o OOM killer

O kernel registra a hora e o PID de quem ele matou:

sudo dmesg -T | grep -i 'out of memory'
sudo journalctl -k --since '2 days ago' | grep -i 'killed process'
free -h
swapon --show

Se sair uma linha do tipo Out of memory: Killed process 1187 (mysqld), acabou a investigação. Sem swap o kernel não tem pra onde empurrar página nenhuma quando o backup, o wp-cron e o PHP-FPM rodam no mesmo minuto, então ele sacrifica o processo mais gordo — numa VPS de site, o banco.

Criar o swapfile de 2 GB

sudo fallocate -l 2G /swapfile      # se o swapon reclamar de "holes", use o dd:
# sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
grep -q '^/swapfile ' /etc/fstab || echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swap.conf
sudo sysctl --system

O chmod 600 não é frescura: com 644 o mkswap já avisa que a permissão é insegura: qualquer usuário da máquina lê pedaço de memória de processo dentro do arquivo. A linha do /etc/fstab é o que faz o swap voltar depois do reboot — o grep -q na frente evita duplicar a linha, e como fstab é arquivo de boot, confira antes de reiniciar. Swappiness em 10 manda o kernel só recorrer ao disco quando a RAM apertar.

Rode free -h de novo e confira a linha Swap. Swap é rede de segurança, não RAM extra: se o mysqld passar a viver no disco, o passo seguinte é baixar o innodb_buffer_pool_size.

Se travou nisso e precisa de ajuda, me chama aqui.

Post Recentes

Grupos nomeados no preg_match: pare de contar índice de $matches

Regex com cinco parênteses e ninguém lembra se a data é $matches[2] ou $matches[3]. Nomeie os grupos e leia o…

19 horas atrás

Token de integração da API do Magento 2: gerar e usar no header Bearer

Erro The consumer isn't authorized to access resources ao chamar a REST do Magento 2.4.8? Ative a integração, libere os…

23 horas atrás

Rate limit no wp-login.php com nginx: barrar força bruta antes do PHP

Bots batendo centenas de POST por minuto no login derrubam a CPU. Configure limit_req_zone no nginx e devolva 429 antes…

2 dias atrás

Anonimizar IP no nginx: mascarar o último octeto do log para a LGPD

Seu access.log guarda o IP inteiro dos visitantes há meses sem necessidade. Mascare o último octeto com map e log_format…

3 dias atrás

Prompt injection em campo de usuário: isole a observação do pedido

A observação do pedido chegou com ordem embutida para gerar cupom. Delimite o texto do cliente e trate a resposta…

3 dias atrás

Preço promocional em massa no WooCommerce: agendar a Black Friday pelo WP-CLI

Um CSV com SKU e preço, um wp eval-file que agenda início e fim da promoção guardando o estado anterior,…

3 dias atrás