当一个进程异常退出或根本不退出时,我仍然希望能够收集到那时可能产生的输出。
此示例代码的明显解决方案是使用os.kill终止子进程,但在我的实际代码中,子进程挂起等待NFS并且不响应SIGKILL。
#!/usr/bin/python
import subprocess
import os
import time
import signal
import sys
child_script = """
#!/bin/bash
i=0
while [ 1 ]; do
echo "output line $i"
i=$(expr $i \+ 1)
sleep 1
done
"""
childFile = open("/tmp/childProc.sh", 'w')
childFile.write(child_script)
childFile.close()
cmd = ["bash", "/tmp/childProc.sh"]
finish = time.time() + 3
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
while p.poll() is None:
time.sleep(0.05)
if finish < time.time():
print "timed out and killed child, collecting what output exists so far"
out, err = p.communicate()
print "got it"
sys.exit(0)
在这种情况下,出现关于超时的打印语句,并且python脚本永远不会退出或进行。有没有人知道我怎么能以不同的方式做到这一点,仍然可以从我的孩子过程中获得输出
答案 0 :(得分:1)
问题是当没有与终端连接时,bash不回答CTRL-C。 切换到SIGHUP或SIGTERM似乎可以解决问题:
cmd = ["bash", 'childProc.sh']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
close_fds=True)
time.sleep(3)
print 'killing pid', p.pid
os.kill(p.pid, signal.SIGTERM)
print "timed out and killed child, collecting what output exists so far"
out = p.communicate()[0]
print "got it", out
输出:
killing pid 5844
timed out and killed child, collecting what output exists so far
got it output line 0
output line 1
output line 2
答案 1 :(得分:1)
这是一种没有临时文件的POSIX方式。我意识到子进程在这里有点多余,但是由于最初的问题使用它...
import subprocess
import os
import time
import signal
import sys
pr, pw = os.pipe()
pid = os.fork ()
if pid: #parent
os.close(pw)
cmd = ["bash"]
finish = time.time() + 3
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=pr, close_fds=True)
while p.poll() is None:
time.sleep(0.05)
if finish < time.time():
os.kill(p.pid, signal.SIGTERM)
print "timed out and killed child, collecting what output exists so far"
out, err = p.communicate()
print "got it: ", out
sys.exit(0)
else: #child
os.close(pr)
child_script = """
#!/bin/bash
while [ 1 ]; do
((++i))
echo "output line $i"
sleep 1
done
"""
os.write(pw, child_script)
答案 2 :(得分:0)
另一个stackoverflow问题有很好的提示:How do I get 'real-time' information back from a subprocess.Popen in python (2.5)
其中的大多数提示都使用pipe.readline()
而不是pipe.communicate()
,因为后者仅在流程结束时返回。
答案 3 :(得分:0)
我遇到了完全相同的问题。我最后通过在调用subprocess.Popen
(或.call
)时设置以下参数来解决问题(在搜索Google并发现许多相关问题之后):
stdout=None
和
stderr=None
这些功能存在许多问题,但在我的具体情况下,我认为stdout
正在被我调用的进程填满,然后导致阻塞条件。通过将这些设置为None
(与subprocess.PIPE
相反),我相信这是可以避免的。
希望这有助于某人。