coderelliot
coderelliot

Reputation: 501

Exception handling for a particular exit_code in shell scripting?

i understood that

a_command || fallback_command

It will catch any non zero exit_code from command_a (i.e when command_a fails) and will run fallback_commad. How to achieve this for some particular codes? How to make it work like when a_command throws 255 only then run fallback_command ?

I tried to do something like

a_command
VAR=$?
if [ $VAR==255 ]
then
    fallback_command
    exit 0
fi

But this will not suppress the non zero errors thrown by command_a. I want to suppress the non zero exit_codes.

Upvotes: 2

Views: 436

Answers (7)

Stanley Yu
Stanley Yu

Reputation: 101

To play nice with set -e and traps:

set -e

trap cleanup ERR

cleanup () {
    echo cleaning up
}

a_command && rc=0 || rc=$?
case $rc in
    0)
        # no error handling needed
        ;;

    255)
        # handle error code 255
        fallback_command
        ;;
    254)
        # handle error code 254
        another_fallback_command
        ;;
    *)
        # unhandled error code; subshell used so we can trigger `set -e`
        # and any associated traps without exiting directly
        (exit "$rc")
        ;;
esac

If no traps on ERR are used, we can just exit directly like set -e normally would:

set -e

a_command && rc=0 || rc=$?
case $rc in
    0)
        # no error handling needed
        ;;

    255)
        # handle error code 255
        fallback_command
        ;;
    254)
        # handle error code 254
        another_fallback_command
        ;;
    *)
        # unhandled error code; exit like `set -e` normally would
        exit "$rc"
        ;;
esac

Upvotes: 0

coderelliot
coderelliot

Reputation: 501

Well after trying a bit i found out a way

a_command || export ECODE="$?"    # Here non zero exit codes are suppressed.

if [ "$ECODE" -eq 255 ]

then
    fallback_command
fi

Upvotes: 0

user1934428
user1934428

Reputation: 22356

Your code will always execute the fallback_command. The reason is that test x always succeeds, if x is not empty. As an example, assume that VAR equals 100, so you basically do a test 100==255, and since the string 100==255 is not empty (it has a length of 8 characters), the condition suceeds.

You could do something like:

if (( VAR > 127 ))
then
  # There was a problem starting the program
  ....
elif (( VAR == 72 || VAR >118 ))
then
  # Deal with exit codes 72 and 119 up to 127
  .....
elif (( VAR > 0 ))
  # Deal with all other non-zero exit codes
  ....
fi

Upvotes: 0

Léa Gris
Léa Gris

Reputation: 19675

As simple as this with maintaining the inline boolean or ||:

a_command || [ $? -ne 255 ] || fallback_command

Testing the implementation:

#!/usr/bin/env bash

a_command_success(){ echo 'running a_command_success';}
a_command_failing_42(){ echo 'running a_command_failing_42'; return 42;}
a_command_failing_255(){ echo 'running a_command_failing_255'; return 255;}

fallback_command(){ echo 'running fallback_command';}

for a_command in a_command_success a_command_failing_255 a_command_failing_42
do "$a_command" || [ $? -ne 255 ] || fallback_command; done

Output of test:

running a_command_success
running a_command_failing_255
running fallback_command
running a_command_failing_42

Going further with a fall_back caller utility command:

# When return code equals argument 1, execute command and arguments 2+
# Example:
# a_command || falllback_rc 255 fallback_command arg1 arg2 ... argn
fallback_rc(){ [ "$?" -eq "$1" ]&&{ shift;"$@";}}

Upvotes: 1

ATR
ATR

Reputation: 107

You can just do with an if instruction:

command_a

if test $? = 255

then

   fallback_command

fi

One one line :

command_a ; if test $? = 255 ; then fallback_command ; fi

Upvotes: 0

Ivan
Ivan

Reputation: 7317

IMHO case is perfect for this

a_command
VAR=$?
case $VAR in
    255) fallback_command ;;
    123) fallback_command2;;
    ...) ...   ;;
      0) exit 0;;
esac

Upvotes: 3

MichalH
MichalH

Reputation: 1074

You have one mistake in your code. [ $VAR==255 ] will always be true, because it is the same as this:

[ string ]
Returns true if string is not empty.

If you want to compare numbers, use -eq:

if [ $VAR -eq 255 ]

Similarly, to test equality of strings you would use:

if [ $VAR = 255 ]

In your case you want to use -eq.

This page can help: https://www.computerhope.com/unix/bash/test.htm

Upvotes: 1

Related Questions