5

我正在尝试使用 paramiko python 模块(1.7.7.1)将命令和/或 xfer 文件并行执行到一组远程服务器。一项任务如下所示:

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()

"obj" 包含 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 的问题还是我误解/误用了多处理模块?有人愿意建议一个实用的解决方法吗?非常感谢,

4

2 回答 2

5

更新:正如@ento 所说,分叉的 ssh 包已合并回 paramiko,因此下面的答案现在无关紧要,您现在应该再次使用 Paramiko。

这是 Paramiko 中的一个已知问题,已在 Paramiko 的一个分支(停滞在 1.7.7.1 版)中修复,该分支现在被称为pypi 上的 ssh 包(在撰写本文时,它已将内容带到了 1.7.11版) .

显然,在主线 Paramiko 中获取一些重要补丁时存在问题,并且维护者没有响应,因此Fabric 的维护者@bitprophet在 pypi 上以新的包名称ssh package分叉了 Paramiko 。你可以看到你提到的具体问题在这里讨论,这也是他决定分叉的原因之一;如果你真的想, 你可以阅读血淋淋的细节。

于 2011-12-18T06:29:14.900 回答
1

正如Paramiko 问题中的一条评论所提到的,可以通过为每个进程打开一个单独的 ssh 句柄来避免 RNG 错误,然后 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)
于 2012-05-07T12:43:46.717 回答