Take the 2-minute tour ×

I am trying to combine the output of stdout and stderr. My belief is that this can be done with the set_combine_stderr() of a Channel object.

This is what I am doing:

SSH = paramiko.SSHClient()
#I connect and everything OK, then:
chan = ssh.invoke_shell()
chan.exec_command('python2.6 subir.py')
resultado = chan.makefile('rb', -1.)

However, I get the following error when I try to store the result (last line above, chan.makefile() ):

Error: Channel closed.

Any help would be greatly appreciated

share|improve this question
add comment

2 Answers

While it is true that set_combine_stderr diverts stderr to the stdout stream, it does so in chaotic order, so you do not get the result you probably want, namely, the lines combined in the order written, as if you were running the command in a local terminal window. Instead, use get_pty. That will cause the server to run the lines through a pseudo-terminal, keeping them in chronological sequence.

Here's a test program, outerr.py, that writes alternating lines on stdout and stdin. Assume it's sitting in the home directory of llmps@meerkat2.

#!/usr/bin/env python

import sys

for x in xrange(1, 101):
    (sys.stdout, sys.stderr)[x%2].write('This is line #%s, on std%s.\n' %
                (x, ('out', 'err')[x%2]))

Now try the following code to run it remotely:

#!/usr/bin/env python

import paramiko

def connect():
    ssh = paramiko.SSHClient()
    ssh.connect('meerkat2', username='llmps', password='..')
    return ssh

def runTest(ssh):
    tran = ssh.get_transport()
    chan = tran.open_session()
    # chan.set_combine_stderr(True)
    f = chan.makefile()
    print f.read(),

if __name__ == '__main__':
    ssh = connect()

If you run the above, you should see 100 lines in order as written. If, instead, you comment out the chan.get_pty() call and uncomment the chan.set_combine_stderr(True) call, you will get clumps of stdout and stderr lines interspersed randomly from run to run.

share|improve this answer
add comment

@AaronMcSmooth: I am referring to the stdout and stderr of the computer I am connecting to (via SSH).

I ended up doing this:

stdin, stdout, stderr = ssh.exec_command(...)

output = stdin.read().strip() + stdout.read().strip()

For the purpose of my application, it doesn't matter to distinguish between stdout and stderr, but I don't think that's the best way to combine the two.

The code of SSHClient.exec_command() is (looking at paramiko's source code):

def exec_command(self, command, bufsize=-1):
    chan = self._transport.open_session() 
    stdin = chan.makefile('wb', bufsize) 
    stdout = chan.makefile('rb', bufsize) 
    stderr = chan.makefile_stderr('rb', bufsize) 
    return stdin, stdout, stderr

I am performing the same actions on the channel but receive the Channel is closed error.

share|improve this answer
add comment

Your Answer


