2

The exit statements in each status check if statement do not break the while loop and truly exit the script. Is there something I can do to break the loop and exit with that $STATUS code?

EDIT: I've updated my code and it still isn't working. The status check if statements successfully break the loop but when I try to evaluate the $EXIT_STATUS it's always null, likely having something to do with scope. What am I missing here?

  if [ $RESTART -le $STEP ]; then
  . tell_step

  while read XML_INPUT; do

    XML_GDG=`get_full_name $GDG_NAME P`

    cp $XML_INPUT $XML_GDG


    STATUS=$?
    EXIT_STATUS=$STATUS
    if [ $STATUS -ne 0 ]; then
      break
    fi

    add_one_gen $XML_GDG

    STATUS=$?
    EXIT_STATUS=$STATUS
    if [ $STATUS -ne 0 ]; then
      break
    fi

  done < $XML_STAGE_LIST

  echo $EXIT_STATUS
  if [ $EXIT_STATUS -ne 0 ]; then
    exit $EXIT_STATUS
  fi

fi
8
  • quick comment - hard to read a script with soo many UPPERCASES. Try reserve the uppercase names for some "special" variables (or better, only for exported ones).. Commented Jul 23, 2013 at 12:49
  • 1
    Use break instead of exit. Commented Jul 23, 2013 at 12:49
  • @fedorqui break will exit the loop but will not exit the script with the status, I'm essentially trying to do both. Commented Jul 23, 2013 at 12:51
  • 1
    And what about storing the exit status in a variable (exit_status=$STATUS) in those cases and then exiting with it exit $exit_status? Commented Jul 23, 2013 at 12:52
  • @fedorqui Good call, that should work. Commented Jul 23, 2013 at 12:55

4 Answers 4

7

I had the same problem: when piping into a while loop, the script did not exit on exit. Instead it worked like "break" should do.

I have found 2 solutions:

a) After your while loop check the return code of the while loop and exit then:

somecommand | while something; do
    ...
done
# pass the exit code from the while loop
if [ $? != 0 ]
then
    # this really exits
    exit $?
fi

b) Set the bash script to exit on any error. Paste this at the beginning of your script:

set -e
Sign up to request clarification or add additional context in comments.

Comments

3

Not really understand why your script dosn't exits on exit, because the next is works without problems:

while read name; do
    echo "checking: $name"
    grep $name /etc/passwd >/dev/null 2>&1
    STATUS=$?
    if [ $STATUS -ne 0 ]; then
        echo "grep failed for $name rc-$STATUS"
        exit $STATUS
    fi
done <<EOF
root
bullshit
daemon
EOF

running it, produces:

$ bash testscript.sh ; echo "exited with: $?"
grep failed for bullshit rc-1
exited with: 1

as you can see, the script exited immediatelly and doesn't check the "daemon".

Anyway, maybe it is more readable, when you will use bash functions like:

dostep1() {
    grep "$1:" /etc/passwd >/dev/null 2>&1
    return $?
}

dostep2() {
    grep "$1:" /some/nonexistent/file >/dev/null 2>&1
    return $?
}

err() {
    retval=$1; shift;
    echo "$@" >&2 ; return $retval
}

while read name
do
    echo =checking $name=
    dostep1 $name || err $? "Step 1 failed" || exit $?
    dostep2 $name || err $? "Step 2 failed" || exit $?
done

when run like:

echo 'root
> bullshit' | bash testexit.sh; echo "status: $?"
=checking root=
Step 2 failed
status: 2

so, step1 was OK and exited on the step2 (nonexisten file) - grep exit status 2, and when

echo 'bullshit
bin' | bash testexit.sh; echo "status: $?"
=checking bullshit=
Step 1 failed
status: 1

exited immediatelly on step1 (bullshit isn't in /etc/passwd) - grep exit status 1

Comments

0

You'll need to break out of your loop and then exit from your script. You can use a variable which is set on error to test if you need to exit with an error condition.

Comments

0

I had a similar problem when pipelining. My guess is a separate shell is started when piplining. Hopefully it helps someone else who stumbles across the problem.

From jm666's post above, this will not print 'Here I am!':

while read name; do
   echo "checking: $name"
   grep $name /etc/passwd >/dev/null 2>&1
   STATUS=$?
   if [ $STATUS -ne 0 ]; then
      echo "grep failed for $name rc-$STATUS"
      exit $STATUS
   fi
done <<EOF
root
yayablah
daemon
EOF

echo "Here I am!"

However the following, which pipes the names to the while loop, does. It will also exit with a code of 0. Setting the variable and breaking doesn't seem to work either (which makes sense if it is another shell). Another method needs to be used to either communicate the error or avoid the situation in the first place.

cat <<EOF |
root
yayablah
daemon
EOF
while read name; do
   echo "checking: $name"
   grep $name /etc/passwd >/dev/null 2>&1
   STATUS=$?
   if [ $STATUS -ne 0 ]; then
      echo "grep failed for $name rc-$STATUS"
      exit $STATUS
   fi
done

echo "Here I am!"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.