Como obter o efeito de comandos de encadeamento quando eles não podem ser encadeados?

2

Eu quero executar uma série de comandos apenas se o comando anterior tiver sido bem-sucedido. De acordo com Scripts Shell: Perigos de “set -e” para tratamento de erros :

The recommendation is to do your own error checking by stringing together a series of commands with “&&” like this:

mkdir abc &&
cd abc &&
do_something_else &&
last_thing ||
{ echo error >&2; exit 1; }

Na situação em que deve haver alguma lógica de script entre alguns dos comandos (como um loop ou condicionais complexos), qual é a maneira idiomática de capturar o status para uma variável, então use a variável novamente para garantir comandos só executam se os comandos anteriores foram bem sucedidos?

Algo como:

mkdir abc
status=$?
... # do stuff (which might alter $?)
$status && cd abc
status=$?
... # do more stuff
$status && do_something_else
status=$?
... # do even more
$status && last_thing
status=$?
... # do final stuff
$status || { echo error >&2; exit 1; }
    
por Mike Henry 18.01.2018 / 20:37

2 respostas

2

Enquanto escrevia esta pergunta, percebi que uma possível solução seria:

mkdir abc || { echo error >&2; exit 1; }
... # do stuff (which might alter $?)
cd abc || { echo error >&2; exit 1; }
... # do more stuff
do_something_else || { echo error >&2; exit 1; }
... # do even more
last_thing || { echo error >&2; exit 1; }
... # do final stuff

Nesse caso, nenhuma variável $status é necessária e os comandos serão executados somente se os anteriores forem bem-sucedidos. E, eu também percebo, é aqui que uma função die "error message" seria útil para ecoar a mensagem de erro e sair com o código de erro.

Atualizar

Com die , seria:

die() { echo "$*" >&2; exit 1; }

mkdir abc || die "error"
... # do stuff
cd abc || die "error"
... # do more stuff
do_something_else || die "error"
... # do even more
last_thing || die "error"
... # do final stuff
    
por 18.01.2018 / 20:37
3

Uma versão um pouco mais limpa (em meu olho) do que está na resposta auto-fornecida do OP pode ser:

bail() {
  return=${1-1} # if no parameters sent, default to exit code 1
  shift
  echo "$@" 1>&2
  exit $return
}

if mkdir abc; then
  do_stuff
else
  bail 1 "Unable to create directory"
fi
if cd abc; then
  do_stuff
else
  bail 2 "Unable to enter directory"
fi
# et cetera

O crux está dando a cada caso de falha seu próprio código de saída, e essa construção também permite que você faça seu próprio gerenciamento de caso de falha em cada cláusula else antes de disparar bail() .

    
por 18.01.2018 / 21:25