我在python中使用多处理模块并行启动几个进程。这些过程彼此独立。它们生成自己的输出并将结果写入不同的文件中。每个进程都使用subprocess.call方法调用外部工具。 它工作正常,直到我在外部工具中发现一个问题,由于某些错误情况,它进入“提示”模式并等待用户输入。现在在我的python脚本中,我使用join方法等待所有进程完成任务。这导致整个事情等待这个错误的子进程调用。我可以为每个进程设置一个超时但我不知道每个进程运行多长时间,因此排除了这个选项。
如何确定是否有任何子进程正在等待用户输入,以及如何向其发送“exit”命令?任何指向python中相关模块的指针或建议都会非常感激。
我的代码在这里:
import subprocess
import sys
import os
import multiprocessing
def write_script(fname,e):
f = open(fname,'w')
f.write("Some useful cammnd calling external tool")
f.close()
subprocess.call(['chmod','+x',os.path.abspath(fname)])
return os.path.abspath(fname)
def run_use(mname,script):
print "ssh "+mname+" "+script
subprocess.call(['ssh',mname,script])
if __name__ == '__main__':
dict1 = {}
dict['mod1'] = ['pp1','ext2','les3','pw4']
dict['mod2'] = ['aaa','bbb','ccc','ddd']
machines = ['machine1','machine2','machine3','machine4']
log_file.write(str(dict1.keys()))
for key in dict1.keys():
arr = []
for mod in dict1[key]:
d = {}
arr.append(mod)
if ((mod == dict1[key][-1]) | (len(arr)%4 == 0)):
for i in range(0,len(arr)):
e = arr.pop()
script = write_script(e+"_temp.sh",e)
d[i] = multiprocessing.Process(target=run_use,args=(machines[i],script,))
d[i].daemon = True
for pp in d:
d[pp].start()
for pp in d:
d[pp].join()
答案 0 :(得分:0)
由于您正在编写shell脚本来运行子命令,您是否可以简单地告诉他们从/dev/null
读取输入?
#!/bin/bash
# ...
my_other_command -a -b arg1 arg2 < /dev/null
# ...
这可能会阻止他们阻止输入,这是一个非常简单的解决方案。如果这对您不起作用,请继续阅读其他选项。
subprocess.call()
函数只是构造subprocess.Popen
实例然后在其上调用wait()
方法的简写。因此,您的备用进程可以创建自己的subprocess.Popen
实例,并使用poll()
方法在对象上轮询它们而不是wait()
(在具有适当延迟的循环中)。这使他们可以自由地与主进程保持通信,因此您可以允许主进程通过Popen
或terminate()
告知子进程终止kill()
实例。方法,然后自己退出。
所以,问题是子进程如何判断子进程是否在等待用户输入,这是一个棘手的问题。我想说也许最简单的方法是监视子进程的输出并搜索用户输入提示,假设它总是使用一些你可以查找的字符串。或者,如果期望子进程连续生成输出,那么您可以简单地查找任何输出,如果配置的时间量过去而没有任何输出,那么您声明该进程已死并按上面详述的方式终止
由于您正在读取输出,实际上您不需要poll()
或wait()
- 关闭其输出文件描述符的过程足以知道它在这种情况下已终止。
以下是修改run_use()
方法的示例,该方法监视子流程的输出:
def run_use(mname,script):
print "ssh "+mname+" "+script
proc = subprocess.Popen(['ssh',mname,script], stdout=subprocess.PIPE)
for line in proc.stdout:
if "UserPrompt>>>" in line:
proc.terminate()
break
在此示例中,我们假设进程 挂起UserPrompt>>>
(替换为相应的字符串)或它会自然终止。例如,如果它被卡在无限循环中,那么你的脚本仍然不会终止 - 你只能用整体超时来解决这个问题,但你似乎并不热衷于这样做。但是,希望你的子进程不会以这种方式行为不端。
最后,如果您事先不知道将从您的流程中提供的提示,那么您的工作就会变得更加困难。实际上,您要求的是监视外部进程并知道它何时被阻止读取文件描述符,我不相信有一个特别干净的解决方案。你可以考虑在strace
或类似的情况下运行一个进程,但这是一个非常糟糕的黑客,我真的不会推荐它。 strace
之类的东西非常适合手动诊断,但它们确实不应该是生产设置的一部分。