PowerShellを用いたWindowsサービスの自動監視と障害通知の実装

## はじめに

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

今回は、Active DirectoryのディレクトリサービスであるNTDSサービスが停止した際、その状態をPowerShellスクリプトで監視し、停止を検知した際にメールで通知するシステムの検証を行いました。

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

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

:::note info
**検証環境**
**Windows Server:**
仮想環境や実際のサーバー上でWindows Server（ここではWindows Server 2022を使用）が稼働していること。

**管理者権限を持つユーザーアカウント:**
管理者権限でPowerShellを実行できること。

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

**Blatインストール済み:**
Blatを用いてメール送信を行います（後で解説）。
:::

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/3d9d22ff-457a-1b00-58af-ff9948466145.png)

:::note info
※検証には「Windows Server 2022」を使用します。
:::

## 知識整理
自宅サーバーのサービス監視を効率化するために、PowerShellスクリプトを作成しました。**このスクリプトは、特定のサービス（ここではNTDS）の状態を確認し、停止していた場合に自動的に再起動するロジックを実装**しています。

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

### ディレクトリ構成
スクリプトのディレクトリ構成は以下の通りです。

```
service_monitor/
├── sendmail.ps1
├── service_monitor.log
└── service_monitor.ps1
```

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

### フロー処理の流れ
以下は、NTDSサービス（Active Directoryのディレクトリサービス）を監視し、サービスが停止していた場合に自動的に起動し、メール通知を行うPowerShellスクリプトの処理フローです。

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

## 検証の流れ
PowerShellスクリプトの作成および検証手順を以下の3ステップで説明します。

**ステップ1: Blatのインストール手順**
**ステップ2: PowerShellスクリプトの作成**
**ステップ3: サービス停止時のメール通知検証**

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

## **ステップ1: Blatのインストール手順**
まず、Blatの公式サイトからWindows用のバイナリをダウンロードします。一般的にはZIPファイルが提供されています。

https://www.veritas.com/support/ja_JP/article.100036340

ダウンロードしたZIPファイルを解凍します。blat.exeが含まれていることを確認してください。

解凍したディレクトリをWindowsの環境変数に追加します。以下の手順で設定できます。

```
・ Windowsの検索バーに「環境変数」と入力し、「システム環境変数の編集」を選択。
・「環境変数」をクリック。
・「Path」を選択し、「編集」をクリック。
・「新規」をクリックし、Blatの解凍先のパスを追加。
・ 変更を保存して、コマンドプロンプトを再起動します。
```

環境変数を設定したら、再度コマンドプロンプトを開き、次のコマンドを実行します。
```
blat -install <SMTPサーバーのIPアドレス> xxxx@gmail.com
```

:::note warn
Postfixが外部からの接続を許可しているか確認し、必要に応じて/etc/postfix/main.cfファイルのinet_interfacesがallに設定されていることを確認してください。

```/etc/postfix/main.cf
inet_interfaces = all
```
設定を変更した場合は、Postfixの再起動が必要になります。
:::

## **ステップ2: PowerShellスクリプトの作成**
次に、以下のスクリプトを任意の場所に作成します。

### スクリプトの詳細
**sendmail.ps1の説明**
「sendmail.ps1」は、指定した件名と本文を使ってメールを送信するためのスクリプトです。
```sendmail.ps1
param (
    [string]$Subject,
    [string]$Body
)

# 送信元と送信先のメールアドレス
$MAIL_FROM = "xxxx@gmail.com"
$MAIL_TO = "xxxx@gmail.com"

# メール送信
& blat.exe - -f $MAIL_FROM -t $MAIL_TO -s $Subject -body $Body
```

**service_monitor.ps1の説明**
「service_monitor.ps1」は、NTDSサービス（Active Directoryのディレクトリサービス）の状態を監視し、停止している場合には再起動を行います。また、再起動の結果をメールで通知します。

```service_monitor.ps1
$SERVICE_NAME = "NTDS"
$LOG_FILE = "C:\path\to\service_monitor.log"

# サービスの状態をチェック
if ((Get-Service $SERVICE_NAME).Status -eq 'Running') {
    Add-Content -Path $LOG_FILE -Value "$(Get-Date): $SERVICE_NAME は正常に実行中です。"
} else {
    Add-Content -Path $LOG_FILE -Value "$(Get-Date): $SERVICE_NAME が停止しているため起動します。"
    Start-Service $SERVICE_NAME
    Start-Sleep -Seconds 5
    
    # サービスが正常に起動したと記録
    if ((Get-Service $SERVICE_NAME).Status -eq 'Running') {
        Add-Content -Path $LOG_FILE -Value "$(Get-Date): $SERVICE_NAME が正常に起動しました。"

        # sendmail.ps1 を呼び出してメール送信
        & .\sendmail.ps1 "$SERVICE_NAME サービスの再起動成功" "$SERVICE_NAME が正常に再起動されました。"
    } else {
        Add-Content -Path $LOG_FILE -Value "$(Get-Date): $SERVICE_NAME の起動に失敗しました。"
    }
}
```

:::note alert
**注意: PowerShellスクリプトの実行権限を確認してください。** 実行権限を変更するには、次のコマンドを実行します。

```powershell
Set-ExecutionPolicy RemoteSigned
```
:::

## **ステップ3: サービス停止時のメール通知検証**
このステップでは、NTDSサービス（Active Directoryのディレクトリサービス）が停止した際に、PowerShellスクリプトが正しく動作し、メール通知が送信されるかどうかを検証します。手順は以下の通りです。

### 検証手順
まず、NTDSサービスを意図的に停止させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/df327665-8dcd-7c84-b9cc-9c16b2d87d75.png)



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

```powershell
.\service_monitor.ps1
```

**スクリプト実行後の画面**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/f8729841-9509-1657-5cbb-04c1e9aaa632.png)


:::note warn
スクリプト実行後、NTDSサービス（Active Directoryのディレクトリサービス）が正常に「**実行中**」になっていることが確認できました。
:::

### 検証結果

NTDSサービス（Active Directoryのディレクトリサービス）が再起動され、指定されたメールアドレスに再起動成功の通知が送信されたことを確認します。

**メール通知確認**
送信元と送信先のメールアドレスに、再起動成功のメールが届いていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/6a447016-ff1f-d2f8-9752-b19460e67496.png)


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

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

```service_monitor.log
09/22/2024 23:50:06: NTDS が停止しているため起動します。
09/22/2024 23:28:19: NTDS が正常に起動しました。
```

ログにも想定通りの結果が出力されていることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/41546c49-f36c-780b-6d08-11c41d0d6567.png)


## まとめ
今回の検証では、NTDSサービスが停止した際に、PowerShellスクリプトで監視し、停止を検知するとメール通知を行うシステムを構築しました。

Windows Server 2022を検証環境に使用し、Blatを使ってメール通知機能を実装しました。

サービスが停止した際、自動で再起動し、結果をログに記録してメールで報告する機能も確認できました。引き続き、自宅検証を頑張ります。

## 参考記事
https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7.4

https://www.dospara.co.jp/5info/cts_str_pcuse_powershelluse.html