set -efinaliza o script se um código de saída diferente de zero for encontrado, exceto sob certas condições. Para resumir os perigos de seu uso em poucas palavras: não se comporta como as pessoas pensam.
Na minha opinião, deve ser considerado um hack perigoso que continua a existir apenas para fins de compatibilidade. A set -einstrução não transforma o shell de uma linguagem que usa códigos de erro em uma linguagem que usa o fluxo de controle do tipo exceção, apenas tenta emular mal esse comportamento.
Greg Wooledge tem muito a dizer sobre os perigos de set -e:
No segundo link, existem vários exemplos do comportamento não intuitivo e imprevisível de set -e.
Alguns exemplos do comportamento não intuitivo de set -e(alguns extraídos do link wiki acima):
set -e
x = 0
deixe x ++
eco "x é $ x"
O exemplo acima fará com que o script shell saia prematuramente, porque let x++retorna 0, que é tratado pela letpalavra - chave como um valor falso e transformado em um código de saída diferente de zero. set -enota isso e termina silenciosamente o script.
set -e
[-d / opt / foo] && echo "Aviso: o foo já está instalado. Será substituído." > & 2
eco "Instalando foo ..."
O procedimento acima funciona como esperado, imprimindo um aviso, se /opt/foojá existir.
set -e
check_previous_install () {
[-d / opt / foo] && echo "Aviso: o foo já está instalado. Será substituído." > & 2
}
check_previous_install
eco "Instalando foo ..."
O que foi dito acima, apesar da única diferença de que uma única linha foi refatorada em uma função, terminará se /opt/foonão existir. Isso ocorre porque o fato de ter funcionado originalmente é uma exceção especial ao set -ecomportamento de. Quando a && bretorna diferente de zero, é ignorado por set -e. No entanto, agora que é uma função, o código de saída da função é igual ao código de saída desse comando e a função que retorna diferente de zero encerra silenciosamente o script.
set -e
IFS = $ '\ n' lê-d '' -r -a config_vars <config
O acima irá ler a matriz config_varsdo arquivo config. Como o autor pretende, ele termina com um erro se configestiver faltando. Como o autor pode não pretender, ele termina silenciosamente se confignão terminar em uma nova linha. Se set -enão fosse usado aqui, config_varsconteria todas as linhas do arquivo, terminando ou não em uma nova linha.
Usuários de texto sublime (e outros editores de texto que lidam com novas linhas incorretamente), tenha cuidado.
set -e
should_audit_user () {
grupos de grupos locais = "$ (groups" $ 1 ")"
para grupo em $ groups; Faz
if ["$ group" = auditoria]; então retorne 0; fi
feito
retorno 1
}
if should_audit_user "$ user"; então
madeireiro 'Blah'
fi
O autor aqui pode esperar razoavelmente que, se por algum motivo o usuário $usernão existir, o groupscomando falhará e o script será encerrado em vez de permitir que o usuário execute alguma tarefa não auditada. No entanto, nesse caso, a set -erescisão nunca entra em vigor. Se $usernão puder ser encontrado por algum motivo, em vez de encerrar o script, a should_audit_userfunção retornará dados incorretos como se set -enão estivessem em vigor.
Isso se aplica a qualquer função chamada da parte da condição de uma ifinstrução, não importa quão profundamente aninhada, não importa onde seja definida, não importa mesmo se você executar set -edentro dela novamente. O uso ifa qualquer momento desativa completamente o efeito de set -eaté que o bloco de condições seja totalmente executado. Se o autor não está ciente dessa armadilha ou não conhece toda a pilha de chamadas em todas as situações possíveis em que uma função pode ser chamada, ele escreverá um código de buggy e a falsa sensação de segurança fornecida por set -eserá pelo menos parcialmente culpa.
Mesmo que o autor esteja totalmente ciente dessa armadilha, a solução alternativa é escrever o código da mesma maneira que se escreveria sem set -e, tornando efetivamente essa troca menos que inútil; não apenas o autor precisa escrever o código de tratamento manual de erros como se set -enão estivesse em vigor, mas a presença de set -epode ter enganado-os a pensar que não precisam.
Algumas desvantagens adicionais de set -e:
- Ele incentiva código desleixado. Os manipuladores de erros são completamente esquecidos, na esperança de que tudo que falhou reportará o erro de alguma maneira sensata. No entanto, com exemplos como
let x++acima, este não é o caso. Se o script morre inesperadamente, geralmente é silencioso, o que dificulta a depuração. Se o script não morrer e você esperava (veja o ponto anterior), você tem um bug mais sutil e insidioso em suas mãos.
- Isso leva as pessoas a uma falsa sensação de segurança. Veja novamente o
ifmarcador de condição.
- Os locais onde o shell termina não são consistentes entre os shells ou as versões do shell. É possível escrever acidentalmente um script que se comporte de maneira diferente em uma versão mais antiga do bash devido ao comportamento de
set -eter sido ajustado entre essas versões.
set -eé uma questão controversa, e algumas pessoas cientes dos problemas que a cercam recomendam, enquanto outras recomendam tomar cuidado enquanto estiver ativo para conhecer as armadilhas. Existem muitos iniciantes em scripts de shell que recomendam set -eem todos os scripts um exemplo geral para condições de erro, mas na vida real isso não funciona dessa maneira.
set -e não substitui a educação.