python2写ping监控,自动发现ip

玩了hostmonitor,老外写的很好。但是不符合国情,只有邮件适合发送。

今天用python 写一个自动发现ip,ping失败报警的程序。(微信和邮件报警)

以前用python写的发微信,发邮件直接导入即可。

# -*- coding: utf-8 -*-
# ping for Windows

import os
import sys
import socket
import struct
import select
import time
import ConfigParser
import weixin
import mail

class getcfg(object):
	def __init__(self,filename):
		self.filename=filename
		self.cfg=ConfigParser.ConfigParser()
		self.cfg.read(self.filename)
		#self.allip=self.cfg.items('allip')
		self.retry=self.cfg.get('rule','retry')
		self.timeout=self.cfg.get('rule','timeout')
		self.reload=self.cfg.get('rule','next_check')
		self.scan=self.cfg.items('scan_network')
		self.mailto=self.cfg.items('mail','mail_to')
	
	#发送邮件报警
	def sendmessage(self,failip):
		weixin.sendMessage('@all','ping %s failed.'% failip)
		for key,value in self.mailto:
			mail.send(value,"ping %s failed." % failip,'python ping fail')
			
	#判断要扫描ip
	def scan_network(self):
		self.scan.sort()
		allip=self.cfg.items('allip')
		i=0
		while i < len(self.scan):
			ipbegin=int(self.scan[i][1].split('.')[-1])
			ipend=int(self.scan[i+1][1])+1
			for x in range(ipbegin,ipend):
				ipvalue=self.scan[i][1].split('.')[0]+'.'+self.scan[i][1].split('.')[1]+'.'+self.scan[i][1].split('.')[2]+'.'+str(x)
				ip_dict=[]
				for k,v in allip:
					ip_dict.append(v)
				if ipvalue in ip_dict:
					pass
				else:
					#执行扫描
					self.to_ping(ipvalue,int(self.timeout))
			i=i+2
	
	#执行扫描
	def to_ping(self,ip_addr,timeout):
		print 'scan ip ' + ip_addr,
		try:
			delay = ping(self.filename).ping_once(ip_addr, timeout)
			if delay == None:
				print 'failed. (timeout within %s second.)' % timeout
			else:
				print 'get reply in %0.4f ms' % (delay * 1000)
				self.scan_resule(ip_addr)
		except socket.gaierror, e:
			print "failed. (socket error: '%s')" % e[1]
	
	#判断扫描结果,如果有新扫描到的ip则保存到配置文件
	def scan_resule(self,ip_addr):
		allip=self.cfg.items('allip')
		ip_dict=[]
		for k,v in allip:
			ip_dict.append(v)
		if ip_addr in ip_dict:
			pass
		else:
			self.cfg_write(ip_addr)
	
	#保存扫描到的ip到配置文件
	def cfg_write(self,ipvalue):
		ipkey='auto_'+str(time.time())
		self.cfg.set('allip',ipkey,ipvalue)
		self.cfg.write(open('ping_monitor.txt','w'))
		
	#去执行ping类
	def to_ping(self):
		allip=self.cfg.items('allip')
		for k,v in allip:
			if len(v) >0:
				ping(self.filename).icmp_ping(v,int(self.timeout),int(self.retry))

	#下次执行扫描时间
	def next_check(self):
		while True:
			self.to_ping()
			print('------------------------------------------------------------')
			nextcheck=0
			while nextcheck < int(self.reload):
				sys.stdout.write('next check %s second
' % (int(self.reload)-nextcheck))
				sys.stdout.flush()
				time.sleep(1)
				nextcheck=nextcheck+1
			self.scan_network()
			print('------------------------------------------------------------')
			

class ping(object):
	def __init__(self,filename):
		self.ICMP_ECHO_REQUEST = 8
		self.filename=filename

	def receive_ping(self,my_socket, ID, timeout):
		start_time = timeout
		while True:
			start_select = time.clock()
			what_ready = select.select([my_socket], [], [], start_time)
			how_long = (time.clock() - start_select)
			if what_ready[0] == []: #timeout
				return

			time_received = time.clock()
			rec_packet, addr = my_socket.recvfrom(1024)
			icmp_header = rec_packet[20 : 28]
			ip_type, code, checksum, packet_ID, sequence = struct.unpack("bbHHh", icmp_header)
			if ip_type != 8 and packet_ID == ID: # ip_type should be 0
				byte_in_double = struct.calcsize("d")
				time_sent = struct.unpack("d", rec_packet[28 : 28 + byte_in_double])[0]
				return time_received - time_sent

			start_time = start_time - how_long
			if start_time <= 0:
				return


	def get_checksum(self,source):
		checksum = 0
		count = (len(source) / 2) * 2
		i = 0
		while i < count:
			temp = ord(source[i + 1]) * 256 + ord(source[i]) # 256 = 2^8
			checksum = checksum + temp
			checksum = checksum & 0xffffffff # 4,294,967,296 (2^32)
			i = i + 2

		if i < len(source):
			checksum = checksum + ord(source[len(source) - 1])
			checksum = checksum & 0xffffffff

		# 32-bit to 16-bit
		checksum = (checksum >> 16) + (checksum & 0xffff)
		checksum = checksum + (checksum >> 16)
		answer = ~checksum
		answer = answer & 0xffff

		# why? ans[9:16 1:8]
		answer = answer >> 8 | (answer << 8 & 0xff00)
		return answer


	def send_ping(self,my_socket, ip_addr, ID):
		ip = socket.gethostbyname(ip_addr)

		my_checksum = 0

		header = struct.pack('bbHHh', self.ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1)
		byte_in_double = struct.calcsize("d") # C type: double
		data = (192 - byte_in_double) * "P" # any char is OK, any length is OK
		data = struct.pack("d", time.clock()) + data

		my_checksum = self.get_checksum(header + data)

		header = struct.pack("bbHHh", self.ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1)
		packet = header + data
		my_socket.sendto(packet, (ip, 80)) # it seems that 0~65535 is OK (port?)


	def ping_once(self,ip_addr, timeout):
		icmp = socket.getprotobyname('icmp')
		try:
			my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
		except socket.error:
			raise

		my_ID = os.getpid() & 0xFFFF

		self.send_ping(my_socket, ip_addr, my_ID)
		delay = self.receive_ping(my_socket, my_ID, timeout)

		my_socket.close()
		return delay


	def icmp_ping(self,ip_addr,timeout,count):
		number=1
		for i in range(count):
			print 'ping ' + ip_addr,
			try:
				delay = self.ping_once(ip_addr, timeout)
				if delay == None:
					print 'failed. (timeout within %s second.)' % timeout
					if number==count:
						print('The request has failed %s times,Email alerts are being sent' % count)
						getcfg(self.filename).sendmessage(ip_addr)
				else:
					print 'get reply in %0.4f ms' % (delay * 1000)
					break
			except socket.gaierror, e:
				print "failed. (socket error: '%s')" % e[1]
				break
			number=number+1
			

if __name__ == '__main__':
	weixin=weixin.WeChat()
	mail=mail.sendmail()
	cfgname='ping_monitor.txt'
	ping(cfgname)
	pingcfg=getcfg(cfgname)
	pingcfg.next_check()

 

配置文件

[rule]
retry = 4
timeout = 1
next_check = 300
#单位都是秒
[scan_network]
3paragraph_begin = 10.1.3.198
3paragraph_end = 202
2paragraph_begin = 10.1.2.1
2paragraph_end = 10


[mail]
mailto1=guoyabin@ccln.gov.cn
mailto2=lzt417@126.com


[allip]
#这里会自动把扫描到的ip写入

  

 

原文地址:https://www.cnblogs.com/guoyabin/p/8310028.html