script de retorno automático `fuente` en caso de fallo del comando

script de retorno automático `fuente` en caso de fallo del comando

¿Cómo hago que un sourcescript d regrese automáticamente si falla algún comando dentro de él?

Supongamos que tengo un script que sale automáticamente en caso de error a través de set -e, por ejemplo

#!/bin/bash
# foo.env
set -e        # auto-exit on any command failure
echo "hi"
grep 123 456  # this command will fail (I don't have a file named "456")
echo "should not reach here"

Si ejecuto el comando normalmente, se cerrará automáticamente con el grepcomando fallido:

box1% ./foo.env
hi
grep: 456: No such file or directory

Sin embargo, si ejecuto sourceel script, sale de mi shell actual, no solo del script de origen:

box1% ssh box2
box2% source ./foo.env
hi
grep: 456: No such file or directory
Connection to box2 closed.
box1%

Si elimino el set -e,

#!/bin/bash
# foo2.env
echo "hi"
grep 123 456  # this command will fail (I don't have a file named "456")
echo "should not reach here"

entonces no sale ni regresa automáticamente el sourcescript d en absoluto:

box1% ssh box2
box2% source ./foo2.env
hi
grep: 456: No such file or directory
should not reach here
box2%

La única solución que he encontrado hasta ahora es agregar una returnexpresión a cada línea de código en el script, por ejemplo

box1% cat foo3.env
#!/bin/bash
# foo3.env - works, but is cumbersome
echo "hi" || return
grep 123 456 || return
echo "should not reach here" || return

box1% source foo3.env
hi
grep: 456: No such file or directory
box1%

¿Existe otra forma para sourcelos scripts d, similar a cómo set -efunciona para sourcelos que no son d?

Respuesta1

Cuando escribes sourceun script es como si estuvieras escribiendo ese archivo línea por línea desde el teclado. Significa que set -econsiderará el shell actual y que, en caso de error, saldrá del shell actual.

Esa es una solución. Hoy me da pereza así que pensé que la computadora puede escribir ||returnpor mí, o mejor leer línea por línea el archivo y ejecutar así:

#!/bin/bash
# this is the file MySource.sh
while IFS='' read -r line
do
   [[ $line == \#* ]] || $line || return
done < "$1"

ejecutarlo con. MySource.sh FileToBeSourced.sh

Si tuArchivoToBeSourced.shEl script tiene comandos de una línea, debería funcionar.
Muy, muy lejos de estar listo para ser utilizado en un entorno de producción.
Pruébalo y eventualmenteÚselo bajo su propio riesgo.

Omite líneas que comienzan con #porque deberían causar el error # command not found.

información relacionada