平台工具:

  • 实验平台:WIN10
  • 使用工具:eNSP v1.3.00.100、python 3.7.3

实验拓扑:
注意:
书中使用了 192.168.2.0/24 ,我这里才有eve桥接的虚拟网段192.168.242.0/24来演示本次实验。

【SSH 服务端】LSW x,IP为 192.168.242.1x/24,连接到透明交换机SW1。

7、回显保存成文件,Win中处理空行 - 图1

实验背景:

实际运维中,我们经常有这么个需求:登录设备,在设备上执行命令,采集回显信息,保存下来备份或待后续分析比较。

实验目的:

(1)登录设备,执行dis int bri收集设备端口概要信息,保存至本地目录。
(2)处理回显保存的文本,规范化显示。

实验过程
实验拓扑搭建、账号配置调测等在“环境搭建”文章中我们已详细介绍,这里从略。
第 1 步,创建Python脚本文件
有了前面几个实验的基础,相信我们可以很快码出功能性python脚本。延续咱们一贯的简单实用风格,代码我就不定义main函数,子函数,异常处理等内容了。我们聚焦提炼,先把要实现的功能做出来。

  1. import paramiko
  2. import time
  3. username = 'python'
  4. password = '123'
  5. for i in range(11,16):
  6. ip = '192.168.242.' + str(i)
  7. ssh_client = paramiko.SSHClient()
  8. ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  9. ssh_client.connect(hostname=ip,username=username,
  10. password=password,look_for_keys=False)
  11. command = ssh_client.invoke_shell()
  12. print('=-=-=-=-=-=-=-=-=-=-=-=-=-=')
  13. print('已经成功登陆交换机 LSW-' + str(i-10) + ' ' + ip)
  14. # 关闭分屏功能
  15. command.send('screen-length 0 temporary\n')
  16. # 进入系统视图
  17. command.send('sys\n')
  18. command.send('dis int bri\n')
  19. time.sleep(2)
  20. #抓取回显,放入output变量
  21. output = command.recv(65535).decode('ASCII')
  22. print(output)
  23. #保存结果到python脚本同目录下的result文件夹中
  24. f1 = open(f".\\result\\{ip}_dis_int_bri.txt","w")
  25. f1.write(output)
  26. f1.close()
  27. ssh_client.close()

代码我大概过程串一下:根据实验拓扑交换机IP尾数11-15的规律做一个循环。循环中每次用paramiko模块SSH登录每台交换机,执行取消分屏,进入系统视图,执行dis int bri,抓取回显打印并写入txt,按“ip+指令”的命名规则,保存在result文件夹中,之后断开SSH。继续……直到循环结束。
第 2 步,运行Python脚本
好了,我们跑一下脚本。不出意外的话,我们可以从idle上看到回显,然后在result文件夹中看到保存的文件。至此,实验目的(1)已完成。
7、回显保存成文件,Win中处理空行 - 图2
第 3 步,打开观察保存的文本
cmd上的print操作没异常,符合预期。保存下来的文本文件,我们先用记事本打开,发现有很多空行,见上图。强迫症患者哪里受得了??我们再用写字板打开看一下。结果只能是更加受不了。
7、回显保存成文件,Win中处理空行 - 图3
第 4 步,规范化数据(一)
对上面的现象,起初我尝试搜下资料,但并未找到有针对性地解释这现象和解决办法的内容。我自己思考下,这现象估计是数据写入时不规范导致。强迫症还是小事,这种不规范可能会对后续其它操作带来不利影响。
怎么办?原因不知道,生产还是要进行的。那只能想个土办法来应对一下。

在python脚本的最后,补上下面代码。

f1 = open(f".\\result\\{ip}_dis_int_bri.txt","r")
f2 = open(f".\\result\\new_{ip}_dis_int_bri.txt","w")
for line in f1.readlines():
   if line.split():
       f2.write(line)
f1.close()
f2.close()

代码我大概过程串一下:前面的代码跑完后,python脚本重新打开每个文件,逐行读取。对读取的每一行先做split()分列操作,处理后,如果为空则跳过直接处理下一行了,如果非空则写入另一个文件中。这可以说是一个笨手笨脚效率低的方法。咱们是网工,能有效应对生产,效率低点没关系。
来,执行一下。我们发现result文件夹中处理后的new开头的文件,用记事本打开或者写字板打开就都正常了。

7、回显保存成文件,Win中处理空行 - 图4
7、回显保存成文件,Win中处理空行 - 图5

第 5 步,规范化数据(二)
虽然用第4步的代码我们已经能达到目的了。但是这样的代码一来效率低,二来也没办法解释为啥会出现空行。
我们回头观察未经过第4步空行“笨手笨脚”处理的文件。用UE编辑工具打开这个文件后(此时,不会显示空行,但用记事本打开则有空行),我们按快捷键ctrl+h切换。观察每行末尾,我们会看到都有

7、回显保存成文件,Win中处理空行 - 图6
我们查一下ASCI:

0x0D \r(carrige return) 指打字头归位的动作
0x0A \n(new line) 指打字机上卷一行的动作

Windows系统中连用”\r\n”,类UNIX系统多用”\n”(看上面python代码我们在指令后面加了“\n”)。回到用UE打开的文本,我们翻译一下。

| OD OD OA |

| | —- | —- |

我推测Windows的记事本工具可能把\r呈现成换行,\r\n也呈现成换行,于是空行就这么出现了。既然我们指令用“\n”,那何不我们在接收回显是时候就直接把“\r”都处理掉呢?
我们在第1步大代码中,修改这条代码,在最后面加上.replace(‘\r’,’’),把“\r”直接替换成空。

output = command.recv(65535).decode('ASCII').replace('\r','')

完整的代码我再贴一次:

import paramiko
import time

username = 'python'
password = '123'

for i in range(11,16):
    ip = '192.168.11.' + str(i)

    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh_client.connect(hostname=ip,username=username,
                       password=password,look_for_keys=False)
    command = ssh_client.invoke_shell()

    print('=-=-=-=-=-=-=-=-=-=-=-=-=-=')
    print('已经成功登陆交换机 Layer3Switch-' + str(i-10) + ' ' + ip)
    # 关闭分屏功能
    command.send('screen-length 0 temporary\n')
    # 进入系统视图
    command.send('sys\n')
    command.send('dis int bri\n')
    time.sleep(2)
    output = command.recv(65535).decode('ASCII').replace('\r','')
    print(output)

    #保存结果到python脚本同目录下的result文件夹中
    f1 = open(f".\\result\\{ip}_dis_int_bri.txt","w")    
    f1.write(output)
    f1.close()

    ssh_client.close()

再跑一下python脚本,马上就没有多余的空行了,这里就不截图了。至此,实验目的(2)完成。

另外再次用UE打开,发现还是会有”\r\n”,这我估计Windows遇到“\r\n”时保持“\r\n”,遇到“\n”时则处理成“\r\n”。
7、回显保存成文件,Win中处理空行 - 图7

实验小结:

虽然用第4步的代码我们已经能达到目的了。但是这样的代码一来效率低,二比如我们想做配置备份,就把指令改成“dis cur”即可,这个实验还是挺具有通用性的。网工普遍没什么计算机编码解码基础,遇到此类问题可能会比较棘手。我也有过多次因处理乱码等搞到焦头烂额的经历。有时候我们使用点工具,看编码解码后的变化,或许能帮忙解决些问题吧。另外,当使用netmiko、nornir等高大上模块后,我们再回过头来使用paramiko模块,会不会觉得其实反而它轻巧好操作些呢?!