For some reason Paramiko’s SSHClient.exec_command has an issue with setting timeouts.
For example, despite passing the timeout=3 to the client.connect, the code below will not timeout if the connection to the server is flaky.
client = paramiko.SSHClient()
client._policy = paramiko.AutoAddPolicy()
client.load_system_host_keys()
client.connect(host, int(port), username=getpass.getuser(),
timeout=3)
stdin, stdout, stderr = client.exec_command('ls -l /tmp')
print stdout.read()
I found a nice workaround on a comment to a blog post by a chap who was having the same problem - http://www.stillhq.com/commentform.cgi?post=python/paramiko/000004 and I am blogging it here for posterity. It involves overiding the exec_command method to accept at timeout like so:
class mySSHClient(paramiko.SSHClient):
## overload the exec_command method
def exec_command(self, command, bufsize=-1, timeout=None):
chan = self._transport.open_session()
chan.settimeout(timeout)
chan.exec_command(command)
stdin = chan.makefile('wb', bufsize)
stdout = chan.makefile('rb', bufsize)
stderr = chan.makefile_stderr('rb', bufsize)
return stdin, stdout, stderr
client = mySSHClient()
client._policy = paramiko.AutoAddPolicy()
client.load_system_host_keys()
client.connect(host, int(port), username=getpass.getuser())
stdin, stdout, stderr = client.exec_command('ls -l /tmp',timeout=3)
print stdout.read()
Works like a charm!