Disco cheio por journals do systemd: diagnóstico e limpeza
Neste artigo
O alerta de disco cheio dispara, o df mostra /var quase cheio e o du dos directórios óbvios não justifica nada. O suspeito, em servidores com systemd, é o journal: /var/log/journal/ acumula os logs de todos os serviços, o default do journald autoriza-o a crescer até 10% do sistema de ficheiros (com um tecto de 4GB) e o default só encolhe ficheiros arquivados quando escreve logs novos. Numa PME com uma aplicação ruidosa, o journal chega aos gigabytes e empurra /var contra o limite. Este guia mostra a sequência completa: medir, limpar, fixar um tecto e travar o serviço que regista demasiado.
Nota
o diagnóstico que aqui interessa é o espaço em disco. Para ler e filtrar os logs por unidade, prioridade e padrão, o caminho é o artigo do journalctl, que cobre a análise de conteúdo.
O sintoma: disco cheio sem ficheiros grandes
Comece por confirmar o sistema de ficheiros afectado:
df -h /var
Saída típica num servidor de 40G com o disco quase cheio:
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 40G 37G 1.2G 97% /
O passo seguinte mede os directórios de primeiro nível de /var (o -x impede o du de descer para outros sistemas de ficheiros montados por dentro):
du -xh --max-depth=1 /var | sort -rh | head -6
31G /var
18G /var/lib
8.6G /var/www
2.9G /var/log
1.5G /var/cache
9.1M /var/spool
Se /var/lib pesa 18G — dado real, nada que se toque. Os 8,6G de /var/www também não: são ficheiros do site. O /var/log é o único bloco que se liberta de imediato e sem risco — e aos 97% de ocupação, os 2,6G de journal compram o respiro. Desça um nível: /var/log, desça um nível:
du -xh --max-depth=1 /var/log | sort -rh | head -6
2.9G /var/log
2.6G /var/log/journal
110M /var/log/nginx
18M /var/log/dnf.log
8.9M /var/log/sa
Porquê
o journal cresce: o journald guarda os logs com rotação automática e, por default, autoriza-se a usar até 10% do sistema de ficheiros (tecto de 4GB), deixando 15% livre para o resto do disco. Só encolhe ficheiros arquivados quando escreve logs novos, pelo que o histórico cresce até ao tecto e não recua por si.
Etapa 1: medir o que o journal ocupa
O du mostra o directório, mas o journald tem o seu próprio contador, que distingue ficheiros activos e arquivados:
sudo journalctl --disk-usage
Archived and active journals take up 2.6G in the file system.
A distinção interessa: os ficheiros activos são os que o journald está a escrever, os arquivados são os já rotados. A limpeza manual só actua sobre os arquivados, e este facto explica o erro comum da secção final. Para ver os ficheiros concretos:
sudo ls -lh /var/log/journal/*/ | tail -5
-rw-r----- 1 root systemd-journal 128M Oct 12 07:44 [email protected]
-rw-r----- 1 root systemd-journal 128M Oct 12 08:31 [email protected]
-rw-r----- 1 root systemd-journal 96M Oct 12 08:55 [email protected]
-rw-r----- 1 root systemd-journal 64M Oct 12 09:01 system.journal
Num servidor com semanas de uptime, a lista de ficheiros arquivados chega às dezenas de entradas. O tamanho de cada uma tem tecto próprio: por defeito, 1/8 do SystemMaxUse, com um máximo de 128M — serviços ruidosos multiplicam o número de ficheiros, não o tamanho de cada.
Etapa 2: limpar com vacuum
Antes de apagar, considere guardar: copie os ficheiros para outro disco (cp -a /var/log/journal /backup/logs/) se os registos históricos têm valor. Depois, a sequência correcta é fazer a rotação primeiro e o vacuum depois. A rotação arquiva o ficheiro activo (e abre um novo), para que o vacuum possa actuar sobre tudo:
sudo journalctl --rotate
⚠ Atenção
os comandos seguintes apagam logs arquivados de forma definitiva. Não há confirmação nem recuperação, o que passar não volta. Verifique o que quer manter (--vacuum-time ou --vacuum-size) antes de correr, e confirme no output do journalctl --disk-usage depois.
O vacuum por tamanho remove os arquivos mais antigos até o total arquivado cair abaixo do valor pedido (o ficheiro activo não é tocado):
sudo journalctl --vacuum-size=200M
Deleted archived journal /var/log/journal/4c1f.../[email protected] (128M)
Deleted archived journal /var/log/journal/4c1f.../[email protected] (128M)
Vacuuming done, freed 2.4G of archived journals from /var/log/journal/4c1f....
Variantes úteis por tempo e por contagem de ficheiros:
sudo journalctl --vacuum-time=30days
sudo journalctl --vacuum-files=20
A man page permite combinar rotação e limpeza numa só linha, que fica bem num runbook de manutenção:
sudo journalctl --rotate --vacuum-time=30days
💡 Dica
se os logs arquivados são um activo para a PME (auditoria, investigação de incidentes), não use o vacuum como rotina de limpeza. Exporte para um servidor de logs central antes de apagar: o artigo de logs centralizados mostra o caminho com rsyslog, Loki e ELK.
Etapa 3: fixar um tecto no journald.conf
A limpeza manual resolve o sintoma, mas volta a acontecer. A solução permanente é fixar o tamanho do journal. Escreva um drop-in (não edite o journald.conf principal: os drop-ins sobrevivem a updates do pacote e o sistema ordena-os de forma previsível):
sudo mkdir -p /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/60-limite-journal.conf <<'EOF'
[Journal]
SystemMaxUse=512M
SystemKeepFree=2G
EOF
sudo systemctl restart systemd-journald
As directivas, com os defaults da man page:
| Directiva | Efeito | Default |
|---|---|---|
| SystemMaxUse | tecto do journal em /var/log/journal | 10% do sistema de ficheiros, tecto 4GB |
| SystemKeepFree | espaço livre a deixar no disco | 15% do sistema de ficheiros, tecto 4GB |
| RateLimitIntervalSec | janela de avaliação do rate limit global | 30s |
| RateLimitBurst | mensagens máximas por serviço na janela | 10000 |
| MaxRetentionSec | tempo de retenção dos logs | 0 (desligado) |
Os dois limites valem em simultâneo: o SystemMaxUse limita o total do journal e o SystemKeepFree é o espaço que o disco mantém livre. Num disco de 40G confortável, é o SystemMaxUse=512M que manda. Quando o espaço livre desce abaixo do SystemKeepFree — os 1,2G do sintoma inicial já violam os 2G do exemplo —, a man page descreve o efeito: o journald levanta o limite, deixa de crescer o journal e não apaga nada para se auto-recuperar. É por isso que o vacuum da Etapa 2 vem antes do restart: fixar o tecto não recupera um disco já em pressão. Em discos pequenos (10 a 20G), reduza o SystemKeepFree — o default de 15% em 20G são 3G —, senão o tecto é inalcançável.
Verifique depois do restart:
sudo journalctl --disk-usage
Os limites aplicam-se à medida que o journald escreve; o uso que já está no disco pode não descer com o restart. Confirme com journalctl --disk-usage antes e depois de reiniciar o serviço: se o valor se mantiver, é o vacuum da Etapa 2 que faz o trabalho. Num servidor com o disco já em 97%, a prática sensata é fixar o tecto na Etapa 3 e correr o vacuum da Etapa 2 no mesmo dia: o primeiro evita o regresso do problema, o segundo liberta a pressão já instalada.
Etapa 4: limitar o serviço que enche o journal
Quando um serviço regista sem parar, o tecto da Etapa 3 só adiará o sintoma: o volume chega ao limite mais depressa. O comando seguinte conta entradas, não bytes — um serviço com muitas mensagens curtas também aqui se revela. Descubra quem é o responsável:
sudo journalctl -b -o verbose | grep -oE '(^|[[:space:]])_SYSTEMD_UNIT=[^[:space:]]+' | sort | uniq -c | sort -rn | head -5
Com o serviço identificado, aplique um rate limit próprio à unidade, com LogRateLimitIntervalSec e LogRateLimitBurst. Os valores por serviço sobrepõem-se aos globais do journald.conf:
sudo mkdir -p /etc/systemd/system/NOME_DO_SERVICO.service.d
sudo tee /etc/systemd/system/NOME_DO_SERVICO.service.d/60-logs.conf <<'EOF'
[Service]
LogRateLimitIntervalSec=30s
LogRateLimitBurst=200
EOF
sudo systemctl daemon-reload
sudo systemctl restart NOME_DO_SERVICO
Com o rate limit, o serviço continua a registar e o journald descarta dentro da janela as mensagens acima do limite, com uma nota no log sobre o número descartado. Atenção ao perfil de ruído: um serviço a registar uma linha por segundo soma 30 mensagens na janela de 30s — nunca chega às 10 000 do default, e o LogRateLimitBurst=200 quase não dispara. Para esse caso — debug constante que despeja linhas legítimas — o corte certo é pelo nível de severidade, com LogLevelMax na mesma unidade:
sudo mkdir -p /etc/systemd/system/NOME_DO_SERVICO.service.d
sudo tee /etc/systemd/system/NOME_DO_SERVICO.service.d/70-loglevel.conf <<'EOF'
[Service]
LogLevelMax=4
EOF
sudo systemctl daemon-reload
sudo systemctl restart NOME_DO_SERVICO
Com LogLevelMax=4, o journald guarda o que o serviço escreve até warning: as linhas info e debug são descartadas à entrada, sem tocar em disco.
Erro comum: o vacuum não liberta espaço
Causa 1: o comando só actua sobre arquivos. O --disk-usage inclui ficheiros activos, o vacuum não os toca. Faça a rotação primeiro (--rotate) e o vacuum depois.
Causa 2: o disco encheu por outra causa e passou o limite de espaço livre. O journald nessas condições levanta o limite: deixa de usar mais espaço — não deixa de escrever logs —, e também não encolhe ficheiros antigos para recuperar espaço. Corrija a causa no disco e faça o vacuum manualmente.
Causa 3: /var/log/journal vazio. O Storage= do journald.conf decide: auto grava em /var/log/journal quando o directório existe, em /run/log/journal caso contrário; volatile só em memória. Mudar de persistent para volatile não apaga os dados persistentes que já lá estão, apenas deixa de os usar.
Causa 4: journal só em /run. Em servidores onde /var/log/journal nunca foi criado, os logs vivem em /run/log/journal e desaparecem no reboot. Para activar o modo persistente, crie o directório com os modos correctos e faça flush:
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
sudo journalctl --flush
Veredicto
Numa PME, o journal do systemd não devia ser a variável que enche o disco: fixe o SystemMaxUse (512M num servidor pequeno, 1 a 2G num com muitos serviços), deixe o SystemKeepFree num valor que o disco real permita e trate os serviços ruidosos com o rate limit por unidade da Etapa 4. O vacuum da Etapa 2 é o gesto único de manutenção quando o disco já está cheio, e a combinação de rotação com vacuum fica num runbook. O journal é uma ferramenta de diagnóstico, e o vacuum troca histórico por espaço livre: até onde recuar é decisão de retenção de cada operação — pondere a auditoria contra o risco do disco e fixe a escolha no runbook. Para ler e filtrar o que o journal guarda, siga para o artigo do journalctl.
Artigos Relacionados
- journalctl: Diagnóstico de Serviços Linux do journal ao Root Cause
- Dia 26: Logs Centralizados no Linux, rsyslog, journald, Loki e ELK
- Dia 7: Systemd no Linux, Services, Timers e journalctl
- lsof: Ficheiros Abertos, Portas e Diagnóstico no Linux