RaspberryPi Zero W2 監視・自動復旧システム まとめ
システム構成
| 機器 | IPアドレス | 役割 |
|---|---|---|
| RaspberryPi (監視側) | 192.168.11.22 | 監視・制御 |
| RaspberryPi Zero W2 | 192.168.11.50 | 監視対象(温湿度計測) |
| TP-Link Tapo スマートプラグ | 192.168.11.52 | Zero W2の電源制御 |
動作フロー
30秒ごとにPing監視
↓
3回連続失敗?
↓ YES
📧 メール「ダウン検出」送信
↓
SSH reboot 試行
↓ ↓
成功 失敗
60秒待機 📧 メール「Tapo電源サイクル実行」
Tapo電源OFF(5秒)→ON
60秒待機
↓
復旧確認
↓ ↓
復旧 また失敗
📧「復旧しました」 📧「手動対応が必要」
ファイル構成
/home/zero/scripts/
├── monitor_zero.py # 監視スクリプト本体
└── zero_monitor.log # 動作ログ
/etc/systemd/system/
└── zero-monitor.service # systemdサービス定義
主要設定値(monitor_zero.py)
~/scripts/monitor_zero.pyに書き込み
#!/usr/bin/env python3
# monitor_zero.py
import subprocess
import time
import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
from tapo import ApiClient # pip3 install tapo
# =====================
# === 設定エリア ===
# =====================
# --- Zero W2 ---
ZERO_IP = "192.168.11.50" # Zero W2の固定IP
ZERO_USER = "zero" # Zero W2のSSHユーザー名
# --- 監視パラメータ ---
CHECK_INTERVAL = 30 # 監視間隔(秒)
PING_TIMEOUT = 5 # pingタイムアウト(秒)
FAIL_THRESHOLD = 3 # 連続失敗回数でリカバリ開始
BOOT_WAIT_SEC = 60 # 再起動後の待機時間(秒)
POWER_OFF_SEC = 5 # 電源OFF保持時間(秒)
# --- Tapo スマートプラグ ---
TAPO_IP = "192.168.11.52" # TapoプラグのIP
TAPO_EMAIL = "your@email.com" # Tapoアカウントのメール
TAPO_PASSWORD = "your_tapo_password" # Tapoアカウントのパスワード
# --- メール通知 ---
SMTP_HOST = "smtp.gmail.com" # SMTPサーバー
SMTP_PORT = 587
SMTP_USER = "your@gmail.com" # 送信元メール
SMTP_PASSWORD = "your_app_password" # Gmailアプリパスワード
MAIL_TO = "alert@example.com" # 通知先メール
# --- ログ ---
LOG_FILE = "/home/zero/scripts/zero_monitor.log"
# =====================
logging.basicConfig(
filename=LOG_FILE,
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s'
)
def log(msg: str, level="info"):
print(f"[{datetime.now().strftime('%H:%M:%S')}] {msg}")
getattr(logging, level)(msg)
# ---------- Ping ----------
def ping(ip: str) -> bool:
result = subprocess.run(
["ping", "-c", "1", "-W", str(PING_TIMEOUT), ip],
capture_output=True
)
return result.returncode == 0
# ---------- SSH再起動 ----------
def ssh_reboot() -> bool:
try:
result = subprocess.run(
["ssh",
"-o", "ConnectTimeout=5",
"-o", "StrictHostKeyChecking=no",
f"{ZERO_USER}@{ZERO_IP}",
"sudo reboot"],
capture_output=True, timeout=10
)
return result.returncode == 0
except Exception as e:
log(f"SSH reboot失敗: {e}", "error")
return False
# ---------- Tapo電源制御 ----------
async def tapo_power_cycle():
try:
client = ApiClient(TAPO_EMAIL, TAPO_PASSWORD)
device = await client.p105(TAPO_IP) # P115の場合は p115()
log("Tapo: 電源OFF")
await device.off()
time.sleep(POWER_OFF_SEC)
log("Tapo: 電源ON")
await device.on()
return True
except Exception as e:
log(f"Tapo制御失敗: {e}", "error")
return False
# ---------- メール通知 ----------
def send_mail(subject: str, body: str):
try:
msg = MIMEMultipart()
msg["From"] = SMTP_USER
msg["To"] = MAIL_TO
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain", "utf-8"))
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
server.starttls()
server.login(SMTP_USER, SMTP_PASSWORD)
server.sendmail(SMTP_USER, MAIL_TO, msg.as_string())
log(f"メール送信成功: {subject}")
except Exception as e:
log(f"メール送信失敗: {e}", "error")
# ---------- メインループ ----------
import asyncio
async def main():
fail_count = 0
alerted = False # 連続アラートを防ぐフラグ
log("=== Zero W2 Monitor 開始 ===")
while True:
is_alive = ping(ZERO_IP)
if is_alive:
if fail_count > 0:
log(f"✅ Zero W2 復旧確認({fail_count}回失敗後)")
send_mail(
subject="✅ [ZeroW2] 復旧しました",
body=f"RaspberryPi Zero W2 が復旧しました。\n"
f"連続失敗回数: {fail_count}\n"
f"復旧時刻: {datetime.now()}"
)
alerted = False
fail_count = 0
else:
fail_count += 1
log(f"⚠️ Ping失敗 ({fail_count}/{FAIL_THRESHOLD}): {ZERO_IP}", "warning")
if fail_count >= FAIL_THRESHOLD:
log("🔴 Zero W2 ダウン検出。復旧処理を開始します", "error")
if not alerted:
send_mail(
subject="🔴 [ZeroW2] ダウン検出!復旧処理中",
body=f"RaspberryPi Zero W2 がダウンしました。\n"
f"自動復旧を試みています。\n"
f"検出時刻: {datetime.now()}\n"
f"対象IP: {ZERO_IP}"
)
alerted = True
# --- Step1: SSHで再起動を試みる ---
log("Step1: SSH reboot を試みます...")
if ssh_reboot():
log(f"SSH reboot送信成功。{BOOT_WAIT_SEC}秒待機...")
time.sleep(BOOT_WAIT_SEC)
else:
# --- Step2: SSHも失敗 → Tapoで強制電源サイクル ---
log("Step2: SSH失敗 → Tapo電源サイクルを実行します...", "warning")
send_mail(
subject="⚡ [ZeroW2] Tapo電源サイクル実行",
body=f"SSH rebootに失敗したため、\n"
f"Tapoスマートプラグで電源を再投入します。\n"
f"実行時刻: {datetime.now()}"
)
success = await tapo_power_cycle()
if success:
log(f"電源サイクル完了。{BOOT_WAIT_SEC}秒待機...")
time.sleep(BOOT_WAIT_SEC)
else:
log("❌ Tapo制御も失敗。手動対応が必要です", "error")
send_mail(
subject="❌ [ZeroW2] 自動復旧失敗!手動対応が必要",
body=f"SSH・Tapo両方の復旧に失敗しました。\n"
f"手動での確認が必要です。\n"
f"失敗時刻: {datetime.now()}"
)
fail_count = 0 # カウントリセット
await asyncio.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
asyncio.run(main())
python
ZERO_IP = "192.168.11.50" # Zero W2のIP
ZERO_USER = "zero" # Zero W2のSSHユーザー
CHECK_INTERVAL = 30 # 監視間隔(秒)
FAIL_THRESHOLD = 3 # 連続失敗回数
BOOT_WAIT_SEC = 60 # 再起動後の待機時間
TAPO_IP = "192.168.11.52" # TapoプラグのIP
SMTP_HOST = "smtp.gmail.com" # メール送信サーバー
systemdサービス(zero-monitor.service)
/etc/systemd/system/zero-monitor.service に保存
ini
[Unit]
Description=RaspberryPi Zero W2 Monitor
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/zero/scripts/monitor_zero.py
Restart=always
RestartSec=10
User=zero
WorkingDirectory=/home/zero/scripts
StandardOutput=append:/home/zero/scripts/stdout.log
StandardError=append:/home/zero/scripts/stderr.log
[Install]
WantedBy=multi-user.target
保存後(Ctrl+O → Enter → Ctrl+X):
sudo systemctl daemon-reload
sudo systemctl restart zero-monitor
sleep 10
cat ~/scripts/stderr.log
cat ~/scripts/stdout.log
セットアップ時のトラブルと解決策
| トラブル | 原因 | 解決策 |
|---|---|---|
Failed at step USER | User=piが存在しない | User=zeroに変更 |
No module named 'tapo' | ライブラリ未インストール | pip3 install tapo --break-system-packages |
PermissionError log | ログファイルの権限不足 | sudo chown -R zero:zero ~/scripts |
| Tapo接続タイムアウト | TapoのIPが間違い | 192.168.1.102→192.168.11.52に修正 |
便利なコマンド
bash
# サービス状態確認
sudo systemctl status zero-monitor
# リアルタイムログ確認
tail -f ~/scripts/zero_monitor.log
# サービス再起動
sudo systemctl restart zero-monitor
# サービス停止
sudo systemctl stop zero-monitor
# 起動時の自動起動確認
sudo systemctl is-enabled zero-monitor
動作確認済み結果
✅ Ping監視 正常動作
✅ SSH reboot試行 正常動作
✅ Tapo電源サイクル 実際にZero W2の復旧を確認
✅ メール通知 送受信確認済み
✅ systemd自動起動 有効化済み
📧 実際に
✅ [ZeroW2] 復旧しましたのログが記録され、 Tapoによる電源サイクルでZero W2が自動復旧することを確認済み。
セットアップ中にインストールしたものは以下の2つです:
インストールしたもの
1. tapo(Pythonライブラリ)
bash
pip3 install tapo --break-system-packages
TP-Link TapoスマートプラグをローカルAPIで制御するライブラリです。
2. nmap(コマンドラインツール)
bash
sudo apt install nmap -y
LAN内のデバイスIPを探すために使用しました。(Zero W2のIPアドレス特定のため)
確認コマンド
bash
# tapoの確認
pip3 show tapo
# nmapの確認
nmap --version
nmapはIPアドレス特定のために一時的に使っただけなので、不要であれば削除できます:
bash
sudo apt remove nmap -y