勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ

Laravel 13系をsystemd timerで自動実行する方法

  PHP Laravel

Laravelで特定の処理をsystemd timerで自動実行したい。また、systemd timerはCockpitから設定したい。以下に対応方法をメモ。

 

対応方法

Artisanコマンドの作成

サーバにSSH接続し以下でArtisanコマンドを作成する。

pa make:command TimerTestCommand

すると「/app/Console/Commands/TimerTestCommand.php」ファイルが生成されるのでこちらを以下のように編集してアップする。日時をログファイルに追記していくといった内容になる。

<?php
namespace App\Console\Commands;

use Illuminate\Console\Attributes\Description;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

#[Signature('app:timer-test')]
#[Description('タイマーのテスト')]
class TimerTestCommand extends Command
{

    public function handle()
    {
        $logMessage = '[timer test]' . now()->toDateTimeString();
        Storage::append('timer_test.log', $logMessage);

        # /storage/app/public/ に保存する場合
        Storage::disk('public')->append('timer_test.log', $logMessage);
    }
}

ちなみに以下コマンドで確認できる。

# 作成済みのapp内のコマンドリストを表示
pa list app

# 以下のように表示される
Available commands for the "app" namespace:
  app:timer-test  タイマーのテスト

タスクスケジューリング

「/routes/console.php」に以下を追記する。作成したコマンドを毎分実行し、タスクの重複は防ぐといった内容になる。

use Illuminate\Support\Facades\Schedule;
use Illuminate\Support\Facades\Storage;

Schedule::command('app:timer-test')->everyMinute()->withoutOverlapping();

タイマーの作成

Cockpitから以下の通り設定する。

  • 名前 -> 半角英数字と特定の半角記号「:」「_」「.」「@」「-」で名前を入力
  • 説明 -> 説明文を入力。日本語可。
  • Shell command -> /usr/bin/podman exec -w 【Laravelのディレクトリ】 --user www-data 【コンテナ名】 php artisan schedule:run
  • トリガー -> 1分間隔で繰り返し

動作確認

自動実行すると「/storage/app/private」「/storage/app/public」にログファイルが生成される筈。

生成されない場合はディレクトリのパーミッションの確認、Cockpit側の.serviceのログを確認すること。

 

補足

Laravel側のスケジュール頻度オプション

systemd timer側は基本的に前述の通り1分間隔で実行するように設定し、Laravel側ではリファレンスのようにスケジュール頻度オプションを指定する形になる。

Artisanコマンドを作成しない場合

「/routes/console.php」に以下を追記する形でも動作する。ただ、自動実行のプログラムが多い場合に見づらくなると思うので、基本的にはArtisanコマンドを作成した方がよさそう。

use Illuminate\Support\Facades\Schedule;
use Illuminate\Support\Facades\Storage;

Schedule::call(function () {
    $logMessage = '[timer test]' . now()->toDateTimeString();
    Storage::append('timer_test.log', $logMessage);

    # /storage/app/public/ に保存する場合
    Storage::disk('public')->append('timer_test.log', $logMessage);
})
->everyMinute()
->name('timer_test_closure')
->withoutOverlapping();

 

リファレンス

タスクスケジューリング

https://laravel-jp.toolboxforweb.xyz/docs/scheduling

 - PHP Laravel

  関連記事

Laravel 13系でエラーログをブラウザ上で表示・検索できる「log-viewer」の導入方法
Laravel 13系でエラーログをブラウザ上で表示・検索できる「log-viewer」の導入方法

先日Laravel 13系でエラーログ設定を行ったが、このログをブラウザ上で表示 ...

Laravelのディレクトリ構造・バージョン・DB接続情報確認
Laravelのディレクトリ構造・バージョン・DB接続情報確認

Laravelで作成されているシステムに携わることがあった。しかしながら当方La ...

Laravel 13系で外部ファイル(CSS / JS)の読み込みと共通パーツ化する方法
Laravel 13系で外部ファイル(CSS / JS)の読み込みと共通パーツ化する方法

Laravel 13系でBootstrap 5系のCSS及びJavaScript ...

Laravel 13系でGET / POSTパラメータを受け取って出力する方法
Laravel 13系でGET / POSTパラメータを受け取って出力する方法

Laravel 13系でフォームから送信したGET / POSTパラメータを受け ...

Laravel 13系でエラーログ設定と出力及び確認方法
Laravel 13系でエラーログ設定と出力及び確認方法

Laravelのエラーログはデフォルト設定だと同じファイルに無制限に追記していく ...