0Pricing
Linux Command Line & Bash Scripting Mastery · Lección

Modo estricto con set -euo pipefail

Active un comportamiento de fallo inmediato y comprenda exactamente qué errores detecta y cuáles omite cada opción del modo estricto.

Modo estricto con set -euo pipefail es una lección gratuita de Linux Command Line & Bash Scripting Mastery en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Linux Command Line & Bash Scripting Mastery, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Linux Command Line & Bash Scripting Mastery incluye 4 lecciones en total.

Por qué Bash falla silenciosamente de forma predeterminada

De forma predeterminada, Bash sigue ejecutándose aunque fallen los comandos. Esto provoca problemas sutiles y difíciles de depurar en los scripts de producción.

Considere este script, que intenta crear una copia de seguridad:

  • Un error tipográfico en una ruta hace que cp falle.
  • Bash ignora el fallo y continúa.
  • El script informa de que todo se realizó correctamente aunque los datos nunca se hayan respaldado.

Este es el problema de los fallos silenciosos. El modo estricto lo resuelve haciendo que Bash se comporte como un lenguaje compilado: se detiene inmediatamente cuando algo sale mal.

#!/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

Las tres opciones principales: set -euo pipefail

El modo estricto se activa colocando esta línea cerca del principio de cada script:

set -euo pipefail

Esto activa tres mecanismos de protección distintos:

  • -e — Sale inmediatamente si algún comando devuelve un estado distinto de cero.
  • -u — Trata las variables no definidas como un error (en lugar de expandirlas a una cadena vacía).
  • -o pipefail — Una canalización falla si falla cualquier comando que la compone, no solo el último.

Juntas forman la cabecera defensiva estándar de los scripts Bash serios. Cada opción detecta una clase distinta de errores.

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

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

Cómo funciona set -e (errexit)

set -e (también escrito como set -o errexit) hace que el script termine inmediatamente cuando un comando finaliza con un estado distinto de cero.

Comportamientos importantes que debe conocer:

  • Los comandos simples como false, grep pattern file (sin coincidencias) y ls /nonexistent provocan la salida.
  • El código de salida del último comando del script se convierte en el código de salida del script.
  • Los comandos de las condiciones de if están exentos; -e no se activa para la expresión de prueba.
  • Los comandos seguidos de || true también están exentos (consulte las escenas siguientes).

Considere -e como su primera línea de defensa para evitar continuar silenciosamente después de un fallo.

#!/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"

Cómo funciona set -u (nounset)

set -u (también escrito como set -o nounset) hace que Bash trate cualquier referencia a una variable no definida como un error fatal.

Sin -u, un error tipográfico como $FLENAME en lugar de $FILENAME se expande silenciosamente a una cadena vacía, lo que hace que los comandos se comporten de forma inesperada o peligrosa (imagine rm -rf "$TMPDIR/" cuando $TMPDIR no está definida).

Excepciones importantes:

  • ${VAR:-default} — sustitución segura con un valor predeterminado; no activa -u.
  • ${VAR:+value} — expansión condicional, también segura.
  • "$@" y "$*" están exentos cuando no se pasan argumentos posicionales.
#!/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

Cómo funciona -o pipefail

Sin pipefail, el estado de salida de una canalización depende únicamente del último comando. Los fallos anteriores se ignoran silenciosamente.

Ejemplo sin pipefail:

  • cat /missing/file | wc -l
  • cat falla con el código de salida 1, pero wc -l finaliza correctamente con el código 0.
  • La canalización devuelve 0: ¡éxito! Aunque se hayan perdido datos.

Con pipefail activado, Bash devuelve el código de salida del último comando que haya fallado. Esto hace que los fallos de las canalizaciones sean visibles y detectables.

Nota: pipefail no es una opción de una sola letra; debe configurarse con -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"

Fallos intencionados de comandos: uso de || true

A veces se permite que un comando falle. Con set -e, debe indicar explícitamente los fallos tolerados; de lo contrario, el script se interrumpe.

La solución idiomática es || true, que añade una alternativa que siempre tiene éxito:

  • command || true — ignora completamente el fallo.
  • command || echo "Warning: step failed, continuing" — registra un mensaje y continúa.
  • command || { echo "fatal"; exit 1; } — gestiona el fallo de forma personalizada.

Este patrón hace explícita su intención en el código: un comando sin más significa «debe ejecutarse correctamente»; || true significa «puede fallar y no pasa nada».

#!/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"

Qué NO detecta set -e

set -e tiene excepciones y riesgos conocidos. Comprenderlos evita una falsa sensación de seguridad:

  • Comandos en condiciones de if / while / until — la expresión de prueba está exenta por diseño.
  • Comandos negados con ! — ! false no provoca la salida.
  • El último comando antes de || — por ejemplo, false || handle_error.
  • El estado de salida de subshells en determinados contextos — por ejemplo, VAR=$(failing_command) en algunas versiones de Bash.
  • Valores de retorno de las funciones — solo cuenta el último comando de una función.

El modo estricto no sustituye a la comprobación explícita de errores; es una red de seguridad que detecta la mayoría de los fallos accidentales.

#!/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"

Subshells y funciones con el modo estricto

La configuración del modo estricto se hereda en los subshells, pero se comporta de forma sutil en las funciones y las sustituciones de comandos.

Reglas principales:

  • Las funciones heredan -e, -u y pipefail del shell que las invoca.
  • Un retorno distinto de cero de una función hace que el proceso que la invoca termine (cuando -e está configurado), salvo si la llamada está en una condición o después de ||.
  • Sustitución de comandos $(): en versiones antiguas de Bash, un comando fallido dentro de $() puede no activar -e en el proceso principal; para mayor seguridad, asigne el resultado y utilícelo por separado.
  • Los subshells explícitos () heredan todas las opciones.
#!/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"

Combinación del modo estricto con la captura de errores

El modo estricto indica a Bash cuándo detenerse. Un trap sobre ERR le permite ejecutar tareas de limpieza o diagnóstico antes de que termine el script.

El patrón habitual es:

  • Configurar el modo estricto al principio.
  • Definir una función cleanup o on_error.
  • Registrarla con trap 'on_error' ERR.
  • Opcionalmente, capturar también EXIT para garantizar la limpieza independientemente de que la ejecución termine correctamente o con un error.

Importante: utilice set -E (E mayúscula, también llamado errtrace) para que la captura de ERR también se herede en las funciones y los subshells; sin esta opción, las capturas solo se ejecutan en el cuerpo del 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"

Desactivación local del modo estricto

A veces un bloque de código es intencionadamente «desordenado», por ejemplo, al comprobar si hay herramientas opcionales o ejecutar comandos antiguos que devuelven un valor distinto de cero por motivos que no indican un error. Puede desactivar temporalmente el modo estricto y restaurarlo después.

El patrón seguro:

  • Guarde el estado con set +e (desactiva -e), ejecute el bloque y vuelva a activarlo con set -e.
  • O utilice un subshell ( set +e; ... ) para que las opciones del shell principal nunca se vean afectadas.
  • Vuelva a activar siempre las opciones en cuanto termine el bloque de riesgo; dejar las opciones desactivadas es una fuente habitual de errores.

Prefiera la forma con subshell cuando el bloque incluya varios comandos, ya que restaura automáticamente las opciones al salir.

#!/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

Plantilla completa de un script con modo estricto

Esta es una plantilla lista para producción que reúne todas las prácticas recomendadas del modo estricto tratadas en esta lección:

  • set -Eeuo pipefail — las cuatro opciones, incluida errtrace.
  • IFS=$'\n\t' — división de palabras más segura (evita dividir por espacios).
  • Capturas ERR + EXIT para diagnósticos y limpieza.
  • Valores predeterminados explícitos para los parámetros opcionales.
  • readonly y local para limitar el ámbito de las variables.

Copie esta plantilla al principio de cada script Bash no trivial para beneficiarse de inmediato de un comportamiento de fallo rápido y de errores rastreables.

#!/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 "$@"

Comprobación de conocimientos: comportamiento de pipefail

Compruebe su comprensión de cómo pipefail afecta a los códigos de salida de las tuberías.

Repaso: modo estricto con set -euo pipefail

En esta lección ha aprendido a hacer que los scripts de Bash fallen rápidamente y de forma explícita mediante el modo estricto.

Las tres opciones y lo que controlan:

  • -e (errexit) — sale ante cualquier estado de comando distinto de cero; se omite en condiciones y después de ||
  • -u (nounset) — aborta ante referencias a variables no definidas; use ${VAR:-default} para variables opcionales
  • -o pipefail — hace que falle toda la tubería si falla cualquier etapa, no solo la última

Prácticas complementarias:

  • Añada -E (errtrace) para que las trampas ERR se propaguen a las funciones
  • Use trap con ERR y EXIT para diagnósticos y limpieza
  • Use || true para tolerar fallos de forma intencionada
  • Desactívelo temporalmente con set +e dentro de subshells para código heredado o de prueba

El modo estricto no es una solución mágica — conozca sus excepciones—, pero es el hábito más eficaz para escribir scripts de Bash fiables y defensivos.

Preguntas frecuentes

¿La lección «Modo estricto con set -euo pipefail» es gratis?

Sí — el texto completo de «Modo estricto con set -euo pipefail» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Linux Command Line & Bash Scripting Mastery, actualiza a CoddyKit PRO. El curso de Linux Command Line & Bash Scripting Mastery incluye 4 lecciones en total.

¿Qué aprenderé en «Modo estricto con set -euo pipefail»?

Active un comportamiento de fallo inmediato y comprenda exactamente qué errores detecta y cuáles omite cada opción del modo estricto. Practicas Linux Command Line & Bash Scripting Mastery con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Linux Command Line & Bash Scripting Mastery?

No se requiere experiencia previa. Linux Command Line & Bash Scripting Mastery en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Modo estricto con set -euo pipefail»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Linux Command Line & Bash Scripting Mastery?

Sí. Cada lección de Linux Command Line & Bash Scripting Mastery incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Modo estricto con set -euo pipefail
  2. Controladores trap para limpieza y señales
  3. Archivos temporales seguros y directorios de bloqueo
  4. Scripts idempotentes y lógica de reintento con backoff
← Volver a Linux Command Line & Bash Scripting Mastery