Como sair de um script de shell se uma parte dele falhar?

Como posso escrever um script de shell que sai, se uma parte dele falhar? Por exemplo, se o snippet de código a seguir falhar, o script deve ser encerrado.

n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3 

Resposta

Uma abordagem seria adicionar set -e ao início do seu script. Isso significa (de help set):

 -e Exit immediately if a command exits with a non-zero status. 

Portanto, se algum de seus comandos falhar, o script será encerrado.

Como alternativa, você pode adicionar instruções exit explícitas nos possíveis pontos de falha:

command || exit 1 

Comentários

  • Eu (e o wiki bash ) prefiro que as pessoas pensem no tratamento de erros adequado em vez de usar o recurso (quebrado por design IMO) set -e. Mas não ' realmente se aplica aqui. O OP deseja sair do script após 5 tentativas falhadas de executar o comando.
  • @St é phaneChazelas eu ganhei ' discuto com você se ele ' está quebrado, eu ' tenho certeza de que ' re certo. No entanto, o OP perguntou " Como posso escrever um script de shell que sai, se uma parte dele falhar? ", o que o torna acho que ' é sobre sair após 5 falhas?
  • porque eu não posso ' pensar em qualquer outra forma de pergunta pode ser interpretada.
  • @St é phaneChazelas você pode muito bem estar certo. Eu interpretei literalmente: como todo o script pode sair se alguma parte dele falhar. E set -e é a única maneira que conheço de fazer isso.
  • Nesse fragmento de script, os comandos que podem acionar set -e é sleep (break sendo um builtin especial faria com que o script fechasse em caso de falha na maioria dos shells, comandos em if ou à esquerda de && não são afetados por set -e, n=... poderia falhar se n fosse somente leitura, mas então isso sairia do script sem set -e também), de modo que interpretação parece bastante improvável. Eu concordo que a pergunta está mal formulada.

Resposta

Você pode sair de um script em qualquer lugar usando a palavra-chave exit. Você também pode especificar um código de saída para indicar a outros programas que ou como seu script falhou, por exemplo, exit 1 ou exit 2 etc. (Por convenção, o código de saída 0 é para sucesso e qualquer coisa maior que 0 significa falha; no entanto, também por convenção , os códigos de saída acima de 127 são reservados para finalização anormal (por exemplo, por um sinal)).

A construção genérica para sair em caso de falha é

if [ failure condition ]; then exit n fi 

com failure condition e n adequados. Mas em cenários específicos, você pode proceder de forma diferente. Agora, para o seu caso, interpreto sua pergunta de que se qualquer uma das cinco invocações de gksu falhar, você pretende sair. Uma maneira é usar uma função como esta

function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 } 

e, em seguida, invocar o loop por try_command.

Existem maneiras (mais) avançadas ou sofisticadas de como responder à sua pergunta. No entanto, a solução acima é mais acessível para iniciantes do que, digamos, a solução de Stephane.

Resposta

attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done 

exit sai do script a menos que seja chamado em um subshell. Se essa parte do script estiver em um subshell, por exemplo, porque está dentro de (...) ou $(...) ou parte de uma tubulação , então ele só sairá daquele subshell .

Nesse caso, se você quiser que o script saia além do subshell, você ” Vou precisar chamar exit na saída desse subshell.

Por exemplo, aqui com 2 níveis aninhados de subshells:

( life=hard output=$( echo blah [ "$life" = easy ] || exit 1 # exit subshell echo blih not run ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status echo not run either ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status 

Pode se tornar mais complicado se o subshell fizer parte de um pipeline. bash tem uma matriz $PIPESTATUS especial, semelhante a zsh “s $pipestatus que pode ajudá-lo aqui:

{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi 

Resposta

O Trap executará uma ação ao receber um sinal.

trap "echo EXIT; exit" 0 trap "echo HUP; exit" 1 trap "echo CTL-C; exit" 2 trap "echo QUIT; exit" 3 trap "echo ERR; exit" ERR n=0 until [ $n -ge 5 ] do n=$[$n+1] echo $n sleep 3 done 

Execute e deixe-o sair normalmente. Ele intercepta o sinal 0.

EXIT 

Execute-o novamente e interrompa com ^ C. Ele intercepta os sinais 2 e 0.

CTL-C EXIT 

Um status de saída diferente de zero irá interceptar ERR

ERR EXIT 

Resposta

pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )& 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *