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")

  

 

原文地址:https://www.cnblogs.com/japhi/p/7183296.html