tee.py 1.43 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
'''
Launches a command, copyies its output both to standard output and in zero or more files,
and finally exits with the same exit code of the command.
'''

from __future__ import print_function

import sys
import subprocess
import shlex

import argparse

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-v', '--verbose', action='store_true', default=False)

parser.add_argument('cmd', help='''command to run''')
parser.add_argument('file', nargs='*', help='''output file(s)''')



22 23 24 25 26 27
def unbuffered_read(f):
    # see http://stackoverflow.com/a/1183654
    l = f.readline()
    while l:
        yield l
        l = f.readline()
28 29 30 31 32 33

def tee(cmd, outputs):
    '''Runs 'cmd', pipe the output to 'outputs', and returns the exit code of 'cmd' '''
    argz = shlex.split(cmd)
    p = subprocess.Popen(argz,
                         stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
34
                         bufsize=0,
35
                         close_fds=True)
36 37

    for l in unbuffered_read(p.stdout):
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
        for o in outputs:
            o.write(l)

    p.wait()
    return p.returncode



if __name__ == '__main__':

    args = parser.parse_args()
    outputs = [sys.stdout]

    print()

    for f in args.file:
        print('==> %s' % f)
        outputs += [open(f, 'w')]

    if args.verbose:
        print('### %s' % args.cmd)
        
    ex = tee(args.cmd, outputs)

    if args.verbose:
        print('##> %s' % ex)

    sys.exit(ex)