automating remote commands over SSH with paramiko
I don't know how high ranking python is for automating system administration tasks but when I had to script remote ssh commands, I thought I'd give python a try. The main SSH library is paramiko and, while lacking in the documentation department, it's rather rich in features.
Besides the usual root login, I had a more difficult use case: using a regular user with full sudo rights instead of the superuser. These are the functions I came up with:
- import paramiko
- import getpass
-
- def ssh_connection(user, host, port=22, password=None, key_filename=None):
- """
- with password='' you will be prompted for a password when the script runs
- """
- ssh = paramiko.SSHClient()
- ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- if password == '':
- # ask for one on stdin
- password = getpass.getpass('Password for %s@%s: ' % (user, host))
- ssh.connect(host, port=port, username=user, password=password, key_filename=key_filename)
- # custom attributes
- ssh.user = user
- if user == 'root':
- ssh.homedir = '/root'
- else:
- ssh.homedir = '/home/%s' % user
- ssh.password = password
- ssh.use_sudo = False
- return ssh
-
- def run_remote(ssh, cmd, check_exit_status=True, verbose=True):
- chan = ssh.get_transport().open_session()
- stdin = chan.makefile('wb')
- stdout = chan.makefile('rb')
- stderr = chan.makefile_stderr('rb')
- processed_cmd = cmd
- if ssh.use_sudo:
- processed_cmd = 'sudo -S bash -c "%s"' % cmd.replace('"', '\\"')
- chan.exec_command(processed_cmd)
- if stdout.channel.closed is False: # If stdout is still open then sudo is asking us for a password
- stdin.write('%s\n' % ssh.password)
- stdin.flush()
- result = {
- 'stdout': [],
- 'stderr': [],
- }
- exit_status = chan.recv_exit_status()
- result['exit_status'] = exit_status
- def print_output():
- for line in stdout:
- result['stdout'].append(line)
- print line,
- for line in stderr:
- result['stderr'].append(line)
- print line,
- if check_exit_status and exit_status != 0:
- print_output()
- print 'non-zero exit status (%d) when running "%s"' % (exit_status, cmd)
- exit(exit_status)
- if verbose:
- print processed_cmd
- print_output()
- return result
- # set up a ssh connection for root and ask for the password interactively
- myconn = ssh_connection('root', 'example.com', password='')
- # run some commands with the default settings
- run_remote(myconn,
- """
- pwd
- cd /var/log
- pwd
- ls -la
- """)
-
- # set up a connection for a regular user with full sudo rights and use it for running commands with root privileges
- sudoconn = ssh_connection('jim', 'example.com', password='imanewbieandileavepasswordsintextfiles')
- sudoconn.use_sudo = True
- run_remote(sudoconn,
- """
- whoami
- pwd
- cd /var/log
- pwd
- ls -la
- """)
Bottom line, it might not be easy to use paramiko's API directly but it's trivial to use my functions so go ahead and script those repetitive administration tasks. As always when doing stuff as root, try not to hose the server ;-)
Category: Python



Discussion
Try Fabric. It's easier to use the API. Perfect for deployments and sysadmin tasks
no thanks
Great blog and thanks for the example definitions however when trying to test them I am having issues. Is there a chance you might be able to actually make a couple example files and post them?
Thanks!
Nevermind my previous comment as I have tried to build the include file again and the defs are now successfully working. Thanks alot for the example!
Leave a Comment :
Leave a Comment