LaravelコントローラーでArtisan::call(‘schedule:run’)

crontabが設定できない環境でcronを再現しようとコントローラーで呼び出せるように実装したところ何故か実行できなかった問題を解決した件です(長い)

前提としては crontab を編集することなく定期実行を作成しようとしたのが発端です。Laravelを実行しているサーバー以外でcronをURL読み込みすれば可能になる想定です。

始めはこのようにコントローラー無いで Artisanクラスを使用してコマンド実行するようにしました

<?php

    public function cron(Request $request)
    {
        Artisan::call('schedule:run');
    }

この方法では起動できず、失敗してしまいます。

状況の確認をしようとコマンド実行の結果を返却するようにしました

<?php

    public function cron(Request $request)
    {
        Artisan::call('schedule:run'); // 定期的に app:send コマンドの実行をするように設定済み

        return Artisan::output();
    }
% curl 'https://laravel.test/api/cron'

  2023-10-31 22:29:28 Running ['artisan' app:send] .................. 7ms FAIL
  ⇂ '' 'artisan' app:send > '/dev/null' 2>&1  

結果としては FAIL の文字が…

ですが出力ログが親切で、どうやらPHPコマンドが指定できていないようです。

schedule:run コマンドのクラス ( vendor/laravel/framework/src/Illuminate/Console/Scheduling/ScheduleRunCommand.php ) の処理を追っていくと、内部でCLI実行しているためにPHPコマンドが見つけられないのが問題でした。 ( vendor/symfony/process/PhpExecutableFinder.php )

コマンドラインでの実行であれば環境変数から解決してくれる実装だったため、CLI実行できるPHPのパスを設定してあげて解決しました。

<?php

    public function cron(Request $request)
    {
        if (config('app.php_binary')) {
            \putenv('PHP_BINARY='.config('app.php_binary'));
        }
        Artisan::call('schedule:run');

        return Artisan::output();
    }
<?php

return [

    'php_binary' => env('APP_PHP_BINARY', ''),

];
APP_PHP_BINARY="/path/to/php"

終わりに

以上、コントローラーでschedule:runを実行する方法でした。

Laravel実行環境以外でcron設定をしようと設定しましたが、簡単に外部実行できるURLにしてしまうと攻撃者の格好の的になってしまうので認証等を正しく設定してください。

こちらの記事で紹介している認証を活用してみてください。

今回の問題はこちらで議論していましたが、解決しておらず、なんとか自己解決できてよかったです。

https://laracasts.com/discuss/channels/laravel/calling-artisancallschedulerun-from-a-controller

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA