MENU
カテゴリー
アーカイブ

Python3でアドレス自動通知:ver2.1

ieServer はサービス終了したみたいだし、他にもいくつか自宅のグローバル IP アドレスを確認できるサイトがあるから、今まで自前チェック用に使用していた無料レンタルサーバー XFREE を退会することにして、MyDNS の自動通知スクリプトを微修正した。

ifconfig.me はアドレス取得に失敗することが多かったから ifconfig.io で様子を見てみる。ついでに wget から cURL API での取得に変更してみた。

#!/usr/bin/python3

import codecs
import datetime
import ipaddress
import os
import re
import subprocess
import sys
from datetime import datetime
from datetime import timedelta

#####///// 編集箇所 /////#####
MYPATH = "/usr/local/sbin/mydns/"               #このpythonスクリプトの配置場所
MASTER_ID = "mydns999999"                       #マスターID
PWD = "AAAaaa99999"                             #パスワード
C_CODE = "utf8"                                 #通知サイトの文字コード(utf8,eucjp等)
LOG_FILE = "update.log"                         #MYPATH内に記録します。
SAVE_IP = "saveip.txt"                          #MYPATH内に記録します。
FORCE_UPDATE_TIME = 24                          #強制通知間隔を時間単位で指定します。
LOG_FILE_SIZE = 20                              #ログファイルの記録数を指定します。
#####///// ここまで /////#####


#####///// 環境に応じて1つ有効化して下さい /////#####
#REMOTE_ADDR_CHK = "https://ifconfig.me"
REMOTE_ADDR_CHK = "https://ifconfig.io"
#REMOTE_ADDR_CHK = "https://www.cman.jp/network/support/go_access.cgi"
#####///// ここまで /////#####


### 定数を定義します。
PATTERN = "\d+\.\d+\.\d+\.\d+"
DDNS_UPDATE = "www.mydns.jp/login.html"


### 確認サイトから取得した受信データより、現在割り当てられているIPアドレスを抽出します。
current_IP = subprocess.run("curl " + REMOTE_ADDR_CHK , stdout = subprocess.PIPE , shell=True)
currIp = re.search(PATTERN,current_IP.stdout.decode("utf8"))


### ログファイルが"LOG_FILE_SIZE"行を超えていたら1行目を削除します。
if os.path.isfile(MYPATH + LOG_FILE) == True:
        line_count = int(subprocess.check_output(["wc", "-l", MYPATH + LOG_FILE]).decode().split(" ")[0])
        if (line_count >= LOG_FILE_SIZE):
                with open(MYPATH + LOG_FILE,"r") as f:
                        mylist = f.readlines()
                with open(MYPATH + LOG_FILE,"w") as f:
                        f.writelines(mylist[1:])


### IPアドレスの取得に失敗したときはログを残してプログラムを終了します。
if (currIp  and  ipaddress.ip_address(currIp.group()).version == 4):
        addr4 = currIp.group()
else:
        with open(MYPATH + LOG_FILE,"a") as f:
                line =  datetime.now().strftime("%Y/%m/%d %H:%M:%S")
                line += "\tIP Address を取得できませんでした。\n"
                f.write(line)

                ### 強制終了します。
                sys.exit()


### 直近で確認したIPアドレスを読み込みます。
line_ip = ("none")

if os.path.exists(MYPATH + SAVE_IP) == True:
        with open(MYPATH + SAVE_IP,"r") as f:
                for line_ip in f:
                        dummy = line_ip


### IPアドレス更新ログが無かったら強制通知します。
force_update = False

if os.path.isfile(MYPATH + LOG_FILE) == True:
        line_count = int(subprocess.check_output(["wc", "-l", MYPATH + LOG_FILE]).decode().split(" ")[0])
        with open(MYPATH + LOG_FILE,"r") as f:
                lines = f.readlines()
        c = 1
        while c <= line_count:
                if ("IP Address を更新しました。") in lines[line_count - c]:
                        log_date = re.match("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}",lines[line_count -c]).group()
                        break
                c += 1
        else:
                ### 更新成功ログが残っていなかった場合は強制通知フラグが立ちます。
                log_date =  "2000/01/01 00:00:00"
         

### LOG_FILEそのものが無かったら"2000/01/01 00:00:00"を書き込んでファイルを作成します。
else:
        with open(MYPATH + LOG_FILE,"w") as f:
                log_date =  "2000/01/01 00:00:00"
                f.write(log_date + "\n")
                         

### 強制通知間隔を経過したら強制通知フラグを立てます。
td = datetime.today() - datetime.strptime(log_date, "%Y/%m/%d %H:%M:%S")
time_delta = td.total_seconds() / 3600
if (time_delta >= FORCE_UPDATE_TIME):
        force_update = True


### IPアドレスの更新通知処理です。
if (addr4 != line_ip  or  force_update == True):
        cmd = "wget -q -O - '"
        cmd += "https://"
        cmd += MASTER_ID
        cmd += ":" + PWD
        cmd += "@" + DDNS_UPDATE + "'"
        ret = subprocess.run(cmd , stdout = subprocess.PIPE , shell=True)

        ### cmdの実行に成功した時の処理です。
        if ("Login and IP address notify OK.") in ret.stdout.decode(C_CODE):
                with open(MYPATH + SAVE_IP,"w") as f:
                        f.write(addr4)
                with open(MYPATH + LOG_FILE,"a") as f:
                        line =  datetime.now().strftime('%Y/%m/%d %H:%M:%S')
                        line += "\tIP Address を更新しました。[" + addr4 + "]\n"
                        f.write(line)

        ### cmdの実行に失敗した時の処理です。
        else:
                with open(MYPATH + LOG_FILE,"a") as f:
                        line =  datetime.now().strftime('%Y/%m/%d %H:%M:%S')
                        line += "\tIP Address の更新に失敗しました。\n"
                        f.write(line)

コメント

コメントする

目次