LaravelをインストールしたEC2 に Supervisor を導入する

# はじめに
LaravelのSupervisorを使用してworkerプロセスを管理するため、Ec2にSupervisorを導入する流れをまとめました。

# 初期構築

EC2 Laravelは、下記記事で構築済み。

https://qiita.com/hirai-11/items/ea6cfe997c254375e811

ルートディレクトリは、`/var/www/html`です。
`/var/www/html`配下に laravel の public や storage があります。

# Supervisorをインストール
まず、epelをインストール後、supervisorをインストールします。
```terminal
$ sudo amazon-linux-extras install -y epel

$ sudo yum --enablerepo=epel install -y supervisor

$ supervisord -v
3.4.0
```
`/etc/supervisord.d`配下に管理プロセスファイルを新規作成します。

```terminal
$ sudo vim /etc/supervisord.d/laravel-worker.conf
```
ルートパスが`/var/www/html`の場合を想定して、記載しています。
（`command`と`stdout_logfile`は、各自パスが異なります）

```conf:/etc/supervisord.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d 
command=php /var/www/html/artisan queue:work --sleep=60
autostart=true
autorestart=true
user=ec2-user 
numprocs=1 
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/laravel-worker.log
```
`/etc/supervisord.conf`ファイルに、上記の管理プロセスファイルをincludeの設定をします。
```terminal
$ sudo vim /etc/supervisord.conf
```
一番下の [include] に追加します。
また、`supervisord.d/*.ini`は、コメントアウトします！
```diff_conf:/etc/supervisord.conf
[include]
+ files = supervisord.d/*.conf
- files = supervisord.d/*.ini
+ ;files = supervisord.d/*.ini
```
これで設定ファイルの修正は完了です。

# Supervisordの起動
Supervisorの操作は、`supervisord`と`supervisorctl`コマンドを使用します。
Supervisorではsupervisorctlコマンドでプロセスの管理を行います。
ただし、supervisorctl コマンドを利用するためには Supervisor を使用するには`supervisord`であらかじめ起動しておく必要があります。
下記で、ステータスの確認や起動、停止ができます。

supervisordのステータスを確認
```terminal
$ sudo service supervisord status
Redirecting to /bin/systemctl status supervisord.service
● supervisord.service - Process Monitoring and Control Daemon
   Loaded: loaded (/usr/lib/systemd/system/supervisord.service; disabled; vendor preset: disabled)
   Active: inactive (dead) since 木 2022-11-10 21:41:33 JST; 3s ago
  Process: 2886 ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf (code=exited, status=0/SUCCESS)
 Main PID: 2889 (code=exited, status=0/SUCCESS)

11月 10 21:40:26 ip-10-0-1-47.ap-northeast-1.compute.internal systemd[1]: Starting Process Monitoring and Control Daemon...
11月 10 21:40:26 ip-10-0-1-47.ap-northeast-1.compute.internal systemd[1]: Started Process Monitoring and Control Daemon.
```
supervisordを停止
```terminal
$ sudo service supervisord stop
Redirecting to /bin/systemctl stop supervisord.service
```
supervisordを起動
```terminal
$ sudo service supervisord start
Redirecting to /bin/systemctl start supervisord.service
```
では、supervisordを起動状態にしておきます。

また、自動起動設定を有効にします。
```terminal
$ sudo systemctl enable supervisord
Created symlink from /etc/systemd/system/multi-user.target.wants/supervisord.service to /usr/lib/systemd/system/supervisord.service.

$ sudo service supervisord status
status supervisord.service
● supervisord.service - Process Monitoring and Control Daemon
   Loaded: loaded (/usr/lib/systemd/system/supervisord.service; enabled; vendor preset: disabled)
   Active: active (running) since 木 2022-11-10 21:42:52 JST; 6min ago
  Process: 3065 ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf (code=exited, status=0/SUCCESS)
 Main PID: 3068 (supervisord)
   CGroup: /system.slice/supervisord.service
           ├─3068 /usr/bin/python /usr/bin/supervisord -c /etc/supervisord.conf
           └─3111 php /var/www/html/artisan queue:work --sleep=60

11月 10 21:42:52 ip-10-0-1-47.ap-northeast-1.compute.internal systemd[1]: Starting Process Monitoring and Control Daemon...
11月 10 21:42:52 ip-10-0-1-47.ap-northeast-1.compute.internal systemd[1]: Started Process Monitoring and Control Daemon.
```
`supervisord.service; enabled`：自動起動が有効になったことを確認しました。

# supervisorでのプロセス管理
supervisorctlコマンドを利用してプロセスの管理します。

プロセスのステータスを確認
```terminal
$ sudo supervisorctl status
laravel-worker:laravel-worker_00   RUNNING   pid 3131, uptime 0:00:44
```

プロセスを停止
```terminal
$ sudo supervisorctl stop laravel-worker:*
laravel-worker:laravel-worker_00: stopped
```
プロセスを起動
```terminal
$ sudo supervisorctl start laravel-worker:*
laravel-worker:laravel-worker_00: started
```
ログを確認
```terminal
$ cat /var/www/html/storage/logs/laravel-worker.log 

   INFO  Processing jobs from the [default] queue.  


   INFO  Processing jobs from the [default] queue.  
```

# supervisor管理プロセスファイル修正し、反映
`/etc/supervisord.d/laravel-worker.conf`管理プロセスファイルを変更します。

```terminal
$ sudo vim /etc/supervisord.d/laravel-worker.conf
```
プロセス数を1から３個に変更します。
```diff_conf:/etc/supervisord.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d 
command=php /var/www/html/artisan queue:work --sleep=60
autostart=true
autorestart=true
user=ec2-user 
- numprocs=13
+ numprocs=3
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/laravel-worker.log
```
設定変更したファイルの読み込みと再起動は、`supervisorctl reload`コマンドでしてくれます。


```terminal
$ sudo supervisorctl reload
Restarted supervisord

$ sudo supervisorctl status
laravel-worker:laravel-worker_00   RUNNING   pid 3250, uptime 0:00:07
laravel-worker:laravel-worker_01   RUNNING   pid 3251, uptime 0:00:07
laravel-worker:laravel-worker_02   RUNNING   pid 3252, uptime 0:00:07
```
プロセスを３個に変更なっていることを確認できました。

## supervisorctl reread
`supervisorctl reload`する前に、`supervisorctl reread`コマンドをすると、設定ファイルに変更があるか確認できます。
また、設定ファイル記載にミスがあった場合、エラーが表示され、反映ミスを防ぐことができます。

そのため、`supervisorctl reload`する前に、`supervisorctl reread`コマンドを実行しておくことをおすすめします。

### 変更メッセージ
```terminal
$ sudo supervisorctl reread
laravel-worker: changed
```
### 変更なしのメッセージ
```terminal
$ sudo supervisorctl reread
No config updates to processes
```
### 管理プロセスファイルに記載ミス
エラー内容も確認できます。
```terminal
$ sudo supervisorctl reread
ERROR: CANT_REREAD: invalid literal for long() with base 10: '3te' in section 'program:laravel-worker' (file: '/etc/supervisord.d/laravel-worker.conf')
```

# エラー集１
```terminal
`/etc/supervisord.d/laravel-worker.conf`管理プロセスファイルに記載ミスがあったまま、`reload`で反映してしまった場合などでおきるエラーです。
$ sudo supervisorctl status
unix:///var/run/supervisor.sock no such file
```
Supervisordデーモンを再起動しましょう。
```terminal
$ sudo service supervisord restart
Redirecting to /bin/systemctl restart supervisord.service

$ sudo supervisorctl status
laravel-worker:laravel-worker_00   RUNNING   pid 3581, uptime 0:00:05
laravel-worker:laravel-worker_01   RUNNING   pid 3582, uptime 0:00:05
laravel-worker:laravel-worker_02   RUNNING   pid 3589, uptime 0:00:05
```
# エラー集２
Supervisordデーモンが停止している場合などに遭遇するエラーです。
```terminal
$ sudo supervisorctl reread
error: <class 'socket.error'>, [Errno 2] No such file or directory: file: /usr/lib64/python2.7/socket.py line: 228
```
先程のエラー同様、Supervisordデーモンを再起動しましょう。
```terminal
$ sudo service supervisord restart
Redirecting to /bin/systemctl restart supervisord.service

$ sudo supervisorctl status
laravel-worker:laravel-worker_00   RUNNING   pid 3581, uptime 0:00:05
laravel-worker:laravel-worker_01   RUNNING   pid 3582, uptime 0:00:05
laravel-worker:laravel-worker_02   RUNNING   pid 3589, uptime 0:00:05
```

# 参考

https://readouble.com/laravel/9.x/ja/queues.html#supervisor-configuration

https://qiita.com/mokkos/items/473978ef0699df3173f5

https://qiita.com/kimzzang/items/0f7369fc062a5e4b2f45

https://reffect.co.jp/laravel/laravel-ubuntu-supervisor

https://www.task-notes.com/entry/20170311/1489224418