PHP 报 500 错误时,浏览器只显示“Internal Server Error”,具体原因不会直接暴露给前端,这是设计上的安全策略。要查具体原因,核心动作是把错误细节从服务器端捞出来,而不是在浏览器里反复刷新。判断方向:先确认错误发生在 PHP-FPM 还是 Web 服务器层,再打开对应日志;如果日志里没有线索,用临时错误显示或最小化复现来定位。边界是:生产环境不要长期开启 display_errors,也不要把错误详情直接输出给用户。
PHP 500 错误排查的关键是找到被隐藏的错误信息。优先查 PHP 错误日志和 Web 服务器错误日志;临时开启 display_errors 只适合本地或预发环境;若日志无记录,检查 PHP-FPM 进程状态和权限配置。不要在生产环境向浏览器输出错误详情,也不要在未确认根因前反复重启服务。
先分清 500 是 PHP 抛的,还是 Web 服务器抛的
PHP 代码抛出致命错误时,通常由 PHP-FPM 返回 500,并在 PHP 错误日志里留下记录;而 Web 服务器(Nginx/Apache)自身配置错误、上游超时、权限拒绝,也可能返回 500,此时 PHP 日志可能完全空白。一个简单的判断动作:查看 Nginx 的 error.log 或 Apache 的 error_log,如果出现“upstream timed out”“connect() failed”或“Permission denied”,问题在 Web 服务器到 PHP-FPM 这一段;如果 error.log 里只有“client intended to send too large body”之类的请求问题,而 PHP 日志有对应时间点的报错,则根因在 PHP 代码或扩展。
打开正确的日志,而不是猜
PHP 错误日志的位置由 php.ini 中的 error_log 决定,也可以用 phpinfo() 或 php -i | grep error_log 确认。常见位置包括 /var/log/php-fpm/error.log、/var/log/php_errors.log,或项目目录下的 error_log 文件。如果日志里没有内容,先检查 log_errors 是否开启,以及 PHP-FPM 进程用户是否有写日志文件的权限。另一个容易忽略的点:error_reporting 级别太低会过滤掉部分错误,排查阶段可以临时设为 E_ALL,但改完记得恢复。
临时让错误显示出来,但只限安全环境
在本地或预发环境,可以在 PHP 脚本顶部临时加入以下代码,让错误直接输出到页面或日志:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
如果这样仍然只看到 500 而没有错误文本,说明错误发生在 PHP 解析之前(比如语法错误导致文件无法编译),或者被 PHP-FPM 的 catch_workers_output 设置拦截。此时应检查 PHP-FPM 配置中的 catch_workers_output = yes 是否开启,并重启 PHP-FPM 使配置生效。生产环境不要保留这些设置,排查完立即还原。
用最小化复现锁定代码位置
如果日志里有错误但信息模糊,比如只提示“Allowed memory size exhausted”或“Maximum execution time exceeded”,可以按以下顺序缩小范围:
- 在入口文件(如 index.php)最前面加一行
echo 'start'; exit;,确认请求是否进入 PHP 层。 - 逐步注释掉可疑代码块,或使用
try/catch捕获异常并写入自定义日志。 - 检查最近修改的文件、新增的扩展或依赖,500 错误常与语法错误、未定义函数、类加载失败相关。
- 如果使用框架,打开框架的调试模式(如 Laravel 的
APP_DEBUG=true),但同样只限非生产环境。
对于内存或超时类错误,日志里通常有明确提示,直接调整 memory_limit 或 max_execution_time 只能缓解症状,仍需定位是哪段代码消耗了资源。
常见问题
日志里什么都没有,怎么办?
先确认 PHP-FPM 是否在运行,用 systemctl status php-fpm 或 ps aux | grep php-fpm 查看进程状态。如果 PHP-FPM 崩溃,错误可能记录在系统日志(/var/log/messages 或 journalctl -u php-fpm)中。另外检查磁盘空间是否已满,磁盘满会导致日志无法写入。
开了 display_errors 还是只看到 500?
可能是 Web 服务器配置了 fastcgi_intercept_errors on,把 PHP 的响应替换成了自定义错误页。检查 Nginx 配置中该指令,或查看 error_page 500 的指向。临时关闭该指令可让 PHP 错误直接透出,但同样只建议在排查阶段使用。