Estoy observando un comportamiento extraño cuando uso set -e
( errexit
), set -u
( nounset
) junto con trampas ERR y EXIT. Parecen relacionados, por lo que ponerlos en una pregunta parece razonable.
1) set -u
no activa trampas ERR
Código:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}
- Esperado: se llama la trampa ERR, RC! = 0
- Real: no se llama la trampa ERR , RC == 1
- Nota:
set -e
no cambia el resultado
2) Usar set -eu
el código de salida en una trampa EXIT es 0 en lugar de 1
Código:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}
- Esperado: se llama la trampa EXIT, RC == 1
- Real: se llama a EXIT trap, RC == 0
- Nota: Cuando se usa
set +e
, el RC == 1. La trampa EXIT devuelve el RC apropiado cuando cualquier otro comando arroja un error. - Editar: hay una publicación SO sobre este tema con un comentario interesante que sugiere que esto podría estar relacionado con la versión Bash que se está utilizando. Probar este fragmento con Bash 4.3.11 da como resultado un RC = 1, por lo que es mejor. Lamentablemente, la actualización de Bash (desde 3.2.51) en todos los hosts no es posible en este momento, por lo que tenemos que encontrar alguna otra solución.
¿Alguien puede explicar cualquiera de estos comportamientos?
La búsqueda de estos temas no tuvo mucho éxito, lo cual es bastante sorprendente dada la cantidad de publicaciones en la configuración y trampas de Bash. Sin embargo, hay un hilo en el foro , pero la conclusión es bastante insatisfactoria.
set -e
y set -u
ambos están diseñados específicamente para matar un shell con script. Usarlos en condiciones que puedan desencadenar su aplicación matará un shell con script. No hay forma de evitar eso, excepto para no usarlos, y en su lugar para probar esas condiciones cuando se aplican en una secuencia de código. Entonces, básicamente, puedes escribir un buen código de shell, o puedes usarlo set -eu
.
-u
qué no dispararía la trampa ERR (es un error, así que no debería disparar la trampa) o el código de error es 0 en lugar de 1. El Esto último parece ser un error que ya se ha solucionado en una versión posterior, así que eso es todo. Pero la primera parte es bastante difícil de entender si no se ha dado cuenta de que los errores en la evaluación de shell (expansión de parámetros) y los errores reales en los comandos parecen ser dos cosas diferentes. Para la solución, bueno, como sugirió, ahora estoy tratando de evitar -eu
y verificar manualmente cuando sea necesario.
(set -u; : $UNSET_VAR)
y similar. Este tipo de cosas también pueden ser buenas, de vez en cuando puedes soltar muchas &&
: (set -e; mkdir dir; cd dir; touch dirfile)
si me entiendes. Es solo que esos son contextos controlados: cuando los configura como opciones globales, pierde el control y se vuelve controlado. Sin embargo, generalmente hay soluciones más eficientes.
bash
rompió con el estándar y comenzó a poner trampas en subcapas. Se supone que la trampa se ejecuta en el mismo entorno de donde vino el regreso, perobash
no lo ha hecho durante bastante tiempo.