此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标准中找不到任何暗示管道必须通向子壳的东西。有人可以确认是否可以依赖这种行为吗?
答案 0 :(得分:2)
在2.12 Shell Execution Environment中,你会发现这句话:
子shell环境应创建为shell环境的副本,但未被忽略的信号陷阱应设置为默认操作。对子shell环境所做的更改不会影响shell环境。命令替换,与括号分组的命令和异步列表应在子shell环境中执行。另外,多命令管道的每个命令都在子shell环境中;但是,作为扩展,管道中的任何或所有命令都可以在当前环境中执行。所有其他命令都应在当前shell环境中执行。
此问题的关键句是
此外,多命令管道的每个命令都在子shell环境中;但是,作为扩展,管道中的任何或所有命令都可以在当前环境中执行
所以没有扩展名(bash
用于lastpipe
这样的东西,我想,对于管道中的第一个元素,但显然不是或者至少不是总是)它看起来像你可以假设管道的每个部分都有一个子壳,但例外意味着你不能指望它。