SaltyCrane Blog — Notes on JavaScript and web development

Python paramiko notes

Paramiko is a Python ssh package. The following is an example that makes use of my ssh config file, creates a ssh client, runs a command on a remote server, and reads a remote file using sftp. Paramiko is released under the GNU LGPL

Install paramiko

Example

from paramiko import SSHClient, SSHConfig

# ssh config file
config = SSHConfig()
config.parse(open('/home/saltycrane/.ssh/config'))
o = config.lookup('testapa')

# ssh client
ssh_client = SSHClient()
ssh_client.load_system_host_keys()
ssh_client.connect(o['hostname'], username=o['user'], key_filename=o['identityfile'])

# run a command
print "\nRun a command"
cmd = 'ps aux'
stdin, stdout, stderr = ssh_client.exec_command(cmd)
for i, line in enumerate(stdout):
    line = line.rstrip()
    print "%d: %s" % (i, line)
    if i >= 9:
        break

# open a remote file
print "\nOpen a remote file"
sftp_client = ssh_client.open_sftp()
sftp_file = sftp_client.open('/var/log/messages')
for i, line in enumerate(sftp_file):
    print "%d: %s" % (i, line[:15])
    if i >= 9:
        break
sftp_file.close()
sftp_client.close()

# close ssh client
ssh_client.close()

Results:

Run a command
0: USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1: root         1  0.0  0.0   1920   536 ?        S     2009   0:00 /sbin/init
2: root         2  0.0  0.0      0     0 ?        S     2009   0:00 [migration/0]
3: root         3  0.0  0.0      0     0 ?        SN    2009   0:00 [ksoftirqd/0]
4: root         4  0.0  0.0      0     0 ?        S     2009   0:00 [watchdog/0]
5: root         5  0.0  0.0      0     0 ?        S<    2009   0:00 [events/0]
6: root         6  0.0  0.0      0     0 ?        S<    2009   0:00 [khelper]
7: root         7  0.0  0.0      0     0 ?        S<    2009   0:00 [kthread]
8: root         8  0.0  0.0      0     0 ?        S<    2009   0:00 [xenwatch]
9: root         9  0.0  0.0      0     0 ?        S<    2009   0:00 [xenbus]

Open a remote file
0: Feb 21 06:47:03
1: Feb 21 07:14:03
2: Feb 21 07:34:03
3: Feb 21 07:54:04
4: Feb 21 08:14:04
5: Feb 21 08:34:05
6: Feb 21 08:54:05
7: Feb 21 09:14:05
8: Feb 21 09:34:06
9: Feb 21 09:54:06

Some SFTP helper code

Added 2011-09-15

import errno
import os.path

import paramiko


class SFTPHelper(object):

    def connect(self, hostname, **ssh_kwargs):
        """Create a ssh client and a sftp client

        **ssh_kwargs are passed directly to paramiko.SSHClient.connect()
        """
        self.sshclient = paramiko.SSHClient()
        self.sshclient.load_system_host_keys()
        self.sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.sshclient.connect(hostname, **ssh_kwargs)
        self.sftpclient = self.sshclient.open_sftp()

    def remove_directory(self, path):
        """Remove remote directory that may contain files.
        It does not support directories that contain subdirectories
        """
        if self.exists(path):
            for filename in self.sftpclient.listdir(path):
                filepath = os.path.join(path, filename)
                self.sftpclient.remove(filepath)
            self.sftpclient.rmdir(path)

    def put_directory(self, localdir, remotedir):
        """Put a directory of files on the remote server
        Create the remote directory if it does not exist
        Does not support directories that contain subdirectories
        Return the number of files transferred
        """
        if not self.exists(remotedir):
            self.sftpclient.mkdir(remotedir)
        count = 0
        for filename in os.listdir(localdir):
            self.sftpclient.put(
                os.path.join(localdir, filename),
                os.path.join(remotedir, filename))
            count += 1
        return count

    def exists(self, path):
        """Return True if the remote path exists
        """
        try:
            self.sftpclient.stat(path)
        except IOError, e:
            if e.errno == errno.ENOENT:
                return False
            raise
        else:
            return True

See also

Comments