Linux 在这种情况下,为什么shell会启动另一个shell进程?

Linux 在这种情况下,为什么shell会启动另一个shell进程?,linux,bash,shell,Linux,Bash,Shell,这是密码 #!/bin/bash echo $$ cd $HOME && sleep 10 & exit 0 现在让我们运行sh test.sh 我得到的结果是: 21936这是我运行的shell进程的pid 如果我在10秒内ps-ef | grep test.sh,这就是睡眠时间 我得到根21937 1 0 12:41分/0 00:00:00 sh测试。sh 问题1:它应该不是test.sh,而是一个sleep过程。为什么还有一个test.sh 问题2:似乎测试。sh

这是密码

#!/bin/bash
echo $$
cd $HOME && sleep 10 &
exit 0
现在让我们运行
sh test.sh

我得到的结果是:
21936
这是我运行的shell进程的pid

如果我在
10秒内
ps-ef | grep test.sh
,这就是睡眠时间

我得到
根21937 1 0 12:41分/0 00:00:00 sh测试。sh

问题1:它应该不是
test.sh
,而是一个
sleep
过程。为什么还有一个
test.sh

问题2:似乎
测试。sh
I grep out与
测试不一样。sh
I在终端中运行,取决于
PID
。那么新的
test.sh
是如何产生的呢


嗨,如果我换衣服的话,还有另一个例子

cd $HOME && sleep 10 &

它不会以相同的方式运行,
test.sh
将在执行
sh test.sh
后立即消失,只有一个
睡眠过程。

来自:

如果命令被控制操作符
&
终止,shell将在子shell中异步执行该命令

也就是说,父shell进程是分叉的(在生成子shell时)

您可以使用以下代码段轻松测试这一点:

#!/usr/bin/env bash
print_subshell_level () { echo $BASH_SUBSHELL; }

printf "foreground: "
print_subshell_level

printf "background: "
print_subshell_level &
输出:

foreground: 0
background: 1
(好的,我会冒险把我的猜测/评论变成答案。)

由于
&
-操作符本质上是一个shell内置的,即它需要由shell处理,因此将它与
&
一起使用将为/a shell创建一个子进程,而不是它的各个部分(或者只是它的最后一部分,如您所期望的那样)

甚至当所有与
&
链接的命令都是外部命令时,也会发生这种情况。例如,
sleep3&&sleep5&
也将创建一个子shell进程

只是分隔单个命令,就好像它们被写在单独的行上一样。因此,在这种情况下,只有
&
前面的命令被分叉(“发送到后台”)


(当然,分叉的原始进程始终是shell-这就是分叉的工作方式-但在第二种情况下,它被实际命令的可执行文件替换,
sleep
(在您的示例中)。

后台作业使用
&
分叉进程。您的意思是
&
会自行分叉进程吗?我曾经认为,在这种情况下,它只会分叉
sleep
。我认为(!)您看到的情况是因为您将shell内置命令与外部命令“链接”在一起(在这种情况下是sleep)。通过指定“内置&&external&”,shell在后台运行整个过程,因此需要分叉(而不仅仅是“sleep”)。在第二次编辑中,您运行了两个不同的命令(使用“;”而不是“&&&”),尽管只使用了“sleep”分叉。我想您说到点子上了!有关于“将内置命令与外部命令链接在一起”的文档吗?对不起,我不知道。但在这个问题上有一个几乎重复的问题,这是对的。我知道
sh test.sh&
将把
test.sh
放在后台。但是在这种情况下,
&
在shell脚本
test.sh
中,如果这也将
test.sh
置于后台?我以为这只是
sleep
@louissbang命令行
sh test的过程。sh
是分叉的。您应该首先了解什么是分叉,这与“被发送到后台”不同。你可能应该读一下维基百科的条目:.@louisthebang“我认为这只是
睡眠
”没有任何意义。即使在前台执行,
sleep
也将是一个不同的过程,因为它是一个外部命令。背景的不同之处在于
sh
是分叉的。我在问题中添加了另一个案例,请看一看。是的,我知道fork是什么,因为我在开发中经常使用它。我认为这不是对
fork
的误解,而是
&
&
&
shell
@louisthebang我认为这里发生的是subshell调用
exec
,因此subshell被
sleep
过程所取代。“它被实际命令的可执行文件所取代”-可能是
exec
在这里工作。我用
&
&
做了一些测试,效果很好。
foreground: 0
background: 1