Perform Commands Over Ssh with Python

Perform commands over ssh with Python

I will refer you to paramiko

see this question

ssh = paramiko.SSHClient()
ssh.connect(server, username=username, password=password)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd_to_execute)

If you are using ssh keys, do:

k = paramiko.RSAKey.from_private_key_file(keyfilename)
# OR k = paramiko.DSSKey.from_private_key_file(keyfilename)

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=host, username=user, pkey=k)

execute which command over ssh in python script

When you run a command over SSH, your shell executes a different set of startup files than when you connect interactively to the server. So the fundamental problem is really that the path where this tool is installed is not in your PATH when you connect via ssh from a script.

A common but crude workaround is to force the shell to read in the file with the PATH definition you want; but of course that basically requires you to know at least where the correct PATH is set, so you might as well just figure out where exactly the tool is installed in the first place anyway.

ssh server '. .bashrc; type -all solsql'

(assuming that the PATH is set up in your .bashrc; and ignoring for the time being the difference between executing stuff as yourself and as root. The dot and space before .bashrc are quite significant. Notice also how we use the POSIX command type rather than the brittle which command which should have died a natural but horrible death decades ago).

If you have a good idea of where the tool might be installed, perhaps instead do

subprocess.check_output(['ssh', 'root@' + ip, '''
for path in /opt/solidDB/*/bin /usr/local/bin /usr/bin; do
test -x "$path/solsql" || continue
echo "$path"
exit 0
done
exit 1'''])

Notice how we also avoid the (here, useless) shell=True. Perhaps see also Actual meaning of 'shell=True' in subprocess

Python script - connect to SSH and run command

Use paramiko, see http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/ for a through example of using it.

Execute a command on Remote Machine in Python

Sure, there are several ways to do it!

Let's say you've got a Raspberry Pi on a raspberry.lan host and your username is irfan.

subprocess

It's the default Python library that runs commands.

You can make it run ssh and do whatever you need on a remote server.

scrat has it covered in his answer. You definitely should do this if you don't want to use any third-party libraries.

You can also automate the password/passphrase entering using pexpect.

paramiko

paramiko is a third-party library that adds SSH-protocol support, so it can work like an SSH-client.

The example code that would connect to the server, execute and grab the results of the ls -l command would look like that:

import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('raspberry.lan', username='irfan', password='my_strong_password')

stdin, stdout, stderr = client.exec_command('ls -l')

for line in stdout:
print line.strip('\n')

client.close()

fabric

You can also achieve it using fabric.

Fabric is a deployment tool which executes various commands on remote servers.

It's often used to run stuff on a remote server, so you could easily put your latest version of the web application, restart a web-server and whatnot with a single command. Actually, you can run the same command on multiple servers, which is awesome!

Though it was made as a deploying and remote management tool, you still can use it to execute basic commands.

# fabfile.py
from fabric.api import *

def list_files():
with cd('/'): # change the directory to '/'
result = run('ls -l') # run a 'ls -l' command
# you can do something with the result here,
# though it will still be displayed in fabric itself.

It's like typing cd / and ls -l in the remote server, so you'll get the list of directories in your root folder.

Then run in the shell:

fab list_files

It will prompt for an server address:

No hosts found. Please specify (single) host string for connection: irfan@raspberry.lan

A quick note: You can also assign a username and a host right in a fab command:

fab list_files -U irfan -H raspberry.lan

Or you could put a host into the env.hosts variable in your fabfile. Here's how to do it.


Then you'll be prompted for a SSH password:

[irfan@raspberry.lan] run: ls -l
[irfan@raspberry.lan] Login password for 'irfan':

And then the command will be ran successfully.

[irfan@raspberry.lan] out: total 84
[irfan@raspberry.lan] out: drwxr-xr-x 2 root root 4096 Feb 9 05:54 bin
[irfan@raspberry.lan] out: drwxr-xr-x 3 root root 4096 Dec 19 08:19 boot
...


Related Topics



Leave a reply



Submit