Latest LQ Deal: Linux Power User Bundle
Go Back > Blogs > Musings on technology, philosophy, and life in the corporate world
User Name


Hi. I'm a Unix Administrator, mathematics enthusiast, and amateur philosopher. This is where I rant about that which upsets me, laugh about that which amuses me, and jabber about that which holds my interest most: Unix.
Rate this Entry

Remote management of Linux systems via Python and ssh

Posted 12-30-2008 at 12:47 PM by rocket357
Updated 02-03-2009 at 07:52 PM by rocket357 (link)

Ok, so some time back I posted on here about cleartext passwords and Python, and how to encrypt passwords for storage on your hard drive. The task that prompted that post was writing a script capable of round-robin connecting to SQL Server and PostgreSQL databases to extract information about databases, software versions, log file sizes, etc...

Today's task is to round-robin connect to Linux via ssh. Python's os.popen3 is perhaps my favored (yes, I know it's been supplanted by more "modern" modules) mechanism for launching external processes because it returns stdin, stdout, and stderr, each of which can be read/written to individually. But ssh via popen3 seems to hang...if you're using password-based authentication for ssh.

First trick is to setup key-based authentication for ssh. If you've never done that before, it's as simple as running the following commands on the machine you'll be connecting *from*:

$ ssh-keygen -t rsa -b 4096 -C "a comment...likely just an e-mail address or other contact info"

Here's a sample run:

user@host ~ $ ssh-keygen -t rsa -b 4096 -C "this is a test run"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/<user>/.ssh/id_rsa): /home/<user>/test
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/<user>/test.
Your public key has been saved in /home/<user>/
The key fingerprint is:
5f:b3:f0:2e:31:cc:c3:e0:fe:78:2e:62:64:99:33:9f this is a test run
The key's randomart image is:
+--[ RSA 4096]----+
|                 |
|                 |
|                 |
|        .        |
|       +S=. o    |
|      B ..B+ o   |
|     o = ..+o    |
|      o E.o.     |
|     . ..=o..    |
Ok, as you can see from the output, is the *public* key component of the key pair. You can safely publish this key, but you need to lockdown your private key! Also note that if you enter a passphrase for the private key, this passphrase is required to connect (which will cause Python to hang waiting for ssh, which is waiting for the password input).

Ok, now ssh to the remote machine you want to manage. Check to make sure there aren't any files in the user's directory, then in another terminal scp the *public* key over to the remote machine:

user@host ~ $ scp -p remotehost:
The authenticity of host 'remotehost (' can't be established.
RSA key fingerprint is c1:8f:5f:c1:06:6a:52:47:1d:eb:e2:e5:d9:a9:f1:78.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'remotehost,' (RSA) to the list of known hosts.
user@host's password:                                      100%  740     0.7KB/s   00:00    
user@host ~ $ ssh remotehost
user@remotehost's password: 
Linux remotehost 2.6.18-5-amd64 #1 SMP Sat Dec 22 20:43:59 UTC 2007 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Sep 29 10:17:14 2008 from host
user@remotehost:~$ cat >>.ssh/authorized_keys
-bash: .ssh/authorized_keys: No such file or directory
user@remotehost:~$ mkdir .ssh
user@remotehost:~$ chmod 700 .ssh
user@remotehost:~$ cat >>.ssh/authorized_keys
user@remotehost:~$ rm 
user@remotehost:~$ exit
Connection to remotehost closed.
Now you should be able to ssh to remotehost without a password =)

Now then, with that out of the way, let's see some actual code:

#!/usr/bin/env python

import os, sys

# first let's copy the script to be run (can be python, shell, perl, whatever =)
stdin, stdout, stderr = os.popen3("scp -p remotehost:")

# close the previous file descriptors:

# and now ssh into the remotehost and launch the script we just uploaded to it...
stdin, stdout, stderr = os.popen3("ssh remotehost")

# chmod and execute the script...
stdin.write("""chmod 700\n""")

# then close the ssh connection

# and close the file descriptors:
This script is pretty simple, and lacks production-quality error checking and such, but it gets the concept across... with this basic framework, you can write a python script to round-robin ssh into each Linux machine and run a shell script, another python script, or whatever.

I haven't quite gotten to the point of interactive processing (python scripts "talking" to each other over the wire), but when I get that worked out I'll be sure to post again.

Edit - There's an "facade" for paramiko that's available here:

that makes paramiko exceptionally easy to use...I haven't tested it yet, though. I'll save that for a future posting =)

Edit - my next post (available here) covers a much easier approach to managing Linux systems via Python and ssh.
Posted in Uncategorized
Views 4464 Comments 0
« Prev     Main     Next »
Total Comments 0




All times are GMT -5. The time now is 05:11 AM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration