0Pricing
Linux Command Line & Bash Scripting Mastery · Aula

Modo estrito com set -euo pipefail

Ative o comportamento de falha imediata e entenda exatamente quais erros cada opção do modo estrito captura e quais deixa passar.

Modo estrito com set -euo pipefail é 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.

Por que o Bash falha silenciosamente por padrão

Por padrão, o Bash continua em execução mesmo quando os comandos falham. Isso causa problemas sutis e difíceis de depurar em programas de produção.

Considere este programa, que tenta criar um backup:

  • Um erro de digitação em um caminho faz o cp falhar
  • O Bash ignora a falha e continua
  • O programa informa sucesso, embora os dados nunca tenham sido copiados

Esse é o problema das falhas silenciosas. O modo estrito resolve isso fazendo o Bash se comportar como uma linguagem compilada: parar imediatamente quando algo dá errado.

#!/usr/bin/env bash
# Without strict mode — dangerous default behavior

cp /important/data /backups/data   # fails (path doesn't exist)
echo "Backup complete"              # still prints — false confidence!
rm -rf /tmp/staging                # still runs — potentially destructive

Os três sinalizadores principais: set -euo pipefail

O modo estrito é ativado colocando esta linha perto do início de todo programa:

set -euo pipefail

Isso ativa três proteções distintas:

  • -e — Sai imediatamente se algum comando retornar um status diferente de zero
  • -u — Trata variáveis não definidas como um erro (em vez de expandi-las para uma string vazia)
  • -o pipefail — Um pipeline falha se qualquer comando nele falhar, e não apenas o último

Juntos, eles formam o cabeçalho defensivo padrão de programas Bash robustos. Cada sinalizador detecta uma classe diferente de erro.

#!/usr/bin/env bash
set -euo pipefail

echo "Strict mode is now active"
echo "Every command failure will abort the script"

Entendendo set -e (errexit)

set -e (também escrito como set -o errexit) faz o programa sair imediatamente quando um comando termina com um status diferente de zero.

Principais comportamentos que você deve conhecer:

  • Comandos simples: false, grep pattern file (nenhuma correspondência), ls /nonexistent — todos acionam a saída
  • O código de saída do último comando do programa se torna o código de saída do programa
  • Comandos em condições de if são isentos — -e não é acionado para a expressão de teste
  • Comandos seguidos por || true também são isentos (veja as próximas cenas)

Considere -e sua primeira linha de defesa contra a continuação silenciosa após uma falha.

#!/usr/bin/env bash
set -e

echo "Before failure"
ls /this/path/does/not/exist   # exits here with code 2
echo "This line never runs"

Entendendo set -u (nounset)

set -u (também escrito como set -o nounset) faz o Bash tratar qualquer referência a uma variável não definida como um erro fatal.

Sem -u, um erro de digitação como $FLENAME em vez de $FILENAME é silenciosamente expandido para uma string vazia, fazendo os comandos se comportarem de modo inesperado — ou perigoso (imagine rm -rf "$TMPDIR/" quando $TMPDIR não está definido).

Exceções importantes:

  • ${VAR:-default} — substituição segura com valor padrão; não aciona -u
  • ${VAR:+value} — expansão condicional, também segura
  • "$@" e "$*" são isentos quando nenhum argumento posicional é fornecido
#!/usr/bin/env bash
set -euo pipefail

# Safe: provide a default for optional vars
OUTPUT_DIR="${1:-/tmp/output}"
LOG_LEVEL="${LOG_LEVEL:-info}"

echo "Writing to: $OUTPUT_DIR"
echo "Log level: $LOG_LEVEL"

# This would abort the script:
# echo "$UNDEFINED_VAR"   # bash: UNDEFINED_VAR: unbound variable

Entendendo -o pipefail

Sem pipefail, o status de saída de um pipeline é determinado exclusivamente pelo último comando. As falhas anteriores são silenciosamente ignoradas.

Exemplo sem pipefail:

  • cat /missing/file | wc -l
  • cat falha com o código de saída 1, mas wc -l é executado com sucesso e retorna o código 0
  • O pipeline retorna 0 — sucesso! Embora os dados tenham sido perdidos.

Com pipefail ativado, o Bash retorna o código de saída do comando mais à direita que falhou. Isso torna as falhas do pipeline visíveis e detectáveis.

Observação: pipefail não é um sinalizador de uma letra — ele deve ser definido com -o pipefail.

#!/usr/bin/env bash
set -euo pipefail

# With pipefail: this aborts if grep finds nothing (exit 1)
# grep returns 1 when no match found
ps aux | grep "[n]ginx" | awk '{print $2}'

echo "If we reach here, nginx is running"

Falhas intencionais de comandos — usando || true

Às vezes, é permitido que um comando falhe. Com set -e, você deve indicar explicitamente as falhas toleradas; caso contrário, o programa será interrompido.

A solução idiomática é || true, que acrescenta uma alternativa que sempre tem sucesso:

  • command || true — ignora completamente a falha
  • command || echo "Warning: step failed, continuing" — registra um aviso e continua
  • command || { echo "fatal"; exit 1; } — tratamento personalizado da falha

Esse padrão deixa clara a sua intenção no código: um comando simples significa "isso deve ter sucesso"; um || true significa "isso pode falhar, e tudo bem".

#!/usr/bin/env bash
set -euo pipefail

# Remove temp dir if it exists — OK if it doesn't
rm -rf /tmp/my_workspace || true
mkdir -p /tmp/my_workspace

# Check if a service is running — OK if not
if systemctl is-active --quiet nginx 2>/dev/null || true; then
  echo "nginx is active"
fi

# Grep that may find nothing — OK
grep 'ERROR' /var/log/app.log || true

echo "Done"

O que set -e NÃO captura

set -e tem exceções e armadilhas conhecidas. Entendê-las evita uma falsa sensação de segurança:

  • Comandos em condições de if / while / until — a expressão de teste é isenta por projeto
  • Comandos negados com ! — ! false não aciona a saída
  • O último comando antes de || — por exemplo, false || handle_error
  • Status de saída de subprocessos em determinados contextos — por exemplo, VAR=$(failing_command) em algumas versões do Bash
  • Valores de retorno de funções — somente o último comando de uma função é considerado

O modo estrito não substitui a verificação explícita de erros — ele é uma rede de segurança que captura a maioria das falhas acidentais.

#!/usr/bin/env bash
set -euo pipefail

# These do NOT trigger -e:
if false; then echo "never"; fi         # -e exempt in conditions
! false                                  # negation exempts
false || echo "handled"                 # || exempts the left side

# This DOES trigger -e (no condition, no ||):
# false

echo "Script continues after exempted failures"

Subprocessos e funções com o modo estrito

As configurações do modo estrito são herdadas pelos subprocessos, mas têm comportamentos sutis em funções e substituições de comandos.

Regras principais:

  • As funções herdam -e, -u e pipefail do shell que as chama
  • Um retorno diferente de zero de uma função faz o chamador sair (quando -e está definido) — a menos que a chamada esteja em uma condição ou depois de ||
  • Substituição de comandos $(): em versões antigas do Bash, um comando com falha dentro de $() pode não acionar -e no processo pai; para garantir segurança, atribua o resultado e use-o separadamente
  • Subprocessos explícitos () herdam todos os sinalizadores
#!/usr/bin/env bash
set -euo pipefail

setup_workspace() {
  local dir="$1"
  mkdir -p "$dir"          # fails here if permissions denied
  cd "$dir"
  echo "Ready in $(pwd)"
}

# Safe pattern: assign result then use it
TODAY=$(date +%Y-%m-%d)   # capture separately
WORKDIR="/tmp/run_${TODAY}"

setup_workspace "$WORKDIR"
echo "Workspace: $WORKDIR"

Combinando o modo estrito com captura de erros

O modo estrito informa ao Bash quando parar. Uma trap em ERR permite executar a limpeza ou o diagnóstico antes de o programa sair.

O padrão comum é:

  • Definir o modo estrito no início
  • Definir uma função cleanup ou on_error
  • Registrá-la com trap 'on_error' ERR
  • Opcionalmente, também capturar EXIT para garantir a limpeza independentemente de sucesso ou falha

Importante: use set -E (E maiúsculo, também chamado de errtrace) para que a captura de ERR também seja herdada por funções e subprocessos — sem isso, as capturas só são acionadas no corpo do shell principal.

#!/usr/bin/env bash
set -Eeuo pipefail

on_error() {
  local exit_code=$?
  local line_number=${BASH_LINENO[0]}
  echo "ERROR: command failed with code ${exit_code} at line ${line_number}" >&2
}

cleanup() {
  echo "Cleaning up temporary files..." >&2
  rm -rf /tmp/my_run_dir 2>/dev/null || true
}

trap on_error ERR
trap cleanup EXIT

mkdir -p /tmp/my_run_dir
echo "hello" > /tmp/my_run_dir/output.txt
cat /tmp/my_run_dir/output.txt
echo "Done"

Desativando localmente o modo estrito

Às vezes, um bloco de código é intencionalmente "desorganizado" — por exemplo, ao procurar ferramentas opcionais ou executar comandos antigos que retornam um valor diferente de zero por motivos que não indicam erro. Você pode desativar temporariamente o modo estrito e restaurá-lo depois.

O padrão seguro:

  • Salve o estado com set +e (desativa -e), execute o bloco e reative-o com set -e
  • Ou use um subprocesso ( set +e; ... ) para que os sinalizadores do shell pai nunca sejam afetados
  • Sempre reative os sinalizadores assim que o bloco arriscado terminar — deixar os sinalizadores desativados é uma fonte comum de erros

Prefira a forma com subprocesso quando o bloco envolver vários comandos, pois ela restaura automaticamente os sinalizadores ao terminar.

#!/usr/bin/env bash
set -euo pipefail

# Probe for optional tools without aborting
HAS_JQ=false
(
  set +e
  command -v jq > /dev/null 2>&1
  [[ $? -eq 0 ]] && echo "jq_found"
) && HAS_JQ=true || true

if [[ "$HAS_JQ" == "true" ]]; then
  echo "jq is available — using JSON output"
else
  echo "jq not found — using plain text"
fi

Um modelo completo de programa com modo estrito

Veja um modelo pronto para produção que reúne todas as boas práticas do modo estrito abordadas nesta lição:

  • set -Eeuo pipefail — os quatro sinalizadores, incluindo errtrace
  • IFS=$'\n\t' — divisão de palavras mais segura (evita dividir nos espaços)
  • Capturas de ERR + EXIT para diagnóstico e limpeza
  • Valores padrão explícitos para parâmetros opcionais
  • readonly e local para limitar o escopo das variáveis

Copie este modelo para o início de todo programa Bash não trivial e obtenha imediatamente os benefícios de um comportamento de falha rápida e de erros rastreáveis.

#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

# ── Constants ────────────────────────────────────────────
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"

# ── Trap handlers ────────────────────────────────────────
err_handler() {
  echo "[${SCRIPT_NAME}] ERROR on line ${BASH_LINENO[0]}: exit ${?}" >&2
}
cleanup() {
  echo "[${SCRIPT_NAME}] Exiting" >&2
}
trap err_handler ERR
trap cleanup EXIT

# ── Defaults ─────────────────────────────────────────────
ENV="${1:-production}"
MAX_RETRIES="${MAX_RETRIES:-3}"

# ── Main ─────────────────────────────────────────────────
main() {
  echo "Running in env=${ENV}, max_retries=${MAX_RETRIES}"
  echo "Script dir: ${SCRIPT_DIR}"
}

main "$@"

Verificação de conhecimento: comportamento de pipefail

Teste sua compreensão de como pipefail afeta os códigos de saída de uma cadeia de comandos.

Recapitulação: modo estrito com set -euo pipefail

Nesta lição, você aprendeu a fazer os scripts Bash falharem rapidamente e informarem claramente as falhas usando o modo estrito.

Os três sinalizadores e o que eles protegem:

  • -e (errexit) — encerra a execução quando qualquer comando retorna um status diferente de zero; não se aplica a condições nem após ||
  • -u (nounset) — interrompe a execução ao referenciar variáveis não definidas; use ${VAR:-default} para variáveis opcionais
  • -o pipefail — faz toda a cadeia de comandos falhar se qualquer etapa falhar, e não apenas a última

Práticas complementares:

  • Adicione -E (errtrace) para que as armadilhas de ERR sejam propagadas para as funções
  • Use trap em ERR e EXIT para diagnósticos e limpeza
  • Use || true para tolerar falhas intencionalmente
  • Desative temporariamente com set +e dentro de subshells para código legado ou de sondagem

O modo estrito não é uma solução mágica — conheça suas exceções —, mas é o hábito mais eficaz para escrever scripts Bash confiáveis e defensivos.

Perguntas Frequentes

A aula “Modo estrito com set -euo pipefail” é grátis?

Sim — o texto completo de “Modo estrito com set -euo pipefail” é 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 “Modo estrito com set -euo pipefail”?

Ative o comportamento de falha imediata e entenda exatamente quais erros cada opção do modo estrito captura e quais deixa passar. 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 “Modo estrito com set -euo pipefail”?

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. Modo estrito com set -euo pipefail
  2. Manipuladores trap para limpeza e sinais
  3. Arquivos temporários seguros e diretórios de bloqueio
  4. Scripts idempotentes e lógica de novas tentativas com espera progressiva
← Voltar para Linux Command Line & Bash Scripting Mastery