journalctl: filtrar log como gente grande
A maioria das pessoas usa três comandos do journalctl e sofre com o resto. Ele é um banco de dados indexado, não um arquivo de texto — e isso muda completamente o que dá para perguntar.
Equipe EasyOps Cloud · · 7 min de leitura
Quase todo mundo usa o journalctl de três formas: -u servico, -f para
acompanhar, e | grep para o resto. Funciona, e desperdiça o que a ferramenta tem
de melhor.
O journal não é um arquivo de texto — é um banco indexado, onde cada linha carrega dezenas de campos estruturados além da mensagem. Saber consultar esses campos muda a investigação de incidente de "procurar agulha no palheiro" para "perguntar exatamente o que interessa".
O que existe além da mensagem
Comece vendo tudo que uma linha carrega:
journalctl -u nginx -n 1 -o verboseA saída traz campos como _PID, _UID, _SYSTEMD_UNIT, _HOSTNAME, _BOOT_ID, PRIORITY,
_COMM, _EXE e _CMDLINE. Todos são consultáveis diretamente, sem grep:
journalctl _COMM=sshd
journalctl _UID=1001
journalctl _PID=21847
journalctl _EXE=/usr/sbin/nginxFiltros com o mesmo campo são combinados com "ou"; campos diferentes, com "e":
# sshd OU sudo
journalctl _COMM=sshd _COMM=sudo
# do usuario 1001 E do processo sshd
journalctl _UID=1001 _COMM=sshdA diferença em relação ao grep não é apenas elegância. O grep acerta a mensagem
por texto e traz falso positivo — uma linha que menciona nginx no meio de outra
coisa. O filtro por campo é exato, e usa índice em vez de varrer.
Tempo, que é o filtro mais usado
journalctl --since '2026-08-10 14:00' --until '2026-08-10 15:30'
journalctl --since '30 min ago'
journalctl --since yesterday --until today
journalctl --since '09:00' # hoje, às 9hPara investigar um incidente, a janela costuma ser o primeiro corte. Uma dica que economiza tempo: pegue alguns minutos antes do sintoma. A causa quase nunca está no instante em que o erro apareceu — está no que aconteceu logo antes.
Também dá para recortar por inicialização da máquina, o que é útil quando o problema é no boot:
journalctl --list-boots
journalctl -b # o boot atual
journalctl -b -1 # o boot anterior
journalctl -b -1 -p err # erros do boot anteriorO -b -1 é o comando que responde "por que a máquina caiu ontem?" — ele mostra o
que foi registrado antes do desligamento, que se perde se você só olhar o boot
atual.
Prioridade: separar ruído de problema
journalctl -p err # err e mais graves
journalctl -p warning..err # faixa
journalctl -u meuapp -p err -bOs níveis vão de emerg (0) a debug (7). Na prática, -p err é o corte que
transforma milhares de linhas em algumas dezenas.
Vale saber que o nível depende de a aplicação registrar corretamente. Muito
programa manda tudo para a saída padrão, e o journald classifica tudo como info
— nesse caso o filtro por prioridade não ajuda, e a solução é a aplicação usar o
nível certo.
Combinando janela, unidade e prioridade, chega-se rápido ao essencial:
journalctl -u meuapp --since '1 hour ago' -p warning --no-pagerO --no-pager evita o paginador quando você quer a saída direta, para canalizar
para outro comando.
Seguir ao vivo, com filtro
journalctl -f -u meuapp
journalctl -f -u nginx -u php8.3-fpm # duas unidades juntas
journalctl -f -p err # só erro, de tudoAcompanhar duas unidades relacionadas ao mesmo tempo é subestimado. Ver nginx e php-fpm
lado a lado mostra a sequência real — a requisição chegou, o backend demorou, o
proxy desistiu — que fica invisível olhando um log de cada vez.
Para reproduzir um problema, o padrão que funciona é abrir o acompanhamento em uma sessão, disparar a ação em outra, e ler o que apareceu.
Saída estruturada, quando o olho não dá conta
journalctl -u meuapp -o json-pretty -n 5
journalctl -u meuapp -o json --since '1 hour ago' | \
python3 -c "
import json,sys,collections
c=collections.Counter()
for l in sys.stdin:
d=json.loads(l)
c[d.get('MESSAGE','')[:60]] += 1
for m,n in c.most_common(15): print(f'{n:5} {m}')
"Esse agrupamento por mensagem é o mesmo raciocínio descrito no artigo sobre triagem de log com LLM: contar assinaturas revela padrão que a leitura linha a linha não revela, e custa nada.
Outros formatos úteis:
journalctl -o cat # só a mensagem, sem prefixo
journalctl -o short-iso # data em ISO, boa para ordenarO -o cat é o que você quer ao canalizar para outra ferramenta, porque remove
timestamp e nome de unidade que atrapalhariam a análise.
Investigar um incidente, na prática
Uma sequência que funciona bem quando algo aconteceu e você não sabe o quê:
# 1. Panorama de erros na janela
journalctl --since '14:00' --until '15:00' -p err --no-pager | head -50
# 2. O que reiniciou nesse período
journalctl --since '14:00' -u '*' -p notice --no-pager | grep -i -E 'start|stop'
# 3. O kernel viu alguma coisa?
journalctl -k --since '14:00' --no-pager
# 4. Alguém entrou ou executou sudo
journalctl --since '14:00' _COMM=sshd _COMM=sudo --no-pagerO passo 3 é o mais esquecido e o que mais explica sumiço inesperado: OOM killer, disco com erro e problema de rede aparecem no log do kernel, não no da aplicação. O artigo sobre o OOM killer detalha como ler essas mensagens.
O passo 4 responde a pergunta desconfortável mas necessária: alguém mexeu?
Espaço e retenção
O journal tem limite próprio e o padrão é generoso demais — até 10% do disco:
journalctl --disk-usage# /etc/systemd/journald.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=30daysudo systemctl restart systemd-journaldO Storage=persistent merece atenção: sem ele, em algumas configurações o journal
fica só em memória e some no reinício — justamente quando você precisa saber o
que aconteceu antes da máquina cair. Confira se /var/log/journal existe:
ls -d /var/log/journal 2>/dev/null || \
echo "journal volátil — cria o diretório para persistir"Para corte imediato quando o disco apertar:
sudo journalctl --vacuum-size=500M
sudo journalctl --vacuum-time=14dO tema completo de espaço está no artigo sobre disco cheio — journal sem limite é uma das causas recorrentes.
Exportar para levar embora
Quando o log precisa sair da máquina — para anexar em chamado, ou analisar com calma:
journalctl -u meuapp --since '2 hours ago' -o short-iso > /tmp/meuapp.log
# Ou o formato nativo, que preserva todos os campos
journalctl -u meuapp --since '2 hours ago' -o export | \
gzip > /tmp/meuapp.journal.gzAntes de enviar para qualquer lugar, vale lembrar que log costuma conter dado sensível — token em URL, e-mail, IP de usuário. Filtrar antes de compartilhar é parte da higiene, e o artigo sobre segredos no servidor traz os comandos para achar o que vazou.
Os comandos que valem memorizar
journalctl -u SERVICO -f # acompanhar
journalctl -u SERVICO -p err --since '1h ago' # o que deu errado
journalctl -b -1 -p err # por que caiu
journalctl -k --since '30 min ago' # o kernel viu?
journalctl _COMM=sudo --since today # quem mexeu
journalctl --disk-usage # quanto ocupaSeis comandos cobrem a maior parte das investigações. O que muda o resultado não é conhecer opções exóticas — é lembrar de olhar o log do kernel e o boot anterior, que são justamente os dois lugares onde a resposta costuma estar e que quase ninguém consulta.
Correlacionar com o que não está no journal
O journal cobre serviços do systemd e o kernel. Fica de fora o que grava em
arquivo próprio — nginx, muitas aplicações, e ferramentas antigas.
Numa investigação isso importa, porque a sequência real de eventos está espalhada. Uma forma prática de juntar é normalizar o formato de tempo e mesclar por ordem:
journalctl -u meuapp --since '14:00' --until '15:00' -o short-iso --no-pager \
> /tmp/a.log
sudo awk '{print}' /var/log/nginx/error.log > /tmp/b.log
sort -m /tmp/a.log /tmp/b.log | lessVale um investimento maior quando isso se repete: fazer a aplicação registrar no journal em vez de em arquivo. Basta escrever na saída padrão e deixar o systemd capturar — o que já acontece automaticamente com uma unit bem escrita.
O ganho é ter tudo no mesmo lugar, com os mesmos filtros e a mesma retenção. E some uma categoria inteira de problema: log de aplicação sem rotação, que é uma das formas mais comuns de encher disco.
Se a aplicação usa formato estruturado, o journald preserva os campos quando o
texto é JSON com os nomes esperados — o que permite filtrar por campo próprio da
aplicação, como identificador de requisição, exatamente como se filtra por _PID.
Vale um último hábito que muda a qualidade de toda investigação futura: quando encontrar a linha que explicou um incidente, anote o comando que a encontrou. Uma lista curta de consultas que já funcionaram no seu ambiente vale mais que qualquer manual, porque ela é específica dos serviços que você opera e dos erros que eles de fato produzem.