What is the simplest way to SSH using Python?
Asked Answered
H

12

88

How can I simply SSH to a remote server from a local Python (3.0) script, supply a login/password, execute a command and print the output to the Python console?

I would rather not use any large external library or install anything on the remote server.

Homothermal answered 5/8, 2009 at 14:34 Comment(0)
B
43

I haven't tried it, but this pysftp module might help, which in turn uses paramiko. I believe everything is client-side.

The interesting command is probably .execute() which executes an arbitrary command on the remote machine. (The module also features .get() and .put methods which allude more to its FTP character).

UPDATE:

I've re-written the answer after the blog post I originally linked to is not available anymore. Some of the comments that refer to the old version of this answer will now look weird.

Brillatsavarin answered 5/8, 2009 at 14:49 Comment(7)
Good find! As long as you don't care about customizing error responses, this additional abstraction would be very useful.Handcart
The ssh module did the trick. Simple and works fine. No searching through the Paramiko API.Homothermal
The link to the ssh.py file inside the link you give is broken :/Hurdygurdy
Yup, can we have a new link please. I found ssh.py on github, but it's not the same (and not as good)Alake
The pysftp package only provides SFTP. Far from a SSH client.Collado
@Collado I haven't tested but my understanding was that the .execute() method executes an arbitrary command on the remote machine - which is as close to an ssh client as you can get programmatically. .get() and .put() methods seem like add-ons to this.Brillatsavarin
@dgorissen: You can get this (or very similar) script here: github.com/tadeck/ssh-matic/tree/master/ssh. I will separate it into different module for easier usage.Magical
O
63

You can code it yourself using Paramiko, as suggested above. Alternatively, you can look into Fabric, a python application for doing all the things you asked about:

Fabric is a Python library and command-line tool designed to streamline deploying applications or performing system administration tasks via the SSH protocol. It provides tools for running arbitrary shell commands (either as a normal login user, or via sudo), uploading and downloading files, and so forth.

I think this fits your needs. It is also not a large library and requires no server installation, although it does have dependencies on paramiko and pycrypt that require installation on the client.

The app used to be here. It can now be found here.

* The official, canonical repository is git.fabfile.org
* The official Github mirror is GitHub/bitprophet/fabric

There are several good articles on it, though you should be careful because it has changed in the last six months:

Deploying Django with Fabric

Tools of the Modern Python Hacker: Virtualenv, Fabric and Pip

Simple & Easy Deployment with Fabric and Virtualenv


Later: Fabric no longer requires paramiko to install:

$ pip install fabric
Downloading/unpacking fabric
  Downloading Fabric-1.4.2.tar.gz (182Kb): 182Kb downloaded
  Running setup.py egg_info for package fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
Downloading/unpacking ssh>=1.7.14 (from fabric)
  Downloading ssh-1.7.14.tar.gz (794Kb): 794Kb downloaded
  Running setup.py egg_info for package ssh
Downloading/unpacking pycrypto>=2.1,!=2.4 (from ssh>=1.7.14->fabric)
  Downloading pycrypto-2.6.tar.gz (443Kb): 443Kb downloaded
  Running setup.py egg_info for package pycrypto
Installing collected packages: fabric, ssh, pycrypto
  Running setup.py install for fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
    Installing fab script to /home/hbrown/.virtualenvs/fabric-test/bin
  Running setup.py install for ssh
  Running setup.py install for pycrypto
...
Successfully installed fabric ssh pycrypto
Cleaning up...

This is mostly cosmetic, however: ssh is a fork of paramiko, the maintainer for both libraries is the same (Jeff Forcier, also the author of Fabric), and the maintainer has plans to reunite paramiko and ssh under the name paramiko. (This correction via pbanka.)

Otero answered 5/8, 2009 at 15:0 Comment(3)
As this seems an interesting link, I'd like to update it as yours is now broken. please use: clemesha.org/blog/…Eponymy
Didn't the asker specify that he doesn't want to use a "large external library" ? Paramiko and Fabric are both overkill when all the author really asked for is a simple one-off ssh recipe.Innovation
@Zoran Pavlovic: all answers were either to install a local package (paramiko, fabric, ssh, libssh2) or to use subprocess to run ssh. The latter is a no-install solution, but I don't think spawning ssh is a great idea, and neither did the OP since he selected the answer to install ssh module. Those docs say: "ssh.py provides three common SSH operations, get, put and execute. It is a high-level abstraction upon Paramiko." So unless you favor libssh2, which is heavy on coding, there is no conforming recommendation. I favor giving a good solution when the OP's conditions cannot reasonably be met.Otero
B
43

I haven't tried it, but this pysftp module might help, which in turn uses paramiko. I believe everything is client-side.

The interesting command is probably .execute() which executes an arbitrary command on the remote machine. (The module also features .get() and .put methods which allude more to its FTP character).

UPDATE:

I've re-written the answer after the blog post I originally linked to is not available anymore. Some of the comments that refer to the old version of this answer will now look weird.

Brillatsavarin answered 5/8, 2009 at 14:49 Comment(7)
Good find! As long as you don't care about customizing error responses, this additional abstraction would be very useful.Handcart
The ssh module did the trick. Simple and works fine. No searching through the Paramiko API.Homothermal
The link to the ssh.py file inside the link you give is broken :/Hurdygurdy
Yup, can we have a new link please. I found ssh.py on github, but it's not the same (and not as good)Alake
The pysftp package only provides SFTP. Far from a SSH client.Collado
@Collado I haven't tested but my understanding was that the .execute() method executes an arbitrary command on the remote machine - which is as close to an ssh client as you can get programmatically. .get() and .put() methods seem like add-ons to this.Brillatsavarin
@dgorissen: You can get this (or very similar) script here: github.com/tadeck/ssh-matic/tree/master/ssh. I will separate it into different module for easier usage.Magical
D
29

If you want to avoid any extra modules, you can use the subprocess module to run

ssh [host] [command]

and capture the output.

Try something like:

process = subprocess.Popen("ssh example.com ls", shell=True,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output

To deal with usernames and passwords, you can use subprocess to interact with the ssh process, or you could install a public key on the server to avoid the password prompt.

Dalesman answered 5/8, 2009 at 15:5 Comment(4)
But what if the client is on Windows?Volsung
It might be difficult to supply a password to ssh subprocess via a pipe. See Why not just use a pipe (popen())?. You might need pty, pexpect modules to workaround it.Mercier
doesnt seem to work for the string 'ssh somecomputer; python -c "import numpy; print numpy.__version__"' it says it doesnt know the command "import"Crocein
@usethedeathstar: wrap the whole remote command in quotes: ssh somecomputer 'python -c "import this; print this"'Dalesman
M
18

I have written Python bindings for libssh2. Libssh2 is a client-side library implementing the SSH2 protocol.

import socket
import libssh2

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('exmaple.com', 22))

session = libssh2.Session()
session.startup(sock)
session.userauth_password('john', '******')

channel = session.channel()
channel.execute('ls -l')

print channel.read(1024)
Medical answered 28/2, 2011 at 12:51 Comment(2)
It seems very low-level. For instance (your own example), you have to explicitely say you use IPv4 or IPv6 (something you do not have to do with OpenSSH command-line client). Also, I did not find how to make it work with the ssh-agent.Collado
The good thing about pylibssh2 is that it transfer files WAY faster than any native python implementation of ssh like paramiko.Far
H
8

Your definition of "simplest" is important here - simple code means using a module (though "large external library" is an exaggeration).

I believe the most up-to-date (actively developed) module is paramiko. It comes with demo scripts in the download, and has detailed online API documentation. You could also try PxSSH, which is contained in pexpect. There's a short sample along with the documentation at the first link.

Again with respect to simplicity, note that good error-detection is always going to make your code look more complex, but you should be able to reuse a lot of code from the sample scripts then forget about it.

Handcart answered 5/8, 2009 at 14:44 Comment(0)
A
6

Like hughdbrown, I like Fabric. Please notice that while it implement its own declarative scripting (for making deploys and the such) it can also be imported as a Python module and used on your programs without having to write a Fabric script.

Fabric has a new maintainer and is in the process of being rewriten; that means that most tutorials you'll (currently) find on the web will not work with the current version. Also, Google still shows the old Fabric page as the first result.

For up to date documentation you can check: http://docs.fabfile.org

Adaptable answered 6/8, 2009 at 10:8 Comment(1)
Fabric uses a fork of paramiko pypi.python.org/pypi/ssh for all ssh stuff.Far
F
6

I found paramiko to be a bit too low-level, and Fabric not especially well-suited to being used as a library, so I put together my own library called spur that uses paramiko to implement a slightly nicer interface:

import spur

shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello

You can also choose to print the output of the program as it's running, which is useful if you want to see the output of long-running commands before it exits:

result = shell.run(["echo", "-n", "hello"], stdout=sys.stdout)
Fausta answered 10/1, 2013 at 21:47 Comment(3)
Doesn't support running non-standard commands, for example on some routers (MikroTik) commands are prefixed with '/', this library throws an error. For standard linux hosts, it seems pretty good however.Nessus
When I pass an IP address to hostname it throws an error saying IP was not found in known_hosts...Remount
@Remount This is the normal behaviour of SSH: in order to make sure that you're talking to the correct server, SSH will only accept the key from a host if it is already known. The solution is either to add the relevant key to known_hosts, or to set the missing_host_key argument to an appropriate value, as described in the documentation.Fausta
D
4

For benefit of those who reach here googling for python ssh sample. The original question and answer are almost a decode old now. It seems that the paramiko has gain a bit of functionalities (Ok. I'll admit - pure guessing here - I'm new to Python) and you can create ssh client directly with paramiko.

import base64
import paramiko

client = paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.1.1', username='user', password='password')
stdin, stdout, stderr = client.exec_command('cat /proc/meminfo')
for line in stdout:
    print('... ' + line.strip('\n'))
client.close()

This code was adapted from demo of https://github.com/paramiko/paramiko It works for me.

Devaluate answered 21/6, 2018 at 11:9 Comment(1)
In 2022 the paramiko page suggests using Fabric for this use case (run a command). Fabric pulls in paramiko as a dependency. Fabric seems to implement this in two lines: one import from fabric import Connection and one invocation result = Connection('web1.example.com').run('uname -s', hide=True) That's not much shorter tho.Crashland
D
3

This worked for me

import subprocess
import sys
HOST="IP"
COMMAND="ifconfig"

def passwordless_ssh(HOST):
        ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
                       shell=False,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
        result = ssh.stdout.readlines()
        if result == []:
                error = ssh.stderr.readlines()
                print >>sys.stderr, "ERROR: %s" % error
                return "error"
        else:
                return result
Dirty answered 22/12, 2015 at 8:51 Comment(1)
This is the best solution. worked for me.Officious
J
1

please refer to paramiko.org, its very useful while doing ssh using python.

import paramiko

import time

ssh = paramiko.SSHClient() #SSHClient() is the paramiko object</n>

#Below lines adds the server key automatically to know_hosts file.use anyone one of the below

ssh.load_system_host_keys() 

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:

#Here we are actually connecting to the server.

ssh.connect('10.106.104.24', port=22, username='admin', password='')

time.sleep(5)

#I have mentioned time because some servers or endpoint prints there own information after 
#loggin in e.g. the version, model and uptime information, so its better to give some time 
#before executing the command.

#Here we execute the command, stdin for input, stdout for output, stderr for error

stdin, stdout, stderr = ssh.exec_command('xstatus Time')

#Here we are reading the lines from output.

output = stdout.readlines() 

print(output)


#Below all are the Exception handled by paramiko while ssh. Refer to paramiko.org for more information about exception.


except (BadHostKeyException, AuthenticationException,  
    SSHException, socket.error) as e:           

print(e)
Jugglery answered 11/5, 2019 at 2:54 Comment(0)
T
0

Have a look at spurplus, a wrapper around spur and paramiko that we developed to manage remote machines and perform file operations.

Spurplus provides a check_output() function out-of-the-box:

import spurplus
with spurplus.connect_with_retries(
        hostname='some-machine.example.com', username='devop') as shell:
     out = shell.check_output(['/path/to/the/command', '--some_argument']) 
     print(out)
Tellurion answered 23/8, 2018 at 6:33 Comment(0)
O
0
host = "test.rebex.net"
port = 22
username = "demo"
password = "password"

command = "ls"

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, port, username, password)

stdin, stdout, stderr = ssh.exec_command(command)
lines = stdout.readlines()
print(lines)

`

Obvolute answered 9/6, 2022 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.