【发布时间】:2026-02-14 21:30:01
【问题描述】:
我有一个管道命令,例如:
set -euxo pipefail
echo 'hello' | foo | touch example.sh
这是输出:
$ set -euxo pipefail
$ echo hello
$ foo
$ touch example.sh
pipefail.sh: line 4: foo: command not found
我认为set -e 会导致脚本退出。但即使foo 无法识别,脚本仍在执行touch 命令。如果foo 失败,我如何让它退出?
【问题讨论】:
-
管道的所有组件同时发生。您的代码停止执行管道之后的任何额外行。它无法阻止其他流水线阶段的运行。
-
那么失败就没有办法退出了吗?
-
想想管道的作用:
echo hello | foo | touch example.sh将运行echo的子shell 的标准输出连接到将使用exec将自身替换为foo的子shell 的标准输入,和foo的标准输出到子shell 的标准输入,它将用touch替换自己。然后,在建立这些连接之后,它会启动所有三个程序并并行运行它们。显然,在您启动程序之前,您无法判断程序是否会失败。 -
现在,如果你有
echo hello | foo | cat; touch example.sh,那个会按照你的预期行事。 (cat只是一个占位符,表明foo不需要在尾部位置)。 -
好的。如果命令是这样的:gunzip file1 | gzip文件1?第一个管道的结果被传递到第二个管道。这两个不是同时发生的吧?这是我的真实用例。我们可能会收到一个常规的 .txt 文件,但程序没有退出。