2

我正在用 Python 编写一个脚本来 ssh 到几台计算机(大约十台),并让它们开始从 Blender 渲染 3d 图像。它工作正常,除了下一台计算机的渲染在前一台计算机完成之前不会开始。有没有办法启动命令并让它们在自己的机器上同时运行?

我的代码是什么样的:

import os
path = /home/me
comp1 = ['sneffels','1','2'] #computer name, start frame, end frame
comp2 = ['bierstadt','3','4']
comp3 = ['diente','5','6']

os.system("ssh igp@" + str(comp1[0]) + " blender -b "+ str(path) +" -s " + str(comp1[1]) + " -e " + str(comp1[2]) + " -a")

os.system("ssh igp@" + str(comp2[0]) + " blender -b "+ str(path) +" -s " + str(comp2[1]) + " -e " + str(comp2[2]) + " -a")

os.system("ssh igp@" + str(comp3[0]) + " blender -b "+ str(path) +" -s " + str(comp3[1]) + " -e " + str(comp3[2]) + " -a")
4

6 回答 6

2

问题是os.system在程序完成之前不会返回,并且ssh在您给它的命令完成之前不会完成。

这是不使用的众多原因之一os.system——正如文档明确指出的那样:

subprocess 模块提供了更强大的工具来生成新进程并检索它们的结果;使用该模块优于使用此功能。请参阅子流程文档中的用子流程模块替换旧功能部分以获取一些有用的秘诀。

subprocess中,您可以创建一堆子流程,然后在它们全部启动后将它们全部加入。例如:

p1 = subprocess.Popen("ssh igp@" + str(comp1[0]) + " blender -b "+ str(path) +" -s " + str(comp1[1]) + " -e " + str(comp1[2]) + " -a", shell=True)
p2 = subprocess.Popen("ssh igp@" + str(comp2[0]) + " blender -b "+ str(path) +" -s " + str(comp2[1]) + " -e " + str(comp2[2]) + " -a", shell=True)
p3 = subprocess.Popen("ssh igp@" + str(comp3[0]) + " blender -b "+ str(path) +" -s " + str(comp3[1]) + " -e " + str(comp3[2]) + " -a", shell=True)
p1.wait()
p2.wait()
p3.wait()

这可能不是最好的方法。阅读子流程文档以了解为什么shell=True传递字符串通常不如传递list参数、管理子流程的其他方法等。但与此同时,这可能是您已有的最简单的更改。

另一种选择是不ssh首先使用命令,而是使用类似的东西paramiko从 Python 中生成远程进程。

于 2013-02-05T21:58:53.600 回答
0

+ " & "在每个末尾添加有什么问题os.system(...)

如果每个都有效,您似乎并不会太在意blender

从外观上看,您可以在 shell 脚本中执行此操作。

你可以安装类似的东西beanstalkd,让你的 10 台服务器每台运行一个从共享队列中提取作业的工作程序。然后让您的作业调度员执行提及文件名、起始帧、结束帧的作业。

一个好处是,当消费者完成时,他们可以将他们的状态放回队列中。

否则,您将无法知道其中一个子流程是否失败等。

于 2013-02-05T22:21:32.297 回答
0

您可以尝试使用threading包。可以在 Salty Crane 博客上找到一个可能对您有所帮助的简单示例。它应该允许您同时运行所有进程。

于 2013-02-05T21:52:47.457 回答
0

您可能希望将您的电话串接起来。我准备了一个小例子,它只是呼应了一些东西(你可以把它改成 ssh)。我希望它足够清楚,所以你可以明白

#!/usr/bin/env python

import threading
import os
import random

ips = ["192.168.1.25", "192.168.1.26", "192.168.1.27"]

def run(ip, otherParameter):
    os.system("echo %s with other parameter %s" % (ip, otherParameter))

if __name__ == "__main__":
    for ip in ips:
        thread = threading.Thread(target=run, args=[ip, random.randint(0, 10)])
        thread.run()

此外,您应该查看 subprocess 模块,而不是 os.system,或者更好的是,使用旨在运行 ssh 命令的东西,查看paramiko模块。

于 2013-02-05T21:59:10.717 回答
0

subprocess.Popen应该可以解决问题。

查看之前的答案: 如何从 Python 异步运行外部命令?

于 2013-02-05T21:59:43.057 回答
0

我建议使用 pssh 之类的工具。
该工具使用多线程并且执行速度很快。你可以在这里
阅读更多关于它的信息。

于 2017-01-03T10:45:52.037 回答