使用python pexpect获取多线程以使用列表

时间:2013-03-21 22:33:06

标签: python linux multithreading ubuntu pexpect

我写了一个简单的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()

[更新] 我可能只是尝试使用调用子线程的父线程来执行此操作......尽管多线程可以从列表或某种工作队列中工作会很好。

1 个答案:

答案 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构造函数。

除了少量读取,写入,出错,调试等代码之外,它还具有更多功能 - 例如,您可以从服务器获得结果和/或异常,返回主线程。