Log de erros

O Valério perguntou no FGdH se haveria um log unificado de erros no GNU/Linux. Tentarei responder aqui.

Existem três maneiras de logar:

1) Usar a função syslog() da libc ou sd_journal_*() da libsystemd. Mensagens publicadas dessa forma serão processadas pelo daemon syslog (rsyslog, syslog-ng, etc.) ou pelo systemd-journald.

2) Enviar diretamente as mensagens para um arquivo.

3) Enviar as mensagens para stdout e/ou stderr.

Na minha opinião, todo daemon deveria logar usando syslog e, apenas quando estritamente necessário, mandar mensagens adicionais para um arquivo (a ser rotacionado pelo logrotate). Exemplo: eu configuro o Squid para logar mensagens de status apenas via syslog (opção -s) e deixo o log de acesso em /var/log/squid/access.log. É possível despejar o log de acesso no syslog também ou desabilitá-lo completamente caso desejado.

Alguns daemons têm o hábito de logar para stdout/stderr. Em distribuições que usem o systemd você pode ter a certeza que tais mensagens serão capturadas pelo journald, e que, se existir uma implementação syslog alternativa instalada, esta as receberá. É uma segunda possibilidade: caso o daemon não suporte logar via syslog, fazendo-o via stdout/stderr terá o mesmo efeito em distribuições modernas. Nota: acredito que Upstart da mesma forma redirecione tudo para o syslog.

Então, uma maneira de achar o log de erros é filtrar na implementação syslog mensagens que tenham prioridade entre 0 e 3 (e talvez 4). São elas:

0 emergência (emerg)
1 alerta (alert)
2 crítico (crit)
3 erro (err)
4 aviso (warning)
5 notícia (notice)
6 informação (info)
7 depuração (debug)

Daemons syslog permitem configurar arquivos específicos de log para receberem mensagens de determinadas prioridades. O (open)SUSE, por exemplo, joga mensagens com prioridade 4 até 0 (quanto menor o número, maior a prioridade) em /var/log/warn. Contudo, não existe padronização definida. Cada distribuição tem suas peculiaridades e configura de forma diferente.

Com o journald (preferencialmente configurado para armazenar as mensagens), podemos usar:

# journalctl --since=-72h --priority=0..3
-- Logs begin at Sex 2015-01-30 16:57:35 BRST, end at Sex 2015-02-06 09:01:01 BRST. --
Fev 04 08:55:46 pluto.localdomain kernel: watchdog watchdog0: watchdog did not stop!
-- Reboot --
Fev 04 09:22:50 pluto.localdomain squid[1345]: Failed to make swap directory /var/cache/squid: (13) Permission denied
Fev 04 09:22:50 pluto.localdomain systemd[1]: Failed to start Squid caching proxy.
Fev 04 09:28:23 pluto.localdomain firewalld[294]: 2015-02-04 09:28:23 ERROR: ALREADY_ENABLED: ssh
Fev 04 09:32:46 pluto.localdomain kernel: watchdog watchdog0: watchdog did not stop!
-- Reboot --
Fev 04 09:33:21 pluto.localdomain systemd[1]: Reload failed for Squid caching proxy.
Fev 04 09:58:22 pluto.localdomain firewalld[294]: 2015-02-04 09:58:22 ERROR: NOT_ENABLED: masquerade

Para modificar a forma como os resultados são exibidos, temos a opção --output.

O recurso que diferencia o journald são os metadados adicionados em cada mensagem. Quando são apenas repassadas para uma implementação syslog, não os aproveitamos.

Pode um programa não logar via syslog. E, se não for um daemon, stdout e stderr não serão capturados pelo journald. Suas mensagens não serão processadas pela implementação syslog e só restará você garimpar em /var/log (ou sabe-se lá onde) se existe alguma coisa do programa em questão.

Relacionado:
Um concentrador de logs

Comentários