Lone Learner Lone Learner - 7 months ago 11
Bash Question

Is pipeline guaranteed to create a subshell in any POSIX shell?

This shell script behaves as expected.

trap 'echo exit' EXIT

foo()
{
exit
}

echo begin
foo
echo end


Here is the output.

$ sh foo.sh
begin
exit


This shows that the script exits while executing
foo
.

Now see the following script.

trap 'echo exit' EXIT

foo()
{
exit
}

echo begin
foo | cat
echo end


The only difference here is that the output of
foo
is being piped into `cat. Now the output looks like the following.

begin
end
exit


This shows that the script does not exit while executing
foo
because
end
is printed.

I believe this happens because in bash a pipeline causes a subshell to be opened, so
foo | cat
is equivalent to
(foo) | cat
.

Is this behaviour guaranteed in any POSIX shell? I could not find anything in the POSIX standard at http://pubs.opengroup.org/onlinepubs/9699919799/ that implies that a pipeline must lead to a subshell. Can someone confirm if this behaviour can be relied upon?

Answer

In 2.12 Shell Execution Environment you find this quote:

A subshell environment shall be created as a duplicate of the shell environment, except that signal traps that are not being ignored shall be set to the default action. Changes made to the subshell environment shall not affect the shell environment. Command substitution, commands that are grouped with parentheses, and asynchronous lists shall be executed in a subshell environment. Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.

Where the key sentence for this question is

Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment

So without the extension (which bash uses for things like lastpipe and, I thought, for the first element in a pipeline as well but apparently not or at least not always) it looks like you can assume there will be a subshell for each part of the pipeline but the exception means you can't quite count on that.