TP6日志写入失败主因是权限不足、日志级别过滤或驱动被运行时覆盖;需确认Web进程用户对runtime及子目录有完整写权限,检查log.level配置是否匹配日志级别,并排查Log::driver()调用导致的驱动覆盖。

TP6 日志写入失败,绝大多数情况不是配置写错了,而是权限没到位——目录不可写、用户不匹配、runtime 层级被忽略。修复关键在三点:确认 Web 进程用户对 runtime 及其子目录有完整写权限;确保日志级别与调用匹配;排除驱动被运行时覆盖。
检查并修正 runtime 目录权限
ThinkPHP 6 默认将日志写入 runtime/log,但这个路径能否写入,取决于两层权限:
-
runtime目录本身必须可写(否则连日志文件都创建不了) -
runtime/log子目录也必须可写(否则已有文件无法追加) - Linux 下需确认 PHP-FPM 或 Web 服务用户(如
www-data、nginx、apache)是目录属主或属组成员
执行以下命令快速验证:
ls -ld runtime runtime/log
若显示权限为 drwxr-xr-x 但属主不是 Web 用户,用对应命令修复:
Debian/Ubuntu:sudo chown -R www-data:www-data runtime
CentOS/RHEL:sudo chown -R nginx:nginx runtime
Docker 环境要额外检查挂载卷的 UID/GID 是否与容器内 Web 用户一致,否则 chown 无效。
确认日志级别未过滤掉你的日志
TP6 日志是“门禁式”控制:低于 log.level 配置的日志根本不会进入写入流程。例如你调用 Log::info(),但配置中设了 'level' => 'error',那这条日志就静默丢弃了。
检查 config/log.php 中的 level 设置:
- 开发阶段建议设为
'debug'或['debug', 'info', 'warning', 'error'] - 生产环境至少设为
'warning',避免info类日志刷爆磁盘 - 注意:该值是“最低记录门槛”,
level => 'warning'表示只记录warning及以上级别
APP_DEBUG 开关不影响日志写入,它只控制错误页面是否显示堆栈。
排查日志驱动是否被运行时覆盖
很多人只改了 config/log.php,却在中间件、命令行入口或 app/common.php 中写了 Log::driver('socket') 或 Log::driver('test'),导致后续所有日志都走错通道。
-
'type' => 'trace'和'type' => 'test'是内存驱动,不落盘,线上误配等于关日志 - 全局搜索项目中所有
Log::driver(调用,尤其检查中间件、Console 命令和单元测试启动逻辑 - 确保
config/log.php中'default' => 'file',且没有代码在运行时强行切换
临时验证:在控制器里加一行 Log::save(); 强制立即刷盘,如果这时能写出日志,基本可锁定是驱动延迟或被覆盖问题。
CLI 模式下权限独立处理
Web 请求用 www-data 用户,而命令行(如 php think hello)常以 root 或当前登录用户运行。两者对 runtime/log 的权限可能完全不同。
- 不要指望 Web 环境的权限设置能保 CLI 日志
- 方案一:统一属主,例如把 CLI 也切到
www-data(sudo -u www-data php think hello) - 方案二:为 CLI 单独配置日志路径,在
config/log.php中根据PHP_SAPI === 'cli'动态指定path
若 CLI 下 Log::info() 无声失败,优先检查该场景下的目录权限,而非重配 level 或 type。

















