Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to test SSH availability

I need a Python program I'm using to poll a remote server for SSH connectivity and notify when it is available. I am currently doing this using paramiko; attempt to connect, if failure, wait and retry until success or max retries. This works, but it's a bit clunky. Also paramiko seems to either connect or throw an error, so the only way I could see to do this was with a try/except block which is bad, bad, bad. Here is the method:

def check_ssh(self, ip, user, key_file, initial_wait=0, interval=0, retries=1):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    sleep(initial_wait)

    for x in range(retries):
        try:
            ssh.connect(ip, username=user, key_filename=key_file)
            return True
        except Exception, e:
            print e
            sleep(interval)
    return False

There must be a more elegant solution than this. Paramiko is my SSH library of choice but am open to any suggestions here.

To clarify, I want to avoid using try / except as a means to control the normal flow of code execution - it should be used for catching actual errors such as bad host key, invalid user etc.

like image 554
nightowl Avatar asked Jan 09 '13 13:01

nightowl


People also ask

What is Paramiko SSH?

Paramiko is a Python library that makes a connection with a remote device through SSh. Paramiko is using SSH2 as a replacement for SSL to make a secure connection between two devices. It also supports the SFTP client and server model.

What is Paramiko transport?

class paramiko.Transport. An SSH Transport attaches to a stream (usually a socket), negotiates an encrypted session, authenticates, and then creates stream tunnels, called Channels, across the session. class paramiko.SSHClient. A high-level representation of a session with an SSH server.


1 Answers

As mentioned in the comment by frb, a try ... except block is a good approach to test availability of a specific service. You shouldn't use a "catch-all" except block though, but limit it to the specific exceptions that occur if the service is unavailable.

According to documentation, paramiko.SSHClient.connect may throw different exceptions, depending on the problem that occured while connecting. If you want to catch all those, your try ... except block would look like this:

try:
    ssh.connect(ip, username=user, key_filename=key_file)
    return True
except (BadHostKeyException, AuthenticationException, 
        SSHException, socket.error) as e:
    print e
    sleep(interval)

If just a subset of these exceptions is relevant to your case, put only those into the tuple after except.

like image 61
silvado Avatar answered Sep 27 '22 16:09

silvado