2011-06-22 59 views
5

我试图使用paramiko python模块(1.7.7.1)并行执行一组远程服务器的命令和/或xfer文件。一个任务是这样的:多进程模块与paramiko

jobs = [] 
for obj in appObjs: 
    if obj.stop_app: 
     p = multiprocessing.Process(target=exec_cmd, args=(obj, obj.stop_cmd)) 
     jobs.append(p) 
     print "Starting job %s" % (p) 
     p.start() 

“目标文件” 包含,除其他事项外,一个的paramiko SSHClient,运输和SFTPClient。 appObjs列表包含大约25个这些对象,因此有25个连接到25个不同的服务器。

我得到的paramiko的transport.py以下错误的回溯

raise AssertionError("PID check failed. RNG must be re-initialized after fork(). 
Hint: Try Random.atfork()") 

我打补丁立足岗位在https://github.com/newsapps/beeswithmachineguns/issues/17 /usr/lib/python2.6/site-packages/paramiko/transport.py但它似乎没有帮助。我已经验证上述路径中的transport.py是正在使用的路径。 paramiko邮件列表似乎已经消失。

这看起来像paramiko中的问题,或者我误解/误用多处理模块吗?任何人都愿意提出一个实用的解决方法吗?非常感谢,

回答

5

UPDATE:作为@ento笔记,叉形SSH软件包已经merged back into paramiko所以下面的答案是现在无关,你现在应该被再次使用的paramiko。

这是的paramiko是现在只是被称为 ssh package on pypi(这使事情1.7.11版本的已知问题已得到修复的paramiko(在1.7.7.1版本停滞)的一个分支本文)。

显然有一些重要补丁进入主线Paramiko并且维护者没有响应,因此Fabric的维护者 @bitprophet在新包名 ssh package on pypi下分配了Paramiko。你可以看到你提到的具体问题是 discussed here,这也是他决定分手的原因之一。如果你真的想要,你可以阅读 gory details

+2

+1,主要是因为我不知道的paramiko已被@ bitprophet的SSH软件包取代 –

+1

PyPI上的SSH软件包(测试版本1.7.11,1.7.13)给出了与问题中提到的相同的错误,至少在Python 2.7.1中。 – ifischer

+1

pypi上的ssh包[已合并回上游](http://bitprophet.org/blog/2012/09/29/paramiko-and-ssh/)作为paramiko v1.8.0 – ento

1

作为Paramiko issue中的一个注释,RNG错误可以通过在每个进程中打开一个单独的ssh句柄来避免,然后paramiko不会再抱怨了。 此示例脚本演示了这一点(我使用一个游泳池,而不是过程):

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import ssh 
from multiprocessing import Pool 
import getpass 

hostnames = [HOST1, HOST2] 
user = USERNAME 
pw = getpass.getpass("Enter ssh password:") 

def processFunc(hostname): 
    handle = ssh.SSHClient() 
    handle.set_missing_host_key_policy(ssh.AutoAddPolicy()) 
    handle.connect(hostname, username=user, password=pw) 
    print("child") 
    stdin, stdout, stderr = handle.exec_command("ls -l /var/log; sleep 5") 
    cmdOutput = "" 
    while True: 
     try: 
      cmdOutput += stdout.next() 
     except StopIteration: 
      break 
    print("Got output from host %s:%s" % (hostname, cmdOutput)) 
    handle.close() 

pool = Pool(len(hostnames)) 
pool.map(processFunc, hostnames, 1) 
pool.close() 
pool.join() 

## If you want to compare speed: 
# for hostname in hostnames: 
#  processFunc(hostname)