Resolución de Errores Comunes de Sintaxis en Bash: Una Guía Práctica
Corrige errores comunes de sintaxis en Bash con ejemplos para comillas, corchetes, variables, redirecciones y problemas de búsqueda de comandos.
Resolución de Errores Comunes de Sintaxis en Bash: Una Guía Práctica
Los errores de sintaxis en Bash suelen deberse a pequeños descuidos: una comilla faltante, un corchete incorrecto, una redirección mal colocada o una variable que se expandió de forma inesperada. Cuando tu script de Bash se detiene con syntax error near unexpected token, comienza revisando la línea anterior a la que Bash reporta, luego ejecuta el script con una verificación de sintaxis.
Usa esta verificación rápida antes de ejecutar un script modificado en un servidor:
bash -n script.sh
bash -n analiza el archivo sin ejecutar comandos. No detectará todos los errores lógicos, pero sí muchos problemas de comillas rotas, declaraciones fi faltantes y bucles mal formados.
Comillas Faltantes
Las comillas sin cerrar son una de las formas más rápidas de confundir al analizador.
nombre="desplegar
printf 'Desplegando %s\n' "$nombre"
Bash sigue leyendo líneas posteriores porque aún está buscando la " de cierre. Soluciónalo cerrando la comilla y citando las expansiones de variables que puedan contener espacios:
nombre="desplegar"
printf 'Desplegando %s\n' "$nombre"
Usa comillas dobles cuando quieras que las variables se expandan. Usa comillas simples cuando quieras texto literal:
printf 'HOME se mantiene literal: $HOME\n'
printf "HOME se expande: %s\n" "$HOME"
Bloques if, for y while Incorrectos
Cada comando compuesto necesita su palabra clave de cierre. Si falta una, a menudo se reporta el error cerca del final del archivo.
if systemctl is-active --quiet nginx; then
echo "nginx está funcionando"
# falta fi
Versión corregida:
if systemctl is-active --quiet nginx; then
echo "nginx está funcionando"
fi
El mismo patrón aplica para bucles y declaraciones case:
for host in web1 web2 web3; do
ssh "$host" uptime
done
case "$env" in
prod) echo "producción" ;;
dev) echo "desarrollo" ;;
*) echo "desconocido" ;;
esac
Errores de Corchetes y Pruebas
El comando [ es un comando real, por lo que necesita espacios alrededor de sus argumentos y antes del corchete de cierre.
Incorrecto:
if [$count -gt 5]; then
echo "demasiados"
fi
Corregido:
if [ "$count" -gt 5 ]; then
echo "demasiados"
fi
Para scripts específicos de Bash, [[ ... ]] suele ser más seguro para pruebas de cadenas porque maneja variables vacías de manera más elegante y admite coincidencia de patrones:
if [[ "$archivo" == *.log ]]; then
gzip "$archivo"
fi
Usa operadores numéricos para números y operadores de cadena para texto:
[[ "$estado" == "listo" ]] # comparación de cadenas
[[ "$reintentos" -lt 3 ]] # comparación numérica
Problemas de Expansión de Variables
Un error común es agregar espacios alrededor de = durante la asignación. Bash lo trata como un comando en lugar de una asignación de variable.
Incorrecto:
directorio_backup = /var/backups
Corregido:
directorio_backup=/var/backups
Usa llaves cuando el nombre de la variable toque otro texto:
servicio="nginx"
log="/var/log/${servicio}.log"
Sin llaves, Bash podría leer un nombre de variable más largo del que pretendías.
Errores de command not found
command not found no siempre es un error de sintaxis. Generalmente significa que Bash no pudo encontrar un ejecutable con ese nombre.
Primero verifica errores tipográficos:
systemctl status nginx
Luego verifica si el comando existe y está en PATH:
command -v systemctl
printf '%s\n' "$PATH"
Si el script se ejecuta bajo cron, systemd o un trabajo de CI, PATH puede ser más corto que en tu shell interactiva. Usa rutas absolutas para comandos críticos o establece PATH cerca del inicio del script:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export PATH
Errores de Redirección y Tuberías
El orden de redirección importa. Este comando escribe stdout en app.log y luego envía stderr al mismo lugar:
./deploy.sh >app.log 2>&1
Este es diferente porque stderr se copia al stdout anterior antes de que stdout sea redirigido:
./deploy.sh 2>&1 >app.log
Para tuberías, recuerda que Bash normalmente devuelve el código de salida del último comando. Usa pipefail cuando un comando fallido en medio debería fallar toda la tubería:
set -o pipefail
kubectl get pods | grep CrashLoopBackOff
Un Flujo de Depuración Práctico
Comienza con una verificación de sintaxis:
bash -n script.sh
Ejecuta con seguimiento cuando la sintaxis sea válida pero el comportamiento sea incorrecto:
bash -x script.sh
Para scripts de producción más seguros, agrega el modo estricto deliberadamente y prueba el script después de cada cambio:
set -euo pipefail
set -e sale en muchos fallos de comandos, set -u trata las variables no definidas como errores, y pipefail detecta fallos dentro de tuberías. Estas opciones son útiles, pero pueden cambiar el comportamiento del script, así que actívalas intencionalmente en lugar de agregarlas a un script antiguo sin probar.
Conclusión
La mayoría de los errores de sintaxis en Bash se vuelven simples una vez que verificas comillas, palabras clave de cierre, espaciado de corchetes, asignaciones de variables y redirecciones en ese orden. Mantén bash -n y bash -x en tu flujo de trabajo habitual, y prueba los scripts con el mismo shell y entorno que se ejecutará en producción.