8

I'm writing a script that needs to be executed using source, because its task is to modify the environment. During the script, I want to use set -e so that any error stops the script. The script looks like this:

#!/bin/bash
set -e
# do something
cd somewhere
source anotherScript

The problem is that set -e naturally remains in effect after the script finishes. How can I ensure that the altered set option is properly restored to its prevous value when the script stops (in any way - either by completing successfully or on an error)?

3

Exactly the same way you activate it: calling the buitin set:

$ set -o errexit
$ set -o | grep errexit
errexit         on
$ set +o errexit
$ set -o | grep errexit
errexit         off

From the bash(1) manpage, under the SHELL BUILTIN COMMANDS section, `set' command:

-o option-name
The option-name can be one of the following:
    errexit Same as -e.
  • 3
    Is there a way how to save (all) these settings and restore them later? – Petr Pudlák Sep 21 '13 at 10:04
  • Run set -o to known your current setup. Be explicit when setting/unsetting any of them on your scripts. – dawud Sep 21 '13 at 10:12
11

The command set +o lists the current settings as commands that restore the same state, e.g.

$ set +o
set +o allexport
set -o braceexpand
set -o emacs
set +o errexit
set +o errtrace
...

You can easily restore all the options later, if you save this output to a shell variable:

SAVED_OPTIONS=$(set +o)
set -e
# do something
eval "$SAVED_OPTIONS"

Bash includes also a number of non-standard (not POSIX) options that are adjusted using shopt command. The command shopt -p can be used to save these options in a similar fashion.

If you only want to save and restore one option, you can use the $- environment variable, which lists the current set of options as letters, e.g.

$ echo $-
himBH

You could use something like this to save and restore a particular option:

[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e
  • Note that it's very important not to miss the quotes around "$SAVED_OPTIONS" in the eval call. – Matt Jun 6 '18 at 16:47
0

Use a RETURN trap

RETURN traps work for sourced scripts, too.

Commands specified with an RETURN trap are executed before execution resumes after a shell function or a shell script executed with . or source returns.

https://www.gnu.org/software/bash/manual/bash.html

main_script.sh

#!/usr/bin/env bash
echo "inside main script"
shopt -o errexit
source a_script_to_be_sourced.sh
echo "back inside main script"
shopt -o errexit

a_script_to_be_sourced.sh

trap "$(shopt -p -o errexit)" RETURN
set -e # Equivalents: set -o errexit; shopt -s -o errexit
echo "inside sourced script"
shopt -o errexit

Test

$ ./main_script.sh 
inside main script
errexit         off
inside sourced script
errexit         on
back inside main script
errexit         off
0

Restoring previous activated settings can be quickly done as:

PREV_SETTING=$-  # e.g. himxBH  (there was xtrace)

set +x
# do your script without xtrace, ...

set -$PREV_SETTING

The other way around (restore to the off state) AFAIK there isn't such a shortcut and Seppo's answer covers all cases.

  • Your code as written yields -bash: set: -i: invalid option because the -i flag notes an interactive shell. – dpw Jul 8 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.