Existem mais algumas maneiras de abordar esse problema. Assumindo que um de seus requisitos é executar um script / função de shell contendo alguns comandos de shell e verificar se o script foi executado com êxito e lançar erros em caso de falhas.
Os comandos do shell geralmente dependem de códigos de saída retornados para permitir que o shell saiba se foi bem-sucedido ou falhou devido a alguns eventos inesperados.
Então, o que você quer fazer recai nessas duas categorias
- saia por erro
- sair e limpar em caso de erro
Dependendo de qual você deseja fazer, existem opções de shell disponíveis para uso. Para o primeiro caso, o shell oferece uma opção com set -e
e para o segundo você pode fazer um trap
onEXIT
Devo usar exit
em meu script / função?
O uso exit
geralmente aumenta a legibilidade Em certas rotinas, depois de saber a resposta, você deseja sair para a rotina de chamada imediatamente. Se a rotina for definida de tal maneira que não exija nenhuma limpeza adicional depois de detectar um erro, não sair imediatamente significa que você terá que escrever mais código.
Portanto, nos casos em que você precisa fazer ações de limpeza no script para fazer o encerramento do script limpo, é preferível não usar exit
.
Devo usar set -e
para erro ao sair?
Não!
set -e
foi uma tentativa de adicionar "detecção automática de erros" ao shell. Seu objetivo era fazer com que o shell abortasse sempre que um erro ocorresse, mas ele vem com muitas armadilhas potenciais, por exemplo,
Os comandos que fazem parte de um teste if são imunes. No exemplo, se você espera que ele interrompa a test
verificação do diretório inexistente, não iria, ele vai para a condição else
set -e
f() { test -d nosuchdir && echo no dir; }
f
echo survived
Os comandos em um pipeline diferente do último são imunes. No exemplo abaixo, porque o código de saída do comando executado mais recentemente (mais à direita) é considerado ( cat
) e foi bem-sucedido. Isso poderia ser evitado definindo pela set -o pipefail
opção, mas ainda é uma advertência.
set -e
somecommand that fails | cat -
echo survived
Recomendado para uso - trap
na saída
O veredicto é se você deseja ser capaz de lidar com um erro em vez de sair cegamente, em vez de usar set -e
, use um trap
no ERR
pseudo sinal.
A ERR
armadilha não é executar o código quando o próprio shell sai com um código de erro diferente de zero, mas quando qualquer comando executado por aquele shell que não faz parte de uma condição (como em if cmd
ou cmd ||
) sai com um status de saída diferente de zero .
A prática geral é definir um manipulador de trap para fornecer informações adicionais de depuração sobre qual linha e o que causa a saída. Lembre-se de que o código de saída do último comando que causou o ERR
sinal ainda estaria disponível neste ponto.
cleanup() {
exitcode=$?
printf 'error condition hit\n' 1>&2
printf 'exit code returned: %s\n' "$exitcode"
printf 'the command executing at the time of the error was: %s\n' "$BASH_COMMAND"
printf 'command present on line: %d' "${BASH_LINENO[0]}"
# Some more clean up code can be added here before exiting
exit $exitcode
}
e apenas usamos este manipulador como abaixo no topo do script que está falhando
trap cleanup ERR
Juntando isso em um script simples que continha false
na linha 15, as informações que você obteria como
error condition hit
exit code returned: 1
the command executing at the time of the error was: false
command present on line: 15
O trap
também fornece opções independentemente do erro para apenas executar a limpeza na conclusão do shell (por exemplo, o script de shell sai), no sinal EXIT
. Você também pode capturar vários sinais ao mesmo tempo. A lista de sinais suportados para trap pode ser encontrada na página de manual trap.1p - Linux
Outra coisa a observar seria entender que nenhum dos métodos fornecidos funciona se você estiver lidando com subshells envolvidos, nesse caso, você pode precisar adicionar seu próprio tratamento de erros.
Em um sub-shell com set -e
não funcionaria. O false
é restrito ao sub-shell e nunca é propagado para o shell pai. Para fazer o tratamento de erros aqui, adicione sua própria lógica para fazer(false) || false
set -e
(false)
echo survived
O mesmo acontece com trap
também. A lógica abaixo não funcionaria pelos motivos mencionados acima.
trap 'echo error' ERR
(false)