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

907º
fonte
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
related: stackoverflow.com/questions/25794905/…
Ciro Santilli escreveu

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 "|| ".

G-Man diz que 'restabelece Monica'
fonte
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
cuonglm
fonte
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.

Archemar
fonte
Mas eu não usoif ... fi
907th
Eu sei, isso é implícito se.
Archemar 27/09