2

How can I have my shell script echo to me that the script that it calls has failed?

#!/bin/sh

test="/Applications/test.sh"

sh $test

exit 0
exit 1
3
  • Does test.sh follow the convention of returning 0 on success and non-zero otherwise? Commented Feb 25, 2013 at 23:47
  • yes it does test.sh also has exit 0 exit 1 Commented Feb 25, 2013 at 23:49
  • Only the first exit would do anything in your example; the second is never reached, because you've already exited with the first. Commented Feb 26, 2013 at 0:01

3 Answers 3

3
#!/bin/sh

if sh /Applications/test.sh; then
    echo "Well done $USER"
    exit 0
else
    echo "script failed with code [$?]" >&2
    exit 1
fi

The /Applications/test.sh script should be well coded to exit with conventional status. 0 if it's ok and > 0 if it fails.

Like you can see, no need to test the special variable $?, we use boolean expression directly.

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

Comments

1

I usually take the following approach:

#!/usr/bin/env bash

test="/Applications/test.sh"
sh "${test}"
exit_status=$?
if [[ ${exit_status} ]] ; then
    echo "Error: ${test} failed with status ${exit_status}." >&2
else
    echo "Success!"
fi

5 Comments

+1, but using [[ will fail if /bin/sh is a primitive shell (eg, not bash). Safer to do: if ! test $exit_status = 0; then. Also, the failure message should probably be directed to stderr.
$? is often used like in this post by noobs because they don't understands if true; then ...; else ...; fi
@sputnick: …or by people who want to first test and then report the value.!
You can report the value with: if $test; then echo Success; else echo "Error: $test failed with status $?" >&2; fi There's no need to for the exit_status variable.
@WilliamPursell: You can. I find my format more readable. Also, if another command gets added into the then block, it will still work.
0

In terms of best practice, you should not. If a script fails, it should emit an error message before it terminates so that its parent doesn't have to. The main reason for this is that the process knows why it is failing, while the parent can only guess. In other words, you should just write:

#!/bin/sh

test="/Applications/test.sh"

sh $test

Although really, it would be more typical to just write:

#!/bin/sh
/Applications/test.sh

test.sh will emit the necessary error message, and your script will return the same value as did test.sh. Also, in its current form your script will always be successful, even if test.sh actually failed because exit 0; exit 1 is pretty pointless: the exit 1 will never be called.

1 Comment

Unfortunately, not all third-party scripts are so well behaved and sometimes it's necessary to wrap them.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.