自动化运维是什么意思,自动化运维初级村-巡检-文本解析-从正则到TextFSM

全文上一段落中坚信他们已经对程序语言有了基本上的基本上概念,正像我以后提及的,纯粹看完习题的如是说根本无法算是“梦境”,假如没有课堂教学,就算把程序语言全部的规则都Pardoux了,也不能算是“学会” 。今天这一段落就要率领他们课堂教学一下怎样小捷尔的文档撰写程序语言 。
但为什么副标题是“文档导出-TextFSM”呢,即使有许多朋友一开始就想从TextFSM上手,但TextFSM到底比二阶强在哪儿?TextFSM所遵从的状态转移和相匹配监督机制到底是怎样产生又是怎样运用的?
在我率领他们课堂教学程序语言的过程中,他们会发现如此灵活的二阶相匹配的软肋在哪里?而这些软肋不可否认是造就TextFSM的重要因素 。
纯粹文档相匹配他们以Cisco电子设备上继续执行“show clock”的输入为原始文档,由于输入文档足够纯粹,适于作为第两个范例来传授,输入如下表所示:
18:42:41.321 CST Sun Jan 1 2023现在想据此输入文本相匹配两个关键性重要信息,分别是:时间、夏令时间、月份、日、年 。
透过程序语言来相匹配的话会有许多种形式,我这里提供两个实例如下表所示:
import restdout = "18:42:41.321 CST Sun Jan 1 2023"# 括弧表示以获取相匹配,最后会将括弧内结论回到regexp = r(..:..:..\....) (\w+) \w+ (\w+) (\d+) (\d+)result = re.findall(regexp, stdout)print(result)# 输入结论 [(18:42:41.321, CST, Jan, 1, 2023)]对于从两个个文档中想相匹配选定的两个关键性重要信息,透过程序语言更为方便 。
但有两个十分不言而喻的瑕疵,那是他们透过“以获取相匹配”的形式来甄选相匹配关键性重要信息,假如两个个文档中的关键性重要信息有许多个,那程序语言就会变得十分乏味,且最后梅西县界定别的相匹配结论相关联别的重要信息 。比如说上面范例中想回到复本的形式化数据通常还须要做如下表所示处理:
res_dict = {"time": result[0][0],"timezone": result[0][1],"month": result[0][2],"day": result[0][3],"year": result[0][4],}所以到为止,根据两个纯粹的实例可以延伸分析得出,他们须要两个监督机制能够标记相匹配函数所相关联的重要信息Hamming称;但光有这一点,还足以让伊藤清拆去函数,即使关键性重要信息再多也是有限的,再低落也是多写两个负号检索罢了 。
二百一十三文档相匹配假如输入文本是二百一十三文档时,相匹配的维数Ploudalm两个捷伊提升,比如说Cisco电子设备继续执行“show version”的输入如下表所示:
Cisco IOS Software, Catalyst 4500 L3 Switch Software (cat4500-ENTSERVICESK9-M), Version 12.2(31)SGA1, RELEASE SOFTWARE (fc3)Technical Support: http://www.cisco.com/techsupportCopyright (c) 1986-2007 by Cisco Systems, Inc.Compiled Fri 26-Jan-07 14:28 by kellythwImage text-base: 0x10000000, data-base: 0x118AD800?ROM: 12.2(31r)SGAPod Revision 0, Force Revision 34, Gill Revision 20?router.abc uptime is 11 weeks, 4 days, 20 hours, 26 minutesSystem returned to ROM by reloadSystem restarted at 22:49:40 PST Tue Nov 18 2008System image file is "bootflash:cat4500-entservicesk9-mz.122-31.SGA1.bin"??This product contains cryptographic features and is subject to UnitedStates and local country laws governing import, export, transfer anduse. Delivery of Cisco cryptographic products does not implythird-party authority to import, export, distribute or use encryption.Importers, exporters, distributors and users are responsible forcompliance with U.S. and local country laws. By using this product youagree to comply with applicable laws and regulations. If you are unableto comply with U.S. and local laws, return this product immediately.?A summary of U.S. laws governing Cisco cryptographic products may be found at:http://www.cisco.com/wwl/export/crypto/tool/stqrg.html?If you require further assistance please contact us by sending email toexport@cisco.com.?cisco WS-C4948-10GE (MPC8540) processor (revision 5) with 262144K bytes of memory.Processor board ID FOX111700ZNMPC8540 CPU at 667Mhz, Fixed ModuleLast reset from Reload2 Virtual Ethernet interfaces48 Gigabit Ethernet interfaces2 Ten Gigabit Ethernet interfaces511K bytes of non-volatile configuration memory.?Configuration register is 0x2102现在他们的目标仍然是以获取两个关键性重要信息,包括:版本号、启动时长、镜像文件、重置原因 。
虽然须要从二百一十三文档中去相匹配重要信息,但仍然可以透过程序语言来实现,代码如下表所示:
import restdout = "output of show version"regexp = rCisco IOS .*Version (\S+),.*uptime is (.*?)\n.*System image file is "(.*)".*Last reset from (\w+)result = re.findall(regexp, stdout, re.DOTALL)print(result)""" 输入结论 [(12.2(31)SGA1,11 weeks, 4 days, 20 hours, 26 minutes,bootflash:cat4500-entservicesk9-mz.122-31.SGA1.bin,Reload)]"""上述的代码有两个须要注意的地方:
re.findall函数中多传了两个参数,re.DOTALL,表示“.”可以相匹配任何字符,包括换行符(默认不包括) 。程序语言中的“.?”,即使加了re.DOTALL参数,所以“.”可以相匹配任意多个字符(贪婪相匹配特性会导致尽可能多的相匹配字符),这样会导致不能准确的相匹配到uptime所在行尾的\n,但加了?,会将贪婪相匹配转为非贪婪相匹配,此时就会尽可能少的相匹配字符 。虽然可以成功相匹配出结论,但他们应该已经发现,二百一十三文档的相匹配中会存在更多因素影响相匹配结论的准确性,所以以我个人经验来看,尽量不用程序语言来相匹配二百一十三文档 。
那是否可以改变相匹配形式来进行相匹配呢,代码如下表所示:
import restdout = "output of show version"version_regexp = r^Cisco IOS .*Version (\S+),uptime_regexp = r.*uptime is (.*)image_regexp = rSystem image file is "(.*)"reset_regexp = rLast reset from (\w+)regexps = [version_regexp, uptime_regexp, image_regexp, reset_regexp]result = []for regexp in regexps:res = re.findall(regexp, stdout)result.append(res[0] if len(res) > 0 else "unknown")print(result)""" 输入结论 [(12.2(31)SGA1,11 weeks, 4 days, 20 hours, 26 minutes,bootflash:cat4500-entservicesk9-mz.122-31.SGA1.bin,Reload)]"""透过稍加改造后,将相匹配不同重要信息的程序语言分开定义,然后每个函数相匹配一次完整的字符串,最后就可以得出所有的相匹配结论;但理论上已经相匹配过的文本实际上不须要再次被相匹配了,而且仍存在准确性问题,即使某个关键性重要信息的程序语言是对某一行进行相匹配的,所以假如用该二阶去相匹配全文,可能会出现相似文本导致结论不准确,所以可以将文档文本分成一行行再去进行相匹配,如下表所示:
import restdout = "output of show version"version_regexp = r^Cisco IOS .*Version (\S+),uptime_regexp = r.*uptime is (.*)image_regexp = r^System image file is "(.*)"reset_regexp = r^Last reset from (\w+)regexps = [version_regexp, uptime_regexp, image_regexp, reset_regexp]result = []for line in stdout:for regexp in regexps:res = re.findall(regexp, line)if res not res:continueresult.append(res[0])breakprint(result)此时就可以程序语言前加两个“^”来表示相匹配行首,这样可以大大增加相匹配结论的准确性 。
这里我希望他们可以着重理解上述代码的逻辑,即使这个逻辑其实已经和TextFSM的基本上相匹配逻辑十分相似,那是:定义多个相匹配规则,一行一行的读取文档,用该行去依次相匹配每个二阶,假如相匹配到则读取新行,再次去和所有规则进行相匹配 。
复杂文本的相匹配纯粹文档和二百一十三文档都是针对关键性字重要信息的提取,虽然可以总结出一些优化逻辑,但整体上相匹配过程相对纯粹,所以仍没有办法说服他们拆去二阶,而选择TextFSM 。
即使一旦引入两个捷伊第三方包,就意味着增加了更多的学习成本,而且会由于对于使用方法和原理的理解不够清晰,而导致增加更多的不稳定因素 。
那么现在除了上述的重要信息提取外,还有一种在网络电子设备十分常见的输入文本,那是表格类型的输入,比如说“show ip route”的输入文本,如下表所示:
Destination Gateway Dist/Metric Last Change----------- ------- ----------- -----------B EX 0.0.0.0/0 via 192.0.2.73 20/100 4w0dvia 192.0.2.201via 192.0.2.202via 192.0.2.74B IN 192.0.2.76/30 via 203.0.113.183 200/100 4w2dB IN 192.0.2.204/30 via 203.0.113.183 200/100 4w2dB IN 192.0.2.80/30 via 203.0.113.183 200/100 4w2dB IN 192.0.2.208/30 via 203.0.113.183 200/100 4w2d上述的输入增加了一些难处理的文本,比如说表头的多余文本,表格的结构,以及某个列中可能会包含多个值 。
他们可以仍然尝试使用二阶来进行处理,代码如下表所示:
import restdout = "output of show ip route"regexp = r(\w) (\w+) (\S+)\s+via (\S+)\s+(\d+)/(\d+)\s+(\S+)result = []for line in stdout.split("\n"):res = re.findall(regexp, line)if not res:continueresult.append(res[0])print(result)""" 输入文本 [(B, EX, 0.0.0.0/0, 192.0.2.73, 20, 100, 4w0d),(B, IN, 192.0.2.76/30, 203.0.113.183, 200, 100, 4w2d),(B, IN, 192.0.2.204/30, 203.0.113.183, 200, 100, 4w2d),(B, IN, 192.0.2.80/30, 203.0.113.183, 200, 100, 4w2d),(B, IN, 192.0.2.208/30, 203.0.113.183, 200, 100, 4w2d)]"""透过代码的处理貌似可以提取出部分的重要信息,但仍然有最为关键性的文本被错过了,那是Gateway列的多个值 。
最后想的结论应该是Gateway列最后相匹配到的值是两个列表,可以包含多个值,那么代码改造如下表所示:
import restdout = "output of show ip route"regexp = r(\w) (\w+) (\S+)\s+via (\S+)\s+(\d+)/(\d+)\s+(\S+)gateway_regexp = r\s+via (\S+)result = []for line in stdout.split("\n"):res = re.findall(regexp, line)if res:res = list(res[0])res[3] = [res[3]]result.append(res)continuecol = re.findall(gateway_regexp, line)if not col:continueif len(result) > 0:result[-1][3].append(col[0])print(result)"""输入文本 [[B, EX, 0.0.0.0/0, [192.0.2.73, 192.0.2.201, 192.0.2.202, 192.0.2.74], 20, 100, 4w0d],[B, IN, 192.0.2.76/30, [203.0.113.183], 200, 100, 4w2d],[B, IN, 192.0.2.204/30, [203.0.113.183], 200, 100, 4w2d],[B, IN, 192.0.2.80/30, [203.0.113.183], 200, 100, 4w2d],[B, IN, 192.0.2.208/30, [203.0.113.183], 200, 100, 4w2d]]"""上述代码中定义了两个二阶语句,并且在相匹配过程中进行了额外的处理,虽然最后得到了正确的结论,但实现的过程也是十分“hack”,这种情况显然不是他们想的 。
总结虽然上述三个范例都透过程序语言+代码的逻辑完成了输入文本的形式化处理,但有两个地方是不符合预期的:
相匹配规则和结论缺少字段标记处理二百一十三文档+多个程序语言时引入的额外代码逻辑处理表格类型文档+多值字段时引入的额外代码逻辑讲到这里我仍然想说的是,上述的三个缺点在处理有限的文本时也并足以让他们拆去程序语言,而引入TextFSM,比如说某个纯粹的需求只想导出选定两个输入文本,那么导出的逻辑和规则时可以穷举的,只须要将相关联输入文本的导出方法封装成相应的函数,然后直接的调用即可 。
但在他们的县丞场景或者更为大型的系统中,要处理的输入文本是无法穷举的,随时会有可能新增某个县丞项,假如所有的导出逻辑都透过封装函数来一一相关联处理,那么这种形式并不符合程序设计的原则 。
他们的预期是想透过某种形式来实现导出逻辑的抽象化,只须要维护导出模版即可,将导出模版以文件的形式保存或者存储在数据库中,这样就可以随时新增某个模版来应对须要处理的文本,而没有必要改动代码逻辑 。而TextFSM正好可以帮助他们实现,而在我看来这才是须要引入TextFSM的真正原因 。
【自动化运维是什么意思,自动化运维初级村-巡检-文本解析-从正则到TextFSM】假如他们只是想写某个脚本来处理有限的输入文本而引入TextFSM,那显然是脱离了“最小化上手原则”,并且我希望他们能够学会根据需求合理的选择工具的使用 。

    推荐阅读