leaf

Two examples of errexit

This post presents two different examples of the errexit option from the sh(1) shell. Each example exhibits a different behavior, although at a glance it would be easy to mistake the two examples as being the same.

In POSIX shell scripts - the errexit option can be used to enter a mode of operation where any "untested command" that exits unsuccessfully will cause the script that spawned the command to immediately exit as well.

There are at least two ways to enter the errexit mode of operation; either via an argument given directly to the sh(1) executable or within a script via the set(1) command.

Example 1

The first example provides the errexit option to the sh(1) executable via the script's shebang line.

The script spawns a subshell by surrounding a command in parenthesis, and the command exits unsuccessfully. Perhaps surprisingly script execution continues as normal. Keep in mind the script would have exited as expected if a subshell had not been used:

#!/bin/sh -e

# 'realpath' exits unsuccessfully
(realpath /path/does/not/exist)

# But we reach here anyway
echo "reached"

Example 2

The second example provides the errexit option via the set(1) command. The script spawns a subshell which will exit unsuccessfully, and perhaps as you would have expected, script execution does not proceed past that point:

#!/bin/sh
set -e

# 'realpath' exits unsuccessfully
(realpath /path/does/not/exist)

# And we never reach here
echo "unreached"

Conclusion

We can conclude that the set(1) command propagates the errexit option to subshells. The errexit option doesn't propagate when given to the sh(1) executable as an argument. My default is almost always to set errexit via the set(1) command for this very reason.