SSH in Python: A Quick Working Sample
In one of my recent consulting projects, I had to use SSH from Python. After a little research, I ended up with using the paramiko package as library.
Lost VMs or Containers? Too Many Consoles? Too Slow GUI? Time to learn how to "Google" and manage your VMware and clouds in a fast and secure HTML5 App.
To download the paramiko package, just check out this link. What I downloaded was paramiko-1.12.0.tar.gz. After it’s uncompressed with 7-Zip to a temparary directory, just issue the following command and the needed library got installed into the site-packages directory.
C:\Dev\python27\python.exe setup.py install
That is not enough as I found out through a series of import errors. To make the paramiko package work, two dependent packages are needed: PyCrypto and ecdsa. The installation of the PyCrypto is straight-forward with an installer from this site. I first downloaded the 64 bit but didn’t seem to work well as it could not find my Python installation home. I then tried the 32 bit (pycrypto-2.6.win32-py2.7.exe) and worked well.
The ecdsa is a bit interesting. A quick search got me the project home on the GitHub right away, and then some description there concerned me as it mentioned support for Python 3.x. After going through a few issues with Python compatibility from version to version, I was not sure if I wouldn’t run into issues. Regardless, I downloaded the zip (python-ecdsa-master.zip) from master branch anyway. Without typical setup.py, I just copied the ecdsa folder to the site-packages folder, and it worked magically.
That is all about the installation of needed libraries.
Sample to Run Remote Shell Command
Let’s now take a look at the working sample code. To run it, you want to change the IP address and password to your Linux machine.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
__author__ = 'Steve Jin' import paramiko def runSshCmd(hostname, username, password, cmd, timeout=None): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname, username=username, password=password, allow_agent=False, look_for_keys=False, timeout=timeout) stdin, stdout, stderr = client.exec_command(cmd) data = stdout.read() print data client.close() runSshCmd("192.168.16.8", "root", "cloud", "uname -a")
As you can see, the code has one function that takes host, credentials, and a command to be executed. The last line calls the function with needed information. If you have many commands to run in a row, you can change the design a bit so that you don’t connect and close for each command.
Besides several import errors that pointed me to additional packages, I also got the following error in the end just before it started to work:
paramiko.SSHException: No authentication methods available
The code that leads to this error is slightly different as follows:
client.connect(hostname, username, password, allow_agent=False, look_for_keys=False)
After debugging into it, I found the underlying library got password as None. It turned out one of the parameter names is exactly called parameter and my arguments order does not match the API, therefore it assumed that password is None. A silly mistake. Changing it to password = password solved the problem.