在python脚本中执行二进制文件

时间:2017-01-06 14:33:54

标签: python multithreading ssh paramiko

编辑: 使用下面的代码段我遇到了一些问题

import paramiko, threading

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def connectAndCMD(command):
    ssh.connect('127.0.0.1',22,'MY_USER','MY_SSH_PASS')
    stdin, stdout, stderr = ssh.exec_command(command)
    print stdout.read()

commandList=[
    "pwd",
    "whoami",
    "ls",
    "echo hello",
    "ping google.com", 
    "ifconfig | grep Bcast | awk {'print $2'}"
]
for command in commandList:
    print '[',command, '] command thread started'
    t=threading.Thread(target=connectAndCMD,args=(command,))
    t.start()

在控制台中我看到: SSHException:没有现有会话 奇怪的是,当我将列表的大小减少到几个命令,减少线程数时,我能够看到随机线程的一个ssh命令的输出,但随后脚本无限期地挂起。问题是什么?如何纠正这个问题?

这是一个模型,但在我的实际程序中,我使用不同的参数/选项来运行相同的命令

1 个答案:

答案 0 :(得分:1)

问题是您尝试为每个命令重新验证ssh连接。 SSH使用单个传输连接(通常是TCP,但理论上是其他连接)来复用多个ssh级通道,这些通道运行命令,管道和shell等操作。 SSHClient.connect将打开传输连接,对服务器进行身份验证(注意丢失的主机密钥策略 - 您使用了相当不安全的策略)并验证客户端(在您的情况下是密码)。

之后,客户端可以打开任意数量的ssh级别通道来完成工作。每个exec_command打开一个通道,在服务器上启动一个shell,运行一个命令并关闭该通道。但由于这些通道是多路复用的,它们可以并行运行,是多线程读取的好选择。

import paramiko, threading

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('127.0.0.1',22,'MY_USER','MY_SSH_PASS')

def connectAndCMD(command):
    stdin, stdout, stderr = ssh.exec_command(command)
    print stdout.read()

commandList=[
    "pwd",
    "whoami",
    "ls",
    "echo hello",
    "ping google.com", 
    "ifconfig | grep Bcast | awk {'print $2'}"
]
for command in commandList:
    print '[',command, '] command thread started'
    t=threading.Thread(target=connectAndCMD,args=(command,))
    t.start()

更新

由于ssh服务器限制了并发命令的数量,您可以使用线程池来确保您保持在限制之下。

import paramiko
import multiprocessing.pool

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('127.0.0.1',22,'MY_USER','MY_SSH_PASS')

def connectAndCMD(command):
    stdin, stdout, stderr = ssh.exec_command(command)
    return command, stdout.read(), stderr.read()

commandList=[
    "pwd",
    "whoami",
    "ls",
    "echo hello",
    "ping google.com", 
    "ifconfig | grep Bcast | awk {'print $2'}"
]

pool = multiprocessing.pool.ThreadPool(min(10, len(commandList))
for command, out, err in pool.map(connectAndCMD, commandList, chunksize=1):
    print((command, out, err))
pool.close()
pool.join()