9

当我们的网站遇到内部服务器错误时,我正在尝试收集信息。我们有许多应用程序从未设置过正确的错误日志记录,当出现问题时,我们的客户不会向我们提供最好的信息来处理。我想做的是,当 500 发生时,我想收集有关问题发生位置的数据,例如:

  • 用户所在的页面
  • 与页面关联的任何数据($_GET、$_POST 等)

我已经使用以下配置在我们的服务器(IIS 7)上设置了自定义错误页面:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Custom">
            <remove statusCode="500" />
            <error statusCode="500" path="/error.php?code=500" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
</configuration>

在那个页面上,我只是 var_dump-ing $_POST 和 $_GET 以查看其中是否有任何内容进入错误页面,但它没有。我对 500 错误的目标是:

  • 在出错时收集有关页面/用户的数据
  • 向支持团队发送有关包含所收集数据的问题的电子邮件

有什么方法可以收集这些数据并让自定义错误页面看到它?

错误.php:

switch($ErrorCode){
    case '500':
         var_dump($_REQUEST, $_POST, $_GET);
         echo "internal server error";
         break;
}

在所有情况下 $_POST 都是空的,即使我提交了一个表单来得到这个错误并且 $_GET 包含这个(这是有道理的):

array(2) {
  ["code"]=>
  string(3) "500"
  ["500;http://icom-sbs/test_php"]=>
  string(0) ""
}

4/19 更新

我尝试了一些想法,主要是将有用的数据存储在会话变量中。我试图将一些表单数据存储在给出错误的测试页面上的会话变量中,但它从未进入会话。似乎服务器检测到页面上将发生错误,因此它甚至从未执行页面上的任何代码并立即执行错误页面。

4

4 回答 4

2

我认为您需要在服务器级别而不是 php 级别记录详细信息,因为当发生 500 内部错误时,php 甚至可能不会初始化。如果您使用的是 apache,您可以查看

http://httpd.apache.org/docs/1.3/mod/mod_log_config.html#logformat

错误日志肯定会为您提供请求 url、远程地址和获取参数(查询字符串)。但我不确定发布数据。可能您可以对日志格式进行一些更改,以在某个级别转储整个标题和原始数据。

但我敢肯定,当服务器实际放弃并且 php 没有启动时,在 php 级别的日志记录会在某些时候跳过......

于 2013-04-26T07:12:28.937 回答
2

如果您的服务器开始解释 php 文件并且在发生此 500 错误之后,这意味着您的代码中发生了一些致命错误。它可能是任何东西,从简单的错字到达到执行时间限制。

在 PHP 中捕获致命错误的最好也是唯一的方法是使用register_shutdown_function。您应该在工作文件之上定义它:

function handle_fatal() {
    $error = error_get_last(); // PHP 5.2+
    if($error !== NULL){
        $error_landing_page = '[FATAL] '.$error['message'].' in '.$error['file'].':'.$error['line'] . '<br/>GET:<br/>' . print_r($_GET, true) . '<br/>POST:<br/>' . print_r($_POST, true);
        // mail here if you need that and include $_GET, $_POST variables - this will be the last state before error occurred
        exit($error_landing_page);
    }
}

register_shutdown_function('handle_fatal');

简单的测试用例:

// put handling function at the very beginning
function handle_fatal() {/*...*/}
register_shutdown_function('handle_fatal');

// now do some logic
if($_GET['page'] == 'dupa'){
    $_POST['subpage'] = 1; // more and more logic
    $obj = new Dupa(); // class not found exception
}

这就是我从示例中得到的 handle_fatal :

[FATAL] Class 'Dupa' not found in /var/www/index.php:22
GET:
Array ( [page] => dupa )
POST:
Array ( [subpage] => 1 ) 

毕竟你应该知道捕捉这些错误并不总是最好的主意,你应该小心。

于 2013-04-28T22:40:43.817 回答
0

我相信您可以在 PHP 中设置自定义错误处理程序。困难的是,一些错误可能会导致 PHP 死掉并返回 500 而不会触发错误处理程序。好的一面是它应该很容易在站点范围内实现,而无需进行大量更改。

http://www.php.net/manual/en/function.set-error-handler.php

您应该能够在 $_SERVER 全局中找到大部分相关信息。您还可以查看 debug_backtrace 函数,该函数将为您提供堆栈跟踪。

http://php.net/manual/en/function.debug-backtrace.php

祝你好运

于 2013-04-23T02:45:00.473 回答
0

$_SERVER如果有任何感兴趣的东西,请检查阵列。

我进行了一些研究,如果您使用的是 ASP,您将能够在Server.GetLastError中获取错误详细信息,这使我相信 IIS 可能会通过$_SERVER数组传递信息。

于 2013-04-19T07:20:12.403 回答