作业2:实现修改harproxy配置文件
要求,通过文件读写实现增删改查
global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defaults log global mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms option dontlognull listen stats :8888 stats enable stats uri /admin stats auth admin:1234 frontend oldboy.org bind 0.0.0.0:80 option httplog option httpclose option forwardfor log global acl www hdr_reg(host) -i www.oldboy.org use_backend www.oldboy.org if www backend www.oldboy.org server 100.1.7.9 weight 20 maxconn 30 backend www.sina.com server 100.1.7.7 100.1.7.7 weight 20 maxconn 3000 backend www.baidu.com server 100.1.7.9 weight 20 maxconn 30
以上是配置文件内容。
1 import os 2 # 导入os模块,获得haproxy.txt的路径 3 DB_PATH=os.path.join(os.path.dirname(__file__),"haproxy.txt") 4 # 获得new.txt的路径,这是一个临时文件,用于临时存需要修改的数据,之后会改名成haproxy.txt,而之前的haproxy.txt文件将会被删除 5 DB_NEW_PATH=os.path.join(os.path.dirname(__file__),"new.txt") 6 7 # 查找函数(查询函数中调用的) 8 def select(bef_find): 9 with open(DB_PATH, "r", encoding="utf-8")as f: 10 # 每行每行的遍历。防止文件过大 爆内存 11 for line in f: 12 # 查询到一样的字符串 就读取它的下一行。然后返回 13 if bef_find == line: 14 out_find = f.readline() 15 return out_find 16 # 若读完全部的行后都没找到打印该信息 17 else: 18 print("没有查询到") 19 20 # 添加消息函数 21 def add_message(one_line): 22 with open(DB_PATH,'a',encoding="utf-8")as f: 23 f.write(one_line) 24 25 def update_message(old_data,new_data): 26 # 方法都一样。 27 with open(DB_PATH,"r",encoding="utf-8")as f,\ 28 open(DB_NEW_PATH,"w",encoding="utf-8")as f1: 29 for line in f: 30 if line == old_data: 31 line=line.replace(line,new_data) # 因为字符串是不可变类型,所以要重新进行赋值才能实现修改操作 32 f1.write(line) 33 os.remove(DB_PATH) 34 os.rename(DB_NEW_PATH,DB_PATH) 35 36 # 查询函数 37 def search(): 38 while True: 39 # 接受查询的网址 40 find=input("请输入查询的网址:") 41 if find=="q": 42 break 43 # 设置开头,拼接成查询的数据的最终格式 44 before="backend " 45 bef_find=before+find+"\n" 46 # 调用查找函数 47 res=select(bef_find) 48 # 若查找函数没有返回值就什么都不做 49 if not res: 50 pass 51 # 若查找函数有返回值,打印它 52 else: 53 print(res) 54 55 # 添加函数 56 def add(): 57 while True: 58 # 接收记录 59 args=input("请输入添加的记录(以字典的形式):").strip() 60 # 接收到 q 退出 61 if args=='q': 62 break 63 '''arg = {'backend': 'www.oldboy.org','record': {'server': '100.1.7.9','weight': 20,'maxconn': 30}}''' 64 # 如果输入正确,是能够调用eval函数不报错的进入try的函数 65 try: 66 # 执行eval内置函数,将字符串转换成python类型 67 args=eval(args) 68 # 拼接字符串 69 bef_find = f"backend " + args["backend"] + "\n" 70 # 调用查询函数,接收返回值 71 old_data = select(bef_find) 72 # 有返回值,打印”已经存在了“ 73 if old_data: 74 print("已经存在了,不能添加该网址的配置") 75 break 76 # 没有返回值就继续拼接字符串 77 one_line = f"backend {args['backend']}\n\t\tserver {args['record']['server']} weight {args['record']['weight']} maxconn {args['record']['maxconn']}\n" 78 # 调用添加消息函数。 79 add_message(one_line) 80 # 否则就抛出异常 81 except (SyntaxError,TypeError,KeyError,NameError,UnboundLocalError): 82 print("输入格式不符合规范") 83 84 85 86 87 def update(): 88 while True: 89 # 还是接收记录 90 args=input("请输入要更新的记录(以字典的形式):").strip() 91 if args=="q": 92 break 93 # 都跟删除的一样的套路 94 try: 95 args = eval(args) 96 # 拼接字典的值 97 bef_find=f"backend "+ args["backend"] +"\n" 98 # 调用查找函数 99 old_data=select(bef_find) 100 '''arg = {'backend': 'www.oldboy.org','record': {'server': '100.1.7.9','weight': 20,'maxconn': 30}}''' 101 # 继续拼接字符串 102 new_data=f"\t\tserver {args['record']['server']} weight {args['record']['weight']} maxconn {args['record']['maxconn']}\n" 103 # 调用更新记录函数,将老数据和新数据传进去 104 update_message(old_data,new_data) 105 except (SyntaxError,TypeError,KeyError,NameError,UnboundLocalError): 106 print("输入格式不符合规范") 107 108 109 def delete(): 110 while True: 111 # 接收网址 112 website=input("请输入要删除的网址:").strip() 113 # q就退出 114 if website=="q": 115 break 116 # 创建一个旗帜,默认为False,通过旗帜来控制是否将haproxy.txt的内容是否写入到new.txt的文件中(最后通过改名变相的起到了删除的作用) 117 delete_flag=False 118 # 计数,删除多少条(貌似没啥子用) 119 count=0 120 # 用读方式打开,haproxy.txt, 用写的方式打开new.txt(w方式下没有就会新建一个空文件) 121 with open(DB_PATH,"r",encoding="utf-8")as f,\ 122 open(DB_NEW_PATH,"w",encoding="utf-8")as f1: 123 # 还是遍历每一行,免得爆内存 124 for line in f: 125 # 还是老办法,继续拼接字符串 126 if f"backend {website}" == line.strip(): 127 # 若相等,就将旗帜设置为True(之后判断是否写入到new文件中的时候,True就表示不写) 128 delete_flag=True 129 count+=1 130 continue 131 # 遍历到下一行的时候,碰到backend开头的字符串,并且 后面的网址不存在的就把旗帜给调会False(不恢复的话后面的都不会写入new文件) 132 if line.strip().startswith("backend") and line.strip()!=website.strip(): 133 delete_flag=False 134 # 旗帜为False 就写写写 135 if not delete_flag: 136 f1.write(line) 137 print(f"找到{count}条,已经删除!") 138 # 移除之前的文档,把新文档改名成老文档,实现删除功能 139 os.remove(DB_PATH) 140 os.rename(DB_NEW_PATH,DB_PATH) 141 142 # 创建一个功能字典,用于存放【功能编号】 和 【函数地址】 143 run_dict={ 144 "1":search, 145 "2":add, 146 "3":update, 147 "4":delete, 148 } 149 def run(): 150 while True: 151 # 遍历功能字典,取出函数名称 152 for k in run_dict: 153 print(k,run_dict[k].__name__) 154 # 获取功能编号 155 choice=input("请输入功能:").strip() 156 # 接收到q就退出 157 if choice=="q": 158 break 159 # 查看是否是数字 160 if not choice.isdigit(): 161 print("您输入的不是数字!") 162 continue 163 # 查看是否有这个功能编号 164 if choice not in run_dict.keys(): 165 print("没有该功能编码!") 166 continue 167 # 通过功能编号调用对应的函数 168 run_dict[choice]() 169 170 run()