0Pricing
Linux Command Line & Bash Scripting Mastery · Aula

Análise de registros da Web e de aplicações em grande escala

Extraia códigos de status, latências e campos de clientes de registros de acesso usando grep, cut e awk.

Análise de registros da Web e de aplicações em grande escala é uma aula grátis de Linux Command Line & Bash Scripting Mastery no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Linux Command Line & Bash Scripting Mastery, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Linux Command Line & Bash Scripting Mastery inclui 4 aulas no total.

O que é um registro de acesso à web?

Todo servidor HTTP — Apache, Nginx, Caddy — grava uma linha em um registro de acesso para cada solicitação. Entender a estrutura dessas linhas é a base de todo trabalho de análise de registros.

Uma linha típica do Formato de Registro Combinado (CLF) tem esta aparência:

  • IP do cliente — quem fez a solicitação
  • Carimbo de data e hora — quando isso aconteceu
  • Linha da solicitação — método, caminho e protocolo
  • Código de status — resposta HTTP (200, 404, 500…)
  • Bytes enviados — tamanho do corpo da resposta
  • Referenciador — página de origem
  • Agente do usuário — texto que identifica o navegador ou bot

Exemplo de linha de /var/log/nginx/access.log:

192.168.1.10 - alice [11/Jun/2026:14:32:01 +0000] "GET /api/orders HTTP/1.1" 200 1482 "-" "curl/7.88.1"

Em grande escala, esses arquivos chegam a milhões de linhas por dia. O objetivo desta lição é extrair, filtrar e agregar campos deles com eficiência usando ferramentas padrão do BASH.

Amostrando um registro ativo com tail e grep

Antes de escrever qualquer cadeia de processamento, examine o registro para entender seu formato. tail permite acompanhar um fluxo ativo; grep o restringe imediatamente às linhas relevantes.

Padrões comuns:

  • tail -n 1000 access.log — últimas 1000 linhas
  • tail -f access.log — acompanhar em tempo real
  • tail -f access.log | grep '" 5' — apenas erros 5xx à medida que chegam

A principal ideia é que grep compara com a linha inteira, portanto é importante fixar corretamente o padrão. Comparar ' 500 ' (com espaços) evita que você corresponda acidentalmente a um caminho de URL que contenha a sequência 500.

#!/usr/bin/env bash
# Watch only HTTP 5xx errors arriving in real time
tail -f /var/log/nginx/access.log \
  | grep --line-buffered '" 5[0-9][0-9] '

Extraindo o código de status com cut

cut divide cada linha usando um delimitador e exibe os campos selecionados. No Formato de Registro Combinado, o código de status fica no campo 9 quando a divisão é feita nos espaços — mas as aspas ao redor da linha da solicitação fazem com que seja mais seguro contar a partir de uma referência conhecida.

Um truque confiável: como a linha da solicitação está sempre entre aspas, o código de status é sempre o primeiro item depois das aspas de fechamento do campo da solicitação. Usar cut -d'"' -f3 isola tudo depois das aspas da solicitação; em seguida, um segundo cut -d' ' -f2 seleciona o código de status.

Esse uso do cut em duas etapas é um padrão clássico para registros CLF — rápido e sem dependências externas.

#!/usr/bin/env bash
# Print only the HTTP status code from each log line
# Input format: ... "GET /path HTTP/1.1" 200 1482 ...
cut -d'"' -f3 /var/log/nginx/access.log \
  | cut -d' ' -f2 \
  | sort \
  | uniq -c \
  | sort -rn

Contando códigos de status com awk

awk é mais poderoso que cut porque pode acumular estado entre as linhas. O padrão idiomático para contar ocorrências é usar uma matriz associativa indexada pelo valor que você deseja analisar.

No CLF, o campo $9 (indexado a partir de 1 e delimitado por espaços) contém o código de status. awk processa cada linha, incrementa um contador e depois exibe um resumo ordenado no bloco END.

Por que preferir awk a cut | sort | uniq -c? Porque awk faz isso em uma única passagem, sem ordenar primeiro o arquivo inteiro — algo essencial quando o registro tem centenas de gigabytes.

#!/usr/bin/env bash
# Count HTTP status codes in a single awk pass
awk '{ count[$9]++ }
END {
  for (status in count)
    printf "%6d  %s\n", count[status], status
}' /var/log/nginx/access.log \
  | sort -rn

Filtrando erros e extraindo IPs de clientes

Uma das tarefas operacionais mais comuns é descobrir quais IPs de clientes estão gerando mais erros. Isso combina filtragem (apenas linhas de erro) com extração de campos (o IP no campo 1).

A estratégia da cadeia de processamento:

  • Use awk para filtrar pelo intervalo do código de status e extrair o IP em uma única etapa — evite uma passagem separada com grep
  • Encadeie com sort | uniq -c | sort -rn | head para obter rapidamente uma visão dos N primeiros

Esse padrão é rápido o suficiente para ser executado em um arquivo de registro de 10 GB em um único servidor, sem carregar o arquivo na memória.

#!/usr/bin/env bash
# Top 10 IPs generating HTTP 4xx or 5xx errors
awk '$9 ~ /^[45][0-9][0-9]$/ { print $1 }' \
    /var/log/nginx/access.log \
  | sort \
  | uniq -c \
  | sort -rn \
  | head -10

Analisando a latência das respostas nos registros da aplicação

Servidores de aplicações (Rails, Gunicorn, Express com morgan etc.) costumam registrar a duração das solicitações. O Nginx pode ser configurado para emitir $request_time como um campo adicional no fim de cada linha.

Exemplo de formato de registro personalizado do Nginx em nginx.conf:

log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt=$request_time';

Quando a latência estiver no registro, você poderá usar awk para calcular a média, o máximo e aproximações de percentis em milhões de solicitações, sem carregar os dados em um banco de dados.

#!/usr/bin/env bash
# Compute average and max request_time from Nginx timed log
# Assumes last field is rt=<seconds> e.g. rt=0.042
awk '{
  # Extract numeric value after rt=
  n = split($NF, a, "=")
  if (n == 2 && a[1] == "rt") {
    t = a[2] + 0
    sum += t
    count++
    if (t > max) max = t
  }
}
END {
  if (count > 0)
    printf "Requests: %d  Avg: %.4fs  Max: %.4fs\n", count, sum/count, max
}' /var/log/nginx/timed_access.log

Criando um histograma de latência com awk

Uma única média oculta a latência da cauda. Um histograma revela a distribuição — mostra se a maioria das solicitações é rápida e algumas são muito lentas (cauda longa) ou se a distribuição é uniforme.

O truque é agrupar cada valor em um intervalo arredondado usando aritmética inteira dentro do awk. Multiplicar por 1000 (convertendo segundos em milissegundos) e depois usar a divisão inteira produz limites de intervalo bem definidos.

Isso produz um histograma textual que você pode ler diretamente em um terminal, o que costuma ser mais rápido do que enviar dados ao Grafana para uma investigação rápida.

#!/usr/bin/env bash
# Latency histogram (50ms buckets) from Nginx timed log
awk '{
  n = split($NF, a, "=")
  if (n == 2 && a[1] == "rt") {
    ms = int(a[2] * 1000)      # convert to ms
    bucket = int(ms / 50) * 50 # round down to 50ms boundary
    hist[bucket]++
  }
}
END {
  for (b in hist)
    printf "%6dms  %d\n", b, hist[b]
}' /var/log/nginx/timed_access.log \
  | sort -n

Extraindo o agente do usuário e detectando bots

O campo do agente do usuário (campo 6 ao dividir em ") identifica os clientes. Rastreadores, coletores e bots mal-intencionados costumam poluir suas métricas e inflar as contagens de erros. Filtrá-los resulta em uma visão mais clara do tráfego de usuários reais.

Assinaturas comuns de bots: bot, crawler, spider, curl, python-requests, Googlebot, Bingbot.

Use grep -iv (inversão sem distinção entre maiúsculas e minúsculas) para excluir bots conhecidos ou use awk para dividir em " e comparar diretamente o campo UA.

#!/usr/bin/env bash
# Count top 15 User-Agent strings, excluding known bots
awk -F'"' '{ print $6 }' /var/log/nginx/access.log \
  | grep -iv -e 'bot' -e 'crawler' -e 'spider' -e 'curl' \
              -e 'python' -e 'wget' -e 'Go-http-client' \
  | sort \
  | uniq -c \
  | sort -rn \
  | head -15

Agregando tráfego por endpoint

Saber quais endpoints recebem mais tráfego — e geram mais erros — ajuda a priorizar a otimização e o planejamento de capacidade. O caminho da solicitação fica dentro do campo entre aspas.

Divida em ", use o campo 2 (a linha da solicitação) e depois remova o método e o protocolo para isolar o caminho. Para APIs com parâmetros no caminho, como /users/12345, talvez você também queira normalizar os IDs para /users/:id usando sed ou um padrão mais complexo de awk.

#!/usr/bin/env bash
# Top 20 requested endpoints (method + path, no query string)
awk -F'"' '{ print $2 }' /var/log/nginx/access.log \
  | awk '{ print $1, $2 }' \
  | sed 's|/[0-9][0-9]*\b|/:id|g' \
  | sort \
  | uniq -c \
  | sort -rn \
  | head -20

Correlacionando erros com endpoints usando awk

A análise de passagem única mais poderosa combina vários campos ao mesmo tempo: endpoint, código de status e, opcionalmente, latência. Matrizes associativas de awk indexadas por valores compostos tornam isso simples e rápido.

O padrão abaixo conta erros 5xx por endpoint em uma única passagem — sem arquivos temporários e sem ordenações intermediárias até o final. Essa é a abordagem usada em scripts de observabilidade de produção quando você precisa de respostas em menos de um minuto sobre um registro grande.

#!/usr/bin/env bash
# Count 5xx errors per endpoint path in a single pass
awk -F'"' '{
  # $2 = request line e.g. "GET /api/orders HTTP/1.1"
  # $0 in original space-split: $9 = status
  split($0, fields, " ")
  status = fields[9]
  if (status ~ /^5/) {
    split($2, req, " ")
    path = req[2]
    # Normalise numeric IDs
    gsub(/\/[0-9]+/, "/:id", path)
    errors[path]++
  }
}
END {
  for (p in errors)
    printf "%6d  %s\n", errors[p], p
}' /var/log/nginx/access.log \
  | sort -rn \
  | head -20

Processando registros rotacionados e compactados

Na maioria dos servidores, os registros são rotacionados diariamente. Os arquivos mais antigos são compactados com gzip como access.log.1.gz, access.log.2.gz etc. As ferramentas padrão não conseguem lê-los diretamente, mas duas abordagens funcionam bem:

  • zcat — descompacta para a saída padrão e envia para sua cadeia de processamento
  • zgrep — executa grep diretamente dentro dos arquivos gzip, sem extraí-los

Para analisar uma semana inteira de registros que inclua arquivos descompactados e compactados, use a substituição de processo ou concatene com zcat. O trecho abaixo processa os últimos 7 arquivos rotacionados e o registro ativo atual em uma única invocação de awk — não são necessários arquivos temporários.

#!/usr/bin/env bash
# Aggregate status codes across a week of rotated logs
# Handles both plain and gzip-compressed rotation files

LOG_DIR="/var/log/nginx"

{
  cat  "${LOG_DIR}/access.log" 2>/dev/null
  zcat "${LOG_DIR}/access.log".*.gz 2>/dev/null
} | awk '
{ count[$9]++ }
END {
  for (s in count)
    printf "%6d  %s\n", count[s], s
}' | sort -rn

Qual campo do awk contém o código de status HTTP no Formato de Registro Combinado?

Você está escrevendo uma linha única de awk para filtrar apenas respostas HTTP 4xx de um registro de acesso padrão do Nginx no Combined Log Format (delimitado por espaços, com a linha de requisição entre aspas). Qual número de campo identifica corretamente o código de status HTTP?

Resumo da lição: pipelines de análise de registros

Nesta lição, você construiu um conjunto completo de ferramentas para analisar registros da Web e de aplicações em grande escala usando apenas utilitários padrão do BASH.

Principais técnicas abordadas:

  • Estrutura em primeiro lugar — o Combined Log Format tem uma disposição previsível dos campos; conhecê-la permite dividi-lo de forma confiável com cut -d'"' ou referências a campos do awk.
  • Extração do código de status — awk '{ count[$9]++ }' conta todos os códigos em uma única passagem; filtre com $9 ~ /^5/ para encontrar erros do servidor.
  • Análise de latência — analise o campo personalizado rt= com awk para calcular médias, valores máximos e intervalos de histogramas sem nenhuma ferramenta externa.
  • Análise de clientes e robôs — divida em " com -F'"' para acessar o campo User-Agent; use um pipeline com grep -iv para excluir robôs antes de agregar os dados.
  • Normalização de endpoints — use gsub(/\/[0-9]+/, "/:id") dentro do awk para agrupar caminhos parametrizados antes da contagem.
  • Registros rotacionados — combine cat e zcat em um subshell para enviar todos os arquivos de rotação em uma única passagem pelo pipeline.

Esses padrões podem ser combinados: você pode encadear filtragem, extração, normalização e agregação em um único pipeline que processa centenas de milhões de linhas em hardware comum. Domine essas primitivas e raramente precisará de um serviço dedicado de agregação de registros para investigar incidentes pontuais.

Perguntas Frequentes

A aula “Análise de registros da Web e de aplicações em grande escala” é grátis?

Sim — o texto completo de “Análise de registros da Web e de aplicações em grande escala” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Linux Command Line & Bash Scripting Mastery, atualize para CoddyKit PRO. O curso de Linux Command Line & Bash Scripting Mastery inclui 4 aulas no total.

O que vou aprender em “Análise de registros da Web e de aplicações em grande escala”?

Extraia códigos de status, latências e campos de clientes de registros de acesso usando grep, cut e awk. Você pratica Linux Command Line & Bash Scripting Mastery com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Linux Command Line & Bash Scripting Mastery?

Nenhuma experiência prévia é necessária. Linux Command Line & Bash Scripting Mastery no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Análise de registros da Web e de aplicações em grande escala”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Linux Command Line & Bash Scripting Mastery?

Sim. Cada aula de Linux Command Line & Bash Scripting Mastery inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Análise de registros da Web e de aplicações em grande escala
  2. Acompanhamento de registros em tempo real e alertas por transmissão
  3. Consulta ao journald com journalctl em scripts
  4. Cálculo de métricas e histogramas a partir de fluxos de registros
← Voltar para Linux Command Line & Bash Scripting Mastery