Automatize uma Tarefa com Shell Script
Transforme os comandos que você aprendeu num script Bash real e reutilizável: argumentos, condicionais, loops e um cabeçalho seguro — construindo um resumidor de logs que transforma um arquivo de log cru num relatório. O complemento prático do Terminal & Linux Essentials.
Problema
Digitar os mesmos três comandos todo dia é como você sabe que uma tarefa deveria ser um script. A distância entre "sei usar o terminal" e "automatizo meu trabalho" é pequena — um shebang, algumas variáveis, um `if` e um `for` — mas é o salto que te transforma de usuário de ferramenta em construtor de ferramenta. Neste lab você vai escrever um script Bash real do zero: um **resumidor de logs** que recebe um arquivo de log, conta erros e avisos, acha as fontes que mais causam problema e imprime um relatório limpo. No caminho você vai tratar argumentos, se proteger de entrada ruim, iterar sobre linhas e adicionar o cabeçalho de segurança que todo script sério precisa. Você vai terminar com um script que poderia de fato colocar no crontab de um servidor.
Objetivos
- Transformar uma sequência de comandos num script executável com shebang e
chmod +x - Ler argumentos posicionais (
$1,$@,$#) e validá-los antes de trabalhar - Usar
if/elif/elsecom testes de arquivo (-f,-r) e comparações de string/número - Iterar com
forewhile readpara processar um arquivo linha a linha - Combinar
grep,sort,uniq -ceawkdentro de um script para agregar dados - Adicionar o cabeçalho de segurança
set -euo pipefaile códigos de saída e mensagens de erro significativos
Pré-requisitos
- Um shell tipo Unix: Linux, macOS, ou WSL/Git Bash no Windows. Rode
bash --versionpara confirmar que você tem Bash. - Os comandos do dia a dia do Terminal & Linux Essentials:
cd,ls,cat,grep, pipes e redirecionamento,chmod - Qualquer editor de texto (nano, vim, VS Code)
- Git instalado, para entregar seu script no fim
O que você vai construir
Um único script, logstats.sh, que você vai crescer passo a passo. Dado um arquivo de log, ele vai:
- validar que recebeu um arquivo legível como argumento,
- contar total de linhas,
ERRORs eWARNings, - listar as principais fontes de erro,
- e imprimir um relatório organizado — saindo com código diferente de zero se a entrada for ruim.
Cada passo adiciona um conceito de shell e uma funcionalidade ao script, então você termina com algo
real em vez de trechos de brinquedo.
Por que script, e não só comandos
Um comando que você digita some no momento em que sai da tela. Um script é esse conhecimento
capturado — versionado, compartilhável, agendável. O mesmo grep | sort | uniq -c que você
rodaria na mão vira, embrulhado num script, um relatório que qualquer um (ou o cron) roda
identicamente às 2 da manhã. Essa reprodutibilidade é todo o valor da automação.
Um arquivo de log de exemplo
Você vai gerar um logfile realista no Passo 1 para todo mundo trabalhar nos mesmos dados. Logs reais
são mais bagunçados, mas o formato — um timestamp, um nível, uma fonte, uma mensagem por linha — é universal.
Como trabalhar neste lab
Construa o script incrementalmente e rode-o após cada passo (./logstats.sh sample.log), lendo a
saída real. Não cole tudo só no fim — o ponto é ver cada peça funcionar.
Passos
-
Do comando ao script: shebang e chmod
Primeiro, crie dados de exemplo e seu primeiro script executável.
Gere um logfile de exemplo
Cole isto para criar
sample.logcom uma mistura realista de níveis e fontes:cat > sample.log <<'EOF' 2026-07-10 09:01:12 INFO auth user login ok 2026-07-10 09:02:03 WARN auth slow response 2026-07-10 09:02:44 ERROR payments gateway timeout 2026-07-10 09:03:10 INFO web GET /home 200 2026-07-10 09:04:55 ERROR payments card declined 2026-07-10 09:05:01 WARN web deprecated endpoint 2026-07-10 09:06:22 ERROR auth token expired 2026-07-10 09:07:30 INFO web GET /pricing 200 2026-07-10 09:08:14 ERROR payments gateway timeout EOF wc -l sample.log # 9 linhasEscreva o primeiro script
Crie
logstats.sh:#!/usr/bin/env bash echo "logstats starting" wc -l "sample.log"- A primeira linha é o shebang:
#!/usr/bin/env bashdiz ao SO para rodar o arquivo com o
Bash. Sem ele, o arquivo é só texto. - Usar
env bashacha o Bash noPATHdo usuário, o que é mais portátil do que fixar/bin/bash.
Torne executável e rode
chmod +x logstats.sh # adiciona a permissão de execução ./logstats.sh # o ./ diz "rode o arquivo aqui", não um comando do PATHUm arquivo não é executável só porque contém comandos — ele precisa do bit de execução. É
isso que ochmod +xconcede;ls -l logstats.shagora mostra umxnas permissões.Entregável deste passo: a saída de
ls -l logstats.shmostrando o bitx, e a saída do script. - A primeira linha é o shebang:
-
Argumentos e validação
Fixar
sample.logfaz um script de um truque só. Receba o nome do arquivo como argumento.Leia o argumento
Substitua o corpo do
logstats.sh:#!/usr/bin/env bash logfile="$1" # primeiro argumento passado na linha de comando echo "Analisando: $logfile" wc -l "$logfile"-
$1é o primeiro argumento,$2o segundo, e assim por diante.$@é todos os argumentos,
$#é quantos são. - Sempre coloque variáveis entre aspas (
"$logfile") para nomes com espaços não quebrarem o script.
Rode de duas formas:
./logstats.sh sample.log ./logstats.sh # sem argumento — o que acontece?Sem argumento,
$1está vazio e owcdá um erro feio. Um script real valida primeiro.Proteja a entrada
Adicione uma checagem no topo, antes de qualquer trabalho:
#!/usr/bin/env bash if [ "$#" -lt 1 ]; then echo "Uso: $0 <logfile>" >&2 exit 1 fi logfile="$1" if [ ! -f "$logfile" ]; then echo "Erro: '$logfile' não é um arquivo legível" >&2 exit 2 fi echo "Analisando: $logfile"O que cada peça faz:
-
[ "$#" -lt 1 ]→ "menos de 1 argumento". Se for o caso, imprime o uso no stderr (>&2) e sai com código diferente de zero. -
$0é o próprio nome do script — uma mensagem de uso autodocumentada. -
[ ! -f "$logfile" ]→ "não é um arquivo regular". Falhe cedo com um código de saída distinto. - Códigos de saída diferentes (1 para uso, 2 para arquivo ruim) deixam outros scripts reagirem ao porquê da falha.
Entregável deste passo: a saída ao rodar sem argumento e com um arquivo inexistente, mostrando as mensagens de erro e (via
echo $?) os códigos de saída. -
-
Condicionais e contagem
Agora o trabalho de verdade: contar o que há no log e ramificar conforme o resultado.
Conte os níveis
Adicione abaixo da validação:
total=$(wc -l < "$logfile") errors=$(grep -c 'ERROR' "$logfile") warnings=$(grep -c 'WARN' "$logfile") echo "Total de linhas: $total" echo "Erros: $errors" echo "Avisos: $warnings"-
$( ... )é substituição de comando: roda o comando e captura a saída na variável. -
wc -l < "$logfile"alimenta o arquivo via stdin para owcimprimir só o número (sem o nome do arquivo). -
grep -c PADRÃOconta linhas que casam diretamente — sem precisar de pipe para owc.
Ramifique conforme as contagens
Transforme números num veredito com
if/elif/else:if [ "$errors" -eq 0 ]; then echo "Status: saudável ✅" elif [ "$errors" -lt 3 ]; then echo "Status: atenção ⚠️ ($errors erros)" else echo "Status: crítico ❌ ($errors erros)" fiComparações de número usam operadores de palavra:
-eq(=),-lt(<),-gt(>),-le,-ge.
(Comparações de string usam=e!=— uma pegadinha clássica.)Rode
./logstats.sh sample.log— com 4 erros na amostra, você deve cair no ramocrítico.Entregável deste passo: a saída do script mostrando as três contagens e o veredito de status.
-
-
Loops e agregação: principais fontes de erro
Uma contagem é útil; de onde os erros vêm é acionável. Agregue por fonte.
O pipeline que acha os maiores culpados
A terceira coluna de cada linha de log é a fonte (
auth,payments,web). Extraia, agrupe e ranqueie:echo "Principais fontes de erro:" grep 'ERROR' "$logfile" | awk '{ print $4 }' | sort | uniq -c | sort -rnLeia o pipeline da esquerda para a direita — essa é a essência do Unix:
-
grep 'ERROR'→ mantém só as linhas de erro. -
awk '{ print $4 }'→ imprime o 4º campo separado por espaço (a fonte). Oawksepara por espaço automaticamente. -
sort→ agrupa fontes idênticas (necessário antes douniq). -
uniq -c→ colapsa duplicatas e prefixa cada uma com sua contagem. -
sort -rn→ ordena por essa contagem, numericamente (-n), da maior primeiro (-r).
Na amostra,
paymentsdeve liderar com 3 erros.Itere sobre os resultados
Para formatar cada linha de fonte você mesmo, itere com
while read:echo "Detalhamento:" grep 'ERROR' "$logfile" | awk '{ print $4 }' | sort | uniq -c | sort -rn | while read -r count source; do echo " - $source causou $count erro(s)" done-
while read -r count sourcelê cada linha, separando em duas variáveis no espaço. -
-rimpede que barras invertidas sejam interpretadas — sempre use comread. - O corpo do loop roda uma vez por fonte, deixando você formatar, aplicar limite, ou alertar por linha.
Entregável deste passo: a saída de "Principais fontes de erro" e "Detalhamento" para o log de exemplo.
-
-
Torne robusto: set -euo pipefail e uma função de relatório
Um script que continua após um erro pode causar estrago de verdade. Adicione o cabeçalho de segurança e estrutura.
O cabeçalho de segurança
Coloque isto logo após o shebang:
#!/usr/bin/env bash set -euo pipefailCada flag previne uma classe de bug silencioso:
-
-e→ sai imediatamente se algum comando falhar, em vez de seguir tropeçando. -
-u→ erro em variáveis indefinidas (um$logfylecom typo vira um crash, não string vazia). -
-o pipefail→ um pipeline falha se qualquer estágio falhar, não só o último.
Esse trio é o hábito mais importante para scripts confiáveis. Teste: referencie temporariamente
uma variável indefinida e veja o script parar em vez de produzir lixo.Embrulhe o relatório numa função
Agrupe a saída numa função para legibilidade e reuso:
print_report() { local file="$1" echo "==============================" echo " Relatório de log: $file" echo " Gerado em: $(date '+%Y-%m-%d %H:%M')" echo "==============================" echo "Total de linhas: $(wc -l < "$file")" echo "Erros: $(grep -c 'ERROR' "$file")" echo "Avisos: $(grep -c 'WARN' "$file")" } print_report "$logfile"-
local file="$1"escopa a variável à função — ela não vaza para o resto do script. - Funções transformam um script longo em peças nomeadas e testáveis, exatamente como funções em qualquer linguagem.
Rode o script completo mais uma vez e confirme que o relatório renderiza limpo, com cabeçalho e contagens.
Entregável deste passo: a saída do relatório completo, e uma nota sobre o que aconteceu quando você disparou o
set -ucom uma variável indefinida. -
-
Entregue: seu script e uma execução de exemplo
Empacote o script, o log de exemplo e uma execução capturada, e entregue.
Monte o repositório
Seu
logstats.shdeve agora conter, em ordem: o shebang,set -euo pipefail, validação de
argumento, a funçãoprint_report, o pipeline/loop das principais fontes de erro, e o veredito
de status. Crie umSUBMISSION.mdcapturando uma execução real:# Lab de Shell Script — <seu nome> ## O script Veja logstats.sh (versão final). ## Execução de exemplo $ ./logstats.sh sample.log <cole a saída real completa: cabeçalho do relatório, contagens, status, principais fontes> ## Comportamento de validação $ ./logstats.sh # (erro de uso, exit 1) $ ./logstats.sh nope.log # (arquivo ruim, exit 2) <cole ambos, com `echo $?` após cada> ## Reflexão (2-3 frases) Nas minhas palavras: contra o que o `set -euo pipefail` protege, e uma tarefa da minha própria vida que eu poderia automatizar com um script assim.Entregue
git init git add logstats.sh sample.log SUBMISSION.md git commit -m "Lab de shell script — resumidor de logs" # faça push para um repo público ou gist, depois entregue essa URLCritério de submissão (autoverificação)
-
logstats.shcomeça com um shebang eset -euo pipefail - Valida a quantidade de argumentos e a existência do arquivo, com códigos de saída distintos e diferentes de zero
- Usa substituição de comando
$(...)para contar linhas/erros/avisos - Usa um
if/elif/elsepara imprimir um veredito de status - Agrega as principais fontes de erro com
grep | awk | sort | uniq -c | sort -rn - Um loop
while readou uma função é usado para estruturar a saída - A entrega mostra uma execução real mais os dois casos de falha de validação com seus códigos de saída
O que vem a seguir
Você já consegue transformar qualquer tarefa repetitiva do terminal num script seguro e
reutilizável. Um próximo passo natural é agendá-lo (cron) e, no Backend Developer Path, usar
scripts assim para automatizar partes de construir e fazer deploy da API que você vai criar. -