网络设备自动巡检与配置备份

Linux下使用crontab定时执行脚本:

vi /etc/crontab

minute hour day-of-month month-of-year day-of-week commands  
分钟    小时   天              月            星期      要执行的命令

语法

crontab [ -u user ] file

crontab [ -u user ] { -l | -r | -e }

说明:

crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类似使用者的时程表。

-u user 是指设定指定 user 的时程表,这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话,就是表示设定自己的时程表。

参数说明

  • -e : 执行文字编辑器来设定时程表,内定的文字编辑器是 VI,如果你想用别的文字编辑器,则请先设定 VISUAL 环境变数来指定使用那个文字编辑器(比如说 setenv VISUAL joe)
  • -r : 删除目前的时程表
  • -l : 列出目前的时程表

时间格式如下:

f1 f2 f3 f4 f5 program
  • 其中 f1 是表示分钟,f2 表示小时,f3 表示一个月份中的第几日,f4 表示月份,f5 表示一个星期中的第几天。program 表示要执行的程序。
  • 当 f1 为 * 时表示每分钟都要执行 program,f2 为 * 时表示每小时都要执行程序,其馀类推
  • 当 f1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行,f2 为 a-b 时表示从第 a 到第 b 小时都要执行,其馀类推
  • 当 f1 为 */n 时表示每 n 分钟个时间间隔执行一次,f2 为 */n 表示每 n 小时个时间间隔执行一次,其馀类推
  • 当 f1 为 a, b, c,... 时表示第 a, b, c,... 分钟要执行,f2 为 a, b, c,... 时表示第 a, b, c...个小时要执行,其馀类推
*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    +----- 星期中星期几 (0 - 7) (星期天 为0)
|    |    |    +---------- 月份 (1 - 12) 
|    |    +--------------- 一个月中的第几天 (1 - 31)
|    +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59)
50 7 * * * python3 back-diff-config.py 意思是每天7:50执行一次脚本

back-diff-config

#!/usr/bin/python3.7
# -*- coding=utf-8 -*-
import poplib,getpass,sys
import time
import paramiko
from difflib import *
import re
import pickle
import random
import smtplib, email.utils
from email.mime.multipart import MIMEMultipart  
from email.mime.text import MIMEText  
from email.mime.application import MIMEApplication

#需要备份的设备地址,可持续添加
#host_list = [input('IP:')]
host_list = ['172.16.16.1','172.16.16.254']

#远程链接设备
def SSHClient_SingleCMD(ip, username, password, cmd):
	try:
		ssh = paramiko.SSHClient()
		ssh.load_system_host_keys()
		ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
		ssh.connect(ip,port=22,username=username,password=password,timeout=5,compress=True)#SSH连接
		stdin,stdout,stderr = ssh.exec_command(cmd)#执行命令
		x = stdout.read()#读取回显
		return x
		ssh.close()
	except Exception as e:
		print('%stErrorn %s'%(ip,e))

#MD5值生成
def get_md5_config(host_list, username, password,operation=0):
	dict_config = {}
	for host in host_list:
		if operation == 0:
			try:
				run_config = SSHClient_SingleCMD(host, 'admin', 'admin', 'show run')
				list_run_config = run_config.decode().split('\r\n')
				location = 0
				host_location = 0
				for i in list_run_config:
					if re.match('.*hostname .*', i):
						host_location = location
					else:
						location += 1
				list_run_config = list_run_config[host_location:]
				run_config = '\r\n'.join(list_run_config)
				md5 = SSHClient_SingleCMD(host, 'admin', 'admin', 'verify /md5 system:running-config')
				dict_config[host] = [run_config.encode(),md5.strip()[-32:]]
			except Exception as e:
				print('%stErrorn %s'%(host,e))
		elif operation == 1:
			try:
				run_config = SSHClient_SingleCMD(host, 'admin', 'admin', 'show run')
				list_run_config = run_config.decode().split('\r\n')
				location = 0
				host_location = 0
				for i in list_run_config:
					if re.match('.*hostname .*', i):
						host_location = location
					else:
						location += 1
				list_run_config = list_run_config[host_location:]
				run_config = '\r\n'.join(list_run_config)
				#md5 = SSHClient_SingleCMD(host, 'admin', 'admin', 'verify /md5 system:running-config')
				dict_config[host] = run_config.encode()
			except Exception as e:
				print('%stErrorn %s'%(host,e))
		elif operation == 2:
			try:
				#run_config = SSHClient_SingleCMD(host, 'admin', 'admin', 'show run')
				md5 = SSHClient_SingleCMD(host, 'admin', 'admin', 'verify /md5 system:running-config')
				dict_config[host] = md5.strip()[-32:]
			except Exception as e:
				print('%stErrorn %s'%(host,e))
		else:
			print('操作码传入错误!')
	return dict_config
#配置文件对比
def diff_file(file1,file2):
	txt1 = open(file1, 'r').readlines()
	txt2 = open(file2, 'r').readlines()
	result = Differ().compare(txt1, txt2)
	return_result = '\n'.join(list(result))
	return return_result

def diff_file(txt1,txt2):
	txt1_list = txt1.decode().split('\r\n')
	txt2_list = txt2.decode().split('\r\n')
	result = Differ().compare(txt1_list, txt2_list)
	return_result = '\r\n'.join(list(result))
	return return_result

#邮件配置
def smtp_attachment(mailserver, username, password, From, To, Subj, Main_Body, files=None):
	Tos = To.split(';')#把多个邮件接受者通过';'分开
	Date = email.utils.formatdate()#格式化邮件时间
	msg = MIMEMultipart() 
	msg["Subject"] = Subj  
	msg["From"]    = From  
	msg["To"]      = To
	msg["Date"]    = Date

	part = MIMEText(Main_Body)  
	msg.attach(part)

	if files:
		for file in files:
			part = MIMEApplication(open(file,'rb').read())
			part.add_header('Content-Disposition', 'attachment', filename=file)  
			msg.attach(part) 

	server = smtplib.SMTP(mailserver)#连接邮件服务器
	server.login(username, password)#通过用户名和密码登录邮件服务器
	failed = server.sendmail(From, Tos, msg.as_string())#发送邮件
	server.quit()#退出会话
	if failed:
		print('Falied recipients:', failed)#如果出现故障,打印故障原因!
	else:
		print('邮件已经成功发出!')#如果没有故障发生,打印‘No errors.’!

def rec_mail(mailserver, mailuser, mailpasswd, mailprefix):
	print('Connecting...')
	server = poplib.POP3(mailserver)#连接到邮件服务器
	server.user(mailuser)#邮件服务器用户名
	server.pass_(mailpasswd)#邮件服务器密码

	try:
		print(server.getwelcome())#打印服务器欢迎信息
		msgCount, msgBytes = server.stat()#查询邮件数量与字节数
		print('There are', msgCount, 'mail message in', msgBytes, 'bytes')#打印邮件数量与字节数
		print(server.list())#打印邮件清单

		for i in range(msgCount):#逐个读取邮件
			hdr, message, octets = server.retr(i + 1)#读取邮件
			mail_file_name = mailprefix + '_' + str(i+1) + '.txt'#本地邮件文件名
			mail_file = open(mail_file_name, 'wb')#创建本地邮件文件
			for line in message:
				mail_file.write(line)#把邮件写入本地邮件文件
			mail_file.close()#写入完毕,关闭本地邮件文件
			print(mail_file_name + ' Recieved!!!')
	finally:
		server.quit()#退出服务器
	print('Bye.')


#备份配置
def first_bak(host_list, username, password):
	dict_config = get_md5_config(host_list, 'admin', 'admin')
	#print(dict_config)
	with open('./config_bak/Config-file', "wb") as config-file:
		pickle.dump(dict_config, config-file)
	print('配置备份成功!')


def find_diff(host_list, username, password):
	new_md5_dict = get_md5_config(host_list, 'admin', 'admin', operation=2)
	with open('./config_bak/Config-file', "rb") as config-file:
		old_md5_dict = pickle.load(Pickle_config)
	for x in new_md5_dict:
		if new_md5_dict[x] != old_md5_dict[x][1]:
			diff_md5_dict = get_md5_config(host_list, 'admin', 'admin')
			diff_result = diff_file(old_md5_dict[x][0],diff_md5_dict[x][0])
			#print(old_md5_dict[x][0])
			#print('=='*50)
			#print(diff_md5_dict[x][0])
			#print(diff_result )
			return x,diff_result

def check_diff():
	try:
		ip, config_changed = find_diff(host_list, 'admin', 'admin')
		print('发现配置更改!')
		id_no = str(int(random.random()*10000))
		Subject = ip + ' configuration changed ' + 'reply "y1" for update db ' + id_no
		Main_Body = config_changed
		smtp_attachment('smtp.163.com',
							'username',
							'password',
							'[email protected]',
							'[email protected]',
							Subject,
							Main_Body)
		time.sleep(300)
		operation_code = rec_mail('pop.163.com', 'mail-username', 'mail-password', id_no)
		if operation_code == True:
			print('邮件已确认!更新数据库!')
			first_bak(host_list, 'admin', 'admin')

	except TypeError:
		print('配置没有任何修改!')


if __name__ == '__main__':
    first_bak(host_list, 'admin', 'admin')




猜你喜欢

转载自blog.csdn.net/weixin_44019506/article/details/105097194