Bash sério: set -euo pipefail, funções e exit codes
Objetivos desta aula
- Escrever scripts que falham cedo e alto
- Usar funções, trap e logging
- Retornar códigos de saída úteis
Script de automação sem tratamento de erro é armadilha: ele continua depois de falhar e produz estado pior que o inicial. set -e aborta em erro, set -u falha em variável não definida (evitando rm -rf em caminho vazio), set -o pipefail propaga erro em pipeline e IFS ajustado evita quebra com espaços em nomes.
Exit code é a interface do seu script com o mundo: 0 é sucesso e qualquer outro valor é falha. CI, systemd, cron e Kubernetes tomam decisão com base nisso. Definir códigos específicos (2 para dependência ausente, 3 para validação falha) torna a automação legível.
Estruture com funções pequenas, log com timestamp para stderr, trap para limpeza de arquivos temporários e validação de argumentos no início. E rode ShellCheck: ele encontra em segundos bugs de quoting que custariam horas.
1. Por que set -euo pipefail
-e: sai no primeiro comando que falhar-u: erro ao usar variável não definida (evitarm -rf "$DIR/"com DIR vazio)-o pipefail: um pipe falha se qualquer etapa falhar, não só a última
2. Aspas sempre
"$arquivo" protege contra espaços e curingas. Sem aspas, um nome como meu log.txt vira dois argumentos.
3. Funções, argumentos e retorno
Funções recebem $1, $2, "$@"; usam local para variáveis internas; retornam status com return e dados via echo.
4. Exit codes e trap
0 é sucesso, qualquer outro é falha — é assim que o CI decide se o job passou. trap cleanup EXIT garante limpeza de arquivos temporários mesmo em erro.
5. Qualidade com shellcheck
O shellcheck encontra aspas faltando, variáveis não usadas e armadilhas clássicas. Coloque-o no pipeline.
6. Checagem final
Você deve escrever um script com modo estrito, validação de argumentos, log com horário, trap de limpeza e exit code correto.
Na prática
Health-check do CloudShop em Bash
bash
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
URL="${1:-https://api.cloudshop.dev/health}"
TIMEOUT="${TIMEOUT:-5}"
RETRIES=3
log() { printf '%s [%s] %s\n' "$(date -Is)" "$1" "$2" >&2; }
cleanup() { rm -f "$TMP"; }
TMP="$(mktemp)"
trap cleanup EXIT
command -v curl >/dev/null || { log ERRO "curl nao instalado"; exit 2; }
for attempt in $(seq 1 "$RETRIES"); do
code="$(curl -sS -m "$TIMEOUT" -o "$TMP" -w '%{http_code}' "$URL" || echo 000)"
if [[ "$code" == "200" ]]; then
log INFO "saudavel (tentativa $attempt)"
exit 0
fi
log AVISO "status $code na tentativa $attempt"
sleep $(( attempt * 2 ))
done
log ERRO "servico indisponivel apos $RETRIES tentativas"
cat "$TMP" >&2 || true
exit 3Nota de segurança: Sempre use aspas em variáveis e nunca construa comando concatenando entrada externa: é injeção de shell.
Esqueleto de script profissional
bash
#!/usr/bin/env bash
set -euo pipefail
log() { printf '%s [%s] %s\n' "$(date -Is)" "$1" "$2" >&2; }
usage() { echo "uso: $0 <ambiente>" >&2; exit 2; }
[[ $# -eq 1 ]] || usage
env="$1"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT # limpa sempre, mesmo com erro
log INFO "verificando saude em $env"
if ! curl -fsS "https://api.$env.cloudshop.dev/health" > "$tmp/health.json"; then
log ERROR "health check falhou"
exit 1
fi
log INFO "ok"Por que isso importa
Bash aparece em toda vaga porque é a cola de qualquer automação: pipelines, entrypoints e rotinas de plantão.
Erro comum
Esquecer aspas em variável com espaço e apagar o arquivo errado.
Dica de produção
Adicione shellcheck ao CI. É o linter mais barato e mais rentável que existe.
Pergunta de entrevista
O que cada parte de set -euo pipefail faz e qual problema evita?
Glossário
- trap
- Registra comando a executar quando o script recebe um sinal ou termina.
- exit code
- Número retornado pelo processo; 0 indica sucesso.
- exit code
- Número devolvido pelo processo; 0 significa sucesso.
- trap
- Comando Bash que executa uma ação ao receber sinal ou ao sair.
- shellcheck
- Analisador estático de scripts shell.
Conexão com o CloudShop
Usar o health-check no cron do host e como comando de verificação pós-deploy.
Quiz da aula
1. Qual opção faz o script abortar quando um comando dentro de um pipeline falha?
2. O que -o pipefail muda?
3. Qual a vantagem de trap ... EXIT?
Minhas anotações
Salvo automaticamente neste navegador.