HTTP 500报错,不少人第一次碰到会以为是网络中断。页面要么空白,要么显示Internal Server Error。它和404错误性质不一样,404代表访问地址不存在,500代表服务器内部处理发生异常。浏览器请求成功送达服务器,服务器接收之后处理请求时出错,没办法返回正常页面内容。刷新页面、更换浏览器、清除缓存大多没有效果,最多用来判断故障范围:是单页面打不开还是整个网站瘫痪。
全站返回500,故障一般偏向底层,例如web服务配置、PHP进程、数据库连接、磁盘空间耗尽。如果只有单个页面报500,其余页面正常,大概率是这个页面对应的代码、插件或者模板出错。还有一种场景,提交表单之后才触发500,这类问题多和数据处理、数据库写入、调用第三方接口相关。

排查500故障第一步不是修改代码,而是读取日志。500不会把详细原因展示在网页上,全部记录在日志文件。Nginx error.log一般在 /var/log/nginx/,Debian系Apache错误日志 /var/log/apache2/error.log,CentOS系Apache在 /var/log/httpd/error_log。宝塔面板网站日志存放在 /www/wwwlogs。使用PHP环境还要查看PHP-FPM日志,常见路径 /var/log/php-fpm.log 或者 /var/log/php7.x-fpm.log。应用自身日志也不要忽略,WordPress可以开启debug.log,Laravel日志在 storage/logs/laravel.log,ThinkPHP日志默认runtime/log目录。
没有服务器操作权限的用户能做的操作有限,但也不是完全没办法。把故障网址、发生时间、页面报错码发给主机商或者运维人员,请求帮忙查看日志。不要只简单描述网站打不开,这样很难定位问题。如果可以登录宝塔或者虚拟主机控制面板,一般自带错误日志入口,查看最新日志条目,大多能找到具体报错原因。
日志里面常见报错信息分为几类。PHP内存溢出提示Allowed memory size exhausted,脚本执行超时是Maximum execution time exceeded,Permission denied代表文件权限错误,No space left on device是磁盘占满,Access denied for user是数据库账号密码或者权限错误,Unknown database说明数据库不存在。还有Call to undefined function,一般是缺少PHP扩展,或是代码调用了当前PHP版本不支持函数。PHP8对变量类型、未定义变量校验更严格,老项目迁移上来很容易直接抛出500。
临时打开错误提示可以简化排查流程,但存在安全风险。PHP修改php.ini,将display_errors改为On,或者在.htaccess添加php_flag display_errors on。WordPress在wp-config.php写入 define('WP_DEBUG', true); 和 define('WP_DEBUG_LOG', true);,错误信息写入wp-content/debug.log。Laravel修改APP_DEBUG为true。这些操作只适合临时调试,线上环境持续开启会泄露文件路径、数据库账号这类敏感信息,问题修复之后务必关闭。
排查500故障优先回想最近改动。刚更新插件、更换主题、修改伪静态、升级PHP版本、迁移服务器,如果改动时间和报错时间重合,优先回滚这次操作。WordPress可以一次性禁用全部插件,切换回官方默认主题,测试首页是否恢复。恢复正常之后逐个启用插件定位问题代码。代码项目直接回退到上一个正常版本,故障期间不要新增代码修改,越改动越难定位根源。
服务器资源也要检查。df -h查看磁盘占用,free -m查看内存使用,top监控CPU负载。磁盘写满的时候,日志无法写入,会话存储失败,数据库拒绝写入,表现就是500。内存不足,PHP-FPM进程会被系统终止,Nginx收到异常响应。重启php-fpm、Nginx或者Apache可以临时恢复页面,但资源瓶颈不解决,过段时间故障会再次出现。
配置文件写错同样会触发500。Apache .htaccess写入不支持指令,Nginx rewrite规则语法错误,SSL证书路径填写错误,都会造成服务器抛出内部错误。把最近修改的配置还原,或是执行 nginx -t、apachectl configtest校验配置语法,可以快速定位这类问题。伪静态规则很容易踩坑,直接复制别的程序规则,没有修改路径参数,经常引发报错。
数据库连接失败属于高频诱因。账号密码错误、数据库地址变更、连接数打满、数据表损坏,程序在连接阶段直接崩溃。可以命令行尝试连接数据库,命令示例 mysql -u 用户名 -p -h 主机地址,成功连接之后执行简单查询语句。如果无法连接,问题出在数据库服务或权限,不是网页代码。连接正常但单张表无法访问,需要检查表是否损坏,必要时执行修复。
第三方服务调用失败也会引发500。支付回调、短信接口、对象存储、CDN回源,任意环节超时或者返回程序无法解析的数据格式,整个请求流程中断。这类情况日志里一般会出现timeout、connection refused、unexpected response。临时注释相关调用代码,或者缩短超时时间、增加异常捕获,可以验证是不是第三方接口导致故障。
500经常和502、504混淆,简单区分一下。500是应用内部代码处理出错;502是网关收到后端无效响应;504是网关等待后端处理超时。三者可能先后出现,后端程序崩溃,Nginx就会返回502。排查思路有重叠,但500偏向应用代码和配置问题,502偏向进程未启动或者程序崩溃,504偏向脚本执行耗时过长。查看日志留意报错主体,能少走很多弯路。
修复完成不要立刻关闭日志。保留错误日志一段时间,观察相同警告是否重复出现。很多500故障不是突发产生,之前日志已经持续输出大量警告,只是没人查看。养成定期翻看日志习惯,比故障发生之后搜索500解决办法更高效。遇到报错优先读取日志末尾,关键错误信息基本都在那里。