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

题目要求

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

代码

#!/usr/bin/env python3
import sys, paramiko, os, time, pickle
from multiprocessing import Process, Lock
import logging

logging.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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值