Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will () construct always start a subshell?

Tags:

linux

bash

shell

Current shell is

$ echo $$
23173

Note the parent of ps is current shell

$ ( ps -o pid,ppid,cmd )
  PID  PPID CMD
 8952 23173 ps -o pid,ppid,cmd
23173 23169 bash

But here , the parent of ps is the subshell (bash)

$ ( echo hello ; ps -o pid,ppid,cmd )
hello
  PID  PPID CMD
 8953 23173 bash
 8954  8953 ps -o pid,ppid,cmd
23173 23169 bash

Is bash doing optimizations ? How come an extra echo made the the difference and spawned a subshell in 3rd case ?

like image 815
Ankur Agarwal Avatar asked May 08 '11 16:05

Ankur Agarwal


2 Answers

Yes, what you're seeing is an optimization. Technically, the (…) construct always starts a subshell, by definition. Most of the time, the subshell runs in a separate subprocess. This ensures that everything done in the subshell stays in the subshell. If bash can guarantee this isolation property, it's free to use any implementation technique it likes.

In the fragment ( ps -o pid,ppid,cmd ), it's obvious that nothing can influence the parent shell, so there's an optimization in bash that makes it not fork a separate process for the subshell. The fragment ( echo hello ; ps -o pid,ppid,cmd ) is too complex for the optimizer to recognize that no subshell is needed.

If you experiment with ksh, you'll notice that its optimizer is more aggressive. For example, it doesn't fork a subprocess for ( echo hello ; ps -o pid,ppid,cmd ) either.

like image 167
Gilles 'SO- stop being evil' Avatar answered Oct 15 '22 21:10

Gilles 'SO- stop being evil'


A subshell consisting of a single simple command instead of a list or pipeline of more than one command could be implemented by simply "execing" the command, i.e. replacing the subshell with the process for the command called. If the subshell is more complex then a simple exec is not possible, the subshell must stay around to manage the command sequence.

From your diagnostics it's impossible to tell the difference between a bash optimization where a subshell consisting of a simple command is optimized to a "direct" fork and exec of the called command or a fork of a subshell followed by an exec of the command called. This isn't surprising as the difference is (almost?) entirely academic.

like image 25
CB Bailey Avatar answered Oct 15 '22 21:10

CB Bailey