O script bash com `set -e` não para no comando`… &&… `


13

Eu uso set -epara parar o script bash no primeiro erro .

Todos funcionam bem, a menos que eu use o comando com &&:

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$

comparado com:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$

O primeiro exemplo ainda ecoa I'm running!, mas o segundo não. Por que eles se comportam de maneira diferente?

UPD. Pergunta semelhante: /programming/6930295/set-e-and-short-tests


O que você espera que aconteça no primeiro exemplo?
Flup 27/09/16

@Flup Espero que o script pare após um cdcomando malsucedido
907th 27/09/16

1
Veja o BashFAQ # 105 para uma discussão geral de lugares onde o set -ecomportamento é surpreendente.
Charles Duffy

Respostas:


9

Este é um comportamento documentado. A página do manual bash (1) diz, para set -e,

O shell não será encerrado se o comando que falhar fizer parte da lista de comandos imediatamente após uma palavra while- untilchave ou , parte do teste após as palavras reservadas ifou parte de qualquer comando executado em uma lista ou, exceto o comando após o final ou qualquer comando em um pipeline, mas o último, ou se o valor de retorno do comando estiver sendo invertido . [Enfase adicionada.]elif&&||&&||!

E a especificação de linguagem de comando do shell POSIX confirma que este é o comportamento correto:

o -e configuração será ignorada durante a execução da lista seguinte composto a while, until, ifou elifpalavra reservada, um gasoduto começando com a !palavra reservada, ou qualquer comando de um AND-OR lista que não seja o último.

e a Seção 2.9.3 Listas desse documento define

Uma lista AND-OR é uma sequência de um ou mais pipelines separados pelos operadores " &&" e "|| ".


9

A set -eopção não tem efeito em algumas situações, e esse é o comportamento padrão e portátil através do shell compatível com POSIX.


O comando com falha faz parte do pipeline:

false | true; echo printed

irá imprimir printed .

E apenas a falha do pipeline é considerada:

true | false; echo 'not printed'

não imprimirá nada.


A corrida comando falhou na lista seguinte composto a while, until, if, elifpalavra reservada, um gasoduto começando com a !palavra reservada, ou qualquer comando como parte de &&ou ||lista, exceto o último:

false || true; echo printed

O último comando que falha ainda torna set -eafetado:

true && false; echo 'not printed'

O subshell falha em um comando composto:

(false; echo 'not printed') | cat -; echo printed

Obrigado! Seria mais claro usar echo "printed"e echo "not_printed"nos seus exemplos (em vez de echo 1).
907th 27/09/16

3
Observe que isso set -ecausa uma saída dentro (false && true); echo not here, mas não dentro { false && true; }; echo here, apesar de YMMV com shells diferentes e até versões diferentes de um mesmo shell. Eu não tocaria set -ecom um poste de barcaça e, em vez disso, faria o tratamento adequado de erros.
Stéphane Chazelas

1

meu palpite é que a condição se-então é avaliada como um todo.

eu tentei

set -e
if cd not_existing_dir
then  echo 123
fi
echo "I'm running! =P"

quem dá

-bash: cd: not_existing_dir: No such file or directory
I'm running! =P

o código de erro é capturado pela condição if, portanto, o bash não acionará o fim da execução.


Mas eu não usoif ... fi
907th

Eu sei, isso é implícito se.
Archemar 27/09
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.