使用Paramiko同时创建多个SSH连接

22 投票
3 回答
42399 浏览
提问于 2025-04-16 02:48

下面的代码通过SSH在一台机器上运行grep命令,并打印出结果:

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()

我该如何同时在五台机器上运行grep(这样就不会有很大的延迟),然后把所有结果放在五个变量里,最后把它们全部打印出来呢?

3 个回答

-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() 
        
0

在我的情况下,我需要在一个服务器上执行命令,这个服务器有一个特定的IP地址和端口。完成这些命令后,我还需要通过SFTP连接到另一个IP和不同的端口。条件是,在进行SFTP连接到另一个IP的时候,第一个连接必须保持活着,因为需要进行端口转发。

这两个连接单独使用时都能正常工作,但当我试图把这两个连接结合在一起时,第二个SFTP连接就无法正常工作了。

42

你需要把这些调用放到不同的线程里(或者进程,不过那样有点过于复杂),这就要求你的代码要放在一个函数里(这样做其实是个好主意:不要在模块的顶层写太多代码)。

比如说:

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()

如果你有超过五个主机,我建议你使用“线程池”架构和一个工作队列。但对于只有五个主机的情况,使用“专用线程”模型会更简单(尤其是因为标准库里没有线程池,所以你需要用像threadpool这样的第三方包……或者自己写很多复杂的代码,当然;-)。

撰写回答