先查error_log实际值和权限,再看框架是否接管日志流;常见原因包括父目录不存在、php进程用户无写权限、selinux/apparmor拦截,需逐层验证。

日志文件“突然消失”不是删了,而是写到了别处、被覆盖、或根本没写成功——先查 error_log 实际值和权限,再看框架是否接管了日志流。
php -i | grep error_log 显示路径但文件不存在
这说明 PHP 尝试往那个路径写,但失败了,且默认静默丢弃。常见原因有三个:
-
error_log路径的父目录不存在(比如配置了/var/log/php/errors.log,但/var/log/php/目录没创建) - PHP 进程用户(如
www-data或nginx)对目录无写权限,ls -ld /var/log/php一看便知 - SELinux 或 AppArmor 启用时拦截了写入,
ausearch -m avc -ts recent | grep php可验证
临时验证:运行 sudo -u www-data touch /var/log/php/test.log,如果报 Permission denied,就不是配置问题,是权限或策略卡住了。
ThinkPHP / Laravel 日志目录空,但 error_log 有内容
框架日志和 PHP 原生日志是两套系统,互不干扰。框架日志不出现,大概率不是 PHP 配置问题,而是:
-
runtime/log(ThinkPHP)或storage/logs(Laravel)目录属主不是 Web 进程用户,ls -ld runtime/log看一眼就知道 - 框架配置里
level设得太高(比如只记error),而你用的是Log::info(),结果直接过滤掉 - CLI 模式下跑了命令(如
php think queue:work),但runtime目录在容器里是只读挂载,或被 .gitignore 忽略导致部署时缺失
别依赖 phpinfo() 查框架日志位置——它只反映 PHP 配置,不反映框架实际行为。直接进项目跑 php think env:get LOG_CHANNEL(TP6)或 php artisan tinker --execute="config('logging.default')"(Laravel)更准。
tail -f /var/log/php-fpm/www-error.log 一直空,但页面确实 500
www-error.log 是 PHP-FPM 的管理日志,只记录子进程崩溃、启动失败、opcache 加载异常等底层问题,**不记录应用层错误**(比如 Fatal error: Uncaught Error:)。这类错误只出现在 PHP 自己的 error_log 文件里,前提是:
-
log_errors = On在当前 SAPI(FPM)生效,而不是只在 CLI 的 php.ini 里开了 -
php_admin_value[error_log]在 pool 配置(如www.conf)中没被设成syslog或stderr - 没被
catch_workers_output = no关闭了 stderr 捕获——否则var_dump()和未捕获异常的堆栈也不会进日志
最简验证法:在入口文件第一行加 error_log("ping", 3, "/tmp/php-ping.log");,然后访问页面,看 /tmp/php-ping.log 是否生成。能写,说明 PHP 写日志能力正常;不能写,就是权限或 SELinux 问题。
日志路径没错、权限也对,但新错误就是不落盘
这种“半失效”现象,90% 出现在日志轮转或磁盘满之后:
- 日志文件被 logrotate 重命名或删除,但 PHP 进程还持有着旧 fd,继续往已删除文件写(Linux 允许),
lsof -p $(pgrep php-fpm) | grep deleted可确认 - 磁盘 inodes 耗尽(
df -i),比磁盘空间满更隐蔽,touch都会报 No space left on device - PHP-FPM 配置了
slowlog且request_slowlog_timeout过短,大量慢请求把日志刷爆,反而掩盖了致命错误
不要只盯着“有没有文件”,要盯“PHP 进程是否还在往正确位置写”。strace -e trace=write -p $(pgrep php-fpm | head -1) 2>&1 | grep -E "(error|log)" 能直接看到它 write() 调用的目标路径和返回值。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











