bash 是否支持类似于 C 的 fork() 的分叉?

bash 是否支持类似于 C 的 fork() 的分叉?

我有一个脚本,我想在某一时刻分叉,以便同一脚本的两个副本正在运行。

例如,我希望存在以下 bash 脚本:

echo $$
do_fork()
echo $$

如果这个 bash 脚本确实存在,预期的输出将是:

<ProcessA PID>
<ProcessB PID>
<ProcessA PID>

或者

<ProcessA PID>
<ProcessA PID>
<ProcessB PID>

我可以用什么东西来代替“do_fork()”来获得这种输出,或者使 bash 脚本执行类似 C 的 fork 吗?

答案1

是的。分叉的拼写是&

echo child & echo parent

您可能会感到困惑的是,这$$不是 shell 进程的 PID,而是原来的壳进程。这样做的要点是,它$$是 shell 脚本的特定实例的唯一标识符:它在脚本执行期间不会更改,并且与$$任何其他并发运行的脚本不同。获取 shell 进程的实际 PID 的一种方法是sh -c 'echo $PPID'

shell 中的控制流与 C 不同。如果在 C 中你会写

first(); fork(); second(); third();

那么 shell 等效项是

after_fork () { second; third; }
first; after_fork & after_fork

简单的 shell 形式first; child & parent对应于通常的 C 习惯用法

first(); if (fork()) parent(); else child();

&$$在每个 Bourne 风格的 shell 和 (t)csh 中都以这种方式存在和表现。$PPID原始 Bourne shell 中不存在,但存在于 POSIX 中(因此存在于 ash、bash、ksh、zsh 等中)。

答案2

是的,它叫子壳。括号内的 Shell 代码作为子 shell(fork)运行。然而,第一个 shell 通常等待子进程完成。您可以使用终止符使其异步&。看看它的实际效果,如下所示:

#!/bin/bash

(sleep 2; echo "subsh 1")&
echo "topsh"

$ bash subsh.sh

答案3

没有本机 bash(或者据我所知,任何其他典型的 *nix shell)方法可以执行此操作。有很多方法可以生成分叉进程来异步执行其他操作,但我认为没有任何内容遵循 fork() 系统调用的确切语义。

典型的方法是让您的顶级脚本生成助手,这些助手只完成您想要拆分的工作。如果你这样做了$0 $@ &或者无论如何,你都会从头开始,并且需要以某种方式解决这个问题。

我实际上开始考虑几种聪明的方法来做到这一点......

,在我的大脑对此过于着迷之前,我认为一个很好的规则是:如果您尝试用 shell 编写一些东西,并且它充满了聪明的技巧,并且您希望获得更多的语言功能,那么是时候切换了具有这些功能的编程语言。

相关内容