【Laravel】タスクスケジュール(Cron)の実装

はじめに

レンタルサーバ上でWebアプリを運用していると、定期的にタスク(プログラム)を実行したい時があります。レンタルサーバ上でこれを実現する方法として「Cron」というものがあり、たいていサーバの管理画面から設定することができます。

今回は、Laravelにもタスクスケジュールという機能があると知り実装してみる事にしました。

Laravelのタスクスケジュール機能は単体で機能するものではなく、「Cron」の利用を前提とした機能のようです。ただ、複数の定期タスクを実装したい時に、通常なら複数のCron設定をしなければいけないところですが、Laravelのタスクスケジュールを使えば、Cron設定は1つで済むとの事です。

環境

Laravel バージョン7.x

流れ

オリジナルのコマンドを作成してそれを定期的に実行する仕組みを作る。コマンドというのは、例えば「php artisan migrate」とかです。「migrate」の部分を好きな文字列で作ることができます。

手順

・オリジナルのコマンドを作成する
・「Kernel.php」に定期タスクを登録する
・サーバにCron設定をする

オリジナルコマンドの作成

まずオリジナルのコマンドを作りましょう。

コマンドクラスの作成

以下のコマンドでオリジナルコマンド用クラスを新規作成します。

php artisan make:command DeleteLog

「DeleteLog」の部分は任意の名前でOKです。そのままファイル名になるので頭文字を大文字にしましょう。

実行すると「app/Console/Commands/DeleteLog.php」というファイルができるので3箇所を修正します。

1箇所目(コマンド名設定)

protected $signature = 'command:name';

デフォルトで「command:name」となっていますが、それがそのままコマンドになります。例えば「delete:log」とかにすると、「php artisan delete:log」で実行できるようになります。「:」はグループ分けする場合に使用します。使わなくてもOKです。

2箇所目(コマンドの説明)

protected $description = 'Command description';

ここはあまり重要ではないです。どういうコマンドかわかりやすいような説明を書きます。例えば、

protected $description = 'ログの削除';

3箇所目(実際のタスク)

public function handle()
{
    return 0;
}

「return 0;」の部分を書き換えて実際に実行したいタスクを書き込みます。

コマンドの動作確認

php artisan delete:log

3箇所目で書いたタスクが実行されていれば成功です。

Kernel.phpにタスク登録する

ここで定期タスクの設定をします。

「app/Console/Kernel.php」の2箇所を編集します。

まず1箇所目(コマンドの登録)

protected $commands = [
    //
];

中身が空なので、以下のように追記します。

protected $commands = [
    // コマンドの登録
    \App\Console\Commands\DeleteLog::class,
];

「DeleteLog::class」の「DeleteLog」部分は先程作成したコマンドクラス名です。

2箇所目(スケジュール設定)

protected function schedule(Schedule $schedule)
{
	// $schedule->command('inspire')
	//          ->hourly();
}

記入例が入っているので、今回は以下のように書き換えます。

protected function schedule(Schedule $schedule)
{
    // スケジュールの登録
    $schedule->command('delete:log')->everyMinute();
}

「delete:log」の部分に定期的に実行したいコマンド(先程定義したコマンド)を入れます。
「hourly()」や「everyMinute()」は実行間隔です。

->cron(‘* * * * *’); Cron指定に基づきタスク実行
->everyMinute(); 毎分タスク実行
->hourly(); 毎時タスク実行
->daily(); 毎日深夜12時に実行
->dailyAt(’13:00′); 毎日13:00に実行
->weekly(); 毎週日曜日の00:00にタスク実行
->monthly(); 毎月1日の00:00にタスク実行
->yearly(); 毎年1月1日の00:00にタスク実行

他にも細かな指定ができます。詳しくは公式ページで。
https://readouble.com/laravel/7.x/ja/scheduling.html

Cron設定

オリジナルのコマンドを作成して、それが定期的に実行される仕組みができたので、あとはサーバにタスク実行のトリガーとなるCronの設定をするだけです。

設定方法として「crontab」を使って設定する方法が一般的のようですが、今回は自分が愛用しているレンタルサーバ「エックスサーバ」への設定方法が特殊だったので、書いておきたいと思います。

エックスサーバの場合はコントロールパネル内の指定の箇所にコマンドを登録しますが、通常のコマンドでは動かないらしく、以下のような書き方をする必要があるようです。

cd $HOME/[ドメイン名]/[プロジェクトまでのパス] && /usr/bin/php7.4 artisan schedule:run >> /dev/null 2>&1

「cd」でディレクトリ移動して、「php artisan」のところで使用しているPHPのパスを入れる必要があるようです。(バージョンはそれぞれの環境のものを入れて下さい)

「/dev/null 2>&1」はエラーが起きてもログを残さず終了させるという意味です。

別の書き方

/usr/bin/php7.4 /home/[アカウント名]/[ドメイン名]/[プロジェクトまでのパス] artisan schedule:run >> /dev/null 2>&1

まとめ

以上で定期タスクが設定できたと思います。

サーバ側のCronの周期を毎分にしてLaravel側で任意の周期を設定するのが一般的のようですが、タスクが1つならサーバに負担をかけない意味でも、Cron側で周期を設定して、Laravel側では「->cron(‘* * * * *’);」を使ってCronに基づき実行するようにした方が良いかもしれませんね。