01 - journalctl (filtros, desde, seguir)
video: https://youtu.be/... no frontmatter da nota.1. Arquitetura de Acesso e Leitura Mapeada (mmap)
O journalctl distingue-se dos leitores de texto clássicos (como less, grep ou tail) por não realizar operações de leitura sequencial ingênua (read() tradicional) sobre arquivos de texto.
Quando o administrador executa o journalctl, o utilitário invoca internamente a API sd-journal fornecida pela biblioteca libsystemd. O processo de acesso aos dados ocorre em dois modos de operação, definidos pelo nível de privilégio da chamada:
- Acesso Direto por Mapeamento de Memória (
mmap): Se o usuário possui privilégios de leitura direta sobre os arquivos contidos em/var/log/journal/<machine-id>/ou/run/log/journal/<machine-id>/(seja comorootou membro do gruposystemd-journal), ojournalctlmapeia os arquivos binários.journaldiretamente no espaço de endereçamento virtual do processo via chamada de sistemammap(). Isso permite navegar pelas árvores B+ internas e tabelas de hash do arquivo sem incorrer na sobrecarga de copiar blocos de dados do espaço de kernel para o espaço de usuário através de chamadas I/O convencionais. - Acesso Intermediado por IPC (D-Bus): Se executado por um usuário sem permissões de leitura direta no sistema de arquivos, mas autorizado pelas políticas do Polkit, o
journalctlestabelece uma conexão via D-Bus com osystemd-journaldpara solicitar as entradas de log serializadas, atuando como um cliente RPC (Remote Procedure Call).
Como o arquivo binário do journal mantém índices em tabela de hash ordenados temporal e semanticamente, o journalctl pode saltar diretamente para a posição exata de uma entrada de log em tempo constante $O(1)$ ou logarítmico $O(\log N)$, sem precisar descompactar ou parsear o arquivo desde a primeira linha.
2. O Motor de Filtragem por Campos (Field Matching) e Álgebra Booleana
A filtragem no journalctl opera sobre o dicionário de chaves e valores (Key-Value Pair) gravado nativamente em cada entrada do banco de dados binário. A sintaxe de linha de comando implementa uma álgebra booleana estrita para combinar predicados de busca.
2.1. Injeção de Predicados e Igualdade
Qualquer argumento passado na forma CAMPO=valor instrui a API sd-journal a consultar as tabelas de hash de índice associadas àquele campo específico.
Exemplo de campos estruturados de alta cardinalidade:
_SYSTEMD_UNIT=nome.service: Restringe a busca às entradas originadas pelo cgroup atrelado àquela unidade._PID=1234: Filtra eventos produzidos estritamente pelo PID 1234._UID=1000: Filtra eventos de processos executados pelo UID de usuário 1000._COMM=sshd: Filtra pelo nome do processo no espaço do kernel (campocommdo objetotask_struct).PRIORITY=3: Filtra mensagens pelo nível de severidade Syslog (0=Emergência, 3=Erro, 6=Info, 7=Debug).SYSLOG_FACILITY=4: Filtra pela facilidade de origem (ex: 4 = auth/security).
2.2. Lógica Combinatória (AND vs OR)
A combinação de múltiplos argumentos de filtragem obedece às seguintes regras lógicas de ordenamento:
- Operação AND (Conjunção Implícita): A inclusão de campos distintos na mesma linha de comando é processada como um AND lógico.
journalctl _SYSTEMD_UNIT=sshd.service _UID=0 PRIORITY=3
Resultado: Retorna apenas logs gerados pelo sshd.service E disparados pelo usuário root (UID 0) E com prioridade de erro (3).
* Operação OR (Disjunção Explícita via Operador +): Para realizar uniões lógicas entre campos ou valores diferentes, utiliza-se o caractere + isolado como delimitador.
journalctl _SYSTEMD_UNIT=httpd.service + _SYSTEMD_UNIT=nginx.service
Resultado: Retorna entradas onde a unidade é httpd.service OU nginx.service.
* Expressões Mistas: É possível compor grupos complexos combinando conjuntos interseccionados.
journalctl _SYSTEMD_UNIT=nginx.service _PID=5000 + _SYSTEMD_UNIT=php-fpm.service
Resultado: (Nginx AND PID 5000) OR (PHP-FPM).
2.3. Atalhos Sintáticos (-u, -g, -p)
O journalctl provê flags utilitárias que envelopam pesquisas de campos comuns:
-u nginx.service(ou--unit=): Abreviação para_SYSTEMD_UNIT=nginx.service.-p err(ou--priority=): Filtra por prioridade. Permite passar nomes ou números, suportando faixas (ex:-p warning..errbusca entre o nível 4 e 3).-g "expressao"(ou--grep=): Aplica um mecanismo de busca por expressão regular (PCRE2) sobre o campoMESSAGE=. Nota de Desempenho: Ao contrário dos filtros de campo indexados que usam a tabela de hash, o--grepexige que ojournalctldescompacte a string de mensagem de cada entrada que já passou pelos filtros de campo, revertendo parcialmente a busca para $O(N)$ sobre o subconjunto filtrado.
3. Delimitação Temporal e Paginação Robusta por Cursores
A navegação no tempo é um dos pilares do journalctl. Como o journal armazena internamente dois timestamps distintos para cada mensagem — o Realtime Clock (Wall Clock) e o Monotonic Clock do kernel —, o utilitário oferece precisão absoluta mesmo em cenários onde o relógio da máquina sofreu saltos drásticos por sincronização NTP ou alteração manual.
3.1. Filtros de Intervalo Temporal (--since e --until)
As flags -S (--since) e -U (--until) aceitam especificadores de tempo em múltiplos formatos:
- Formatos Absolutos (ISO 8601):
journalctl --since "2026-10-14 08:00:00" --until "2026-10-14 10:30:00" - Formatos Relativos:
journalctl --since "1 hour ago"oujournalctl --since "2 days ago" - Marcadores de Sistema:
journalctl --since "yesterday"oujournalctl --since "today"
3.2. Escopo por Ciclo de Inicialização (-b / --boot)
Em vez de depender de datas, o administrador pode restringir a busca a um ciclo de execução específico do sistema operacional utilizando o campo _BOOT_ID.
journalctl -b: Exibe logs do boot atual (equivalente a filtrar pelo_BOOT_IDcorrente).journalctl -b -1: Exibe logs do boot imediatamente anterior.journalctl -b -2: Exibe logs de dois reboots atrás.journalctl -b 8f5a4e3...: Exibe logs de um_BOOT_IDespecífico de 128 bits.
3.3. Paginação Imutável baseada em Cursores (--cursor)
A navegação por número de linha (ex: OFFSET 100) é inerentemente instável em um banco de dados de logs concorrente de alta gravação, pois novos registros alteram os índices numéricos continuamente. O systemd-journald resolve isso emitindo uma string opaca denominada Cursor para cada registro individual.
Um cursor é gerado concatenando a assinatura do registro:
s=3f1b2c...;i=2c4;b=8f5a...;m=1a2b...;t=5c3d...;x=8e7f...
Essa estrutura encapsula:
s(Sequential Number): O número de sequência global da mensagem.i(Inode / Entry Array Index): O índice interno dentro do arquivo.journal.b(Boot ID): O UUID do boot.m(Monotonic Timestamp): O tempo em microssegundos desde o início do boot.t(Realtime Timestamp): O tempo em microssegundos desde a Época Unix.
O uso da flag --cursor="s=..." instrui o journalctl a buscar a posição exata daquela estrutura de dados na árvore do arquivo, independente do relógio ter sido alterado. As aplicações de monitoramento de terceiros gravam a string do último cursor processado em disco (--cursor-file=arquivo.txt) para garantir a retoma da leitura sem perda nem duplicidade de eventos caso o processo coletor seja interrompido subitamente.
4. Acompanhamento de Fluxo em Tempo Real via Kernel Inotify (--follow)
A funcionalidade de acompanhamento contínuo da cauda do log (journalctl -f ou --follow) replica o comportamento histórico do tail -f, mas opera sobre o ecossistema de eventos do kernel Linux.
Mecânica Interna da Flag -f:
- Posicionamento Inicial: O
journalctllê os últimos 10 registros (ou o valor especificado pela flag-n/--lines=) navegando retrogradamente a partir do final da árvore do arquivo. - Registro de Evento
inotify: O processo invoca a chamada de sistemainotify_init()e adiciona um monitor (inotify_add_watch()) no diretório onde os arquivos.journalresidem (/var/log/journal/<machine-id>/). Ele escuta eventos do tipoIN_MODIFYeIN_CREATE. - Espera Bloqueante (Poll/Epoll): O
journalctlentra em um laço de espera não-ocupativa (epoll_wait()), consumindo 0% de CPU enquanto nenhum novo dado é gravado no disco pelosystemd-journald. - Despertar e Rotação Dinâmica: Quando o
systemd-journaldexecuta a chamadawrite()oummap_write()adicionando uma nova entrada no arquivo ativo, o kernel dispara o eventoIN_MODIFY. Ojournalctlacorda, lê o novo trecho utilizando a estrutura indexada do cursor atual, atualiza seu ponteiro interno e imprime a linha na tela. Se o journal sofrer rotação (o arquivo ativo é fechado como.journal~e um novo.journalé criado), a API intercepta o eventoIN_CREATEe altera silenciosamente os descritores de arquivo monitorados sem interromper o fluxo de saída no terminal do usuário.
5. Serialização de Saída e Formatos de Exportação (-o / --output)
O journalctl possui um compilador de formatação interna que lê as estruturas de dicionário da libsystemd e as serializa em variados formatos de apresentação via flag -o (ou --output=):
| Formato | Comportamento Arquitetural e Estrutural |
|---|---|
short |
(Padrão) Formato Syslog clássico em linha única (Mon DD HH:MM:SS host service[PID]: mensagem). |
short-precise |
Idêntico ao short, mas exibe o timestamp com precisão de microssegundos (essencial para debugging de concorrência). |
json |
Serializa o dicionário completo de cada entrada em um objeto JSON válido por linha (formato JSON Lines / ndjson). Transforma todos os campos internos (_SYSTEMD_UNIT, _PID, etc.) em chaves de primeiro nível. |
json-pretty |
Formatador de exibição humana do JSON, identado e espaçado. Ineficiente para pipelines de texto, mas ideal para inspeção de campos raros. |
cat |
Limpa absolutamente todos os metadados, timestamps, nomes de host e PIDs, emitindo estritamente o texto bruto contido dentro do campo MESSAGE=. |
export |
Formato binário/texto nativo da suíte systemd (Systemd Journal Export Format). Preserva a integridade dos tipos primitivos e blocos binários. É o formato utilizado pelo comando systemd-journal-remote para streaming de logs via rede HTTP/HTTPS. |
verbose |
Exibe a estrutura chave-valor completa do registro no formato de bloco legível, exibindo hash de integridade, offsets de inode e flags do FSS. |
Exemplo de saída utilizando o formato json:
{
"__CURSOR": "s=3f1b2c...;i=2c4;b=8f5a...",
"__REALTIME_TIMESTAMP": "1791888000000000",
"__MONOTONIC_TIMESTAMP": "123456789",
"_BOOT_ID": "8f5a4e3c2b1a0987654321fedcba0987",
"_SYSTEMD_UNIT": "sshd.service",
"_PID": "2045",
"_UID": "0",
"_COMM": "sshd",
"MESSAGE": "Accepted publickey for root from 192.168.1.50 port 54321 ssh2",
"PRIORITY": "6"
}
6. Análise de Desempenho e Custo Computacional das Consultas
Compreender o custo de execução das chamadas no journalctl é vital para a escrita de automações que não causem exaustão de I/O em servidores sob alta carga.
+-----------------------------------------------------------------------+
| Estratégia de Busca e Custo de I/O |
+-----------------------------------------------------------------------+
| |
| 1. Filtro por Campo Indexado (_SYSTEMD_UNIT=, _PID=, _UID=) |
| [Tabela Hash / Árvore B+] ---> Busca O(1) a O(log N) |
| (Desempenho Extremo - Acesso Direto aos Blocos Indexados) |
| |
| 2. Filtro Temporal (--since, --until, -b) |
| [Busca Binária sobre Timestamps Monotônicos/Realtime] |
| (Desempenho Alto - Descarta Arquivos Inteiros Fora do Intervalo) |
| |
| 3. Filtro por Expressão Regular / Texto Bruto (-g / --grep) |
| [Varredura Sequencial + Descompactação de Mensagens] |
| (Custo Elevado - Requer Leitura Exaustiva O(N) do Subconjunto) |
| |
+-----------------------------------------------------------------------+
Regras de Otimização de Consultas:
- Sempre aplique restrições de campo antes de expressões regulares: Rodar
journalctl -g "error"força o sistema a ler e descompactar a mensagem de todas as entradas gravadas no disco. Rodarjournalctl -u app.service -g "error"reduz a busca por regex estritamente ao subconjunto de entradas previamente indexadas daquela unidade. - Combine limites temporais com cursores em pipelines automatizados: Evite ler o arquivo do início continuamente. O utilitário que consome logs deve gravar o
__CURSORda última linha lida e passar--cursor="..."na invocação subsequente. - Evite a conversão para texto se o destino for outro utilitário systemd: Ao transferir logs entre máquinas através da rede, utilize
journalctl -o exportem conjunto com osystemd-journal-remote. Isso evita a sobrecarga de serializar dados em texto no remetente para desparsear o texto no destino, mantendo a integridade binária dos metadados através do pipeline de transporte.