用于检测 link up/down 的程序

为了可以检测到哪个网口 up/down。
这里使用 python 来 调用 ip monitor link 来实现 网口 up/down 状态的观测。

观察其中的输出:

  • 如果有 LOWER_UP,就是 link up。
  • 如果没有 LOWER_UP,就是 link down。
#!/usr/bin/python
# -*- coding:utf-8 -*-

from subprocess import * 
import traceback
from threading import *
import time
import re

class net_link_event():
	def __init__(self
		, timestamp
		, link_id
		, link_name
		, is_link_up
		):
		
		self.timestamp = timestamp
		self.link_id = link_id
		self.link_name = link_name
		self.is_link_up = is_link_up

	def to_string(self):
		return "{timestamp: %d, link_id: %s, link_name: %s, is_link_up: %s}" % (self.timestamp
				, self.link_id
				, self.link_name
				, self.is_link_up
			)

'''
case:

# link down
	16: vEth0:  mtu 1500 qdisc pfifo_fast state DOWN 
	2: eth0:  mtu 1500 qdisc pfifo_fast state DOWN 
# link up
	16: vEth0:  mtu 1500 qdisc pfifo_fast state UNKNOWN 
									   ^^^^^^^^  link up
	2: eth0:  mtu 1500 qdisc pfifo_fast state UP 
									 ^^^^^^^^   link up
'''

class net_link_monitor():
	'''
	public
	'''
	def run(self):
		if self.__thread:
			self.__thread.start()
			
	'''
	private
	'''
	def __init__(self
		, link_changed_handler
		, init_handler = None, error_handler = None, exit_handler = None
		):
		# verify the user input	
		if link_changed_handler is None:
			print("ERROR: link_changed_handler is NOT assigned!!!")
			exit()

		# command line for ip link monitor in Linux
		self.__command = "ip monitor link"

		# pattern to for link id, link name, and link status
		self.__regexp = re.compile(
			r"^(?P\d+):"		# link id
			r"\s+"						#   white space 
			r"(?P\S+):"		# link name
			r"\s+"						#   while space
			r"(?P<.*>)"	# link status
			)
		# the keyword to verify wether link up
		self.__link_up_keyword = "LOWER_UP"

		# handlers
		self.__link_changed_handler = link_changed_handler
		self.__init_handler = init_handler
		self.__error_handler = error_handler
		self.__exit_handler = exit_handler

		# threading
		self.__shell = True
		self.__stdin = PIPE
		self.__stdout = PIPE
		self.__stderr = PIPE
		self.__thread = Thread(target=self.__run)
	def __run(self):
		try:
			self.__pipe = Popen(self.__command
				, shell=self.__shell
				, stdin=self.__stdin
				, stdout=self.__stdout
				, stderr=self.__stderr
				)
				
		except OSError as error:
			if self.__error_handler:
				self.__error_handler(self.__command, error)
			
			
		# pipe init 
		if self.__init_handler:
			self.__init_handler(self.__command)
		
		# read each line 
		while True: 
			line = self.__pipe.stdout.readline()
			# break the loop if empty line
			if not line:  
				break
			# parse line
			self.__parse_line(line)

		# pipe exit
		if self.__exit_handler:
			self.__exit_handler(self.__command)

	def __parse_line(self, line):
		
		found = self.__regexp.search(line)
		if found:
			#  print(line)						# for debug only

			# detect wether link up from status
			if found.group("link_status").find(self.__link_up_keyword) > 0:
				is_link_up = True
			else:
				is_link_up = False
		
			# fill event object
			event = net_link_event(time.time()	# timestamp
				, found.group("link_id")		# link_id
				, found.group("link_name")		# link_name
				, is_link_up					# is_link_up
				)

			# handle event
			self.__link_changed_handler(event)

'''
example
'''
if __name__ == '__main__': 
	def on_link_changed(link_event):
		print("link changed", link_event.to_string())
		
	def on_init(process_name):
		print(process_name, "init")
	
	def on_error(process_name, error):
		print(process_name, "error", error)
		
	def on_exit(process_name):
		print(process_name, "exit")
	
	monitor = net_link_monitor(on_link_changed
		, on_init, on_error, on_exit)
	monitor.run()

	



你可能感兴趣的:(python,linux)