作业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+"
"
 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"] + "
"
 70             # 调用查询函数,接收返回值
 71             old_data = select(bef_find)
 72             # 有返回值,打印”已经存在了“
 73             if old_data:
 74                 print("已经存在了,不能添加该网址的配置")
 75                 break
 76             # 没有返回值就继续拼接字符串
 77             one_line = f"backend {args['backend']}
		server {args['record']['server']} weight {args['record']['weight']} maxconn {args['record']['maxconn']}
"
 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"] +"
"
 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"		server {args['record']['server']} weight {args['record']['weight']} maxconn {args['record']['maxconn']}
"
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()
原文地址:https://www.cnblogs.com/lijunlin-py/p/13649114.html