CronはRunningなのにCrontabに書いた定時実行が動かなかった理由
CronはRunningなのにCrontabに書いた定時実行が動かなかった理由
こんな場面に遭遇してしまいました。
慣れてきたから起こるポカというか理解不足というか。
原因は超簡単な所だったので、次回の為の備忘録です。
DockerをリビルドしたらLaravelのSchedulerが動かなくなった
切っ掛けはDockerのリビルド。
昨日書いた記事の通り、サジェストを大量に取得するモードも用意したいと思いDockerを再構築しました。
その結果、サジェストは意図したとおりに動いたわけですが、スケジュールに収めていたRanking取得とか他店売価取得が動作していないのです。
原因追及の為、下記コマンドを実行して調査しました。
- crontab -e :スケジュールがちゃんと登録されています。
- service cron status :cron is running が返ってきます。
- (Projectに移動して)php artisan schedule:run :No scheduled commands are ready to run.と怒られます。
この結果を受けてLaravelスケジュールの方の問題と判断してしまったのが今回の最大のミスでした。
正しくても『No scheduled commands are ready to run.』は出る
実はプログラム自体に間違いが無くても「No scheduled commands are ready to run.」というメッセージは出現します。これは「今動く(準備すべき)スケジュールはないよ」と言う事なので、例えばスケジュールが毎時実行で組まれていた場合【今】動かす奴がいないので【No scheduled commands are ready to run.】とメッセージが出てきます。
何かのミスで動かないのか、それともただ単に計画時間に達していないのかの判断は毎分実行に変更してschedule:run を叩く事でわかります。
■File:app/Console/Kernel.php
<?php
namespace App\Console;
use DB;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\Log;
class Kernel extends ConsoleKernel
{
protected $commands = [
(中略)
\App\Console\Commands\schedules\loging::class
];
protected function schedule(Schedule $schedule)
{
$schedule->command('command:loging')->everyMinute();
(中略)
}
(後略)
■File:app/Console/Commands/loging.php
<?php
namespace App\Console\Commands\schedules;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class loging extends Command
{
protected $signature = 'command:loging {--secret=}';
protected $description = 'テスト用スケジュ―ルログ';
public function __construct()
{
parent::__construct();
}
public function handle()
{
Log::info('TESTです。');
}
}
->everyMinute();としてスケジュールを登録し、その上で php artisan schedule:run を実行するとコマンドが動く場合、問題の箇所はLaravel Scheduler にはありません。
cron is running でも crontabを見ているとは限らない
今回の一番の失敗はcron is running を見た瞬間、cronの問題ではないと判断してしまった事です。
実際はタイトルの通り、CRONが走っていてもCRONTABをみていませんでした。
なので【service cron restart】の実行で従来通りLaravelScheduleが実行されるようになりました。
cron が crontabを見ていなかった理由
今回作成したDockerでは、OSを含むWEBサービスをDockerfileに記載し、docker-compose.ymlでcrontabの設定やLaravelProjectを設置しました。Cronのインストールと起動の指示はDockerfile内に、ありどうやらこれが問題だったようです。
docker-compose.ymlにてWEBサービスに登録されたファイル達はDockerfileを実行した後に適用される。
だからCronを起動した時点でcrontabは空っぽ。
動いているCRONにはcrontabが読み込まれていないため、LaravelSchedulerの実行をしなかったわけです。
なるほど、起動の順番か。
cronサービスのリスタートで解決
crontab -e
これで登録したLaravelのschedule:runを登録したファイルが出てくればリスタートだけで課題解決です。
$ service cron restart * Restarting periodic command scheduler cron * Stopping periodic command scheduler cron [ OK ] * Starting periodic command scheduler cron [ OK ]
いやぁ~ここまで来るの長かった...。
まとめ
慣れてくるとツイツイこういった【順番】を見落として細かい間違いに目をやってしまいます。
今まで起こらなかったような事案が発生するのは当たり前のパートが疎かになってしまったからなんですよね。
気を引き締めたいと思います。


