Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I seem to misunderstand the Bash rule for creating a subshell. I thought parentheses always creates a subshell, which runs as its own process.

However, this doesn't seem to be the case. In Code Snippet A (below), the second sleep command does not run in a separate shell (as determined by pstree in another terminal). However, in Code Snippet B, the second sleep command does run in a separate shell. The only difference between the snippets is that the second snippet has two commands within the parentheses.

Could somebody please explain the rule for when subshells are created?

CODE SNIPPET A:

sleep 5
(
sleep 5
)

CODE SNIPPET B:

sleep 5
(
x=1
sleep 5
)
share|improve this question

2 Answers 2

up vote 10 down vote accepted

The parentheses always start a subshell. What's happening is that bash detects that sleep 5 is the last command executed by that subshell, so it calls exec instead of fork+exec. The sleep command replaces the subshell in the same process.

When you add something else after the call the sleep, the subshell needs to be kept around, so this optimization can't happen.

When you add something else before the call to sleep, the optimization could be made (and ksh does it), but bash doesn't do it (it's very conservative with this optimization).

share|improve this answer

From the Advanced Bash Programming Guide:

"In general, an external command in a script forks off a subprocess, whereas a Bash builtin does not. For this reason, builtins execute more quickly and use fewer system resources than their external command equivalents."

And a little further down:

"A command list embedded between parentheses runs as a subshell."

Examples:

[root@talara test]# echo $BASHPID
10792
[root@talara test]# (echo $BASHPID)
4087
[root@talara test]# (echo $BASHPID)
4088
[root@talara test]# (echo $BASHPID)
4089

Example using OPs code (with shorter sleeps because I am impatient):

echo $BASHPID

sleep 2
(
    echo $BASHPID
    sleep 2
    echo $BASHPID
)

The output:

[root@talara test]# bash sub_bash
6606
6608
6608
share|improve this answer
    
Thanks for the reply Tim. I'm not sure it fully answers my question though. Since "A command list embedded between parentheses runs as a subshell", I would expect the second sleep to run in a subshell (perhaps on the subshell's process since it's a built-in, rather than a subprocess of the subshell). However, in any case, I would have expected a subshell to exist, i.e. a Bash subprocess under the parent Bash process. For Snippet B above, this doesn't seem to be the case. –  bashful Jun 22 '12 at 16:07
    
Correction: Because sleep doesn't seem to be a built-in, I would expect the second sleep call in both snippets to run in a subprocess of the subshell process. –  bashful Jun 22 '12 at 16:15
    
@bashful I took the liberty of hacking your code with my $BASHPID variable. Sadly the way you were doing it was not giving you the whole story I believe. See my added output in the answer. –  Tim Jun 22 '12 at 17:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.