译文 GitHub https://github.com/yuansir/diving-laravel-zh

原文链接 https://divinglaravel.com/task-scheduling/before-the-dive

想象这种情况,作为一个大型 SaaS 的开发者,您需要找到一种在周末每分钟选择 10 个随机客户的方式,并提供折扣升级,发送折扣的工作可能非常简单,但我们需要每分钟运行一次,为此我分享一些 CRON 的简要介绍给还不熟悉人。

CRON

CRON 是一个守护进程,它驻留在你的 linux 服务器中,大部分时间都没有唤醒,但是每一分钟它都会睁开双眼,看看是否运行任何给定的任务,你使用 crontab 文件与该守护进程通信,在大多数常见的设置文件可以位于/etc/crontab,crontab 文件可能看起来像这样:

0 0 1 * * /home/full-backup
0 0 * * * /home/partial-backup
30 5 10 * * /home/check-subscriptions

在 crontab 文件中,每行表示一个计划任务作业,每个作业定义包含两部分:

  1. *部分代表该作业运行的计时器。
  2. 第二部分是应运行的命令

CRON 时序语法

5 个星号按顺序排列如下:

  1. 一小时内的分钟
  2. 一天内的小时
  3. 一个月内的日期
  4. 一年内的月份
  5. 一周的内的天

示例:

  • 0 0 1 * * 在第一个例子中,表示该工作应在每月,每个月的第一个天,上午 12 点,每小时第一分钟运行。 或者简单地说,它应该在每月的第一天上午 12:00 运行。
  • 0 * * * * 在第二个例子中,表示该工作应该每小时运行一次。
  • 30 5 10 * * 表示该工作应该在每个月 10 日上午 5:30 运行

这里还有一些其他的示例:

  • * * * * 3 表示工作应该在星期三每分钟运行一次。
  • * * * * 1-5 表示该工作应该每周一至周五运行。
  • 0 1,15 * * * 表示该工作应该每天在凌晨 1 点和 3 点运行两次。
  • */10 * * * * 表示该工作应该每 10 分钟运行一次。

所以我们为我们的工作注册一个 cron 任务?

是的,我们可以在我们的 crontab 文件中注册:

 * * * * php /home/divingLaravel/artisan send:offer

该命令将通知 CRON 守护程序每分钟运行 php artisan send:offer artisan 命令,是不是很容易? 但是,当我们想要在星期四和星期二或每个特定日子里每分钟运行命令时会感到困惑,记住 cron 作业的语法不是一件容易的事,而且还需要更新 crontab 文件,你想添加一个新的工作或更新的时间表可能是相当耗时的时间,所以几个版本发布后 Laravel 添加了一些有趣的功能,为调度任务提供了一个容易记住的语法:

$schedule->command('send:offer')
          ->everyFiveMinutes()
          ->wednesdays();

你只需要在你的 crontab 中注册一个 cron 工作,laravel 会处理剩下的事:

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

您可以在App\Console\Kernel类的 schedule 方法中定义预定的命令:

protected function schedule(Schedule $schedule)
{
    $schedule->command('send:offer')
          ->everyFiveMinutes()
          ->wednesdays();
}

如果您想了解有关不同计时器选项的更多信息,请查看 官方文档

当 Console Kernel 被实例化时,Laravel 向内核的booted事件注册一个侦听器,该事件将 Scheduler 绑定到容器并调用 kernel 的 schedule()方法:

// in Illuminate\Foundation\Console\Kernel

public function __construct(Application $app, Dispatcher $events)
{
    $this->app->booted(function () {
        $this->defineConsoleSchedule();
    });
}

protected function defineConsoleSchedule()
{
     // Register the Scheduler in the Container
    $this->app->instance(
        Schedule::class, $schedule = new Schedule($this->app[Cache::class])
    );

     // Call the schedule() method that we override in our App\Console\Kernel
    $this->schedule($schedule);
}

一旦 console kernel 完成 Kernel 类中定义的引导顺序,这个booted事件就被触发。

在 Kernel 的 handle()方法中,Laravel 会检查Foundation\Application是否已启动,如果不是调用应用程序的 bootstrapWith()方法,并传递在 console Kernel 定义的引导程序数组。

简单地说:

当 CRON 守护程序每分钟都调用php artisan schedule:run命令时,控制台 Console Kernel 将被启动,您在App\Console\Kernel::schedule()方法中定义的作业将被注册到调度程序。

schedule()方法调用Illuminate\Console\Scheduling\Schedule的实例作为唯一的参数,这是用于记录您提供的作业的计划任务管理器,并决定每次 CRON 守护进程应该运行什么。

转载请注明:  转载自Ryan 是菜鸟 | LNMP 技术栈笔记

如果觉得本篇文章对您十分有益,何不 打赏一下

谢谢打赏

本文链接地址: 剖析 Laravel 计划任务–初探

知识共享许可协议 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可