任务调度
简介
过去,你可能需要在服务器上为每一个调度任务去创建 Cron 条目。因为这些任务的调度不是通过代码控制的,你要查看或新增任务调度都需要通过 SSH 远程登录到服务器上去操作,所以这种方式很快会让人变得痛苦不堪。 Laravel 的命令行调度器允许你在 Laravel 中清晰明了地定义命令调度。在使用这个任务调度器时,你只需要在你的服务器上创建单个 Cron 入口。你的任务调度在 app/Console/Kernel.php 的 schedule 方法中进行定义。为了帮助你更好的入门,这个方法中有个简单的例子。
定义调度
你可以在 App\Console\Kernel
类的 schedule
方法中定义所有的调度任务。在开始之前,我们来看一个例子:我们计划每天午夜执行一个 闭包
,这个 闭包
会执行一次数据库语句去清空一张表:
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;
class Kernel extends ConsoleKernel
{
/**
* 定义应用中的命令调度
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
}
}
除了调用闭包这种方式来调度外,你还可以调用 可调用对象. 可调用对象是简单的 PHP 类,包含一个 __invoke
方法:
$schedule->call(new DeleteRecentUsers)->daily();
如果你想查看任务计划的概述 及其下次计划运行时间,你可以使用 schedule:list
Artisan 命令:
php artisan schedule:list
Artisan 命令调度
调度方式不仅有调用闭包,还有调用 Artisan commands 和操作系统命令。例如,你可以给 command
方法传递命令名称或类来调度一个 Artisan 命令:
当使用命令类名调度 Artisan 命令时,你可以通过一个数组传递附加的命令行参数,且这些参数需要在命令触发时提供:
use App\Console\Commands\SendEmailsCommand;
$schedule->command('emails:send Taylor --force')->daily();
$schedule->command(SendEmailsCommand::class, ['Taylor', '--force'])->daily();
队列任务调度
job
方法可以用来调度 queued job。此方法提供了一种快捷方式来调度任务,而无需使用 call 方法创建闭包来调度任务:
use App\Jobs\Heartbeat;
$schedule->job(new Heartbeat)->everyFiveMinutes();
job
方法提供了可选的第二,三参数,分别指定任务将被放置的队列名称及连接:
use App\Jobs\Heartbeat;
// 分发任务到「heartbeats」队列及「sqs」连接...
$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
Shell 命令调度
exec
方法可发送命令到操作系统:
$schedule->exec('node /home/forge/script.js')->daily();
调度频率选项
我们已经看到了几个如何设置任务在指定时间间隔运行的例子。不仅如此,你还有更多的任务调度频率可选:
方法 | 描述 |
---|---|
->cron('* * * * *'); | 自定义 Cron 计划执行任务 |
->everyMinute(); | 每分钟执行一次任务 |
->everyTwoMinutes(); | 每两分钟执行一次任务 |
->everyThreeMinutes(); | 每三分钟执行一次任务 |
->everyFourMinutes(); | 每四分钟执行一次任务 |
->everyFiveMinutes(); | 每五分钟执行一次任务 |
->everyTenMinutes(); | 每十分钟执行一次任务 |
->everyFifteenMinutes(); | 每十五分钟执行一次任务 |
->everyThirtyMinutes(); | 每三十分钟执行一次任务 |
->hourly(); | 每小时执行一次任务 |
->hourlyAt(17); | 每小时第十七分钟时执行一次任务 |
->everyTwoHours(); | 每两小时执行一次任务 |
->everyThreeHours(); | 每三小时执行一次任务 |
->everyFourHours(); | 每四小时执行一次任务 |
->everySixHours(); | 每六小时执行一次任务 |
->daily(); | 每天 00:00 执行一次任务 |
->dailyAt('13:00'); | 每天 13:00 执行一次任务 |
->twiceDaily(1, 13); | 每天 01:00 和 13:00 各执行一次任务 |
->weekly(); | 每周日 00:00 执行一次任务 |
->weeklyOn(1, '8:00'); | 每周一 08:00 执行一次任务 |
->monthly(); | 每月第一天 00:00 执行一次任务 |
->monthlyOn(4, '15:00'); | 每月第四天 15:00 执行一次任务 |
->twiceMonthly(1, 16, '13:00'); | 每月第一天和第 十六天的 13:00 各执行一次任务 |
->lastDayOfMonth('15:00'); | 每月最后一天 15:00 执行一次任务 |
->quarterly(); | 每季度第一天 00:00 执行一次任务 |
->yearly(); | 每年第一天 00:00 执行一次任务 |
->yearlyOn(6, 1, '17:00'); | 每年六月第一天 17:00 执行一次任务 |
->timezone('America/New_York'); | 设置时区 |
这些方法与额外的约束 条件相结合后,可用于创建在一周的特定时间运行甚至更精细的计划任务。例如,在每周一执行命令:
// 在每周一 13:00 执行...
$schedule->call(function () {
//
})->weekly()->mondays()->at('13:00');
// 在每个工作日 8:00 到 17:00 之间的每小时周期执行...
$schedule->command('foo')
->weekdays()
->hourly()
->timezone('America/Chicago')
->between('8:00', '17:00');
下方列出了额外的约束条件:
方法 | 描述 |
---|---|
->weekdays(); | 限制任务在工作日执行 |
->weekends(); | 限制任务在周末执行 |
->sundays(); | 限制任务在周日执行 |
->mondays(); | 限制任务在周一执行 |
->tuesdays(); | 限制任务在周二执行 |
->wednesdays(); | 限制任务在周三执行 |
->thursdays(); | 限制任务在周四执行 |
->fridays(); | 限制任务在周五执行 |
->saturdays(); | 限制任务在周六执行 |
->days(array|mixed); | 限制任务在每周的指定日期执行 |
->between($startTime, $endTime); | 限制任务在 $startTime 和 $endTime 区间执行 |
->unlessBetween($startTime, $endTime); | 限制任务不在 $startTime 和 $endTime 区间执行 |
->when(Closure); | 限制任务在闭包返回为真时执行 |
->environments($env); | 限制任务在特定环境中执行 |
周几(Day)限制
days
方法可以用于限制任务在每周的指定日期执行。举个例子,您可以在让一个命令每周日和每周三每小时执行一次:
$schedule->command('emails:send')
->hourly()
->days([0, 3]);
不仅如此,你还可以使用 Illuminate\Console\Scheduling\Schedule
类中的常量来设置任务在指定日期运行:
use Illuminate\Console\Scheduling\Schedule;
$schedule->command('emails:send')
->hourly()
->days([Schedule::SUNDAY, Schedule::WEDNESDAY]);
时间范围限制
between
方法可用于限制任务在一天中的某个时间段执行:
$schedule->command('emails:send')
->hourly()
->between('7:00', '22:00');