前回はCisco C1812JのCPU・メモリ・インターフェース状態をSNMPで取得する方法を紹介しました。
Raspberry PiでCiscoルータをSNMP監視する方法|OID調査と取得コマンド | Yuu Log
今回は、その取得処理をPythonで自動化し、Raspberry Piから1分ごとに監視する仕組みを構築します。
監視プログラムの配置、環境変数ファイル、systemd timer、Gmail通知、CSVログ保存までを解説します。
Python監視プログラムのディレクトリ構成
今回のシステムでは、プログラム、設定ファイル、状態ファイル、ログを別々のディレクトリに配置しています。
Linuxの一般的なディレクトリ構成に合わせることで、保守やバックアップがしやすくなります。
ディレクトリ階層
/
├── opt/
│ └── pi-monitor/
│ ├── monitor.py
│ ├── test_mail.py
│ └── test_interface.py
│
├── etc/
│ ├── pi-monitor.env
│ ├── systemd/
│ │ └── system/
│ │ ├── pi-monitor.service
│ │ └── pi-monitor.timer
│ └── logrotate.d/
│ └── pi-monitor
│
├── var/
│ ├── lib/
│ │ └── pi-monitor/
│ │ └── state.json
│ │
│ └── log/
│ └── pi-monitor/
│ └── metrics.csv
テスト時に作成したバックアップファイルなどは省略しています。
各ファイルの役割
| ファイル | 役割 |
|---|---|
monitor.py | SNMP取得・閾値判定・メール送信を行うメインプログラム |
test_mail.py | Gmail SMTPの送信確認 |
test_interface.py | インターフェースDOWNの模擬テスト |
pi-monitor.env | SNMP・SMTP接続情報 |
pi-monitor.service | Pythonプログラムの実行定義 |
pi-monitor.timer | 1分ごとの自動実行設定 |
state.json | 前回の監視値や障害状態の保存 |
metrics.csv | 監視履歴の保存 |
logrotate.d/pi-monitor | CSVログのローテーション |
特に重要なのが、state.jsonです。

今回のPythonプログラムは常駐型ではなく、systemdによって毎分起動されます。
プロセスが終了するとPythonの変数も消えるため、連続障害回数や前回の通信量カウンタをファイルに保存する必要があります。
state.jsonを利用することで、複数回の監視結果を比較できるようにしています。
SNMP監視プログラム「monitor.py」を作成する
ここまでで、Cisco C1812JからSNMPでCPU使用率やメモリ使用率、インターフェースの状態を取得する方法を確認しました。
次に、これらの処理を自動化するPython監視プログラムを作成します。
今回使用するmonitor.pyは、実際にRaspberry Pi上で動作させ、障害通知や復旧通知を検証したプログラムです。
SNMP監視だけでなく、Raspberry Pi自身のリソース監視、CSVへのログ保存、Gmailによるメール通知までを1つのPythonファイルで実行します。
監視プログラムの主な機能
monitor.pyには、以下の機能を実装しています。
| 機能 | 内容 |
|---|---|
| SNMP死活監視 | CiscoルータへのSNMP応答を確認 |
| CPU監視 | Cisco CPU MIBから5分平均使用率を取得 |
| メモリ監視 | 2つのメモリプールの使用率を計算 |
| インターフェース監視 | 6つのインターフェースのUP・DOWNを確認 |
| トラフィック監視 | 64bitカウンタから送受信bpsを計算 |
| Raspberry Pi監視 | CPU負荷・メモリ・ディスク・温度・低電圧 |
| 障害判定 | WARNING・CRITICAL・RECOVERY |
| メール通知 | Gmail SMTPで状態変化を通知 |
| 履歴保存 | CSVとJSONに監視結果を保存 |
監視用ディレクトリを作成する
まず、Pythonスクリプト、状態ファイル、ログを保存するディレクトリを作成します。
sudo mkdir -p /opt/pi-monitor
sudo mkdir -p /var/lib/pi-monitor
sudo mkdir -p /var/log/pi-monitor
monitor.pyを配置する
/opt/pi-monitor/配下にmonitor.pyを配置します。

今回のプログラムはPython標準ライブラリとNet-SNMPのsnmpgetコマンドを使用しているため、追加のPythonパッケージを大量にインストールする必要はありません。
配置したらmonitor.pyのアクセス権を制限します。
sudo chmod 755 /opt/pi-monitor/monitor.py
monitor.pyの処理の流れ
監視処理は次の順序で実行されます。
monitor.py 起動
│
├── 前回の状態をstate.jsonから読み込み
│
├── Raspberry Piのリソース情報を取得
│
├── Cisco C1812JへSNMPでアクセス
│
├── CPU・メモリ・IF状態を判定
│
├── 前回カウンタとの差分からbpsを計算
│
├── WARNING・CRITICAL・RECOVERYを判定
│
├── state.jsonを更新
│
├── metrics.csvへ監視結果を追記
│
└── 状態変化があればGmailで通知
SNMP取得処理:poll_router()
CiscoルータへのSNMPアクセスは、poll_router()関数で実行しています。

この関数では、取得対象のOIDを10個ずつに分割してsnmpgetを実行します。
古いCisco IOSでは、大量のOIDを一度に要求するとUDP応答が大きくなる場合があります。
そこで、1回の要求で取得するOID数を制限しています。
また、SNMP応答が取得できない場合は例外を発生させ、メイン処理側で連続失敗回数をカウントします。
Raspberry Pi監視:pi_metrics()
pi_metrics()では、Raspberry Pi自身のリソースを取得します。

メモリ情報は/proc/meminfo、ディスク使用率はPythonのshutil.disk_usage()、CPU温度は/sys/class/thermal/thermal_zone0/tempから取得します。
また、vcgencmd get_throttledを使用して、現在の低電圧状態も確認します。
障害状態の保存:state.json
今回のプログラムで重要なのが、前回の監視状態をJSONファイルに保存する仕組みです。
/var/lib/pi-monitor/state.json
このファイルには、SNMPの連続失敗回数、インターフェースDOWNの連続回数、現在のアラート、通知済みアラート、前回の通信量カウンタなどを保存します。
これにより、systemd timerが毎分Pythonを新しく起動しても、前回の監視結果を引き継げます。
また、JSONの更新には一時ファイルを使い、ファイル置換によって保存する方式を採用しています。
WARNING・CRITICAL・RECOVERYの通知を実装する
監視システムでは、単純に閾値を超えるたびにメールを送信すると、大量の通知が発生してしまいます。
例えば、インターフェースがDOWNした状態で毎分メールを送信すると、1時間で60通ものメールが届くことになります。
そこで、今回のシステムでは障害状態の変化に応じてメールを送信するようにしました。
SNMP障害の通知条件
| 状態 | 条件 |
|---|---|
| OK | SNMP応答あり |
| WARNING | 2回連続でSNMP取得失敗 |
| CRITICAL | 3回連続でSNMP取得失敗 |
| RECOVERY | SNMP応答が正常に復旧 |
インターフェース障害の通知条件
| 状態 | 条件 |
|---|---|
| OK | ifOperStatus = 1 |
| WARNING | 1回DOWN |
| CRITICAL | 3回連続DOWN |
| RECOVERY | DOWNからUPへ復旧 |
メール通知の重複を防止する
メール送信処理では、現在の障害状態と、前回メール通知した状態を比較します。
例えば、インターフェースがDOWNした場合、1回目はWARNING、3回連続でDOWNするとCRITICALを通知します。
その後、DOWNが継続しても同じ通知を繰り返しません。
インターフェースがUPへ復旧した場合には、RECOVERYメールを送信します。
さらに、SMTP送信に失敗した場合は、通知済み状態を更新せずに異常終了します。
そのため、次回の監視実行時に通知を再試行できる設計です。
Pythonの構文チェックを実行する
ファイルを保存したら、構文エラーがないか確認します。
sudo python3 -m py_compile /opt/pi-monitor/monitor.py
エラーが表示されなければ構文チェックは完了です。

SNMP・SMTP接続情報ファイル「pi-monitor.env」を作成する
メインプログラム「monitor.py」の作成が完了しました。
次は接続情報をまとめたファイル「pi-monitor.env」を作成します。
Googleアカウントでアプリパスワードを発行
障害時の通知にはGmailを使用します。
そのためまずアプリパスワードを発行します。
環境変数ファイルを作成する
sudo nano /etc/pi-monitor.env
設定例:

ROUTER_IP=192.168.20.1
SNMP_COMMUNITY=コミュニティ文字列
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=youraddress@gmail.com
SMTP_APP_PASSWORD=アプリパスワード
ALERT_TO=notify@example.com
パスワードなどの認証情報をPythonスクリプトへ直接記述しないようにしています。
設定ファイルには、管理者以外が読み取れないようアクセス権限を設定します。
sudo chown root:root /etc/pi-monitor.env
sudo chmod 600 /etc/pi-monitor.env
systemdで1分ごとに実行
メインプログラム「monitor.py」、接続情報ファイル「pi-monitor.env」の作成が完了しました。
次に以下を作成します。
- サービスファイル「pi-monitor.service」(monitor.pyの実行定義)
- タイマーファイル「pi-monitor.timer」(1分ごとの自動実行設定)
サービスファイル
sudo nano /etc/systemd/system/pi-monitor.service
[Unit]
Description=C1812J and Raspberry Pi Monitoring
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/pi-monitor.env
WorkingDirectory=/opt/pi-monitor
ExecStart=/usr/bin/python3 /opt/pi-monitor/monitor.py
TimeoutStartSec=120
タイマーファイル
sudo nano /etc/systemd/system/pi-monitor.timer
[Unit]
Description=Run Network Monitor Every Minute
[Timer]
OnCalendar=*-*-* *:*:00
AccuracySec=10s
Persistent=true
Unit=pi-monitor.service
[Install]
WantedBy=timers.target
有効化
準備が整いました。設定を読み込んでサービスを起動しましょう。
sudo systemctl daemon-reload
sudo systemctl enable --now pi-monitor.timer
実行状況の確認:
systemctl list-timers --all pi-monitor.timer

Gmailへのメール送信テスト
サービス起動が完了しました。
まずはGmailのSMTP送信だけをテストします。
そのためにテスト用のプログラム「test_mail.py」を作成します。
sudo nano /opt/pi-monitor/test_mail.py
以下を張り付けて保存。
from monitor import send_mail
send_mail(
"[TEST] Raspberry Pi Monitor",
"Gmail SMTPの送信テストです。\n"
"このメールが届けばSMTP設定は正常です。"
)
print("メール送信成功")
systemdと同じ環境変数を使って実行します。
sudo bash -c '
set -a
source /etc/pi-monitor.env
set +a
cd /opt/pi-monitor
python3 test_mail.py
'
メールが届けばSMTPの基本設定は完了です。

メール送信成功と表示されても、受信トレイへの配信まで保証するものではないため、実際の受信も確認してください。
監視結果を確認する
サービスが正常動作している場合、1分ごとにCSVファイルが保存されます。

/var/log/pi-monitor/metrics.csv
CSVには、取得日時、SNMP応答状態、CPU・メモリ使用率、インターフェース状態、通信速度などが記録されます。
CSVファイルはExcelやPythonなどで後から集計・グラフ化することが可能です。

例えば、CPU使用率の推移を確認したり、特定の時間帯にトラフィックが増加していないか分析したり。
ログの肥大化を防ぐ
24時間監視する場合、CSVのサイズがどんどん増え続けてしまします。
そのため増え続けないよう、logrotateも設定しておきます。
sudo nano /etc/logrotate.d/pi-monitor
設定例:

/var/log/pi-monitor/*.csv {
weekly
rotate 12
compress
missingok
notifempty
copytruncate
}
この設定では、CSVログを週単位でローテーションし、12世代保存します。
まとめ
monitor.py、pi-monitor.env、systemd timerを組み合わせ、1分ごとのSNMP監視とGmail通知、CSVログ保存を構築しました。
次回は、障害を模擬してメール通知が正しく届くか確認します。
