运维少年系列 python and cisco (4)

运维少年系列 python and cisco (4)

骚年 运维少年

运维少年系列 python and cisco (4)

说明

本章使用了多线程的方式提高脚本执行的效率,本章也是本系列文章的最后一个内容。回顾前三章,从单台交换机到多台交换机然后到异常处理,到今天的多线程,我觉得还算比较连贯吧~

多线程

为什么要使用多线程?在前面我们写的所有程序都是单线程的,串行执行,也就是说,要等上一个命令执行完成之后,下一个命令才能执行,但很显然,在机器比较多的情况下显得效率很低。所以我们应该使用多线程,使程序并发执行。

单线程和多线程比较

  • 单线程执行时间
    来看看上一次写的脚本的执行时间吧(动图)~

运维少年系列 python and cisco (4)

可以看到,需要28s,这仅仅是三台机器啊~如果100台呢,那也太久了吧~

  • 多线程执行时间
    来看看多线程的执行时间是多少吧(动图)~

运维少年系列 python and cisco (4)

可以看到,使用了多线程之后,速度提升了很多~

多线程使用

多线程的简单使用

python中的多线程实现使用的是threading函数,但是在使用多线程的时候,可能会遇到很多问题。先来看看多线程简单的用法吧


import threading  # 导入多线程模块
import time

def run(num):  # 定义函数(必须)
    print 'this is the thread ', num
    time.sleep(1)

for i in range(20):
    t = threading.Thread(target=run,args=(i,))  # 实例化,target表示需要使用多线程的函数名,args为传入的参数,必须为元组,所以如果只有一个参数,需要加,号
    t.start() #运行

多线程需要考虑的问题

在使用多线程的时候,线程之间会抢占资源,不按顺序执行,比如:在连接主机的时候,我们希望从连接到连接成功之前,目标IP保持不变,很显然,如果连接的时候目标IP发生变化,会导致连接出错或者验证失败。比如


import paramiko
import socket
import time
import threading
starttime = time.time()
user = 'yunwsn'
passwd = '123456'
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
IP = file('IP.txt','rb')
def run(ip): # 定义函数
    try:
        s.connect(ip,username=user,password=passwd,timeout=5,look_for_keys=False,allow_agent=False)
        print '[ \033[0;32m success\033[0m ] login %s ' %ip
        cmd = s.invoke_shell()
        command = file('command.txt','rb')
        for command in command.xreadlines():
            cmd.send(command)
            time.sleep(0.3)
            output = cmd.recv(65535)
            print output
        cmd.close()
    except paramiko.ssh_exception.NoValidConnectionsError:
        print '[ \033[0;31m failed \033[0m ] Unable to connect to %s ' % ip
    except socket.error,err:
        print '[ \033[0;31m failed \033[0m ] %s to %s' %(err,ip)
    except paramiko.ssh_exception.AuthenticationException:
        print '[ \033[0;31m failed \033[0m ] Authentication failed on %s' % ip

for i in IP.xreadlines():  # 循环IOP
        t = threading.Thread(target=run, args=(i,)) # 多线程实例化
        t.start()  # 启用多线程
IP.close()

执行效果如下:


[root@yunwei cisco]# python ywsn_p_c_lab4.py 

[  failed  ] Authentication failed on 192.168.108.252

[  failed  ] Authentication failed on 192.168.108.253

[  failed  ] Authentication failed on 192.168.108.251

[root@yunwei cisco]# 

这时候我们就需要用到RLock办法了,RLock可以在指定的范围内锁定值,保证这个值使不会被修改。很明显在我们这个程序用,我们要在s.connect(ip,username=user,password=passwd,timeout=5,look_for_keys=False,allow_agent=False)这里进行数据锁定,直到它连接成功。

  • 如何锁定数据
    那怎么锁定呢?这需要使用到RLock办法,具体使用如下:

lock = threading.RLock()  # 实例化
lock.acquire() # 开始锁定
lock.release() # 解锁

我们只需要在开始锁定和解锁之间加上程序需要锁定值的代码即可


def run(ip):
    try:
        lock.acquire()
        s.connect(ip,username=user,password=passwd,timeout=5,look_for_keys=False,allow_agent=False)
        lock.release()
        print '[ \033[0;32m success\033[0m ] login %s ' %ip

对于命令来说也是一样的,在执行命令的时候,需要锁定该值,不然会出现以下情况:


Sw2(config)#
name V80
Sw1(config-vlan)#
vlan 100
Sw3(config-vlan)#
int e0/1
Sw2(config-if)#
vlan 90
Sw1(config-vlan)#
name V100
Sw3(config-vlan)#
switchport mode access
Sw2(config-if)#
name V90
Sw1(config-vlan)#
exit
Sw3(config)#
switchport trunk encapsulation dot1q

数据全部乱了…

实现代码


import paramiko
import socket
import time
import threading
user = 'yunwsn'
passwd = '123456'
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
IP = file('IP.txt','rb')
lock = threading.RLock()
def run(ip):
    try:
        lock.acquire()
        s.connect(ip,username=user,password=passwd,timeout=5,look_for_keys=False,allow_agent=False)
        lock.release()
        print '[ \033[0;32m success\033[0m ] login %s ' %ip
        cmd = s.invoke_shell()
        command = file('command.txt','rb')
        for command in command.xreadlines():
            lock.acquire()
            cmd.send(command)
            lock.release()
            time.sleep(0.3)
            output = cmd.recv(65535)
            print output
        cmd.close()
    except paramiko.ssh_exception.NoValidConnectionsError:
        print '[ \033[0;31m failed \033[0m ] Unable to connect to %s ' % ip
    except socket.error,err:
        print '[ \033[0;31m failed \033[0m ] %s to %s' %(err,ip)
    except paramiko.ssh_exception.AuthenticationException:
        print '[ \033[0;31m failed \033[0m ] Authentication failed on %s' % ip

for i in IP.xreadlines():
        t = threading.Thread(target=run, args=(i,))
        t.start()
IP.close()
  • 效果(动图)
    运维少年系列 python and cisco (4)
上一篇:利用python实现日间、星期客流高峰提示


下一篇:python-用户登录小程序