编辑: 使用下面的代码段我遇到了一些问题
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命令的输出,但随后脚本无限期地挂起。问题是什么?如何纠正这个问题?
这是一个模型,但在我的实际程序中,我使用不同的参数/选项来运行相同的命令
答案 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()