Laravelで毎分ログを出力するバッチを実装

こんにちは、JeffTechです。

# 説明
今回の記事では、Laravelで毎分実行するバッチを作成していきます。
やることとしては、作成したバッチを毎分ごとに動かして`storage/logs`のlogファイルに、`バッチを実行しました。`というログを出力していきたいと思います。

# この記事で実現できること
- Laravelでログを出力させる
- Laravelでバッチを作成する
- Laravelでcronを使用したバッチの毎分処理

# 開発環境
- MacOS：Catalina
- PHP：7.3
- Laravel：6.2

# 実装の流れ
1. Laravelのインストール
1. バッチの作成
1. タイムスケジュール設定
1. cronのフルディスクアクセス許可
1. cronへ登録
1. 動作確認
1. cron補足

# 実装

## Laravelのインストール
下記コマンドでLaravelのインストールをしてください。

```bash
$ composer create-project --prefer-dist laravel/laravel test_cron "6.*"
```



## バッチの作成
バッチは`php artisan make:commnad [バッチ名]`で作成することができます。
Laravelのプロジェクトフォルダ直下で下記のコマンドを実行してください。

```bash
$ php artisan make:command TestBatch
```
成功すると、`app/Console/Commands`配下にTestBatch.phpが作成されます。

```php:TestBatch.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class TestBatch extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
    }
}
```
さっそく`TestBatch.php`を編集していきましょう。

```TestBatch.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class TestBatch extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'batch:test';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '毎分Logファイルに「バッチを実行しました。」と出力する';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        \Log::info('バッチを実行しました。');
    }
}
```
小分けして見ていきます。

```TestBatch.php
protected $signature = 'batch:test';
```
バッチの名前をこちらで設定しています。

```TestBatch.php
protected $description = '毎分Logファイルに「バッチを実行しました。」と出力する';
```
バッチの説明をこちらで設定しています。
試しに下記コマンドを実行して、うまく登録されているか確認してみましょう。

```bash
$ php artisan list
```

```bash
Laravel Framework 6.20.20

Usage:
  command [options] [arguments]
ーー省略ーー
 batch
  batch:test           毎分Logファイルに「バッチを実行しました。」と出力する
ーー省略ーー
```
バッチの名前と説明がちゃんと反映していることがわかります。

```TestBatch.php
public function handle()
{
    \Log::info('バッチを実行しました。');
}
```
実際の処理を記述しています。
これで、`storage/logs`配下のLogファイルにバッチを実行しました。というログが残るようになりました。

試しにログが本当に出力されるのかを確かめてみます。

```bash
$ php artisan batch:test
```
実行したら、`storage/logs/laravel.log`を見てみてください。

```log:laravel.log
[2021-03-25 02:58:02] local.INFO: バッチを実行しました。  
```
ここまでできていれば完璧です。
時間が現在時刻と違う！という方は、`config/app.php`で日本時間にしてください。

```php:app.php
// 'timezone'の部分のみ抜粋
'timezone' => 'Asia/Tokyo',
```



## タイムスケジュール設定
コマンドでのログ出力ができたので、定期的にバッチが実行されるようにスケジュール設定をしていきます。
いつ、どのタイミングでバッチを実行するのかを設定するのは、`app/Console/Kernel.php`で行います。

```php:Kernel.php
<?php

namespace App\Console;

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

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        //
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // $schedule->command('inspire')
        //          ->hourly();
    }

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

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

`protected function schedule(Schedule $schedule){}`を変更していきます。

```php:Kernel.php
// scheduleメソッドの部分のみ抜粋
protected function schedule(Schedule $schedule)
{
    $schedule->command('batch:test')
    ->everyMinute();
}
```
`batch:test`を`everyMinute()`で毎分実行してね！という処理になります。
毎時や毎日指定の時間に実行なども行えます。
もっと詳しく設定したい方は[こちら](https://readouble.com/laravel/5.7/ja/scheduling.html)を参照してください。


## cronのフルディスクアクセス許可
LinuxやUnix系OSで特定の処理を定期的に実行するにはCronという機能を利用します。まずはこちらを使用できるようにしていきます。
なお、すでにcronが正常に動作している方は飛ばして大丈夫です。

下記の順番でcronにフルディスクアクセスを許可してください。
→システム環境設定
→セキュリティとプライバシー
→フルディスクアクセス
→鍵マークをクリック
→パスワード入力
→＋ボタンをクリック
→command + shift + g
→/usr/sbin/cronを検索→
移動
→開く
これでフルディスクアクセスが許可できました。



## cronへ登録
毎分バッチを実行するために、cronへ登録していきます。
実は、1行書くだけで終わっちゃいます。
下記コマンドをプロジェクトフォルダ直下で実行してください。

```bash
$ crontab -e
```
初めてのかたは、~~~~がたくさん出てくるかと思いますが、そのままキーボードで`i`を入力してください。
そうすると`-- INSERT --`となり、文字が入力できるようになります。

```bash
* * * * * cd Laraveのプロジェクトフォルダフルパス && php artisan schedule:run >> /dev/null 2>&1
```
を入力してください。
例としては下記の通りです。

```bash
* * * * * cd /Users/ユーザー名/Desktop/project/test_cron && php artisan schedule:run >> /dev/null 2>&1
```
入力が完了したら、Esc(エスケープ)キーを押して、`:wq`と入力してエンターを押してください。
そうすると、保存して終了されます。

万が一下記のようなモーダルが出てきたら、そのまま許可してください。

```
“Visual Studio Code”がコンピュータを管理することを要求しています。管理にはパスワード、ネットワーク、およびシステム設定の変更が含まれます。
```



## 動作確認
実際に`storage/logs/laravel.log`を確認してみてください。
毎分ごとにバッチが実行されていれば、下記のようになるはずです。

```log:laravel.log
[2021-03-25 02:58:02] local.INFO: バッチを実行しました。  
[2021-03-25 03:34:01] local.INFO: バッチを実行しました。  
[2021-03-25 03:35:00] local.INFO: バッチを実行しました。  
[2021-03-25 03:36:01] local.INFO: バッチを実行しました。  
[2021-03-25 03:37:00] local.INFO: バッチを実行しました。  
[2021-03-25 03:38:01] local.INFO: バッチを実行しました。  
```

これで無事実装完了です。



## cron補足

### Cronコマンド一覧
先程使った`$crontab -e`以外にもコマンドが存在しています。

```
// crontabの編集
$ crontab -e

// crontabのエントリーを確認
$ crontab -l

// crontabのエントリーを全削除
$ crontab -r
```
crontabのエントリーの一部だけ削除したい場合は、`$ crontab -e`で該当のテキストを削除してください。



### Cron Table(crontab)の書式
先程cronへ登録したときの`* * * * * `にはちゃんと意味があります。

```
分 時 日 月 曜日
* * * * *
```
の順番です。

各アスタリスクには下記の値を指定することができます。
- 分：0-59
- 時：0-23
- 日：1-31
- 月：1-12
- 曜日：0-6(0は日曜日)

毎分処理を行いたいときは`*****`とします。

毎時30分に処理を行いたいときは下記のようにします。

```bash
30 * * * *
```
毎日15時に処理を行いたいときは下記のようにします。

```bash
0 15 * * *
```
金曜日の朝4時に処理を行いたいときは下記のようにします。

```bash
0 4 * * 5
```

# 最後に
少しでも役に立った！という時は、いいねをポチッとして
フォローしてくださると嬉しいです、、、笑

役に立たなかった時は、怒らないでコメント頂けますと幸いです笑

Twitterもやってますので、よかったら見てみてくださいね！
https://twitter.com/jefftechsaku