我写了一个简单的python pexpect脚本来ssh到一台机器并执行一个动作。现在我需要对多个服务器执行此操作。我正在使用列表来使用多线程同时命中所有服务器。我的问题是由于所有内容同时运行,每个线程都运行在相同的服务器名称上。有没有办法同时让每个线程只运行一个列出的服务器?
#! /usr/bin/python
#Test script
import pexpect
import pxssh
import threading
import datetime
currentdate = datetime.datetime.now()
easterndate = (datetime.datetime.now() + datetime.timedelta(0, 3600))
#list of servers
serverlist = ["025", "089"]
#server number
sn = 0
ssh_new_conn = 'Are you sure you want to continue connecting'
class ThreadClass(threading.Thread):
def run(self):
index = 0
sn = serverlist[index]
print sn
username = '[a username]'
password = '[a password]'
hostname = '%(sn)s.[the rest of the host url]' % locals()
command = "/usr/bin/ssh %(username)s@%(hostname)s " % locals()
index = index + 1
now = datetime.datetime.now()
print command
p = pexpect.spawn(command, timeout=360)
***do some other stuff****
for i in range(len(severlist)):
t = ThreadClass()
t.start()
[更新] 我可能只是尝试使用调用子线程的父线程来执行此操作......尽管多线程可以从列表或某种工作队列中工作会很好。
答案 0 :(得分:0)
问题与“同时运行的所有内容”无关。您在index = 0
函数的开头明确设置run
,因此当然每个线程都在索引0上工作。
如果您希望每个线程处理一个服务器,只需将索引传递给每个线程对象:
class ThreadClass(threading.Thread):
def __init__(self, index):
super(ThreadClass, self).__init__()
self.index = index
def run(self):
sn = serverlist[self.index]
print sn
# same code as before, minus the index = index + 1 bit
for i in range(len(severlist)):
t = ThreadClass(i)
t.start()
(当然,您可能希望使用serverlist
代替severlist
并修复导致代码无法运行的其他错误。)
或者,更简单地说,传递sn
本身:
class ThreadClass(threading.Thread):
def __init__(self, sn):
super(ThreadClass, self).__init__()
self.sn = sn
def run(self):
print self.sn
# same code as last version, but use self.sn instead of sn
for sn in severlist:
t = ThreadClass(sn)
t.start()
或者,如果你真的想要使用全局变量,只需将其设为全局变量,并锁定它:
index = 0
index_lock = threading.Lock()
class ThreadClass(threading.Thread):
def run(self):
global index, index_lock
with index_lock:
sn = serverlist[index]
index += 1
print sn
# same code as first version
但是,您可能想要考虑一个更简单的设计,使用池或执行器而不是显式工作线程和要处理的事物列表。例如:
def job(sn):
print sn
# same code as first version again
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.map(job, serverlist)
这只会同时运行4或8或其他一些好的“神奇数字”的作业。这通常是你想要的。但是,如果您只需要每个服务器一个线程,只需将max_workers=len(serverlist)
传递给ThreadPoolExecutor
构造函数。
除了少量读取,写入,出错,调试等代码之外,它还具有更多功能 - 例如,您可以从服务器获得结果和/或异常,返回主线程。