Comando tail (e head): ler e seguir logs no Linux

Terminal Linux a executar tail -f sobre um log de autenticação, com tentativas de login falhadas a chegar em tempo real

Um log num servidor em produção cresce ao segundo — e quase tudo o que interessa está numa das pontas: as últimas linhas dizem o que está a acontecer agora, as primeiras dizem quando tudo começou. É exatamente para isso que existem o tail e o head: ler o fim e o princípio de um ficheiro sem o despejar inteiro no terminal.

Neste artigo da série sobre comandos Linux, tratamos os dois em conjunto — porque são simétricos e porque, na prática, se usam lado a lado. Vamos das opções básicas ao tail -f, a ferramenta clássica de vigilância de logs em tempo real, e terminamos num simulador interativo onde pode acompanhar, ao vivo, a triagem de um ataque de força bruta a SSH.

O que fazem o tail e o head

Ambos leem ficheiros (ou o standard input) e escrevem uma parte deles no standard output: o head mostra o princípio, o tail mostra o fim. Sem opções, cada um imprime 10 linhas. Parece pouco, mas é a quantidade certa para responder à pergunta mais frequente de quem administra sistemas: «o que é que este serviço registou por último?»

tail [OPÇÕES] [FICHEIRO...]
head [OPÇÕES] [FICHEIRO...]

tail /var/log/auth.log       # últimas 10 linhas
head /var/log/auth.log       # primeiras 10 linhas
tail -n 50 servidor.log      # últimas 50 linhas
tail -f /var/log/auth.log    # segue o ficheiro ao vivo (Ctrl+C para sair)

Note que, em muitos sistemas, ler logs como o auth.log exige privilégios: o ficheiro pertence normalmente ao grupo adm, pelo que precisará de sudo ou de pertencer a esse grupo — um bom exemplo de privilégio mínimo aplicado aos próprios registos do sistema.

As opções que interessam

Escolher a janela de leitura

  • -n N — define quantas linhas mostrar. tail -n 50 imprime as últimas 50; head -n 5, as primeiras 5. A forma abreviada histórica (tail -50) ainda funciona, mas -n é a forma portável e legível.
  • -n +N (só no tail) — o sinal + muda o significado: em vez de «as últimas N», passa a «a partir da linha N até ao fim». tail -n +2 é o idioma clássico para saltar a linha de cabeçalho de um CSV.
  • head -n -N — com sinal negativo, o head mostra tudo menos as últimas N linhas: o inverso exato do anterior.
  • -c N — trabalha em bytes em vez de linhas. head -c 512 ficheiro é uma forma prudente de espreitar um ficheiro desconhecido sem arriscar despejar megabytes de binário no terminal.

Seguir um ficheiro ao vivo: -f e -F

O tail -f não termina quando chega ao fim do ficheiro: fica à espera e imprime cada linha nova no momento em que é escrita. É a forma mais direta de observar um serviço a funcionar — ou um ataque a decorrer. Há, porém, uma armadilha importante: o -f segue o descritor do ficheiro aberto. Quando o logrotate renomeia o auth.log para auth.log.1 e cria um ficheiro novo, o tail -f continua agarrado ao antigo — e emudece sem qualquer aviso.

tail -f /var/log/auth.log     # segue o descritor: morre em silêncio na rotação
tail -F /var/log/auth.log     # segue o NOME: reabre o ficheiro quando ele é substituído
tail -f --pid=1234 app.log    # termina sozinho quando o processo 1234 acabar

O -F equivale a --follow=name --retry: vigia o nome do ficheiro e, quando este desaparece e reaparece, reabre-o e continua. Para monitorização contínua, a escolha certa é quase sempre -F. Complementos úteis: -s N ajusta o intervalo de sondagem em segundos e --pid encerra o tail quando um processo associado termina. Se quiser o melhor dos dois mundos — seguir ao vivo e poder parar para navegar no histórico — experimente less +F; e para os serviços que registam no journal do systemd, o equivalente é journalctl -f.

Vários ficheiros e pipes

  • Com vários ficheiros, ambos os comandos imprimem cabeçalhos ==> nome <== antes de cada bloco. -q suprime-os (importante em scripts) e -v força-os mesmo com um único ficheiro.
  • O par natural do tail -f é o grep: tail -F log | grep padrão transforma um rio de linhas num alerta focado.
  • Num pipe com mais estágios, use grep --line-buffered: sem isso, o grep acumula output em buffer e as linhas «ao vivo» chegam em blocos atrasados.
$ tail -F /var/log/auth.log | grep --line-buffered "Failed password"
Jul 28 11:57:12 srv01 sshd[2633]: Failed password for root from 203.0.113.45 port 54104 ssh2
Jul 28 11:57:19 srv01 sshd[2637]: Failed password for invalid user admin from 203.0.113.45 port 54121 ssh2

tail e head em cibersegurança

Deteção de força bruta em tempo real. Um ataque de password guessing a SSH deixa um rasto inconfundível no auth.log: sequências de Failed password e Invalid user vindas do mesmo endereço, com segundos de intervalo. tail -F auth.log | grep "Failed password" mostra a cadência do ataque no momento em que acontece — e filtrar pelo IP suspeito isola a atividade de um único atacante no meio do tráfego legítimo.

Resposta a incidentes. Durante a contenção de um incidente, é comum manter um terminal com tail -F sobre os logs críticos enquanto se atua noutro: cada ação do atacante — nova tentativa, nova sessão, novo erro — aparece de imediato. O fluxo em direto orienta as decisões: bloquear o IP na firewall, desativar uma conta, isolar a máquina.

Recolha de evidência. Para o relatório, tail -n 50 extrai as últimas linhas como registo do estado final, e head documenta o início do ficheiro — desde quando há registos e como era a atividade normal antes do ataque. Em ficheiros de origem desconhecida, head -c permite uma amostragem controlada sem executar nem despejar o conteúdo completo.

Monitorização que sobrevive à rotação. Muitos pipelines caseiros de alerta morrem em silêncio na primeira rotação de logs porque usam -f em vez de -F. É um erro com consequências de segurança reais: a vigilância pára precisamente sem avisar. Os coletores de logs profissionais resolvem este problema da mesma forma — seguindo o nome e o inode do ficheiro — e o tail -F é a versão de bolso desse mecanismo.

Experimente no simulador interativo

No simulador abaixo, o painel esquerdo mostra um auth.log fictício a crescer ao vivo — com um ataque de força bruta a decorrer — e o terminal executa o tail e o head sobre ele. Use Demonstrar tudo para seguir a triagem guiada completa do ataque, avance com Anterior/Seguinte, ou combine livremente as opções: -n, -n +10, -f, -F, o pipe com grep e a simulação de logrotate que mostra, lado a lado, porque é que o -f emudece e o -F sobrevive.

Erros comuns e boas práticas

  • Usar -f onde devia estar -F: em qualquer vigilância que dure mais do que alguns minutos, a rotação de logs vai acontecer — e o -f morre em silêncio. Reserve o -f para sessões curtas e interativas.
  • Esquecer o buffering do pipe: se o tail -f | grep alimenta mais um estágio, as linhas podem ficar retidas. grep --line-buffered (ou stdbuf -oL) resolve.
  • Confundir -n N com -n +N: tail -n 10 são as últimas 10 linhas; tail -n +10 começa na linha 10 e vai até ao fim. Para saltar só o cabeçalho, é -n +2 — não -n +1.
  • Contar com as 10 linhas por omissão: em logs movimentados, 10 linhas são segundos de história. Diga explicitamente quantas quer com -n.
  • Cabeçalhos inesperados em scripts: ao processar vários ficheiros, os ==> nome <== entram no output e partem o parsing. Use -q.
  • Despejar binários: antes de aplicar tail ou head a um ficheiro desconhecido, confirme o tipo com file e prefira head -c para amostrar com segurança.

Conclusão

O tail e o head são a primeira e a última página de qualquer ficheiro — e o tail -F | grep é, ainda hoje, a forma mais rápida de pôr um par de olhos em cima de um log em produção. Dominar a diferença entre -f e -F, o significado do -n +N e o buffering dos pipes transforma estes dois comandos simples numa ferramenta séria de monitorização e resposta a incidentes. Se quer levar estas competências mais longe, a HJFR oferece formação prática em Linux e cibersegurança e serviços de consultoria: explore o nosso catálogo de serviços e reveja também outros artigos da série, como o do comando useradd.

Este artigo faz parte da série «Comandos Linux, um a um» do blog HJFR — fique atento aos próximos comandos.