【问题标题】:Trigger 500 Internal Server Error in PHP and display Apache error page在 PHP 中触发 500 Internal Server Error 并显示 Apache 错误页面
【发布时间】:2012-01-31 00:34:57
【问题描述】:

如何在 PHP 中触发 500 Internal Server Error404 Page Not Found Apache 错误?

对于 500 内部服务器错误,我尝试了以下代码:

header("HTTP/1.0 500 Internal Server Error");

但它显示了一个空白页。 如何以 Apache 的默认格式显示错误?

请指导..

【问题讨论】:

  • 乍一看,我认为这很容易解决。但看起来实际上并非如此。所以+1
  • 只是把它扔给大家:我在想你可以从共享文件中包含 Apache 的原始错误文档(对我来说是/usr/share/httpd/error/HTTP_INTERNAL_SERVER_ERROR.html.var)并退出 PHP 脚本。但是我遇到了一个大问题:您将如何处理 .html.var 文件?在 Apache 中,它被设置为 AddHandler type-map var,但我想不出任何在 PHP 中有用的东西。

标签: php apache


【解决方案1】:

您可以将 Apache 错误文档复制到您的 Web 根目录(或将它们符号链接)并使用 header() 设置错误代码并将这些文档作为输出。除非您有令人信服的理由不这样做,否则这可能是最好的。但万一这对你不起作用,还有一些替代方案(尽管是老套的替代方案)。

对于 500,只需在您的代码中添加一个错误。

<?php throw new Exception('Nooooooooooooooo!'); ?>

PHP 脚本将引发异常,从而导致常规 Apache 500 错误页面。 (但请注意,如果 PHP 初始化设置 display_errors 设置为 0,这只会导致 Apache 错误。在大多数开发配置中,情况并非如此。在大多数生产配置中,这是情况。如果你不知道你的生产服务器的设置,你只需要测试一下看看它是否有效。)

对于 404,我认为您能做的最好的事情就是重定向到一个不存在的页面。这不完全一样,但可能适合您的目的。

<?php header("Location: /i-dont-think-therefore-i-am-not"); ?>

在大多数浏览器中,用户实际上不会看到重定向,他们只会静默快速地重定向到不存在的页面,从而导致常规的 Apache 404 错误。当然,网址会发生变化,一些用户可能会注意到这一点。如果这不可接受,您也许可以使用 Apache mod_rewrite 将 url 后端重写到不存在的位置来获得类似的结果。

响应多个 cmets:通过header()(或其他方式)设置响应代码不会导致标准的 Apache 错误文档。它只会用您自己的输出返回该响应代码。这是有意的行为,旨在让您可以拥有自定义错误文档,或者按照 HTTP 规范对任何请求的要求设置响应代码。如果你想要 Apache 错误文档,你必须要么伪造它们(按照我最初的建议,简单地将错误文档复制到你的 web 根目录),或者你必须欺骗 Apache 将它们返回(根据我的备份建议)。

【讨论】:

  • 致命错误:未捕获的异常 'Exception' 带有消息 'Nooooooooooooooooo!'
  • 布莱赫。这种骇客真的没必要。
  • PHP 只会回显异常并停止。它不会导致内部服务器错误。它仅适用于某些框架,因为它们具有异常处理程序,可以在未捕获的异常上生成内部服务器错误
  • 我想借此机会改写我原来的评论:Blech。有时需要这种hackery,但仍然需要,blech ;)
  • 一个妥协的解决方案是:创建一个文件夹并在其中保留一个 .htaccess 文件并在 htaccess 文件中添加以下代码: RewriteEngine On RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^])(.(*/ RewriteRule ^])((a-zA 要显示错误,只需使用 header() 重定向到该文件夹​​ URL。成功了。谢谢大家
【解决方案2】:

经过这样一个知识渊博的讨论,我认为没有 php 代码可以显示默认的 500 Internal Server Error。 解决办法是:
1. 在 php 文件旁边创建一个名为 http500 的文件夹。
2.在其中创建一个.htaccess文件并添加以下代码:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^])(.(*/
    RewriteRule ^])((a-zA
</IfModule>
  1. PHP 重定向代码:

header('位置:http500/');

【讨论】:

  • 或者甚至不用制作 php 文件,只需自己导航到该目录即可。我没有让 php 重定向我。
  • 我的问题是从 PHP 触发 500 或 404。
  • 如果您尝试调试问题,当您被重定向到实际出错的页面时会非常烦人。
  • 您不需要在 .htaccess 中使用如此骇人听闻的东西,您可以直接触发 500:RewriteRule ^ - [R=500]。 (事实上​​,任何无效的语法都可以完成这项工作,例如crash)。您不需要单独的文件夹,您可以在主 .htaccess 文件中设置错误条件:RewriteRule ^crash$ - [R=500] 并重定向到 /crash
  • 将其添加到提到的 .htaccess 文件对我来说很好Redirect 500 /http500
【解决方案3】:
function ISE()
{
  header('HTTP/1.1 500 Internal Server Error', true, 500);
  trigger_error('ISE function called.', E_USER_ERROR);//if you are logging errors?
}

但是,在使用echo 等任何输出函数后,您需要打开输出缓冲才能使用php header() 函数。

【讨论】:

    【解决方案4】:

    我知道这是一个旧线程但是......

    您可以将 iframe 元素渲染到您的视图中,然后将其高度和宽度设置为 100%,以防您准备处理错误。

    <?php header("HTTP/1.0 500 Internal Server Error"); http_response_code(500); ?>

    &lt;iframe src="page_displaying_apache_screenshot_fullscreen.html"&gt;&lt;/iframe&gt;

    说过

    我真的认为最好的现代解决方案是这样的:

    <?php
    header("HTTP/1.0 500 Internal Server Error");
    http_response_code(500);
    ?>
    <div class="panel-body">
        <h1>Error!</h1>
         <p>
             <?php
    
             // Then, in the view if your in dev env, print exception and stack trace
             if ($env === 'dev') 
             {
                 throw new Exception('Uh oh! Something broke while adding a new user the db.');
             }
             else 
             {
                 echo "Hold your butts, an error has occured.";
                 die();
             }
             ?>
         </p>
       </div>
    

    如果您在开发堆栈上将 $env 变量设置为“dev”,这将为所有用户生成正确的错误代码,并且还会为 dev 生成堆栈跟踪。

    没有重定向,没有骇客,安全,除非您需要公开它不会的错误。 :)

    【讨论】:

    • 这是 2020+ 年最优雅的解决方案,既适用于生产环境,也适用于 PHP 显示错误时
    【解决方案5】:

    我可能已经很晚了,但是这个解决方案应该可以工作

    header("HTTP/1.0 500 Internal Server Error");
    include("/path-to-public-html/errors/500.php");
    die();
    

    这将触发 500 ISE 响应,并显示默认的 500 错误页面,然后停止脚本。显然你需要修改包含文件的位置

    【讨论】:

    • 我想让这段代码通用,这样它就可以在任何服务器上运行。根据您的解决方案,我仍然可以通过创建自定义“500 错误”页面来做到这一点,但我想根据服务器设置显示错误页面。
    【解决方案6】:

    如果没有 ben lee 提出的骇客重定向,您根本无法从 php 代码触发 apache 错误页面,因为错误文档重定向是由应用程序堆栈的另一层(特别是 apache 的 mod_core)处理的。
    当您的脚本运行时,为时已晚。

    通过抛出异常来获取错误页面的诡计很大程度上取决于您的 php.ini 中关于 error handling and verbosity 的设置。

    http_response_code()目前只存在于 php 的 svn 中,因此它在大多数应该运行官方发布版本的生产环境中不可用。

    我的建议是分别通过set_error_handler()set_exception_handler() 正确实现自定义错误和异常处理程序,使用header() 向客户端发送正确的http 状态信息并(如果需要)生成错误页面。

    【讨论】:

    • "通过抛出异常获取错误页面的诡计" - 这个"诡计"仅设置 HTTP 状态代码/响应标头,它仍然不返回 Apache 错误文档。 (见my comment to Ben Lee's answer)而http_response_code()只是设置HTTP状态码/响应头的快捷方式,它不返回Apache错误文档。
    【解决方案7】:

    我知道这是一个旧线程,但是当我在 Google 上搜索时,它会作为第一个答案跳出来。这些天我试图弄清楚如何做到这一点,所以我认为我应该从 2018 年开始发布我的解决方法。

    众所周知,不,不能简单地从 PHP 触发 Apache 的错误页面。没有办法做到这一点。因此,经过一番研究,我能找到的最佳解决方法是使用 PHP 函数来显示自定义错误页面,它是从您在 Apache 中指定的内容和您想要的页面中调用的触发 500 内部服务器错误。

    这是我的 Apache conf

    ErrorDocument 400 /error.php
    ErrorDocument 401 /error.php
    ErrorDocument 403 /error.php
    ErrorDocument 404 /error.php
    ErrorDocument 500 /error.php
    

    如您所见,所有 4xx 和 500 错误都被重定向到同一个 php 文件。为什么我不为每个代码使用单独的文件是另一个问题,这里与您的问题无关,所以让我们忘记它,现在专注于error.php

    这里有几行error.php

    <?php
    require_once("error_page.php");
    
    $relative_path = "";
    $internal_server_error = FALSE;
    
    if (isset($_SERVER['REDIRECT_URL']) && $_SERVER['REDIRECT_URL'] != "")
    {
        $relative_path = $_SERVER['REDIRECT_URL'];
        $internal_server_error = (http_response_code() >= 500);
    }
    else if (isset($_SERVER['REQUEST_URI']))
    {
        $relative_path = $_SERVER['REQUEST_URI'];
    }
    
    ErrorPage::GenerateErrorPage($internal_server_error, $relative_path);
    ?>
    

    简而言之,它通过http_response_code()从Apache接收HTTP状态码,并将状态码简单地分为两类:Internal Server Error和Non-Internal Server Error。然后它将类别传递给ErrorPage::GenerateErrorPage(),它实际上会生成错误页面的内容。

    ErrorPage::GenerateErrorPage(),我做了这样的事情:

    <?php
    http_response_code($internal_server_error ? 500 : 404);
    ?>
    

    在函数的开头,这样就不会有任何烦人的“headers already sent”。此函数将生成一个功能齐全的错误页面,其中包含正确的(或至少是我们预期的)HTTP 状态代码。设置好HTTP状态码后,你可能猜到了,下面的php代码会生成两个准备好的内容之一,一个是500,一个是404。

    现在让我们回到你的问题。

    您想触发与 Apache 完全相同的错误页面,现在您可以简单地从任何地方调用 ErrorPage::GenerateErrorPage(),只要您给它正确的参数(TRUE 表示 500,FALSE 表示404 在我的情况下)。

    显然,由于 Apache 错误页面是由同一函数 ErrorPage::GenerateErrorPage() 生成的,我们可以保证您在任何地方触发的内容正是您对 Apache 错误页面的期望。

    这是我的触发页面示例:

    <?php
    ob_start();
    
    require_once("error_page.php");
    
    try
    {
        // Actual contents go here
        phpInfo();
        throw new Exception('test exception');
    }
    catch (Exception $e)
    {
        ob_clean();
        ErrorPage::GenerateErrorPage(TRUE);
        ob_end_flush();
        exit();
    }
    
    ob_end_flush();
    ?>
    

    我使用ob_start()ob_clean()的原因是,通过这种方式,我可以在异常发生之前清除任何输出,并且发送一个看起来与Apache完全一样的纯500 Internal Server Error页面给出,触发页面上没有任何内容(在这种情况下为phpInfo())。 ob_start()ob_clean()确保不会有“标头已发送”,因为除非您致电 ob_end_flush(),否则不会发送任何内容。

    上面的解决方案是根据我这几天的研究得出的。到目前为止,这对我来说很好,但我不确定这是否是正确的方法。欢迎任何 cmets、问题、想法、建议和改进。

    【讨论】:

    • +1 用于 ob_start() / ob_clean() 调用,允许我们开始构建 HTML 内容,但可以随时使用 header() 调用进行重定向。
    【解决方案8】:

    显然有一个名为http_response_code 的函数可以让您适当地设置响应代码。如果这不起作用(文档中有一条说明它可能仅在 SVN 中),那么 header 函数可以采用可选的响应代码参数:

    header("HTTP/1.0 ...", true, 404);
    

    这应该正确地向 Apache 发出信号。

    【讨论】:

    • 为什么会触发Apache的错误文档? PHP 仍然会发送一个不包含任何内容的Content-type: text/html 文档。这会被神奇地忽略吗?请解释更多。
    • @animuson:你测试过还是在推测?如果我正确理解 Apache,这 应该 触发它通常的错误文档处理。当然,这可能取决于配置。
    • 上面的代码向我展示了空白页。对于 http_response_code() 它给了我一个错误:调用未定义的函数 http_response_code()
    • @Forte:好的,然后试试header 的 3-arg 版本。 http_response_code 必须是尚未完全发布的前沿功能。
    【解决方案9】:

    在 PHP 5.5 => "header("tester.php",true,500);"其中 tester.php 不存在。它可以工作并将我带到我的 500 页 :)

    很遗憾,出于某种原因,此处列出的其他方法均不适合我。

    【讨论】:

      【解决方案10】:

      内部服务器错误 500 的原因。 我open httpd.conf text file and edit it 修复了我的错误,只需将我的 serverName localhost 更改为 81 而不是 80。

      【讨论】:

      • 我认为最好在实际答案中分享链接图像中的内容。链接不是最佳实践的一部分,因为它们可能会在将来中断并损害答案的帮助。
      猜你喜欢
      • 1970-01-01
      • 2015-08-16
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      相关资源
      最近更新 更多