Laravel日志默认写入storage/logs/laravel.log,需确保storage目录对Web服务器用户可写,并检查APP_LOG、LOG_CHANNEL及config/logging.php中驱动与级别配置。

日志文件默认在哪?storage/logs/laravel.log 是主入口
Laravel 默认把运行时错误、异常、调试信息全写进 storage/logs/laravel.log,前提是 storage/ 目录可写且权限正确。常见现象是页面 500 但看不到具体报错——八成是日志没写进去,而不是没日志。
实操建议:
-
storage/目录必须对 Web 服务器用户(如www-data或nginx)有写权限,用ls -l storage/logs看属组和权限,别只 chmod 755 了事 - 如果启用了多环境(如
APP_ENV=production),日志级别可能被设为error,debug()或info()不会落盘,得查config/logging.php里stack或singlechannel 的level配置 - 日志文件名带日期(如
laravel-2024-06-15.log)说明启用了daily日志驱动,不是 bug,是配置行为
php artisan log:tail 能实时看,但生产环境慎用
这个命令本质是 tail -f 包装,适合本地或预发快速验证,但生产服务器上直接跑它,等于让 PHP 进程常驻并持续读文件,既占资源又可能因超时断连——尤其 Nginx + PHP-FPM 架构下,它跟业务请求无关,纯属运维操作。
实操建议:
- 开发/测试机上用
php artisan log:tail没问题;生产环境优先用系统级命令:tail -f storage/logs/laravel.log - 如果日志量大,
tail -f可能卡顿,加-n 50限制初始行数,再配合grep --line-buffered "Exception"过滤关键错误 - 注意:该命令不读取
daily驱动下的历史日期文件,只盯当前活跃日志
日志内容看不懂?重点盯 message、context 和堆栈末尾
Laravel 日志是 JSON 格式(默认)或单行文本(single 驱动),但真正有用的线索不在开头的 timestamp 或 level,而在 message 字段的原始异常描述,以及 context 里传入的变量快照(比如 DB 查询参数、用户 ID)。堆栈(trace)最后几行才是出问题的具体位置。
实操建议:
- 别从头逐字读,先搜
"message":"或Stack trace:,定位到异常本体 -
context里如果出现"exception":{...},说明是未捕获异常,重点看里面的file和line - 常见陷阱:日志里显示
Class not found,但实际是自动加载失败,不是类名写错——检查composer dump-autoload是否执行,vendor/autoload.php是否被正确引入
日志不写、写空、或写错文件?先查 config/logging.php 和 APP_LOG
日志行为由两个地方共同控制:环境变量 APP_LOG(决定驱动类型)和 config/logging.php(定义各驱动细节)。比如 APP_LOG=stderr 会让日志输出到 PHP-FPM 的 error_log,而非文件;而 APP_LOG=stack 则走组合通道,可能同时写文件+推 Sentry。
实操建议:
- 运行
php artisan tinker,输入config('logging.default')看当前生效的 channel,再查config('logging.channels.'.$channel)确认路径、级别、处理器 - 检查
.env是否误写了LOG_CHANNEL=(旧版键名),新版统一用LOG_CHANNEL,不是APP_LOG - 自定义日志处理器(如写入数据库)时,若没实现
write()或抛出异常,会导致整个日志链路静默失败——此时laravel.log本身可能停更
日志路径和格式看着简单,但一旦混用环境变量、驱动配置、文件权限、PHP 运行用户,排查链条就很容易断在某个你以为“肯定没问题”的环节。最常漏掉的是:改完 .env 忘了 php artisan config:clear,或者改了 config/logging.php 却没意识到缓存配置已固化。











