网工Python之路之paramiko 模块实验(七)回显保存成文件,Win中处理空行

2022-10-27 19:08:34 浏览数 (1)

感谢知乎两位大佬:@弈心和@朱嘉盛

@弈心大佬的实验主要是基于 linux 系统、思科设备或 GNS3 模拟器完成。

@朱嘉盛大佬考虑到当前在国内华为较为主流,也用 Windows 系统,尝试用华为的真机或者 eNSP 模拟器,把书中提及的实验做一做,方便大家学习记录,方便交流。

小编这里采用ensp windows复现一遍华为的实验。

平台工具:

  • 实验平台: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。

实验背景:

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

实验目的:

(1)登录设备,执行dis int bri收集设备端口概要信息,保存至本地目录。

(2)处理回显保存的文本,规范化显示。

实验过程

实验拓扑搭建、账号配置调测等在“环境搭建”文章中我们已详细介绍,这里从略。

第 1 步,创建Python脚本文件

有了前面几个实验的基础,相信我们可以很快码出功能性python脚本。延续咱们一贯的简单实用风格,代码我就不定义main函数,子函数,异常处理等内容了。我们聚焦提炼,先把要实现的功能做出来。

代码语言:javascript复制
import paramiko
import time

username = 'python'
password = '123'

for i in range(11,16):
    ip = '192.168.242.'   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('已经成功登陆交换机 LSW-'   str(i-10)   ' '   ip)
    # 关闭分屏功能
    command.send('screen-length 0 temporaryn')
    # 进入系统视图
    command.send('sysn')
    command.send('dis int brin')
    time.sleep(2)

    #抓取回显,放入output变量
    output = command.recv(65535).decode('ASCII')
    print(output)

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

    ssh_client.close()

代码我大概过程串一下:根据实验拓扑交换机IP尾数11-15的规律做一个循环。循环中每次用paramiko模块SSH登录每台交换机,执行取消分屏,进入系统视图,执行dis int bri,抓取回显打印并写入txt,按“ip 指令”的命名规则,保存在result文件夹中,之后断开SSH。继续……直到循环结束。

第 2 步,运行Python脚本

好了,我们跑一下脚本。不出意外的话,我们可以从idle上看到回显,然后在result文件夹中看到保存的文件。至此,实验目的(1)已完成。

第 3 步,打开观察保存的文本

cmd上的print操作没异常,符合预期。保存下来的文本文件,我们先用记事本打开,发现有很多空行,见上图。强迫症患者哪里受得了??我们再用写字板打开看一下。结果只能是更加受不了。

第 4 步,规范化数据(一)

对上面的现象,起初我尝试搜下资料,但并未找到有针对性地解释这现象和解决办法的内容。我自己思考下,这现象估计是数据写入时不规范导致。强迫症还是小事,这种不规范可能会对后续其它操作带来不利影响。

怎么办?原因不知道,生产还是要进行的。那只能想个土办法来应对一下。

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

代码语言:javascript复制
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开头的文件,用记事本打开或者写字板打开就都正常了。

第 5 步,规范化数据(二)

虽然用第4步的代码我们已经能达到目的了。但是这样的代码一来效率低,二来也没办法解释为啥会出现空行。

我们回头观察未经过第4步空行“笨手笨脚”处理的文件。用UE编辑工具打开这个文件后(此时,不会显示空行,但用记事本打开则有空行),我们按快捷键ctrl h切换。观察每行末尾,我们会看到都有

我们查一下ASCI:

0x0D

r(carrige return)

指打字头归位的动作

0x0A

n(new line)

指打字机上卷一行的动作

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

OD OD OA

我推测Windows的记事本工具可能把r呈现成换行,rn也呈现成换行,于是空行就这么出现了。既然我们指令用“n”,那何不我们在接收回显是时候就直接把“r”都处理掉呢?

我们在第1步大代码中,修改这条代码,在最后面加上.replace('r',''),把“r”直接替换成空。

代码语言:javascript复制
output = command.recv(65535).decode('ASCII').replace('r','')

完整的代码我再贴一次:

代码语言:javascript复制
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 temporaryn')
    # 进入系统视图
    command.send('sysn')
    command.send('dis int brin')
    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打开,发现还是会有"rn",这我估计Windows遇到“rn”时保持“rn”,遇到“n”时则处理成“rn”。

实验小结:

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

0 人点赞