AzureのLinux仮想マシンのLoad averageの監視をSystemdのtimerで行う

船井総研デジタルのよもぎたです。

先日[「AzureのLinux仮想マシンでLoad averageを監視する方法の検討と実装」](https://qiita.com/t_ymgt/items/9a94900cd6a32e8bf22b)という記事を投稿いたしました。しかし、このやり方だとおよそ301秒間のうち300秒間``sleep``しているわけで、なんかカッコ悪いよね、と思います。そこで、今回はSytemdのtimerを使って監視してみたいと思います。環境は引き続きAzureの仮想マシンでディストリビューションはRocky Linuxの8系を使いました。

# 大まかな仕組み

``uptime``コマンドでLoad averageを取得してしきい値を越えていたらSyslogにメッセージを出力するのは前回と同様です。今回は無限ループして待ちのための``sleep``は行わず、処理を1回実行してスクリプトは終了します。このスクリプトをSytemdのtimerで定期的に実行します。

# 監視スクリプト

下記のとおりです。

```bash
$ ls -l /usr/local/bin/loadaveragemonitor.sh
-rwxr-xr-x. 1 root root 178 Oct  8 15:33 /usr/local/bin/loadaveragemonitor.sh
$ cat /usr/local/bin/loadaveragemonitor.sh
#!/bin/bash

/bin/uptime | /bin/grep -o 'load average:.*' | /usr/bin/tr -d ',' |\
  /bin/awk -v th=${LOAD_AVERAGE_THRESHOLD} '{if($NF>th || $(NF-1)>th || $(NF-2)>th){print $0}}'
```

``while``無限ループがなくなってシンプルになりました。監視するload averageを変えたい場合は、``awk``スクリプトを適宜調整してください。

# Systemdのtimerで定期実行するようにする

## 大まかな手順

* スクリプトに与えるパラメータファイルを作成する
* ``<servicename>.service``ファイルを作成する
* ``<servicename>.timer``ファイルを作成する
* ``systemctl daemon-reload``コマンドを実行する
* ``systemctl start <servicename>.timer``コマンドを実行する
* 動作確認を行う
* ``systemctl enable <servicename>.timer``コマンドで自動起動するように設定する
* OSを再起動して自動起動していることを確認する

## パラメータファイルの作成

内容は下記のとおりです。

```bash
$ ls -l /etc/default/loadaveragemonitor
-rw-r--r--. 1 root root 25 Oct  8 15:35 /etc/default/loadaveragemonitor
$ cat /etc/default/loadaveragemonitor
LOAD_AVERAGE_THRESHOLD=5
```

設定する値が一つだけになってしまったので別ファイルにする意味あるのか？と感じますが、あくまでこういうことができますよ、という例を示すために別ファイルにしています。（苦しいな）

## ``<servicename>.service``ファイルの作成

内容は下記のとおりです。

```bash
$ ls -l /etc/systemd/system/loadaveragemonitor.service
-rw-r--r--. 1 root root 398 Oct  8 22:36 /etc/systemd/system/loadaveragemonitor.service
$ cat /etc/systemd/system/loadaveragemonitor.service
[Unit]
Description=Run the uptime command and output a message if the load average exceeds the threshold.
After=local-fs.target

[Service]
EnvironmentFile=/etc/default/loadaveragemonitor
User=nobody
Group=nobody
ExecStart=/usr/local/bin/loadaveragemonitor.sh
StandardOutput=journal
SyslogIdentifier=LoadAverageMonitor
SyslogFacility=local0
SyslogLevel=warning

[Install]
WantedBy=multi-user.target
```

前回と比べて、``Service``セクションの``ExecStop``パラメータを削除しました。常駐するわけではなく、定期的に実行されるよう変更したためです。

## ``<servicename>.timer``ファイルの作成

内容は下記のとおりです。

```bash
$ ls -l /etc/systemd/system/loadaveragemonitor.timer
-rw-r--r--. 1 root root 131 Oct  8 16:06 /etc/systemd/system/loadaveragemonitor.timer
$ cat /etc/systemd/system/loadaveragemonitor.timer
[Unit]
Description=Exec loadaveragemonitor.service.

[Timer]
OnBootSec=5min
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target
```

``[Timer]``セクションで実行タイミングを指定していて、上記の場合だと起動から5分後に初回実行、その後5分毎に実行となります。

## 監視を開始する

``systemctl daemon-reload``コマンドを実行してから、``systemctl start <servicename>.timer``を実行します。

```bash
$ sudo systemctl daemon-reload
$ sudo systemctl start loadaveragemonitor.timer
```

## 動作確認をする

例によって``dd``コマンドで負荷を掛けました。

```
$ /usr/bin/dd if=/dev/random of=/dev/null bs=1024 count=9999999999 &
```

``/var/log/messages``に下記の通り出力されました。

```
Oct 11 01:05:50 rocky1 systemd[1]: Started Run the uptime command and output a message if the load average exceeds the threshold..
Oct 11 01:05:50 rocky1 LoadAverageMonitor[5915]: load average: 5.70 1.32 0.44
Oct 11 01:05:50 rocky1 systemd[1]: loadaveragemonitor.service: Succeeded.
```

``systemd[1]``の2件のメッセージは毎回出力されるので、``LoadAverageMonitor``か``load average:``を監視キーワードにするのが良いと思います。（前者は大文字小文字を区別する必要アリ）

## OS再起動時に自動実行されるようにする

``systemctl``コマンドで``<servicename>.timer``の方を``enable``にします。

```bash
$ sudo systemctl enable loadaveragemonitor.timer
Created symlink /etc/systemd/system/timers.target.wants/loadaveragemonitor.timer → /etc/systemd/system/loadaveragemonitor.timer.
```

実際に再起動して様子を見ます。

```bash
$ sudo shutdown -r now
---snip---
$ systemctl status loadaveragemonitor.timer
● loadaveragemonitor.timer - Exec loadaveragemonitor.service.
   Loaded: loaded (/etc/systemd/system/loadaveragemonitor.timer; enabled; vendor preset: disabled)
   Active: active (waiting) since Wed 2023-10-11 01:18:10 UTC; 1min 42s ago
  Trigger: Wed 2023-10-11 01:22:59 UTC; 3min 5s left

Oct 11 01:18:10 rocky1 systemd[1]: Started Exec loadaveragemonitor.service..
```

ステータスは無事``active (waiting)``になっていました。

これで、ほとんどの時間を``sleep``しているスクリプトとお別れできます。

最後までお読みいただきありがとうございました。