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

Linux 当我使用`&;时会发生什么在Bash脚本中使用函数?,linux,bash,shell,Linux,Bash,Shell,我正在用shell脚本调试一个奇怪的东西,想知道我是否误解了Bash的“fork”(&)的工作原理,可能是因为我通常通过终端在单个命令中使用它,例如: [~me]$ someExecutable & 现在,在shell脚本中: foo() { echo "logic" } bar() { echo "idic" } baz() { echo "katra" } foo & bar baz 我的目的是异步调用函数foo,然后让脚本的其余部分继续在原始流程

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

[~me]$ someExecutable &
现在,在shell脚本中:

foo() {
   echo "logic"
}

bar() {
   echo "idic"
}

baz() {
   echo "katra"
}

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

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

logic
idic
katra
(也就是说,只有对
bar
baz
的单个明显调用;我一点也不担心三行输出的相对顺序,我知道这可能会有所不同)

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

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


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

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

接下来的命令将立即执行


不存在执行两次脚本的危险,因此它在这方面不同于C的
fork()

在您的示例中,符号AND只是fork调用foo()。它并不是要对整个脚本进行分叉。只有foo()在单独的线程中运行,该线程在foo()完成时退出。bar()和baz()继续在同一个线程中运行

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

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

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


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

除了控制操作符
&
导致命令在子shell中异步执行之外,您还可以利用来控制输出

而不是通过以下语句调用函数:

foo &
cat <&"${fubar[0]}"
说:

然后读输出,说:

foo &
cat <&"${fubar[0]}"
将产生:

idic
katra
logic1
logic2

实际上,该命令在后台运行函数foo:

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

但是,如果像这样运行函数,则会注意到不同之处:

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

这里,您的进程id可能与我的不同,但您可以看到,
逻辑
在其他两个函数的输出之后打印出来。

我不在乎输出的顺序,只得到了三行。就像您在终端中键入一样。但我想你已经摸索过了:)这一切跌跌撞撞地归结为:
&
不是分叉,即它不分叉调用shell(或者更确切地说是shell+脚本)。shell在单独的进程中生成命令,然后在后台处理它,而不是等待它完成后再继续。收到。这意味着这些年来我对它的直觉一直是正确的,但我最初的错误仍然无法解释:(我们也许可以帮助解决它?是否愿意解释一下它是什么错误,并提取它周围的线条?[尝试找出它的错误,一开始不要担心变量的值].给我们输出,为什么它是一个错误,以及导致它的潜在线路。它在系统中太根深蒂固,无法直接描述,我甚至还不能完全确定症状是什么,除了一些原因似乎有问题,这些原因只是让我怀疑,可能导致一些更具体的间歇性故障。我有我一整天都在尝试为它构建一个测试用例;我还没有完成是我没有发布关于它的问题的原因之一;)另一个原因是,构建了一个测试用例后,我应该能够自己修复它。:)谢谢-这就是我想要的+1解决问题的核心。Quibble:foo()在(异步)子shell中运行,这是一个单独的进程;这是因为只有
foo
在后台运行,而不是整个脚本。不,我没有强调顺序,我只是指出函数
foo
确实是在后台和
bar
中调用的,
baz
被正常调用,这就是为什么输出顺序发生了变化。我知道
foo
是在后台运行的,但我想确保子进程只运行
foo
,而不会继续运行脚本的其余部分(导致脚本的其余部分运行两次)虽然OP的问题没有直接解决,但了解协进程(bash4+)是一件好事。