Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

[Dúvida] Projeto final: monitoramento-logs.sh

Fiz uma pequena refatoração no script monitoramento-logs.sh:

  • Evitei o uso excessivo de sed -i (cada execução cria um novo processo).
  • Reduzi a duplicação de date +%F.
  • Utilizei awk para reduzir múltiplos grep + sed.
  • Criei variáveis temporárias em vez de muitos arquivos intermediários.
  • Minimizei I/O em disco (um dos maiores gargalos).
#!/bin/bash

# Diretórios
LOG_DIR="../myapp/logs"
ARQUIVO_DIR="../myapp/logs-processados"
TEMP_DIR="../myapp/logs-temp"

# Criação dos diretórios
mkdir -p "$ARQUIVO_DIR" "$TEMP_DIR"

# Data de hoje
HOJE=$(date +%F)
LOG_STATS="${ARQUIVO_DIR}/log_stats_${HOJE}.txt"
LOG_COMBINADOS="${ARQUIVO_DIR}/logs_combinados_${HOJE}.log"

# Processamento de arquivos .log
find "$LOG_DIR" -name "*.log" -print0 | while IFS= read -r -d '' arquivo; do
    nome_arquivo=$(basename "$arquivo")
    filtrado=$(mktemp)

    # Filtra linhas com ERROR ou SENSITIVE_DATA e faz substituições inline com awk
    awk '
        /ERROR|SENSITIVE_DATA/ {
            gsub(/User password is .*/, "User password is REDACTED");
            gsub(/User password reset request with token .*/, "User password reset request with token REDACTED");
            gsub(/API key leaked: .*/, "API key leaked: REDACTED");
            gsub(/User credit card last four digits: .*/, "User credit card last four digits: REDACTED");
            gsub(/User session initiated with token: .*/, "User session initiated with token: REDACTED");
            print;
        }
    ' "$arquivo" | sort | uniq > "$filtrado"

    num_palavras=$(wc -w < "$filtrado")
    num_linhas=$(wc -l < "$filtrado")

    {
        echo "Arquivo: $nome_arquivo"
        echo "Número de linhas: $num_linhas"
        echo "Número de palavras: $num_palavras"
        echo "--------------------------"
    } >> "$LOG_STATS"

    # Adiciona prefixo dependendo do tipo
    if [[ "$nome_arquivo" == *frontend* ]]; then
        sed 's/^/[FRONTEND] /' "$filtrado" >> "$LOG_COMBINADOS"
    elif [[ "$nome_arquivo" == *backend* ]]; then
        sed 's/^/[BACKEND] /' "$filtrado" >> "$LOG_COMBINADOS"
    else
        cat "$filtrado" >> "$LOG_COMBINADOS"
    fi

    rm "$filtrado"
done

# Ordena o log combinado por segunda coluna (assumindo formato que permita isso)
sort -k2 "$LOG_COMBINADOS" -o "$LOG_COMBINADOS"

# Move arquivos para o diretório temporário
mv "$LOG_COMBINADOS" "$TEMP_DIR/"
mv "$LOG_STATS" "$TEMP_DIR/"

# Compacta
tar -czf "${ARQUIVO_DIR}/logs_${HOJE}.tar.gz" -C "$TEMP_DIR" .

# Limpa
rm -r "$TEMP_DIR"

Melhorias:

  • Substituições de dados feitas em um único awk, sem múltiplos sed.
  • Menos arquivos intermediários (.filtrado, .unico).
  • Variáveis reutilizadas (como HOJE).
  • Evitar reprocessamentos ou comandos redundantes

continua...

Garanta sua matrícula hoje e ganhe + 2 meses grátis

Continue sua jornada tech com ainda mais tempo para aprender e evoluir

Quero aproveitar agora
3 respostas

E continuando....
Agora, vamos criar a versão Python desse mesmo script:

import os
import re
import shutil
import tarfile
from datetime import datetime
from pathlib import Path

LOG_DIR = Path("../myapp/logs")
ARQUIVO_DIR = Path("../myapp/logs-processados")
TEMP_DIR = Path("../myapp/logs-temp")
HOJE = datetime.now().strftime("%Y-%m-%d")

LOG_STATS = ARQUIVO_DIR / f"log_stats_{HOJE}.txt"
LOG_COMBINADOS = ARQUIVO_DIR / f"logs_combinados_{HOJE}.log"

SENSITIVE_PATTERNS = [
    (r"User password is .*", "User password is REDACTED"),
    (r"User password reset request with token .*", "User password reset request with token REDACTED"),
    (r"API key leaked: .*", "API key leaked: REDACTED"),
    (r"User credit card last four digits: .*", "User credit card last four digits: REDACTED"),
    (r"User session initiated with token: .*", "User session initiated with token: REDACTED"),
]

def sanitize_line(line):
    for pattern, replacement in SENSITIVE_PATTERNS:
        line = re.sub(pattern, replacement, line)
    return line

def process_log_file(filepath):
    sanitized_lines = []
    with open(filepath, "r", encoding="utf-8") as file:
        for line in file:
            if "ERROR" in line or "SENSITIVE_DATA" in line:
                sanitized = sanitize_line(line.strip())
                sanitized_lines.append(sanitized)

    sanitized_lines = sorted(set(sanitized_lines))

    num_linhas = len(sanitized_lines)
    num_palavras = sum(len(line.split()) for line in sanitized_lines)

    nome_arquivo = filepath.name
    with open(LOG_STATS, "a", encoding="utf-8") as stats:
        stats.write(f"Arquivo: {nome_arquivo}\n")
        stats.write(f"Número de linhas: {num_linhas}\n")
        stats.write(f"Número de palavras: {num_palavras}\n")
        stats.write("--------------------------\n")

    prefix = ""
    if "frontend" in nome_arquivo:
        prefix = "[FRONTEND] "
    elif "backend" in nome_arquivo:
        prefix = "[BACKEND] "

    with open(LOG_COMBINADOS, "a", encoding="utf-8") as combined:
        for line in sanitized_lines:
            combined.write(f"{prefix}{line}\n")

def main():
    ARQUIVO_DIR.mkdir(parents=True, exist_ok=True)
    TEMP_DIR.mkdir(parents=True, exist_ok=True)

    for log_file in LOG_DIR.glob("*.log"):
        process_log_file(log_file)

    # Ordena o arquivo combinado pela segunda palavra (se aplicável)
    with open(LOG_COMBINADOS, "r", encoding="utf-8") as f:
        lines = sorted(f.readlines(), key=lambda l: l.split()[1] if len(l.split()) > 1 else l)

    with open(LOG_COMBINADOS, "w", encoding="utf-8") as f:
        f.writelines(lines)

    shutil.move(str(LOG_COMBINADOS), TEMP_DIR)
    shutil.move(str(LOG_STATS), TEMP_DIR)

    tar_path = ARQUIVO_DIR / f"logs_{HOJE}.tar.gz"
    with tarfile.open(tar_path, "w:gz") as tar:
        tar.add(TEMP_DIR, arcname=".")

    shutil.rmtree(TEMP_DIR)

if __name__ == "__main__":
    main()

Execute o script:

python3 ~/log_processor.py

Lembrando que precisa ter o python instalado.
Confere ai e envia um feedback.
Bons estudos e até o proximo curso.

solução!

Oi, Ronaldo! Como vai?

Agradeço por compartilhar.

Gostei do projeto: você reduziu processos com awk, evitou vários sed -i, diminuiu I/O e ainda criou uma versão em Python com sanitização e empacotamento tar.gz. No Bash, a leitura com find … -print0 e read -d '' ficou cuidadosa; no Python, a separação em funções e a lista de padrões sensíveis deixou o fluxo claro.

Siga em frente, está evoluindo bem.

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!

Olá Lorena.
Obrigado por seu feedback.
Até... : )