获取子进程的输出';s";PHP致命错误“;

获取子进程的输出';s";PHP致命错误“;,php,unit-testing,fork,jenkins,Php,Unit Testing,Fork,Jenkins,我已经了解到,您无法捕获PHP致命错误,您的脚本将在遇到错误时立即终止。我正在CI服务器上运行一个大型PHP测试套件(不是PHPUnit,而是一个自定义解决方案),并希望以JUnit输出格式报告测试通过/失败 由于PHP中有太多的东西是“致命错误”,我不希望致命错误结束我的测试运行,所以我的解决方案是使用分叉,类似这样: foreach($tests as $test) { $pid = pcntl_fork(); if ($pid) { $test->ru

我已经了解到,您无法捕获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的文件吗?基本上,我想做的是,没有exec()步骤


在子进程因PHP致命错误而死亡后,我可以获取其输出吗?

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

但是,您可以在您的孩子中使用
ini\u set('error\u log',$some\u log\u path)
,然后在孩子崩溃时读取文件以确定错误消息

否则,您可以重写代码,通过
proc\u open
调用单独的测试运行程序PHP包装器,并使用shell将stderr发送到某个正常的地方。

您可以在子进程中检查调用时的最后一个错误。如果存在与致命类型之一相匹配的错误(
E\u error
E\u COMPILE\u error
E\u CORE\u error
E\u PARSE
),请将其写入JUnit文件。虽然无法从致命错误中恢复,但仍会调用关闭函数


更新:正如Pacerier在评论中指出的那样,由于
E_CORE_ERROR
仅在PHP解释器自身启动时才会抛出,因此它发生在关闭函数可以注册且无法捕获之前。

这可能很有用,但是如果我可以在unix管道中执行它,而不是在文件系统中抛出一些东西,而不是$some_log_path,那会更好。这是一个可怕的黑客虽然。据我所知,无法从shutdown函数内部访问致命错误stacktrace(关于它的任何消息)。如果这真的有可能,这将是一个完全可行的解决方案。我真的不喜欢PHP。@Chad-您可以使用获取消息、代码、文件和行号,但仅此而已。我对这个答案感到兴奋,但后来我发现错误\u get\u last不在PHP5.1中。无论如何,我都会把你们标记为最佳答案,因为我并没有指定版本,若其他人有这个问题,他们可以使用这个技巧。希望我们能在不久的将来更新到一个不太古老的PHP版本。@David,E_CORE_错误不是只发生在脚本运行之前吗?@Pacerier-“PHP初始启动时发生的致命错误。”是的,听起来你是对的。