Is it preferred to avoid use of "exit" in bash scripts as much as possible?

9,409

Solution 1

Quoting 'Code Complete'

Use [exit] when it enhances readability In certain routines, once you know the answer, you want to [exit] to the calling routine immediately. If the routine is defined in such a way that it doesn’t require any further cleanup once it detects an error, not [exiting] immediately means that you have to write more code.

So normally one exit is preferred (people looking at your code don't have to find the correct exit statement), however with error checking (especially at the start of a program/routine having multiple exit statements is clearer.

Your example is borderline, however I would say that the second is preferred so that maintenance to your program/script can leave it tidy.

Your program currently is (in psudocode)

if error condition 1
    // Show error message 1
else
    // Do stuff
fi

or

if error condition 1
    // Show error message 1
    // exit
fi

// Do stuff

Once your program has grown, you realise some more ways that the program can fail. Your program now becomes

if error condition 1
    // Show error message 1
else 
    if error condition 2
         // Show error message 2
    else
         if error condition 3
             // Show error message 3
         else
             // Do stuff
         fi
    fi
fi

or maybe

if error condition 1
    // Show error message 1
else if error condition 2
    // Show error message 2
else if error condition 3
    // Show error message 3
else
    // Do stuff
fi

versus

if error condition 1
    // Show error message 1
    // exit
else if error condition 2
    // Show error message 2
    // exit
else if error condition 3
    // Show error message 3
    // exit
fi

// Do stuff

In my mind, the last one is the clearest in being able to spot which is the error cases and which is the main flow of the program. Now add returning different values (eg. 0 on success, 1 on error 1, 2 on error 2, etc.) and the difference will become more pronounced.

Solution 2

I suppose it depends on the script to some extent on your code and what you are trying to accomplish, traps, error handling, etc.

In general you are going to either want to specify an exit status

exit 1

or set -e

#!/bin/bash -e

You can add error management in a variety of ways

command 1 || echo "command 1 failed"

to writing functions to traps.

There are a few nice (introductory) discussions with references :

Solution 3

My preference is this:

#!/bin/bash
if [[ -z "$1" ]]; then
        # Notice that I added quotes and redirection
        echo "You need to enter the directory you want to backup" 1>&2
        exit
fi
# Notice that I fixed the indentation
sourceFile="$1"
targetFile="/home/me/Desktop/myBackups/files_$(date +%Y_%m_%d_%s)"
tar cvf "$targetFile" "$sourceFile"

I think exiting at the point where it's clear that the program can't continue or where it's clearly finished makes for the cleanest code.

On an unrelated note, beware of unquoted strings in Bash. They'll bite you sooner or later. It's a good habit to always surround strings with double quotes (even when it's technically unnecessary) unless you specifically want the unquoted behavior. Also, as long as you're using bash, [[ is much better than [.

Share:
9,409

Related videos on Youtube

user784637
Author by

user784637

Updated on September 18, 2022

Comments

  • user784637
    user784637 over 1 year

    I've been told in php it's preferred to avoid the use of the exit command as much as possible.

    Is the same true for bash?

    For example is the following

    #!/bin/bash
    if [ -z $1 ]; then
            echo You need to enter the directory you want to backup
    else
            sourceFile=$1
            targetFile=/home/me/Desktop/myBackups/files_$(date +%Y_%m_%d_%s)
            tar cvf $targetFile $sourceFile
    fi
    

    Preferred to this?

    #!/bin/bash
    if [ -z $1 ]; then
            echo You need to enter the directory you want to backup
            exit
    fi
            sourceFile=$1
            targetFile=/home/me/Desktop/myBackups/files_$(date +%Y_%m_%d_%s)
            tar cvf $targetFile $sourceFile
    
    • elias
      elias over 12 years
      actually, using exit would be a recommended practice. in the abs-guide, for example, most scripts ends with exit 0.