1、要求
题目:简单主机批量管理工具
需求:
1.主机分组
2.主机信息配置文件用configparser解析
3.可批量执行命令、发送文件,结果实时返回,执行格式如下 1.batch_run -h h1,h2,h3 -g web_clusters,db_servers -cmd "df -h" 2.batch_scp -h h1,h2,h3 -g web_clusters,db_servers -action put -local test.py -remote /tmp/
4.主机用户名密码、端口可以不同
5.执行远程命令使用paramiko模块
6.批量命令需使用multiprocessing并发
2、实现
(1)文档结构
hostdetail是存放主机信息的
main是主程序
两个test1 2文件是用来测试上传下载文件的
(2)主要思路
主机信息要从文件里读出来,放在一个字典里,字典嵌套,以组分开
批量处理要用threading类,批量处理,先把需要的信息放在__init__中进行初始化,批量处理的逻辑放在run中,主程序中实例化线程,再start即可
1 import paramiko 2 import threading 3 import os 4 5 class batchthread(threading.Thread): 6 def __init__(self,hostip,hostport,user,passwd,cmd): 7 super(batchthread,self).__init__() 8 self.ip=hostip 9 self.port=hostport 10 self.user=user 11 self.passwd=passwd 12 self.cmd=cmd 13 return 14 15 def run(self): 16 #发送命令执行的代码 17 ssh=paramiko.SSHClient() 18 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 19 ssh.connect(hostname=self.ip,port=self.port,username=self.user,password=self.passwd) 20 21 stdin,stdout,stderr=ssh.exec_command(self.cmd) 22 23 result=stdout.read()#读出来的是byte,要decode才能看懂结果 24 print(result.decode('utf-8')) 25 26 ssh.close() 27 return 28 29 class filebatch(threading.Thread): 30 def __init__(self,hostip,hostport,user,passwd,file,targetfile): 31 super(batchthread,self).__init__() 32 self.ip=hostip 33 self.port=hostport 34 self.user=user 35 self.passwd=passwd 36 self.putfile=file 37 self.targetfile=targetfile 38 return 39 40 def run(self): 41 #建立对象,用户名密码连接,建立ftp对象,put上传,get下载 42 transport=paramiko.Transport( (self.ip,self.port) ) 43 transport.connect(username=self.user,password=self.passwd) 44 45 sftp=paramiko.SFTPClient.from_transport(transport) 46 sftp.put(self.putfile,self.targetfile) 47 transport.close() 48 return 49 50 def chooseact(): 51 act=input("输入您要做的操作选项:\n1、批量命令\n2、上传文件") 52 return 53 54 #用户输入名字和口令登陆本应用程序 55 appname=input("请输入用户名:") 56 kouling=input("请输入密码:") 57 if appname=='admin' and kouling=='admin': 58 print("登陆成功") 59 # 首先获取主机信息,信息存在文件里,要读出来, 60 # 一个主机的信息,放在一个list中,按顺序 主机名、主机ip、port、用户名、密码 61 # 根据它的属组,放在字典里, 62 #字典设计: 63 ''' 64 hostdic= 65 { 66 '组名1':[hostinfo1,hostinfo2.....] 67 '组名2':[hostinfo3,hostinfo4.....] 68 } 69 hostinfo={ 70 主机名:主机ip, 71 port:主机port, 72 用户名:密码} 73 ''' 74 rootdir = os.path.dirname(os.path.dirname(__file__)) 75 hostfiledir = os.path.join(rootdir, 'hostlist', 'hostdetail') 76 77 hostdic={} 78 with open(hostfiledir,'r') as fd: 79 line=fd.readline() 80 while line: 81 list=line.split() 82 hostinfo={ 83 'hostname':list[1], 84 'hostip':list[2], 85 'port':list[3], 86 'user':list[4], 87 'password':list[5] 88 } 89 if list[0] in hostdic: 90 hostdic[list[0]].append(hostinfo) 91 else: 92 hostdic[list[0]]=[] 93 hostdic[list[0]].append(hostinfo) 94 line=fd.readline() 95 # 到这里,文件里的主机信息已经存在dic里面了,后面的过程就是要读取相应的信息了 96 97 #第一步显示主机信息 98 for key in hostdic: 99 print(key) 100 i=0 101 while i <len(hostdic[key]): 102 print('\t'+hostdic[key][i]['hostname']+'\t'+hostdic[key][i]['hostip']) 103 i=i+1 104 105 #第二步 让用户选择要操作的组 106 while True: 107 groupchoose=input("请输入您要操作的主机组,输入组名(q退出):") 108 if groupchoose in hostdic: 109 #操作对象hostdic[groupchoose] 110 lenth=len(hostdic[groupchoose])#要操作的组里有多少台主机 111 # 第三步 让用户选择是要批量处理命令,还是上传文件 112 113 114 115 while True: 116 actchoose=input("请输入您要做的操作(1、批量命令处理 2、上传文件 3、退出):") 117 if actchoose=='1': 118 cmd=input("请输入命令:") 119 #建立多线程,批量各自处理命令 120 j = 0 121 if j < lenth: 122 th = batchthread(hostdic[groupchoose][j]['hostip'], hostdic[groupchoose][j]['port'], 123 hostdic[groupchoose][j]['user'], hostdic[groupchoose][j]['password'],cmd) 124 th.start() 125 j += 1 126 elif actchoose=='2': 127 putfile=input("请输入要上传的文件路径:") 128 putfiletarget=input("请输入要上传到哪里:") 129 j=0 130 if j<lenth: 131 th=filebatch(hostdic[groupchoose][j]['hostip'], hostdic[groupchoose][j]['port'], 132 hostdic[groupchoose][j]['user'], hostdic[groupchoose][j]['password'],putfile,putfiletarget) 133 th.start() 134 j+=1 135 elif actchoose=='3': 136 exit() 137 else: 138 print("输入无效,重新输入。") 139 continue 140 elif groupchoose=='q': 141 exit() 142 else: 143 print("输入无效,重新输入。") 144 continue 145 else: 146 print("登陆失败") 147 exit()