How to send a stream with python fabric
Question: I need to send the stdout stream of a program across a network, to the stdin
of another program, running on another host.

This can be easily accomplished using ssh:

    
    
    program 1 | ssh host 'program 2'
    

It's trivial to call this using `subprocess`:

    
    
    subprocess.call("program 1 | ssh host 'program 2'", shell=True)
    

However, since I need to run many other commands on the remote host, I'm using
[fabric](http://fabfile.org).

Sending files with fabric is easy enough, but I can't find any documentation
on sending streams. I know fabric uses the paramiko ssh library, so I could
[use it's channel](http://stackoverflow.com/questions/2554292/how-to-send-eof-
to-stdin-in-paramiko) but there seems to be no documentation for accessing the
channel from fabric.


Answer: I ended up digging through the fabric source code
(`fabric.operations._execute`) and came up this:

    
    
    from fabric.state import default_channel
    import subprocess
    
    def remote_pipe(local_command, remote_command, buf_size=1024):
        '''executes a local command and a remove command (with fabric), and 
        sends the local's stdout to the remote's stdin.
        based on fabric.operations._execute'''
        local_p= subprocess.Popen(local_command, shell=True, stdout=subprocess.PIPE)
        channel= default_channel() #fabric function
        channel.set_combine_stderr(True)
        channel.exec_command( remote_command )
        read_bytes= local_p.stdout.read(buf_size)
        while read_bytes:
            channel.sendall(read_bytes)
            read_bytes= local_p.stdout.read(buf_size)
        local_ret= local_p.wait()
        channel.shutdown_write()
        received= channel.recv(640*1024) #ought to be enough for everyone
        remote_ret= channel.recv_exit_status()
        if local_ret!=0 or remote_ret!=0:
            raise Exception("remote_pipe failed: "+received)
    

