这是代码
#!/bin/bash
echo $$
cd $HOME && sleep 10 &
exit 0
现在让我们运行sh test.sh
我得到了结果:
21936
这是我运行的shell进程的pid。
如果我在 10秒内执行ps -ef | grep test.sh
,那就是睡眠时间。
我得到了root 21937 1 0 12:41 pts/0 00:00:00 sh test.sh
Q1:它应该是test.sh
而不是sleep
进程。为什么还有test.sh
?
Q2:看起来我{gre}的test.sh
与我在终端中运行的test.sh
不一样,取决于PID
。那么新的test.sh
是如何出来的?
嗨,如果我改变了
,还有另一种情况cd $HOME && sleep 10 &
到
cd $HOME; sleep 10 &
它的行为方式不同,test.sh
会在执行sh test.sh
后立即消失,只有sleep
个进程。
答案 0 :(得分:2)
(好吧,我会走出困境,将我的猜测/评论转化为答案。)
由于&&
- 运算符本质上是一个shell内置函数,即它需要由shell处理,因此将它与&
一起使用将为/ a shell创建一个子进程而不是它的各个部分(或者只是它看起来的最后部分,你预期的那样)。
当与&&
链接的所有命令都是外部命令时,甚至会发生这种情况。例如,sleep 3 && sleep 5 &
也将创建子shell进程。
;
只是将各个命令分开,就好像它们是在不同的行上写的一样。因此,在这种情况下,只有&
之前的命令被分叉("发送到后台")。
(当然,分叉的原始进程总是shell - 这就是fork的工作方式 - 但在第二种情况下,它被替换为实际命令的可执行文件sleep
in你的例子。)
答案 1 :(得分:1)
如果命令被控制操作符
&
终止,则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