使用python启动并行ssh渲染作业

时间:2013-02-05 21:48:21

标签: python ssh blender

我正在用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")

6 个答案:

答案 0 :(得分:2)

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

这是不使用os.system的众多原因之一 - 正如the documentation明确指出:

  

子流程模块提供了更强大的工具来生成新流程并检索其结果;使用该模块比使用此功能更可取。有关一些有用的配方,请参阅子流程文档中的“使用子流程模块替换旧函数”部分。

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中生成远程进程。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

您可能需要thread来电。我准备了一个小例子,只是回声(你可以把它改成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模块,或者甚至更好地使用用于运行ssh命令的内容,而不是os.system,请查看paramiko模块。

答案 3 :(得分:0)

subprocess.Popen应该可以做到这一点。

查看以前的答案:How can I run an external command asynchronously from Python?

答案 4 :(得分:0)

+ " & "放在每个os.system(...)的末尾有什么问题?

如果每个blender工作与否,你似乎不会感到困扰。

从外观上看,你可以在shell脚本中完成它。

您可以安装类似beanstalkd的内容,并让您的10台服务器各自运行一个工作程序,从而从共享队列中取出作业。然后让你的工作调度员进行提及文件名,开始帧,结束帧的工作。

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

否则,您将知道其中一个子流程是否失败等问题

答案 5 :(得分:0)

我建议使用像pssh这样的工具 该工具使用多线程并快速执行 你可以阅读更多相关信息here