bashreturnreturn-valueconventionscanonical-form

Given a main function and a cleanup function, how (canonically) do I return an exit status in Bash/Linux?


Context:

I have a bash script (a wrapper for other scripts, really), that does the following pseudocode:

do a main function
if the main function returns:
    $returncode = $? #most recent return code
if the main function runs longer than a timeout:
    kill the main function
    $returncode = 140 #the semi-canonical "exceeded allowed wall clock time" status

run a cleanup function
if the cleanup function returns an error: #nonzero return code
    exit $? #exit the program with the status returned from the cleanup function
else #cleanup was successful
    ....

Question:

What should happen after the last line?

If the cleanup function was successful, but the main function was not, should my program return 0 (for the successful cleanup), or $returncode, which contains the (possibly nonzero and unsuccessful) return code of the main function?

For a specific application, the answer would be easy: "it depends on what you need the script for."

However, this is more of a general/canonical question (and if this is the wrong place for it, kill it with fire): in Bash (or Linux in general) programming, do you typically want to return the status that "means" something (i.e. $returncode) or do you ignore such subjectivities and simply return the code of the most recent function?

This isn't Bash-specific: if I have a standalone executable of any kind, how, canonically should it behave in these cases? Obviously, this is somewhat debatable. Even if there is a system for these things, I'm sure that a lot of people ignore it. All the same, I'd like to know.

Cheers!


Solution

  • Return the exit code from main. As the user of your script, I want to know if it did its job, not whether it cleaned up after failure. In fact, I expect programs/scripts clean up properly when they fail, so returning 0 would be misleading.

    Lazily-written scripts just return with whatever exit code their last command happened to have. Well-written ones make sure to return a meaningful exit code.


    By the way, my favorite way to ensure proper cleanup is to run a cleanup function on trap EXIT.

    WORKING_DIR=$(mktemp -d)
    
    cleanUp() {
        rm -rf "$WORKING_DIR"
    }
    
    # Run cleanUp() when the script exits, whether that's from a SIGTERM/SIGINT or
    # just exiting normally.
    trap cleanUp EXIT