【发布时间】:2021-05-20 08:04:23
【问题描述】:
我刚刚注意到,即使编译失败,我的一些 CI 作业也返回了 OK。这本质上是因为调用 bash 命令来编译代码,虽然失败并返回 1,但它的输出通过sed 管道传输以向输出添加一些颜色等。
本质上,这归结为以下内容
$ false; echo $? # returns 1
$ true; echo $? # returns 0
$ false | sed 's/^/OUTPUT: /' # returns 0 because sed returns 0
$ true | sed 's/^/OUTPUT: /' # returns 0 because sed returns 0
我知道在 bash 上有PIPESTATUS,所以我可以使用${PIPESTATUS[0]} 来获取在管道之前运行的命令的退出代码。但是我如何对任何命令进行包装,以便将其输出通过管道传输到 sed,然后返回命令本身的退出代码(丢弃 sed 的退出代码)?
为了使它真正通用,假设我想通过管道将任何命令的输出传递给 sed,以便在每行输出之前添加一个彩色前缀:
$ PREFIX="$(printf '\033[1;31m')OUTPUT: $(printf '\033[0m')"
$ ls | sed "s/^/$PREFIX/"
如上所述,由于到sed 的管道,无论ls 返回什么,它都会返回0,并且将显示目录内容,每行前面都有一个红色OUTPUT: 。
我可以定义一个函数、别名等(我们称之为“包装”)来让我调用例如wrap ls *.txt 以这样的方式执行 ls *.txt,通过 sed 模式管道输出,并返回 ls *.txt 本身的退出代码,以便
$ wrap ls *.txt
OUTPUT: file1.txt
OUTPUT: file2.txt
$ echo $? # displays 0 (assuming there is at least one .txt file)
$ wrap ls *.foo
ls: No such file or directory
$ echo $? # displays 1 (assuming there is NO .foo file)
【问题讨论】:
-
set -o pipefail? Do not parse ls。或者只是command > >(sed 's/^/OUTPUT: /')? -
一个愚蠢的 hack 是
whatever | sed whatever | grep .如果没有来自sed的输出则失败。这显然只有在您总是期望sed脚本的输出时才有效,或者即使第一个命令失败也可能产生部分结果。 -
@JHH :输出是什么意思?标准输出、标准错误或两者兼有?
-
@user1934428 只是标准输出。
标签: bash sed pipe exit-code pipestatus