简体   繁体   English

为什么shell命令“{command1; command2:}&“打开子shell?

[英]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.

相关问题 自动将一堆命令转换为command1 && command2 - Automatically convert bunch of commands to command1 && command2 为什么在分组命令中执行简单命令不分叉子shell进程,而复合命令将执行此操作 - Why does executing a simple command in a grouping command does not fork a subshell process, and the compound command will do it 如何在不运行source命令的情况下将子shell的执行行打印到主shell? - How does a subshell's executed lines get printed to the main shell without running the source command? Linux Shell:为什么在此telnet命令中需要“打开” - Linux shell: why is “open” required in this telnet command 为什么这个命令会杀死我的shell? - Why does this command kill my shell? 为什么“查找”命令在 shell 脚本中不起作用 - why does “find” command not working in shell script 将命令通过管道传递给 shell 脚本时,为什么退出管道命令会使 shell 脚本退出? - When piping a command to shell script, why does exiting piped command makes shell script exit? 这个shell命令中的“:?”是什么意思? - what does “:?” mean in this shell command? 为什么此egrep命令在我的Shell中有效,而在Perl中却无效? - Why does this egrep command work in my shell but not in Perl? 杀死在子外壳程序中运行的tftp命令 - Kill tftp command that's running in subshell
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM