一、背景:工作上掌管着近百台交换机,其中赫斯曼大概有60台。现在需要定期备份配置和查看日志检查隐患。可是用网页方式下载太费时间,安排2人轮着下载用了1天,而且ms1600的配置是二进制的,所以萌生研究python脚本的想法。

二、方案:在Windows的NMS上运行脚本自动获取保存交换机配置到本地,下载日志网页。
①确认非运营时间下载②获取时间,作于文件夹名字③读取IpAddress文件,获取交换机ip④登陆交换机⑤按命令列表输入命令⑥读取返回值并保存文件⑦下载日志网页

三、实现代码:

  1 #! python3
  2 # Download Hirschmann eventlog & configuration
  3 import os, requests, time, logging, telnetlib
  4 
  5 # TODO: Telnet登陆、命令、退出模块
  6 class TelnetClient():
  7     def __init__(self,):
  8         self.tn = telnetlib.Telnet()
  9     def login_host(self,host_ip,username,password):
 10         try:
 11             #   self.tn = telnetlib.Telnet(host_ip,port=23) 另一种方法
 12             self.tn.open(host_ip,port=23)
 13         except:
 14             logging.warning('%s network connection failed' % k) #连接失败
 15             errorlog = open(os.path.join("D:\\%s" % DirName, "error.log"), 'a')
 16             errorlog.write('%s connection failed \n' % host_ip)
 17             errorlog.close()
 18             return False
 19         self.tn.read_until(b'User:', timeout=5) #接入后读取“User”的返回值,最多等5s,超出执行下一步
 20         self.tn.write(username.encode('utf-8') + b'\n') #写入用户名,换行符代表回车
 21         self.tn.read_until(b'Password:', timeout=5)
 22         self.tn.write(password.encode('utf-8') + b'\n')
 23         time.sleep(5)   #等待5s反应时间
 24         command_result = self.tn.read_very_eager().decode('utf-8')  #读取返回值,read_very_eager()获取到的是的是上次获取之后本次获取之前的所有输出
 25 
 26         if '>' in command_result:   #判断登陆成功
 27             print('%s Logging successfully' %host_ip)
 28             return True
 29         else:
 30             logging.warning('%s Logging unsuccessfully' % host_ip)
 31             errorlog = open(os.path.join("D:\\%s" % DirName, "error.log"), 'a')
 32             errorlog.write('%s Logging unsuccessfully \n' % host_ip)
 33             errorlog.close()
 34             return False
 35     def exec_command(self,command):
 36         for i in range(len(command)):
 37             self.tn.write(command[i].encode('utf-8') + b'\n')   #执行命令列表
 38             time.sleep(5)   #务必提供反应时间
 39         command_result = self.tn.read_very_eager().decode('utf-8')
 40         if "snooping" in command_result:    #判断数据完整
 41             config_file = open(os.path.join("D:\\%s" % DirName, "%s" % k + "_config.txt"), 'a')     #新建config文件
 42             config_file.write(command_result)   #写入读取的数据
 43             config_file.close()
 44         else:
 45             Errorconfig = open(os.path.join("D:\\%s" % DirName, "error.log"), 'a')  #打开error文件
 46             Errorconfig.write('%s configuration isn\'t complete \n' % v)    #记录错误数据
 47             Errorconfig.close()
 48     def logout_host(self):
 49           self.tn.write(b"exit\n")  #输入exit退出
 50 
 51 
 52 # TODO:下载网页模块:
 53 class Dnld():
 54     def dnldevent(self,  name, ip):
 55         url = "http://" + ip + "/base/system/event_log.html"    #制作url
 56         res = requests.get(url) #获取网页
 57         res.raise_for_status()
 58         EventFile = open(os.path.join("D:\\%s" % DirName, "%s" % name + "_eventlog.html"), 'wb')    #新建html文件
 59         for chunk in res.iter_content(100000):  #分片写入
 60             EventFile.write(chunk)
 61         EventFile.close()
 62     def dnldsys(self, name, ip):
 63         url = "http://" + ip + "/base/system/systemInfo.html"
 64         res = requests.get(url)
 65         res.raise_for_status()
 66         EventFile = open(os.path.join("D:\\%s" % DirName, "%s" % name + "systemInfo.html"), 'wb')
 67         for chunk in res.iter_content(100000):
 68             EventFile.write(chunk)
 69         EventFile.close()
 70 
 71 # TODO:建立主程序,导入字典
 72 if __name__ == '__main__':
 73     confirm = input('请确认在非运营时段操作下载配置,确认请在下方输入"ok" \n')
 74     if confirm.lower() == 'ok':
 75         localtime = time.strftime("%Y%m%d%H%M", time.localtime())   #获取当前年月日时分
 76         DirName = localtime + "_dump"   #生成文件夹名
 77         DirName2 = DirName  #复式文件夹,为后面文件夹重名做容器
 78         Dic = []    #新建字典做ip地址容器
 79         i = 1
 80         while os.path.exists("D:\\%s" % DirName):   #预防文件夹重名
 81             DirName = DirName2 + '_' + '%s' % i #末尾增加序号
 82             i += 1
 83         os.makedirs("D:\\%s" % DirName) # 新建文件夹
 84         f = open('IpAddress.txt', 'r')  # IpAddress.txt中的url结尾不要有"/"
 85         for line in f.readlines():
 86             line = line.strip('\n')  # 去掉换行符\n
 87             b = line.split(' ')  # 将每一行以空格为分隔符转换成列表
 88             Dic.append(b)  # 按行读取txt文件,然后转换成嵌套列表
 89         Dic = dict(Dic)  # 通过dict方法将嵌套列表转换成字典
 90     else:
 91         exit()  #未输入ok直接退出程序
 92 
 93 # TODO:导入用户密码命令参数
 94     for k, v in Dic.items():
 95         host_ip = v
 96         host_name = k
 97         username = 'xxxxx'
 98         password = 'xxxxx'
 99         command = ['en', 'show running-config'] #命令列表
100         #Respond = ['#'] #回应特征值,暂未用
101         telnet_client = TelnetClient()
102         Download_web = Dnld()
103         if telnet_client.login_host(host_ip, username, password):
104             telnet_client.exec_command(command)
105             telnet_client.logout_host()
106             Download_web.dnldevent(host_name, host_ip)
107             Download_web.dnldsys(host_name, host_ip)

后面是编译成exe,我使用的是Pyinstaller,使用pycharm安装编译器后就能在terminal上输入pyinstaller -F xxx.py编译成一个exe了,注意编译系统如果是64位的是不能放在32位系统上运行的。

四、期间遇到如下问题:
1、文件夹重名:本时间精确到分,故一分钟内重复运行os.makedirs会报文件已存在,故增加了文件夹存在的判断,若重名结尾递增数字。
2、日志下载不完整:此问题主要是命令间给的反应时间不够导致,需要现场调试增加反应时间。同时增加了判断点,将配置末端的特征值作为判断,若不完整记录到errorlog里。
3、网页下载若错误无记录:这点还在研究中,初步是换下顺序,先telnet连接,ok后下载网页。
五、心得:
这是我做的第一个相对实用性的脚本,的确是摸着石头过河,参考了网上大神的方案,遇到问题解决问题。最终还是要到现场实测才能验证功能的好坏,继续研究一些其他实用的脚本,做好自动化运维。

 

版权声明:本文为riomo原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/riomo/p/12826148.html