laravel 12 任务调度依赖系统 cron 每分钟执行 php artisan schedule:run,再由 kernel.php 中 schedule() 方法按频率(如 ->daily())触发已注册的 artisan 命令,需避免交互、支持队列、启用去重与失败回调,并通过 schedule:list 和日志调试。

Laravel 12 的任务调度执行 Artisan 命令,核心是通过 app/Console/Kernel.php 中的 schedule() 方法定义任务,并由系统级 cron 触发 php artisan schedule:run 来统一调度。
配置调度入口:确保系统 cron 正常运行
Artisan 调度本身不自带守护进程,必须依赖服务器的 cron 定时拉起。在 Linux/macOS 上,需添加以下 crontab 条目(替换为你的项目真实路径):
* * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1
该行表示每分钟检查一次待执行任务。Laravel 会根据你在 schedule() 中设置的频率(如 ->daily()、->hourly())判断是否真正触发命令。注意:不能省略 cron,仅靠 PHP 进程无法长期可靠运行定时任务。
在 Kernel.php 中注册和定义调度任务
打开 app/Console/Kernel.php,在 schedule(Schedule $schedule) 方法内使用 command() 或 exec() 指定要运行的 Artisan 命令:
- 调用已注册的自定义命令(推荐):
$schedule->command('app:send-weekly-report')->weekly(); - 调用内置命令:
$schedule->command('backup:database')->dailyAt('02:00'); - 执行带参数的命令:
$schedule->command('app:process-orders', ['--status' => 'pending'])->everyFiveMinutes(); - 若需环境隔离或特殊选项,可用
exec():$schedule->exec('php artisan app:cleanup --env=production')->daily();
所有被 command() 调用的命令,必须已在 Artisan 中注册(Laravel 8+ 默认自动发现,但需满足:类在 app/Console/Commands/、命名空间为 App\Console\Commands、继承 Illuminate\Console\Command、且 $signature 非空)。
让命令支持调度的关键细节
不是所有 Artisan 命令都适合直接调度,需注意以下几点:
-
避免交互式逻辑:调度环境下无终端输入,禁用
$this->confirm()、$this->ask()等阻塞方法;改用默认值或配置驱动 -
处理长耗时任务:大数量操作建议结合队列(
->onQueue('high')),防止调度进程阻塞 -
启用重试与失败回调:可链式调用
->onFailure(function (ScheduledTask $task) { \Log::error('调度失败:'.$task->getCommand()); }) -
去重保障:对幂等性差的操作,加上
->withoutOverlapping()防止上一周期未结束就启动新实例
调试与验证调度是否生效
开发阶段快速验证调度逻辑是否写对:
- 运行
php artisan schedule:list查看所有已定义任务及其预计下次运行时间 - 手动触发一次调度(跳过 cron):
php artisan schedule:run,观察输出是否执行目标命令 - 检查日志:
storage/logs/laravel.log中搜索scheduled或命令名,确认实际调用痕迹 - 在命令的
handle()开头加\Log::info('app:send-weekly-report started');辅助追踪











