Please note:The SCons wiki is in read-only mode due to ongoing spam/DoS issues. Also, new account creation is currently disabled. We are looking into alternative wiki hosts.

Sometimes you want to write the SCons output to a file as well as see it on the screen. The following Bourne shell command will do just that:

scons 2>&1 | tee build.log

The 2>&1 bit (which pipes stderr to stdout) only works in Bourne shells (sh, bash) and not csh or tcsh. If you are using csh or tcsh, use the following command:

scons >&| tee build.log

Since the above command is a fair amount of typing, you can set up a function for it:

build() {
    scons $* 2>&1 | tee build.log

When you start using the 'build' command instead of 'scons', it doesn't matter if errors go flying by. You can just look in the log!

If you want to set this up in the SConstruct file rather than on the command line:

   1 import sys
   2 import os
   3 sys.stdout = os.popen("tee build.log", "w")
   4 sys.stderr = sys.stdout

As an alternative, Timothee Besset posted some code on the scons users mailing list on sept. 30, 2004 to do this within scons:

Here are some snippets:

   1 # need an Environment and a matching buffered_spawn API .. encapsulate
   2 class idBuffering:
   4         def buffered_spawn( self, sh, escape, cmd, args, env ):
   5                 stderr = StringIO.StringIO()
   6                 stdout = StringIO.StringIO()
   7                 command_string = ''
   8                 for i in args:
   9                         if ( len( command_string ) ):
  10                                 command_string += ' '
  11                         command_string += i
  12                 try:
  13                         retval = self.env['PSPAWN']( sh, escape, cmd, args, env, stdout, stderr )
  14                 except OSError, x:
  15                         if x.errno != 10:
  16                                 raise x
  17                         print 'OSError ignored on command: %s' % command_string
  18                         retval = 0
  19                 print command_string
  20                 sys.stdout.write( stdout.getvalue() )
  21                 sys.stderr.write( stderr.getvalue() )
  22                 return retval
  24 # get a clean error output when running multiple jobs
  25 def SetupBufferedOutput( env ):
  26         buf = idBuffering()
  27         buf.env = env
  28         env['SPAWN'] = buf.buffered_spawn

Timothee's original message is at

Timothee, hope you don't mind my posting this. -- Gary Oberbrunner

Using subprocess

My issue was not writing to a log file and the screen, but not getting output at all under buildbot. If I ran SCons from buildbot it captured no output from tools which SCons invoked. I tried idBuffering above but it did not work for me. The implementation of PSPAWN was a little scary. Since I'm using Python 2.5 I tried subprocess, it worked. This is on Windows.

Is there some other way to get around this issue with buildbot? Seems like everyone would want to see the output of tools launched by SCons in the log file, but I did not find anything on this problem.

This routine is surely incomplete but is working for us. Should it catch OSError like idBuffering does?

   1 import subprocess
   3 def echospawn( sh, escape, cmd, args, env ):
   4     """Spawn which echos stdout/stderr from the child."""
   6     # convert env from unicode strings
   7     asciienv = {}
   8     for key, value in env.iteritems():
   9         asciienv[key] = str(value)    
  11     p = subprocess.Popen(
  12         args, 
  13         env=asciienv, 
  14         stderr=subprocess.PIPE,
  15         stdout=subprocess.PIPE,
  16         shell=True,
  17         universal_newlines=True)
  18     (stdout, stderr) = p.communicate()
  20     # Does this screw up the relative order of the two?
  21     sys.stdout.write(stdout)
  22     sys.stderr.write(stderr)
  23     return p.returncode
  25 env['SPAWN']=echospawn

BuildLog (last edited 2008-05-07 20:53:31 by PhilipWinston)