任务调度 
介绍 
过去,您可能为每个需要在服务器上调度的任务生成一个 Cron 条目。然而,这很快就会变得麻烦,因为您的任务调度不再在源代码控制中,您必须 SSH 到服务器中以添加额外的 Cron 条目。
Laravel 的命令调度器允许您在 Laravel 内部流畅且富有表现力地定义命令调度。当使用调度器时,您的服务器上只需要一个 Cron 条目。您的任务调度在 app/Console/Kernel.php 文件的 schedule 方法中定义。为了帮助您入门,该方法中定义了一个简单的示例。
启动调度器 
使用调度器时,您只需在服务器上添加以下 Cron 条目。如果您不知道如何在服务器上添加 Cron 条目,可以考虑使用 Laravel Forge 等服务来管理 Cron 条目:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1这个 Cron 将每分钟调用一次 Laravel 命令调度器。当执行 schedule:run 命令时,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();
$schedule->command(EmailsCommand::class, ['--force'])->daily();exec 命令可用于向操作系统发出命令:
$schedule->exec('node /home/forge/script.js')->daily();调度频率选项 
当然,您可以为任务分配各种调度:
| 方法 | 描述 | 
|---|---|
| ->cron('* * * * * *'); | 按自定义 Cron 调度运行任务 | 
| ->everyMinute(); | 每分钟运行任务 | 
| ->everyFiveMinutes(); | 每五分钟运行任务 | 
| ->everyTenMinutes(); | 每十分钟运行任务 | 
| ->everyThirtyMinutes(); | 每三十分钟运行任务 | 
| ->hourly(); | 每小时运行任务 | 
| ->hourlyAt(17); | 每小时在 17 分钟时运行任务 | 
| ->daily(); | 每天午夜运行任务 | 
| ->dailyAt('13:00'); | 每天 13:00 运行任务 | 
| ->twiceDaily(1, 13); | 每天 1:00 和 13:00 运行任务 | 
| ->weekly(); | 每周运行任务 | 
| ->monthly(); | 每月运行任务 | 
| ->monthlyOn(4, '15:00'); | 每月 4 日 15:00 运行任务 | 
| ->quarterly(); | 每季度运行任务 | 
| ->yearly(); | 每年运行任务 | 
| ->timezone('America/New_York'); | 设置时区 | 
这些方法可以与其他约束结合使用,以创建更精细的调度,仅在一周的某些天运行。例如,要调度一个命令在每周一运行:
// 每周一下午 1 点运行一次...
$schedule->call(function () {
    //
})->weekly()->mondays()->at('13:00');
// 在工作日的上午 8 点到下午 5 点之间每小时运行一次...
$schedule->command('foo')
          ->weekdays()
          ->hourly()
          ->timezone('America/Chicago')
          ->between('8:00', '17:00');以下是其他调度约束的列表:
| 方法 | 描述 | 
|---|---|
| ->weekdays(); | 限制任务在工作日运行 | 
| ->sundays(); | 限制任务在周日运行 | 
| ->mondays(); | 限制任务在周一运行 | 
| ->tuesdays(); | 限制任务在周二运行 | 
| ->wednesdays(); | 限制任务在周三运行 | 
| ->thursdays(); | 限制任务在周四运行 | 
| ->fridays(); | 限制任务在周五运行 | 
| ->saturdays(); | 限制任务在周六运行 | 
| ->between($start, $end); | 限制任务在开始和结束时间之间运行 | 
| ->when(Closure); | 基于真值测试限制任务 | 
时间间隔约束 
between 方法可用于根据一天中的时间限制任务的执行:
$schedule->command('reminders:send')
                    ->hourly()
                    ->between('7:00', '22:00');类似地,unlessBetween 方法可用于排除任务在一段时间内的执行:
$schedule->command('reminders:send')
                    ->hourly()
                    ->unlessBetween('23:00', '4:00');真值测试约束 
when 方法可用于根据给定真值测试的结果限制任务的执行。换句话说,如果给定的 Closure 返回 true,任务将执行,只要没有其他约束条件阻止任务运行:
$schedule->command('emails:send')->daily()->when(function () {
    return true;
});skip 方法可以看作是 when 的反义词。如果 skip 方法返回 true,则计划任务将不会执行:
$schedule->command('emails:send')->daily()->skip(function () {
    return true;
});使用链式 when 方法时,计划命令只有在所有 when 条件返回 true 时才会执行。
防止任务重叠 
默认情况下,即使任务的上一个实例仍在运行,计划任务也会运行。要防止这种情况,您可以使用 withoutOverlapping 方法:
$schedule->command('emails:send')->withoutOverlapping();在此示例中,如果 emails:send Artisan 命令 尚未运行,则每分钟运行一次。withoutOverlapping 方法在您有执行时间变化很大的任务时特别有用,防止您无法准确预测给定任务需要多长时间。
维护模式 
Laravel 的计划任务在 Laravel 处于维护模式时不会运行,因为我们不希望您的任务干扰您可能正在服务器上执行的任何未完成的维护。然而,如果您希望即使在维护模式下也强制运行任务,可以使用 evenInMaintenanceMode 方法:
$schedule->command('emails:send')->evenInMaintenanceMode();任务输出 
Laravel 调度器提供了几种方便的方法来处理计划任务生成的输出。首先,使用 sendOutputTo 方法,您可以将输出发送到文件以供以后检查:
$schedule->command('emails:send')
         ->daily()
         ->sendOutputTo($filePath);如果您希望将输出附加到给定文件,可以使用 appendOutputTo 方法:
$schedule->command('emails:send')
         ->daily()
         ->appendOutputTo($filePath);使用 emailOutputTo 方法,您可以将输出通过电子邮件发送到您选择的电子邮件地址。在通过电子邮件发送任务输出之前,您应该配置 Laravel 的电子邮件服务:
$schedule->command('foo')
         ->daily()
         ->sendOutputTo($filePath)
         ->emailOutputTo('foo@example.com');NOTE
emailOutputTo、sendOutputTo 和 appendOutputTo 方法仅适用于 command 方法,不支持 call。
任务钩子 
使用 before 和 after 方法,您可以指定在计划任务完成之前和之后执行的代码:
$schedule->command('emails:send')
         ->daily()
         ->before(function () {
             // 任务即将开始...
         })
         ->after(function () {
             // 任务完成...
         });URL 监控 
使用 pingBefore 和 thenPing 方法,调度器可以在任务完成之前或之后自动 ping 给定的 URL。此方法对于通知外部服务(如 Laravel Envoyer)您的计划任务正在开始或已完成执行非常有用:
$schedule->command('emails:send')
         ->daily()
         ->pingBefore($url)
         ->thenPing($url);使用 pingBefore($url) 或 thenPing($url) 功能需要 Guzzle HTTP 库。您可以使用 Composer 包管理器将 Guzzle 添加到您的项目中:
composer require guzzlehttp/guzzle