上一节笔者完成了NTP服务器的搭建,并通过对交换机的配置在客户端完成了时间校准。但是同时遇到了一个很严重的问题,笔者专网中有上百台网络交换机,每个交换机都要同步ntp产生的重复劳动简直让笔者想拿头撞墙。但需求永远在推进技术学习,秉持着想尽办法偷懒的态度,笔者准备通过一小段代码来对网络内交换机进行ntp server的配置。
整理一下现状:1.交换机都处于专网中,笔者的服务器均可以直接访问,无需代理设备;2.几乎所有的交换机型号相同,也就是说完成ntp的配置指令相同;3.所有交换机密码相同;4.所有设备都可以telnet管理,端口均是默认端口,唯一的区别就只有设备IP地址。
那笔者的思路就比较清楚了,首先有个指令配置的模板,其中包含了设备登陆、密码输入、配置指令及保存退出。其次定义一个IP地址的表单,对表单内的IP地址进行配置模板的重复执行。
对于linux系统而已,大多数简短脚本都会采用bash来进行编写,而笔者之前尝试过expect脚本编写,感觉这个脚本语言对于初学者相对比较友好,因此这节笔者就通过expect来进行功能实现。
登陆服务器,首先看一下服务器是否有bash和expect:
yum list installed | grep bash
yum list installed | grep expect
看到系统是自带bash组件,但没有expect,继续按照以往的方式进行软件安装:
yum list | grep expect
yum install expect.x86_64
完成软件安装。
查看一下yum把expect安装到了哪里:
whereis expect
熟悉一下文件安装的路径。
下面笔者开始一个初始化脚本的编写,进入文件夹
cd /var
笔者来新建一个文件夹用于储存和管理脚本
mkdir expect
进入笔者新建的文件夹
cd ./expect
开始创建第一个shell文件
vi telnet.sh
编程语言第一步就是声明语言,结合之前笔者看到的安装路径:
#!/usr/bin/expect
设置超时时间为3秒:
set timeout 3
继续随便找一台交换机进行测试:比如10.150.103.61,测试之前呢,笔者也先不拿ntp的相关配置来做操作,毕竟时间看起来比较麻烦。笔者用最简单、直观可见的方式--修改交换机的名称来测试:
插入一部分,编程的同时笔者先梳理一下交换机改名字的配置思路。
第一步telnet 10.150.103.61
执行之后呢,交换机就需要输入密码,为了方便测试脚本笔者改为了简单好记的123456
输入密码之后呢,H3C交换机改个用户名两条简单指令:
system-view
sysname hbaitest1
保存退出:
quit
save
y
y
最后quit退出,就结束了~
如上交换机的配置指令已经梳理清楚了,那就开始脚本配置:
脚本配置的轻松愉快啊,spawn即是执行了telnet的指令,之后expect会匹配密码的输入,完整匹配字符应该是“Password:”前后两个*表示字符“assword”前后匹配任意字符,这样就匹配到了输入密码的界面。
后面的异常轻松,送密码啊送指令啊,送完了之后interact脚本结束。
wq!
保存退出,下面笔者迫不及待的尝试一下脚本的效果,运行之前笔者先登录这台交换机设备,把它修改为原来的名字:hbai1
切换回服务器,执行脚本。
./telnet.sh
提示权限不够。直接给文件夹/var/expect赋予读写执行权限
chmod –R 777 /var/expect
继续运行脚本
./telnet.sh
再看一下交换机,名字已然变成了笔者修改过后的新名字。简简单单的脚本执行完成了。
执行完成后继续把名字修改回来:
笔者最初的目的达成了,可以通过脚本自动修改交换机名称,但是由于脚本是固定的IP地址(spawn telnet 10.150.103.61)无法做到修改多个设备。下一步,笔者就在上述脚本的基础上进行优化设置。
一、增加输入,使得IP地址不再固定;
常见脚本的输入方式大约分为两种,一种是交互式的,可以手动输入,不过一旦输入内容很多,输入变量也会变成一件非常繁琐的事情;另一种方便的方式就是新建一个文件,把所有需要管理的IP地址都加入其中。然后自动读取文件执行就可以了。
很明显在笔者现有的应用场景下,第二种方式比较简便,笔者只需要把所有的交换机IP地址贴出来就可以了,思路上呢,就是首先读取文件第一行IP地址,telnet进行连接,执行交换机修改的命令;读取文件第二行IP地址…………直到读取文件结束。很清晰,一个循环操作。
首先笔者新建一个文件来存储IP地址:
vi ip.txt
输入几个测试的IP地址
笔者新建一个脚本来测试下循环:
vi read.sh
设置读取文件位置和操作:setf [open ip.txt]
执行一个循环while:while {1}
读取字符串并写入line变量中set line [gets $f]
输出变量:puts “ipaddress is : $line”
判断变量是否为空,文件读取结束: if {[eof $f]} { close $f break }
成功完成后输出提示:successful
这样一个简单的循环脚本就完成了,笔者执行一下脚本来看看运行结果:
./read.sh
不错~输入结束,结果很理想。下面笔者要做的就是整合之前完成的两个脚本,一边读取IP地址,一遍执行笔者想要的配置操作。
二、增加循环,使得脚本可以对多个设备执行命令。
回顾一下循环的思路:
1.读取文件;2.执行循环;3.读取字符串写入变量;4.输出变量;5.变量为空循环结束。
回顾一下交换机配置更改的思路:
1>telnet一个IP地址;2>在输入密码界面输入密码;3>执行命令;4>保存退出。
思路上就是将循环中的“4.输出变量”替换为“1>--4>交换机配置更改”,这样就轻松愉快的结束了。
开始操作,将循环脚本read.sh复制为modify.sh
cp read.sh modify.sh
编辑脚本:vi modify.sh
将第四条输出ip地址替换为telnet.sh脚本中的命令修改配置:
完整脚本如上。
找个测试环境,笔者把ip.txt的地址替换为可以访问的交换机地址:vi ip.txt
登陆这两台设备:
执行脚本:./modify.sh
等待脚本执行完成后,回到这两台交换机的管理界面,发现交换机名字已经批量修改了~
到这里为止,笔者的执行脚本已经完成啦,以后的批量作业只需要将指令保存到脚本之中,并且维护交换机ip地址列表ip.txt就可以一键修改了~
可以看到,一个功能性脚本最重要的就是理清思路,知道分几步完成,每步该做什么;同样对于一个复杂的步骤可以将其拆解出来,单独使用一个脚本进行实现,最后再进行脚本的整合。每个复杂脚本基本上基于输入、输出、变量、运算符、注释、流控制来进行的,逻辑思路非常重要。
最后的最后,笔者优化一下了脚本。参考之前的ip地址列表,笔者将地址单独出了一个文件以便修改。同样,笔者将需要执行的命令也单独出来一个文件,命名为command.txt。考虑到笔者最初的目的,将配置指令修改为上一节NTP相关配置。三个文件如下所示:
ip.txt
command.txt
modify.sh
利用如上脚本和两个文件就可以实现网络设备的批量telnet和ssh管理啦~