02 - Persistência vs Volátil
video: https://youtu.be/... no frontmatter da nota.1. Modos de Armazenamento e a Diretiva Storage=
O comportamento do systemd-journald em relação à retenção de dados é governado primariamente pela diretiva Storage= no arquivo de configuração /etc/systemd/journald.conf (ou em drop-ins em /etc/systemd/journald.conf.d/*.conf). A taxonomia dos modos de armazenamento compreende quatro estados mutuamente exclusivos:
1.1. Storage=volatile
Neste modo, os dados do journal são gravados estritamente em memória RAM, utilizando o sistema de arquivos temporário tmpfs montado em /run/log/journal/.
- Comportamento de Ciclo de Vida: Nenhuma informação é escrita no disco rígido ou SSD. No instante em que o sistema operacional é desligado ou reiniciado (ou se ocorrer um power loss ou Kernel Panic), a totalidade dos registros mantidos em memória volatiliza-se irreversivelmente.
- Casos de Uso Primários: Sistemas embarcados (embedded Linux) com memórias Flash do tipo NOR/NAND sujeitas a desgaste por ciclos de escrita (Program/Erase cycles), sistemas operando com raiz em modo somente leitura (Read-Only Root Filesystem), e nós de processamento efêmeros em clusters (stateless nodes) onde os logs são transmitidos em tempo real pela rede via
systemd-journal-remote.
1.2. Storage=persistent
Força a gravação dos dados em armazenamento não volátil, no diretório /var/log/journal/.
- Comportamento Autônomo: Se o diretório
/var/log/journal/não existir no momento em que o daemon é iniciado (ou durante a transição de boot), o própriosystemd-journaldtenta criar o diretório com as permissões e contextos de segurança (SELinux/AppArmor) corretos, ativando a persistência imediatamente. - Casos de Uso Primários: Servidores de produção, estações de trabalho e qualquer ambiente onde a auditoria histórica pós-reboot, análise de causa raiz (post-mortem analysis) e conformidade regulatória sejam mandatórias.
1.3. Storage=auto (O Padrão Distribuído)
Representa uma abordagem híbrida e condicional. É a configuração padrão na maioria das distribuições Linux modernas (Debian, Ubuntu, RHEL, Arch Linux).
- Lógica de Decisão: O
systemd-journaldverifica ativamente a existência física do diretório/var/log/journal/. - Se o diretório existir, o daemon comporta-se exatamente como
Storage=persistent, gravando no disco não volátil. -
Se o diretório não existir, o daemon atua como
Storage=volatile, gravando em/run/log/journal/, sem criar o diretório em/var/de forma autônoma. -
Garantia de Flexibilidade: Permite que distribuidores ofereçam uma única imagem de sistema onde a persistência pode ser ativada pelo administrador simplesmente criando o diretório com
mkdir -p /var/log/journale reiniciando o serviço ou aplicando o flush.
1.4. Storage=none
Aniquila completamente a retenção local de logs.
- Comportamento Interno: Todas as entradas de log recebidas via pipes de
stdout/stderr, soquete/dev/logou/dev/kmsgsão descartadas imediatamente no espaço de memória (redirecionadas internamente para um nulo funcional). - Exceções: Se a duplicação/encaminhamento estiver ativada (
ForwardToSyslog=yes,ForwardToConsole=yes, etc.), as mensagens ainda serão entregues a esses destinos externos antes do descarte do registro no journal.
2. A Mecânica de Transição no Boot: O Processo de Flush
Um dos desafios mais complexos na arquitetura de inicialização do Linux é a fase do early boot. Quando o kernel passa o controle para o PID 1 (systemd), o sistema de arquivos raiz (/) frequentemente está montado apenas como leitura (Read-Only), e a partição dedicada /var/ pode residir em um volume LVM, disco cifrado via LUKS ou ponto de montagem de rede que ainda não está disponível.
Para resolver o paradoxo de ter que registrar logs antes que o disco de destino de logs possa ser escrito, o systemd-journald implementa um pipeline de migração em duas fases denominado Flush.
+-------------------------------------------------------------------------+
| FASE 1: EARLY BOOT |
| |
| [Kernel Ring Buffer / Stdout / Sockets] |
| │ |
| ▼ |
| systemd-journald (RAM) |
| │ |
| ▼ |
| /run/log/journal/<machine-id>/ |
| (tmpfs - Volátil / Alta Velocidade) |
+-------------------------------------------------------------------------+
│
│ Montagem do /var (Read-Write)
│ Alcançado: local-fs.target
│ Execução: systemd-journal-flush.service
▼
+-------------------------------------------------------------------------+
| FASE 2: LATE BOOT |
| |
| 1. Interrupção temporária de novas gravações |
| 2. Leitura dos arquivos em /run/log/journal/<machine-id>/ |
| 3. Transfere e funde entradas em /var/log/journal/<machine-id>/ |
| 4. Remoção atômica dos arquivos binários em RAM |
| 5. Transição de ponteiros de escrita para o Disco Não-Volátil |
+-------------------------------------------------------------------------+
2.1. Sequenciamento de Unidades do Systemd
A migração ordenada do estado volátil para o persistente é orquestrada por uma unidade de serviço dedicada no Grafo Acíclico Dirigido (DAG): systemd-journal-flush.service.
- Montagem do Sistema de Arquivos: O boot prossegue até que todos os sistemas de arquivos locais declarados em
/etc/fstabestejam devidamente montados em modo leitura-escrita (Read-Write). A conclusão desta fase é sinalizada pela unidadelocal-fs.target. - Invocação do Flush: A unidade
systemd-journal-flush.servicepossui as diretivas:
Requires=local-fs.target
After=local-fs.target
ExecStart=journalctl --flush
- A Syscall / Sinal IPC: O comando
journalctl --flushnão realiza a cópia direta por si só; ele envia uma requisição IPC D-Bus (ou o sinal assíncronoSIGUSR1) para o processosystemd-journaldativo.
2.2. A Transfomação Atômica de Estado (Merging)
Ao receber a instrução de flush, o systemd-journald executa a seguinte sequência de operações binárias de baixo nível:
- Abre o diretório persistente
/var/log/journal/<machine-id>/. - Trava temporariamente as threads de gravação para garantir a consistência das tabelas B-Tree dos arquivos em memória RAM.
- Lê os registros do arquivo
.journalpresente em/run/log/journal/<machine-id>/. - Insere ordenadamente cada registro no arquivo
.journalativo dentro de/var/log/journal/<machine-id>/, recomputando os hashes do dicionário, atualizando as árvores de busca e integrando os metadados de tempo (Realtime e Monotonic). - Desconecta os descritores de arquivo de
/run/log/journal/. - Deleta sumariamente os arquivos de log do diretório volátil e remove a estrutura temporária do
tmpfs. - Redireciona todos os ponteiros de escrita dos novos logs de entrada diretamente para o disco rígido/SSD.
Este mecanismo garante que nenhuma mensagem de log gerada nos primeiros milissegundos do boot seja perdida, unificando o histórico do early boot e do runtime em um único repositório ordenado.
3. Estrutura Física de Diretórios e a Função do machine-id
A organização dos arquivos binários em disco e em memória RAM segue uma estrita hierarquia de namespaces isolados por nó físico.
3.1. O Caminho do Identificador Único
Tanto em /run/log/journal/ quanto em /var/log/journal/, o systemd-journald nunca grava arquivos diretamente na raiz do diretório. Ele exige a criação de um subdiretório cujo nome é o código hexadecimal de 128 bits da máquina:
- Caminho Volátil:
/run/log/journal/3a8f9b2c1d4e5f6a7b8c9d0e1f2a3b4c/ - Caminho Persistente:
/var/log/journal/3a8f9b2c1d4e5f6a7b8c9d0e1f2a3b4c/
Este identificador é lido diretamente do arquivo /etc/machine-id (ou /var/lib/dbus/machine-id).
Razão Arquitetural do Isolamento por Machine ID:
Em ambientes corporativos com armazenamento centralizado via SAN, NFS ou iSCSI, múltiplos servidores virtuais ou físicos podem ter suas partições /var/log/ montadas em um volume de rede compartilhado. Se o systemd-journald gravasse em caminhos genéricos, haveria corrupção catastrófica de arquivos binários devido a escritas concorrentes por diferentes PIDs de diferentes kernels. Ao isolar os arquivos pelo machine-id único de cada SO, múltiplos nós podem compartilhar o mesmo diretório de armazenamento central sem risco de colisão de I/O.
3.2. Anatomia dos Arquivos .journal
Dentro do subdiretório do machine-id, encontram-se os arquivos de dados propriamente ditos:
system.journal: O arquivo de gravação ativo para logs gerados pelo kernel, serviços do sistema e daemons do espaço de usuário.user-<UID>.journal: Arquivos de gravação ativos para logs gerados pelas instâncias dosystemd --userde usuários comuns logados (por exemplo,user-1000.journal).system@<hash>.journal/user-<UID>@<hash>.journal: Arquivos rotacionados. Quando o arquivo ativo atinge os limites de tamanho estabelecidos em configuração, ele é selado (marcado como somente leitura) e renomeado acrescentando o hash do identificador e dos timestamps, e um novo arquivo ativo é criado.system.journal~/user-<UID>.journal~: Arquivos de log corrompidos ou desconectados de forma imprópria. Se a máquina sofrer uma queda de energia catastrófica enquanto osystemd-journaldrealizava uma operação de gravação, o cabeçalho do arquivo não terá a flag de fechamento limpo (dirty bit ativo). No boot seguinte, osystemd-journaldrenomeia o arquivo adicionando o caractere~ao final, isola o arquivo corrompido para preservação forense e inicia um novosystem.journalzerado.
4. Análise Comparativa de Impacto no Sistema
A escolha entre persistência total, volatilidade estrita ou operação híbrida afeta diretamente três métricas de infraestrutura: latência de I/O, desgaste de hardware e capacidade de recuperação de desastres.
| Métrica / Propriedade | Armazenamento Volátil (/run/) |
Armazenamento Persistente (/var/) |
|---|---|---|
| Meio Físico | RAM (tmpfs). |
Disco de Bloco (SSD, NVMe, HDD). |
| Latência de Escrita | Nanossegundos / Microssegundos (Acesso direto a memória bus). | Milissegundos (Submetido a filas de I/O de bloco, barriers e flush do FS). |
| Consumo de Recursos | Consome memória RAM alocada dinamicamente (pode pressionar a VFS). | Consome espaço em disco não volátil (sujeito a exaustão de inodes/espaço). |
| Sobrevivência ao Reboot | Não. Histórico é perdido 100% a cada reinicialização. | Sim. Mantém histórico completo acumulado de múltiplos boots. |
| Resistência a Panic/Crash | Logs do momento do crash são perdidos se a RAM for zerada. | Preserva logs até a última chamada de fsync ou intervalo de sync. |
| Desgaste de Hardware | Zero desgaste em mídias de armazenamento Flash. | Causa gravações contínuas (submete SSDs a desgaste de TBW - Bytes Written). |
| Atribuição de Segurança | Requer reconstrução da árvore em memória a cada boot. | Suporta validação contínua de integridade via FSS (Forward Secure Sealing). |
5. Sincronização de Disco e a Diretiva SyncIntervalSec=
No modo persistente, escrever todas as mensagens de log no disco no exato instante em que chegam inviabilizaria o desempenho do sistema de I/O da máquina. Um servidor web recebendo 10.000 requisições por segundo geraria 10.000 operações de escrita de bloco atômicas por segundo, forçando o motor de disco a atuar em pico constante de operação.
Para balancear a performance do sistema com a integridade dos dados, o systemd-journald utiliza uma técnica de Gravação Assíncrona Buffereada combinada com chamadas de sincronização periódicas.
5.1. A Mecânica do SyncIntervalSec=
A diretiva SyncIntervalSec= no /etc/systemd/journald.conf (cujo valor padrão é tipicamente 5s) determina o intervalo máximo de tempo antes que o systemd-journald force uma chamada de sistema fdatasync() ou fsync() nos arquivos .journal abertos no disco.
- Quando uma mensagem chega ao
journald, ela é parseada, indexada na memória e gravada na página de buffer do sistema de arquivos no kernel (Page Cache). - A mensagem é considerada ingerida, mas ainda reside no cache de escrita não volátil do kernel.
- A cada ciclo de
SyncIntervalSec=, osystemd-journaldacorda uma thread interna e emite umfdatasync()nos descritores de arquivos ativos. Isso força o subsistema VFS do kernel a esvaziar os dirty buffers de memória e gravar fisicamente os blocos nos pratos do HD ou na memória Flash do SSD.
5.2. Tratamento de Emergências e Gravação Síncrona
O systemd-journald quebra a regra da assincronicidade e força uma escrita síncrona imediata (fsync() instantâneo) sem aguardar o temporizador do SyncIntervalSec= se a mensagem de log recebida possuir uma prioridade Syslog crítica:
PRIORITY=0(Emergency / Emergência)PRIORITY=1(Alert / Alerta)PRIORITY=2(Critical / Crítico)PRIORITY=3(Error / Erro)
Isto garante que, em caso de falha crítica iminente do aplicativo ou pânico de kernel iminente, as mensagens que explicam a causa do colapso sejam consolidadas no disco não volátil antes do desastre total.
6. Manipulação Prática e Diagnóstico de Estado
O administrador de sistemas interage com a máquina de estados de armazenamento através do utilitário journalctl e chamadas diretas de controle do systemd.
6.1. Verificação do Modo Ativo de Armazenamento
Para verificar se o journald está operando em modo volátil ou persistente no momento presente, inspeciona-se a localização dos arquivos ativos através do próprio journalctl:
# Exibe os arquivos de journal atualmente mapeados na memória
journalctl --header | grep -E "File Path|State"
Se as rotas exibidas apontarem para /run/log/journal/..., o sistema está em modo volátil. Se apontarem para /var/log/journal/..., o sistema está em modo persistente.
6.2. Forçando o Flush Manualmente
Caso o administrador tenha acabado de criar o diretório /var/log/journal/ em um sistema configurado como Storage=auto, não é necessário reiniciar o servidor. A migração dos logs residentes na RAM para o disco pode ser forçada instantaneamente com o comando:
journalctl --flush
Este comando bloqueia o terminal até que toda a base de dados acumulada em /run/ seja transcrita, indexada e consolidada em /var/, removendo os arquivos voláteis ao final.
6.3. Relocação Volátil Forçada (journalctl --relocate)
O comando oposto ao flush é o journalctl --relocate. Ele instrui o systemd-journald a fechar os arquivos no disco não volátil (/var/log/journal/), mover todos os registros atuais para o sistema de arquivos em memória RAM (/run/log/journal/) e continuar gravando exclusivamente em RAM a partir daquele ponto. Este comando é fundamental em operações de manutenção onde a partição /var/ precisa ser desmontada para redimensionamento de LVM, verificação de consistência (fsck) ou criptografia em tempo de execução.