On Wed, Oct 12, 2016 at 8:23 PM, Greg Wooledge <wool...@eeg.ccf.org> wrote:
> On Tue, Oct 11, 2016 at 07:14:24PM -0700, s7v7nisla...@gmail.com wrote: > > why bash bahavior like this? is that a bug? > > > > if not, why should forked before execute subshell? > > Because that's how subshells work. A subshell *is* a fork. > > > 1. the script to reproduce > > bash-4.4$ cat t.sh > > (cd /tmp && sleep 20) & > > > > echo "end" > > When executing the first line: > > 1) Bash (the parent) forks. > 2) The child executes the compound command: cd /tmp && sleep 20 > 2a) The child process uses chdir() to change directory. > 2b) The child proesss forks and execs and waits for the external > command: > sleep 20 > 3) Since the subshell is running in the background, the parent Bash > continues on to execute: echo "end" > 4) The parent Bash exits. The child which is waiting for sleep 20 to > terminate continues running. sleep 20 also continues running. > > > 3. script end, but there is a new forked script. > > bash-4.4$ ps -ef | grep t.sh > > 501 50268 1 0 10:09AM ttys015 0:00.00 bash t.sh > > 501 50275 50181 0 10:10AM ttys015 0:00.00 grep t.sh > > Process 50268 is the child which is waiting for sleep 20 to finish. > > > question: > > when using sh -> dash, It will not fork before subshell, what's the > different? > > Dash probably optimizes the compound command inside the subshell more > aggressively than bash does. It may implicitly exec for you. > > If you want to ENSURE that the child shell process is replaced by the > external sleep 20, use an explicit exec. > > yes, I want to know why bash not optimize this. or any strategy ? Thank you for your explain! > #!/bin/bash > (cd /tmp && exec sleep 20) & > echo "end" > > Then, instead of having: > > $ ./foo > end > $ ps f -t pts/5 > PID TTY STAT TIME COMMAND > 7287 pts/5 Ss 0:00 bash > 20165 pts/5 R+ 0:00 \_ ps f -t pts/5 > 20160 pts/5 S 0:00 /bin/bash ./foo > 20161 pts/5 S 0:00 \_ sleep 20 > > You will have: > > $ ./foo > end > $ ps f -t pts/5 > PID TTY STAT TIME COMMAND > 7287 pts/5 Ss 0:00 bash > 20173 pts/5 R+ 0:00 \_ ps f -t pts/5 > 20172 pts/5 S 0:00 sleep 20 > > This is what you wanted, right? >