[英]Why does shell command “{ command1; command2: } &" open a subshell?
As we all know, placing a list of commands between curly braces causes the list to be executed in the current shell context. 众所周知,在花括号之间放置一个命令列表会导致列表在当前的shell上下文中执行。 No subshell is created. 没有创建子shell。 But when using "&" after "{}", why two subshells are created? 但是当在“{}”之后使用“&”时,为什么要创建两个子壳? pid 1002 and 1003. pid 1002和1003。
{
./a.out
} &
sleep 19
when using "./a.out &", only a subshell is created. 使用“./a.out&”时,只创建一个子shell。 pid 17358. pid 17358。
./a.out &
sleep 19
Why ? 为什么?
If a command is terminated by the control operator &, the shell executes the command (or list of commands that are enclosed in {...}
) in the background (or asynchronously) in a subshell . 如果一个命令被控制操作员,终止外壳执行该命令(或者被封闭在命令列表{...}
中在子shell 背景 (或异步))。
The shell does not wait for the command to finish, and the return status is 0. shell不等待命令完成,返回状态为0。
In C program it is done by doing a fork()
followed by execvp()
system calls. 在C程序中,它通过执行fork()
然后执行execvp()
系统调用来完成。
Update: Based on comments below and updated question. 更新:根据以下评论和更新的问题。 Here is what is happening. 这是正在发生的事情。
When you run: 当你运行:
./a.out &
BASH directly just runs a.out
in background as running binary a.out
doesn't need a separate shell process. BASH直接在后台运行a.out
作为运行二进制文件a.out
不需要单独的shell进程。
When you run: 当你运行:
{ ./a.out; } &
BASH must first fork and create a subshell as you can have series of commands inside {...}
and then the newly forked subshell runs a.out
in a separate process. BASH必须首先分叉并创建一个子shell,因为你可以在{...}
有一系列命令,然后新分叉的子shell在一个单独的进程中运行a.out
。 So it is not that BASH is creating 2 subshells for this. 所以BASH并没有为此创造2个子壳。 Only one subshell gets created and 2nd pid you're seeing is for a.out
. 只有一个子shell被创建,你看到的第二个pid是a.out
。
Background execution of a list uses a subshell because something needs to wait for each member of that list and run the next one. 列表的后台执行使用子shell,因为某些东西需要等待该列表的每个成员并运行下一个成员。 After a list is backgrounded, the parent shell needs to be available for new commands; 列表背景化后,父shell需要可用于新命令; it can't manage the backgrounded list too. 它也无法管理后台列表。 bash can't do more than one thing at a time. bash一次不能做多件事。 So, to make the backgrounded list work, it runs a subshell. 因此,为了使后台列表工作,它运行一个子shell。
Note that you can disown a backgrounded list and it will keep running, showing that the subshell is doing its work: 请注意,您可以拒绝后台列表,它将继续运行,表明子shell正在执行其工作:
$ {
> sleep 1; sleep 2; sleep 3; sleep 4; sleep 5
> } &
$ disown
$ ps -f | grep sleep
dave 31845 31842 0 03:50 pts/1 00:00:00 sleep 3
dave 31849 31771 0 03:50 pts/1 00:00:00 grep sleep
You could even log out and the subshell would continue running processes in the list. 您甚至可以注销,子shell将继续运行列表中的进程。
When you background a single command, there is no need for a subshell because there is no more work for the shell to do after it has run the command. 当您对单个命令进行后台处理时,不需要子shell,因为在运行该命令后,shell不再需要执行任何操作。
In your example, the second additional bash subprocess, PID 1002, appears to be a script which you're executing. 在您的示例中,第二个附加bash子进程PID 1002似乎是您正在执行的脚本。 That's unrelated (conceptually, at least) to the list-backgrounding mechanism; 这与列表背景机制无关(概念上至少); any script in a separate file has its own bash process. 单独文件中的任何脚本都有自己的bash进程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.