我已经了解到你无法捕获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致命错误死后获得子进程的输出吗?
答案 0 :(得分:1)
您可以在子进程中register a shutdown function并查看调用时的最后一个错误。如果存在与其中一种致命类型(E_ERROR
,E_COMPILE_ERROR
,E_CORE_ERROR
和E_PARSE
)匹配的错误,请将其写入JUnit文件。虽然您无法从致命错误中恢复,但仍会调用您的关闭功能。
更新:正如Pacerier在评论中指出的那样,因为E_CORE_ERROR
仅在PHP解释器自行引导时被抛出,所以它发生在注册关闭函数之前并且无法被捕获
答案 1 :(得分:0)
我无法找到任何可以让你用你正在使用的方法重定向stderr的东西。
但是,您可以在您的孩子中使用ini_set('error_log', $some_log_path)
,然后在孩子崩溃时读取该文件以确定错误消息?
如果失败了,你可以重写你的代码,通过proc_open
调用一个单独的测试运行器PHP包装器,并使用shell将stderr发送到某个地方。