日志未写入主因是config:cache未清、storage/logs权限不足或LOG_LEVEL设为error;需依次检查LOG_CHANNEL配置、清缓存、修正目录权限,并确认stack通道包含有效子通道及LOG_LEVEL级别匹配。

日志根本没写进去,90% 是 config:cache 没清、storage/logs 权限不对,或者 LOG_LEVEL 被设成了 error —— 不是代码漏写了 Log::info(),而是环境卡住了输出。
storage/logs/laravel.log 为空?先查这三件事
常见现象:调了 Log::error('test'),但 storage/logs/laravel.log 里啥也没有;或只在本地有日志,上线后就消失。
-
LOG_CHANNEL配置是否生效?检查.env中是否写了LOG_CHANNEL=stack(或single),并确认config/logging.php里对应 channel 的path确实指向storage_path('logs/laravel.log') - 配置缓存是否过期?改完
.env或config/logging.php后,必须运行php artisan config:clear—— 开发中别跳这步,config:cache反而可能锁死新配置 -
storage/logs/目录权限够吗?Linux 下常见错误是 Web 用户(如www-data)无写入权,用ls -l storage/logs看属组,再执行chmod -R 755 storage/logs和chown -R www-data:www-data storage/logs
tail -f 看不到实时日志?别急着重装包
现象:执行 php artisan tail 报错 “command not found”,或运行后没输出、卡住、中途断连。
- 确认是否已安装官方推荐的
spatie/laravel-tail(不是 Laravel 自带命令);composer require spatie/laravel-tail后还要php artisan vendor:publish --provider="Spatie\Tail\TailServiceProvider" -
tail命令依赖日志文件存在且持续写入,如果laravel.log本身为空,tail -f就会静默等待——先手动触发一次Log::info('ping')确保有内容 - 宝塔等面板环境常因日志文件过大(>100MB)导致
tail失效,可临时用tail -n 50 storage/logs/laravel.log验证基础读取能力
ERROR 找得到,但 DEBUG/INFO 不见?看 LOG_LEVEL 和通道定义
现象:Log::debug() 不落盘,但 Log::error() 正常;或 daily 通道写进去了,stack 却没反应。
-
LOG_LEVEL默认是 production 环境下的error,开发时务必设为debug,否则debug/info级别直接被过滤掉 -
stack通道是聚合器,它是否包含single或daily?打开config/logging.php查'stack' => ['channels' => ['single']],如果写成['files']而实际没定义fileschannel,日志就丢了 - Monolog 的
level是「最低记录级别」,level => 'debug'表示debug及以上(info、error……)都记;level => 'error'则debug/info全部静音
线上不敢开 APP_DEBUG=true,怎么快速定位 500 错误?
现象:生产环境页面空白或 500,浏览器看不到任何提示,但 laravel.log 里也没 ERROR 记录。
- 先确认异常是否被
app/Exceptions/Handler.php拦截却没上报——检查report()方法里有没有漏掉parent::report($exception),或加了return提前退出 - 某些中间件(如 JWT 验证、权限校验)抛出的异常若未被
render()显式处理,也可能静默吞掉,建议在report()开头加一行Log::emergency('Unhandled exception: ' . $exception->getMessage()); - 如果用了队列任务,错误默认不进主日志,要查
storage/logs/queue-*.log或监听Illuminate\Queue\Events\JobFailed
最常被忽略的一点:日志写入失败时,Laravel 默认不会报错,也不会 fallback 到其他通道——它就真的沉默了。所以每次部署后,务必手动触发一条 Log::info('deploy-' . now()->timestamp) 并立刻去文件里确认是否落地。











