Bash subshell/pipelines - which parts are executing in subshells?

Indeed, the braces are executed in a new subshell, but only if piped. The first command is with cat, the second without:

xxx@yyy:~$ ps; X=PQR; echo $X; { ps; X=ABC; echo $X; } | cat; ps; echo $X
  PID TTY          TIME CMD
 6768 pts/7    00:00:00 bash
13158 pts/7    00:00:00 ps
PQR
  PID TTY          TIME CMD
 6768 pts/7    00:00:00 bash
13159 pts/7    00:00:00 bash
13160 pts/7    00:00:00 cat
13161 pts/7    00:00:00 ps
ABC
  PID TTY          TIME CMD
 6768 pts/7    00:00:00 bash
13162 pts/7    00:00:00 ps
PQR
xxx@yyy:~$ ps; X=PQR; echo $X; { ps; X=ABC; echo $X; }; ps; echo $X
  PID TTY          TIME CMD
 6768 pts/7    00:00:00 bash
13239 pts/7    00:00:00 ps
PQR
  PID TTY          TIME CMD
 6768 pts/7    00:00:00 bash
13240 pts/7    00:00:00 ps
ABC
  PID TTY          TIME CMD
 6768 pts/7    00:00:00 bash
13245 pts/7    00:00:00 ps
ABC

In this case 6768 is the PID of the terminal shell, and 13159 is the PID of the subshell started for the braces.

It seems that {} are executed in a subshell if (and only if) piped.


Each side of a pipeline becomes a subshell at least.

X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X

will make a subshell/process of , atleast { X=ABC; echo $X; } and cat.

"Each command in a pipeline is executed as a separate process (i.e., in a subshell)." , from man bash

If you instead do this

X=PQR; echo $X; { X=ABC; echo $X; } ; echo | cat; echo $X

You'll see afterwards that echo $X shows ABC.

There's other ways that commands are executed in subshells too, e.g. if you background a subcommand: { X=SUB ; sleep 1; } & , that group will run in a subshell, whereas just { X=SUB ; sleep 1; } will not.

If you want to group commands that always execute in a subshell, use parenthesis, (X=ABC ; echo $X) instead of braces.

Tags:

Bash