Laravelでタスクスケジュールを使用するときは、cronの指定が必要

こんにちは。 エキサイト株式会社の三浦です。

PHPの有名なフレームワークであるLaravelには、「タスクスケジュールの実行」、いわゆる「バッチの実行」処理が組み込まれています。

アプリケーションコード内でタスク実行のスケジュールを書けるなど非常に便利なのですが、実は一つ落とし穴があります。

今回は、実際に私が引っかかったその落とし穴の話をしていきます。

タスクスケジュールの設定

Laravelには、タスクスケジュールという機能があります。

readouble.com

Laravelのコマンドスケジューラは、サーバ上でスケジュールするタスクを管理するための新しいアプローチを提供しています。スケジューラを使用すると、Laravelアプリケーション自体の中でコマンドスケジュールを流暢かつ表現力豊かに定義できます。

以下のように記述することで、アプリケーションコード内でタスクのスケジュールをすることができます。

<?php

declare(strict_types=1);

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * Define the application's command schedule.
     */
    protected function schedule(Schedule $schedule): void
    {
        $schedule
            ->command('batch:sample') // あらかじめ batch:sample というコマンドを登録しておく
            ->everyMinute();
    }

    /**
     * Register the commands for the application.
     */
    protected function commands(): void
    {
        $this->load(__DIR__ . '/Commands');

        require base_path('routes/console.php');
    }
}

この、

$schedule
    ->command('batch:sample')
    ->everyMinute();

という記述で、「毎分 batch:sample を実行する」という表現ができました!

あとはLaravelを実行すれば終わり…と思いきや、実はこれだけだとこのバッチは動きません。

タスクスケジュールの実行にはcronの設定が必要

よく見てみると、タスクスケジュールのドキュメントには以下のように書いてあります。

readouble.com

スケジューラを使用する場合、サーバに必要なcronエントリは1つだけです。

実は、「タスクスケジュールを使用する = cronは不要」 ではありません

タスクスケジュールを使用すると、今まではタスクごとに必要だったcronを1つにまとめられるだけで、cron自体は必要なのです。

以下のcronを設定する必要があります。

スケジューラの実行

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

流れとしては、

  1. cronが毎分Laravelを実行
  2. Laravel側で、タスクスケジュールに設定されたコマンドのうち実行タイミングに該当するものを実行

という流れになります。

最後に

これを読み飛ばしてしまい、私はバッチを実行させるのにかなり苦労してしまいました。

フレームワークによっては実際にcronが全く不要なものもある(JavaのSpring Bootなど)ので、そういったものに慣れている人ほど引っかかりやすいかもしれません。

言語やフレームワークの特性によって要不要が変わってくるので、注意していきましょう。