Python 路由器IP变更邮件通知
2013-06-01 19:33
603 查看
最近遇到一个问题:实验室内部的网络是通过路由器分配IP的,但是经常又需要通过校园网远程实验室内部的电脑,而路由器的外网IP是由DHCP服务器动态分配的,IP地址无法绑定成静态的。RadminViewer远程的速度比较快,但是没办法穿墙,必须知道直连的IP地址,通过在实验室的路由器上设置转发端口,就可以实现实验室内部多台电脑同时远程。但是由于路由器上IP会变,自然想到在服务器上运行一个程序,每隔一段时间监测下路由器的IP,如果变化,就发送邮件通知。
使用Python编写,由于是一个后台的程序,自然想到要做出服务,就不会有窗口一直显示。将Python程序以Windows 服务方式启动,需要用到pywin32。
本来想实现可以获取每一层的IP,因为网络可能经过了多层的IP地址转换。但还不知道怎么做,最后参考了这里的方法后,目前是只能针对TP-Link的路由器获取外网IP,其他路由器没测试过。
后面还可以进一步扩展,实现很多功能,然后可以发邮件通知。使用的时候,需要先安装服务,然后再启动。服务安装后,默认是手动启动,如果需要设置为自动启动,还需要到Windows管理工具,服务设置中,将该服务设置为自动启动。
在开发过程中,可能需要不断调试以检测是否有bug,因此可以使用调试模式,Service debug,这样可以看到print输出的内容,用于测试服务是否能正常运行。
以下是代码
这是另外一个版本,用于检测所在机器的本地IP和外网IP。
需要发送通知的邮件地址,需要以每行一个保存到当前目录下的mail.txt中,如
mail1@.gmail.com
mai2.@gmail.com
最新的本地IP地址会保存在latestIP.txt中。
IPDetector.py
IPService.py
参考资料
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
http://blog.sina.com.cn/s/blog_633b6d790100g4tu.html
使用Python编写,由于是一个后台的程序,自然想到要做出服务,就不会有窗口一直显示。将Python程序以Windows 服务方式启动,需要用到pywin32。
本来想实现可以获取每一层的IP,因为网络可能经过了多层的IP地址转换。但还不知道怎么做,最后参考了这里的方法后,目前是只能针对TP-Link的路由器获取外网IP,其他路由器没测试过。
后面还可以进一步扩展,实现很多功能,然后可以发邮件通知。使用的时候,需要先安装服务,然后再启动。服务安装后,默认是手动启动,如果需要设置为自动启动,还需要到Windows管理工具,服务设置中,将该服务设置为自动启动。
在开发过程中,可能需要不断调试以检测是否有bug,因此可以使用调试模式,Service debug,这样可以看到print输出的内容,用于测试服务是否能正常运行。
以下是代码
#-*- encoding: utf-8 -*- #Service install 安装 #Service start 启动 #Service stop 停止 #Service debug 调试 #Service remove 删除 import win32serviceutil import win32service import win32event import smtplib import time, traceback import threading import logging import win32evtlogutil class Service(win32serviceutil.ServiceFramework): _svc_name_ = "IPDetector" _svc_display_name_ = "IPDetector" _svc_description_ = "Detect the change status of router IP, and send mail to notify user." _svc_deps_ = ["EventLog"] _sleep_time_ = 20 * 60 #时间以秒为单位 _username_ = 'admin'#路由器用户名 _password_ = 'admin'#路由器密码 _routerIP_ = '192.168.1.1'#路由器内部IP _mail_list_ = [ "mail1@qq.com", "mail2@qq.com" ] _currentIP_ = '' def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) print u'Service is running...' def SvcDoRun(self): import servicemanager timer = threading.Timer(self._sleep_time_, self.process()) timer.start() # Write a 'started' event to the event log... win32evtlogutil.ReportEvent(self._svc_name_, servicemanager.PYS_SERVICE_STARTED, 0, # category servicemanager.EVENTLOG_INFORMATION_TYPE, (self._svc_name_, '')) # wait for beeing stopped... win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) # and write a 'stopped' event to the event log. win32evtlogutil.ReportEvent(self._svc_name_, servicemanager.PYS_SERVICE_STOPPED, 0, # category servicemanager.EVENTLOG_INFORMATION_TYPE, (self._svc_name_, '')) return def SvcStop(self): # Before we do anything, tell SCM we are starting the stop process. self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # And set my event win32event.SetEvent(self.hWaitStop) return def send_mail(self, mail_list, msg): try: handle = smtplib.SMTP('smtp.163.com', 25) handle.login('mail@163.com','password') for mail in mail_list: send_msg = "To:" + mail + "\r\nFrom:mail@163.com\r\nSubject: The latest router IP \r\n\r\n"\ + msg +"\r\n" handle.sendmail('mail@163.com', mail, send_msg) handle.close() return True except: print traceback.format_exc() return False def getRouterPublicIP(self, username, password, routerIP): # this provide a way to get public ip address from tp-link import httplib, re, base64 showErrorMessage = 0 # 192.168.1.1 conn = httplib.HTTPConnection(routerIP) # set request headers headers = {"User-Agent": "python host", "Content-type": "application/x-www-form-urlencoded", "Authorization": "Basic %s" % base64.encodestring('%s:%s' % (username, password))[:-1], "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-cn,zh;q=0.5", "Accept-Encoding": "gzip, deflate", "Accept-Charset": "GB2312,utf-8;q=0.7,*;q=0.7", "Connection": "keep-alive"} # get status page conn.request("GET", "/userRpm/StatusRpm.htm", "", headers) response = conn.getresponse() keyword = re.search(' wanPara [^\)]*?\)', response.read()) response.close() conn.close() # search the public ip address found = 0 publicIP = "" if keyword: arr = re.findall('([\d]*?,)|(\"[^\"]*?\",)', keyword.group(0)) if arr: if len(arr) > 3: publicIP = re.search('(?<=\")[^\"]*?(?=\")', arr[2][1]) if publicIP: publicIP = publicIP.group(0) found = 1 if found == 1: return publicIP else: if showErrorMessage == 1: logging.info('router public ip address not found.') #print "router public ip address not found." def process(self): latestIP = self.getRouterPublicIP(self._username_, self._password_, self._routerIP_) logging.info('the latest router ip is: ' + latestIP) #print 'the latest router ip is: ' + latestIP if self._currentIP_ != latestIP: _currentIP_ = latestIP msg = u'The latest router IP is: ' + str(_currentIP_) print time.strftime('%Y-%m-%d %X',time.localtime(time.time())) if self.send_mail(self._mail_list_, msg): logging.info('send mail success') #print 'send mail success' else: #print 'send mail failed' logging.info('send mail failed') if __name__ == '__main__': win32serviceutil.HandleCommandLine(Service)
这是另外一个版本,用于检测所在机器的本地IP和外网IP。
需要发送通知的邮件地址,需要以每行一个保存到当前目录下的mail.txt中,如
mail1@.gmail.com
mai2.@gmail.com
最新的本地IP地址会保存在latestIP.txt中。
IPDetector.py
#-*- encoding: utf-8 -*- ''' Created on 13-5-31 ''' import smtplib import time, traceback, sys, os from email.mime.text import MIMEText class IPDetector(): def __init__(self): pass def send_mail(self, subject, content): try: handle = smtplib.SMTP('smtp.163.com', 25) handle.login('mail@163.com', 'password') mail_list = self.getMailList() time_str = time.strftime('%Y-%m-%d %X', time.localtime(time.time())) msg = '<html><body>' + content + "<br><br><span style='color:#999;font-size:"\ + "10px;font-family:Verdana;'>" \ + time_str + " by servme</span>"+'</body></html>' send_msg = MIMEText(msg, 'html', 'utf-8') send_msg['Subject'] = subject for mail in mail_list: handle.sendmail('servme@163.com', mail, send_msg.as_string()) handle.close() return True except: print traceback.format_exc() return False #读写最新IP信息的文件 def operIPFile(self, mode, data): #获取脚本路径 path = sys.path[0] #判断为脚本文件还是py2exe编译后的文件,如果是脚本文件,则返回的是脚本的目录, #如果是py2exe编译后的文件,则返回的是编译后的文件路径 if os.path.isfile(path): path = os.path.dirname(path) if mode == 'read': file = open(path + u'\latestIP.txt') line = file.readline() file.close() return line else: file = open(path + u'\latestIP.txt', 'w') file.write(data) def getMailList(self): mailList = [] #获取脚本路径 path = sys.path[0] #判断为脚本文件还是py2exe编译后的文件,如果是脚本文件,则返回的是脚本的目录, #如果是py2exe编译后的文件,则返回的是编译后的文件路径 if os.path.isfile(path): path = os.path.dirname(path) file = open(path + u'\mail.txt') while 1: line = file.readline() if not line: break mailList.append(line) file.close() return mailList def getLocalPCIP(self): import socket localIP = socket.gethostbyname(socket.gethostname()) #得到本地ip print localIP import re, urllib2 #获取外网IP class GetExtIP: def getIP(self): try: extIP = self.visit("http://www.ip138.com/ip2city.asp") except: try: extIP = self.visit("http://www.bliao.com/ip.phtml") except: try: extIP = self.visit("http://www.whereismyip.com/") except: extIP = "So sorry!!!" return extIP def visit(self, url): opener = urllib2.urlopen(url) if url == opener.geturl(): str = opener.read() else: str = '' return re.search('\d+\.\d+\.\d+\.\d+', str).group(0) externalIP = GetExtIP().getIP() print externalIP return localIP, externalIP #取本地IP def process(self): localIP, externalIP = self.getLocalPCIP() currentIP = self.operIPFile('read', None) if currentIP != localIP: self.operIPFile('write', localIP) time_str = time.strftime('%Y-%m-%d %X', time.localtime(time.time())) import socket hostname = socket.gethostname() print hostname content = 'Host Name: '+ hostname + '<br>' \ + 'Local IP address: ' + localIP + '<br>' \ + 'External IP address: ' + externalIP + '<br>' subject = "The IP address of " + hostname + " has Changed" if self.send_mail(subject, content): print time_str + ' send mail success' else: print time_str + ' send mail failed' else: print 'The IP address is same with the last detection' if __name__=='__main__': ipDetector = IPDetector() sleep_time = 20 * 60 #时间以秒为单位 while True: ipDetector.process() time.sleep(sleep_time)
IPService.py
#-*- encoding: utf-8 -*- ''' Created on 13-6-1 ''' #IPService install 安装 #IPService start 启动 #IPService stop 停止 #IPService debug 调试 #IPService remove 删除 import win32serviceutil import win32service import win32event import threading import win32evtlogutil import time class Service(win32serviceutil.ServiceFramework): _svc_name_ = "IPDetector" _svc_display_name_ = "IPDetector" _svc_description_ = "Detect the change status of IP, and send mail to notify user." _svc_deps_ = ["EventLog"] _sleep_time_ = 20 * 60 #时间以秒为单位 def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) print 'Service is running...' def SvcDoRun(self): # import servicemanager # from IPDetector import IPDetector # ipDetector = IPDetector() # timer = threading.Timer(self._sleep_time_, ipDetector.process()) # timer.start() # # # Write a 'started' event to the event log... # win32evtlogutil.ReportEvent(self._svc_name_, # servicemanager.PYS_SERVICE_STARTED, # 0, # category # servicemanager.EVENTLOG_INFORMATION_TYPE, # (self._svc_name_, '')) # # # wait for beeing stopped... # win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) # # # and write a 'stopped' event to the event log. # win32evtlogutil.ReportEvent(self._svc_name_, # servicemanager.PYS_SERVICE_STOPPED, # 0, # category # servicemanager.EVENTLOG_INFORMATION_TYPE, # (self._svc_name_, '')) #---------------------------------------------------------------- import servicemanager # Make entry in the event log that this service started servicemanager.LogMsg( servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '') ) from IPDetector import IPDetector ipDetector = IPDetector() # Set an amount of time to wait (in milliseconds) between runs self.timeout = 100 while 1: # Wait for service stop signal, if I timeout, loop again rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout) # Check to see if self.hWaitStop happened if rc == win32event.WAIT_OBJECT_0: # Stop signal encountered break else: # Put your code here ipDetector.process() time.sleep(self._sleep_time_) # Only return from SvcDoRun when you wish to stop return #----------------------------------------------------------------- def SvcStop(self): # Before we do anything, tell SCM we are starting the stop process. self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # And set my event win32event.SetEvent(self.hWaitStop) if __name__ == '__main__': 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
http://blog.sina.com.cn/s/blog_633b6d790100g4tu.html
相关文章推荐
- ***路由器备份/变更时的邮件通知
- Python邮件通知本地外网IP
- 【python】获取本机局域网IP并发送邮件到指定邮箱
- python随机服务器的双线出口ip发送邮件
- Python3判断shell下进程是否存在&&启动&&邮件通知
- Windows SVN变更发送邮件通知(JAVA实现)
- python3 自动获取公网ip并发送邮件通知
- [Python] 爬绿盟官网漏洞列表并存储MySQL与邮件通知
- Windows SVN变更发送邮件通知(JAVA实现)
- 当路由器外网IP变更时,执行操作
- Python打造刷火车票工具邮件通知自己
- 广州.NET 俱乐部联系邮件变更通知
- python获取外网IP并发邮件
- python实现用户登陆邮件通知的方法
- python3.4获取网站40x 50x错误并发邮件通知
- python获取外网IP并发邮件的实现方法
- Postfix配置自动通知客户邮件地址已经变更
- ubuntu10.10 通过hooks和mailer.py发送svn变更通知邮件
- Windows下利用Python动态检测外网IP并发邮件给邮箱
- python实现用户登陆邮件通知的方法