シェルスクリプトで実現するNGINXサービス監視と自動再起動・メール通知の検証

## はじめに
この記事は、以前の[Linuxのサービス監視と自動起動をシェルスクリプトで実現する方法](https://qiita.com/free-honda/items/f3810e87d70001f52622)と[メールサーバーの構築](https://qiita.com/free-honda/items/c10052dcd507ac7e7605)に関する記事の続きです。

今回は、**NGINXサービスが停止した際に、その状態をシェルスクリプトで監視し、停止を検知した場合にメールで通知する機能を追加したシステムの検証**を行います。

現在のプロジェクトでは、AWS環境を使用しており、Datadogと呼ばれる海外製の監視ツールを使ってこれらの要件を実現していますが、コストを抑えつつ自分の環境で同様の機能を実装したいと考えました。


この記事は、今後の自分のためにも忘備録として記録していきます。

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

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

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

**サービス監視と自動起動をシェルスクリプト実装済み：**

[こちらの記事で紹介：Linuxのサービス監視と自動起動をシェルスクリプトで実現する方法](https://qiita.com/free-honda/items/f3810e87d70001f52622)


**メールサーバー構築済み：**

[こちらの記事で紹介：自宅のAlmaLinux 9.3でのメールサーバー構築およびメール送信の検証](https://qiita.com/free-honda/items/c10052dcd507ac7e7605)


:::

**自宅の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）の状態を確認し、停止していた場合に自動的に再起動するロジックを実装**しています。

追加要件として、停止していた場合に自動的に再起動した後に、その結果をメールで通知する機能を追加していきます。


### ディレクトリ構成

シェルスクリプトのディレクトリ構成は次のようになっています。

```bash
service_monitor/
├── sendmail.sh
├── service_monitor.log
└── service_monitor.sh
```

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

### フロー処理の流れ

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

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

## 検証の流れ

今回のシェルスクリプトの作成及び検証手順を以下の2ステップで説明します。

**ステップ1: シェルスクリプトの作成**
**ステップ2: サービス停止時のメール通知検証**

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

## ステップ1: シェルスクリプトの作成
まず、次のスクリプトを任意の場所に作成します。

### スクリプトの詳細
**sendmail.shの説明**
「sendmail.sh」は、指定した件名と本文を使ってメールを送信するためのスクリプトです。
```sendmail.sh
#!/bin/bash

# 送信元と送信先のメールアドレス
MAIL_FROM="xxx@gmail.com"　#送信先のアドレス
MAIL_TO="xxx@gmail.com"　#送信元のアドレス
SUBJECT="$1"
BODY="$2"

# メール送信
sendmail -t <<EOL
From: $MAIL_FROM
To: $MAIL_TO
Subject: $SUBJECT

$BODY
EOL
```

**service_monitor.shの説明**
「service_monitor.sh」は、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

        # sendmail.sh を呼び出してメール送信
        ./sendmail.sh "$SERVICE_NAME サービスの再起動成功" "$SERVICE_NAME が正常に再起動されました。"

    else
        echo "$(date): $SERVICE_NAME の起動に失敗しました。" >> $LOG_FILE
    fi
fi

```

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

## ステップ2: サービス停止時のメール通知検証
このステップでは、NGINXサービスが停止した際に、シェルスクリプトが正しく動作し、メール通知が送信されるかどうかを検証します。手順は以下の通りです。

### 検証手順

まず、NGINXサービスを意図的に停止させます。以下のコマンドを実行して、サービスを停止させます。
```
sudo systemctl stop nginx
sudo systemctl status nginx


**出力結果**
○ nginx.service - The nginx HTTP and reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
     Active: inactive (dead) since Sun 2024-09-22 12:54:56 JST; 10s ago

```

**シェルスクリプト実行前の画面**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/5f512e5d-afa3-f599-6b1b-0aa6d68704ac.png)


次に、シェルスクリプトを実行して、NGINXサービスの状態がチェックされ、停止が検知されて自動再起動されることを確認します。

以下のコマンドでスクリプトを実行します。
```
./service_monitor.sh
sudo systemctl status nginx


**出力結果**
● nginx.service - The nginx HTTP and reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
     Active: active (running) since Sun 2024-09-22 12:56:59 JST; 1min 0s ago
```



**シェルスクリプト実行後の画面**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/25a65ccd-8668-de84-a3c4-af51c8b4201a.png)

:::note warn
**シェルスクリプト実行後、NGINXサービスが正常に「active」になっていることが確認できました。**
:::


### 検証結果

NGINXサービスが再起動され、指定されたメールアドレスに再起動成功の通知が送信されたことを確認します。

**メール通知確認**
送信元と送信先のメールアドレスに、再起動成功のメールが届いていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/8445cf32-29e2-0a53-b26a-c1646089bce0.png)

:::note warn
**シェルスクリプトがNGINXサービスの自動再起動を実行し、再起動成功のメールが指定されたアドレスに無事届いています。**
:::

**ログ確認**
次に、シェルスクリプトが生成したログファイル（service_monitor.log）を確認し、サービス停止や再起動の処理内容、メール通知が正しく記録されているかチェックします。

```
cat /home/honda/service_monitor/service_monitor.log
```

:::note info
ログにも想定通りの内容が記録されており、再起動の処理とメール通知が正常に行われたことが確認できました。
```service_monitor.log
[root@HONDA-TEST service_monitor]# cat service_monitor.log
Sun Sep 22 12:56:58 PM JST 2024: nginx が停止しているため起動します。
Sun Sep 22 12:57:04 PM JST 2024: nginx が正常に起動しました。
```
:::

ログファイルに再起動の処理内容とメール送信の結果が正しく記録されていることが確認できましたので、検証は成功になります！

## まとめ
今回の検証では、NGINXサービスが停止した際に、シェルスクリプトが自動的に再起動を行い、再起動成功の通知メールが正しく送信されることを確認しました。

また、ログファイルにもサービスの停止、再起動、およびメール通知の結果が正常に記録されていることを確認できました。

全体を通して、**実務で使用しているDatadogの基本機能を押さえつつ、シェルスクリプトによるサービスの自動再起動まで、人手を介さずに実現できたこと**は非常に有意義な検証でした！


## 参考記事
https://qiita.com/osw_nuco/items/a5d7173c1e443030875f