在{}
刚组命令一起在当前shell,而()
开始一个新的子shell。但是,你所做的是将分组的命令放到后台,这确实是一个新的过程;如果它在当前进程中,它不可能是后台的。恕我直言,用 strace 看到这种事情更容易:
sauer@humpy:~$ strace -f -etrace=process bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; } & echo $BASHPID;' > /tmp/file
execve("/bin/bash", ["bash", "-c", "{ sleep 10; echo \"Sleeping proce"...], [/* 20 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f15a90da700) = 0
clone(Process 25347 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f15a90da9d0) = 25347
[pid 25346] exit_group(0) = ?
clone(Process 25348 attached (waiting for parent)
Process 25348 resumed (parent 25347 ready)
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f15a90da9d0) = 25348
[pid 25348] execve("/bin/sleep", ["sleep", "10"], [/* 20 vars */] <unfinished ...>
[pid 25347] wait4(-1, Process 25347 suspended
<unfinished ...>
[pid 25348] <... execve resumed> ) = 0
[pid 25348] arch_prctl(ARCH_SET_FS, 0x7f922ad16700) = 0
[pid 25348] exit_group(0) = ?
Process 25347 resumed
Process 25348 detached
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 25348
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fffaa432ad8, WNOHANG, NULL) = -1 ECHILD (No child processes)
exit_group(0) = ?
Process 25347 detached
sauer@humpy:~$ cat /tmp/file
25346
Sleeping process, 25347, 1
Run Code Online (Sandbox Code Playgroud)
请注意 bash 命令启动,然后它创建一个新的子clone()
。对 strace 使用 -f 选项意味着它也跟随子进程,在它运行 sleep 时显示另一个分支(好吧,“克隆”)。如果关闭 -f,则在创建后台进程时只会看到一个克隆调用:
sauer@humpy:~$ strace -etrace=clone bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; } & echo $BASHPID;' > /tmp/file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2bdd5399d0) = 26394
sauer@humpy:~$ strace -etrace=process bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; } & echo $BASHPID;' > /dev/null
execve("/bin/bash", ["bash", "-c", "{ sleep 10; echo \"Sleeping proce"...], [/* 20 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7fd01ae86700) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd01ae869d0) = 26706
exit_group(0) = ?
Run Code Online (Sandbox Code Playgroud)
如果你真的只想知道你创建新进程的频率,你可以通过只观察 fork 和 clone 调用来进一步简化:
sauer@humpy:~$ strace -etrace=fork,clone bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; } & echo $BASHPID;' > /dev/null
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f467fa769d0) = 27025
Run Code Online (Sandbox Code Playgroud)
Ami*_*it 5
更新:
请看上面的回答。使用 {},我并没有真正创建子 shell。相反,这里的背景为我提供了我正在寻找的答案。
好的,所以基本上我使用了正在创建的子外壳的不正确“指标”。我BASHPID
从这里了解了并且除了使用它之外BASH_SUBSHELL
,我可以看到确实正在创建一个子shell。
测试命令:
$ bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL; } & echo $BASHPID; '
12074
Sleeping process, 12075, 1
Run Code Online (Sandbox Code Playgroud)
另一个测试命令也显示 shell 和子 shell 的父进程 ID:
$ bash -c '{ sleep 10; echo "Sleeping process", $BASHPID, $BASH_SUBSHELL, $PPID; } & echo $BASHPID, $PPID; '
12411, 9128
$ Sleeping process, 12412, 1, 9128
Run Code Online (Sandbox Code Playgroud)