我正在用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")
答案 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)
答案 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)
答案 4 :(得分:0)
将+ " & "
放在每个os.system(...)
的末尾有什么问题?
如果每个blender
工作与否,你似乎不会感到困扰。
从外观上看,你可以在shell脚本中完成它。
您可以安装类似beanstalkd
的内容,并让您的10台服务器各自运行一个工作程序,从而从共享队列中取出作业。然后让你的工作调度员进行提及文件名,开始帧,结束帧的工作。
一个好处是,当消费者完成时,他们可以将他们的状态恢复到队列中。
否则,您将知道其中一个子流程是否失败等问题
答案 5 :(得分:0)
我建议使用像pssh这样的工具 该工具使用多线程并快速执行 你可以阅读更多相关信息here。