Parent script continues when child exits with non-zero exit code

14,397

Solution 1

So, I might have made an error in not posting enough details about the child script - I simplified it for the purpose of this question, but maybe too much. The exit statement was buried inside a code block (between { and }) which was piped to tee for logging:

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

From what I understand, I always got a return code of 0 from this child script because the last echo was returning 0. I did some research and discovered $PIPESTATUS. I was able to use this to ensure that when my script tried to exit with exit code 1, it would be passed up to parent script:

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

Combined with John's suggestion, I have a solution that seems to be working.

Solution 2

Since your child processes exit with a proper zero/non-zero exit code convention, and given that you execute them sequentially, I'd say you could just use the && operator:

#!/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

Here, [[ $? -ne 0 ]] && exit acts like:

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

If you don't have anything to do between the calls, you could even use...

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

The && operator acts like a short-circuit AND operator, and a zero exit code is pretty much like a true boolean value. If at any time in the chain, a script exits with non-zero, the && will fail, and subsequents scripts shouldn't be called.

Share:
14,397

Related videos on Youtube

FrustratedWithFormsDesigner
Author by

FrustratedWithFormsDesigner

SOreadytohelp

Updated on September 18, 2022

Comments

  • FrustratedWithFormsDesigner
    FrustratedWithFormsDesigner over 1 year

    I have a script that calls another script. When the child script fails, I'd like the parent to fail as well.

    In the child script child_1.sh, I have something like this:

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

    In the parent, I have this:

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

    I've set up my environment so that $SOME_BAD_CONDITION will always happen, and the script exits as expected and the error message does print, but the parent script continues: the message "continuing..." is printed and the next script begins executing.

    I thought that having set -e would ensure that my parent script fails if any child script exists with a non-zero exit code, but that doesn't seem to be happening. I'm not sure what I got wrong here...

    bash version: 4.2.25


    UPDATE:

    I tried echoing $?:

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

    The output looks like this:

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

    Why doesn't the exit code from the child make it into the parent?


    ANSWER: The original code snippet was incomplete. The exit 1 was inside a code block that was piped to tee. My attempt to post a clean, short code sample ignored this because I did not realize how significant it was (I'm still fairly new to bash scripting). See my posted answer for details.

    • FrustratedWithFormsDesigner
      FrustratedWithFormsDesigner over 9 years
      @StéphaneChazelas: 4.2.25
    • Stéphane Chazelas
      Stéphane Chazelas over 9 years
      Do you see the problem with that simple script, or only when there's more in that #... ellipsis after set -e?
    • Stéphane Chazelas
      Stéphane Chazelas over 9 years
      Does child_1.sh have a trap on EXIT? Did you try adding a echo "$?" after bash ./child_1.sh?
    • FrustratedWithFormsDesigner
      FrustratedWithFormsDesigner over 9 years
      @StéphaneChazelas: No trap in the child. I tried printing $? and it's always 0.
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' over 9 years
      The part that you posted looks fine, the issue is therefore in some part that you didn't post. Post some runnable code that would let us reproduce the problem.
    • FrustratedWithFormsDesigner
      FrustratedWithFormsDesigner over 9 years
      @Gilles: The fault was mine: I over-simplified the code in the example to make it easier to read, and omitted code that I didn't think had an effect. I solved my own problem, see here: unix.stackexchange.com/a/186853/104235 ;)
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' over 9 years
      @FrustratedWithFormsDesigner Then you need to edit the question to demonstrate the problem. As it is, this question won't help anyone, since people facing the same problem won't be able to tell that it's the same problem.
  • FrustratedWithFormsDesigner
    FrustratedWithFormsDesigner over 9 years
    I added a debugging statement to print the value of $? and it prints 0. It looks like the exit code from the child script does not get picked up by the parent script.
  • yorkshiredev
    yorkshiredev over 9 years
    @FrustratedWithFormsDesigner There must be a problem with your child script. I tried it myself just now, and my parent script did get the correct exit code back. Make sure your child script exits as you expect it to.
  • FrustratedWithFormsDesigner
    FrustratedWithFormsDesigner over 9 years
    Yes, you were right, I had a problem in the child script.
  • FrustratedWithFormsDesigner
    FrustratedWithFormsDesigner over 9 years
    Yes, you were right. I had a problem in the child script, but it seems I over-simplified the child script in the original post, which is why no one caught it.