Direct answers
- No. In Bash 5.2 with
set -e but without pipefail, a pipeline exits with the status of its last command. If cmd3 succeeds, the script continues even if cmd1 or cmd2 failed.
- Only the subshell exits. A subshell
(cmd1 | cmd2 | cmd3) that encounters a failing pipeline under set -e will terminate, but the parent shell continues execution. The subshell's exit status is available in $? afterward.
- No material difference. Bash 4.x and 5.x share the same pipeline exit-status semantics for
set -e. Bash 4.4 tightened set -e in command substitution and a few subshell contexts, but pipeline behavior remained unchanged.
Why this happens
POSIX defines a pipeline's exit status as that of its last command. Bash follows this unless set -o pipefail is enabled. set -e only triggers when a simple command or pipeline returns non-zero in a context where its status is checked. Without pipefail, the pipeline's status is zero if the last command succeeds, so set -e sees no failure.
Subshells inherit set -e at creation time. When a subshell exits due to set -e, that exit is confined to the subshell; the parent treats the subshell as a single command whose exit status it can inspect.
Verification you can run
# 1. Pipeline without pipefail — script continues
bash -c 'set -e; false | true; echo "still running"'
# Output: still running
# 2. Same pipeline with pipefail — script exits
bash -c 'set -e; set -o pipefail; false | true; echo "still running"'
# Output: (nothing; exits before echo)
# 3. Subshell with failing pipeline — parent continues
bash -c 'set -e; (false | true); echo "parent continues, subshell status: $?"'
# Output: parent continues, subshell status: 1
Practical workaround
If you need the script to abort on any pipeline component failure and cannot enable pipefail globally, run each command separately and check $? explicitly, or enable pipefail only around the critical pipeline:
set -e
# ...
set -o pipefail
cmd1 | cmd2 | cmd3
set +o pipefail
Version assumption
Behavior described applies to Bash 4.0 through 5.2+. If you are using a strict POSIX sh (e.g., dash), pipeline failure may trigger set -e differently — test on your target shell.