Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PHP与500错误

PHP与500错误

原创
作者头像
yaxin
发布于 2019-03-07 12:22:12
发布于 2019-03-07 12:22:12
7.8K0
举报
文章被收录于专栏:DevOps BoyDevOps Boy

PHP开发过程中经常会遇到返回500错误的情况,而且body体中也没有任何调试(可用)内容。这个时候你就需要慢慢调试了(打断点,开调试模式等),但如果是现网,这个错误就比较让人抓狂了,既不好打断点也不能开调试模式。但既然是错误,总是会有处理方法,下面就一步步分析500的成因及处理方案。

0x01、500错误

500错误,也叫Internal Server Error(内部服务错误),表示服务因未知错误导致无法处理请求。在PHP站点中一般是由PHP返回,也就是说,500错误一般都是PHP脚本的错误。

php-fpm抓包500
php-fpm抓包500

从上图中可以看出(Nginx+PHP-FPM架构),在PHP调用一个不存在的类时,脚本发生错误并返回500给Nginx(并且将错误信息也做了返回,只不过是卸载STDERR中)。

0x02、哪些错误异常会导致500

那么哪类错误会导致500错误呢,PHP所有的错误级别可以在PHP的官方文文档(http://php.net/manual/zh/errorfunc.constants.php)中查询到,而这其中错误级别为E_ERRORE_PARSEE_RECOVERABLE_ERRORE_USER_ERROR以及未捕获的异常等都会导致500错误。

E_ERROR级别错误导致的500
E_ERROR级别错误导致的500

0x03、什么情况下错误不会返回500

上面说了,这个是PHP脚本的错误导致的,但是PHP脚本有了错误或异常一定会导致500吗?显然不是,即使在脚本有致命错误的情况下,依旧可以返回200。

display_errors配置选项

在基于python、nodejs等的web应用中,默认情况下,如果出现异常信息会被打印到控制台(STDERR/STDOUT)中。而在基于PHP-FPM架构的PHP中没有控制台可以打印,它的stderr和stdout被置为FastCGI中对应的STRDERR和STDOUT。如果将错误重定向到STDOUT中,错误会直接输出到响应中,并且状态码也会置为200。这个也是display_errors选项所实现的能力。

display_errors选项的配置需要通过ini_set来实现,PHP文档中关于display_errors的配置表明该值为字符串类型,实际使用中数字和布尔类型也可以打开或关闭该配置。

打开值

关闭值

'On'、1、'1'、true

'Off'、0、'0'、false

error_reporting配置

display_errors控制了PHP脚本发生错误时是否显示错误详情以及是否返回错误状态码,而error_reporting项则用来控制哪级别的错误可以被直接打印出来。

error_reporting的设置项可以通过error_reporting(E_ALL)ini_set('error_reporting', E_ALL)来配置,函数参数的详情可以参考PHP文档

需要注意的是,PHP本身是有错误日志的(error_loglog_errors两个配置项目),若发生错误,PHP会将改错误写入错误日志中,而哪些错误需要被写入是受error_reporting项的控制的。

在错误级别不匹配的情况下不显示错误详情
在错误级别不匹配的情况下不显示错误详情

0x04、现网如何合理处理500

500错误发生已经说明PHP脚本无法正常运行了,这时候能做的只是捕获异常并记录异常到日志,以方便日后的调试和现网bug的处理。

PHP自带错误日志

PHP本身已经带了错误日志的记录,可以在php.ini中将log_errors项设置为On,并配合error_log配置项来指定错误日志的存放路径。

错误日志记录开关
错误日志记录开关
日志路径设置
日志路径设置

该错误日志的的写入不受display_errors的配置的控制。也就是说不管display_errors是否开启,错误都会记录到日志中。但是却受error_reporting配置的控制,如果当前错误级别跟error_reporting中的错误级别不匹配的话,错误不会写入日志中。即如果错误级别是E_ERROR,但是设置却为error_reporting(E_NOTICE),那么日志中不会出现E_ERROR的出错信息。

PHP错误日志记录各种类型的错误
PHP错误日志记录各种类型的错误
错误级别不匹配导致的日志不写入
错误级别不匹配导致的日志不写入

捕获错误异常记录

PHP提供了set_error_handlerregister_shutdown_functionset_exception_handlererror_get_last等相关的错误处理函数。可以通过函数将捕获到的错误信息写入指定日志来实现错误的记录。

函数的使用详情可以参考http://km.oa.com/group/19368/articles/show/302491,这里提供一个模版:

代码语言:txt
AI代码解释
复制
$previousHandler = set_exception_handler(function(Exception $ex) use (&$previousHandler) {
    call_user_func('exceptionHandler', $ex, $previousHandler);
});
set_error_handler('errorHandler');
register_shutdown_function('fatalErrorHandler');

function exceptionHandler(Exception $ex, $previousHandler)
{
    $info = array(
        $ex->getFile(),
        $ex->getLine(),
        $ex->getCode(),
        $ex->getMessage()
    );
    // 记录日志
    logPHPError($info);
    if (isset($previousHandler) && is_callable($previousHandler)) {
        call_user_func($previousHandler, $ex);
    }
}

/**
 * 框架错误处理函数
 * @param $errno
 * @param $errstr
 * @param $errfile
 * @param $errline
 * @return bool
 */
function errorHandler($errno = 0, $errstr = '', $errfile = '', $errline = 0)
{
    switch ($errno) {
        case E_WARNING:
            $errname = 'E_WARNING';
            break;
        case E_NOTICE:
            $errname = 'E_NOTICE';
            break;
        case E_STRICT:
            $errname = 'E_STRICT';
            break;
        case E_RECOVERABLE_ERROR:
            $errname = 'E_RECOVERABLE_ERROR';
            break;
        case E_DEPRECATED:
            $errname = 'E_DEPRECATED';
            break;
        case E_USER_ERROR:
            $errname = 'E_USER_ERROR';
            break;
        case E_USER_WARNING:
            $errname = 'E_USER_WARNING';
            break;
        case E_USER_NOTICE:
            $errname = 'E_USER_NOTICE';
            break;
        case E_USER_DEPRECATED:
            $errname = 'E_USER_DEPRECATED';
            break;
        default:
            restore_error_handler();
            return false;
    }
    // 记录日志
    $info = array(
        $errfile,
        $errline,
        $errname,
        $errstr
    );
    logPHPError($info);
    restore_error_handler();
    return false;
}

/**
 * Fatal error错误处理
 */
function fatalErrorHandler()
{
    if (($e = error_get_last()) && $e['type'] === E_ERROR) {
        $info = array(
            $e['file'],
            $e['line'],
            'E_ERROR',
            $e['message']
        );
        // 记录日志
        logPHPError($info);
    }
}

0x05 总结

总结起来,error_reporting是用于控制向浏览器或PHP错误日志输出错误信息级别的函数或配置,而display_errors则是控制是否向浏览器输出错误和告警信息。

由于PHP的错误日志是全局的,而且受到error_reporting的控制,因此推荐在业务中实现自己的错误(异常)捕获记录逻辑。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
PHP-错误处理
通过trigger_error产生一个用户级别的 error/warning/notice 信息
cwl_java
2020/03/26
8980
PHP错误类型及屏蔽方法
程序只要在运行,就免不了会出现错误,错误很常见,比如Error,Notice,Warning等等。这篇文章具体说一下PHP的错误类型和屏蔽方法。在PHP中,主要有以下3种错误类型。 1. 注意(Notices) 这些都是比较小而且不严重的错误,比如去访问一个未被定义的变量。通常,这类的错误是不提示给用户的,但有时这些错误会影响到运行的结果。 2. 警告(Warnings) 这就是稍微严重一些的错误了,比如想要包含include()一个本身不存在的文件。这样的错误信息会提示给用户,但不会导致程序终止运行。 3
wangxl
2018/03/07
1.6K0
一些简单的错误处理函数(二)
接下来,我们继续学习 PHP 中的错误处理函数。上次学习过的函数是错误信息的获取、设置、发送等功能,今天学习的内容主要是关于错误的捕获相关的函数。
硬核项目经理
2020/06/30
6270
PHP不显示错误信息的解决方法
在有的服务器上,PHP代码执行出错时,浏览器只会显示500错误,这样不利于程序员定位错误代码。
用户2135432
2023/10/21
6670
PHP error_reporting() 错误控制函数功能详解
定义和用法: error_reporting() 设置 PHP 的报错级别并返回当前级别。 函数语法: error_reporting(report_level) 如果参数 level 未指定,当前报错级别将被返回。下面几项是 level 可能的值: 值 常量 描述 1 E_ERROR 致命的运行错误。错误无法恢复,暂停执行脚本。 2 E_WARNING 运行时警告(非致命性错误)。非致命的运行错误,脚本执行不会停止。 4 E_PARSE 编译时解析错误。解析错误只由分析器产生。 8 E_
似水的流年
2018/01/18
7980
display_errors与error_reporting,有意思之处「建议收藏」
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111809.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/11
3710
display_errors与error_reporting,有意思之处「建议收藏」
PHP-错误处理
​ 语法错误最常见,并且也容易修复。如:代码中遗漏一个分号。这类错误会阻止脚本的执行。
汤清丽
2019/11/03
1.8K0
PHP-错误处理
浅谈PHP异常处理
  PHP中的异常的独特性,即PHP中的异常不同于主流语言C++、java中的异常。在Java中,异常是唯一的错误报告方式,而在PHP中却不是这样,而是把所有不正常的情况都视作了错误进行处理。这两种语言对异常和错误的界定存在分歧。什么是异常什么是错误,两种语言的设计者存在不同的观点。
那一叶随风
2018/08/22
1.4K0
浅谈PHP异常处理
PHP中常见的错误与异常处理总结大全
前言 当我们开发程序时,程序出现问题是很常见的,当出现了异常与错误我们该如何处理呢?本文将详细给大家介绍PHP错误与异常处理的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 一、PHP错误处理 1.语法错误
用户2323866
2021/07/01
6990
PHP 错误和异常处理(上)
在 PHP 5 中,程序错误会被划分为多种级别:https://www.php.net/manual/zh/errorfunc.constants.php,然后可以通过 error_reporting 函数设置报告的错误级别:
学院君
2020/07/24
6570
PHP 错误和异常处理(上)
PHP 中的错误处理与异常捕获
在开发任何应用时,错误是不可避免的。无论是由于程序逻辑错误、数据库故障、外部接口问题,还是用户输入不符合预期,错误都会影响应用的正常运行和用户体验。在 PHP 中,处理这些错误的方式至关重要,它直接关系到系统的健壮性、可维护性和可调试性。
繁依Fanyi
2025/01/22
3040
PHP错误处理和调试(一)
当PHP脚本出现错误时,默认情况下,PHP会在浏览器上输出错误信息。这种方式对于开发环境很有用,但在生产环境中,最好将错误信息记录在日志文件中,而不是在浏览器上输出。
堕落飞鸟
2023/04/27
4790
PHP中error_reporting()详解
说白了就是PHP页面报错的级别设置,14个等级供你自定义报错的方式,有数字和字符串两种参数的写法,中文说明对应如下:
用户7657330
2020/08/14
5450
php异常处理 之 BooBoo库介绍
本文介绍php开源库BooBoo,是一个处理php异常和错误的开源库,通过简单的分析代码,我们知道了实际项目中怎么正确的设置错误和异常。
zhuanxu
2018/08/23
5040
php异常处理 之 BooBoo库介绍
PHP框架结构设计-异常机制
1、有哪些代码需要使用异常? 理论上讲,异常可以用在任意地方,但是如果滥用异常,会导致异常链比较复杂,异常处理也比较低效
PHP开发工程师
2021/04/29
4120
一起搞懂PHP的错误和异常(一)
在PHP的学习过程中,我们会接触到两个概念,一个是错误,一个是异常。啥玩意?他们不是一个东西嘛?如果接触过Java、C#之类的纯面向对象语言的同学,可能对异常是没有什么问题,毕竟所有的问题都可以try...catch来解决。但是像PHP这种从面向过程发展到面向对象的语言来说,错误和异常就是两个完全不同的东西了。
硬核项目经理
2020/04/26
1.6K0
你还不会处理 PHP 的错误么?PHP 中错误相关知识看这一篇就够了
错误是程序中的故障或错误。它可以有多种类型。由于错误的语法或错误的逻辑,可能会发生错误。这是一种错误或对代码的了解不正确的情况。
用户1418987
2023/11/18
3240
你还不会处理 PHP 的错误么?PHP 中错误相关知识看这一篇就够了
PHP的错误机制总结
PHP的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课。
wangxl
2018/07/27
1.3K0
PHP 如何捕获 Catchable fatal error?
error_reporting(E_ALL); ini_set("display_errors", "On"); function myErrorHandler($errno, $errstr, $errfile, $errline) { if (E_RECOVERABLE_ERROR === $errno) { throw new ErrorException($errstr, $errno, 0, $errfile, $errline); } return false; } s
OwenZhang
2021/12/08
3360
2021年最新PHP 面试、笔试题汇总(三)
四十九、找出数组中出现一次的元素。10 10 11 11 12 13 12 13 16 只出现一次的数字。要求时间复杂度尽可能低
全栈程序员站长
2022/07/19
1K0
2021年最新PHP 面试、笔试题汇总(三)
相关推荐
PHP-错误处理
更多 >
LV.2
腾讯后台开发
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档