Linux: Fase 3 Mini Projeto — Análise de Log do Servidor

O projeto de conclusão da Fase 3. Você vai combinar redirecionamento, pipes, grep, awk, sed, sort, uniq e todas as suas habilidades de processamento de dados para fazer uma análise completa dos logs de acesso do Nginx e gerar um relatório.

📋 Pré-requisitos: Você já deve conhecer

1. O Que Você Vai Aprender


2. O Site do Xiaoming Ficou Lento

(1) O Problema: O Chefe Pede Dados, Mas o Log de 10GB é Impossível de Navegar

O site do Xiaoming estava lento nos últimos tempos, e o chefe exigiu "me traga dados". O access.log do Nginx gera centenas de MB por dia — abrir é impossível, e procurar palavras-chave é como achar agulha no palheiro.

(2) Cadeia de Pipeline Para Análise

Xiaoming usou as habilidades da Fase 3, extraindo métricas-chave linha por linha com comandos de pipe:

BASH
# Top 10 IPs por número de acessos
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# Top 10 URLs mais requisitadas
cat access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -10

> 💡 Dica: O padrão de pipeline para análise de logs é fixo: `awk extrai campos → sort → uniq -c deduplica e conta → sort -rn ordena por contagem em ordem decrescente → head pega o Top N`. Decore esse modelo — qualquer análise Top N de logs pode usá-lo.

# Requisições por hora
cat access.log | awk -F: '{print $2":00"}' | sort | uniq -c | sort -rn

Saída:

TEXT
    210 192.168.1.100
    198 10.0.0.45
    195 192.168.1.200
    190 10.0.0.88
    180 172.16.0.50
    150 /index.html
    120 /api/users
    110 /api/login
    100 /about
     90 /contact
     85 10:00
     80 14:00
     75 09:00
     70 22:00
     65 18:00

(3) O Benefício: Relatório em 5 Minutos

Xiaoming juntou os resultados da análise em um relatório — tendências de acesso, top 10 requisições lentas, páginas com mais erros 404. O chefe disse: "Bom, vamos adicionar mais servidores."


3. Pontos-Chave

(1) Formato Padrão de Log do Nginx (combined)

TEXT

192.168.1.100 - - [07/Jul/2026:10:15:30 +0000] "GET /index.html HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
│              │ │ │                           │                           │    │    │
│              │ │ └─ User-Agent               │                           │    │    └─ Bytes da resposta
│              │ └───────────────────────────── Referer                    │    └────── Código de status
│              └─────────────────────────────────────────────────────────── Linha da requisição (método/URL/protocolo)
└─── IP do cliente                              Timestamp

ℹ️ Nota: No formato de log combined do Nginx, os campos são separados por espaço, mas alguns campos contêm espaços (por exemplo, a linha da requisição e o timestamp vêm entre colchetes e aspas). Quando o awk divide por espaço, $1 é o IP, $7 é a URL, $9 é o código de status, $10 são os bytes — essas posições são estáveis e podem ser extraídas diretamente pelo awk.

Posições dos campos (separados por espaço):

Campo Significado
$1 IP do cliente
$4 Início do timestamp [
$7 URL requisitada
$9 Código de status HTTP
$10 Bytes da resposta

(2) ▶ Exemplo: Gerar Logs de Amostra

Primeiro, gere um arquivo de log de amostra para análise:

TEXT
#!/bin/bash
# generate-sample-log.sh

IPS=("192.168.1.100" "10.0.0.45" "192.168.1.200" "10.0.0.88" "172.16.0.50")
URLS=("/index.html" "/api/users" "/api/login" "/about" "/contact" "/images/logo.png" "/api/orders" "/products" "/blog")
STATUSES=(200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 201 301 302 400 401 403 404 500 502 503)

rm -f /tmp/access.log

for i in {1..1000}; do
    IP=${IPS[$RANDOM % ${#IPS[@]}]}
    URL=${URLS[$RANDOM % ${#URLS[@]}]}
    STATUS=${STATUSES[$RANDOM % ${#STATUSES[@]}]}
    SIZE=$((RANDOM % 10000 + 100))
    HOUR=$((RANDOM % 24))
    MIN=$((RANDOM % 60))
    SEC=$((RANDOM % 60))
    echo "$IP - - [07/Jul/2026:$HOUR:$MIN:$SEC +0000] \"GET $URL HTTP/1.1\" $STATUS $SIZE \"-\" \"Mozilla/5.0\"" >> /tmp/access.log
done

echo "Generated 1000 sample log entries to /tmp/access.log"
BASH
chmod +x generate-sample-log.sh
./generate-sample-log.sh

Saída:

TEXT
Generated 1000 sample log entries to /tmp/access.log

(3) ▶ Exemplo: Estatísticas de Volume de Requisições

BASH
echo "=== Total Requests ==="
wc -l /tmp/access.log

echo ""
echo "=== Requests per IP ==="
cat /tmp/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

echo ""
echo "=== Request Method Distribution ==="
cat /tmp/access.log | awk '{print $6}' | tr -d '"' | sort | uniq -c | sort -rn

Saída:

TEXT
=== Total Requests ===
1000 /tmp/access.log

=== Requests per IP ===
    210 192.168.1.100
    198 10.0.0.45
    195 192.168.1.200
    190 10.0.0.88
    180 172.16.0.50

=== Request Method Distribution ===
   1000 GET

(4) ▶ Exemplo: Análise de Códigos de Status

BASH
echo "=== Status Code Distribution ==="
cat /tmp/access.log | awk '{print $9}' | sort | uniq -c | sort -rn

echo ""
echo "=== 4xx Errors (Client Errors) ==="
cat /tmp/access.log | awk '$9 ~ /^4/ {print $9, $7, $1}' | sort | uniq -c | sort -rn | head -10

echo ""
echo "=== 5xx Errors (Server Errors) ==="
cat /tmp/access.log | awk '$9 ~ /^5/ {print $9, $7, $1}' | sort | uniq -c | sort -rn | head -10

echo ""
echo "=== Error Rate ==="
TOTAL=$(wc -l < /tmp/access.log)
ERRORS=$(awk '$9 ~ /^[45]/ {count++} END {print count}' /tmp/access.log)
echo "Total requests: $TOTAL"
echo "Errors: $ERRORS"
echo "Error rate: $(echo "scale=2; $ERRORS * 100 / $TOTAL" | bc)%"

Saída:

TEXT
=== Status Code Distribution ===
    960 200
      5 201
      3 301
      2 302
      8 400
      2 401
      3 403
     10 404
      4 500
      2 502
      1 503

=== 4xx Errors (Client Errors) ===
   3 404 /api/login 192.168.1.100
   2 404 /about 10.0.0.45
   2 403 /api/admin 192.168.1.200

=== 5xx Errors (Server Errors) ===
   2 500 /api/data 10.0.0.88
   2 502 /api/users 172.16.0.50
   1 503 /api/health 192.168.1.100

=== Error Rate ===
Total requests: 1000
Errors: 32
Error rate: 3.20%

(5) ▶ Exemplo: Análise de URLs Mais Acessadas

BASH
echo "=== Most Popular URLs ==="
cat /tmp/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -10

echo ""
echo "=== URLs with Most 404s ==="
cat /tmp/access.log | awk '$9 == 404 {print $7}' | sort | uniq -c | sort -rn | head -10

echo ""
echo "=== URLs with Largest Response Size ==="
cat /tmp/access.log | awk '{print $10, $7}' | sort -rn | head -10

Saída:

TEXT
=== Most Popular URLs ===
    150 /index.html
    120 /api/users
    110 /api/login
    100 /about
     90 /contact

=== URLs with Most 404s ===
      5 /api/login
      3 /old-page
      2 /favicon.ico

=== URLs with Largest Response Size ===
10098 /images/logo.png
 9876 /api/users
 8765 /api/orders
 7654 /products
 6543 /blog

(6) ▶ Exemplo: Análise por Dimensão de Tempo

BASH
echo "=== Requests per Hour ==="
cat /tmp/access.log | awk -F: '{print $2":00"}' | sort | uniq -c | sort -rn

echo ""
echo "=== Peak Traffic Hours ==="
cat /tmp/access.log | awk -F: '{print $2}' | sort | uniq -c | sort -rn | head -5

echo ""
echo "=== Requests per Minute (Top 10) ==="
cat /tmp/access.log | awk -F: '{print $2":"$3}' | sort | uniq -c | sort -rn | head -10

Saída:

TEXT
=== Requests per Hour ===
     85 10:00
     80 14:00
     75 09:00
     70 22:00
     65 18:00

=== Peak Traffic Hours ===
     85 10
     80 14
     75 09
     70 22
     65 18

=== Requests per Minute (Top 10) ===
      5 10:15
      4 14:30
      4 09:45
      3 22:10
      3 18:05

(7) ▶ Exemplo: Análise de Desempenho

BASH
echo "=== Response Size Analysis (using $10 as simulated response size) ==="
echo "Largest response: $(awk '{print $10}' /tmp/access.log | sort -rn | head -1) bytes"
echo "Average response: $(awk '{sum += $10; count++} END {printf "%.0f", sum/count}' /tmp/access.log) bytes"
echo ""

echo "=== Large Responses (> 5KB) ==="
cat /tmp/access.log | awk '$10 > 5000 {print $10, $7}' | sort -rn | head -10

Saída:

TEXT
=== Response Size Analysis (using $10 as simulated response size) ===
Largest response: 10098 bytes
Average response: 5142 bytes

=== Large Responses (> 5KB) ===
10098 /images/logo.png
 9876 /api/users
 8765 /api/orders
 7654 /products
 6543 /blog
 5678 /api/data

(8) ▶ Exemplo Abrangente: Script Completo de Relatório de Análise de Log

BASH
#!/bin/bash
# log-report.sh - Gera relatório de análise de log do Nginx

LOG_FILE="${1:-/tmp/access.log}"

if [ ! -f "$LOG_FILE" ]; then
    echo "Error: Log file $LOG_FILE does not exist"
    exit 1
fi

TOTAL=$(wc -l < "$LOG_FILE")

echo "========================================="
echo "     Nginx Access Log Analysis Report"
echo "     File: $LOG_FILE"
echo "     Total requests: $TOTAL"
echo "     Generated at: $(date)"
echo "========================================="
echo ""

# 1. Visão geral dos códigos de status
echo "1. HTTP Status Code Distribution"
echo "--------------------"
cat "$LOG_FILE" | awk '{print $9}' | sort | uniq -c | sort -rn | \
    awk '{printf "  %-5s %s\n", $2, $1}'
echo ""

# 2. TOP 10 IPs
echo "2. Top 10 IPs by Access Count"
echo "---------------------"
cat "$LOG_FILE" | awk '{print $1}' | sort | uniq -c | sort -rn | head -10 | \
    awk '{printf "  %-20s %s\n", $2, $1}'
echo ""

# 3. TOP 10 URLs
echo "3. Top 10 URLs by Request Count"
echo "-----------------------"
cat "$LOG_FILE" | awk '{print $7}' | sort | uniq -c | sort -rn | head -10 | \
    awk '{printf "  %-30s %s\n", $1, $2}'
echo ""

# 4. Erros 4xx/5xx
echo "4. Error Requests"
echo "-------------"
FOURXX=$(awk '$9 ~ /^4/ {count++} END {print count}' "$LOG_FILE")
FIVEXX=$(awk '$9 ~ /^5/ {count++} END {print count}' "$LOG_FILE")
echo "  4xx errors: $FOURXX ($(echo "scale=1; $FOURXX*100/$TOTAL" | bc)%)"
echo "  5xx errors: $FIVEXX ($(echo "scale=1; $FIVEXX*100/$TOTAL" | bc)%)"
echo ""

# 5. Requisições por hora
echo "5. Requests per Hour"
echo "--------------------"
cat "$LOG_FILE" | awk -F: '{print $2":00"}' | sort | uniq -c | sort -rn | head -10 | \
    awk '{printf "  %s: %s\n", $2, $1}'
echo ""

# 6. Maiores respostas
echo "6. Largest Responses (Top 5)"
echo "----------------------"
cat "$LOG_FILE" | awk '{print $10, $7}' | sort -rn | head -5 | \
    awk '{printf "  %s bytes: %s\n", $1, $2}'
echo ""

echo "========================================="
echo "End of Report"
BASH
# Executa o script de relatório
chmod +x log-report.sh
./log-report.sh /tmp/access.log

❓ Perguntas Frequentes

P: O que significam os campos no formato de log do Nginx? R: Formato combined padrão: IP - usuário [horário] "método URL protocolo" código_status bytes "Referer" "User-Agent". Você pode personalizar pela diretiva log_format do Nginx.

P: Pipelines travam com arquivos de log enormes (na casa de GB)? R: Não muito. O streaming de pipeline significa que os dados são processados à medida que são lidos. Porém, o sort bloqueia porque precisa ler todos os dados antes. Para arquivos muito grandes, use sort -S 1G para limitar a memória, ou use arrays do awk para as estatísticas.

P: Como contar PV (page views) e UV (unique visitors) reais? R: PV = wc -l (excluindo requisições que não são páginas, como imagens/CSS/API). UV = awk '{print $1}' access.log | sort -u | wc -l.

P: Como monitorar mudanças no log continuamente? R: tail -f acompanha novas linhas em tempo real. Combine com grep: tail -f access.log | grep " 500 " — mostra todos os erros 500 em tempo real.

P: Como calcular o tempo de resposta P99 de endpoints de API? R: O Nginx precisa ser configurado com $upstream_response_time ou $request_time. Depois: awk '{print $NF}' access.log | sort -n | awk '{all[NR]=$1} END{p99=int(NR*0.99); print all[p99]}'.


📖 Resumo


📝 Exercícios

  1. Básico (⭐): Rode o script de geração de logs de amostra para criar 1000 entradas de teste, depois escreva uma cadeia de pipeline para encontrar os top 5 IPs por número de acessos e suas quantidades de requisições
  2. Intermediário (⭐⭐): Conte o número e o percentual dos códigos de status 404 e 500, depois use awk '{print $7}' para extrair as URLs e encontrar as 5 páginas mais populares
  3. Avançado (⭐⭐⭐): Crie um script de análise de log que gere um relatório formatado em Markdown incluindo: total de requisições, Top 10 IPs, distribuição de códigos de status, tendências de requisições por hora, Top 5 URLs acessadas
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%