Como parar o script quando uma condição falha?

10

Aqui ele mostra para usar o || e && em uma única linha para concatenar a execução de comandos: Como posso verificar erros do apt-get em um script bash?

Estou tentando interromper a execução de um script se uma determinada condição falhar

por exemplo.

false || echo "Obvious error because its false on left" && exit

Aqui imprime Obvious error because its false on the left e sai da consola que é o que eu queria.

true || echo "This shouldn't print" && exit

Aqui, não há impressão de eco, mas o comando exit também é executado, ou seja, o console é fechado, o comando exit não deve ser executado porque o comando echo à direita não foi executado? Ou é por padrão uma declaração considerada falsa no lado esquerdo de um operador && ?

Editar: Eu deveria ter mencionado isso antes, meu objetivo era ecoar o erro e sair se não estivesse claro. w.r.t ao meu caso específico de captura de erros ao agrupar condições usando & amp; & amp; e ||, @ bodhi.zazen answer resolve o problema.

A resposta @takatakatek torna mais claro o controle de fluxo e os links do guia bash são excelentes

@muru answer tem uma boa explicação de por que não usar set -e se você quiser que mensagens de erro personalizadas sejam lançadas com alternativas de usar perl e trap que eu acho que é uma maneira mais robusta e me ver usando do segundo bash roteiro em diante!

    
por kosol 13.06.2017 / 02:10

4 respostas

10

Você provavelmente quer (como apontado por steeldriver)

true || { echo "This shouldn't print" && exit; }

Caso contrário, seu script está lendo uma condicional no momento

a ou be sair

Eu acho que você quer um ou (be sair)?

    
por Panther 13.06.2017 / 02:52
13

O problema é que || e & amp; & amp; Ignore apenas uma sub-rotina subseqüente de uma cadeia de comandos quando a condição falhar. Se você escrever uma estrutura de bloco completa, faz todo o sentido. O que você escreveu se torna isso:

if ! true ; then
   echo "This shouldn't print"
else
   exit
fi

O que você quer é isto:

if ! true ; then
   echo "This shouldn't print"
   exit
fi

Quando você estiver usando os operadores condicionais de atalho do Bash, é melhor evitar misturá-los. A lógica é muito mais fácil de entender enquanto você está escrevendo, e seus leitores irão apreciar seu bom estilo.

por takatakatek 13.06.2017 / 03:03
7

A maneira mais simples de falhar no erro é usar a opção -e do bash ( set -e ou /bin/bash -e no shebang). No entanto, isso não facilita o envio de mensagens de erro personalizadas. Existem alguns idiomas que podem simplificar:

die à la Perl

Perl tem um die command muito conveniente que imprime uma mensagem para stderr e gera uma exceção, que geralmente leva ao término do script. Você pode imitar isso:

die () {
  ret=$?
  print "%s\n" "$@" >&2
  exit "$ret"
}

false || die "Obvious error because its false on left"
true || die "This shouldn't print"

trap ERR

O comando trap <command> pode ser usado para executar um comando quando um sinal é recebido ou ao sair do script ( trap ... EXIT ) ou quando um comando retorna um erro ( trap ... ERR ). Então, algo como:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

Então:

ERR_MSG="Obvious error because its false here"
false
ERR_MSG="This shouldn't print"
true

Em ambos os casos, sugiro usar pelo menos exit 1 , para indicar que o script falhou . Um exit simples usará o status de saída do comando anterior, que nesses casos seria o comando echo ou printf , que normalmente seria bem-sucedido. Salvar o status de saída do comando com falha como eu fiz aqui seria uma boa ideia.

    
por muru 13.06.2017 / 08:56
5

Você poderia experimentar um pouco com o início do script com

#!/bin/bash -e

O -e garante que o script saia no momento em que algo retorna falso. Uma falha específica pode ser evitada com something || true

    
por aggregate1166877 13.06.2017 / 03:22