PHP错误日志写不进文件需分环境确认配置:Web下检查phpinfo()的Loaded Configuration File,CLI下运行php --ini;确保log_errors=On、error_reporting=E_ALL;目录权限和日志轮转(如logrotate)也必须配置。

PHP错误日志写不进文件?先确认运行模式和配置生效位置
PHP的error_log配置只在Web SAPI(如FPM、Apache模块)下才真正写入文件;CLI模式默认输出到终端,即使你改了php.ini也看不到日志文件变化。
必须分环境验证:
- Web环境:访问
phpinfo()页面,查“Loaded Configuration File”路径,确认你改的是这个php.ini - CLI环境:运行
php --ini,看它加载的是哪个配置——多数情况CLI用的是另一份php.ini,和Web无关 - 检查
log_errors = On是否启用,且error_reporting级别足够(比如E_ALL),否则E_NOTICE类错误根本不会触发写入 - 确保
/var/log/php_errors.log所在目录存在,且PHP进程用户(如www-data)有write权限,否则静默失败
只靠error_log()函数记录太单薄,上下文缺失怎么办
error_log()原生行为只输出错误消息+行号,没有请求URL、IP、POST数据、时间戳等关键定位信息。线上出问题时,光看Undefined variable: user根本没法复现。
推荐用set_error_handler()兜底,手动拼接上下文:
立即学习“PHP免费学习笔记(深入)”;
- 在入口文件开头加
error_reporting(E_ALL),再调用set_error_handler(),否则E_NOTICE类错误不会进入你的处理器 - handler里别直接调
error_log()——它受log_errors = Off控制,可能失效;改用file_put_contents($log_file, $msg, FILE_APPEND | LOCK_EX) - 主动抓取
$_SERVER['REQUEST_URI']、$_SERVER['REMOTE_ADDR']、date('c'),再加debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)精简堆栈 - 敏感字段如
$_POST['password']必须过滤,用array_diff_key($_POST, ['password' => ''])或正则擦除,别dump全量数组
访问日志不能只靠PHP,必须由Nginx或Apache接管
PHP本身不生成访问日志(HTTP状态码、响应时间、User-Agent等),这部分完全依赖Web服务器。单独配好error_log却没开access_log,等于只看到“哪里错了”,却不知道“谁在什么时候触发的”。
Nginx配置示例(放在server块内):
access_log /var/log/nginx/example_access.log main; error_log /var/log/nginx/example_error.log warn;
注意:main是Nginx内置日志格式,含时间、IP、方法、路径、状态码、响应大小;若要加请求体或Header,得自定义log_format,但会显著拖慢性能,慎用。
Apache对应指令是CustomLog和ErrorLog,路径和权限要求一致——确保www-data对日志目录有w权限,否则服务启动失败。
日志爆炸没人管?error_log不轮转,必须外挂logrotate
error_log = /var/log/php_errors.log是纯追加写,没有任何大小限制或按天切分逻辑。一个中等流量站点,一天就能写满几GB,磁盘爆掉前毫无预警。
别指望PHP自己处理轮转,必须用系统级工具:
- Linux下配
logrotate,例如/etc/logrotate.d/php-errors内容:
/var/log/php_errors.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 644 www-data www-data
sharedscripts
}
或者用框架自带的日志组件(如Monolog),它支持RotatingFileHandler,但要注意:PHP进程需有权限创建新文件,且rotate动作发生在PHP内部,不如logrotate可靠。
更关键的是:register_shutdown_function()必须配合error_get_last()补漏Fatal Error——因为set_error_handler()捕获不到内存耗尽、语法错误这类致命问题。



















