「深夜のサーバーダウン」という悪夢
Webアプリやボットを動かしているVPSをいくつか管理していますか?朝起きたらサービスが完全に停止していた、という経験は誰にでもあるはずです。顧客からのクレーム、上司からの呼び出し。そして原因を調べてみれば、ディスク容量がいっぱいだったり、特定のプロセスがRAMを使い果たしてフリーズしていたりといった、実にあっけないものだったりします。
大量のエラー通知とともに目が覚めるのは、まさに悪夢です。実際、リソースの状態を事前に把握していれば、こうした事態は防げます。1時間おきに手動でサーバーにSSH接続してtopやdf -hを叩く代わりに、Pythonにその役目を任せましょう。わずか15分のセットアップで、システムに異変があればすぐにDiscordで知らせてくれる、忠実な「門番」を手に入れることができます。
本格的なツールか、それともPythonか?
コードを書き始める前に、現在の監視ソリューションをいくつか見てみましょう。適切なツールを選ぶことで、時間とコストの両方を節約できます。
一般的な監視方法の比較
- 専用ツール (Prometheus, Zabbix): これらは真の「怪物」です。強力でグラフも美しいですが、リソースを非常に消費します。1GB RAMのVPSにPrometheus + Grafana(通常200-400MB RAMを占有)を載せるのは、自分を苦しめているようなものです。
- クラウドサービス (Datadog, New Relic): 機能は非常に優れています。しかし、月額料金がサーバーのレンタル費用よりも高くなることもあります。
- 自作Pythonスクリプト: スタートアップや個人サーバーに最適な選択です。超軽量(わずか15-20MB程度のRAM消費)、100%カスタマイズ可能、そして完全に無料です。
以下の比較表を参考に判断してください:
| 項目 | Zabbix/Prometheus | Pythonスクリプト |
|---|---|---|
| RAM消費量 | ~300MB以上 | < 20MB |
| デプロイ | 複雑 | 非常に早い |
| コスト | 無料/有料 | 0円 |
なぜDiscord Webhookなのか?
メールは遅く、スパムフォルダに入りやすいです。Telegramは一部の地域で接続に問題が発生することがあります。一方、Discordは非常に柔軟なWebhookの仕組みを提供しています。JSONを含むPOSTリクエストを所定のURLに送信するだけで完了です。メッセージはプロフェッショナルなRich Embed形式で即座に表示され、色によって警告の深刻度を明確に区別できます。
3ステップで監視スクリプトを構築する
開始するには、サーバーにPython 3が必要です。システム情報の取得にはpsutilを、Discordへのデータ送信にはrequestsを使用します。
ステップ1: ライブラリのインストール
サーバーのターミナルで以下のコマンドを実行します:
pip install psutil requests
ステップ2: Webhook URLの取得
- Discordを開き、サーバー設定 -> 連携 に移動します。
- Webhook -> 新しいWebhook を選択します。
- ボットの名前(例:「Sentry Bot」)を設定し、URLをコピーします。このURLは秘密にしておいてください!
ステップ3: 処理ロジックの作成
以下のスクリプトはCPU、RAM、ディスクをチェックします。いずれかの数値が安全なしきい値を超えると、アラートをトリガーします。
import psutil
import requests
import socket
from datetime import datetime
# 警告しきい値の設定
DISCORD_WEBHOOK_URL = "YOUR_WEBHOOK_URL_HERE"
CPU_THRESHOLD = 80 # CPUが80%を超えたら警告
RAM_THRESHOLD = 85 # RAMが85%を超えたら警告
DISK_THRESHOLD = 90 # ディスクが90%を超えたら警告
def get_system_status():
hostname = socket.gethostname()
# 正確な数値を得るために1秒間のCPU平均を取得
cpu_usage = psutil.cpu_percent(interval=1)
ram_usage = psutil.virtual_memory().percent
disk_usage = psutil.disk_usage('/').percent
return hostname, cpu_usage, ram_usage, disk_usage
def send_discord_alert(hostname, cpu, ram, disk):
payload = {
"embeds": [{
"title": f"🚨 リソース警告: {hostname}",
"color": 15158332, # 赤色
"fields": [
{"name": "CPU", "value": f"{cpu}%", "inline": True},
{"name": "RAM", "value": f"{ram}%", "inline": True},
{"name": "Disk", "value": f"{disk}%", "inline": True},
],
"footer": {"text": f"記録時刻: {datetime.now().strftime('%H:%M:%S %Y-%m-%d')}"}
}]
}
requests.post(DISCORD_WEBHOOK_URL, json=payload)
def main():
hostname, cpu, ram, disk = get_system_status()
if cpu > CPU_THRESHOLD or ram > RAM_THRESHOLD or disk > DISK_THRESHOLD:
send_discord_alert(hostname, cpu, ram, disk)
else:
print(f"システム正常: CPU {cpu}% | RAM {ram}% | Disk {disk}%")
if __name__ == "__main__":
main()
Crontabによる自動化
スクリプトは完成しましたが、まさか手動で実行し続けるわけにはいきません。5分ごとに自動実行させるために、Linuxの定番スケジューリングツールである Crontab を使用します。
crontab -e を入力し、ファイルの末尾に以下の行を追加します:
*/5 * * * * /usr/bin/python3 /home/user/monitor.py >> /var/log/monitor.log 2>&1
注意:Cron実行時の環境エラーを避けるため、絶対パス(例:/usr/bin/python3)を使用することをお勧めします。
スクリプトをより「賢く」するための実践的なアドバイス
実際のサーバー群で運用してみた経験から、いくつかのアドバイスがあります:
- スパム防止: CPUが連続して90%に張り付いている場合、Discordの通知が爆発してしまいます。状態が「正常」から「警告」に変わったときだけメッセージを送信するようにコードを修正しましょう。
- OOM Killerの監視: RAMがいっぱいになると、Linuxは重いプロセス(MySQLなど)を強制終了させることがあります。
psutil.process_iter()を追加して、重要なサービスが生きているかチェックする機能を追加しても良いでしょう。 - すべてをログに記録する: 常にログをファイルに書き出してください。サーバーが本当にダウンしたとき、これらのログは午前2時に何が起きたかを知るための唯一の手がかりになります。
自前で監視ツールを構築することは、安心感を得られるだけでなく、DevOps的な思考を鍛える良い訓練にもなります。サーバーの突然の「心停止」を心配することなく、ぐっすり眠れる夜を過ごせるよう願っています!

