Documentation Index
Fetch the complete documentation index at: https://kawax.biz/llms.txt
Use this file to discover all available pages before exploring further.
タスクスケジューリングとは
従来、サーバーで定期実行が必要なタスクごとに cron エントリを手書きする必要がありました。
しかしこの方法ではスケジュール定義がソースコード外に存在するため、バージョン管理できず、確認・変更のたびに SSH ログインが必要になります。
Laravelのスケジューラを使うと、アプリケーション内でスケジュールを流暢に定義できます。
サーバーに登録する cron エントリは1行だけで済み、スケジュール定義はコードとともにバージョン管理されます。
スケジュールは routes/console.php に定義するのが標準的なスタイルです。
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
DB::table('recent_users')->delete();
})->daily();
schedule:list Artisanコマンドで、定義済みのタスク一覧と次回実行予定時刻を確認できます。php artisan schedule:list
スケジューラーの実行フロー
スケジュールの定義方法
スケジュールの定義は routes/console.php に記述します。
bootstrap/app.php の withSchedule メソッドを使って定義する方法もあります。
// bootstrap/app.php
use Illuminate\Console\Scheduling\Schedule;
->withSchedule(function (Schedule $schedule) {
$schedule->call(new DeleteRecentUsers)->daily();
})
スケジュール可能なタスクの種類
Artisanコマンドのスケジュール
command メソッドでArtisanコマンドをスケジュールします。
コマンド名またはクラス名で指定できます。
use App\Console\Commands\SendEmailsCommand;
use Illuminate\Support\Facades\Schedule;
// コマンド名で指定
Schedule::command('emails:send Taylor --force')->daily();
// クラス名で指定(引数を配列で渡せる)
Schedule::command(SendEmailsCommand::class, ['Taylor', '--force'])->daily();
クロージャで定義したArtisanコマンドにも、定義の直後にスケジュールメソッドをチェーンできます。
Artisan::command('delete:recent-users', function () {
DB::table('recent_users')->delete();
})->purpose('Delete recent users')->daily();
キュージョブのスケジュール
job メソッドでキュージョブをスケジュールします。
クロージャを使わずにジョブをキューに積む便利な方法です。
use App\Jobs\Heartbeat;
use Illuminate\Support\Facades\Schedule;
Schedule::job(new Heartbeat)->everyFiveMinutes();
キュー名や接続先を指定することもできます。
// "heartbeats" キュー、"sqs" 接続でディスパッチ
Schedule::job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
シェルコマンドのスケジュール
exec メソッドでOSコマンドを実行します。
use Illuminate\Support\Facades\Schedule;
Schedule::exec('node /home/forge/script.js')->daily();
クロージャのスケジュール
call メソッドで任意のPHPクロージャをスケジュールします。
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
DB::table('recent_users')->delete();
})->daily();
__invoke メソッドを持つ Invocable オブジェクトも渡せます。
Schedule::call(new DeleteRecentUsers)->daily();
スケジュール頻度の設定
主な頻度メソッド
よく使う頻度メソッドを以下に示します。
| メソッド | 説明 |
|---|
->everySecond() | 毎秒実行 |
->everyMinute() | 毎分実行 |
->everyFiveMinutes() | 5分ごとに実行 |
->everyFifteenMinutes() | 15分ごとに実行 |
->everyThirtyMinutes() | 30分ごとに実行 |
->hourly() | 毎時実行 |
->hourlyAt(17) | 毎時17分に実行 |
->daily() | 毎日0時に実行 |
->dailyAt('13:00') | 毎日13時に実行 |
->twiceDaily(1, 13) | 毎日1時と13時に実行 |
->weekly() | 毎週日曜0時に実行 |
->weeklyOn(1, '8:00') | 毎週月曜8時に実行 |
->monthly() | 毎月1日0時に実行 |
->monthlyOn(4, '15:00') | 毎月4日15時に実行 |
->quarterly() | 四半期ごとの初日0時に実行 |
->yearly() | 毎年1月1日0時に実行 |
->timezone('Asia/Tokyo') | タイムゾーンを指定 |
cron式で直接指定
cron メソッドで cron 式を直接指定することもできます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')->cron('0 9 * * *'); // 毎日9時に実行
頻度と曜日の組み合わせ
頻度メソッドと曜日の制約を組み合わせて、より細かいスケジュールを作れます。
use Illuminate\Support\Facades\Schedule;
// 毎週月曜13時に実行
Schedule::call(function () {
// ...
})->weekly()->mondays()->at('13:00');
// 平日の8時から17時まで毎時実行
Schedule::command('foo')
->weekdays()
->hourly()
->timezone('Asia/Tokyo')
->between('8:00', '17:00');
タイムゾーンの設定
timezone メソッドで個別タスクのタイムゾーンを指定できます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('report:generate')
->timezone('Asia/Tokyo')
->at('9:00');
すべてのタスクに共通のタイムゾーンを設定したい場合は、config/app.php の schedule_timezone を使います。
// config/app.php
'schedule_timezone' => 'Asia/Tokyo',
夏時間(サマータイム)が適用されるタイムゾーンを使う場合、切り替えのタイミングでタスクが2回実行されるか、まったく実行されないことがあります。
可能な限り UTC を使うことを推奨します。
条件制約
when / skip
when はクロージャが true を返した場合のみタスクを実行します。
skip はその逆で、true を返した場合にスキップします。
use Illuminate\Support\Facades\Schedule;
// 条件が true のときだけ実行
Schedule::command('emails:send')->daily()->when(function () {
return true;
});
// 条件が true のときはスキップ
Schedule::command('emails:send')->daily()->skip(function () {
return true;
});
environments
environments メソッドで特定の環境でのみ実行するよう制限できます。
Schedule::command('emails:send')
->daily()
->environments(['staging', 'production']);
時刻の制約
between / unlessBetween で実行時間帯を制限できます。
// 7時から22時の間だけ実行
Schedule::command('emails:send')
->hourly()
->between('7:00', '22:00');
// 23時から4時の間は実行しない
Schedule::command('emails:send')
->hourly()
->unlessBetween('23:00', '4:00');
曜日の制約
| メソッド | 説明 |
|---|
->weekdays() | 平日のみ |
->weekends() | 週末のみ |
->mondays() 〜 ->sundays() | 特定の曜日のみ |
->days([0, 3]) | 日曜(0)と水曜(3)など複数指定 |
use Illuminate\Support\Facades;
use Illuminate\Console\Scheduling\Schedule;
Facades\Schedule::command('emails:send')
->hourly()
->days([Schedule::SUNDAY, Schedule::WEDNESDAY]);
重複防止
デフォルトでは、前回のタスクがまだ実行中でも次の実行が開始されます。
withoutOverlapping を使うと、前の実行が終わるまで次の実行を待機させられます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')->withoutOverlapping();
ロックの有効期限(分)を指定することもできます。デフォルトは24時間です。
// 10分後にロックが失効する
Schedule::command('emails:send')->withoutOverlapping(10);
withoutOverlapping はアプリケーションのキャッシュを使ってロックを管理します。
タスクが予期せぬ問題でスタックした場合は schedule:clear-cache でロックを解除できます。php artisan schedule:clear-cache
複数サーバーでの実行制御
複数サーバーでスケジューラが動いている場合、onOneServer を使うことで1台のサーバーだけでタスクを実行できます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('report:generate')
->fridays()
->at('17:00')
->onOneServer();
この機能を使うには、アプリケーションのデフォルトキャッシュドライバを database、memcached、dynamodb、または redis に設定し、すべてのサーバーが同じキャッシュサーバーに接続している必要があります。
onOneServer() による分散実行制御フロー
タスクのグループ化
複数のタスクに同じ設定を適用する場合は group メソッドを使ってまとめられます。
use Illuminate\Support\Facades\Schedule;
Schedule::daily()
->onOneServer()
->timezone('Asia/Tokyo')
->group(function () {
Schedule::command('emails:send --force');
Schedule::command('emails:prune');
});
バックグラウンド実行
同じ時刻にスケジュールされたタスクは、デフォルトでは定義順に順番に実行されます。
長時間かかるタスクがあると後続のタスクの開始が遅れます。
runInBackground を使うと、タスクをバックグラウンドで並列実行できます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('analytics:report')
->daily()
->runInBackground();
runInBackground は command と exec メソッドでのみ使用できます。
メンテナンスモード
アプリケーションがメンテナンスモードのとき、スケジュールタスクは実行されません。
メンテナンスモード中でも強制的に実行させたい場合は evenInMaintenanceMode を使います。
Schedule::command('emails:send')->evenInMaintenanceMode();
メンテナンスモードの対応フロー
スケジューラの一時停止
コードを変更せずにスケジューラを一時停止できます。
# スケジューラを停止
php artisan schedule:pause
# スケジューラを再開
php artisan schedule:continue
停止中でも特定のタスクだけ実行し続けたい場合は evenWhenPaused を使います。
ヘルスチェックやシステム監視など、メンテナンス中でも継続が必要なタスクに役立ちます。
Schedule::command('emails:send')->evenWhenPaused();
出力のハンドリング
ファイルへの出力
sendOutputTo でタスクの出力をファイルに保存できます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')
->daily()
->sendOutputTo(storage_path('logs/emails-send.log'));
appendOutputTo を使うと、既存のファイルに追記します。
Schedule::command('emails:send')
->daily()
->appendOutputTo(storage_path('logs/emails-send.log'));
メールへの出力
emailOutputTo でタスクの出力をメールで送信できます。
事前にLaravelのメール設定が必要です。
Schedule::command('report:generate')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('[email protected]');
失敗時のみメールを送る場合は emailOutputOnFailure を使います。
Schedule::command('report:generate')
->daily()
->emailOutputOnFailure('[email protected]');
タスクフック
before / after メソッドで、タスクの実行前後に処理を挿入できます。
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')
->daily()
->before(function () {
// タスク実行前の処理
})
->after(function () {
// タスク実行後の処理
});
成功・失敗時のフックは onSuccess / onFailure で定義します。
use Illuminate\Support\Stringable;
Schedule::command('emails:send')
->daily()
->onSuccess(function (Stringable $output) {
// 成功時の処理
})
->onFailure(function (Stringable $output) {
// 失敗時の処理
});
サーバーへのデプロイ
cron エントリを追加する
サーバーの crontab に以下の1行を追加するだけで、Laravelのスケジューラが毎分実行されます。* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
crontab -e コマンドで編集できます。 スケジューラの動作を確認する
定義済みタスクの一覧と次回実行時刻を確認します。php artisan schedule:list
ローカル開発での実行
ローカル環境では cron を使わず、schedule:work コマンドでスケジューラを常時起動できます。
php artisan schedule:work
このコマンドはフォアグラウンドで動作し、毎分スケジューラを呼び出します。Ctrl+C で停止するまで動き続けます。
サブ分スケジュール(1分未満の頻度)
通常の cron は1分が最小単位ですが、Laravelでは1秒単位のスケジュールも設定できます。
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
DB::table('recent_users')->delete();
})->everySecond();
サブ分タスクが定義されている場合、schedule:run はその分が終わるまで動き続けて、すべてのサブ分タスクを処理します。
サブ分タスクはキュージョブやバックグラウンドコマンドに処理を委譲することを推奨します。
タスク自体が長時間かかると、後続のサブ分タスクの実行が遅れるためです。
デプロイ中に実行中の schedule:run を中断するには、デプロイスクリプトに以下を追加します。
php artisan schedule:interrupt
よく使うコマンドまとめ
# タスク一覧を表示
php artisan schedule:list
# スケジューラを手動実行(サーバーのcronが呼び出すコマンド)
php artisan schedule:run
# ローカル開発用 常時起動
php artisan schedule:work
# スケジューラを一時停止
php artisan schedule:pause
# スケジューラを再開
php artisan schedule:continue
# 重複防止ロックをクリア
php artisan schedule:clear-cache
# サブ分タスクの実行中断(デプロイ時)
php artisan schedule:interrupt