zoukankan      html  css  js  c++  java
  • python之路——作业:类Farbic主机管理程序(仅供参考)

    一、作业需求

    1. 运行程序列出主机组或者主机列表
    2. 选择指定主机或主机组
    3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载)
    4. 充分使用多线程或多进程
    5. 不同主机的用户名密码、端口可以不同

    二、实现功能

    1、创建主机
    2、运行程序列出主机列表
    3、选择指定主机或主机组
    4、选择让主机或主机组执行命令或传输文件
    5、充分使用多线程注意:新用户使用本程序1、创建主机------->需根据自己现已开启的主机创建主机,将主机信息以文件的形式保存下来;
                          2、连接主机------->根据用户创建的主机,读取db目录下使用主机信息,返回列表的形式,并逐一尝试连接,连接成功状态设为1,连接不成功状态设为0;
    3、运行主机------->根据上一步确定的可以连接的主机,输出课连接主机列表,根据用户的选择和命令输入来操控主机
    put上传文件的方法------>上传的本地文件需在localhost下,且只用输入文件名即可
    文件保存的路径只用输入保存的目录和文件名“/Downloads/aaa”,程序会自动加上“/用户名”前缀路径
    get上传文件的方法------>从远程主机下载的文件的路径只用输入目录和文件名“/Downloads/aaa”,程序会自动加上“/用户名”前缀路径
    下载的文件默认保存在localhost下
     

    三、目录说明

    类Farbic主机管理程序/
    |-- bin/
    |   |-- __init__.py
    |   |-- para_start.py                #程序启动的主入口
    |
    |-- conf/
    |   |-- __init__.py
    |   |-- settings.py              #配置文件
    |
    |-- db/                             #主机数据目录
    |
    |-- lib/
    |   |-- __init__.py
    |   |-- common.py                 #公共方法程序
    |   |-- main.py                   #主程序
    |
    |-- localhost/                       #模拟本地文件目录
    |   |-- aaa.jpg
    |
    |-- log/
    |   |-- log_sys.log                #日志文件
    |
    |-- 流程图
    |-- README.txt

    四、流程图

    五、程序代码

    1、bin/para_start.py

    import os,sys
    Base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(Base_dir)
    
    from lib.main import main_func
    
    if __name__ == '__main__':
        main_func()
    

    2、conf/settings.py

    import os
    
    Basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    HOST_INFO = os.path.join(Basedir,"db")
    HOST_DIR = os.path.join(Basedir,"home")
    LOCAL_DIR = os.path.join(Basedir,"localhost")
    LOG_DIR = os.path.join(Basedir,"log")
    

    3、lib/common.py

    import logging,os,sys
    frame = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(frame)
    from conf import settings
    #
    def sys_logging(content,levelname):
        '''
        程序记录日志函数
        :param content: 日志的内容
        :param levelname: 日志的等级
        :return: none
        '''
        _filename = os.path.join(settings.LOG_DIR,"log_sys.log")
        log = logging.getLogger(_filename)
        logging.basicConfig(filename=_filename,level=logging.INFO,format='%(asctime)s-%(levelname)s-%(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
        if levelname == 'debug':
            logging.debug(content)
        elif levelname == 'info':
            logging.info(content)
        elif levelname == 'warning':
            logging.warning(content)
        elif levelname == 'error':
            logging.error(content)
        elif levelname == 'critical':
            logging.critical(content)
    
    def show(msg,msg_type):
        '''
        程序不同信息打印的字体颜色
        :param msg: 打印信息
        :param msg_type: 打印信息的类型
        :return: none
        '''
        if msg_type == "info":
            show_msg = "33[1;35m%s33[0m"%msg
        elif msg_type == "error":
            show_msg = "33[1;31m%s33[0m"%msg
        elif msg_type == "msg":
            show_msg = "33[1;37m%s33[0m"%msg
        else:
            show_msg = "33[1;32m%s33[0m"%msg
        print(show_msg)
        sys_logging(msg, msg_type)
    

    4、lib/main.py

    import os,sys,pickle,threading,paramiko
    
    Far_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    lib_dir = os.path.dirname(os.path.abspath(__file__))
    sys.path.append(lib_dir)
    sys.path.append(Far_dir)
    from common import show
    from conf import settings
    
    def creat_host():
        '''
        creat a new host method
        :return: none
        '''
        hostname = input("请输入主机名:>>>").strip()
        port = input("请输入主机端口号:>>>").strip()
        username = input("请输入登录用户名:>>>").strip()
        psd = input("请输入登录密码:>>>").strip()
        host_dic = {
            "hostname":hostname,
            "port":port,
            "username":username,
            "psd":psd,
            "status":0
        }
        host_dir = settings.HOST_DIR+"/"+hostname
        if hostinfo_write(host_dic,hostname):
            show("主机创建成功","error")
    
    def host_connect():
        '''
        connect host method
        :return: none
        '''
        hostinfo_list = hostinfo_read()
        if len(hostinfo_list) == 0:
            exit("当前暂无主机,请先创建主机")
        print("33[1;37m主机列表33[0m".center(40,"-"))
        for dic in hostinfo_list:
            show("	主机名:%s"%dic["hostname"],"msg")
            TH = threading.Thread(target=ssh_parse,args=(dic,))
            TH.setDaemon(True)
            TH.start()
            TH.join()
    
    def ssh_parse(dic):
        '''
        try to connect all host,if can't connect ,make it's status to 0 ,else to 1
        :param dic: host info dic
        :return: none
        '''
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(hostname=dic["hostname"],port=int(dic["port"]),username=dic["username"],password=dic["psd"])
        except Exception as e:
            show("主机[%s]连接失败	原因:%s"%(dic["hostname"],e),"error")
            dic["status"] = 0
            hostinfo_write(dic, dic["hostname"])
        else:
            show("主机[%s]连接成功" % (dic["hostname"]), "a")
            dic["status"] = 1
            hostinfo_write(dic,dic["hostname"])
        ssh.close()
    
    def run_host():
        '''
        try to operate host
        :return: none
        '''
        active_list = []
        hostinfo_list = hostinfo_read()
        for dic in hostinfo_list:
            if dic["status"] == 1:
                active_list.append(dic)
        # print(active_list)
        if len(active_list) == 0:
            exit("当前无连接的主机,请先连接主机确保主机能正常连接")
        show("已连接的主机:","msg")
        for i,j in enumerate(active_list):
            show("%s:%s"%(i+1,j["hostname"]),"msg")
        choice = input("请输入您要操控的主机(输入“all”,所有主机同时运行):>>>").strip()
        if choice == "all":
            host_parse(active_list)
        else:
            list = []
            list.append(active_list[int(choice)-1])
            host_parse(list)
    
    def host_parse(list):
        '''
        if host can be connected , user can input conmand ,and host will carry out the conmand
        :param list:all host info list
        :return:none
        '''
        while True:
            command = input("请输入指令(help显示帮助信息,b返回):>>>").strip()
            if command == "help":
                help_info = '''-----------【help】-----------
        1、输入“put”上传文件
        2、输入“get”下载文件
        3、输入“df”查看磁盘信息
        4、输入“ls”查看文件或目录
        5、输入“uname”查看系统信息
        6、输入“ifconfig”查看网络信息
        7、更多命令详见“http://www.cnblogs.com/japhi/p/7084042.html”
                                    '''
                show(help_info, "msg")
            elif command == "put":
                dir = input("请输入您要上传的文件名(默认文件路径在---localhost):>>>").strip()
                local_dir = settings.LOCAL_DIR + "/" + dir
                if not os.path.exists(local_dir):
                    show("文件名不存在", "error")
                dir0 = input("请输入您要保存的路径(例:/Downloads/bbb):>>>").strip()
    
                for dic in list:
                    TH = threading.Thread(target=put_method, args=(dic, local_dir, dir0,))
                    TH.start()
                    TH.join()
            elif command == "get":
                dir1 = input("请输入您要下载的远程主机文件路径(例:/temp/ccc):>>>").strip()
                res_list = dir1.split("/")
                local_dir = settings.LOCAL_DIR + "/" + res_list[len(res_list) - 1]
                # print(local_dir)
                for dic in list:
                    TH = threading.Thread(target=get_method, args=(dic, dir1, local_dir,))
                    TH.start()
                    TH.join()
            elif command == "b":
                break
            else:
                for dic in list:
                    TH = threading.Thread(target=command_method, args=(dic, command,))
                    TH.start()
                    TH.join()
    
    def put_method(dic,local_dir,dir):
        '''
        upload file method
        :param dic: host info dic
        :param local_dir: the dir of local file
        :param dir: the dir of the file will be savede
        :return: none
        '''
        try:
            nonlocal_dir = "/" + dic["username"] + dir
            print(nonlocal_dir)
            transport = paramiko.Transport((dic["hostname"], int(dic["port"])))
            transport.connect(username=dic["username"], password=dic["psd"])
            sftp = paramiko.SFTPClient.from_transport(transport)
            sftp.put(local_dir, nonlocal_dir)
            show("主机[%s]上传文件成功" % dic["hostname"], "info")
        except Exception as e:
            show("主机[%s]发生错误:%s" % (dic["hostname"], e), "error")
    
    def get_method(dic,dir, local_dir):
        '''
        downloads file method
        :param dic: host info
        :param dir: the dir of file to be downloads
        :param local_dir: the dir of the file will be saved
        :return: none
        '''
        try:
            nonlocal_dir = "/" + dic["username"] +dir
            transport = paramiko.Transport((dic["hostname"], int(dic["port"])))
            transport.connect(username=dic["username"], password=dic["psd"])
            sftp = paramiko.SFTPClient.from_transport(transport)
            sftp.get(nonlocal_dir, local_dir)
            show("主机[%s]下载文件成功"%dic["hostname"],"info")
        except Exception as e:
            show("主机[%s]发生错误:%s"%(dic["hostname"],e),"error")
    
    def command_method(dic,command):
        '''
        carry out the command which user input
        :param dic: host info
        :param command: the conmand of user input
        :return:
        '''
        try:
            # print(dic)
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            # print(hostname=dic["hostname"], port=int(dic["port"]), username=dic["username"], password=dic["psd"])
            ssh.connect(hostname=dic["hostname"], port=int(dic["port"]), username=dic["username"], password=dic["psd"])
            stdin, stdout, sterr = ssh.exec_command(command)
            result = stdout.read()
            print(result.decode())
        except Exception as e:
            show("主机[%f]发生错误:%s"%(dic["hostname"],e),"error")
    
    def dir_read(dirname):
        '''
        read the dir of db
        :param dirname: diename
        :return: files
        '''
        for roots,dirs,files in os.walk(dirname):
            return files
    
    def hostinfo_write(host_dic,hostname):
        '''
        write the host info into a file
        :param host_dic: host info dict
        :param hostname: host name
        :return: if sucessfully return true
        '''
        hostfile = settings.HOST_INFO+"/"+hostname
        with open(hostfile,"wb") as f:
            f.write(pickle.dumps(host_dic))
            return True
    
    def hostinfo_read():
        '''
        read the host info
        :return: host info list
        '''
        hostinfo_list = []
        for file in os.listdir(settings.HOST_INFO):
            filename = settings.HOST_INFO+"/"+file
            hostinfo_list.append(pickle.load(open(filename,"rb")))
        # print(hostinfo_list)
        return hostinfo_list
    
    def main_func():
        '''
        main function
        :return: none
        '''
        menu_dic = {"1":creat_host,"2":host_connect,"3":run_host}
        menu_info = '''-----欢迎来到Fabric主机管理界面-----
            1、新建主机
            2、连接主机
            3、运行主机
            4、退出程序
        '''
        while True:
            show(menu_info, "info")
            choice = input("您要干啥:>>>").strip()
            if choice.isdigit() and 0 < int(choice) <= len(menu_dic):
                menu_dic[choice]()
            elif choice == "4":
                show("退出程序", "error")
                break
            else:
                show("输入错误", "error")
    

      

     

  • 相关阅读:
    mysql随机数
    限制IP注册到Eureka
    Java日期格式化(DateFormat类和SimpleDateFormat类)
    直播类APP功能及技术难点(转)
    【转】Java之WeakReference与SoftReference使用讲解
    【转】android适配各种分辨率的问题
    国内市场上 Android 手机屏幕分辨率的比例情况如何?
    [转]mongodb与mysql相比的优缺点
    [转]一致性哈希算法及其在分布式系统中的应用
    [转]java byte 数据类型(基础)
  • 原文地址:https://www.cnblogs.com/japhi/p/7183296.html
Copyright © 2011-2022 走看看