我有一个 makefile,带有测试套件目标,如下所示:
rcheck:
foo
这显示了 stdout 上命令的输出foo
,并返回一个退出代码,foo
make 正常处理该退出代码。
我想添加某物到这个目标,解析foo
的输出而不影响现有行为 - 即:
foo
的 stdout/stderr 应该像以前一样显示在 stdout/stderr 上- 就 Make 而言,rcheck 目标的最终结果是
foo
退出代码是什么 - stdout from
foo
应该以某种方式传递给第二个命令bar
。bar
的退出代码并不重要,bar
除了上面的 1. 之外,不应该向 stdout 或 stderr 输出任何内容(除非解决方案意味着bar
处理 1. 本身)
这里最巧妙的解决方案是什么?
答案1
如果您不担心数据从 foo 传递到 bar 的时间,并且您可以使用需要在干净目标中处理的临时文件,那么只需:
rcheck:
foo | tee sometempfile
-bar < sometempfile >/dev/null 2>/dev/null
另一方面,如果您非常关心时间,那么您可以让 bar 重复其对 stdout 的输入,并尝试如下操作:
rcheck:
-(foo; echo $$? > sometempfile) | bar
exit $(cat sometempfile)
我确信会有更干净的方法,但我想到了上面的方法。 (注意,两者均未经测试)
答案2
如果您使用的 shell 支持该pipefail
选项(bash、ksh 和 zsh 都支持),您可以这样做:
rcheck:
set -o pipefail; foo | tee /dev/stderr | { bar >/dev/null 2>&1; true; }
我的 ksh 手册页将该选项记录为:
管道故障 直到管道的所有组件都完成后,管道才会完成 完成,返回值将是最后一个非零的值 命令失败或为零(如果没有命令失败)。
与默认行为相反:
管道的退出状态是最后一个命令的退出状态 除非启用了 pipelinefail 选项。