Básico do logrotate - Mantendo Logs Gerenciáveis com Rotação Automática

Básico do logrotate - Mantendo Logs Gerenciáveis com Rotação Automática

O Que É o logrotate?

logrotate é um utilitário Linux que automaticamente rotaciona, compacta e exclui arquivos de log antigos em um agendamento. Sem ele, os arquivos de log em /var/log crescem indefinidamente até o disco encher e os serviços falharem com No space left on device. Ele vem por padrão no Ubuntu e sistemas baseados em RHEL e é executado diariamente via cron.

Resumo Rápido

  • Rotaciona, compacta e remove arquivos de log automaticamente
  • Configuração em duas camadas: /etc/logrotate.conf (padrões globais) e /etc/logrotate.d/ (por aplicação)
  • Sempre verifique novas configurações com logrotate -d (dry run) antes de depender delas

Por Que a Rotação de Logs É Importante?

Um servidor nginx ou MySQL ocupado pode gerar gigabytes de logs por dia. Sem rotação:

  • O disco enche silenciosamente durante a noite
  • Serviços falham com No space left on device
  • grep em um arquivo de 10 GB se torna dolorosamente lento

A maioria das distribuições já vem com /etc/cron.daily/logrotate instalado:

cat /etc/cron.daily/logrotate
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf

Isso é executado uma vez por dia como root. Seu trabalho é escrever os arquivos de configuração que dizem o que fazer.

Como a Configuração É Estruturada?

O logrotate usa uma estrutura de configuração em duas camadas. /etc/logrotate.conf define os padrões globais e inclui tudo em /etc/logrotate.d/ com uma única diretiva include.

/etc/logrotate.conf        <-- padroes globais
/etc/logrotate.d/          <-- configs por aplicacao (onde a maioria da edicao acontece)
+-- nginx
+-- mysql-server
+-- rsyslog
+-- ...

Um /etc/logrotate.conf típico:

cat /etc/logrotate.conf
weekly
rotate 4
create
dateext
compress
include /etc/logrotate.d

weekly e rotate 4 são padrões globais. Qualquer configuração por aplicação em /etc/logrotate.d/ pode substituí-los.

O pacote nginx cria sua própria configuração automaticamente:

cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        postrotate
                if [ -f /run/nginx.pid ]; then
                        kill -USR1 `cat /run/nginx.pid`
                fi
        endscript
}

Diretivas Principais

As diretivas que você usará com mais frequência:

Diretiva Significado
daily / weekly / monthly Frequência de rotação
rotate N Número de arquivos antigos a manter (ex: rotate 7 mantém 7 gerações)
size N Rotacionar quando o arquivo exceder este tamanho (ex: size 100M)
compress Compactar arquivos rotacionados com gzip
delaycompress Atrasar compactação em um ciclo
missingok Não dar erro se o arquivo de log estiver ausente
notifempty Pular rotação se o arquivo estiver vazio
create MODE USER GROUP Criar um novo arquivo de log vazio após rotação
dateext Adicionar sufixo de data aos nomes dos arquivos rotacionados
sharedscripts Executar postrotate uma vez mesmo se múltiplos arquivos corresponderam ao glob
postrotate / endscript Comandos shell para executar após a rotação

Sempre combine compress com delaycompress. Logo após a rotação, o processo em execução pode ainda ter o arquivo antigo aberto. Compactá-lo imediatamente pode causar falhas de escrita. delaycompress espera um ciclo antes de compactar com gzip.

Escrevendo uma Configuração Personalizada

Crie /etc/logrotate.d/myapp para uma aplicação que você implanta:

/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    dateext
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

Pontos-chave:

  • Sem sharedscripts, postrotate executa uma vez por arquivo correspondente -- uma tempestade de reloads se você tiver muitos logs
  • || true no final do comando postrotate evita que o logrotate falhe quando o serviço está parado
  • nginx usa kill -USR1, Apache usa apachectl graceful, serviços systemd usam systemctl reload para reabrir seus arquivos de log

Como Verificar e Depurar

Sempre teste novas configurações com -d (dry run) antes de depender do cron job diário. A flag -d não faz alterações nos arquivos ou no arquivo de status.

logrotate -d /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/myapp/*.log  after 1 days (30 rotations)
...
rotating log /var/log/myapp/access.log, log->rotateCount is 30
...
not rotating log, since it was already rotated less than 1 days ago

Se a saída disser "already rotated less than 1 days ago" e você quiser testar a rotação completa mesmo assim, force com -f:

logrotate -f /etc/logrotate.d/myapp

-f ignora o timestamp em /var/lib/logrotate/status e rotaciona independentemente. Executá-lo várias vezes em sequência rápida irá sobrescrever arquivos de geração. Verifique o arquivo de status após.

Verifique o status atual da rotação:

cat /var/lib/logrotate/status
logrotate state -- version 2
"/var/log/myapp/access.log" 2026-6-1-3:0:0
"/var/log/nginx/access.log" 2026-6-1-3:0:0

Erros Comuns

postrotate não surtindo efeito

Se o serviço continua escrevendo no arquivo antigo (agora rotacionado), o script postrotate ou não está enviando o sinal correto, ou sharedscripts está faltando. Verifique com lsof:

lsof | grep deleted | grep log

Qualquer processo listado aqui tem o handle do arquivo antigo aberto. Corrija o postrotate para enviar o sinal apropriado ou comando de reload.

Colisão de dateext

Executar logrotate -f duas vezes no mesmo dia causa uma colisão de nome de arquivo dateext. Para ambientes de teste, adicione dateformat -%Y%m%d-%s (precisão de segundos) ou remova manualmente o arquivo rotacionado antes de re-executar.

Usuário ou grupo não existe

create 0640 www-data adm falha silenciosamente se www-data não for um usuário válido naquele sistema. Verifique com id www-data e use o modo verbose para ver o erro exato:

logrotate -v /etc/logrotate.d/myapp 2>&1 | head -30

Próximas Leituras