类 Fabric 主机管理程序开发:
1. 运行程序列出主机组或者主机列表
2. 选择指定主机或主机组
3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载)
4. 充分使用多线程或多进程
5. 不同主机的用户名密码、端口可以不同
README
类 Fabric 主机管理程序
执行命令(SSH)
向其传输文件(上传/下载)
Fabric/#程序目录
|- - -__init__.py
|- - -bin/#启动目录
| |- - -__init__.py
| |- - -Fabric_start.py#视图启动
| |- - -user_reg.py#主机添加启动
|
|- - -cfg/#配置目录
| |- - -__init__.py
| |- - -config.py#配置文件
|
|- - -core/#下载文件目录
| |- - -__init__.py
| |- - -main.py#主要逻辑 类
|
|- - -db/#主机列表文件目录
| |- - -
|
|- - -get_file/#下载文件目录
|
|
|- - -put_file/#上传文件目录
|- - -REDMAE
Fabric/#程序目录
|- - -__init__.py
|- - -bin/#启动目录
| |- - -__init__.py
| |- - -Fabric_start.py#视图启动
1 import configparser 2 import os ,sys 3 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 4 sys.path.append(BASE_DIR)#增加环境变量 5 from core.main import loging 6 if __name__ == '__main__': 7 8 loging()
| |- - -user_reg.py#主机添加启动
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import configparser 6 import os ,sys 7 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 8 sys.path.append(BASE_DIR)#增加环境变量 9 from cfg import config 10 #修改个信息 磁盘大小 11 def set_info(gr_name,addse,name,pwd,ports): 12 config_info=configparser.ConfigParser()#读数据 13 file_dir='%s%s'%(config.AUTH_FILE,gr_name)#主机组用户名密码文件路径 14 15 config_info[addse]={}#ip 主机 16 config_info.set(addse,config.USER,name)#用户 17 config_info.set(addse,config.PWD,pwd)#密码 18 config_info.set(addse,config.PORTS,ports)#端口 19 with open(file_dir,'a') as f: 20 config_info.write(f)#写入文件 21 #config_info.write(open(file_dir,'a'))#写入文件 22 print('创建完成'.center(60,'=')) 23 print('组:【%s】 IP:[%s] 用户名:[%s] 密码:[%s] 端口:[%s]'%(gr_name,addse,name,pwd,ports)) 24 25 if __name__ == '__main__': 26 gr_name=input('组名:')#组 27 addse=input('IP地址:')#ip地址 28 name=input('用户名:')#用户 29 pwd=input('密码:')#密码 30 ports=input('端口:')#端口 31 32 set_info(gr_name,addse,name,pwd,ports)
|- - -cfg/#配置目录
| |- - -__init__.py
|- - -config.py#配置文件
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import configparser 6 import os ,sys 7 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 8 sys.path.append(BASE_DIR)#增加环境变量 9 10 AUTH_FILE='%s/db/'%BASE_DIR#主机组 信息用户名密码文件路径 11 FILE_DIR='%s/put_file'%BASE_DIR#要上传文件所在的目录 12 GET_FILE_DIR='%s/get_file'%BASE_DIR#要上传文件所在的目录 13 #print(AUTH_FILE) 14 PWD='pwd'#密码 15 USER='user' 16 PORTS='ports' 17 INST_LIST=['put','get']#指令列表 18 19 PUT='put' 20 GET='get'
|- - -core/#下载文件目录
| |- - -__init__.py
| |- - -main.py#主要逻辑 类
1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import configparser 6 import os ,sys 7 import threading,time 8 import paramiko,queue 9 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量 10 sys.path.append(BASE_DIR)#增加环境变量 11 from cfg import config 12 13 class Fabric_gr(object): 14 def __init__(self,gr_name):#组名 15 self.gr_name='%s%s'%(config.AUTH_FILE,gr_name)#主机组用户名密码文件路径 16 self.config_info=configparser.ConfigParser()#读数据对象 17 self.name_l=[]#定义一个列表 18 self.attr=[] 19 self.file_dir=''#上传文件路径 20 self.get_file=''#下载传文件路径 21 22 def group_open(self):#打开组文件 23 self.config_info.read(self.gr_name)#读取文件 24 for i in range(len(self.config_info.sections())): 25 self.name_l.append(self.config_info.sections()[i])#信息添加到列表 26 else: 27 print('主机列表:'.center(40,'=')) 28 for i in self.name_l: 29 print(('[%s]'%i).center(40,' ')) 30 31 def inst_attr(self,inst):#获取指令 32 self.instruction=inst 33 self.attr=self.instruction.split() 34 self.inst_a=self.attr[0] 35 36 def inst(self):#指令判断 37 if self.inst_a in config.INST_LIST: 38 return True 39 else: 40 return False 41 42 def open_list(self):#创建 线程 方法 43 if self.inst_a==config.PUT: 44 if self.File_Dir():#查找本地文件 45 pass 46 else: 47 return 48 self.re_lilst=[]#定义一个列表 49 for j in range(len(self.name_l)): 50 sttr=self.config_info.sections()[j]#获取到对象 51 user_dict={}#创建一个空字典 52 for i,v in self.config_info[sttr].items():#可以循环输出 获ip 用户 密码 端口 53 user_dict[i]=v 54 sttr=threading.Thread(target=self.thr_run,args=(sttr,user_dict[config.USER],user_dict[config.PWD],int(user_dict[config.PORTS])))#创建新线程 55 sttr.start()#启动线程 56 self.re_lilst.append(sttr)#不用JOIN,避免阻塞为串行 57 else: 58 for i in self.re_lilst:#等待线程 完成 59 i.join() 60 61 def open_list2(self):#创建 线程 方法 62 self.re_lilst=[]#定义一个列表 63 for j in range(len(self.name_l)): 64 sttr=self.config_info.sections()[j]#获取到对象 65 user_dict={}#创建一个空字典 66 for i,v in self.config_info[sttr].items():#可以循环输出 获ip 用户 密码 端口 67 user_dict[i]=v 68 sttr=threading.Thread(target=self.ssh_run,args=(sttr,user_dict[config.USER],user_dict[config.PWD],int(user_dict[config.PORTS])))#创建新线程 69 sttr.start()#启动线程 70 self.re_lilst.append(sttr)#不用JOIN,避免阻塞为串行 71 else: 72 for i in self.re_lilst:#等待线程 完成 73 i.join() 74 75 76 def thr_run(self,addrs,user,paswd,ports):#传输通道 77 try: 78 transport=paramiko.Transport((addrs,ports))#传输模块 Transport 服务器地址 端口 79 transport.connect(username=user,password=paswd)#用户名,,密码 80 sftp=paramiko.SFTPClient.from_transport(transport)#调用传输方法 81 print('[%s]连接成功!'%addrs) 82 self.file_dir='%s/%s'%(config.FILE_DIR,self.attr[1])#上传文件路径 83 if self.inst_a==config.PUT: 84 sftp.put(self.file_dir,self.attr[2])#上传文件 ,本地路径文件 ,服务器的路径文件 85 print('【%s】文件上传完成!'%addrs) 86 elif self.inst_a==config.GET: 87 self.get_file='%s/%s_%s'%(config.GET_FILE_DIR,addrs,self.attr[2])#下载文件路径 88 print(self.get_file) 89 sftp.get(self.attr[1],self.get_file)#下载文件 ,服务器的路径文件 ,本地路径文件 90 print('【%s】文件下载完成!'%addrs) 91 else: 92 print('【%s】文件相关操作失败!'%addrs) 93 pass 94 except Exception as e: 95 print(e) 96 97 def File_Dir(self):#判断文件是否存在 98 file=self.attr[1] 99 100 print(file) 101 self.file_dir='%s/%s'%(config.FILE_DIR,file)#文件路径 102 if os.path.isfile(self.file_dir): 103 print('成功找到文件!') 104 return True 105 else: 106 print('文件不存在!') 107 return False 108 def ssh_run(self,addrs,user,paswd,ports):#ssh 109 ssh =paramiko.SSHClient()#创建一个SSH连接对象 110 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())#允许连接不在KNOV_HOSTs文件中的主机 自动添加 111 try: 112 ssh.connect(hostname=addrs,port=ports,username=user,password=paswd)#连接,主机 端口 用户名 密码 113 print('[%s]连接成功!'%addrs) 114 except Exception as e: 115 print(e) 116 return 117 stdin,stdout,stderr=ssh.exec_command(self.instruction)#.exec_command 为执行命令,返回结果 ,标准输入,标准输出,标准错误,错误与输出只会返回其一 118 result=stdout.read()#获取结果 119 try: 120 if len(result)<1:#如果为空 返回错误信息 121 result=stderr.read() 122 print(addrs.center(60,'=')) 123 print(result.decode()) 124 else: 125 print(addrs.center(60,'=')) 126 print(result.decode()) 127 except Exception as e: 128 print(e) 129 130 131 info_l='''--------指令帮助-------- 132 上传文件: put file /home/tmp/file (指令 本地文件 服务端位置文件) 133 下载文件: get /home/tmp/file file (指令 服务端位置文件 本地文件) 134 其他指令: ssh相关命令 如 df pwd ifconfig ls等 135 查看帮助: helps 136 返回上层: quit 137 退出程序: exit 138 ''' 139 140 141 def loging(): 142 print(info_l) 143 while True: 144 s=os.listdir(config.AUTH_FILE) 145 print('主机组'.center(60,'=')) 146 for i,v in enumerate(s): 147 print('编号:%s 组名:%s'%(i,v)) 148 gr_name=input('选择组:') 149 if gr_name=='exit': 150 exit() 151 if gr_name=='helps': 152 print(info_l) 153 continue 154 try: 155 gr_file=s[int(gr_name)] 156 157 lst=Fabric_gr(gr_file)#实例连接 158 lst.group_open()#打开 159 while True: 160 #print(info_l) 161 inst=input('指令>>>:') 162 if inst=='exit': 163 exit() 164 if inst=='quit': 165 continue 166 if inst=='helps': 167 print(info_l) 168 continue 169 lst.inst_attr(inst)#获取指令 170 if lst.inst():#指令判断 171 lst.open_list()#开启线程创建 172 else: 173 lst.open_list2() 174 pass 175 except ValueError as e: 176 print(e)