管道是否可以在任何POSIX shell中创建子shell?

时间:2016-04-21 11:31:52

标签: shell posix pipeline

此shell脚本的行为符合预期。

trap 'echo exit' EXIT

foo()
{
    exit
}

echo begin
foo
echo end

这是输出。

$ sh foo.sh
begin
exit

这表明脚本在执行foo时退出。

现在看下面的脚本。

trap 'echo exit' EXIT

foo()
{
    exit
}

echo begin
foo | cat
echo end

这里唯一的区别是foo的输出正在被输入`cat。现在输出如下所示。

begin
end
exit

这表明在执行foo时脚本不会退出,因为打印了end

我相信这是因为在bash中,管道导致子shell被打开,因此foo | cat等同于(foo) | cat

在任何POSIX shell中都能保证这种行为吗?我在http://pubs.opengroup.org/onlinepubs/9699919799/的POSIX标准中找不到任何暗示管道必须通向子壳的东西。有人可以确认是否可以依赖这种行为吗?

1 个答案:

答案 0 :(得分:2)

2.12 Shell Execution Environment中,你会发现这句话:

  

子shell环境应创建为shell环境的副本,但未被忽略的信号陷阱应设置为默认操作。对子shell环境所做的更改不会影响shell环境。命令替换,与括号分组的命令和异步列表应在子shell环境中执行。另外,多命令管道的每个命令都在子shell环境中;但是,作为扩展,管道中的任何或所有命令都可以在当前环境中执行。所有其他命令都应在当前shell环境中执行。

此问题的关键句是

  

此外,多命令管道的每个命令都在子shell环境中;但是,作为扩展,管道中的任何或所有命令都可以在当前环境中执行

所以没有扩展名(bash用于lastpipe这样的东西,我想,对于管道中的第一个元素,但显然不是或者至少不是总是)它看起来像你可以假设管道的每个部分都有一个子壳,但例外意味着你不能指望它。