Python 路由器IP变革邮件通知
添加时间:2013-6-1 点击量:
比来碰到一个题目:实验室内部的收集是经由过程路由器分派IP的,然则经常又须要经由过程校园网长途实验室内部的电脑,而路由器的外网IP是由DHCP办事器动态分派的,IP地址无法绑定成静态的。RadminViewer长途的速度斗劲快,然则没办法穿墙,必须知道直连的IP地址,经由过程在实验室的路由器上设置转发端口,就可以实实际验室内部多台电脑同时长途。然则因为路由器上IP会变,天然想到在办事器上运行一个法度,每隔一段时候监测下路由器的IP,若是变更,就发送邮件通知。
应用Python编写,因为是一个后台的法度,天然想到要做出办事,就不会有窗口一向显示。将Python法度以Windows 办事体式格式启动,须要用到pywin32。
底本想实现可以获取每一层的IP,因为收集可能经过了多层的IP地址转换。但还不知道怎么做,最后参考了这里的办法后,今朝是只能针对TP-Link的路由器获取外网IP,其他路由器没测试过。
后面还可以进一步扩大,实现很多功能,然后可以发邮件通知。应用的时辰,须要先安装办事,然后再启动。办事安装后,默认是手动启动,若是须要设置为主动启动,还须要到Windows经管对象,办事设置中,将该办事设置为主动启动。
1 #-- encoding: utf-8 --
2
3 #Service install 安装
4 #Service start 启动
5 #Service stop 停止
6 #Service debug 调试
7 #Service remove 删除
8
9 import win32serviceutil
10 import win32service
11 import win32event
12 import smtplib
13 import time, traceback
14 import threading
15 import logging
16 import win32evtlogutil
17
18 class Service(win32serviceutil.ServiceFramework):
19 _svc_name_ = IPDetector
20 _svc_display_name_ = IPDetector
21 _svc_description_ = Detect the change status of router IP, and send mail to notify user.
22 _svc_deps_ = [EventLog]
23 _sleep_time_ = 20 60 #时候以秒为单位
24 _username_ = admin#路由器用户名
25 _password_ = admin#路由器暗码
26 _routerIP_ = 192.168.1.1#路由器内部IP
27 _mail_list_ = [
28 mail1@qq.com,
29 mail2@qq.com
30 ]
31 _currentIP_ =
32
33 def __init__(self, args):
34 win32serviceutil.ServiceFramework.__init__(self, args)
35 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
36 print uService is running...
37
38 def SvcDoRun(self):
39 import servicemanager
40 timer = threading.Timer(self._sleep_time_, self.process())
41 timer.start()
42 # Write a started event to the event log...
43 win32evtlogutil.ReportEvent(self._svc_name_,
44 servicemanager.PYS_SERVICE_STARTED,
45 0, # category
46 servicemanager.EVENTLOG_INFORMATION_TYPE,
47 (self._svc_name_, ))
48 # wait for beeing stopped...
49 win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
50
51 # and write a stopped event to the event log.
52 win32evtlogutil.ReportEvent(self._svc_name_,
53 servicemanager.PYS_SERVICE_STOPPED,
54 0, # category
55 servicemanager.EVENTLOG_INFORMATION_TYPE,
56 (self._svc_name_, ))
57 return
58
59 def SvcStop(self):
60 # Before we do anything, tell SCM we are starting the stop process.
61 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
62 # And set my event
63 win32event.SetEvent(self.hWaitStop)
64 return
65
66 def send_mail(self, mail_list, msg):
67 try:
68 handle = smtplib.SMTP(smtp.163.com, 25)
69 handle.login(mail@163.com,password)
70 for mail in mail_list:
71 send_msg = To: + mail + \r\nFrom:mail@163.com\r\nSubject: The latest router IP \r\n\r\n 72 + msg +\r\n
73 handle.sendmail(mail@163.com, mail, send_msg)
74 handle.close()
75 return True
76 except:
77 print traceback.format_exc()
78 return False
79
80 def getRouterPublicIP(self, username, password, routerIP):
81 # this provide a way to get public ip address tp-link
82 import httplib, re, base64
83 showErrorMessage = 0
84
85 # 192.168.1.1
86 conn = httplib.HTTPConnection(routerIP)
87 # set request headers
88 headers = {User-Agent: python host,
89 Content-type: application/x-www-form-urlencoded,
90 Authorization: Basic %s % base64.encodestring(%s:%s % (username, password))[:-1],
91 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8,
92 Accept-Language: zh-cn,zh;q=0.5,
93 Accept-Encoding: gzip, deflate,
94 Accept-Charset: GB2312,utf-8;q=0.7,;q=0.7,
95 Connection: keep-alive}
96
97 # get status page
98 conn.request(GET, /userRpm/StatusRpm.htm, , headers)
99 response = conn.getresponse()
100 keyword = re.search( wanPara [^\)]?\), response.read())
101 response.close()
102 conn.close()
103
104 # search the public ip address
105 found = 0
106 publicIP =
107 if keyword:
108 arr = re.findall(([\d]?,)|(\[^\]?\,), keyword.group(0))
109 if arr:
110 if len(arr) > 3:
111 publicIP = re.search((?<=\)[^\]?(?=\), arr[2][1])
112 if publicIP:
113 publicIP = publicIP.group(0)
114 found = 1
115
116 if found == 1:
117 return publicIP
118 else:
119 if showErrorMessage == 1:
120 logging.info(router public ip address not found.)
121 #print router public ip address not found.
122
123 def process(self):
124 latestIP = self.getRouterPublicIP(self._username_, self._password_, self._routerIP_)
125 logging.info(the latest router ip is: + latestIP)
126 #print the latest router ip is: + latestIP
127 if self._currentIP_ != latestIP:
128 _currentIP_ = latestIP
129 msg = uThe latest router IP is: + str(_currentIP_)
130 print time.strftime(%Y-%m-%d %X,time.localtime(time.time()))
131 if self.send_mail(self._mail_list_, msg):
132 logging.info(send mail success)
133 #print send mail success
134 else:
135 #print send mail failed
136 logging.info(send mail failed)
137
138 if __name__ == __main__:
139 win32serviceutil.HandleCommandLine(Service)
参考材料
http://www.cnblogs.com/talywy/archive/2013/03/07/SynctimeTool.html
http://www.oschina.net/code/snippet_244244_9744
http://blog.csdn.net/verysmall/article/details/7161256
我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》
比来碰到一个题目:实验室内部的收集是经由过程路由器分派IP的,然则经常又须要经由过程校园网长途实验室内部的电脑,而路由器的外网IP是由DHCP办事器动态分派的,IP地址无法绑定成静态的。RadminViewer长途的速度斗劲快,然则没办法穿墙,必须知道直连的IP地址,经由过程在实验室的路由器上设置转发端口,就可以实实际验室内部多台电脑同时长途。然则因为路由器上IP会变,天然想到在办事器上运行一个法度,每隔一段时候监测下路由器的IP,若是变更,就发送邮件通知。
应用Python编写,因为是一个后台的法度,天然想到要做出办事,就不会有窗口一向显示。将Python法度以Windows 办事体式格式启动,须要用到pywin32。
底本想实现可以获取每一层的IP,因为收集可能经过了多层的IP地址转换。但还不知道怎么做,最后参考了这里的办法后,今朝是只能针对TP-Link的路由器获取外网IP,其他路由器没测试过。
后面还可以进一步扩大,实现很多功能,然后可以发邮件通知。应用的时辰,须要先安装办事,然后再启动。办事安装后,默认是手动启动,若是须要设置为主动启动,还须要到Windows经管对象,办事设置中,将该办事设置为主动启动。
1 #-- encoding: utf-8 --
2
3 #Service install 安装
4 #Service start 启动
5 #Service stop 停止
6 #Service debug 调试
7 #Service remove 删除
8
9 import win32serviceutil
10 import win32service
11 import win32event
12 import smtplib
13 import time, traceback
14 import threading
15 import logging
16 import win32evtlogutil
17
18 class Service(win32serviceutil.ServiceFramework):
19 _svc_name_ = IPDetector
20 _svc_display_name_ = IPDetector
21 _svc_description_ = Detect the change status of router IP, and send mail to notify user.
22 _svc_deps_ = [EventLog]
23 _sleep_time_ = 20 60 #时候以秒为单位
24 _username_ = admin#路由器用户名
25 _password_ = admin#路由器暗码
26 _routerIP_ = 192.168.1.1#路由器内部IP
27 _mail_list_ = [
28 mail1@qq.com,
29 mail2@qq.com
30 ]
31 _currentIP_ =
32
33 def __init__(self, args):
34 win32serviceutil.ServiceFramework.__init__(self, args)
35 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
36 print uService is running...
37
38 def SvcDoRun(self):
39 import servicemanager
40 timer = threading.Timer(self._sleep_time_, self.process())
41 timer.start()
42 # Write a started event to the event log...
43 win32evtlogutil.ReportEvent(self._svc_name_,
44 servicemanager.PYS_SERVICE_STARTED,
45 0, # category
46 servicemanager.EVENTLOG_INFORMATION_TYPE,
47 (self._svc_name_, ))
48 # wait for beeing stopped...
49 win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
50
51 # and write a stopped event to the event log.
52 win32evtlogutil.ReportEvent(self._svc_name_,
53 servicemanager.PYS_SERVICE_STOPPED,
54 0, # category
55 servicemanager.EVENTLOG_INFORMATION_TYPE,
56 (self._svc_name_, ))
57 return
58
59 def SvcStop(self):
60 # Before we do anything, tell SCM we are starting the stop process.
61 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
62 # And set my event
63 win32event.SetEvent(self.hWaitStop)
64 return
65
66 def send_mail(self, mail_list, msg):
67 try:
68 handle = smtplib.SMTP(smtp.163.com, 25)
69 handle.login(mail@163.com,password)
70 for mail in mail_list:
71 send_msg = To: + mail + \r\nFrom:mail@163.com\r\nSubject: The latest router IP \r\n\r\n 72 + msg +\r\n
73 handle.sendmail(mail@163.com, mail, send_msg)
74 handle.close()
75 return True
76 except:
77 print traceback.format_exc()
78 return False
79
80 def getRouterPublicIP(self, username, password, routerIP):
81 # this provide a way to get public ip address tp-link
82 import httplib, re, base64
83 showErrorMessage = 0
84
85 # 192.168.1.1
86 conn = httplib.HTTPConnection(routerIP)
87 # set request headers
88 headers = {User-Agent: python host,
89 Content-type: application/x-www-form-urlencoded,
90 Authorization: Basic %s % base64.encodestring(%s:%s % (username, password))[:-1],
91 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8,
92 Accept-Language: zh-cn,zh;q=0.5,
93 Accept-Encoding: gzip, deflate,
94 Accept-Charset: GB2312,utf-8;q=0.7,;q=0.7,
95 Connection: keep-alive}
96
97 # get status page
98 conn.request(GET, /userRpm/StatusRpm.htm, , headers)
99 response = conn.getresponse()
100 keyword = re.search( wanPara [^\)]?\), response.read())
101 response.close()
102 conn.close()
103
104 # search the public ip address
105 found = 0
106 publicIP =
107 if keyword:
108 arr = re.findall(([\d]?,)|(\[^\]?\,), keyword.group(0))
109 if arr:
110 if len(arr) > 3:
111 publicIP = re.search((?<=\)[^\]?(?=\), arr[2][1])
112 if publicIP:
113 publicIP = publicIP.group(0)
114 found = 1
115
116 if found == 1:
117 return publicIP
118 else:
119 if showErrorMessage == 1:
120 logging.info(router public ip address not found.)
121 #print router public ip address not found.
122
123 def process(self):
124 latestIP = self.getRouterPublicIP(self._username_, self._password_, self._routerIP_)
125 logging.info(the latest router ip is: + latestIP)
126 #print the latest router ip is: + latestIP
127 if self._currentIP_ != latestIP:
128 _currentIP_ = latestIP
129 msg = uThe latest router IP is: + str(_currentIP_)
130 print time.strftime(%Y-%m-%d %X,time.localtime(time.time()))
131 if self.send_mail(self._mail_list_, msg):
132 logging.info(send mail success)
133 #print send mail success
134 else:
135 #print send mail failed
136 logging.info(send mail failed)
137
138 if __name__ == __main__:
139 win32serviceutil.HandleCommandLine(Service)
参考材料
http://www.cnblogs.com/talywy/archive/2013/03/07/SynctimeTool.html
http://www.oschina.net/code/snippet_244244_9744
http://blog.csdn.net/verysmall/article/details/7161256
我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》