@@ -147,6 +147,7 @@ def exec_command(self, command, sudo=False, **kwargs):
147147 """
148148 channel = self .client .get_transport ().open_session ()
149149 channel .get_pty ()
150+ # stdin (unused), stdout, stderr
150151 (_ , stdout , stderr ) = (channel .makefile ('wb' ), channel .makefile ('rb' ),
151152 channel .makefile_stderr ('rb' ))
152153 if sudo :
@@ -260,6 +261,30 @@ def __init__(self, hosts,
260261 >>> print output
261262 [{'myhost1': {'exit_code': 2}}, {'myhost2': {'exit_code': 2}}]
262263
264+ **Example with returned stdout and stderr buffers**
265+
266+ >>> from pssh import ParallelSSHClient, AuthenticationException,\
267+ UnknownHostException, ConnectionErrorException
268+ >>> try:
269+ >>> ... client = ParallelSSHClient(['myhost1', 'myhost2'])
270+ >>> except (AuthenticationException, UnknownHostException, ConnectionErrorException):
271+ >>> ... return
272+ >>> cmds = client.exec_command('ls -ltrh /tmp/aasdfasdf', sudo = True)
273+ >>> output = [client.get_stdout(cmd, return_buffers=True) for cmd in cmds]
274+ >>> print output
275+ [{'myhost1': {'exit_code': 2},
276+ 'stdout' : <generator object <genexpr>,
277+ 'stderr' : <generator object <genexpr>},
278+ {'myhost2': {'exit_code': 2}
279+ 'stdout' : <generator object <genexpr>,
280+ 'stderr' : <generator object <genexpr>},
281+ ]
282+ >>> for host_stdout in output:
283+ ... for line in host_stdout[host_output.keys()[0]]['stdout']:
284+ ... print line
285+ ls: cannot access /tmp/aasdfasdf: No such file or directory
286+ ls: cannot access /tmp/aasdfasdf: No such file or directory
287+
263288 **Example with specified private key**
264289
265290 >>> import paramiko
@@ -335,7 +360,7 @@ def _exec_command(self, host, *args, **kwargs):
335360 port = self .port , pkey = self .pkey )
336361 return self .host_clients [host ].exec_command (* args , ** kwargs )
337362
338- def get_stdout (self , greenlet ):
363+ def get_stdout (self , greenlet , return_buffers = False ):
339364 """Print stdout from greenlet and return exit code for host
340365
341366 :mod:`pssh.get_stdout` will close the open SSH channel but this does
@@ -345,20 +370,38 @@ def get_stdout(self, greenlet):
345370 will open a new channel which is very fast on already established
346371 connections.
347372
373+ By default, stdout and stderr will be logged via the logger named \
374+ `host_logger` unless return_buffers is set to True in which case \
375+ both buffers are returned along with the exit status.
376+
348377 :param greenlet: Greenlet object containing an \
349378 SSH channel reference, hostname, stdout and stderr buffers
350379 :type greenlet: :mod:`gevent.Greenlet`
351380
381+ :param return_buffers: Flag to turn on returning stdout and stderr \
382+ buffers along with exit code. Defaults to off.
383+ :type return_buffers: bool
384+
352385 :rtype: Dictionary containing ``{host: {'exit_code': exit code}}`` entry \
353386 for example ``{'myhost1': {'exit_code': 0}}``
387+ :rtype: With return_buffers=True: ``{'myhost1': {'exit_code': 0},
388+ 'stdout' : <iterable>,
389+ 'stderr' : <iterable>}``
354390 """
355- channel , host , stdout , stderr = greenlet .get ()
356- for line in stdout :
357- host_logger .info ("[%s]\t %s" , host , line .strip (),)
358- for line in stderr :
359- host_logger .info ("[%s] [err] %s" , host , line .strip (),)
391+ channel , host , _stdout , _stderr = greenlet .get ()
392+ stdout = (line .strip () for line in _stdout )
393+ stderr = (line .strip () for line in _stderr )
360394 channel .close ()
361- return {host : {'exit_code' : channel .recv_exit_status ()}}
395+ # import ipdb; ipdb.set_trace()
396+ if not return_buffers :
397+ for line in stdout :
398+ host_logger .info ("[%s]\t %s" , host , line ,)
399+ for line in stderr :
400+ host_logger .info ("[%s] [err] %s" , host , line ,)
401+ return {host : {'exit_code' : channel .recv_exit_status (),}}
402+ return {host : {'exit_code' : channel .recv_exit_status (),
403+ 'stdout' : stdout ,
404+ 'stderr' : stderr , }}
362405
363406 def copy_file (self , local_file , remote_file ):
364407 """Copy local file to remote file in parallel
@@ -402,7 +445,8 @@ def test():
402445def test_parallel ():
403446 client = ParallelSSHClient (['localhost' ])
404447 cmds = client .exec_command ('ls -ltrh' )
405- print [client .get_stdout (cmd ) for cmd in cmds ]
448+ output = [client .get_stdout (cmd , return_buffers = True ) for cmd in cmds ]
449+ print output
406450 cmds = client .copy_file ('../test' , 'test_dir/test' )
407451 client .pool .join ()
408452
0 commit comments