11

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)?

2

4 Answers 4

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.
2
  • 4
    Is there a way how to save (all) these settings and restore them later?
    – Petr
    Sep 21, 2013 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, 2013 at 10:12
17

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
1
  • Note that it's very important not to miss the quotes around "$SAVED_OPTIONS" in the eval call.
    – Matt
    Jun 6, 2018 at 16:47
3

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
2

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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .