scons 无法注意到带有管道('|')的命令中的错误

scons fails to notice errors in commands with pipes ('|')

scons 专家 -

Scons 认为这个失败的命令成功了,并且 运行 再次 scons 表明所有目标都是最新的。 fribbleblat 命令不存在。当管道中的 'middle' 命令失败时会出现此行为,但不会在管道中的最后一个命令失败时出现。

如何将管道命令中的错误传播到 scons?

import os
from SCons.Script import Environment

env = Environment()
env.Command(source='foo',
            target='bar',
            action='cat $SOURCE | fribbleblat | cat >$TARGET')

运行 它两次表明 scons 认为它​​已经正确构建了目标。
[编辑:我创建了一个包含随机内容的文件 'foo',echo dslkfjds >foo]

$ scons -f SConstruct.exp 
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cat foo | fribbleblat | cat > bar
sh: 1: fribbleblat: not found
cat: write error: Broken pipe
scons: done building targets.

$ scons -f SConstruct.exp 
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.

$ scons --version
SCons by Steven Knight et al.:
        script: v2.3.0.rel_2.3.0:2870:c8dbbaa4598e, 2013/07/31 13:02:49, by bdbaddog on Williams-MacBook
        engine: v2.3.0, 2013/03/03 09:48:35, by garyo on reepicheep
        engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 The SCons Foundation

你的假设是错误的:认为命令成功的不是 SCons。在我的 Linux 系统上,命令

> cat test.txt | fribblecat | cat > out.txt

产生 "fribblecat: command not found." 和一个立即

> echo $?

结果为“0”(成功)。所以 shell 打开输出文件,并向 SCons 发出成功信号。您必须找到一种方法让管道序列在 shell 级别失败,例如通过将命令包装在 shell 脚本中,该脚本检查可执行文件 "fribblecat" 是否实际存在。 另一种选择是编写一个简单的 "fribblecat" 生成器,假设可执行文件支持输入和输出文件的命令行选项:

env = Environment()
env.Command('out.txt','test.txt','fribblecat -o $TARGET $SOURCE')

查看用户指南“18. 编写自己的构建器”(http://www.scons.org/doc/production/HTML/scons-user.html ), and our guide for writing Tools at http://www.scons.org/wiki/ToolsForFools .

dirkbaechle 是对的 - 事实证明这与其说是一个 scons 问题,不如说是一个 shell 问题。多一点搜索让我得到以下答案:

简短的回答是 'set -o pipefail',但这只适用于 bashkshzsh,但不适用于 sh,所以我必须确保 scons 也在调用 bash

以下 scons 文件按预期工作并捕获失败的命令。

import os
from SCons.Script import Environment

env = Environment()
env['SHELL'] = 'bash'
env['ENV']['SHELLOPTS'] = 'pipefail'

env.Command(source='foo',
            target='bar',
            action='cat $SOURCE | fribbleblat | cat >$TARGET')