在您的应用程序源代码中安排 artisan 命令

v1.5.0 2023-07-28 17:43 UTC

README

Dispatcher 允许您在 Laravel 项目中安排 artisan 命令,从而消除在部署时触摸 crontab 的需求。它还允许按环境运行命令,并将您的调度逻辑保持在版本控制中。

use Indatus\Dispatcher\Scheduling\ScheduledCommand;
use Indatus\Dispatcher\Scheduling\Schedulable;
use Indatus\Dispatcher\Drivers\DateTime\Scheduler;

class MyCommand extends ScheduledCommand {
	public function schedule(Schedulable $scheduler)
	{
        //every day at 4:17am
        return $scheduler
            ->daily()
            ->hours(4)
            ->minutes(17);
    }
}

Latest Stable Version Total Downloads Build Status Code Coverage Scrutinizer Code Quality

README 内容

## 特性
  • 自动运行计划 artisan 命令
  • 调度维护在您的版本控制系统内
  • 命令何时何地运行的单一事实来源
  • 使用参数和选项计划命令运行
  • 以其他用户身份运行命令
  • 在特定环境中运行命令
  • 使用自定义驱动程序进行自定义调度上下文
## 教程

由 Ben Kuhl 在 Laravel Louisville 线上会议@lurvul)发表: 视频 - 幻灯片

由 Jefferey Way 在 Laracasts使用 Laravel 的方式安排重复任务

## 安装

注意:Laravel 5 现在默认包含调度功能。 此包不再为 Laravel 5 及以上版本进行维护

如果您正在使用 Laravel 4,请参阅 1.4 分支中的说明

将此行添加到您的 config/app.php 文件中的 providers 数组

        'Indatus\Dispatcher\ServiceProvider',

将以下内容添加到您的根 Crontab 中(通过 sudo crontab -e

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

如果您要将此添加到 /etc/cron.d,您需要在 * * * * * 之后立即指定一个用户。

您可以将此添加到任何用户的 Crontab,但只有 root crontab 可以以其他用户身份运行命令。

### 从 1.4 升级到 2.0

在所有计划命令中...

  • use Indatus\Dispatcher\Drivers\Cron\Scheduler 替换为 use Indatus\Dispatcher\Drivers\DateTime\Scheduler
  • Scheduler::[DAY_OF_WEEK] 的使用替换为 Day::[DAY_OF_WEEK],将 Scheduler::[MONTH_OF_YEAR] 的使用替换为 Month::[MONTH_OF_YEAR]
  • 已移除 executable 配置选项。现在,Dispatcher 继承了最初用于运行 scheduled:run 的二进制文件的 路径
## 使用方法
scheduled:scheduled:make 创建一个新的计划 artisan 命令 scheduled:run 运行计划命令 scheduled:summary 查看所有计划 artisan 命令的摘要 

如果命令通过 php artisan 不可见,则不能进行计划。

### 生成新的计划命令

使用 php artisan scheduled:make 生成一个新的计划命令,就像使用 artisan 的 command:make 一样。然后 在 Laravel 中注册您的命令

### 计划现有命令

您可以通过实现 \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface 或遵循以下步骤。

  1. 在您的命令中添加 use 语句。如果您使用的是自定义驱动程序,则将使用不同的 Scheduler 类。
use Indatus\Dispatcher\Scheduling\ScheduledCommand;
use Indatus\Dispatcher\Scheduling\Schedulable;
use Indatus\Dispatcher\Drivers\DateTime\Scheduler;
  1. 扩展 \Indatus\Dispatcher\Scheduling\ScheduledCommand
  2. 实现 schedule()
	/**
	 * When a command should run
	 *
	 * @param Scheduler $scheduler
	 *
	 * @return Scheduler
	 */
	public function schedule(Schedulable $scheduler)
	{
		return $scheduler;
    }

有关如何计划的详细信息及示例,请参阅 DateTime 驱动程序

### 以用户身份运行命令

您可以通过覆盖 user() 函数来以特定用户身份运行特定的 artisan 命令。请确保您的 scheduled:run artisan 命令是以 root 用户运行的。

 public function user() { return 'backup'; }

注意:此功能可能不被所有驱动程序支持。

### 环境特定命令

您可以通过覆盖 environment() 函数来确保您的命令仅在特定环境中进行调度。它应该提供单个环境或一组环境。

 public function environment() { return ['development','staging']; }
### 维护模式

默认情况下,当应用程序处于维护模式时,cron 命令不会运行。这可以防止在迁移数据库或进行 composer 更新时运行 cron 命令可能产生的各种奇怪输出。

您可以通过覆盖 runInMaintenanceMode() 函数来强制在应用程序处于维护模式时仍然运行您的命令。

 public function runInMaintenanceMode() { return true; }
### 高级调度

您可以通过 schedule() 返回多个 Schedulable 实例来安排一个命令在多个时间运行。

 public function schedule(Schedulable $scheduler) { return [ // 5am Mon-Fri $scheduler->everyWeekday()->hours(5), // 2am every Saturday App::make(get_class($scheduler)) ->daysOfTheWeek(Scheduler::SATURDAY) ->hours(2) ]; }

您还可以安排一个带有参数和选项的命令运行。

 public function schedule(Schedulable $scheduler) { return [ // 相当于:php /path/to/artisan command:name /path/to/file $scheduler->args(['/path/to/file']) ->everyWeekday() ->hours(5), // 相当于:php /path/to/artisan command:name /path/to/file --force --toDelete="expired" --exclude="admins" --exclude="developers" $scheduler->args(['/path/to/file']) ->opts([ 'force', 'toDelete' => 'expired', 'exclude' => [ 'admins', 'developers' ] ]) ->daysOfTheMonth([1, 15]) ->hours(2) ]; }

注意:无论先调用哪个,args()opts() 都会内部为您创建一个新的 Schedulable 实例,因此您不需要调用 App::make()

## 驱动程序

驱动程序提供了添加额外上下文到您的调度功能。创建自定义驱动程序是一个很好的方法来根据您应用程序的需求来定制这个上下文。

### 日期时间(默认)

如何安排的示例:

 public function schedule(Schedulable $scheduler) { //每天凌晨4:17 return $scheduler->daily()->hours(4)->minutes(17); }
 public function schedule(Schedulable $scheduler) { //每周二/周四凌晨5:03 return $scheduler->daysOfTheWeek([ Scheduler::TUESDAY, Scheduler::THURSDAY ])->hours(5)->minutes(3); }
 public function schedule(Schedulable $scheduler) { //每月第二个和第三个星期二的午夜12点 return $scheduler->monthly()->week([2, 3])->daysOfTheWeek(Day::TUESDAY); }
## 自定义驱动程序

自定义驱动程序允许您在安排中提供应用程序上下文。例如,一个基于教育的应用程序可能包含诸如 inServiceDays()springBreak()christmasBreak() 等安排方法,其中在这些时间段运行或不会运行命令。

创建一个包路径,如 \MyApp\ScheduleDriver\,然后创建两个类:

  • Scheduler 实现 Indatus\Dispatcher\Scheduling\Schedulable。此类应提供有用的接口,以便程序员可以安排他们的命令。
  • ScheduleService 继承自 \Indatus\Dispatcher\Services\ScheduleService。此类包含确定命令是否应运行的逻辑。

使用 php artisan config:publish indatus/dispatcher 发布配置。然后更新您的驱动程序配置以引用包含这两个类的包(不要包含尾部斜杠):

 'driver' => '\MyApp\ScheduleDriver' 
## 常见问题解答

我需要将部署到表示单个环境的多台服务器。我如何确保我的命令只由一台服务器运行,而不是每台服务器都运行?

scheduled:run 安排每分钟运行 rcron

* * * * * /usr/bin/rcron php /path/to/artisan scheduled:run 1>> /dev/null 2>&1

为什么我已正确安排了命令,但它们没有运行?我也没有看到任何错误输出

  1. 通过命令 php -i | mcrypt 验证是否已正确安装并运行 mcrypt。

  2. 使用 php artisan scheduled:run --debug 将告诉你为什么它们没有运行。如果您在这里没有看到您的命令,那么它可能设置不正确。

示例

$ php artisan scheduled:run --debug                                                                                        
Running commands...
     backup:avatars: No schedules were due
     command:name: No schedules were due
     myTestCommand:name: No schedules were due
     cache:clean: /usr/bin/env php /Users/myUser/myApp/artisan cache:clean > /dev/null &
     mail:subscribers: /usr/bin/env php /Users/myUser/myApp/artisan mail:subscribers > /dev/null &

我有扩展 ScheduledCommand 的命令,但为什么它们在运行 scheduled:summary 时没有出现?

禁用的命令将不会显示在这里。请确保 isEnabled() 在这些命令上返回 true。