python小练习八——多线程的发布工具

来源:互联网 发布:python 处理get请求 编辑:程序博客网 时间:2024/05/28 09:33

题目要求

1、对机器进行分组
2、对指定组的机器进行批量操作(执行某条命令,上传下载文件)
3、要有操作日志

代码

#!/usr/bin/env python3import sys, paramiko, os, time, picklefrom multiprocessing import Process, Lockimport logginglogging.basicConfig(filename='dingyi.log', level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%Y-%d-%m %I:%M:%S %p')class Dingyi(object): #定义远程传输文件和执行命令的类    def __init__(self, ip):        self.ip = ip        self.port = 22        self.name = 'root'        self.password = '111111'    def link(self):  #连接        #self.ssh = paramiko.SSHClient()        #self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())        #self.ssh.connect(hostname = self.ip, username = 'root', password = '111111')        self.transport = paramiko.Transport((self.ip, self.port))        self.transport.connect(username = self.name, password = self.password)        self.ssh = paramiko.SSHClient()        self.ssh._transport = self.transport        logging.info("connect %s" % self.ip)        self.sftp = paramiko.SFTPClient.from_transport(self.transport)    def close(self): #断开链接        self.transport.close()        logging.info("close %s" % self.ip)    def cmd(self, user_cmd): #执行命令        stdin, stdout, stderr = self.ssh.exec_command(user_cmd)        result = str(stdout.read().decode())        res_err = str(stderr.read().decode())        if not res_err:            logging.info("bash %s at %s success" % (user_cmd, self.ip))            return result        else:            logging.warning("bash %s at %s fail" % (user_cmd, self.ip))            return res_err    def put(self, local_file_name, target_file_name): #上传文件        try:            self.sftp.put(local_file_name, target_file_name)            logging.info("put %s to %s" % (local_file_name, target_file_name))        except IsADirectoryError:            print("%s文件读取错误,请输入文件\n" % local_file_name)            logging.error("put:%s文件读取错误" % local_file_name )        except FileNotFoundError:            print("%s文件没有找到\n" % local_file_name)            logging.error("put:%s文件没有找到" % local_file_name)        except OSError:            print("%s目标目录不是文件\n" % target_file_name)            logging.error("put:%s目标目录不是文件" % target_file_name)    def get(self, target_file_name, local_file_name): #下载文件        try:            self.sftp.get(target_file_name, local_file_name)            logging.info('get %s to %s' % (target_file_name, local_file_name))        except IsADirectoryError:            print("%s文件读取错误,请输入文件" % local_file_name)            logging.error("get:%s文件读取错误" % local_file_name )        except FileNotFoundError:            print("%s文件没有找到" % local_file_name)             logging.error("get:%s文件读取错误" % local_file_name )        except OSError:            print("%s目标目录不是文件" % target_file_name)            logging.error("get:%s文件读取错误" % local_file_name )    def putdir(self, local_dir, target_dir): #上传目录        try:            dir_list = os.listdir(local_dir) #检查本地目录,获取目录内所有目录和文件        except FileNotFoundError:            print("没有找到此目录%s 或目标目录不正确" % local_dir)            logging.error("putdir:没有找到此目录%s 或目标目录不正确" % local_dir)            sys.exit()        except NotADirectoryError:            print("%s这不是个目录 或目标目录不正确" % local_dir)            logging.error("putdir:%s这不是个目录 或目标目录不正确" % local_dir)            sys.exit()        for i in dir_list: #遍历目录内容            if local_dir[-1] != os.sep: #检查目录末尾是否有'/'                local_dir += os.sep            if target_dir[-1] != os.sep:                target_dir += os.sep            local_file = local_dir + i #将目录拼接成子目录            target_file = target_dir + i            if os.path.isdir(local_file): #如果子目录是文件,则递归                target_dir_temp = target_dir + i                local_dir_temp =  local_dir + i                cmd2 = "mkdir %s" % target_dir_temp                a,b,c = self.ssh.exec_command(cmd2)                time.sleep(0.1) #这里要暂停一下,因为在远程的时候,上传文件要比创建子目录快                self.putdir(local_dir_temp, target_dir_temp)            else: #是文件,上传文件                self.put(local_file, target_file)    def getdir(self, target_dir, local_dir):        user_cmd = "ls -l %s" % target_dir #获取远程目录信息        res = self.cmd(user_cmd).strip()        for i in res.split('\n'): #遍历远程目录            if target_dir[-1] != os.sep: #判断目录结尾是否有'/'                target_dir = target_dir + os.sep            if local_dir[-1] != os.sep:                local_dir = local_dir + os.sep            if i[0] == 'd': #如果是目录,在本地创建目录,并递归                dir_name = i.split()[-1]                target_dir_temp = target_dir + dir_name                local_dir_temp = local_dir + dir_name                os.makedirs(local_dir_temp)                self.getdir(target_dir_temp, local_dir_temp)            elif i[0] == '-': #如果是文件,下载文件                file_name = i.split()[-1]                target_file_name = target_dir + file_name                local_file_name = local_dir + file_name                self.get(target_file_name, local_file_name)def get_group(group_name): #获取机器IP地址组    with open("group", 'rb') as f:        group_dict = pickle.load(f)    try:        return group_dict[group_name]    except KeyError:        return '输入的组名错误'def help(): #帮助文档    title = '''输入错入应输入 python3 dingyi -g 组名 -选项选项可以是:-cmd 命令-put 本地文件 远程目标文件-get 远程目标文件 本地文件-putdir 本地目录 远程目标目录-getdir 远程目标目录 本地目录'''    print(title)def get_user_cmd(target_ip, l): #分析用户输入的命令    l.acquire() #进程锁    #当选项存在时,完成相应的操作    if '-cmd' in sys.argv:        cmd_index = sys.argv.index('-cmd')        try: #判断参数是否正确            user_cmd = sys.argv[cmd_index + 1]        except IndexError:            help()            sys.exit()        rel_cmd(target_ip, user_cmd)    if '-get' in sys.argv:        get_index = sys.argv.index('-get')        try:            target_file_name = sys.argv[get_index + 1]            local_file_name = sys.argv[get_index + 2]        except IndexError:            help()            sys.exit()        rel_get(target_ip, target_file_name, local_file_name)    if '-put' in sys.argv:        put_index = sys.argv.index('-put')        try:            local_file_name = sys.argv[put_index + 1]            target_file_name = sys.argv[put_index + 2]        except IndexError:            help()            sys.exit()        rel_put(target_ip, local_file_name, target_file_name)    if '-getdir' in sys.argv:        getdir_index = sys.argv.index('-getdir')        try:            target_dir = sys.argv[getdir_index + 1]            local_dir = sys.argv[getdir_index + 2]        except IndexError:            help()            sys.exit()        rel_getdir(target_ip, target_dir, local_dir)    if '-putdir' in sys.argv:        putdir_index = sys.argv.index('-putdir')        try:            local_dir = sys.argv[putdir_index + 1]            target_dir = sys.argv[putdir_index + 2]        except IndexError:            help()            sys.exit()        rel_putdir(target_ip, local_dir, target_dir)    l.release() #解锁def rel_cmd(target_ip, user_cmd): #命令操作    dingyi = Dingyi(target_ip)    dingyi.link()    res = dingyi.cmd(user_cmd)    dingyi.close()    print(res)def rel_put(target_ip, local_file_name, target_file_name): #上传文件操作    dingyi = Dingyi(target_ip)    dingyi.link()    dingyi.put(local_file_name, target_file_name)    dingyi.close()def rel_get(target_ip, target_file_name, local_file_name): #下载文件操作    dingyi = Dingyi(target_ip)    dingyi.link()    dingyi.get(target_file_name, local_file_name)     dingyi.close()def rel_getdir(target_ip, target_dir, local_dir):#下载目录操作    dingyi = Dingyi(target_ip)    dingyi.link()    dingyi.getdir(target_dir, local_dir)    dingyi.close()def rel_putdir(target_ip, local_dir, target_dir):#上传目录操作    dingyi = Dingyi(target_ip)    dingyi.link()    dingyi.putdir(local_dir, target_dir)    dingyi.close()def run(): #程序主体    if '-g' in sys.argv: #判断是否输入主机组        group_index = sys.argv.index('-g')        group_name = sys.argv[group_index + 1]    else:        help()        sys.exit()    #判断是否输入参数    if '-cmd' not in sys.argv and '-put' not in sys.argv and '-get' not in sys.argv and '-putdir' not in sys.argv and '-getdir' not in sys.argv:        help()        sys.exit()    ip_list = get_group(group_name)     l = Lock()    process_list = []    for i in ip_list:        t = Process(target = get_user_cmd, args = (i,l, ))        process_list.append(t)    for i in process_list:        i.start()if __name__ == "__main__":    run()