3

I am reading The TTY demystified. In the "Jobs and sessions" section there is an example of a user using an xterm:

$ cat
hello
hello
^Z
[1]+  Stopped                 cat
$ ls | sort

And there is a table listing the processes involved: xterm, bash (child of the xterm), and the three last processes (cat, ls and sort) all have the same PPID (parent process ID) -- they are all children of the same bash process.

Now, I know that pipelines in bash are executed in subshells. I have always thought that this subshell thing meant that there was an extra bash process for each subshell. My question is: shouldn't there be another two bash processes, both children of the first bash, and then ls would be a child of the first bash, and sort would be a child of the second bash? Is the table in the article simplified, or is my understanding of subshells wrong?

fonini
  • 2,989
  • 3
  • 21
  • 39
  • 1
    The behaviour of Bash is configurable; your sweeping generalities are not entirely accurate with the default settings (notably 'pipelines…are executed in subshells' is not accurate). See [`PIPESTATUS`](http://www.gnu.org/software/bash/manual/bash.html#Bash-Variables) and [`shopt -s lastpipe`](http://www.gnu.org/software/bash/manual/bash.html#The-Shopt-Builtin) and [`set -o pipefail`](http://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin). – Jonathan Leffler Dec 27 '14 at 21:42

2 Answers2

4

Programs are executed in child processes, but these are not subshells. The shell forks a child, redirects standard input/output/error as necessary, and then immediately calls execv() to execute the program.

For a very brief period the child process is still running bash, but we don't consider this a subshell because it's not doing any shell command processing -- that was all done in the original shell, and the child is just starting up the external program (as if via an explicit exec for commands like ls).

In the case of a pipeline, if any of the commands are shell built-ins, they run in a subshell. So if you do:

ls | read var

it will create two child processes. One child will run ls, the other will be a subshell executing read var.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • In my understanding, what you described is true for processes like the `cat` command above. But my question is specifically about pipelines. Pipelines always run in a subshell, right? – fonini Dec 27 '14 at 20:50
  • 1
    I've updated the answer to explain subshells running in a pipeline. – Barmar Dec 27 '14 at 20:53
3

Invoking an executable, whether directly or via a pipe, does not spawn a subshell. Only explicitly invoking it within a subshell (via (...), $(...), and so on) does so.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358