Considere os comandos
eval false || echo ok
echo also ok
Normalmente, esperamos que ele execute o false
utilitário e, como o status de saída é diferente de zero, execute echo ok
e echo also ok
.
Em todo o POSIX-como conchas que eu uso ( ksh93
, zsh
, bash
, dash
, OpenBSD ksh
, e yash
), este é o que acontece, mas as coisas começam a ficar interessantes, se permitir set -e
.
Se set -e
estiver em vigor, o OpenBSD sh
e os ksh
shells (ambos derivados de pdksh
) encerrarão o script ao executar o eval
. Nenhum outro shell faz isso.
O POSIX diz que um erro em um utilitário interno especial (como eval
) deve fazer com que o shell não interativo seja encerrado. Não tenho certeza se a execução false
constitui "um erro" (se fosse, seria independente de set -e
estar ativo).
A maneira de contornar isso parece ser colocar o eval
sub-shell,
( eval false ) || echo ok
echo also ok
A questão é se devo fazer isso em um script shell POSIX-ly correto ou se é um bug no shell do OpenBSD? Além disso, o que significa "erro" no texto POSIX vinculado acima?
Informações extras: Os shells do OpenBSD executam os echo ok
dois com e sem set -e
no comando
eval ! true || echo ok
Meu código original parecia
set -e
if eval "$string"; then
echo ok
else
echo not ok
fi
que não saída not ok
com string=false
usando as conchas do OpenBSD (seria terminar), e eu não tinha certeza que era por design, por engano ou por mal-entendido, ou qualquer outra coisa.
eval false
gera um status diferente de zero, então eu esperariaset -e
terminar o script nesse ponto. No caso de!
set -e
não se aplica, a!
instrução verifica explicitamente o status de saída.eval false
finalizar o script mesmo que faça parte de uma lista AND-OR ou de uma declaração condicional? Eu não faria.set -e
está definido se esse é o comportamento correto ... Concordo que faz sentido não terminar em uma declaração condicional.set -e
então o `()` é a resposta.Respostas:
O fato de nenhum outro shell precisar dessa solução alternativa é uma forte indicação de que é um bug no OpenBSD ksh. De fato, o ksh93 não mostra esse problema.
O fato de haver um
||
na linha de comando deve evitar a saída do shell causada por um código de retorno 1 no lado esquerdo dele.O erro de um built-in especial deve causar a saída de um shell não interativo de acordo com o POSIX, mas isso nem sempre é verdadeiro. Tentar
continue
sair de um loop é um erro econtinue
está embutido. Mas a maioria das conchas não sai:Um interno que emite um erro claro, mas não sai.
Portanto, a saída ativada
false
é gerada pelaset -e
condição e não pela característica interna do comando (eval
neste caso).As condições exatas nas quais a
set -e
saída deve ser bem mais imprecisa no POSIX.fonte
[desculpe se esta não for uma resposta real, eu a atualizarei quando for contornada]
Eu dei uma olhada no código fonte e minhas conclusões são:
1) É um bug / limitação, nada filosófico por trás disso.
2) A "correção" para isso do fork portátil do ksh (
mksh
) do OpenBSD é muito ruim, apenas piorando as coisas, sem realmente corrigi-lo:Novo bug, diferente de todos os outros shells:
Ainda não está realmente corrigido:
Você pode substituir
bash
acima, comdash
,zsh
,yash
,ksh93
, etc.fonte