mertyildiran / dispatcher
在应用程序的源代码中安排 artisan 命令
Requires
- php: >=5.3.2
- mtdowling/cron-expression: ~1.0.3
- wp-cli/php-cli-tools: v0.9.4-patch46
Requires (Dev)
- mockery/mockery: ~0.9
- orchestra/testbench: ~2.1.1
- phpunit/phpunit: ~4.0
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); } }
README 内容
## 功能- 自动运行计划 artisan 命令
- 调度维护在您的版本控制系统内
- 关于何时何地运行命令的单一事实来源
- 使用参数和选项计划命令运行
- 以其他用户身份运行命令
- 在特定环境中运行命令
- 使用自定义驱动程序进行自定义调度上下文
由 Ben Kuhl 在 Laravel LouisvilleMeetup(@lurvul)提供:视频 - 幻灯片
由 Jefferey Way 在 Laracasts 提供:以 Laravel 方式执行重复任务
## 安装注意:Laravel 5 现在默认包含调度。此包将不再维护 Laravel 5 及以上版本
如果您使用的是 Laravel 4,请查看 1.4 分支中的 readme
将此行添加到您的 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
,则在 * * * * *
之后需要立即指定用户。
### 从 1.4 升级到 2.0您可以将其添加到任何用户的 Crontab,但只有 root crontab 可以以其他用户身份运行命令。
在所有计划命令中...
- 将
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:scheduled:run 运行定时命令 scheduled:scheduled:summary 查看所有定时 artisan 命令的摘要
如果命令无法通过 php artisan
查看,则无法进行定时。
使用 php artisan scheduled:make
生成一个新的定时命令,就像你使用 artisan 的 command:make
一样。然后 在 Laravel 中注册你的命令。
你可以实现 \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface
或遵循以下步骤。
- 在你的命令中添加 use 语句。如果你使用的是自定义驱动,你将使用不同的
Scheduler
类。
use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Drivers\DateTime\Scheduler;
- 扩展
\Indatus\Dispatcher\Scheduling\ScheduledCommand
- 实现 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 [ // 周一至周五的凌晨5点 $scheduler->everyWeekday()->hours(5), // 每周六凌晨2点 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) { //每月第二个和第三个星期二午夜 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
为什么我正确安排了命令,但它们没有运行?我也没有看到任何错误输出
-
通过命令
php -i | mcrypt
验证 mcrypt 是否已安装并正常工作。 -
使用
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。