如何导致Linux管道失败?

时间:2018-03-13 23:34:00

标签: shell pipe posix pipeline

最近我在Ubuntu 14.04上学习POSIX shell的set -e。我的参考资料是“IEEE Std 1003.1-2008,2016版”,“Shell& Utilities”一章。从this section我看到-e在管道中命令失败时不会导致脚本退出(除非失败的命令是管道中的最后一个命令):

  

多命令管道中任何单个命令的失败都不会导致shell退出。只考虑管道本身的故障。

然后我写了一个简单的脚本来确认这种行为:

(
    set -e
    false | true | false | true
    echo ">> Multi-command pipeline: Last command succeeded."
)
(
    set -e
    false | true | false
    echo ">> Multi-command pipeline: Last command failed."
)

打印出“Last command succeeded”消息,而“Last command failed”消息则不打印。

我的问题是:

  • 链式命令false | true | false似乎不是管道的失败。这只是最后一个命令的失败。 管道本身仍然成功。我是对的吗?
  • 有没有办法模拟管道故障?我们可以使用false来模拟命令的失败。是否有类似的管道命令?

2 个答案:

答案 0 :(得分:1)

默认情况下,bash中管道的成功或失败仅由管道中的最后一个命令决定。

但是,您可以启用pipefail选项(set -o pipefail),如果管道中的任何命令失败,管道将返回失败。

实施例

此管道成功:

$ false | true | false | true ; echo $?
0

此管道失败:

$ set -o pipefail
$ false | true | false | true ; echo $?
1

文档

来自man bash

  

管道的返回状态是最后一个的退出状态   命令,除非启用了pipefail选项。如果是pipefail   启用后,管道的返回状态是最后一个的值   (最右边)命令以非零状态退出,如果全部退出则为零   命令退出成功。

答案 1 :(得分:1)

  

链式命令false | true | false似乎不是管道的失败。它只是最后一个命令的失败。管道本身仍然成功。我是对的吗?

管道的成功被指定为最后一个命令的成功。他们是一回事。

来自§2.9.2 Pipelines

  

如果管道不以!保留字开头,退出状态应为管道中指定的最后一个命令的退出状态。否则,退出状态应为最后一个命令的退出状态的逻辑NOT。也就是说,如果最后一个命令返回零,则退出状态应为1;如果最后一个命令返回大于零,则退出状态应为零。

在bash和ksh中,如果其中的任何命令失败,您可以使用set -o pipefail导致管道失败。不幸的是,这是not a POSIX option。它应该是,但它不是。