当我在 Bash 脚本中将"&"与函数一起使用时会发生什么?



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

[~me]$ someExecutable &

现在,在一个shell脚本中:

foo() {
echo "logic"
}
bar() {
echo "idic"
}
baz() {
echo "katra"
}
foo &
bar
baz

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

当我执行这个示例脚本时,我得到预期的输出:

logic
idic
katra

(也就是说,只有对barbaz的单个明显调用;我一点也不为三行输出的相对顺序所困扰,我知道这可能会有所不同)

但我可能误解了输出和脚本本身。如果是这样的话,这肯定可以解释我在真实代码中看到的奇怪之处,并使我不必再深入研究了。

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

当我在Bash脚本中像这样使用&时,会发生什么

在您的示例中,"与"符号只是派生对foo()的调用。它并没有分叉整个脚本。只有foo()在一个单独的线程中运行,当foo(()完成时就会退出。bar()和baz()继续在同一线程中运行

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

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

因此,"foo"的输出实际上可能发生在bar或baz之后,这取决于它的内容。。但由于它使用了"echo",这是一个shell内置程序,当"foo"后台进程设置好时,"echo"立即可用:因此,在调用shell传递到下一个命令之前,很有可能看到它的输出,这显然就是您的情况。(但是YMMV!如果"foo"调用了一个繁重的外部命令,那么它的输出很可能会在稍后发生)

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

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

接下来的命令将立即执行。

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

除了控制运算符&导致命令在子shell中异步执行1之外,您还可以使用协处理器来控制输出。

而不是通过说:来调用函数

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

实际上,这个命令确实在后台运行您的函数:

foo &

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

然而,如果你这样运行你的功能,那么你会注意到区别:

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

在这里,您的进程id可能与我的不同,但您可以看到logic最终是在其他2个函数的输出之后打印的。

相关内容

  • 没有找到相关文章

最新更新