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. #!/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?