This post shows how to use the Python library Paramiko to implement a SSH client, programmatically connect to another computer over SSH and execute a shell command on that computer. Authentication is performed using either username and password or username and a cryptographic key.
Paramiko have many more features than the ones I use in the example in this article, such as being able to function as a SSH server, SFTP client etc. Please refer to the Paramiko documentation for further details!
You need a computer that you can connect to using SSH. To determine whether you have SSH access, either use ssh in a terminal window (Linux and OS X users) or use PuTTY (Windows).
If you want to run the example program in an IDE and don’t already have one, I recommend JetBrains PyCharm – there is a free community edition available.
Finally, you need to have Paramiko installed, which I will describe how to in the next section.
Installing Paramiko from a Terminal Window
To install Paramiko from a terminal window, use:
pip install paramiko
If you are on Windows, there may be an error telling you that you need to install a library from Microsoft that is required by Paramiko.
Go to the URL shown in the error message and follow the instructions, the retry the installation using pip.
Installing Paramiko from within PyCharm
If you are developing in JetBrain’s PyCharm and assuming that you already have created a new project (File -> New Project), use the following procedure:
- Open the Preferences.
- In the Preferences, locate the Project node and the Project Interpreter node below the Project node.
In my case it looks like this (yes, I have already installed Paramiko and yes, my project is named “test”):
- Click the + button in the lower left of the packages list to install a new package.
- Type “paramiko” without quotes in the new dialog window that appears.
The result should look like this:
- Click the Install Package button.
If you are on Windows, there may be an error message telling you that you need to install a library from Microsoft required by Paramiko.
Go to the URL shown in the error message and follow the instructions. After having installed the library, repeat the process of installing the Paramiko package in PyCharm.
Private Key File
If you do not have a private keyfile and only use a regular login and password when establishing a SSH connection, just skip this part.
If you do intend to authenticate using a private key, you need to create keyfile named “private_key_file” with the key in it and add it to your Python project.
I had a lot of problems obtaining a file in the proper format. My private key is a DSA private key and the keyfile I successfully used with Paramiko looks like this:
-----BEGIN DSA PRIVATE KEY----- [contents omitted] -----END DSA PRIVATE KEY-----
Show Me the Code!
I have written a function that connects to a SSH host and executes a command. The function returns a tuple consisting of two lists of strings. The first list of strings is the output to standard out as produced when the command executed on the remote computer. The second list of strings is the output to standard err produced at the same occasion.
import time import paramiko def execute_ssh_command(host, port, username, password, keyfilepath, keyfiletype, command): """ execute_ssh_command(host, port, username, password, keyfilepath, keyfiletype, command) -> tuple Executes the supplied command by opening a SSH connection to the supplied host on the supplied port authenticating as the user with supplied username and supplied password or with the private key in a file with the supplied path. If a private key is used for authentication, the type of the keyfile needs to be specified as DSA or RSA. :rtype: tuple consisting of the output to standard out and the output to standard err as produced by the command """ ssh = None key = None try: if keyfilepath is not None: # Get private key used to authenticate user. if keyfiletype == 'DSA': # The private key is a DSA type key. key = paramiko.DSSKey.from_private_key_file(keyfilepath) else: # The private key is a RSA type key. key = paramiko.RSAKey.from_private_key(keyfilepath) # Create the SSH client. ssh = paramiko.SSHClient() # Setting the missing host key policy to AutoAddPolicy will silently add any missing host keys. # Using WarningPolicy, a warning message will be logged if the host key is not previously known # but all host keys will still be accepted. # Finally, RejectPolicy will reject all hosts which key is not previously known. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # Connect to the host. if key is not None: # Authenticate with a username and a private key located in a file. ssh.connect(host, port, username, None, key) else: # Authenticate with a username and a password. ssh.connect(host, port, username, password) # Send the command (non-blocking) stdin, stdout, stderr = ssh.exec_command(command) # Wait for the command to terminate while not stdout.channel.exit_status_ready() and not stdout.channel.recv_ready(): time.sleep(1) stdoutstring = stdout.readlines() stderrstring = stderr.readlines() return stdoutstring, stderrstring finally: if ssh is not None: # Close client connection. ssh.close() host = '192.168.1.2' port = 22 username = 'ivan' password = 'secretpassword' keyfile_path = 'private_key_file' (stdoutstring, stderrstring) = execute_ssh_command(host, port, username, password, None, None, "ls -al") for stdoutrow in stdoutstring: print stdoutrow
The code above connects to a computer at the address 192.168.1.2 on port 22 over SSH using the user-name “ivan” and the password “secretpassword” and then execute the command “ls -al”.
If you want to use a private key, change the invocation of the execute_ssh_command function to:
(stdoutstring, stderrstring) = execute_ssh_command(host, port, username, None, keyfile_path, 'DSA', "ls -al")
Note that the ‘DSA’ value should be replaced with ‘RSA’ if your private key is a RSA key and you should ensure that the path to the keyfile is correct.
If you now run the program, a directory listing of your remote computer should be printed to the console.