当我在Bash脚本中使用`&'和函数时会发生什么?

时间:2014-01-13 12:55:08

标签: linux bash shell

我正在用shell脚本调试一个奇怪的东西,想知道我是否误解了Bash的“fork”(&)是如何工作的,也许是因为我通常在单个命令中通过终端使用它,例如:< / p>

[~me]$ someExecutable &

现在,在shell脚本中:

foo() {
   echo "logic"
}

bar() {
   echo "idic"
}

baz() {
   echo "katra"
}

foo &
bar
baz

我的目的是异步调用函数foo,然后让脚本的其余部分继续在原始进程上下文中执行。

当我执行此示例脚本时,我获得预期的输出:

logic
idic
katra

(也就是说,只对barbaz发出一次明显的调用;我完全不会被三行的相对顺序所困扰输出,我理解可能会有所不同)

但我可能误解了输出和脚本本身。如果是这样,那肯定会解释我在实际代码中看到的奇怪之处,并且让我不必再深入挖掘。

在子进程中,在调用foo之后,forked shell脚本是否可能会继续?这意味着我的shell脚本的其余部分将被执行两次

在Bash脚本中使用&时会发生什么?

5 个答案:

答案 0 :(得分:3)

&符号仅在您的示例中分配对foo()的调用。它不是分支整个脚本。只有foo()在一个单独的线程中运行,当foo()结束时它会退出。 bar()和baz()继续在同一个线程中运行

答案 1 :(得分:2)

bash中的&不是分叉。 它告诉bash在子shell中启动命令,并继续解析其他命令(而不是等待该命令完成)。

因此,正如您所料,它在后台运行'foo',并继续处理顶级shell中的'bar'和'baz'命令。没有发生调用shell的分叉,但是'foo'在后台运行。

所以“foo”的输出实际上可能发生在bar或baz之后,具体取决于它的内容..但是因为它使用“echo”,这是一个内置的shell,当“foo”后台进程设置时, “echo”可立即使用:因此,在调用shell传递给下一个命令之前,你很有可能看到它的输出,这显然是你的情况。 (但是YMMV!如果“foo”正在调用一个沉重的外部命令,它的输出可能会在稍后发生)

在终端中,它几乎是一样的:你可以考虑一个带有shell提示符的终端窗口作为该shell的文件脚本,登录shell正在“按你键入时”读取。行为几乎相同。

答案 2 :(得分:1)

&字符告诉shell在后台执行命令(或一组命令)。

立即执行下一个命令。

没有两次执行脚本的危险,因此在这方面它与C fork()不同。

答案 3 :(得分:1)

除了控制操作符&导致命令在子shell 1 中异步执行之外,您可以使用Coprocesses来实现控制输出。

而不是通过说:

来调用该函数
foo &

说:

coproc fubar { foo; }

然后通过说:

读取输出
cat <&"${fubar[0]}"

这也允许您控制输出(是否需要在barbaz等其他函数之前或之后发出。


例如,以下内容:

foo() {
   echo "logic1"
   echo "logic2"
}

bar() {
   echo "idic"
}

baz() {
   echo "katra"
}

coproc fubar { foo; }
bar
baz
cat <&"${fubar[0]}"

会产生:

idic
katra
logic1
logic2

答案 4 :(得分:0)

实际上这个命令确实运行你的函数foo后台:

foo &

但是当你输入barbaz时,foo已经完成了它的运行并在你的终端上打印了它的输出。

但是,如果您运行这样的功能,那么您会注意到差异:

foo & bar; baz
[1] 46453
idic
katra
logic
[1]+  Done                    foo

此处您的流程ID可能与我的不同,但您可以看到logic在其他2个功能的输出后最终打印出来。