如何在子进程中启动崩溃(很少)应用程序 [英] How to launch crashing (rarely) application in subprocess
问题描述
我有一个python应用程序需要执行专有应用程序(它会不时崩溃)每天大约20 000次。
I'm having python application which needs to execute proprietary application (which crashes from time to time) about 20 000 times a day.
问题是当应用程序崩溃,Windows会自动触发 WerFault ,这将使程序挂起,因此< a href =http://docs.python.org/2/library/subprocess.html#subprocess.call> python的 subprocess.call()
将永远等待用户输入(该应用程序必须在周末,节假日,每天24小时运行...因此这是不能接受的)。
The problem is when application crashes, Windows automatically triggers WerFault which will keep program hanging, thus python's subprocess.call()
will wait forever for user input (that application has to run on weekends, on holidays, 24/7... so this is not acceptable).
如果使用 sleep;轮询;杀;终止
,但这意味着丢失使用 communicate()
的能力,应用程序可以运行从几毫秒到2小时,因此设置固定超时将无效
If though about using sleep; poll; kill; terminate
but that would mean losing ability to use communicate()
, application can run from few miliseconds to 2 hours, so setting fixed timeout will be ineffective
我也尝试过打开自动调试(使用脚本将采取应用程序的崩溃转储和终止ID),但不知何故这个 howto 不能在我的服务器上工作(WerFault仍然出现并等待用户输入)。
I also tried turning on automatic debugging (use a script which would take a crash dump of an application and terminate id), but somehow this howto doesn't work on my server (WerFault still appears and waits for user input).
其他一些教程,如这也没有任何效果。
Several other tutorials like this didn't take any effect either.
问题 :
有一种方法如何防止WerFault显示(等待用户输入)? 这是更多的系统然后编程问题
替代问题:是有一个优雅方法在python如何检测应用程序崩溃(无论是否显示WerFault )
推荐答案
)回答,不时监视 WerFault.exe
实例,特别是与违规的 PID
相关联的实例应用。杀了它。处理 WerFault.exe
很复杂,但您不想禁用它 - 请参阅 Windows错误报告服务。
Simple (and ugly) answer, monitor for WerFault.exe
instances from time to time, specially the one associated with the PID
of the offending application. And kill it. Dealing with WerFault.exe
is complicated but you don't want to disable it -- see Windows Error Reporting service.
- 获取按照名称匹配
WerFault.exe
的进程列表。我使用psutil
包。请小心psutil
,因为进程已缓存,请使用psutil.get_pid_list()
。 - 使用
argparse
解码其命令行。这可能是过度的,但它利用现有的Python库。 - 根据
PID
识别持有应用程序的进程。 li>
- Get a list of processes by name that match
WerFault.exe
. I usepsutil
package. Be careful withpsutil
because processes are cached, usepsutil.get_pid_list()
. - Decode its command line by using
argparse
. This might be overkill but it leverages existing python libraries. - Identify the process that is holding your application according to its
PID
.
这是一个简单的实现。
def kill_proc_kidnapper(self, child_pid, kidnapper_name='WerFault.exe'):
"""
Look among all instances of 'WerFault.exe' process for an specific one
that took control of another faulting process.
When 'WerFault.exe' is launched it is specified the PID using -p argument:
'C:\\Windows\\SysWOW64\\WerFault.exe -u -p 5012 -s 68'
| |
+-> kidnapper +-> child_pid
Function uses `argparse` to properly decode process command line and get
PID. If PID matches `child_pid` then we have found the correct parent
process and can kill it.
"""
parser = argparse.ArgumentParser()
parser.add_argument('-u', action='store_false', help='User name')
parser.add_argument('-p', type=int, help='Process ID')
parser.add_argument('-s', help='??')
kidnapper_p = None
child_p = None
for proc in psutil.get_pid_list():
if kidnapper_name in proc.name:
args, unknown_args = parser.parse_known_args(proc.cmdline)
print proc.name, proc.cmdline
if args.p == child_pid:
# We found the kidnapper, aim.
print 'kidnapper found: {0}'.format(proc.pid)
kidnapper_p = proc
if psutil.pid_exists(child_pid):
child_p = psutil.Process(child_pid)
if kidnapper_p and child_pid:
print 'Killing "{0}" ({1}) that kidnapped "{2}" ({3})'.format(
kidnapper_p.name, kidnapper_p.pid, child_p.name, child_p.pid)
self.taskkill(kidnapper_p.pid)
return 1
else:
if not kidnapper_p:
print 'Kidnapper process "{0}" not found'.format(kidnapper_name)
if not child_p:
print 'Child process "({0})" not found'.format(child_pid)
return 0
现在, taskkill
函数使用正确的 PID
调用 taskkill
commmand。
Now, taskkill
function invokes taskkill
commmand with correct PID
.
def taskkill(self, pid):
"""
Kill task and entire process tree for this process
"""
print('Task kill for PID {0}'.format(pid))
cmd = 'taskkill /f /t /pid {0}'.format(pid)
subprocess.call(cmd.split())
这篇关于如何在子进程中启动崩溃(很少)应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!