Truques para filtrar e transformar logs com awk em tempo real
1. Fundamentos do awk para processamento de logs em tempo real
O awk é uma ferramenta de processamento de texto que opera no modelo padrão { ação }, onde o padrão define quais linhas processar e a ação determina o que fazer com elas. Em pipelines Unix, o awk brilha ao receber dados via pipe, permitindo filtragem e transformação contínua de logs.
Variáveis internas essenciais incluem:
- NF (Number of Fields): total de campos na linha atual
- NR (Number of Record): número da linha processada
- FS (Field Separator): separador de campos (padrão: espaço/tab)
- OFS (Output Field Separator): separador na saída
- $0: linha completa, $1, $2...$n: campos individuais
A diferença principal entre awk tradicional e GNU awk (gawk) está no suporte a funções como strftime(), arrays multidimensionais e expressões regulares estendidas, recursos cruciais para logs modernos.
2. Filtrando linhas de log por padrões específicos
Expressões regulares selecionam eventos críticos com precisão:
# Selecionar apenas erros fatais
tail -f /var/log/syslog | awk '/FATAL|CRITICAL/ { print }'
# Combinar padrões com operadores lógicos
awk '/ERROR/ && /database/ { print NR": "$0 }' /var/log/app.log
# Ignorar cabeçalhos e linhas vazias
tail -f access.log | awk 'NR > 1 && NF > 0 { print $0 }'
Para logs com múltiplos níveis de severidade:
# Filtrar warnings e erros, ignorando debug
journalctl -f | awk '$3 ~ /WARNING|ERROR/ && $0 !~ /DEBUG/ { print }'
3. Extração e formatação de campos em tempo real
Delimitadores personalizados são fundamentais para logs estruturados:
# Log CSV: timestamp,level,message,user
tail -f app.csv | awk -F',' '{ print $1, $3, $4 }'
# Reordenar colunas com OFS
awk -F':' '{ OFS=" | "; print $3, $1, $2 }' /var/log/auth.log
Concatenando campos para resumos compactos:
# Compactar log de acesso: IP + URL + status
tail -f access.log | awk '{ print $1 " -> " $7 " [" $9 "]" }'
4. Transformação de timestamps e dados numéricos
Convertendo timestamps Unix para formato legível:
# Log com timestamp Unix no campo 1
tail -f metrics.log | awk '{
$1 = strftime("%Y-%m-%d %H:%M:%S", $1)
print
}'
Cálculos aritméticos em campos numéricos:
# Calcular latência média a cada 10 requisições
tail -f latency.log | awk '{
soma += $2
count++
if (count % 10 == 0) {
printf "Média latência: %.2f ms\n", soma/count
}
}'
Arredondamento com printf():
# Formatar tempo de resposta com 2 casas decimais
awk '{ printf "%-15s %8.2f ms\n", $1, $3 }' response_times.log
5. Agregação e sumarização ao vivo com arrays associativos
Contagem de ocorrências por tipo:
# Contar erros por código HTTP em tempo real
tail -f access.log | awk '{
erros[$9]++
printf "\033[2J\033[H" # limpa terminal
for (cod in erros) print cod, erros[cod]
}'
Cálculo de métricas em fluxo contínuo:
# Média, máximo e mínimo de latência por IP
tail -f api.log | awk '{
ip = $1
lat = $5
soma[ip] += lat
count[ip]++
if (lat > max[ip]) max[ip] = lat
if (min[ip] == "" || lat < min[ip]) min[ip] = lat
printf "%s: média=%.1f max=%.1f min=%.1f\n", ip, soma[ip]/count[ip], max[ip], min[ip]
}'
6. Uso de awk em pipelines com comandos do sistema
Monitoramento contínuo com tail -f:
# Pipeline completo: filtrar, transformar e exibir
tail -f /var/log/nginx/access.log | \
grep -v "127.0.0.1" | \
awk '$9 ~ /5[0-9][0-9]/ { print strftime("%T"), $1, $7, $9 }'
Redirecionamento para arquivos rotativos:
# Salvar apenas erros 5xx em arquivo separado
tail -f access.log | awk '$9 ~ /5[0-9][0-9]/ { print > "errors_5xx.log"}'
Integração com watch e tee:
# Monitorar a cada 2 segundos com resumo
watch -n 2 'tail -100 access.log | awk '\''{stats[$9]++} END {for(s in stats) print s, stats[s]}'\'
7. Scripts awk reutilizáveis para logs comuns
Filtro para logs Apache
# apache_filter.awk
# Uso: tail -f access.log | awk -f apache_filter.awk
{
ip = $1
data = $4
url = $7
status = $9
tempo = $NF
# Remover colchetes da data
gsub(/\[|\]/, "", data)
if (status ~ /5[0-9][0-9]/) {
printf "ERRO %s | %s | %s | %s ms\n", status, ip, url, tempo
}
}
Parsing de syslog
# syslog_parser.awk
# Uso: tail -f /var/log/syslog | awk -f syslog_parser.awk
{
mes = $1
dia = $2
hora = $3
servico = $5
mensagem = $0
# Extrair facilidade e prioridade (formato: facility.priority)
if (servico ~ /.*\..*/) {
split(servico, partes, ".")
facilidade = partes[1]
prioridade = partes[2]
if (prioridade <= 3) # emerg, alert, crit, err
printf "CRITICO: %s %s %s\n", hora, servico, mensagem
}
}
Extração de journalctl
# Extrair campos específicos do journald
journalctl -f -o json | awk '{
# Para logs JSON, usar gawk com suporte JSON
# Exemplo simplificado para logs estruturados
if ($0 ~ /"_PID") {
gsub(/[{},"]/, "")
split($0, campos, " ")
for (i in campos) {
if (campos[i] ~ /MESSAGE=/) print campos[i]
}
}
}'
8. Otimização e boas práticas para logs de alto volume
Uso de next para pular linhas irrelevantes:
# Pular rapidamente linhas de debug e health checks
tail -f app.log | awk '{
if ($0 ~ /healthcheck|heartbeat/) next
if ($0 ~ /DEBUG/) next
if (NF < 5) next
# Processamento principal
print
}'
Limitação de memória com arrays associativos:
# Limitar array a 1000 entradas, descartando as mais antigas
awk '{
if (length(ips) >= 1000) {
delete ips[oldest_ip]
}
ips[$1]++
if (ips[$1] > max_count) {
max_count = ips[$1]
max_ip = $1
}
} END { print max_ip, max_count }' access.log
Evitando expansão desnecessária:
# Ineficiente: expande $0 para cada campo
awk '{ for (i=1; i<=NF; i++) if ($i ~ /ERROR/) print }'
# Eficiente: testa $0 uma vez
awk '/ERROR/ { for (i=1; i<=NF; i++) print $i }'
Para logs de alto volume, prefira:
- Usar -F em vez de definir FS dentro do script
- Evitar gsub() e split() em cada linha
- Utilizar printf() em vez de concatenação com print
- Processar em lotes com getline para reduzir chamadas de sistema
Referências
- GNU Awk User's Guide — Documentação oficial completa do GNU awk, incluindo funções de string, tempo e arrays associativos
- Awk One-Liners Explained — Coleção prática de one-liners awk com explicações detalhadas para processamento de texto e logs
- Linux awk Command Tutorial — Tutorial abrangente cobrindo desde fundamentos até exemplos avançados de filtragem e transformação
- Processing Log Files with awk — Guia específico para processamento de logs com awk, incluindo exemplos com Apache e syslog
- Awk in Real-Time Log Monitoring — Artigo técnico sobre uso de awk em pipelines de monitoramento contínuo de logs