类 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】\nIP:[%s]\n用户名:[%s]\n密码:[%s]\n端口:[%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.q=queue.Queue()#创建一个队列 19 self.event=threading.Event()#生成一个标示位对象 20 self.attr=[] 21 self.file_dir=''#上传文件路径 22 self.get_file=''#下载传文件路径 23 24 def group_open(self):#打开组文件 25 self.config_info.read(self.gr_name)#读取文件 26 for i in range(len(self.config_info.sections())): 27 self.name_l.append(self.config_info.sections()[i])#信息添加到列表 28 else: 29 print('主机列表:'.center(40,'=')) 30 for i in self.name_l: 31 print(('[%s]'%i).center(40,' ')) 32 33 def inst_attr(self,inst):#获取指令 34 self.instruction=inst 35 self.attr=self.instruction.split() 36 self.inst_a=self.attr[0] 37 38 def inst(self):#指令判断 39 if self.inst_a in config.INST_LIST: 40 return True 41 else: 42 return False 43 44 def open_list(self):#创建 线程 方法 45 if self.File_Dir():#查找本地文件 46 pass 47 else: 48 return 49 self.re_lilst=[]#定义一个列表 50 for j in range(len(self.name_l)): 51 sttr=self.config_info.sections()[j]#获取到对象 52 user_dict={}#创建一个空字典 53 for i,v in self.config_info[sttr].items():#可以循环输出 获ip 用户 密码 端口 54 user_dict[i]=v 55 sttr=threading.Thread(target=self.thr_run,args=(sttr,user_dict[config.USER],user_dict[config.PWD],int(user_dict[config.PORTS])))#创建新线程 56 sttr.start()#启动线程 57 self.re_lilst.append(sttr)#不用JOIN,避免阻塞为串行 58 else: 59 for i in self.re_lilst:#等待线程 完成 60 i.join() 61 62 def open_list2(self):#创建 线程 方法 63 self.re_lilst=[]#定义一个列表 64 for j in range(len(self.name_l)): 65 sttr=self.config_info.sections()[j]#获取到对象 66 user_dict={}#创建一个空字典 67 for i,v in self.config_info[sttr].items():#可以循环输出 获ip 用户 密码 端口 68 user_dict[i]=v 69 sttr=threading.Thread(target=self.ssh_run,args=(sttr,user_dict[config.USER],user_dict[config.PWD],int(user_dict[config.PORTS])))#创建新线程 70 sttr.start()#启动线程 71 self.re_lilst.append(sttr)#不用JOIN,避免阻塞为串行 72 else: 73 for i in self.re_lilst:#等待线程 完成 74 i.join() 75 76 77 def thr_run(self,addrs,user,paswd,ports):#传输通道 78 try: 79 transport=paramiko.Transport((addrs,ports))#传输模块 Transport 服务器地址 端口 80 transport.connect(username=user,password=paswd)#用户名,,密码 81 sftp=paramiko.SFTPClient.from_transport(transport)#调用传输方法 82 print('[%s]连接成功!'%addrs) 83 self.file_dir='%s/%s'%(config.FILE_DIR,self.attr[1])#上传文件路径 84 if self.inst_a==config.PUT: 85 sftp.put(self.file_dir,self.attr[2])#上传文件 ,本地路径文件 ,服务器的路径文件 86 print('【%s】文件上传完成!'%addrs) 87 elif self.instruction==config.GET: 88 self.get_file='%s/%s'%(config.GET_FILE_DIR,self.attr[2])#下载文件路径 89 sftp.get(self.attr[1],self.get_file)#下载文件 ,服务器的路径文件 ,本地路径文件 90 else: 91 pass 92 except Exception as e: 93 print(e) 94 95 def File_Dir(self):#判断文件是否存在 96 file=self.attr[1] 97 print(file) 98 self.file_dir='%s/%s'%(config.FILE_DIR,file)#文件路径 99 if os.path.isfile(self.file_dir): 100 print('成功找到文件!') 101 return True 102 else: 103 print('文件不存在!') 104 return False 105 def ssh_run(self,addrs,user,paswd,ports):#ssh 106 ssh =paramiko.SSHClient()#创建一个SSH连接对象 107 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())#允许连接不在KNOV_HOSTs文件中的主机 自动添加 108 try: 109 ssh.connect(hostname=addrs,port=ports,username=user,password=paswd)#连接,主机 端口 用户名 密码 110 print('[%s]连接成功!'%addrs) 111 except Exception as e: 112 print(e) 113 return 114 stdin,stdout,stderr=ssh.exec_command(self.instruction)#.exec_command 为执行命令,返回结果 ,标准输入,标准输出,标准错误,错误与输出只会返回其一 115 result=stdout.read()#获取结果 116 try: 117 if len(result)<1:#如果为空 返回错误信息 118 result=stderr.read() 119 print(addrs.center(60,'=')) 120 print(result.decode()) 121 else: 122 print(addrs.center(60,'=')) 123 print(result.decode()) 124 except Exception as e: 125 print(e) 126 127 128 info_l='''--------指令帮助-------- 129 上传文件: put file /home/tmp/file (指令 本地文件 服务端位置文件) 130 下载文件: put /home/tmp/file file (指令 服务端位置文件 本地文件) 131 其他指令: ssh相关命令 如 df pwd ifconfig ls等 132 查看帮助: helps 133 返回上层: quit 134 退出程序: exit 135 ''' 136 137 138 def loging(): 139 print(info_l) 140 while True: 141 s=os.listdir(config.AUTH_FILE) 142 print('主机组'.center(60,'=')) 143 for i,v in enumerate(s): 144 print('编号:%s 组名:%s'%(i,v)) 145 gr_name=input('选择组:') 146 if gr_name=='exit': 147 exit() 148 if gr_name=='helps': 149 print(info_l) 150 continue 151 gr_file=s[int(gr_name)] 152 lst=Fabric_gr(gr_file)#实例连接 153 lst.group_open()#打开 154 while True: 155 #print(info_l) 156 inst=input('指令>>>:') 157 if inst=='exit': 158 exit() 159 if inst=='quit': 160 continue 161 if inst=='helps': 162 print(info_l) 163 continue 164 lst.inst_attr(inst)#获取指令 165 if lst.inst():#指令判断 166 lst.open_list()#开启线程创建 167 else: 168 lst.open_list2() 169 pass