2

time false以下配方set -e成功(在time可以看到输出的意义上成功):

(
set +e
time { ( set -e; false; echo no0; ); }
echo yes0 $?
)

但以下食谱失败:

(
set -e
time false
echo no1
)

同样:

(
set -e
time { false; echo no2; }
echo no2
)

同样(令人惊讶的是,它在 bash3 下输出 yes3 而在 bash4 下没有输出):

(
set -e
time ( false; echo no3; )
echo yes3 $?
)

同样(不是很令人惊讶):

(
set +e
time { set -e; false; echo no4; }
echo no4
)

同样(惊喜):

(
set +e
time ( set -e; false; echo no5; )
echo yes5 $?
)

以下在 bash3 下成功,在 bash4 下做了完全不同的事情:

(
set -e
time { ( false; echo no7; ); echo yes6 $?; }
echo yes6 $?
)

请注意,“否”echo不打印,而“是”由 bash3 输出(但不是全部由 bash4 输出)。

如果将其与下面的子shell(...)处理进行比较,则在这种情况下,内置函数set -e似乎是在子shell 上下文中执行的。怎么回事?timetime (...)

经测试

GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

输出

real    0m0.000s
user    0m0.001s
sys     0m0.000s
yes0 1
yes3 1
yes5 1
yes6 1

real    0m0.000s
user    0m0.000s
sys     0m0.001s
yes6 0

GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.

输出

real    0m0.001s
user    0m0.000s
sys     0m0.004s
yes0 1
yes5 1

请注意,“yes3”和“yes6”案例显示 bash3 和 bash4 处理方式的巨大差异set -e

但是“yes5”的情况令人困惑。看起来“时间”以某种方式由子外壳而不是在外壳中处理。

这种行为是由 POSIX 强制执行的,是 bashs 错误之一还是只是一种bash特殊行为?

谢谢 ;)

PS:如果你不明白为什么这不是学术性的:曾经有一个脚本在set -e(“yes3” without time)下运行。它被改变以记录一些时间信息,黑客看起来像“yes6”。但是现在 bash4 出现了,它需要再次修复。

4

1 回答 1

2

实际上 bash 4 中的行为是可以预测的,

  • set -e如果当前 shell 或当前 shell 的子 shell 中的任何简单命令返回非零退出状态,将导致您退出当前 shell(有关更详细/准确的描述,请阅读Bash 手册的部分set

  • set -e优先于time,即在no2情况下说

    (
       set -e
       time false;  
    )
    

    您在可以完成执行之前退出子shell time,因此没有来自time.


考虑到这一点,在yes5情况下会发生什么(让我们将第一个( )称为“subshel​​l level 1”,将第二个( )称为“level 2”)

(
    set +e
    time ( set -e; false; echo no5; )
    echo yes5 $?
)

is when you encounter false which returns exit status 1, the set -e causes it to exit subshell level 2, this returns exit status 1 to subshell level 1. But since level 1 has set +e, everything runs.


For yes6 case,

(
    set -e
    time { ( false; echo no7; ); echo yes6 $?; }
    echo yes6 $?
)

the false in subshell level 2 returns triggers set -e, hence the absence of output.


The rest is left as an exercise for the reader.

于 2012-10-23T17:50:45.960 回答