BugKiller: Python subprocess超时后,无法kill进程的问题

出现问题的代码是酱汁的:

process = subprocess.Popen("phantomjs crawler.js {url} {method} {data}", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
try:
    (output, error) = process.communicate(timeout=TIMEOUT)
    re_result = re.findall(r"~~~~123(.*?)321~~~~", output.decode(), re.I|re.S)
    if len(re_result) == 0:
        print_error("Can't find result, %s" % cmd)
        return []

    res = simplejson.loads(re_result[0])
    for item in res:
        item["url"] = Parser.get_url(url, item["url"])

    return res
except subprocess.TimeoutExpired:
    process.kill()
    print_error("TIMEOUT: %s" % cmd)
except Exception as e:
    print(e)

由于PhantomJS的问题,导致任务超时。超时关闭是在Python中处理的,调用了process.kill(),但在实际测试中发现PhantomJS进程并没有被kill掉。

为了Debug,我在process.kill()之前,插入了一句print(process.pid)。原本以为是kill()函数没有正常运行,但让人惊讶的是,根据打印出来的pid,进程中并没有subprocess进程残留,打印的pid和未结束的PhantomJS进程pid并不相同,且phantomjs.pid = process.pid + 1。看起来是subprocess在调度任务的时候,开启了两个进程,在父进程被kill的时候,并没有kill子进程(或者两个进程之间根本没有父子关系)。

很快查到了问题所在,shell=True 参数会模拟在shell中执行,先是起了shell进程,再从shell起了phantomjs进程。解决方案(
去掉了shell=True,改用list格式传参。):

process = subprocess.Popen(["phantomjs", "crawler.js", {url}, {method}, {data}], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

你可能感兴趣的:(BugKiller: Python subprocess超时后,无法kill进程的问题)