PHP 在 Linux 上出错时,最容易浪费时间的不是修复本身,而是一开始就找错方向:明明是扩展没装,却去翻业务代码;明明是权限问题,却一直改 php.ini。更稳妥的做法,是先确认错误能否被记录和复现,再沿着语法、权限、配置和依赖逐层排查。这样处理下来,读者不仅能尽快定位当前故障,也能判断下一步该查日志、改配置,还是直接进入调试器。
先看错误日志,拿到第一手报错信息
排查 PHP 问题时,最直接也最有效的入口通常就是错误日志。日志里会记录脚本运行过程中的语法错误、致命错误、警告等细节,它往往比浏览器里的一句报错更完整,也更接近真实故障点。

先确认日志文件到底写到哪里
常见做法有两种。
第一种是直接查看 php.ini 配置。如果当前机器可使用 root 权限,可以执行:
sudo grep -i "error_log" /etc/php.ini
输出结果里一般就能看到日志路径,例如 /var/log/php-fpm/error.log 或 /var/log/apache2/error.log。
第二种方式是借助 phpinfo()。在任意 PHP 文件中加入下面这段内容:
然后通过浏览器访问该文件,搜索 error_log,就能看到当前实际生效的日志路径。这种方法的好处是,能确认 Web 环境真正加载的是哪套配置。
实时跟踪日志,适合边改边看
找到日志文件后,可以直接实时监听新增内容:

sudo tail -f /var/log/php-fpm/error.log
这样一来,每次触发页面请求,新产生的错误都会立即显示在终端里。对复现问题、对照修改结果尤其有用。
如果发现日志路径对应的目录根本不存在,就需要先手动创建,并把所有权交给实际运行 Web 服务的用户。例如:
sudo mkdir -p /var/log/php-fpm && sudo chown www-data:www-data /var/log/php-fpm
这里的 www-data 只是常见示例,实际环境也可能是 apache 或 nginx,应按当前系统服务用户调整。
开发环境中开启错误显示,但不要带到生产环境
如果日志里信息还不够,或者你正在本地、测试机上调试代码,可以临时开启 PHP 错误显示,让报错直接输出到页面。但这一步只能用于开发环境,生产环境必须关闭,否则路径、变量、配置等敏感信息都可能被直接暴露。
优先修改 php.ini 中的关键参数
需要重点确认的配置通常有三项:

display_errors = On:开启错误显示display_startup_errors = On:显示启动阶段错误error_reporting = E_ALL:报告全部错误级别
修改完成后,别忘了重启相关服务,让配置真正生效。常见命令如下:
sudo systemctl restart apache2
sudo systemctl restart nginx
sudo systemctl restart php-fpm
实际需要重启哪些服务,取决于当前使用的是 Apache、Nginx 还是 PHP-FPM 组合。
无法改 php.ini 时,可在脚本里临时开启
如果当前环境不方便改全局配置,也可以在待调试脚本开头临时加入以下代码:
这种方式适合快速验证单个页面或接口,但它只能覆盖当前脚本,不适合作为长期方案。
先排语法,再查权限,能解决一大批基础错误
很多 PHP 故障并不复杂,只是因为语法写错,或者 Web 服务根本没有权限读取、执行相关文件。把这两类问题先筛掉,排查效率会高很多。
用 php -l 快速检查语法
PHP 自带语法检查工具,不需要运行脚本就能发现明显错误。命令格式是:
php -l 文件名.php
例如:
php -l index.php
如果存在语法问题,终端会直接给出具体位置,例如:
Parse error: syntax error, unexpected ';' in index.php on line 10
这类报错通常很好修,优先处理能立刻缩小问题范围。
此外,VS Code、Sublime Text、PHPStorm 这类编辑器也普遍带有实时语法检查能力,日常开发阶段就能提前发现不少低级错误。
文件权限不对,程序也可能表现得像“代码有问题”
当错误信息里出现 Permission denied、File not found 等提示时,就不能只盯着 PHP 代码本身了,还要检查脚本文件、配置文件、上传目录以及依赖目录的权限和所有权。
常见权限建议如下:
- PHP 脚本文件一般使用
644 - 目录一般使用
755 - 需要写入的上传目录可根据场景使用
775或777
对应命令例如:
sudo chmod 644 文件名.php
sudo chmod 755 目录名/
777 虽然省事,但风险也最大,能不用就尽量不用,更稳妥的做法是把写权限限制给明确的服务用户或用户组。
所有权同样要匹配 Web 服务实际运行账户,例如:
sudo chown www-data:www-data 文件名.php
如果当前环境用的是 apache 或 nginx 用户,也应同步替换。
核对 PHP 配置项,避免环境本身“拖后腿”
有些问题看起来像业务异常,实质上却是 PHP 运行配置不完整。尤其是在迁移服务器、切换 PHP 版本、同时存在多套配置文件时,配置冲突经常会引出一串连锁问题。
几个最值得优先确认的参数
php.ini 里至少有三类配置值得优先检查。
第一类是扩展目录与扩展加载。比如 extension_dir 应指向正确路径,例如:
/usr/lib/php/20230831/
同时要确认 mysqli、gd、opcache 等扩展确实已启用。像下面这样的配置如果被注释掉,就需要按需取消注释:
extension=mysqli.so
第二类是时区设置。若 date.timezone 未正确配置,常见报错就是:
date(): It is not safe to rely on the system's timezone settings
通常可将其设为有效值,例如:
Asia/Shanghai
第三类是内存限制。若脚本执行中断、后台任务处理大文件失败,就要检查 memory_limit 是否过低。常见可用值包括 256M 或 512M,具体取决于项目负载。
改完配置后,一定要重启服务
修改 php.ini 后,如果没有重启服务,很多人会误以为配置无效。常见做法是同时重启 PHP 服务与 Web 服务,例如:
sudo systemctl restart php-fpm && sudo systemctl restart apache2
如果前端是 Nginx,则把对应服务替换成 Nginx 即可。
函数未定义,多半是扩展或依赖没有装全
当页面提示类似 “Call to undefined function mysqli_connect()” 这类错误时,问题通常不在语法,而在运行环境缺少扩展或第三方依赖。
先看当前到底加载了哪些扩展
可以先执行:
php -m
这个命令会列出当前 PHP 已加载的全部扩展,重点确认 mysqli、gd、curl 等项目依赖是否存在。
如果缺失,就按系统类型安装。例如在 Debian/Ubuntu 中:
sudo apt-get install php-扩展名
例如安装 MySQLi:
sudo apt-get install php-mysqli
在 CentOS/RHEL 中则可使用:
sudo yum install php-扩展名
安装完成后,同样要重启 php-fpm 和对应 Web 服务,否则新扩展不会被进程加载。
别漏掉 Composer 依赖
如果项目依赖的是第三方库,而不是 PHP 内置扩展,那么还要确认 Composer 依赖是否已经安装到位。最常见的检查点有两个:一是执行过 composer install,二是项目中的 vendor 目录存在且 Web 进程可访问。
复杂问题再上 Xdebug 和自定义错误处理
如果前面的日志、语法、权限、配置、扩展都确认过了,问题仍然存在,那多半已经不是“基础环境错误”,而是更隐蔽的逻辑问题,例如变量值异常、条件判断分支走错、函数调用链和预期不一致。这时就要借助调试工具做深挖。
Xdebug 适合追踪执行过程
Xdebug 是 PHP 环境里最常用的深度调试工具之一。安装可以直接通过包管理器完成,例如:
sudo apt-get install php-xdebug
安装后,需要在 php.ini 中补充或确认关键配置,例如:
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.idekey=PHPSTORM
配合 PHPStorm、VS Code 等 IDE 设置断点后,就能进行单步执行、变量查看和调用栈分析。对于“代码没报错但结果不对”的场景,这比单纯刷日志更高效。
自定义错误处理,适合持续追踪线上异常
除了通用调试器,也可以在代码中增加更细粒度的错误记录逻辑。比如使用 set_error_handler 定义自定义错误处理函数,把错误信息统一写入指定文件,或者接入通知渠道,便于后续排查和回溯。
如果把整个排查顺序总结一下,比较稳的路径通常是:先看日志确认真实报错,再决定是否临时开启错误显示;接着检查语法、权限和所有权;之后核对 php.ini、扩展和 Composer 依赖;最后再把 Xdebug 这类工具用于复杂逻辑问题。这样分层处理,能避免一开始就在错误方向上反复消耗时间。







