• 入門
  • スケジュールの定義
    • スケジューリング 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メソッドを使用することができます。 しかし、タスクに割り当てることができるタスクスケジュールの頻度はもっとたくさんあります。

    にタスクを実行する。

    毎日15時にタスクを実行。00

    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} この機能を利用するには、アプリケーションのデフォルトのキャッシュドライバとして、databasememcacheddynamodb、または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:workArtisan コマンドを使用することができます。 このコマンドはフォアグラウンドで実行され、コマンドを終了するまで、毎分スケジューラーを呼び出します:

    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}…. emailOutputToemailOutputOnFailuresendOutputToappendOutputToメソッドは、commandexecメソッドと排他的です。

    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

    pingBeforethenPing メソッドを使用すると、タスク実行の前または後に、スケジューラが自動的に指定した 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

    .