thinkphp生产环境记错误日志需同时满足四个条件:app_debug=false、log.level包含'error'、log.type='file'、runtime/log目录可写;缺一不可。

ThinkPHP 生产环境能记错误日志,但默认不记——必须同时满足 APP_DEBUG=false、log.level 包含 error、log.type='File' 且 runtime/log 可写这四个条件,缺一不可。
APP_DEBUG=false 是日志写入的开关前提
开发时设为 true,所有错误直接打屏,Log::error() 和异常处理器全被跳过;只有设为 false,未捕获异常才会走 app/exception/Handle.php 的 report() 方法,并触发日志系统。检查你的 .env 文件或 config/app.php,确认 APP_DEBUG = false 已生效。CLI 模式下也要注意:php think command 默认继承环境变量,但手动调用时可能绕过,需显式传参或改配置。
log.level 必须显式包含 'error' 才会落盘
仅配置 'type' => 'File' 不起作用。TP6+ 的日志级别控制在 config/log.php 中,必须写成:'level' => ['error', 'critical']。常见错误包括:
- 留空或注释掉
level配置 → 日志静默丢弃 - 只写
['info']→ error 级别被过滤 - 用
LOG_LEVEL=error环境变量但没在public/index.php加载框架前定义 → 框架读不到
注意:trace => true 虽然能让 error 日志带堆栈,但它只对 error 和 notice 生效,不影响是否写入。
runtime/log 目录权限和路径必须双重校验
报 Permission denied 不一定是权限数字错了,更可能是用户不匹配:
- 先查 PHP-FPM 实际用户:
ps aux | grep php-fpm(通常是www-data或nginx) - 再查目录归属:
ls -ld runtime runtime/log,确保父目录和子目录都属同一用户 - 执行
chown -R www-data:www-data runtime(替换为你的真实用户) - 在
config/log.php中用绝对路径:'path' => realpath(__DIR__ . '/../runtime/log/') . DS,避免 Web/FPM/CLI 下相对路径解析不一致
Docker 环境还要额外检查挂载卷 UID/GID 是否与容器内用户一致,否则 chown 无效。
Log::error() 不见日志?先看它有没有进队列
TP6 默认延迟写入:Log::error('msg') 只是把日志塞进内存队列,等请求结束才统一刷盘。所以:
- 在
App::init()前调用 → 报错或静默失败(日志系统还没加载) - 在中间件或控制器里调用 → 正常,但看不到实时文件变化
- 需要立即落盘 → 改用
Log::save(),或在Log::error()后加Log::save() - 自定义通道(如数据库)→ 必须用
Log::channel('db')->error(),不能接->record()
如果连队列都没进,回头检查 log.close = true 或 channels.file.level 是否被单独覆盖了。
最常被忽略的是:PHP 底层致命错误(如 Parse error、Fatal error)根本不会经过 ThinkPHP 日志系统,它们只走 php.ini 的 log_errors 和 error_log。要查这类问题,得去翻 /var/log/php_errors.log,而不是 runtime/log。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











