- 入門
- スケジュールの定義
- スケジューリング Artisan コマンド
- キュー内のジョブのスケジュール
- スケジュール Shell コマンド
- スケジュール頻度オプション
- タイムゾーン
- 重複タスク防止
1 つのサーバーでタスクを実行する
- バックグラウンドタスク
- メンテナンスモード
スケジューラを実行する
- スケジューラをローカルで実行する
導入
過去には、次のようにしました。 サーバでスケジュールする必要のある各タスクについて、cron設定エントリを書いていたかもしれません。 しかし、タスクのスケジュールはもはやソース管理されておらず、既存の cron エントリを表示したりエントリを追加したりするためにサーバーに SSH 接続しなければならないため、これはすぐに苦痛となります。 スケジューラーを使用すると、Laravel アプリケーション自体でコマンド スケジュールを流暢かつ表現的に定義することができます。 スケジューラーを使用する場合、サーバー上に必要なのは、1つのcronエントリーだけです。 タスクのスケジュールは、app/Console/Kernel.php
ファイルのschedule
メソッドで定義されます。 2815>
スケジュールの定義
アプリケーションのApp\Console\Kernel
クラスのschedule
メソッドで、スケジュールされたすべてのタスクを定義することができます。 手始めに、例を見てみましょう。 この例では、毎日真夜中に呼び出されるクロージャをスケジュールします。 クロージャの中では、テーブルをクリアするためにデータベースクエリを実行します。 Invokable オブジェクトとは、__invoke
メソッドを含むシンプルな PHP クラスです。
$schedule->call(new DeleteRecentUsers)->daily();
スケジュールされたタスクの概要と次に実行される時間を表示したい場合は、schedule:list
Artisan コマンドを使用できます。 たとえば、コマンド名またはクラスを使用して Artisan コマンドをスケジュールするには、command
メソッドを使用します。
コマンドのクラス名を使用して Artisan コマンドをスケジュールする場合、コマンドが呼び出されたときに提供されるべき追加のコマンド ライン引数の配列を渡すことができます:
use App\Console\Commands\SendEmailsCommand;$schedule->command('emails:send Taylor --force')->daily();$schedule->command(SendEmailsCommand::class, )->daily();
Scheduling Queued Jobs
job
メソッドを使用してキュー内のジョブをスケジュールすることができます。 このメソッドは、ジョブをキューに入れるためにクロージャを定義する call
メソッドを使用せずに、キューに入れられたジョブをスケジュールする便利な方法を提供します:
use App\Jobs\Heartbeat;$schedule->job(new Heartbeat)->everyFiveMinutes();
job
メソッドにはオプションで第 2 および第 3 引数を指定でき、ジョブをキューイングするために使用すべきキュー名とキュー接続が指定されます。
use App\Jobs\Heartbeat;// Dispatch the job to the "heartbeats" queue on the "sqs" connection...$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
シェルコマンドのスケジューリング
オペレーティングシステムにコマンドを発行するには、exec
メソッドを使用することができます。 しかし、タスクに割り当てることができるタスクスケジュールの頻度はもっとたくさんあります。
Method | Description | |
---|---|---|
->cron('* * * * *'); |
カスタム cron スケジュール | |
->everyMinute(); |
1分ごとにタスクを実行 | |
->everyTwoMinutes(); |
2分ごとにタスクを実行 | |
->everyThreeMinutes(); |
3分ごとにタスクを実行 | |
->everyFourMinutes(); |
4分ごとにタスクを実行 | |
->everyFiveMinutes(); |
タスクを実行する。 5分ごと | |
->everyTenMinutes(); |
10分ごとにタスクを実行 | |
->everyFifteenMinutes(); |
15分ごとにタスクを実行 | |
->everyThirtyMinutes(); |
30分ごとにタスクを実行 | |
->hourly(); |
1時間ごとにタスクを実行 | |
->hourlyAt(17); |
毎時17分にタスクを実行 | |
->everyTwoHours(); |
毎時2分にタスクを実行 | |
->everyThreeHours(); |
3時間ごとにタスクを実行 | |
->everyFourHours(); |
4時間ごとにタスクを実行 | |
->everySixHours(); |
タスクを実行する。 6時間ごと | |
->daily(); |
毎日午前0時にタスクを実行 | |
->dailyAt('13:00'); |
毎日13時にタスクを実行 | 毎日15時にタスクを実行 |
->daily(); |
||
->twiceDaily(1, 13); |
毎日1時にタスクを実行 & 13:00 | |
->weekly(); |
毎週日曜日00にタスクを実行。00 | |
->weeklyOn(1, '8:00'); |
毎週月曜日8:00にタスクを実行 | |
->monthly(); |
毎月1日00にタスクを実行します。00 | |
->monthlyOn(4, '15:00'); |
毎月4日の15時にタスクを実行 | |
->twiceMonthly(1, 16, '13:00'); |
毎月1日と16日に13時にタスクを実行。00 | |
->lastDayOfMonth('15:00'); |
毎月最終日の15日にタスクを実行する。00 | |
->quarterly(); |
四半期ごとの最初の日にタスクを00に実行。00 | |
->yearly(); |
タスクを毎年最初の日に 00:00 | |
->yearlyOn(6, 1, '17:00'); |
タスクを毎年 6 月 1 日の 17:00 に実行する。00 | |
->timezone('America/New_York'); |
タスクのタイムゾーンを設定する |
これらの方法は、特定の曜日のみに実行するさらに細かいスケジュールを作成するための追加の制約と組み合わせることができます。 たとえば、あるコマンドを毎週月曜日に実行するようにスケジュールすることができます:
// Run once per week on Monday at 1 PM...$schedule->call(function () { //})->weekly()->mondays()->at('13:00');// Run hourly from 8 AM to 5 PM on weekdays...$schedule->command('foo') ->weekdays() ->hourly() ->timezone('America/Chicago') ->between('8:00', '17:00');
その他のスケジュール制約のリストは、以下を参照してください。
メソッド | 説明 |
---|---|
->weekdays(); |
タスクを平日に限定する |
->weekends(); |
タスクを週末に限定する |
->sundays(); |
タスクを日曜日に限定する |
->mondays(); |
タスクを月曜日 |
->tuesdays(); |
タスクを火曜日 |
->wednesdays(); |
タスクを火曜日 |
->thursdays(); |
木曜日 |
->fridays(); |
金曜日 |
->saturdays(); |
タスクを土曜日に限定する |
->days(array|mixed); |
タスクを特定の日に限定する |
->between($startTime, $endTime); |
開始時刻と終了時刻の間でタスクを実行するように制限する |
->unlessBetween($startTime, $endTime); |
開始時刻と終了時刻の間でタスクを実行しないように制限する。 終了時間 |
->when(Closure); |
真偽判定に基づいてタスクを制限する |
->environments($env); |
特定のタスクに制限する 環境 |
Day Constraints
days
メソッドを使用すると、タスクの実行を特定の曜日に制限することができます。 たとえば、日曜日と水曜日に 1 時間ごとにコマンドが実行されるようにスケジュールできます。
$schedule->command('emails:send') ->hourly() ->days();
あるいは、タスクが実行される日を定義するときに、Illuminate\Console\Scheduling\Schedule
クラスで使用できる定数を使用できます。
$schedule->command('emails:send') ->hourly() ->between('7:00', '22:00');
同様に、unlessBetween
メソッドは、ある期間のタスクの実行を除外するために使用することができる:
$schedule->command('emails:send') ->hourly() ->unlessBetween('23:00', '4:00');
Truth Test Constraints
when
メソッドは、与えられた真実テストの結果に基づいてタスクの実行を制限するために使用されることがある。 言い換えれば、与えられたクロージャが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
を返した場合にのみ、スケジュールされたコマンドが実行されます。
環境制約
environments
メソッドは、与えられた環境 (APP_ENV
環境変数で定義) 上でのみタスクを実行するために使用されるかもしれません。
$schedule->command('emails:send') ->daily() ->environments();
Timezones
timezone
メソッドを使用すると、スケジュールされたタスクの時間が指定されたタイムゾーンの中で解釈されるように指定できます:
$schedule->command('report:generate') ->timezone('America/New_York') ->at('2:00')
もし、スケジュールしたタスクに繰り返し同じタイムゾーンを指定しているなら、App\Console\Kernel
クラスに scheduleTimezone
メソッドを定義するとよいでしょう。 このメソッドは、すべてのスケジュールされたタスクに割り当てられるデフォルトのタイムゾーンを返す必要があります:
/** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */protected function scheduleTimezone(){ return 'America/Chicago';}
{note}. タイムゾーンによっては、サマータイムを利用するものがあることに留意してください。 サマータイムが変更されると、スケジュールされたタスクが2回実行されたり、まったく実行されなかったりすることがあります。 このため、可能な限りタイムゾーン スケジューリングを避けることをお勧めします。
タスク オーバーラップの防止
デフォルトでは、タスクの前のインスタンスがまだ実行中であっても、スケジュール タスクが実行されます。 これを防ぐには、withoutOverlapping
メソッドを使用します:
$schedule->command('emails:send')->withoutOverlapping();
この例では、emails:send
Artisanコマンドがまだ実行中でなければ、1分ごとに実行されます。 withoutOverlapping
メソッドは、実行時間が大幅に異なるタスクがあり、特定のタスクにかかる時間を正確に予測できない場合に特に便利です。
必要に応じて、「重複しない」ロックが切れるまでに何分経過しなければならないかを指定することができます。 デフォルトでは、ロックは 24 時間後に失効します。
$schedule->command('emails:send')->withoutOverlapping(10);
Running Tasks On One Server
{note} この機能を利用するには、アプリケーションのデフォルトのキャッシュドライバとして、
database
、memcached
、dynamodb
、またはredis
キャッシュドライバを使用する必要があります。 さらに、すべてのサーバーが同じセントラル キャッシュ サーバーと通信している必要があります。
アプリケーションのスケジューラーが複数のサーバーで実行されている場合、スケジュールされたジョブが 1 つのサーバーでのみ実行されるように制限することが可能です。 たとえば、毎週金曜日の夜に新しいレポートを生成するスケジュールされたタスクがあるとします。 タスク・スケジューラが3台のワーカー・サーバーで実行されている場合、スケジュール・タスクは3台のサーバーすべてで実行され、3回レポートを生成することになります。 よくないことです!
タスクが1つのサーバーだけで実行されるべきことを示すには、スケジュールされたタスクを定義するときにonOneServer
メソッドを使用します。 タスクを最初に取得したサーバーは、他のサーバーが同じタスクを同時に実行できないように、ジョブに対するアトミック ロックを確保します。
$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();
バックグラウンド タスク
デフォルトでは、同時にスケジュールされた複数のタスクは、schedule
メソッドで定義した順序に基づいて順番に実行されます。 長時間実行されるタスクがある場合、これによって後続のタスクが予想よりかなり遅れて開始されることがあります。 バックグラウンドでタスクを実行し、同時に実行させたい場合は、runInBackground
メソッドを使用します。 runInBackground
メソッドは、command
および exec
メソッドでタスクをスケジュールする場合にのみ使用できます。
メンテナンスモード
アプリケーションがメンテナンスモードの場合、アプリケーションのスケジュールタスクは実行されません。 しかし、メンテナンス モードでもタスクを実行させたい場合は、タスクの定義時に evenInMaintenanceMode
メソッドを呼び出すことができます:
$schedule->command('emails:send')->evenInMaintenanceMode();
Running The Scheduler
さて、スケジュール タスクを定義する方法を学んだので、それらをサーバーで実際に実行する方法を説明しましょう。 schedule:run
Artisanコマンドは、すべてのスケジュールされたタスクを評価し、サーバーの現在の時間に基づいて実行する必要があるかどうかを判断します。
したがって、Laravelのスケジューラーを使用する場合、1分ごとにschedule:run
コマンドを実行するcron構成項目をサーバーに追加するだけでよいのです。 サーバーにcronエントリーを追加する方法がわからない場合は、cronエントリーを管理してくれるLaravel Forgeなどのサービスの使用を検討してください。
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Running The Scheduler Locally
一般的に、ローカル開発マシンにスケジューラーcronエントリーを追加することはないでしょう。 その代わりに、schedule:work
Artisan コマンドを使用することができます。 このコマンドはフォアグラウンドで実行され、コマンドを終了するまで、毎分スケジューラーを呼び出します:
php artisan schedule:work
Task Output
Laravel スケジューラーには、スケジュールしたタスクが生成する出力を扱うための便利なメソッドがいくつか用意されています。 まず、sendOutputTo
メソッドを使用して、出力をファイルに送信し、後で確認することができます:
$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);
出力を所定のファイルに追加したい場合は、appendOutputTo
メソッドを使用します:
$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
emailOutputTo
メソッドを使用すると、出力を任意の電子メールアドレスにメール送信することができます。 タスクの出力を電子メールで送信する前に、Laravelのメールサービスを設定する必要があります:
$schedule->command('report:generate') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('');
スケジュールされたArtisanまたはシステムコマンドがゼロ以外の終了コードで終了した場合にのみ出力を電子メールで送信したい場合は、emailOutputOnFailure
メソッドを使用します:
$schedule->command('report:generate') ->daily() ->emailOutputOnFailure('');
{note}….
emailOutputTo
、emailOutputOnFailure
、sendOutputTo
、appendOutputTo
メソッドは、command
、exec
メソッドと排他的です。
Task Hooks
before
および after
メソッドを使用すると、スケジュールされたタスクの実行前後に実行するコードを指定できます。
$schedule->command('emails:send') ->daily() ->before(function () { // The task is about to execute... }) ->after(function () { // The task has executed... });
onSuccess
および onFailure
メソッドでは、スケジュールされたタスクが成功または失敗する場合に実行するコードを指定します。 失敗した場合は、スケジュールされた Artisan またはシステムコマンドがゼロ以外の終了コードで終了したことを示します。
use Illuminate\Support\Stringable;$schedule->command('emails:send') ->daily() ->onSuccess(function (Stringable $output) { // The task succeeded... }) ->onFailure(function (Stringable $output) { // The task failed... });
Pinging URL
pingBefore
と thenPing
メソッドを使用すると、タスク実行の前または後に、スケジューラが自動的に指定した URL に Ping を送信することができます。 このメソッドは、Envoyer などの外部サービスにスケジュールされたタスクの実行開始または終了を通知するのに便利です。
$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);
pingBeforeIf
および thenPingIf
メソッドは、指定した条件が true
である場合にのみ、指定した URL に ping を送信します。
$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);
pingOnSuccess
および pingOnFailure
メソッドは、タスクが成功または失敗した場合にのみ指定した URL に ping を送信するのに使用される可能性があります。 失敗した場合は、スケジュールされた Artisan またはシステム コマンドがゼロ以外の終了コードで終了したことを示します:
$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);
すべての ping メソッドは Guzzle HTTP ライブラリを必要とします。 Guzzle は通常、すべての新しい Laravel プロジェクトにデフォルトでインストールされますが、誤って削除された場合は、Composer パッケージマネージャを使用してプロジェクトに手動でインストールすることができます:
composer require guzzlehttp/guzzle
.
コメントを残す