set -eo pipelinefail 在 ksh 和 bash 上有所不同

sto*_*ord 5 shell bash ksh pipe

我想在发生任何故障(包括管道内部故障)时终止脚本。在bash中,你可以set -eo pipefail,但这在 ksh 中不起作用。

\n\n

例子:

\n\n
# x\nset -eo pipefail\nfalse | true\necho "done: $?" # reached in ksh, unexpected\nfalse\necho "done2" # not reached in either shell, as expected\n
Run Code Online (Sandbox Code Playgroud)\n\n
bash x        # prints nothing, as expected\nksh x         # done: 1\nksh --version # ... 93u+ 2012-08-01\n
Run Code Online (Sandbox Code Playgroud)\n\n

为什么 ksh 在这种情况下不会退出?

\n\n

编辑:添加另一个测试

\n\n

我将其与其他 shell 进行了比较,得到了不同的结果:

\n\n
-bash-5.0$ zsh -c \'set -eo pipefail; false | true; exit 2\' ; echo $?\n1\n-bash-5.0$ ksh -c \'set -eo pipefail; false | true; exit 2\'; echo $?\n2\n-bash-5.0$ bash -c \'set -eo pipefail; false | true; exit 2\' ; echo $?\n1\n
Run Code Online (Sandbox Code Playgroud)\n\n

除了 ksh 中的错误之外,我不明白是什么导致了这种行为。根据 man ksh 的说法:

\n\n
-e    Unless contained in a \xe2\x8e\xaa\xe2\x8e\xaa or && command, or the command\n      following an if while or until command or in the\n      pipeline following !, if a command has a non-zero exit  # Pipeline does not follow !\n      status, execute the ERR trap, if set, and exit.  This   # Pipeline has a non-zero exit status\n      mode is disabled while reading profiles.\n\npipefail\n      A pipeline will not complete until all\n      components of the pipeline have completed, and\n      the return value will be the value of the last\n      non-zero command to fail or zero if no command\n      has failed.\n
Run Code Online (Sandbox Code Playgroud)\n

Sté*_*las 3

它看起来像是 ksh93u+ 引入的回归。ksh93u 在这方面按预期工作(以及 zsh、bash、mksh、yash 和 busybox sh)。

我刚刚在https://github.com/ksh93/ksh/issues/121提出了这个问题

现已修复https://github.com/ksh93/ksh/commit/c049eec854d506ad6110eb50c769b10224c60075,自 v1.0.0-beta.1 起包含