Masuk Pavel
Masuk Pavel

Reputation: 23

shell exit function for set -e

I have a script.command file with a shell script inside, so that I can double click it to execute in a new terminal window. When it finishes the script it automatically closes regardless of the exit code. Back in the days I used to put ifs after every troublesome command like this:

iCanCouseError
if [[ $? -ne 0 ]]; then
    read -p "Press enter to close"
    exit 1
fi

This was keeping the terminal open until I press a button, so that I could read the logs and determine what caused an exception.

But now I switched to a much more convenient method: set -e at the beginning of the file. It automatically exits the script with an error code if any command fails. But now I can't read logs before the terminal closes. I wonder if there is some way to set an exit function in addition to set -e that will always execute right before script exits, so that I could put read command there to stop terminal from closing in case of non-zero exit code.

Upvotes: 1

Views: 52

Answers (2)

Ed Morton
Ed Morton

Reputation: 203502

Consider not using set -e as it's a mess (see https://mywiki.wooledge.org/BashFAQ/105) and also consider setting a trap to do something different for success vs other exit statuses instead of putting code below your "real" code, something like:

sig_handler() {
    exit_status=$?
    echo "Doing signal-specific stuff"
    exit "$exit_status"
}

trap sig_handler INT HUP TERM QUIT

iCanCouseError

Google for better alternative trap functions/usage, there are plenty of suggestions out there for you to choose from dependent on what you want to do.

Upvotes: 1

J_H
J_H

Reputation: 20450

Package up your commands in a separate "iCanCauseError" executable script file that starts with a shebang.

Then iCanCauseError || read -p "Press enter" suffices.

A zero exit value will be interpreted as True, satifying the short-circuiting OR operator, so it doesn't have to evaluate that second disjunct. Notice that we have a separate Bash child running the commands, rather than say a (subshell) or function within current shell.


Also, when setting -e, you might as well set this:

set -e -o pipeline

Imagine you do grep x y | sort | awk ... | wc -l, and the awk script bombs out with non-zero exit status. The effect of setting the pipeline option is to make that fatal, similar to how set -e makes non-zero status fatal for single command. It's just less surprising.

And while you're at it, the unrelated set -u may be of interest. This will do variable interpolation: echo ${HOME}/. But imagine there's a typographic error, so we accidentally get just a / slash output: echo ${HOMS}/. The "unset variable" -u setting will make that typo a fatal error.

Upvotes: 1

Related Questions