O script pai continua quando o filho sai com código de saída diferente de zero [fechado]

4

Eu tenho um script que chama outro script. Quando o script filho falhar, eu gostaria que o pai também falhasse.

No script filho child_1.sh , tenho algo parecido com isto:

if [ $SOME_BAD_CONDITION ] ; then
  echo "Error message...."
  exit 1
fi

No pai, eu tenho isso:

#!/bin/bash
set -e
#...
bash ./child_1.sh
echo "continuing to next step..."
bash ./child_2.sh
bash ./child_3.sh
#...

Configurei meu ambiente para que $SOME_BAD_CONDITION sempre aconteça e o script saia conforme o esperado e a mensagem de erro seja impressa, mas o script pai continua: a mensagem "continuando. .. "é impresso e o próximo script começa a ser executado.

Eu achei que ter set -e garantiria que meu script pai falhasse se qualquer script filho existir com um código de saída diferente de zero, mas isso não parece estar acontecendo. Eu não tenho certeza do que eu tenho errado aqui ...

versão bash: 4.2.25

ATUALIZAÇÃO:

Eu tentei ecoar $? :

bash ./child_1.sh
echo $?
echo "continuing to next step..."

A saída é assim:

Error message....
0
continuing to next step...

Por que o código de saída do filho não é incluído no pai?

ANSWER: O trecho de código original estava incompleto. O exit 1 estava dentro de um bloco de código que foi canalizado para o tee. Minha tentativa de postar uma amostra de código limpa, curta ignorou isso porque eu não percebi o quão significativa ela era (eu ainda sou relativamente novo no bash scripting). Veja minha resposta postada para detalhes.

    
por FrustratedWithFormsDesigner 25.02.2015 / 18:08

3 respostas

1

Então, eu poderia ter cometido um erro ao não postar detalhes suficientes sobre o script filho - simplifiquei para o propósito desta pergunta, mas talvez seja demais. A instrução exit foi enterrada dentro de um bloco de código (entre { e } ) que foi canalizada para tee para criação de log:

{
  #...
  if [ $SOME_BAD_CONDITION ] ; then
    exit 1
  fi
  #...
} | tee -a $LOGFILE
echo "script ended at $date">>$LOGFILE

Pelo que entendi, sempre recebi um código de retorno 0 desse script filho porque o último echo estava retornando 0. Fiz algumas pesquisas e descobri $ PIPESTATUS . Consegui usar isso para garantir que, quando meu script tentasse sair com o código de saída 1, passasse para o script pai:

{
  #...
} | tee -a $LOGFILE
EXIT_CODE=${PIPESTATUS[0]}
echo "script ended at $date">>$LOGFILE
exit $EXIT_CODE

Combinado com a sugestão de John, tenho uma solução que parece estar funcionando.

    
por 25.02.2015 / 20:18
2

Como o seu filho processa a saída com uma convenção de código de saída zero / diferente de zero, e considerando que você os executa sequencialmente, eu diria que você poderia usar apenas o operador && :

#!/bin/bash

./child_1.sh
[[ $? -ne 0 ]] && exit # Exit if non-zero exit code
./child_2.sh
./child_3.sh
./child_4.sh
exit 0

Aqui, [[ $? -ne 0 ]] && exit age como:

if [ $? -ne 0 ]; then # If: last exit code is non-zero
    exit
fi

Se você não tem nada a fazer entre as ligações, você pode até usar ...

#!/bin/bash
./child_1.sh && ./child_2.sh && ./child_3.sh && ./child_4
exit $?

O operador && age como um operador AND de curto-circuito , e um código de saída zero é bonito muito parecido com um valor booleano true . Se a qualquer momento na cadeia, um script sair com um valor diferente de zero, o && falhará e os scripts subsequents não deverão ser chamados.

    
por 25.02.2015 / 18:43
0

Parece que seu problema decorre de como você lança o erro no seu script filho.

De man set "se um comando simples (veja SHELL GRAMMAR acima) sair com um status diferente de zero. O shell não sai se o comando falhar fizer parte da lista de comandos imediatamente após algum tempo ou até a palavra-chave, parte do teste em uma declaração if, parte de uma lista & ou ||, ou se o valor de retorno do comando estiver sendo invertido via! "

Em vez de usar set -e, use uma instrução trap e envie um erro. (Se você precisar usar a saída condicional.

Veja o link

    
por 25.02.2015 / 18:41