Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In bash shell -E option explanation, what does "any trap inherited by a subshell environment" mean?

Tags:

bash

bash-trap

This is from the manual for bash set options (for set -E)

-E

If set, any trap on ERR is inherited by shell functions, command substitutions, and commands executed in a subshell environment. The ERR trap is normally not inherited in such cases.

What does "trap on ERR" mean? what does "trap on ERR is inherited by shell functions in a subshell environment"? Can a shell script proceed even after the trap and the trap is passed to a subshell? Can someone elaborate on this with a simple example, please?

like image 373
Chan Kim Avatar asked Oct 28 '25 04:10

Chan Kim


1 Answers

The Bash manual on trap says:

trap [-lp] [arg] [sigspec …]

If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status, subject to the following conditions. The ERR trap is not executed if the failed command is part of the command list immediately following an until or while keyword, part of the test following the if or elif reserved words, part of a command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted using !. These are the same conditions obeyed by the errexit (-e) option.

The material you quote says that trap '…' ERR is not normally inherited by a shell function, a command substitution or commands executed in a subshell environment. However, if you use set -E, then the ERR trap is inherited.

The sentence means:

  • If set -E is set, then any trap on ERR is inherited by shell functions.
  • If set -E is set, then any trap on ERR is inherited by command substitutions.
  • If set -E is set, then any trap on ERR is inherited by commands executed in a subshell environment.

The 'in a subshell environment' clause does not apply to shell functions or command substitutions.

I can't parse your question "Can a shell script proceed even after the trap and the trap is passed to a subshell?" A shell script can proceed after a trap — what happens depends on the commands in the arg part of the trap command.

Here's a shell script that demonstrates set -E in action:

#!/bin/bash
#
# SO 6485-2814 'trap ERR and set -E'

trap 'echo TRAP ERR >&2' ERR

echo begin-ls
ls /non-existent
echo end-ls

func()
{
    echo begin-func
    ls /non-existent
    echo end-func
}

echo invoke-func
func
echo finish-func

echo begin-substitution
echo $(date): $(ls /non-existent)
echo end-substitution

echo begin-subshell
(ls /non-existent)
echo end-subshell

set -E

echo invoke-func
func
echo finish-func

echo begin-substitution
echo $(date): $(ls /non-existent)
echo end-substitution

echo begin-subshell
(ls /non-existent)
echo end-subshell

When run, it produces:

begin-ls
ls: /non-existent: No such file or directory
TRAP ERR
end-ls
invoke-func
begin-func
ls: /non-existent: No such file or directory
end-func
finish-func
begin-substitution
ls: /non-existent: No such file or directory
Sun Nov 15 23:16:25 MST 2020:
end-substitution
begin-subshell
ls: /non-existent: No such file or directory
end-subshell
invoke-func
begin-func
ls: /non-existent: No such file or directory
TRAP ERR
end-func
finish-func
begin-substitution
ls: /non-existent: No such file or directory
Sun Nov 15 23:16:25 MST 2020:
end-substitution
begin-subshell
ls: /non-existent: No such file or directory
end-subshell

As you can see, the ERR trap fires on the failing ls command run on its own, but doesn't fail when run in a function or in a subshell or as part of (some) command substitutions.

When the set -E option is set, the ERR trap fires when the command failed in the function, in the subshell, and in the command substitution.

Curiously, the ERR trap does fire in a command substitution like x=$(ls /non-existent) but not in the more complex example shown above. I'm not clear whether that's supposed to happen. I'm using GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18) — it's possible that later versions of Bash (4.x) do not behave the same.

like image 114
Jonathan Leffler Avatar answered Oct 29 '25 23:10

Jonathan Leffler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!