Linuxのサービス監視と自動起動をシェルスクリプトで実現する方法

## はじめに
本記事では、Linuxにおけるサービスの監視および自動起動の方法について説明します。

特に、NGINXやMySQLなどの重要なサービスが停止するとシステム全体に影響を与えるため、自動的に状態を監視し、停止時に起動する仕組みが必要です。

実務では、Datadogなどの監視ツールを使うことが多いですが、今回はシェルスクリプトを用いてシンプルに監視を行う方法を紹介します。

## 前提条件
今回の検証を進めるにあたり、以下の環境が必要です。

:::note info
**検証環境**
**Linuxディストリビューション:**
仮想環境や実際のサーバー上でLinux（ここではAlmaLinux 9.3を使用）が稼働していること。

**管理者権限を持つユーザーアカウント:**
sudo権限にてコマンド操作できること。
:::

**自宅のVirtualBox環境**
今回も VirtualBox 上で構築した検証環境を使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/70df8950-ddfa-2728-1d71-60373a8276e9.png)


:::note info
※検証には実行中の「AlmaLinux」を使用します。
:::

## 知識整理

NGINXサービスの監視と自動起動を行うために、必要な知識を整理します。

:::note warn
**systemctl コマンド：**
サービスの状態を確認および操作するために使用します。

**シェルスクリプト：**
複数のコマンドを自動で実行するために使用します。

**ログファイルの管理：**
サービスが停止し、起動した日時を記録するファイルです。
:::

## 処理フロー

以下は、NGINXサービスを監視し、サービスが停止していた場合に自動的に起動するシェルスクリプトの処理フローです。

```service_monitor.sh
+------------------------------+
|      シェルスクリプト開始    |
+------------------------------+
  |
  v
+------------------------------+
| サービスの状態をチェック     |
+------------------------------+
  |
  v
+------------------------------+
| サービステータスに "running" |
| が含まれているか確認        |
+------------------------------+
  |           |
  |           v
  |   +------------------------------+
  |   | サービスが停止している       |
  |   +------------------------------+
  |           |
  |           v
  |   +------------------------------+
  |   | サービスを開始                |
  |   +------------------------------+
  |           |
  |           v
  |   +------------------------------+
  |   | 正常に開始したことをログに      |
  |   | 書き込む                      |
  |   +------------------------------+
  |           |
  |           v
  |     +------------------------------+
  |     |           処理終了          |
  |     +------------------------------+
  |
  v
+------------------------------+
| サービスは正常に実行中です     |
+------------------------------+
  |
  v
+------------------------------+
| ログファイルにメッセージを書き込み |
+------------------------------+
  |
  v
+------------------------------+
|           処理終了          |
+------------------------------+
```

## ディレクトリ構成
以下は、シェルスクリプトとログファイルの配置例です。

```
/home/your_user/service_monitor/
│
├─ service_monitor.sh         (監視と開始のシェルスクリプト)
└─ service_monitor.log        (監視結果を記録するログファイル)
```

シンプルな構成で作成することで、管理しやすくなり、問題が発生した場合でもログをすぐに確認できます。

また、ファイルの場所を明確にすることで、他の管理者にも分かりやすくなります。

## 検証の流れ

NGINXサービスの監視と自動起動を行う手順を以下の2ステップで説明します。

**ステップ1: サービスの状態を監視して自動起動**
**ステップ2: 定期的な監視の設定 (cronの利用)**

:::note info
前提として、検証環境がすでに構築されていることを前提とします。
:::

### ステップ1: サービスの状態を監視して自動起動

まずは、NGINXの監視と自動起動を行うシェルスクリプトを作成します。このスクリプトにより、NGINXの停止を検知し、自動的に再起動します。

```service_monitor.sh
#!/bin/bash

SERVICE_NAME="nginx"
LOG_FILE="/home/honda/service_monitor/service_monitor.log"

# サービスの状態をチェック
if systemctl is-active --quiet $SERVICE_NAME; then
    echo "$(date): $SERVICE_NAME は正常に実行中です。" >> $LOG_FILE
else
    echo "$(date): $SERVICE_NAME が停止しているため起動します。" >> $LOG_FILE
    sudo systemctl start $SERVICE_NAME
    sleep 5

    # サービスが正常に起動したと記録
    if systemctl is-active --quiet $SERVICE_NAME; then
        echo "$(date): $SERVICE_NAME が正常に起動しました。" >> $LOG_FILE
    else
        echo "$(date): $SERVICE_NAME の起動に失敗しました。" >> $LOG_FILE
    fi
fi
```

:::note warn
LOG_FILEの部分は、ご自身の環境に合わせて修正してください。
:::

このスクリプトでは、systemctl コマンドでサービスの状態を確認し、停止していた場合に起動します。

:::note alert
注意: シェルスクリプトの実行権限を忘れずに付与してください。以下のコマンドで実行権限を付与します。
```
chmod +x 作成したスクリプト名.sh
```
:::

結果は、service_monitor.log に記録され、サービスの監視履歴を確認することができます。

**NGINXが実行中の場合のログ例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/003e8597-a2a0-d1f3-18e2-a3e6e2dae304.png)

```
[root@HONDA-TEST service_monitor]# cat service_monitor.log
Fri Sep 20 10:16:32 PM JST 2024: nginx は正常に実行中です。
```

**NGINXが停止している場合のログ例**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/70062b69-0431-6f32-1fd4-bc1cc462ad89.png)

```
[root@HONDA-TEST service_monitor]# cat service_monitor.log
Fri Sep 20 10:22:50 PM JST 2024: nginx が停止しているため起動します。
Fri Sep 20 10:22:55 PM JST 2024: nginx が正常に起動しました。
```

「nginx」のサービスについても、実機内で起動していることが確認できました。


### ステップ2: 定期的な監視の設定 (cronの利用)

このシェルスクリプトを定期的に実行するために、cronを使用します。手順は以下の通りです。

crontab -e コマンドを実行してcronジョブを編集します。

```
crontab -e
```

以下の行を追加して、5分ごとにスクリプトを実行するように設定します。

```
*/5 * * * * /bin/bash /home/your_user/service_monitor/service_monitor.sh
```

これで、指定した間隔で自動的にサービスを監視し、停止している場合は自動で起動するようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/23e8baa5-51a2-191a-c172-c617c9feb95c.png)

ジョブ登録後、5分経過すると自動的に作成した「service_monitor.sh」が実行されていることが確認できました。

```
[root@HONDA-TEST service_monitor]# grep CRON /var/log/cron | grep service_monitor.sh
Sep 20 22:30:02 HONDA-TEST CROND[4052]: (root) CMD (/bin/bash /home/honda/service_monitor/service_monitor.sh)
Sep 20 22:30:07 HONDA-TEST CROND[4009]: (root) CMDEND (/bin/bash /home/honda/service_monitor/service_monitor.sh)
[root@HONDA-TEST service_monitor]# cat service_monitor.log
Fri Sep 20 10:30:02 PM JST 2024: nginx が停止しているため起動します。
Fri Sep 20 10:30:07 PM JST 2024: nginx が正常に起動しました。
```

cronを使用することで、手動での監視作業を大幅に削減し、システムの安定性を向上させることができます。

## まとめ

systemctl コマンドを使ったサービスの状態監視と、シェルスクリプトを組み合わせることで、日常的な監視作業を自動化し、システムの安定性を向上させることができました。

このシステムを実装することで、サービスの可用性が高まり、自宅検証スキルも向上しました。

今後は、問題発生時に迅速に対応できるよう、メール通知を行う仕組みを構築し、さらなる運用効率の向上を目指します。

## おまけ

Linux環境では、サービスの管理にsystemctlコマンドが広く使われています。ここでは、日常的によく使用される基本的なコマンドの使い方を簡単に紹介します。

**サービスの状態を確認する**
サービスが現在実行中かどうか、エラーが発生していないかなど、詳細なステータスを確認するコマンドです。
```
systemctl status [サービス名]
```

**サービスを開始する**
サービスが停止している場合に、手動で開始するコマンドです。
```
systemctl start [サービス名]
```

**サービスを停止する**
サービスを手動で停止する場合に使用します。
```
systemctl stop [サービス名]
```

**サービスを再起動する**
サービスの設定変更後や、トラブルシューティングのために再起動するコマンドです。
```
systemctl restart [サービス名]
```

**サービスを再読み込みする**
設定ファイルの変更を反映させるためにサービスを再起動する必要があるが、完全な再起動を避けたい場合に使用します。
```
systemctl reload [サービス名]
```

**サービスを自動起動に設定する**
サーバーを再起動した際に、自動でサービスが起動するように設定します。
```
systemctl enable [サービス名]
```

**サービスの自動起動を無効にする**
特定のサービスが自動で起動しないように設定します。
```
systemctl disable [サービス名]
```

## 参考記事
https://hldc.co.jp/blog/2023/12/25/13178/

https://japan.zdnet.com/article/35211516/