Introduction
SSH (secure shell) is good for remotely managing machines using a secure connection.
Typically you will log in to a server using the command-line ssh
tool, or something like
PuTTy or MobaXTerm. This guide will show you how to use Python to connect and run commands
over SSH using the Paramiko package.
Installation
The easiest way to install paramiko
is using pip
.
python -m pip install paramiko
To install from source, clone from GitHub and then install using setup.py
.
git clone https://github.com/paramiko/paramiko
cd paramiko
python setup.py install
Connect to SSH
Connect to an SSH server using
paramiko.client.SSHClient.connect(). The hostname
is the only required parameter.
connect(hostname, port=22, username=None, password=None, pkey=None, key_filename=None, timeout=None, allow_agent=True, look_for_keys=True, compress=False, sock=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True, gss_host=None, banner_timeout=None, auth_timeout=None, gss_trust_dns=True, passphrase=None, disabled_algorithms=None)
One thing to consider is what trusted known host keys you have.
You can use paramiko.client.SSHClient.load_system_host_keys()
.
You can also explicitly load a specific known hosts file with load_host_keys()
and set the client to automatically accept and add unknown hosts with
set_missing_host_key_policy()
to paramiko.AutoAddPolicy
.
Use these options as needed. The AutoAddPolicy is not very secure
since it will trust any remote host.
Connect using password
from paramiko import SSHClient
client = SSHClient()
#client.load_system_host_keys()
#client.load_host_keys('~/.ssh/known_hosts')
#client.set_missing_host_key_policy(AutoAddPolicy())
client.connect('example.com', username='user', password='secret')
client.close()
Connect using SSH key
Using an SSH key is more secure than using a password.
Call connect()
just like using the password, but instead of providing
the user password, we will provide a key_filename
and maybe a passphrase
for the key.
The passphrase may not be needed if your private key file does not have a passphrase.
You can also omit the key file and let Paramiko try to find the right key automatically
in your ~/.ssh/
directory. You can turn that on by calling client.look_for_keys(True)
.
The first example will show how to explicitly provide the key and passphrase and the second
one will show how to look for keys.
# Explicitly provide key and passphrase
from paramiko import SSHClient, AutoAddPolicy
client = SSHClient()
#client.load_system_host_keys()
#client.load_host_keys('~/.ssh/known_hosts')
#client.set_missing_host_key_policy(AutoAddPolicy())
client.connect('example.com', username='user', key_filename='mykey.pem', passphrase='mysshkeypassphrase')
client.close()
This example show hows to look for keys in ~/.ssh/
automatically.
from paramiko import SSHClient
client = SSHClient()
#client.load_system_host_keys()
#client.load_host_keys('~/.ssh/known_hosts')
#client.set_missing_host_key_policy(AutoAddPolicy())
client.look_for_keys(True)
client.connect('example.com', username='user')
client.close()
Run commands over SSH
Once you have a connection open, you can execute any command just like you would if you were in a regular interactive SSH session.
This example shows how to:
- Run a command on the server
- Provide standard input data to command
- Read standard output and error from command
- Get the return code of the command
The command run in this example is the PHP interpreter with the code provided via standard input. The output is then printed out and the return code is checked.
from paramiko import SSHClient
# Connect
client = SSHClient()
client.load_system_host_keys()
client.connect('example.com', username='user', password='secret')
# Run a command (execute PHP interpreter)
stdin, stdout, stderr = client.exec_command('php')
print(type(stdin)) # <class 'paramiko.channel.ChannelStdinFile'>
print(type(stdout)) # <class 'paramiko.channel.ChannelFile'>
print(type(stderr)) # <class 'paramiko.channel.ChannelStderrFile'>
# Optionally, send data via STDIN, and shutdown when done
stdin.write('<?php echo "Hello!"; sleep(2); ?>')
stdin.channel.shutdown_write()
# Print output of command. Will wait for command to finish.
print(f'STDOUT: {stdout.read().decode("utf8")}')
print(f'STDERR: {stderr.read().decode("utf8")}')
# Get return code from command (0 is default for success)
print(f'Return code: {stdout.channel.recv_exit_status()}')
# Because they are file objects, they need to be closed
stdin.close()
stdout.close()
stderr.close()
# Close the client itself
client.close()
Conclusion
After reading this guide you should know how to connect to an SSH server using a password or SSH key. You should also know how to run a command, pass data to standard input, and read the output from standard output and error.