自学python后的第一个能用于实践的成果,有点小成就感,加油!!! 

根据学习的相关语法,参考网络上相关资料,整理完成交换机批量配置的脚本,后期有遇到情况,再做变更。

        代码部分可能看起来比较乱,因为包含了修改过程,在一点点的完善。保留了注释,为了以后方便查看。怕时间久了会忘记,^_^

##批量修改交换机的某一项配置:比如:新建或删除或修改账号
import paramiko
import time
import getpass
import sys
import socket #为了使用try-except来应对网络设备不可达引起的socket.error,这里我们必须import socket

username=input('请输入用户名:')
password=input('Password:')
'''
#password=getpass.getpass()
getpass()在Linux或CMD中可正常显示,在pycharm中无法直接运行。
使用交互式输入用户名和密码,其中用户名使用input()函数,明文;密码使用getpass模块的方法,密文。
'''
'''
创建一个文本文件,把我们需要登录的交换机ip全部写进去,
然后用for...in...语句,配合open()函数来批量登录所有交换机
'''
ip_file=sys.argv[1]
cmd_file=sys.argv[2]
'''
使用sys模块里的argv[],「argv」是「argument variable」参数变量的简写形式,这个变量返回的是一个列表,
argv[0] 一般是被调用的脚本的文件名或全路径,从argv[1]开始就是传入的数据了
在终端中执行:
[root@localhost]#python sw.py h3c_v5_ip.txt h3c_v5_cmd.txt
这里argv=['sw.py','h3c_v5_ip.txt','h3c_v5_cmd.txt']
ip_file=sys.argv[1]就=h3c_v5_ip.txt
cmd_file=sys.argv[2]就=h3c_v5_cmd.txt
'''

switch_with_authentication_issue={}
switch_not_reachable={}
'''创建两个空字典, 分别在脚本最后配合for循环来统计有哪些设备是因为认证问题无法登录,
有哪些是因为设备本身不可达而无法登录
'''
ip_list=open(ip_file,'r')
for line in ip_list.readlines():
    try:
        lst = line.split()
        hostname = lst[0].strip() #strip()去掉空格
        ip = lst[1].strip()
        #将IP地址和主机名分离出来
        client=paramiko.SSHClient() #调用SSHClient()方法并赋给变量client
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #设置host_key机制,使用paramiko自动机制,没有这条会报错找不到主机,无法登录设备
        client.connect(hostname=ip,username=username,password=password,compress=True) #调用connect()方法
        print('-----------------欢迎登陆交换机',hostname,ip,'---------------------')
        command=client.invoke_shell() #调用paramiko的invoke_shell()方法,将其assign给command这个变量。
        cmdlist=open(cmd_file,'r')
        cmdlist.seek(0)
        for cmd in cmdlist.readlines():
            command.send(cmd)
            time.sleep(1)
        cmdlist.close()
        output=command.recv(65535)
        print(output.decode(encoding='utf-8'))
        print('------------------命令执行完毕-----------------------')
    except paramiko.ssh_exception.AuthenticationException:
        print('User authentication failed for' + ip + '.')
        switch_with_authentication_issue[hostname]=ip
    except socket.error:
        print(ip + 'is not reachable')
        switch_not_reachable[hostname]=ip
    '''
    在for循环下使用try-except, 用excpet paramiko.ssh_exception.AuthenticationException:来
    应对用户名/密码不匹配时返回的错误代码,将出现该错误的交换机的管理IP地址当做value值,主机名做key
    添加到switch_with_authentication_issue这个字典中;
    同理用except socket.error:来应对交换机不可达时返回的错误代码,
    将出现该错误的交换机的管理IP地址做value值,主机名做key,添加到switch_not_reachable这个字典中。
    '''
'''本段是简单配置,将命令行写到代码中,实际环境下设备命令格式多样化,这种方法不适用
    # command.send('system-view\n')
    # command.send('int GigabitEthernet 0/0/2\n')
    # command.send('des test\n')
    # command.send('quit\n')
    # command.send('quit\n')
    # command.send('quit\n') #让command配合send()这个函数来对交换机下发配置,注意末尾要有换行符\n,相当于敲回车
    # print('------------------命令执行完毕-----------------------')
    # time.sleep(2) #交换机运行命令可能有延时,让系统延后2秒运行下面的内容
    # out=command.recv(65535)
    # #mylog=open('log.txt','w')
    # #print(out.decode(encoding='utf-8'),file=mylog)  #将回显信息保存到mylog文件中
    # print(out.decode(encoding='utf-8')) #输出的内容默认是二进制字符格式,需要解码成字节,显示内容才和交换机的一样
    #stdin,stdout,stderr=client.exec_command('display vlan')
'''
ip_list.close()
client.close()

print('User authentication failed for below swtiches:')
for i in switch_with_authentication_issue:
    print(i,switch_with_authentication_issue[i])
print('Below swtiches are not reachable:')
for i in switch_not_reachable:
    print(i,switch_not_reachable[i])
'''
在最后将两种错误的主机列表打印出来
'''