接着上节生成的配置文件信息,我们要实现根据配置文件内容实现主机的批量管理。功能亮点:(1)支持raw_iuput列退格重新编辑(2)日志显示加亮(3)使用多进程提升执行效率使用效果图:实现代码如下:#
接着上节生成的配置文件信息,我们要实现根据配置文件内容实现主机的批量管理。
功能亮点:
(1)支持raw_iuput列退格重新编辑(2)日志显示加亮(3)使用多进程提升执行效率
使用效果图:
实现代码如下:
#!/usr/bin/env python#-*- coding:utf-8 -*-#update:20161222#auth:dsc#description:批量管理工具import os,paramiko,sys,time,ConfigParserfrom multiprocessing import Process,Poolimport base64import readline''' 返回命令列表 '''_BACK_CMD_LIST = ('quit','q','exit','bye')''' 不作为命令列表 '''_DO_NOTHING_LIST = ('','/n','/r',None)''' 禁用命令列表 '''_FORBDI_CMD = ('more','less','vi')''' 进程池大小 '''PROCESSES = 30''' 文件分发基础目录 '''DISTRIBUTE_BASE_DIR = '/tmp'''' 初始化配置文件 '''class InitConf: def __init__(self,conf_file): try: file_path = os.path.join(sys.path[0],conf_file) self.cf = ConfigParser.SafeConfigParser() self.cf.read(conf_file) except Exception as e: Log('RED','ConfigParserError:%s' % (str(e))) sys.exit(1) ''' 读取文件配置信息 ''' def readConf(self): hosts=[] try: opts = eval(self.cf.get('host','connList')) for opt in opts: host = [] s = eval(self.cf.get('information',opt)) host.append(s['ip']) host.append(s['user']) host.append(base64.b64decode(s['password'])) host.append(s['port']) hosts.append(host) except Exception as e: Log('RED','ReadConfError:%s' % (str(e))) sys.exit(1) return hosts''' 初始化ssh服务 '''def init_server(): server = paramiko.SSHClient() server.load_system_host_keys() server.set_missing_host_key_policy(paramiko.AutoAddPolicy()) return server ''' 执行命令 '''def exec_pools_cmd(server,server_list,action,cargs): start = time.time() p = Pool(processes = PROCESSES) for h in server_list: if action == 'ssh_run': p.apply_async(ssh_run,[h,] + cargs) elif action == 'distribute_file': p.apply_async(distribute_file,[h,] + cargs) p.close() p.join() end = time.time() print '/033[31;1mCost time:%ss/033[0m' % str(end - start) ''' 初始化日志目录 ''' def chkLogs(): if not os.path.exists(os.path.join(sys.path[0],'log')): os.makedirs(os.path.join(sys.path[0],'log'))''' 获取用户输入 '''def user_input(str): try: cmd = raw_input('/033[32;0m[%s]=>/033[0m' %(str)).strip() return cmd except KeyboardInterrupt: Log('NOMAL','/nKeyboardInterrupt') return None except Exception: print '/n' sys.exit(1)''' 定义日志输出格式 '''def Log(type,msg): date_detail = time.strftime('%Y_%m_%d %H:%M:%S') logText='[%s] %s' %(date_detail,msg) if type == 'NOMAL': print '/033[32;1m%s/033[0m' %(msg) elif type == 'GREEN': print '/033[32;1m[INFO ] %s/033[0m' %(logText) elif type == 'RED': print '/033[31;1m[ERROR] %s/033[0m' %(logText) elif type == 'YELLOW': print '/033[33;1m[WARN ] %s/033[0m' %(logText)''' 操作日志记录 '''def log_write(uargs): date_detail = time.strftime('%Y_%m_%d %H:%M:%S') log = 'Time:%s | Type:%s | Detial:%s | Server:%s | Result:%s/n' % (date_detail,uargs[0],uargs[1],uargs[2],uargs[3]) with open('./log/user_%s_record.log' % (time.strftime('%Y_%m_%d')),'a+') as f: f.write(log)''' 命令执行函数 '''def ssh_run(host_info,cmd,server): try: ip,username,password,port= host_info[0],host_info[1],host_info[2],host_info[3] server.connect(ip,int(port),username,password,timeout=5) stdin,stdout,stderr = server.exec_command(cmd) cmd_result = stdout.read(),stderr.read() for rs in cmd_result: for line in rs.split('/n'): if line.strip() == '': continue else: Log('NOMAL','[%s]: %s' %(ip,line)) except Exception as e: log_write(['cmd batch',cmd,ip,'failed']) Log('RED','[%s]: %s' % (ip,str(e))) else: log_write(['cmd batch',cmd,ip,'success'])''' 文件分发函数 '''def distribute_file(host_info,file_name): try: ip,uname,passwd,port = host_info[0],host_info[1],host_info[2],int(host_info[3]) RemoteFile = os.path.join(DISTRIBUTE_BASE_DIR,os.path.basename(file_name)) t = paramiko.Transport((ip,int(port))) t.connect(username=uname,password=passwd) sftp = paramiko.SFTPClient.from_transport(t) sftp.put(file_name,RemoteFile) t.close() except Exception as e: log_write(['distribute file',file_name,ip,'failed']) Log('RED','[%s] : %s' % (ip,str(e))) else: log_write(['distribute file',file_name,ip,'success']) Log('GREEN','Distribute %s to %s:%s Successfully!' % (file_name,ip,RemoteFile))''' 主函数 '''def main(conf_name): p = InitConf(conf_name) server_list = p.readConf() server = init_server() while True: print ''' ------------------------- [1]Execute command. [2]Distribute files. [q]Exit. -------------------------/n''' choice = user_input('Choice') if choice == '1': while True: cmd = user_input('Cmd') if cmd in _BACK_CMD_LIST: break elif cmd in _DO_NOTHING_LIST: continue elif (set(_FORBDI_CMD) & set(cmd.split())) != set([]): ''' 禁止使用命令列表 ''' Log('RED','Can not use %s command!' %(str(_FORBDI_CMD))) continue exec_pools_cmd(server,server_list,'ssh_run',[cmd,server]) elif choice == '2': while True: file_name = user_input('Distribute') start = time.time() if file_name in _BACK_CMD_LIST: break elif file_name == None: continue file_chcek = os.path.isfile(file_name) if file_chcek == False: Log('YELLOW','The file does not exist or it is a directory!') continue exec_pools_cmd(server,server_list,'distribute_file',[file_name,]) elif choice in _BACK_CMD_LIST: server.close() sys.exit() else: continue''' 程序入口 ''' if __name__ == '__main__': if len(sys.argv) < 2: Log('RED','Usage: python %s test.conf' %(sys.argv[0])) sys.exit(1) else: os.system('clear') conf_name = sys.argv[1] main(conf_name)