任务调度
介绍
过去,开发人员需要为每个需要调度的任务生成一个 Cron 条目。然而,这是一件麻烦事。你的任务调度不再在源代码控制中,你必须 SSH 到你的服务器上添加 Cron 条目。Laravel 命令调度器允许你在 Laravel 内部流畅且富有表现力地定义你的命令调度,并且在你的服务器上只需要一个 Cron 条目。
你的任务调度是在 app/Console/Kernel.php 文件的 schedule 方法中定义的。为了帮助你入门,方法中包含了一个简单的示例。你可以自由地向 Schedule 对象添加任意数量的计划任务。
启动调度器
这是你需要在服务器上添加的唯一 Cron 条目:
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1这个 Cron 将每分钟调用 Laravel 命令调度器。然后,Laravel 会评估你的计划任务并运行到期的任务。
定义调度
你可以在 App\Console\Kernel 类的 schedule 方法中定义所有计划任务。为了开始,让我们看一个计划任务的示例。在这个示例中,我们将计划一个 Closure 每天午夜被调用。在 Closure 中,我们将执行一个数据库查询来清空一个表:
<?php
namespace App\Console;
use DB;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* 应用程序提供的 Artisan 命令。
*
* @var array
*/
protected $commands = [
\App\Console\Commands\Inspire::class,
];
/**
* 定义应用程序的命令调度。
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
}
}除了计划 Closure 调用,你还可以计划 Artisan 命令 和操作系统命令。例如,你可以使用 command 方法来计划一个 Artisan 命令:
$schedule->command('emails:send --force')->daily();exec 命令可以用来向操作系统发出命令:
$schedule->exec('node /home/forge/script.js')->daily();调度频率选项
当然,你可以为任务分配各种调度:
| 方法 | 描述 |
|---|---|
->cron('* * * * * *'); | 在自定义 Cron 调度上运行任务 |
->everyMinute(); | 每分钟运行任务 |
->everyFiveMinutes(); | 每五分钟运行任务 |
->everyTenMinutes(); | 每十分钟运行任务 |
->everyThirtyMinutes(); | 每三十分钟运行任务 |
->hourly(); | 每小时运行任务 |
->daily(); | 每天午夜运行任务 |
->dailyAt('13:00'); | 每天 13:00 运行任务 |
->twiceDaily(1, 13); | 每天 1:00 和 13:00 运行任务 |
->weekly(); | 每周运行任务 |
->monthly(); | 每月运行任务 |
->yearly(); | 每年运行任务 |
这些方法可以与附加约束结合使用,以创建更精细的调度,仅在一周的某些天运行。例如,要计划一个命令在每周一运行:
$schedule->call(function () {
// 每周一 13:00 运行一次...
})->weekly()->mondays()->at('13:00');以下是附加调度约束的列表:
| 方法 | 描述 |
|---|---|
->weekdays(); | 限制任务到工作日 |
->sundays(); | 限制任务到周日 |
->mondays(); | 限制任务到周一 |
->tuesdays(); | 限制任务到周二 |
->wednesdays(); | 限制任务到周三 |
->thursdays(); | 限制任务到周四 |
->fridays(); | 限制任务到周五 |
->saturdays(); | 限制任务到周六 |
->when(Closure); | 基于真值测试限制任务 |
真值测试约束
when 方法可以用来基于给定的真值测试限制任务的执行。换句话说,如果给定的 Closure 返回 true,任务将执行,只要没有其他限制条件阻止任务运行:
$schedule->command('emails:send')->daily()->when(function () {
return true;
});使用链式 when 方法时,计划的命令只有在所有 when 条件返回 true 时才会执行。
防止任务重叠
默认情况下,即使任务的上一个实例仍在运行,计划任务也会运行。为了防止这种情况,你可以使用 withoutOverlapping 方法:
$schedule->command('emails:send')->withoutOverlapping();在这个示例中,emails:send Artisan 命令 将每分钟运行一次,如果它尚未运行。withoutOverlapping 方法在你有执行时间变化很大的任务时特别有用,防止你无法准确预测给定任务需要多长时间。
任务输出
Laravel 调度器提供了几个方便的方法来处理计划任务生成的输出。首先,使用 sendOutputTo 方法,你可以将输出发送到一个文件以供以后检查:
$schedule->command('emails:send')
->daily()
->sendOutputTo($filePath);如果你想将输出附加到给定文件,你可以使用 appendOutputTo 方法:
$schedule->command('emails:send')
->daily()
->appendOutputTo($filePath);使用 emailOutputTo 方法,你可以将输出通过电子邮件发送到你选择的电子邮件地址。请注意,输出必须首先使用 sendOutputTo 方法发送到文件。此外,在通过电子邮件发送任务的输出之前,你应该配置 Laravel 的 电子邮件服务:
$schedule->command('foo')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('foo@example.com');NOTE
emailOutputTo 和 sendOutputTo 方法仅限于 command 方法,不支持 call。
任务钩子
使用 before 和 after 方法,你可以指定在计划任务完成之前和之后执行的代码:
$schedule->command('emails:send')
->daily()
->before(function () {
// 任务即将开始...
})
->after(function () {
// 任务完成...
});Pinging URLs
使用 pingBefore 和 thenPing 方法,调度器可以在任务完成之前或之后自动 ping 给定的 URL。此方法对于通知外部服务(如 Laravel Envoyer)你的计划任务正在开始或完成非常有用:
$schedule->command('emails:send')
->daily()
->pingBefore($url)
->thenPing($url);使用 pingBefore($url) 或 thenPing($url) 功能需要 Guzzle HTTP 库。你可以通过在 composer.json 文件中添加以下行来将 Guzzle 添加到你的项目中:
"guzzlehttp/guzzle": "~5.3|~6.0"