终端环境运维菜单-yaml

来源:互联网 发布:房卡麻将源码教程 编辑:程序博客网 时间:2024/05/16 03:13

菜单功能说明:支持层级深入;选定的父菜单和子集菜单同屏显示,用字母及数字区分;包含子菜单的后缀多..;菜单由执行脚本和菜单模板文件构成,实际执行功能通过配置调用外部脚本。
菜单演示:

    *** 系统管理控制台 ***    1. 应用发布..       a. 生产环境..       b. 测试环境..       c. 发布..    2. 应用重启..    3. 服务管理..    4. 数据库同步..
#coding=utf-8##20161219##@jiansimport os, sysimport json, yamlimport subprocessclass MenuNode(object):    def __init__(self, title):        self.title = title        self.cmd = None        self.directory = None        self.firstneibour = None        self.firstchild = None    def add_cmd(self, cmd):        self.cmd = cmd    def add_neibour(self, other_node):        self.firstneibour = other_node    def add_cwd(self, cwd):        self.directory = cwd    def add_child(self, first_child):        self.firstchild = first_childdef parseMenu(obj, last_node=None):    node = None    if type(obj) == type({}):        node = MenuNode(obj['title'])        if obj.has_key('cmd'):            node.add_cmd(obj['cmd'])        if obj.has_key('directory'):            node.add_cwd(obj['directory'])        if obj.has_key('child'):            parseMenu(obj['child'], node)    #递归调用,并传入当前节点,作为之后的父节点或邻节点    if type(obj) == type([]):        for i in range(len(obj)):            if i == 0:                nd =  parseMenu(obj[i])                last_node.add_child(nd)              else:                nd =  parseMenu(obj[i])                last_node.add_neibour(nd)            last_node = nd    return nodedef displayMenu(menu, key=None):    os.system('clear')    print("    *** 系统管理控制台 ***\n")    menu_map = {}    i = 1    while True:        menu_appd = '..'        if menu.cmd:            menu_appd = ''        menu_item_text = str(i) + '. ' + menu.title + menu_appd        menu_map[str(i)] = menu        i += 1        print("\t" + menu_item_text)        if menu == key:            j = 97            child = menu.firstchild            while True:                child_appd = '..'                if child.cmd:                    child_appd = ''                menu_item_text = chr(j) + '. ' + child.title + child_appd                menu_map[chr(j)] = child                j += 1                print("\t" + '   ' + menu_item_text +"\n")                if child.firstneibour:                    child = child.firstneibour                else:                    break        if menu.firstneibour:            menu = menu.firstneibour            print(" ")        else:            break    return menu_mapif __name__ == '__main__':    dirname = os.path.dirname(sys.argv[0])    abspath = os.path.abspath(dirname)    with open(os.path.join(abspath,'menu.yml'), 'r') as f:        j = yaml.load(f)        menu_struct = parseMenu(j)    menu_saved = []     ##历史菜单入栈,用于返回    menu_map = {}       ##当前菜单与按键映射    menu_pos = menu_struct.firstchild    menu_hot = None    while True:        menu_map = displayMenu(menu_pos, menu_hot)        input = raw_input("\n  请输入选择(r返回上级,x退出):")        input = input.strip()        if input.lower() == 'r':            if menu_hot:                menu_hot = None                menu_map = displayMenu(menu_pos, menu_hot)            else:                if len(menu_saved) > 0:                    menu_pos = menu_saved.pop(-1)        if input.lower() == 'x':            sys.exit()         if menu_map.has_key(input.lower()):            if menu_map[input].cmd:                k = raw_input("确认执行请按y,其他返回: ")                if k != 'y':                    continue                print(menu_map[input].cmd.split())                ret = subprocess.Popen(menu_map[input].cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=menu_map[input].directory)                print("\n======>\n")                if ret.stdout:                    for line in ret.stdout:                        line = line.strip()                        print(line)                    wait = raw_input("\n任意键返回..")            else:                if input.isdigit():                    menu_hot = menu_map[input]                if input.isalpha():                    menu_saved.append(menu_pos) # 保存历史                    menu_pos = menu_map['a']                    menu_hot = menu_map[input]        menu_map = displayMenu(menu_pos, menu_hot)

菜单结构配置采用yaml格式书写,也可以用json格式,用json包导入处理:
title: 菜单中显示的名称
child:该菜单下包含的子菜单
cmd: 菜单对应的执行脚本,包含子菜单则为空
directory:菜单执行时切换的目录

title: 系统菜单child:  - title: 应用发布    cmd:    child:      - title: 生产环境        child:          - title: 预演            cmd: /usr/bin/ansible-playbook yun1_prop3p.yml restart_yun1_prop3p.yml yun2_prop3p.yml restart_yun2_prop3p.yml            directory: /data/local/auto/deploys/product          - title: 生产pro1            child:              - title: 只更新不重启                cmd: /usr/bin/ansible-playbook yun1_prop.yml yun2_prop.yml                directory: /data/local/auto/deploys/product              - title: 更新、重启                cmd: /usr/bin/ansible-playbook yun1_prop.yml restart_yun1_prop.yml yun2_prop.yml restart_yun2_prop.yml                directory: /data/local/auto/deploys/product  - title: 应用重启            child:      - title: shop        cmd: /usr/bin/ansible-playbook restart_yun1_proshop.yml        directory: /data/local/auto/deploys/product      - title: pro1        cmd: /usr/bin/ansible-playbook restart_yun1_prop.yml        directory: /data/local/auto/deploys/product  - title: 服务管理    child:      - title: dns域名        cmd: show_dns.sh      - title: 内网proxy映射        cmd: show_proxy.sh  - title: 数据库同步    child:      - title: db1同步至本地        cmd: /yunwei/scripts/sync_prod.sh prod_db1      - title: db2同步至本地        cmd: /yunwei/scripts/sync_prod.sh prod_db2
0 0