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
cpfalhar - 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 destructiveOs 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
ifsão isentos —-enão é acionado para a expressão de teste - Comandos seguidos por
|| truetambé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 variableEntendendo -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 -lcatfalha com o código de saída 1, maswc -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 falhacommand || echo "Warning: step failed, continuing"— registra um aviso e continuacommand || { 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
!—! falsenã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,-uepipefaildo shell que as chama - Um retorno diferente de zero de uma função faz o chamador sair (quando
-eestá 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-eno 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
cleanupouon_error - Registrá-la com
trap 'on_error' ERR - Opcionalmente, também capturar
EXITpara 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 comset -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"
fiUm 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, incluindoerrtraceIFS=$'\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
readonlyelocalpara 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
trapemERReEXITpara diagnósticos e limpeza - Use
|| truepara tolerar falhas intencionalmente - Desative temporariamente com
set +edentro 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
- Modo estrito com set -euo pipefail
- Manipuladores trap para limpeza e sinais
- Arquivos temporários seguros e diretórios de bloqueio
- Scripts idempotentes e lógica de novas tentativas com espera progressiva