一、背景:工作上掌管着近百台交换机,其中赫斯曼大概有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后下载网页。
五、心得:
这是我做的第一个相对实用性的脚本,的确是摸着石头过河,参考了网上大神的方案,遇到问题解决问题。最终还是要到现场实测才能验证功能的好坏,继续研究一些其他实用的脚本,做好自动化运维。


剑来
1 声望0 粉丝