Laravel 11 调度日志需手动配置:改 cron 输出到日志文件、在任务中加 Log 记录、用 schedule:list 验证注册、通过 timeout/onFailure 和锁日志排查超时与并发问题。

调试 Laravel 11 的任务调度日志,关键不是改命令或加 echo,而是让调度器“说话”——把执行过程、命中状态、失败原因都落到文件里。Laravel 11 默认不写调度日志,得手动配,而且方式和旧版不同。
启用调度器运行日志(最直接)
系统 cron 每分钟调用 schedule:run,但默认输出被重定向到 /dev/null。想看它干了啥,就改这行:
- 把服务器上的 cron 条目从:
* * * * * /usr/bin/php /var/www/myapp/artisan schedule:run >> /dev/null 2>&1
改成:* * * * * /usr/bin/php /var/www/myapp/artisan schedule:run >> /var/log/laravel-schedule.log 2>&1 - 确保
/var/log/laravel-schedule.log文件存在且 web 用户(如 www-data)有写权限 - 执行一次测试:
php artisan schedule:run --verbose,观察终端输出是否含任务名、是否跳过、是否报错
在任务中加自定义日志(精准定位)
光看调度器启动不够,要确认具体命令是否真执行、中间出了啥问题,就在任务逻辑里打点日志:
- 如果是 Artisan 命令类(如
App\Console\Commands\EmailSend),在handle()开头加:\Log::info('EmailSend started', ['time' => now()->toDateTimeString()]); - 在可能出错的位置加:
\Log::error('EmailSend failed', ['exception' => $e->getMessage()]); - 日志会写入
storage/logs/laravel.log(或你配置的其它通道),可用tail -f storage/logs/laravel.log实时跟踪
检查任务是否被识别(避免“写了却没跑”)
常见问题是任务注册了但调度器根本没看到,先验证注册表是否生效:
- 运行:
php artisan schedule:list,它会列出所有已注册任务及其表达式、下次运行时间 - 如果列表为空,说明
Kernel类没正确绑定——确认bootstrap/app.php中已调用withSingletons([...])并传入Illuminate\Contracts\Console\Kernel::class => App\Console\Kernel::class - 如果任务在列表里但“Next Run”始终不更新,检查系统时间是否准确,以及
schedule()方法里有没有语法错误(比如漏了分号、用了未定义变量)
捕获超时与并发冲突(Laravel 11 特有)
Laravel 11 支持任务超时和防重叠,这些行为也需日志辅助排查:
- 给任务加超时并记录失败:
$schedule->command('email:send')->daily()->timeout(120)->onFailure(function () { \Log::error('Email task timed out'); }); - 启用防重叠后,若任务卡住,锁文件默认在
storage/framework/cache,可查schedule-*.lock文件修改时间判断是否残留 - 想看锁机制是否生效,临时加一行:
\Log::debug('Lock acquired for email:send', ['lock_path' => storage_path('framework/cache/schedule-email-send.lock')]);在任务开头


















