script `source`d de retorno automático em caso de falha no comando

script `source`d de retorno automático em caso de falha no comando

Como faço para que um sourcescript d retorne automaticamente se algum comando dentro dele falhar?

Suponha que eu tenha um script que sai automaticamente em caso de falha via set -e, por exemplo

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

Se eu executar o comando normalmente, ele sairá automaticamente no grepcomando com falha:

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

No entanto, se eu usar sourceo script, ele sairá do meu shell atual, e não apenas do script que está sendo originado:

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

Se eu remover o 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"

então ele não sai nem retorna automaticamente o sourcescript d:

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

A única solução que encontrei até agora é adicionar uma returnexpressão a cada linha de código do script, por exemplo

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 outra maneira para sourcescripts d, semelhante a como set -efunciona para sourcescripts não-d?

Responder1

Quando você sourcecria um script, é como se você estivesse escrevendo aquele arquivo linha por linha no teclado. Isso significa que set -econsiderará o shell atual e que em caso de erro sairá do shell atual.

Essa é uma solução alternativa. Hoje estou com preguiça então pensei que o computador pudesse escrever ||returnpara mim, ou melhor ler linha por linha o arquivo e executar assim:

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

execute-o com. MySource.sh FileToBeSourced.sh

Se seuArquivoToBeSourced.shscript está com comandos de uma linha e deve funcionar.
Muito longe de estar pronto para ser usado em um ambiente de produção.
Teste e eventualmenteuse-o por sua conta e risco.

Ele pula as linhas que começam com #porque deveriam causar o erro # command not found.

informação relacionada