如何捕获PHP致命错误
我可以使用set_error_handler()
来捕获大多数PHP错误,但它不适用于致命( E_ERROR
)错误,例如调用一个不存在的函数。 是否有另一种方法来捕捉这些错误?
我正在尝试为所有错误调用mail()
,并且正在运行PHP 5.2.3。
使用register_shutdown_function
记录致命错误,它需要PHP 5.2+:
register_shutdown_function( "fatal_handler" );
function fatal_handler() {
$errfile = "unknown file";
$errstr = "shutdown";
$errno = E_CORE_ERROR;
$errline = 0;
$error = error_get_last();
if( $error !== NULL) {
$errno = $error["type"];
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
error_mail(format_error( $errno, $errstr, $errfile, $errline));
}
}
你将不得不定义error_mail
和format_error
函数。 例如:
function format_error( $errno, $errstr, $errfile, $errline ) {
$trace = print_r( debug_backtrace( false ), true );
$content = "
<table>
<thead><th>Item</th><th>Description</th></thead>
<tbody>
<tr>
<th>Error</th>
<td><pre>$errstr</pre></td>
</tr>
<tr>
<th>Errno</th>
<td><pre>$errno</pre></td>
</tr>
<tr>
<th>File</th>
<td>$errfile</td>
</tr>
<tr>
<th>Line</th>
<td>$errline</td>
</tr>
<tr>
<th>Trace</th>
<td><pre>$trace</pre></td>
</tr>
</tbody>
</table>";
return $content;
}
使用Swift Mailer编写error_mail
函数。
也可以看看:
刚刚想出了这个解决方案(PHP 5.2.0+):
function shutDownFunction() {
$error = error_get_last();
// fatal error, E_ERROR === 1
if ($error['type'] === E_ERROR) {
//do your stuff
}
}
register_shutdown_function('shutDownFunction');
在http://www.php.net/manual/en/errorfunc.constants.php中定义了不同的错误类型
PHP不提供从致命错误中捕获和恢复的常规手段。 这是因为处理通常不应该在致命错误后被恢复。 匹配输出缓冲区的字符串(正如PHP.net上描述的原始文章所建议的那样)绝对不适合。 这根本不可靠。
从错误处理程序方法中调用mail()函数也被证明是有问题的。 如果你有很多错误,你的邮件服务器将被加载工作,并且你可能会发现自己的一个粗糙的收件箱。 为避免这种情况,您可能会考虑运行cron以定期扫描错误日志并相应地发送通知。 您可能还想研究系统监控软件,如Nagios。
谈谈关于注册关机功能的一点:
确实,你可以注册关机功能,这是一个很好的答案。
这里的要点是,我们通常不应该尝试从致命错误中恢复,特别是不要使用正则表达式对输出缓冲区进行恢复。 我回应了接受的答案,该答案与php.net上的建议有关,后者已被更改或删除。
该建议是在异常处理期间针对输出缓冲区使用正则表达式,并且在发生致命错误(通过匹配您所期望的任何配置的错误文本来检测)时,尝试执行某种恢复或继续处理。 这不会是一个推荐的做法(我相信这也是为什么我也找不到最初的建议,我可以忽略它,或者PHP社区将它击落)。
值得注意的是,在输出缓冲回调被调用之前,较新版本的PHP(大约5.1)似乎更早地调用了关闭函数。 在版本5和更早版本中,该顺序是相反的(输出缓冲回调之后是关闭功能)。 此外,由于约5.0.5(这比问题的5.2.3版本早得多),因此在调用已注册的关闭函数之前卸载对象,因此您将无法依赖内存中的对象执行操作很多东西。
所以注册一个关闭函数没有问题,但是应该由关闭函数执行的任务可能仅限于一些轻微的关闭过程。
这里关键的一点是,任何人在这个问题上磕磕绊绊,并在最初接受的答案中看到建议时,都只是一些智慧的话语。 不要对输出缓冲区进行regex。
链接地址: http://www.djcxy.com/p/26609.html