获取子进程的输出“PHP致命错误”

时间:2011-03-25 01:27:29

标签: php unit-testing fork jenkins

我已经了解到你无法捕获PHP致命错误,并且你的脚本会在它命中时立即终止。我正在CI服务器上运行一个大型PHP测试套件(不是PHPUnit,而是一个自定义解决方案),并希望以JUnit输出格式报告测试通过/失败。

由于PHP中有太多东西是“致命错误”,我不希望致命错误结束我的测试运行,所以我的解决方案是使用分叉,如下所示:

foreach($tests as $test) {
    $pid = pcntl_fork();
    if ($pid) {
        $test->run();
        $test->write_junit($some_file_name);
    }
    else {
        pcntl_wait($status);
        if ($status) { //fatal error
            // from here we have no data about why it 
            // crashed, since that was in the child's memory
        }
    }
}

我的想法是关闭子进程中的STDERR并让它将标准错误发送到父可以读取的管道并将错误数据保存到JUnit文件中,但现在我不知道是否可能。你能改变STDERR的文件吗?基本上,我想要做的就像popen但没有exec()步骤。

我可以在PHP致命错误死后获得子进程的输出吗?

2 个答案:

答案 0 :(得分:1)

您可以在子进程中register a shutdown function并查看调用时的最后一个错误。如果存在与其中一种致命类型(E_ERRORE_COMPILE_ERRORE_CORE_ERRORE_PARSE)匹配的错误,请将其写入JUnit文件。虽然您无法从致命错误中恢复,但仍会调用您的关闭功能。

更新:正如Pacerier在评论中指出的那样,因为E_CORE_ERROR仅在PHP解释器自行引导时被抛出,所以它发生在注册关闭函数之前并且无法被捕获

答案 1 :(得分:0)

我无法找到任何可以让你用你正在使用的方法重定向stderr的东西。

但是,您可以在您的孩子中使用ini_set('error_log', $some_log_path),然后在孩子崩溃时读取该文件以确定错误消息?

如果失败了,你可以重写你的代码,通过proc_open调用一个单独的测试运行器PHP包装器,并使用shell将stderr发送到某个地方。