22

The code below runs grep in one machine through SSH and prints the results:

import sys, os, string
import paramiko

cmd = "grep -h 'king' /opt/data/horror_20100810*"

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.10.3.10', username='xy', password='xy')
stdin, stdout, stderr = ssh.exec_command(cmd)
stdin.write('xy\n')
stdin.flush()

print stdout.readlines()

How can I grep five machines all at once (so that I don't have major delay), than put all that in five variables and print them all out.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Whit3H0rse
  • 569
  • 2
  • 8
  • 16

3 Answers3

42

You'll need to put the calls into separate threads (or processes, but that would be overkill) which in turn requires the code to be in a function (which is a good idea anyway: don't have substantial code at a module's top level).

For example:

import sys, os, string, threading
import paramiko

cmd = "grep -h 'king' /opt/data/horror_20100810*"

outlock = threading.Lock()

def workon(host):

    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(host, username='xy', password='xy')
    stdin, stdout, stderr = ssh.exec_command(cmd)
    stdin.write('xy\n')
    stdin.flush()

    with outlock:
        print stdout.readlines()

def main():
    hosts = ['10.10.3.10', '10.10.4.12', '10.10.2.15', ] # etc
    threads = []
    for h in hosts:
        t = threading.Thread(target=workon, args=(h,))
        t.start()
        threads.append(t)
    for t in threads:
        t.join()

main()

If you had many more than five hosts, I would recommend using instead a "thread pool" architecture and a queue of work units. But, for just five, it's simpler to stick to the "dedicated thread" model (especially since there is no thread pool in the standard library, so you'd need a third party package like threadpool... or a lot of subtle custom code of your own of course;-).

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • I eliminated 1 machine, so I on only need 4. I forgot to mention that all data will be processed diffrently later in the script and as I can understood your code (I m PyN00b) it will print all data from all machines at once, but how can I process data just from one host then? And all the hosts have diffrent pass so can I put them all in workon()? Ty for quick replay Alex. Regards – Whit3H0rse Aug 15 '10 at 00:00
  • 1
    @konjo, you can perform the processing of the data in the thread that's just obtained the data -- I was instead `print`ing it, only because that's what *you* did in your question. The processing of course can involve checks on the value of `host`, if you need to perform different processing for different values thereof. Or, you could write multiple functions to use as `target=` in your threads: there's no constraint that all threads must run the same function! – Alex Martelli Aug 15 '10 at 02:20
  • Oke i was able to grep all 4 machines, but now all data is merged. How can I extract data from to each individual host, can you give mi example, please extend example above? Regards – Whit3H0rse Aug 26 '10 at 03:37
  • Ty Alex for this, I think that you misunderstood me, I did accept you advice and example from above, but I m new at programing so I need little more hints. I did all you have written above with my modification for different cmd commands. Ty again. Regards – Whit3H0rse Aug 26 '10 at 07:25
  • @konjo, on Stack Overflow, for the asker of a question to "accept" an answer means to click on the checkmark-shaped icon to the left on the answer -- that gives the asker a few point of reputation, and the answerer more. Your "0% accepted" means you've _never_ done that, which is baffling. – Alex Martelli Aug 26 '10 at 13:52
  • @AlexMartelli what would the code be like if we want more than 5 connections taking place simultaneously? – udit kanotra Jun 05 '19 at 11:59
0

In my case i have to execute commands on server with one ip and port and after complete need to do sftp to other ip and different port.Condition is one connection should be live while doing sftp to another ip due to port forwarding.

Both connection are working separably but while combining both second sftp connection is not working.

Romita Thakur
  • 233
  • 1
  • 3
  • 8
-1
#! /usr/bin/env python3
import sys, os, string, threading
try:
    import paramiko
    #import paramiko package
except:
    im = input("Paramiko module is missing. Do you want to install[Y/N]:")
    im = im.upper()
    if im == "Y":
        try:
            try:
                os.system("pip install paramiko")
            except:
                os.system("pip3 install paramiko")
        except:
            print("Please install paramiko package manually")
    else:
        print("Rerun and type 'y' to install")

#Running paramiko module with interactive password sending function
#this function helps to send password when sudo command is executed
def sudossh():
    host = "type host ip"
    port = 22
    username = "type username"
    password = "type password"
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host, port, username, password)
        ssh.get_transport()
        #In this example we will run HTTP module on server in port 80
        command = "sudo su -c 'sudo python -m SimpleHTTPServer 80'"
        print(f"Running: {command}\n")
        stdin, stdout, stderr = ssh.exec_command(command=command,get_pty=True)
        stdin.write("password\n")
        print("sent password\n")
        print("HTTP service is running now\n")
        stdin.flush()
        if stderr.channel.recv_exit_status() != 0:
            print(f"Error: {stderr.readlines()}")
        else:
            print(f"Output: \n{stdout.readlines()}")
        ssh.close()
    except Exception as err:
        print(str(err));
        print("Thanks for using my application");

#Running another paramiko module with interactive password sending function
def grepverification():
    host = "type host ip"
    port = 22
    username = "type username"
    password = "type password"
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host, port, username, password)
        ssh.get_transport()
        #Open new session and check port 80 status on server
        command = "sudo su -c 'netstat | grep 80'"
        print(f"Running: {command}\n")
        stdin, stdout, stderr = ssh.exec_command(command=command,get_pty=True)
        stdin.write("password\n")
        print("sent password\n")
        print("Connection is established. Check below output\n")
        stdin.flush()
        if stderr.channel.recv_exit_status() != 0:
            print(f"Error: {stderr.readlines()}")
        else:
            print(f"Output: \n{stdout.readlines()}")
        ssh.close()
    except Exception as err:
        print(str(err));
        print("Thanks for using my application");


def main():
    #Multithreading helps to run both at a same time. Useful for verification.
    # creating thread
    th1 = threading.Thread(target=sudossh)
    th2 = threading.Thread(target=grepverification)
    # starting thread 1
    th1.start()
    # starting thread 2
    th2.start()
    # wait until thread 1 is completely executed
    th1.join()
    # wait until thread 2 is completely executed
    th2.join()
    # both threads completely executed
    print("Completed!")
#you can use for loop to reduce lines but for understanding & smooth multithreading process will keep it as separate functions
#Comments are welcome. Thanks. Follow me on https://www.linkedin.com/in/dinesh-kumar-palanivelu-858441128/
#you need to change line - 23-26,36,51-54,64

if __name__=='__main__':
       main() 
        
  • Your answer could be improved with additional supporting information. You can find more information on how to write good answers in the [help center](https://stackoverflow.com/help/how-to-answer). – MagnusO_O Oct 14 '22 at 11:50