Os ficheiros de log Linux que deve monitorizar em RHEL 9 e 10
Um guia prático para os ficheiros de log que importam em Red Hat Enterprise Linux 9 e 10 e em sistemas compatíveis (Oracle Linux, AlmaLinux, Rocky Linux): onde vive cada um, o que lhe diz, os comandos para o ler, e como o conservar e centralizar.

Todos os problemas num servidor Linux deixam um rasto algures: um login falhado, um serviço que não arrancou, uma atualização de pacote que mudou uma biblioteca, um disco que começou a dar erros. Saber que log guarda que rasto é a diferença entre um diagnóstico de cinco minutos e uma tarde de adivinhação. Este guia cobre os logs que importam em Red Hat Enterprise Linux 9 e 10, e em sistemas compatíveis como Oracle Linux, AlmaLinux e Rocky Linux, com os comandos que usamos para os ler.
Dois sítios onde os logs vivem em RHEL: o journal e /var/log
Em RHEL 9 e 10 quase tudo é recolhido primeiro pelo systemd-journald. O journal é um repositório estruturado e indexado que se lê com journalctl. Numa instalação padrão, o rsyslog lê depois o journal e escreve os conhecidos ficheiros de texto em /var/log: messages, secure, cron, maillog e boot.log. Alguns serviços mantêm os seus próprios ficheiros de qualquer forma, nomeadamente o audit daemon, os servidores web, as bases de dados e o dnf.
Confirme que o rsyslog está presente e a correr antes de confiar nos ficheiros de texto. As imagens minimal e de containers podem não o incluir:
rpm -q rsyslog
systemctl status rsyslog
# if it is missing:
dnf install rsyslog
systemctl enable --now rsyslog
A maioria dos ficheiros em /var/log só pode ser lida pelo root, por isso execute os comandos abaixo como root ou com sudo.
O journal do systemd
O journal é o primeiro sítio onde olhar, porque guarda a saída de todas as units do systemd, do kernel e de tudo o que regista através do syslog, tudo com timestamps precisos e metadados pelos quais pode filtrar.
Comandos que vale a pena memorizar
# everything from one service, newest last
journalctl -u nginx
# follow a service live, like tail -f
journalctl -u sshd -f
# only errors and worse, from the current boot
journalctl -p err -b
# warnings and worse from the previous boot (useful after a crash)
journalctl -p warning -b -1
# a time window
journalctl --since "1 hour ago"
journalctl -u php-fpm --since "2026-10-22 08:00" --until "2026-10-22 09:00"
# kernel messages only (the replacement for reading a dmesg file)
journalctl -k -b
# search message text
journalctl -u sshd -g "Failed password"
# list the boots the journal knows about
journalctl --list-boots
Várias opções -u podem ser combinadas, o que dá jeito quando um pedido passa por mais do que um serviço: journalctl -u nginx -u php-fpm --since "10 min ago".
Torne o journal persistente
Numa instalação RHEL por omissão, o journal é guardado em /run/log/journal, em memória, e desaparece depois de um reboot. É exatamente o momento em que mais precisa dele. Para o manter em disco, crie um drop-in e reinicie o journald:
mkdir -p /etc/systemd/journald.conf.d
vi /etc/systemd/journald.conf.d/persistent.conf
[Journal]
Storage=persistent
SystemMaxUse=2G
systemctl restart systemd-journald
journalctl --flush
ls -ld /var/log/journal
journalctl --disk-usage
O SystemMaxUse limita o espaço que o journal pode usar. Escolha um valor adequado ao disco. Depois do reboot seguinte, journalctl --list-boots mostra mais do que uma entrada e journalctl -b -1 funciona.
/var/log/messages: o log geral do sistema
Este é o ficheiro que apanha tudo: arranques e paragens de serviços, mensagens do kernel, avisos de hardware e drivers, alterações de rede e tudo o resto registado ao nível info ou acima que não pertença às categorias de mail, autenticação ou cron. É o equivalente em texto de uma grande parte do journal, e é conveniente para grep e para ferramentas que esperam ficheiros simples.
tail -f /var/log/messages
grep -iE "error|fail|oom" /var/log/messages | tail -50
grep -i "out of memory" /var/log/messages
Uma linha como Out of memory: Killed process significa que o kernel terminou um processo porque o servidor ficou sem RAM. A resposta é dar mais memória à carga de trabalho ou reduzir o que ela usa (menos workers de PHP-FPM ou de base de dados, uma cache, corrigir uma fuga), não esconder o sintoma.
/var/log/secure: o log de segurança do Linux para autenticação e privilégios
Todos os logins SSH, todas as palavras-passe falhadas, todos os sudo e su, e as mensagens do PAM acabam aqui. Em RHEL, Oracle Linux, AlmaLinux e Rocky Linux este é o ficheiro a vigiar para o acesso ao servidor.
# failed SSH passwords and the addresses they came from
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
# successful logins
grep "Accepted" /var/log/secure
# who used sudo, and for what
grep "COMMAND=" /var/log/secure
Duas ferramentas relacionadas completam o quadro. O last lista os logins bem-sucedidos a partir de /var/log/wtmp, e o lastb lista os falhados a partir de /var/log/btmp. Se as contas bloqueiam depois de tentativas falhadas, faillock --user alice mostra as tentativas e faillock --user alice --reset limpa-as.
/var/log/audit/audit.log: o rasto de auditoria
O sistema de audit do Linux regista eventos relevantes para a segurança ao nível do kernel: logins, alterações de privilégios, decisões do SELinux e qualquer ficheiro ou chamada de sistema que escolha vigiar. É escrito pelo auditd e lido com ausearch e aureport em vez de grep, porque essas ferramentas compreendem o seu formato.
# summary of everything in the log
aureport --summary
# failed logins
aureport --login --failed
# authentication attempts
aureport -au
# today's events, with numeric IDs turned into names
ausearch -ts today -i
# failed login events only
ausearch -m USER_LOGIN -sv no -i
Vigie os ficheiros que importam
As regras de audit permitem registar todas as alterações a um ficheiro sensível. Coloque-as num ficheiro sob /etc/audit/rules.d/, por exemplo /etc/audit/rules.d/50-watch.rules:
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
augenrules --load
auditctl -l
ausearch -k sshd_config -i
O último comando mostra quem alterou a configuração do SSH, quando, e com que programa.
Negações do SELinux
O RHEL corre com o SELinux em enforcing, e assim deve ficar. Quando o SELinux bloqueia algo, a negação é registada como um registo AVC no log de audit. Olhe para aí antes de mudar o que quer que seja:
getenforce
ausearch -m AVC,USER_AVC -ts recent -i
ausearch -m AVC -ts today | audit2why
Para uma explicação em linguagem simples com correções sugeridas, instale o setroubleshoot e corra o sealert sobre o log:
dnf install setroubleshoot-server
sealert -a /var/log/audit/audit.log
A maioria das negações tem uma causa simples: um ficheiro com a etiqueta errada (corrija com restorecon -Rv <path>), conteúdo colocado num diretório fora do padrão (etiquete-o com semanage fcontext), ou uma funcionalidade que precisa de um boolean ativo (getsebool -a | grep httpd, depois setsebool -P). Esgote estas hipóteses antes de considerar um policy module à medida.
/var/log/cron: tarefas agendadas
Todas as tarefas iniciadas pelo crond e pelo anacron ficam registadas aqui, com o utilizador e o comando. Quando um backup ou um relatório «não correu», este ficheiro diz se chegou sequer a ser iniciado.
grep CROND /var/log/cron | tail -20
grep "(root) CMD" /var/log/cron | tail -20
Muitas tarefas de manutenção do RHEL correm agora como systemd timers em vez de cron jobs. Liste-os com systemctl list-timers e leia a sua saída com journalctl -u <name>.service, por exemplo journalctl -u logrotate.service.
/var/log/maillog: entrega de correio
O Postfix e outro software de correio registam aqui todas as mensagens que aceitam, reencaminham, adiam ou devolvem. Se uma aplicação web diz que enviou um e-mail e ninguém o recebeu, a resposta está normalmente neste ficheiro.
# the full path of one message, by recipient
grep "user@example.org" /var/log/maillog
# bounces and deferrals
grep -E "status=(bounced|deferred)" /var/log/maillog | tail -20
# what is still waiting in the queue
postqueue -p
Cada mensagem do Postfix tem um queue ID (por exemplo 4F2A81C0B3E). Faça grep por esse ID para ver cada passo da sua entrega, incluindo a resposta do servidor recetor.
/var/log/dnf.log e dnf history: o que mudou
Quando algo se avaria depois de uma manutenção, a primeira pergunta é o que mudou. Em RHEL 9 e 10 as operações de pacotes são tratadas pelo dnf, que escreve /var/log/dnf.log (a própria execução do dnf), /var/log/dnf.rpm.log (cada pacote instalado, atualizado ou removido) e /var/log/dnf.librepo.log (transferências dos repositórios). A vista mais rápida é a base de dados de histórico:
# every transaction, newest first
dnf history
# exactly what one transaction did
dnf history info last
dnf history info 42
# every transaction that touched a package
dnf history list nginx
# packages changed recently, from the log file
grep -E "Install|Upgrade|Erase" /var/log/dnf.rpm.log | tail -30
# does anything need a restart after updates (dnf-plugins-core)
dnf needs-restarting -r
Se uma atualização tiver de ser revertida, dnf history undo <id> anula uma única transação, desde que os pacotes mais antigos ainda estejam disponíveis nos repositórios.
/var/log/boot.log e o journal do arranque
O /var/log/boot.log guarda as mensagens de estado do arranque que veria na consola. É útil para uma vista rápida, mas o registo completo de um arranque está no journal:
cat /var/log/boot.log
journalctl -b -p err
journalctl -b -1 -p err # previous boot, needs the persistent journal
systemctl --failed # units that did not start
systemd-analyze blame | head # what took longest
Logs do servidor web e do PHP
Cada servidor web mantém os seus próprios access e error logs:
- nginx:
/var/log/nginx/access.loge/var/log/nginx/error.log, mais quaisquer ficheiros por site que defina comaccess_logeerror_log. - Apache httpd:
/var/log/httpd/access_log,/var/log/httpd/error_log, essl_access_logessl_error_logquando o mod_ssl está instalado. - PHP-FPM:
/var/log/php-fpm/error.logpara o master do FPM e/var/log/php-fpm/www-error.logpara erros de PHP do pool por omissão. O pool pode também escrever um slow log com um stack trace de cada pedido lento assim querequest_slowlog_timeoutestiver definido.
# top client addresses (default nginx log format)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# count of server errors (5xx) by URL
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# the latest errors
tail -50 /var/log/nginx/error.log
tail -50 /var/log/php-fpm/www-error.log
Uma rajada de respostas 502 ou 504 no access log, acompanhada de «upstream timed out» ou «connect() failed» no error log do nginx, aponta para o PHP-FPM: ou todos os workers estavam ocupados ou um script correu demasiado tempo.
Logs de bases de dados
- MariaDB (a base de dados dos repositórios RHEL):
/var/log/mariadb/mariadb.log, definido porlog-errorem/etc/my.cnf.d/mariadb-server.cnf. - MySQL dos repositórios RHEL:
/var/log/mysql/mysqld.log. - PostgreSQL:
/var/lib/pgsql/data/log/, um ficheiro por dia da semana por omissão.
O error log mostra problemas de arranque, crashes, tabelas corrompidas e erros de replicação. Para o desempenho, ative o slow query log. Para MariaDB, acrescente à secção [mysqld] de /etc/my.cnf.d/mariadb-server.cnf e reinicie:
slow_query_log = 1
slow_query_log_file = /var/log/mariadb/mariadb-slow.log
long_query_time = 1
Depois resuma-o com mysqldumpslow -s t /var/log/mariadb/mariadb-slow.log | head -40 para ver que queries custam mais tempo no total.
Manter os logs sob controlo com o logrotate
O RHEL roda os ficheiros de log com o logrotate, executado uma vez por dia por um systemd timer (logrotate.timer). As predefinições globais estão em /etc/logrotate.conf (semanal, quatro rotações, nomes de ficheiro com data como messages-20261018), e cada pacote acrescenta as suas próprias regras sob /etc/logrotate.d/. Os ficheiros do sistema (messages, secure, cron, maillog) são cobertos por /etc/logrotate.d/rsyslog.
systemctl list-timers logrotate.timer
cat /etc/logrotate.d/nginx
# dry run: show what would happen, change nothing
logrotate -d /etc/logrotate.d/nginx
# force a rotation now, verbosely
logrotate -vf /etc/logrotate.d/nginx
Para a sua própria aplicação, acrescente um ficheiro como /etc/logrotate.d/myapp:
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myapp myapp
postrotate
/usr/bin/systemctl reload myapp.service >/dev/null 2>&1 || true
endscript
}
Mantenha os logs das aplicações sob /var/log: os ficheiros aí recebem a etiqueta SELinux que o logrotate está autorizado a gerir. Se o diretório dos logs for gravável por um utilizador que não o root, acrescente uma linha su myapp myapp para que o logrotate o possa rodar em segurança.
O journal roda-se a si próprio dentro do limite SystemMaxUse. Para o aparar à mão, use journalctl --vacuum-time=30d ou journalctl --vacuum-size=1G.
Centralizar os logs com rsyslog
Os logs que vivem apenas no servidor que descrevem têm duas fraquezas: tem de iniciar sessão em cada máquina para os ler, e um atacante que obtenha root pode editá-los. Reencaminhar os logs de todos os servidores para um coletor central resolve as duas, e permite pesquisar num único sítio durante um incidente. O coletor pode ser outro servidor RHEL a correr rsyslog, ou uma plataforma de logs como o Graylog.
No coletor
Crie /etc/rsyslog.d/10-collector.conf. Escuta na porta TCP 20514, que a política SELinux já etiqueta como porta de syslog (verifique com semanage port -l | grep syslogd), e escreve um ficheiro por host e programa:
module(load="imtcp")
template(name="RemotePerHost" type="string"
string="/var/log/remote/%HOSTNAME:::secpath-replace%/%PROGRAMNAME:::secpath-replace%.log")
ruleset(name="remote") {
action(type="omfile" dynaFile="RemotePerHost")
}
input(type="imtcp" port="20514" ruleset="remote")
Abra a porta apenas para os seus servidores, aqui através da zona internal do firewalld, e depois valide e reinicie:
firewall-cmd --permanent --zone=internal --add-source=10.0.10.0/24
firewall-cmd --permanent --zone=internal --add-port=20514/tcp
firewall-cmd --reload
rsyslogd -N1
systemctl restart rsyslog
ss -tlnp | grep 20514
Se escolher uma porta que ainda não esteja etiquetada, acrescente-a primeiro com semanage port -a -t syslogd_port_t -p tcp <port>, no coletor e nos emissores. Acrescente uma regra de logrotate para /var/log/remote//.log como mostrado acima.
Em cada servidor
Crie /etc/rsyslog.d/90-central.conf. TCP com uma fila assistida por disco significa que um reinício do coletor ou uma interrupção de rede atrasa as mensagens em vez de as perder:
*.* action(type="omfwd" target="logs.example.net" port="20514" protocol="tcp"
template="RSYSLOG_SyslogProtocol23Format"
queue.type="LinkedList" queue.filename="fwd_central"
queue.maxDiskSpace="1g" queue.saveOnShutdown="on"
action.resumeRetryCount="-1")
rsyslogd -N1
systemctl restart rsyslog
Para enviar também os eventos de audit, defina active = yes em /etc/audit/plugins.d/syslog.conf e reinicie o auditd com service auditd restart (o auditd não aceita um reinício através do systemctl).
Prove que chega
Envie uma mensagem de teste e encontre-a no coletor:
# on the server
logger -t logtest "central logging test from $(hostname)"
# on the collector
tail /var/log/remote/*/logtest.log
Repita o teste depois de cada alteração ao coletor ou à firewall, e alerte sobre o silêncio: um servidor que deixou de enviar logs é fácil de não notar, porque nada nos logs lho diz.
Uma lista de verificação diária rápida
journalctl -p err -b: algo de novo ao nível de erro desde o arranque?aureport --login --failedelastb | head: logins falhados fora do habitual?ausearch -m AVC -ts today: negações do SELinux?dnf history: mudou alguma coisa que não tinha planeado?tail /var/log/nginx/error.loge o error log da base de dados: problemas na aplicação?journalctl --disk-usageedf -h /var/log: espaço para continuar a registar?
Ler isto demora alguns minutos. Automatizá-lo, através de um coletor central e de alertas sobre os padrões que importam, é o que transforma os logs de um arquivo num aviso antecipado.
Os engenheiros da EuroVPS constroem, operam e vigiam pipelines de logs como esta para clientes nos nossos managed servers.
Do arquivo do blog da EuroVPS, publicado pela primeira vez em 19 de abril de 2020.
Todas as notas de campo