@@ -104,7 +104,7 @@ def __init__(self, hosts, user=None, password=None, port=None, pkey=None,
104104
105105 def run_command (self , command , sudo = False , user = None , stop_on_errors = True ,
106106 use_pty = False , host_args = None , shell = None ,
107- encoding = 'utf-8' ):
107+ encoding = 'utf-8' , timeout = None ):
108108 """Run command on all hosts in parallel, honoring self.pool_size,
109109 and return output dictionary.
110110
@@ -152,6 +152,10 @@ def run_command(self, command, sudo=False, user=None, stop_on_errors=True,
152152 :param encoding: Encoding to use for output. Must be valid
153153 `Python codec <https://docs.python.org/2.7/library/codecs.html>`_
154154 :type encoding: str
155+ :param timeout: (Optional) Timeout in seconds for reading from stdout
156+ or stderr. Defaults to no timeout. Reading from stdout/stderr will
157+ timeout after this many seconds if remote output is not ready.
158+ :type timeout: int
155159
156160 :rtype: Dictionary with host as key and
157161 :py:class:`pssh.output.HostOutput` as value as per
@@ -169,24 +173,24 @@ def run_command(self, command, sudo=False, user=None, stop_on_errors=True,
169173 string format
170174 :raises: :py:class:`KeyError` on no host argument key in arguments
171175 dict for cmd string format
172- :raises: :py:class:`pssh.exceptions.ProxyErrors ` on errors connecting
176+ :raises: :py:class:`pssh.exceptions.ProxyError ` on errors connecting
173177 to proxy if a proxy host has been set.
174178 """
175179 return BaseParallelSSHClient .run_command (
176180 self , command , stop_on_errors = stop_on_errors , host_args = host_args ,
177181 user = user , shell = shell , sudo = sudo ,
178- encoding = encoding , use_pty = use_pty )
182+ encoding = encoding , use_pty = use_pty , timeout = timeout )
179183
180184 def _run_command (self , host , command , sudo = False , user = None ,
181185 shell = None , use_pty = False ,
182- encoding = 'utf-8' ):
186+ encoding = 'utf-8' , timeout = None ):
183187 """Make SSHClient if needed, run command on host"""
184188 self ._make_ssh_client (host )
185189 return self .host_clients [host ].run_command (
186190 command , sudo = sudo , user = user , shell = shell ,
187- use_pty = use_pty , encoding = encoding )
191+ use_pty = use_pty , encoding = encoding , timeout = timeout )
188192
189- def join (self , output , consume_output = False ):
193+ def join (self , output , consume_output = False , timeout = None ):
190194 """Wait until all remote commands in output have finished
191195 and retrieve exit codes. Does *not* block other commands from
192196 running in parallel.
@@ -198,11 +202,17 @@ def join(self, output, consume_output=False):
198202 buffers. Output buffers will be empty after ``join`` if set
199203 to ``True``. Must be set to ``True`` to allow host logger to log
200204 output on call to ``join`` when host logger has been enabled.
201- :type consume_output: bool"""
205+ :type consume_output: bool
206+ :param timeout: Timeout in seconds if remote command is not yet
207+ finished.
208+ :type timeout: int
209+
210+ :rtype: ``None``"""
202211 for host in output :
203212 if host not in self .host_clients or self .host_clients [host ] is None :
204213 continue
205- self .host_clients [host ].wait_finished (output [host ].channel )
214+ self .host_clients [host ].wait_finished (output [host ].channel ,
215+ timeout = timeout )
206216 if consume_output :
207217 for line in output [host ].stdout :
208218 pass
@@ -217,6 +227,8 @@ def _get_exit_code(self, channel):
217227 return channel .get_exit_status ()
218228
219229 def _start_tunnel (self , host ):
230+ if host in self ._tunnels :
231+ return self ._tunnels [host ]
220232 tunnel = Tunnel (
221233 self .proxy_host , host , self .port , user = self .proxy_user ,
222234 password = self .proxy_password , port = self .proxy_port ,
@@ -284,7 +296,7 @@ def copy_file(self, local_file, remote_file, recurse=False):
284296
285297 .. note ::
286298
287- Remote directories in `remote_file` that do not exist will be
299+ Remote directories in `` remote_file` ` that do not exist will be
288300 created as long as permissions allow.
289301
290302 """
0 commit comments