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

时间:2015-01-26 18:16:11

标签: pipe scons

scons专家 -

Scons认为这个失败的命令成功,而另一个时间运行scons表示所有目标都是最新的。 fribbleblat命令不存在。当管道中的“中间”命令失败时,会发生此行为,但是当管道中的最后一个命令失败时,则会发生此行为。

如何将管道命令中的错误传播到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

2 个答案:

答案 0 :(得分:2)

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

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

产生" fribblecat:命令未找到。"

> echo $?

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

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

查看UserGuide" 18。编写自己的建筑商" (http://www.scons.org/doc/production/HTML/scons-user.html),以及我们在http://www.scons.org/wiki/ToolsForFools撰写工具的指南。

答案 1 :(得分:2)

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')