Bash 中的函数是否作为子进程运行?

Bash 中的函数是否作为子进程运行?

高级 Bash 脚本指南, 在示例27-4,从底部算起的第 7 行,我读过:

函数作为子进程运行。

我在Bash中做了测试,看来上面的说法是错误的。

Bash Man 和我的搜索引擎在这个网站上的搜索没有带来任何线索。

您有答案并愿意解释一下吗?

答案1

高级 Bash 脚本指南并不总是可靠,其示例脚本包含过时的实践,例如使用已有效弃用用于命令替换的反引号,即,`command`而不是$(command).

在这种特殊情况下,这是明显错误的。

该部分关于外壳函数在(规范的)Bash 手册中明确指出

Shell 函数在当前 shell 上下文中执行;没有创建新的流程来解释它们。

答案2

大括号函数将在调用 shell 进程中运行,除非它们需要自己的子 shell,即:

  • 当你在后台运行它们时&
  • 当您将它们作为管道中的链接运行时

重定向或额外的环境。变量不会强制创建新的子 shell:

hw(){
    echo hello world from $BASHPID
    echo var=$var
} 
var=42 hw >&2
echo $BASHPID  #unexports var=42 and restores stdout here

如果您使用括号而不是花括号定义函数:

hw()(
  echo hello world from $BASHPID
)
hw 
echo $BASHPID

它总是在一个新的进程中运行。

命令替换$()也总是在 bash 中创建进程(但如果您在其中运行内置命令,则不会在 ksh 中创建进程)。

答案3

该示例中的相关命令如下所示:

echo ${arrayZ[@]/%e/$(replacement)}

后面的例子指出:

#    $( ... ) is command substitution.
#    A function runs as a sub-process.

出于对 ABS Guide 的善意,他们显然想写的是该函数在一个命令替换并且命令替换中的命令在子外壳

答案4

我要注意的是,如果在背景,bash 函数将在子 shell 中执行。我之所以注意到这一点,是因为我在检查这一事实时偶然发现了这个问题。

[192.168.28.1 (1ae7468c) ~ 19:17:50]# function foo () { echo $BASHPID; }
[192.168.28.1 (1ae7468c) ~ 19:17:59]# foo
807477
[192.168.28.1 (1ae7468c) ~ 19:18:02]# foo
807477
[192.168.28.1 (1ae7468c) ~ 19:18:03]# foo &
[1] 1996783
1996783
[1]+  Done                    foo
[192.168.28.1 (1ae7468c) ~ 19:18:06]# 

相关内容