pythonで外形監視とSSL証明書の有効期限を監視を監視してみた
サービスを使うのが確実だけど、個人用途なのでサクッと作って Line で通知してみました。
必要なのは python と env 読み込み用のパッケージ。
- LINE Notify でトークン払い出し
- LINE Notifyにアクセス
- 登録サービス管理からサービスを登録するとトークンが払い出されるのでメモする
- 必要パッケージのインストール
トークンとか設定値は外だしするので下記パッケージをインストール
pip install python-dotenv
- .env ファイルの設定
MONITOR_SITE は複数サイト監視する場合は,で区切る
LINE_TOKEN=YOUR_LINE_NOTIFY_TOKEN
LINE_NOTIFY_API=https://notify-api.line.me/api/notify
MONITOR_SITES=hoge1.jp,hoge2.net,hoge3.com
SSL_EXPIRY_DAYS=30
- 実行と登録
試しに、サイトを停止した上でスクリプトを実行し、Line へ通知がくれば OK。
ログはスクリプトと同じディレクトリに monitoring.log に出力されます。
python script.py
cron で実行登録。実行間隔はお好みで(下記は5分ごと)
*/5 * * * * /usr/bin/python3 /path/to/your/script.py
python コード
from datetime import datetime
import os
from dotenv import load_dotenv
import pytz
import ssl
import socket
import requests
import logging
# .env ファイルから環境変数を読み込む
load_dotenv()
# 環境変数の取得
LINE_TOKEN = os.getenv("LINE_TOKEN")
LINE_NOTIFY_API = os.getenv("LINE_NOTIFY_API")
MONITOR_SITES = os.getenv("MONITOR_SITES").split(',')
SSL_EXPIRY_DAYS = int(os.getenv("SSL_EXPIRY_DAYS"))
# ロギング設定
logging.basicConfig(level=logging.INFO, filename='monitoring.log')
# LINEにメッセージを送る関数
def send_line_message(message):
headers = {"Authorization": f"Bearer {LINE_TOKEN}"}
payload = {"message": message}
requests.post(LINE_NOTIFY_API, headers=headers, data=payload)
# SSL証明書の残り日数を取得
def get_remaining_days(hostname):
context = ssl.create_default_context()
conn = context.wrap_socket(socket.socket(socket.AF_INET),
server_hostname=hostname)
conn.connect((hostname, 443))
cert = conn.getpeercert()
not_after = datetime.strptime(cert['notAfter'], r"%b %d %H:%M:%S %Y %Z").replace(tzinfo=pytz.UTC)
tz = pytz.timezone('Asia/Tokyo')
now_aware = datetime.now().astimezone(tz)
remaining = (not_after.astimezone(tz) - now_aware).days
conn.close()
return remaining
# サイトをチェックする関数
def check_sites():
for site in MONITOR_SITES:
try:
# ステータスコードのチェック
response = requests.get(f"https://{site}")
if response.status_code != 200:
send_line_message(f"Status code error: {site} returned {response.status_code}")
logging.error(f"{datetime.now()} - Status code error: {site} returned {response.status_code}")
# SSL証明書の有効期限をチェック
remaining = get_remaining_days(site)
if remaining <= SSL_EXPIRY_DAYS:
send_line_message(f"SSL certificate alert: {site} will expire in {remaining} days")
logging.warning(f"{datetime.now()} - SSL certificate alert: {site} will expire in {remaining} days")
except Exception as e:
send_line_message(f"An error occurred with {site}: {str(e)}")
logging.error(f"{datetime.now()} - An error occurred with {site}: {str(e)}")
if __name__ == "__main__":
check_sites()