Check if paramiko ssh connection is still alive

Question:

Is there a way to check if a paramiko SSH connection is still alive?

In [1]: import paramiko

In [2]: ssh = paramiko.SSHClient() 

In [3]: ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

In [4]: ssh.connect(hostname)

I want to mimic something like this (which doesn’t currently exist)

In [5]: ssh.isalive()
True
Asked By: MRocklin

||

Answers:

 if ssh.get_transport() is not None:
     ssh.get_transport().is_active()

should do it …. assuming I read the docs right.

Answered By: Joran Beasley

I had observed is_active() returning false positives.

I would recommend using this piece:

  # use the code below if is_active() returns True
  try:
      transport = client.get_transport()
      transport.send_ignore()
  except EOFError, e:
      # connection is closed
Answered By: user2488286

For me the above answer doesn’t work so I’ve done it by sending an exec_command() with a timeout :

self.ssh.exec_command('ls', timeout=5)

for exemple the full method will be like :

def check_connection(self):
    """
    This will check if the connection is still availlable.

    Return (bool) : True if it's still alive, False otherwise.
    """
    try:
        self.ssh.exec_command('ls', timeout=5)
        return True
    except Exception as e:
        print "Connection lost : %s" %e
        return False

and I call it every 5 or so seconds.

Answered By: Robin Jacquelin

I was having issues at the moment to download a file after 5 minutes or less of inactivity ( the exception that I was getting was paramiko.ssh_exception.SSHException), the way I handled a possible fix was the following:


class ...:

def connect(self) -> paramiko.SFTPClient:
        """
        Important information to take into consideration:
        - with .ppk files, the following exception is being raised.
        paramiko.ssh_exception.SSHException: not a valid RSA private key file

        - a possible fix is to convert .ppk file to .pem file
        brew install putty
        puttygen <filename>.ppk -O private-openssh -o <filename>.pem

        - then the content of the .pem file should be updated in GCP secret manager.
        """

        transport = paramiko.Transport(self.hostname, int(self.port))
        params: Dict[str, Any] = {
            "username": self.username,
        }
        if self.password:
            params.update(
                {
                    "password": self.password,
                }
            )

        if self.certificate:
            private_key = paramiko.RSAKey.from_private_key(open(self.certificate))
            params.update(
                {
                    "pkey": private_key,
                }
            )

        transport.connect(**params)
        conn = paramiko.SFTPClient.from_transport(transport)
        if conn:
            if required_directory := self.directory:
                conn.chdir(required_directory)
            return conn
        raise SFTPClientException(f"Unable to connect to sftp {self.hostname}")


def reconnect(self) -> None:
        """
        Start a new connection to sftp host
        """
        self.client = self.connect()

def download_file(self, path_file: str) -> str:
        """
        Download a file from a specific path.
        """
        from os import path

        local_destination: str = f"/tmp/{uuid4()}_{path.basename(path_file)}"
        try:
            self.client.get(path_file, local_destination)
        except paramiko.ssh_exception.SSHException:
            self.reconnect()
            self.client.get(path_file, local_destination)

        return local_destination

I really hope the shared code helps anybody who is facing a similar incident.

Answered By: Manuel Lazo
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.