Skip to content
虚位以待
虚位以待
赞助商
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

任务调度

介绍

过去,开发人员需要为每个需要调度的任务生成一个 Cron 条目。然而,这是一件麻烦事。你的任务调度不再在源代码控制中,你必须 SSH 到你的服务器上添加 Cron 条目。Laravel 命令调度器允许你在 Laravel 内部流畅且富有表现力地定义你的命令调度,并且在你的服务器上只需要一个 Cron 条目。

你的任务调度是在 app/Console/Kernel.php 文件的 schedule 方法中定义的。为了帮助你入门,方法中包含了一个简单的示例。你可以自由地向 Schedule 对象添加任意数量的计划任务。

启动调度器

这是你需要在服务器上添加的唯一 Cron 条目:

php
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1

这个 Cron 将每分钟调用 Laravel 命令调度器。然后,Laravel 会评估你的计划任务并运行到期的任务。

定义调度

你可以在 App\Console\Kernel 类的 schedule 方法中定义所有计划任务。为了开始,让我们看一个计划任务的示例。在这个示例中,我们将计划一个 Closure 每天午夜被调用。在 Closure 中,我们将执行一个数据库查询来清空一个表:

php
<?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 命令:

php
$schedule->command('emails:send --force')->daily();

exec 命令可以用来向操作系统发出命令:

php
$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();每年运行任务

这些方法可以与附加约束结合使用,以创建更精细的调度,仅在一周的某些天运行。例如,要计划一个命令在每周一运行:

php
$schedule->call(function () {
    // 每周一 13:00 运行一次...
})->weekly()->mondays()->at('13:00');

以下是附加调度约束的列表:

方法描述
->weekdays();限制任务到工作日
->sundays();限制任务到周日
->mondays();限制任务到周一
->tuesdays();限制任务到周二
->wednesdays();限制任务到周三
->thursdays();限制任务到周四
->fridays();限制任务到周五
->saturdays();限制任务到周六
->when(Closure);基于真值测试限制任务

真值测试约束

when 方法可以用来基于给定的真值测试限制任务的执行。换句话说,如果给定的 Closure 返回 true,任务将执行,只要没有其他限制条件阻止任务运行:

php
$schedule->command('emails:send')->daily()->when(function () {
    return true;
});

使用链式 when 方法时,计划的命令只有在所有 when 条件返回 true 时才会执行。

防止任务重叠

默认情况下,即使任务的上一个实例仍在运行,计划任务也会运行。为了防止这种情况,你可以使用 withoutOverlapping 方法:

php
$schedule->command('emails:send')->withoutOverlapping();

在这个示例中,emails:send Artisan 命令 将每分钟运行一次,如果它尚未运行。withoutOverlapping 方法在你有执行时间变化很大的任务时特别有用,防止你无法准确预测给定任务需要多长时间。

任务输出

Laravel 调度器提供了几个方便的方法来处理计划任务生成的输出。首先,使用 sendOutputTo 方法,你可以将输出发送到一个文件以供以后检查:

php
$schedule->command('emails:send')
         ->daily()
         ->sendOutputTo($filePath);

如果你想将输出附加到给定文件,你可以使用 appendOutputTo 方法:

php
$schedule->command('emails:send')
         ->daily()
         ->appendOutputTo($filePath);

使用 emailOutputTo 方法,你可以将输出通过电子邮件发送到你选择的电子邮件地址。请注意,输出必须首先使用 sendOutputTo 方法发送到文件。此外,在通过电子邮件发送任务的输出之前,你应该配置 Laravel 的 电子邮件服务

php
$schedule->command('foo')
         ->daily()
         ->sendOutputTo($filePath)
         ->emailOutputTo('foo@example.com');

NOTE

emailOutputTosendOutputTo 方法仅限于 command 方法,不支持 call

任务钩子

使用 beforeafter 方法,你可以指定在计划任务完成之前和之后执行的代码:

php
$schedule->command('emails:send')
         ->daily()
         ->before(function () {
             // 任务即将开始...
         })
         ->after(function () {
             // 任务完成...
         });

Pinging URLs

使用 pingBeforethenPing 方法,调度器可以在任务完成之前或之后自动 ping 给定的 URL。此方法对于通知外部服务(如 Laravel Envoyer)你的计划任务正在开始或完成非常有用:

php
$schedule->command('emails:send')
         ->daily()
         ->pingBefore($url)
         ->thenPing($url);

使用 pingBefore($url)thenPing($url) 功能需要 Guzzle HTTP 库。你可以通过在 composer.json 文件中添加以下行来将 Guzzle 添加到你的项目中:

php
"guzzlehttp/guzzle": "~5.3|~6.0"