Python练习_更改配置文件(3)

学习完成第三阶段,我们来写一个功能:也就是实现对配置文件的backend字段进行增删改查

 1 1、查
 2     输入:www.oldboy.org
 3     获取当前backend下的所有记录
 4 2、新建
 5     输入:
 6         arg = {            'bakend': 'www.oldboy.org',            'record':{                'server': '100.1.7.9',                'weight': 20,                'maxconn': 30
 7             }
 8         }
 9 3、删除
10     输入:
11         arg = {            'bakend': 'www.oldboy.org',            'record':{                'server': '100.1.7.9',                'weight': 20,                'maxconn': 30
12             }
13         }
需求

配置文件:

 1 global       
 2         log 127.0.0.1 local2
 3         daemon
 4         maxconn 256
 5         log 127.0.0.1 local2 info
 6 defaults
 7         log global
 8         mode http
 9         timeout connect 5000ms
10         timeout client 50000ms
11         timeout server 50000ms
12         option  dontlognull
13 
14 listen stats :8888
15         stats enable
16         stats uri       /admin
17         stats auth      admin:1234
18 
19 frontend oldboy.org
20         bind 0.0.0.0:80
21         option httplog
22         option httpclose
23         option  forwardfor
24         log global
25         acl www hdr_reg(host) -i www.oldboy.org
26         use_backend www.oldboy.org if www
27 
28 backend www.oldboy.org
29         server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000
配置文件

 

                          我的实现思路:

一、流程图:

Python练习_更改配置文件(3)_第1张图片

二、功能实现思路

查询操作:

  (1)首先捕获用户输入的域名,并定义一个空的列表用于存放查询域名下方的server内容,生成一个控制器flag = False 

  (2)开始打开配置文件并按行读取配置文件,开始按行循环判断,直到读取到当前行与用户输入匹配是,将flag变成=True这样就可以出发下面的代码,把server写入到列表中 

  (3)为了保证不输入多余的所以当匹配下一个以backend开头时将flag=False这样就不会触发下面的代码来写入了

  (4)我将获取值得列表return了出来这样就可以使用ccc()自定义函数来格式化输出也可以判断当前域名是否查询到了结果

添加模块:

  (1)使用循环可以让用户无需再次匹配关键字进入添加自定义函数中来添加

  (2)首先设置几个全局列表用于保存backend信息,和server中的ip以及weight,maxconn的值因为这里可以循环添加所以一开始就将这几个列表清空保证正常添加

  (3)首先判断用户输入的域名存在不存在,不存在直接在文件后面添加即可,存在则需要找到匹配的位置然后将所有server信息跟新添加的server信息加入到列表中,在写入,这里用到了老师的方法

 

  Python练习_更改配置文件(3)_第2张图片

  (4) 因为使用了os.remove在windows下会出现问题,主要原因是文件以及存在所有我考虑到当添加的时候当前 file.bak文件也就是备份文件就没有必要存在所有我就先将他删除,在把file配置文件改成备份,

     最后将新的文件改成配置文件的文件名这样就避免了windows下的错误

删除模块:

  删除的原理跟添加差不多,考虑到有两种情况一种是删除整个域名的所有内容,还有的是删除域名下的server,对于整个域名来说只需要匹配成功的地方不写入新的配置文件就好了

    至于删除server,只需要先将匹配项读出来写入列表然后,从列表中删除匹配删除的server项,在根据添加的模块进行写入就完成了

 

回滚功能:

   存粹的更改文件名,没啥好说的

三、代码模块

代码:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import flow
 5 
 6 if __name__ == '__main__':
 7     print('''
 8     *******************************************************************************
 9     *                        -欢迎使用自动化修改工具-                             *
10     *                            \033[31m !请谨慎修改!\033[0m                                    *
11     *                                                                             *
12     *         F \033[35m<查询>\033[0m         A \033[35m<添加>\033[0m        D\033[35m <删除>\033[0m     G\033[35m <滚回配置>\033[0m          *
13     *                                                                             *
14     *******************************************************************************
15     ''')
16     flow.log()
main主文件
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 def log():
 6     while True :#开始循环
 7         import func,time,os#加载func,函数全在里面
 8         times = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())) #时间
 9         sssd = "请输入操作(exit结束)["+times+"]:"
10         inpu = raw_input(sssd)  #捕获操作
11         if inpu == 'f': #f表示查询
12             while True: #进入循环
13                 opp = raw_input('请输入查询域名(exit退出):')#获取用户要查询的域名
14                 if opp == 'exit':   #如果为exit就退出
15                     break
16                 else:   #否则进入查询模块
17                     sss = func.aaa(opp) #进入查询模块并,拿到查询模块的值
18                     aaa = len(sss)  #判断返回值的列表是否为空
19                     if aaa > 0 :    #如果不是空则输出结果
20                         print
21                         print("\033[32m     ----------------------- %s ---------------------\033[0m") %(opp)
22                         func.ccc(sss) #调用输出的函数
23                         print("\033[32m     ---------------------------------------------------------\033[0m")
24                         break
25                     elif aaa == 0 : #如果是空则域名不存在
26                         print("您输入的域名不存在!")
27         elif inpu == 'a' :  #a表示添加
28             func.add_log()  #调用添加逻辑函数
29         elif inpu == 'd':
30             func.rem()
31         elif inpu == 'g':
32             func.rest()
33         elif inpu == 'exit':
34             os._exit(0)
逻辑文件flow
  1 #!/usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 import os
  4 #查找内容
  5 backend_new = []#存放主机名称的列表
  6 backend_newip = []#存放ip跟weight,maxconn的列表 用于后面的写入
  7 backend_ser = []
  8 #查询模块
  9 def aaa(app):
 10     pap_list1 = []#定义一个空列表用于存放查询的结果
 11     pap_title = 'backend %s' %(app) #传入flow的opp的值
 12     with open('file') as pen: #打开文件
 13         flag = False    #flag等于假
 14         for lin in pen: #从pen按行读出
 15             lin = lin.strip()   #去除空
 16             if lin == pap_title:    #判断lin的内容跟pap_title的内容是否相同,因为我们要拿取backend加域名下面的地址地址地址地址
 17                 flag = True  #将flag=真,这样就可以激活下面两个判断
 18                 continue    #并且当前循环结束
 19             elif flag and lin.startswith('backend'):#这里flag为真,但是还有一个条件也就是碰到下一个backend的时候,出发下面的代码
 20                 flag = False                            #将flag设置为false,并且退出循环,因为我们拿到我们需要的结果了
 21                 break
 22             elif flag : #flag为真出发下面
 23                 pap_list1.append(lin)   #将此时的lin 写入pap_list1列表中
 24     return pap_list1 #将列表的值传出
 25 
 26 #排序输出
 27 def ccc(aad):   #利用循环格式化输出
 28     q = 1
 29     ss = '    [{aa}]_____({bb})'
 30     for i in aad:
 31         ss.format(aa=q,bb=i)
 32         print(ss.format(aa=q,bb=i))
 33         q = q + 1
 34 
 35 #生成域名列表用于,判断
 36 def ddd():
 37     pad_list1 = []  #生成空列表
 38     with open('file') as ped: #打开文件
 39         for lid in ped: #for循环读取文件
 40             if lid.startswith('backend'): #碰到以backend开头的写入pad_list1列表
 41                 pad_list1.append(lid)
 42     return pad_list1 #将 pad_list1 传出
 43 #验证ip模块,判断用户输入ip是否正确
 44 
 45 
 46 #用于判断id,这里写的不好等学会re进行更改
 47 def ip():
 48     ser_1 = raw_input("请输入主机1的ip地址:")#获取第一个ip
 49     ser_2 = raw_input("请输入主机2的ip地址:")#获取第二个ip
 50     ser1_list = ser_1.strip().split('.')    #以·进行分割
 51     ser2_list = ser_2.strip().split('.')    #同理
 52     ser1_list.extend(ser2_list) #将两个列表合成
 53     ser1_list = set(ser1_list)  #去除相同的
 54     for ser in ser1_list:   #开始循环取值
 55         q_2 = str.isdigit(ser)  #判断值是不是数字
 56         if q_2 == True:#如果是进入循环
 57             sea = int(ser)#转换成int类型
 58             if sea < 255 :  #比较是否小于255
 59                 seradd = True #如果小于则 seradd等于True
 60                 backend_newip.append(ser_1) #列表 backend_newip 传入值
 61                 backend_newip.append(ser_2)#列表 backend_newip 传入值
 62                 wm()    #运行wm函数
 63                 break #退出循环
 64             else:   #否则
 65                 seradd = False#seradd= False
 66                 break   #退出循环
 67         else:#如果不是则直接推出,并返回值seradd = False,我用这个激活别的代码
 68             print("--------------------\033[32m↓↓↓您输入的ip有误↓↓↓\033[0m--------------------")
 69             seradd = False
 70             break
 71     return seradd
 72 
 73 
 74 #weight和maxconn
 75 def wm():           #获取weight和maxconn的值
 76     while True:
 77         sew_1 = raw_input("请输入weight的值:")
 78         sew_2 = raw_input("请输入maxconn的值:")
 79         if str.isdigit(sew_1) and str.isdigit(sew_2):   #判断类型是不是数字
 80             backend_newip.append(sew_1) #是的话则写入
 81             backend_newip.append(sew_2)
 82             print(backend_newip)
 83             print("ok")
 84             break   #退出循环
 85         else:   #不是的话则重新输入
 86             print("-------------------\033[32m↓↓↓您输入有误↓↓↓\033[0m-------------------")
 87 
 88 #添加模块
 89 def add_log():
 90     while True:#进行添加循环
 91         inp_d = raw_input('请输入添加的域名(exit退出):') #添加的域名
 92         del backend_newip[:]#第二次添加时清空列表
 93         del backend_ser[:]#第二次添加时清空列表
 94         del backend_new[:]#第二次添加时清空列表
 95         paa_title = 'backend %s\n' %(inp_d) #用于判断
 96         ddd()   #执行函数
 97         rec_a = ddd()   #得到文件中所有域名的类别
 98         if  paa_title in rec_a: #查看用户输入是否包含在当前文件中
 99             inp_d1 = raw_input('当前域名已存在是否添加记录(y/n):')   #如果包含,请用户判断是否添加记录
100             if inp_d1 == 'y':
101                 backend_new.append(inp_d)
102                 ip_result = ip()
103                 print ip_result
104                 if ip_result == True:   #如果上面执行的结果为真那么就进行添加
105                     aasd = aaa(inp_d)
106                     for add_l in aasd:
107                         backend_ser.append(add_l)
108                     asp()
109             elif inp_d1 == 'n': #如果等于n 则退出
110                 print("-------------------\033[32m已经退出\033[0m-------------------")
111                 break
112         elif inp_d == 'exit':   #等于exit则退出
113             print("-------------------\033[32m→已退出←\033[0m-------------------")
114             break
115         elif inp_d.count('.') != 2: #判断输入是否有两个 点 判断输入的类型,如果没有则提示错误
116             print("-------------------\033[32m↓↓↓您输入的域名有误↓↓↓\033[0m-------------------")
117         elif inp_d.count('.') == 2: #如果有两个点则进行添加,因为第一个if判断是否在文件中,所以处理到这里当前域名肯定不在文件中
118             inp_d2 = raw_input("您正在添加新的域名是否继续(y/n):") #判断是是否添加
119             if inp_d2 == 'y':   #如果是y则执行添加
120                 backend_new.append(inp_d)   #将域名传入保存域名的列表
121                 ip_result = ip()    #执行ip函数并得到结果
122                 print(backend_new)  #打印结果
123                 print ip_result     #打印列表,包含ip等信息
124                 if ip_result == True:   #如果上面执行的结果为真那么就进行添加
125                     asd()   #添加模块
126             elif inp_d2 == 'n': #如果等于n 则退出
127                 print("-------------------\033[32m已经退出\033[0m-------------------")
128                 break
129 
130 
131 #在末尾写入文件模块
132 def asd():
133     with open('file') as file_open,open('file_new','w') as new_open:#同时打开两个文件
134         back_ls = "backend %s\n" %(backend_new[0])    #生成backend条码
135         back_ls1 = "        server %s %s weight %s maxconn %s\n" %(backend_newip[0],backend_newip[1],backend_newip[2],backend_newip[3])#生成server条目
136         print('您要添加的域名:\033[32m%s\033[0m,添加的server1:\033[32m%s\033[0m,添加的server2:\033[32m%s\033[0m,添加的weighe:\033[32m%s\033[0m,添加的maxconn:\033[32m%s\033[0m') %(backend_new[0],backend_newip[0],backend_newip[1],backend_newip[2],backend_newip[3])
137         for a_new in file_open: #把老文件前内容都写入新文件中
138             new_open.write(a_new)
139         new_open.write(back_ls) #然后写入backend 语句
140         new_open.write(back_ls1)    #写入server语句
141         print("ok") #输出
142     os.remove("file.bak")
143     os.rename('file','file.bak')
144     os.rename('file_new','file')
145 
146 #传入域名存在的配置
147 def asp():
148     asp_a = True #设定asp_a 等于True 这样就可以激活elif asp_a 从而执行添加
149     paa_title = 'backend %s\n' %(backend_new[0])    #生成用户输入的backend条目
150     asp_ls = "server %s %s weight %s maxconn %s" %(backend_newip[0],backend_newip[1],backend_newip[2],backend_newip[3])#生成server条目
151     print('您要添加的域名:\033[32m%s\033[0m,添加的server1:\033[32m%s\033[0m,添加的server2:\033[32m%s\033[0m,添加的weighe:\033[32m%s\033[0m,添加的maxconn:\033[32m%s\033[0m') %(backend_new[0],backend_newip[0],backend_newip[1],backend_newip[2],backend_newip[3])
152     #上面一句是提示打印
153     backend_ser.append(asp_ls) #将新的server条目跟原来的server条目进行合成
154     with open('file') as file_open,open('file_new','w') as new_open: #打开两个文件
155         for sp_up in file_open: #循环读取file的内容
156             if sp_up == paa_title:  #如果sp_up的内容等于用户输入的内容就将这行添加到file_new中,并且开始循环server的列表进行添加
157                 print("正常")
158                 new_open.write(sp_up)
159                 for as_2 in backend_ser:
160                     aaa = ' '*8+as_2+'\n'
161                     new_open.write(aaa)
162                     asp_a = False   #为了不让最后一个elif继续添加这里进行false 停止
163                 continue    #并且结束当前循环,为了不触发下面的条目将asp_a变回True
164             elif sp_up.startswith('backend'): #因为上面输入了匹配backend条目的server所以直到碰到下一个backend才开始输入
165                 new_open.write(sp_up)   #输入backend,因为if判断将这个条目进入到这里这里不会去匹配下一个条件所以这里要添加进去
166                 asp_a = True    #并将asp_a变成True这样就重新激活了下面的elif,通过下面将剩下的文件写入
167             elif asp_a:
168                 new_open.write(sp_up)
169     os.remove("file.bak")
170     os.rename('file','file.bak')    #换名
171     os.rename('file_new','file')    #换名
172 #删除逻辑处理
173 def rem():
174     while True:
175         del backend_ser[:]#第二次添加时清空列表
176         del backend_new[:]#第二次添加时清空列表
177         re_in = raw_input("请输入你要删除的域名(exit退出):")
178         re_inup = "backend %s\n" %(re_in)
179         re_up = ddd()
180         if re_in == "exit":
181             break
182         re_ins = raw_input("是否要删除\033[31m整个域名条目\033[0m(y/n)")
183         if re_ins == "y":
184             if re_inup in re_up:
185                 backend_new.append(re_in)
186                 delta()
187         elif re_ins == "n":
188             if re_inup in re_up:
189                 backend_new.append(re_in)
190                 re_up2 = aaa(re_in)
191                 for isd in re_up2:
192                     backend_ser.append(isd)
193                 print("\033[32m     ----------------------- %s ---------------------\033[0m") %(re_in)
194                 ccc(re_up2)
195                 print("\033[32m     ---------------------------------------------------------\033[0m")
196                 while True:
197                     re_ser = raw_input("请输入你要删除的server第一个ip地址(exit退出):")
198                     re_str = "server %s" %(re_ser)
199                     if re_ser == "exit" :
200                         break
201                     elif re_ser.count('.') == 3:
202                         for re_ups in re_up2:
203                             if re_ups.startswith(re_str):
204                                 print('ok')
205                                 print("您要删除的条目:%s") %(re_ups)
206                                 backend_ser.remove(re_ups)
207                                 delt()
208                                 break
209                     else:
210                         print("!!!输入有误!!!")
211         else:
212             print("------------\033>>>>>[32m当前域名不存在\033[0m------------")
213 
214 #删除server功能函数
215 def delt():
216     asp_a = True #设定asp_a 等于True 这样就可以激活elif asp_a 从而执行添加
217     paa_title = 'backend %s\n' %(backend_new[0])    #生成用户输入的backend条目
218     with open('file') as file_open,open('file_new','w') as new_open: #打开两个文件
219         for sp_up in file_open: #循环读取file的内容
220             if sp_up == paa_title:  #如果sp_up的内容等于用户输入的内容就将这行添加到file_new中,并且开始循环server的列表进行添加
221                 new_open.write(sp_up)
222                 for as_2 in backend_ser:
223                     aaa = ' '*8+as_2+'\n'
224                     new_open.write(aaa)
225                     asp_a = False   #为了不让最后一个elif继续添加这里进行false 停止
226                 continue    #并且结束当前循环,为了不触发下面的条目将asp_a变回True
227             elif sp_up.startswith('backend'): #因为上面输入了匹配backend条目的server所以直到碰到下一个backend才开始输入
228                 new_open.write(sp_up)   #输入backend,因为if判断将这个条目进入到这里这里不会去匹配下一个条件所以这里要添加进去
229                 asp_a = True    #并将asp_a变成True这样就重新激活了下面的elif,通过下面将剩下的文件写入
230             elif asp_a:
231                 new_open.write(sp_up)
232     os.remove("file.bak")
233     os.rename('file','file.bak')    #换名
234     os.rename('file_new','file')    #换名
235     print("------------\033>>>>>[32m配置文件替换完成<<<<<\033[0m------------")
236 
237 #删除域名功能函数,实现方法很简单只需要匹配到相关项不添加即可
238 def delta():
239     asp_a = True #设定asp_a 等于True 这样就可以激活elif asp_a 从而执行添加
240     paa_title = 'backend %s\n' %(backend_new[0])    #生成用户输入的backend条目
241     with open('file') as file_open,open('file_new','w') as new_open: #打开两个文件
242         for sp_up in file_open: #循环读取file的内容
243             if sp_up == paa_title:  #如果sp_up的内容等于用户输入的内容就将这行添加到file_new中,并且开始循环server的列表进行添加
244                 asp_a = False   #为了不让最后一个elif继续添加这里进行false 停止
245                 continue    #并且结束当前循环,为了不触发下面的条目将asp_a变回True
246             elif sp_up.startswith('backend'): #因为上面输入了匹配backend条目的server所以直到碰到下一个backend才开始输入
247                 new_open.write(sp_up)   #输入backend,因为if判断将这个条目进入到这里这里不会去匹配下一个条件所以这里要添加进去
248                 asp_a = True    #并将asp_a变成True这样就重新激活了下面的elif,通过下面将剩下的文件写入
249             elif asp_a:
250                 new_open.write(sp_up)
251     os.remove("file.bak")
252     os.rename('file','file.bak')    #换名
253     os.rename('file_new','file')    #换名
254     print("配置文件替换完成")
255 
256 
257 #还原最近一次配置
258 def rest():
259     ress = raw_input("请谨慎操是否回滚到最近一次配置(y):")
260     if ress == "y" :
261         os.rename("file","back")
262         os.rename('file.bak','file')
263         os.rename("back","file.bak")
264     else:
265         print("------------\033[32m>>>>>退出还原配置<<<<<\033[0m------------")
函数文件func

两个配置文件:

 1 frontend oldboy.org
 2         bind 0.0.0.0:80
 3         option httplog
 4         option httpclose
 5         option  forwardfor
 6         log global
 7         acl www hdr_reg(host) -i www.oldboy.org
 8         use_backend www.oldboy.org if www
 9 backend www.aaa.com
10         server 100.1.2.9 100.1.5.9 weight 20 maxconn 3000
11         server 100.1.3.9 100.1.6.9 weight 20 maxconn 3000
12 backend www.bbb.com
13         server 100.2.1.9 100.2.3.9 weight 20 maxconn 3000
14         server 100.2.2.9 100.2.4.9 weight 20 maxconn 3000
15 backend www.ccc.com
16         server 100.3.2.9 100.3.4.9 weight 50 maxconn 50
file文件
 1 frontend oldboy.org
 2         bind 0.0.0.0:80
 3         option httplog
 4         option httpclose
 5         option  forwardfor
 6         log global
 7         acl www hdr_reg(host) -i www.oldboy.org
 8         use_backend www.oldboy.org if www
 9 backend www.aaa.com
10         server 100.1.2.9 100.1.5.9 weight 20 maxconn 3000
11         server 100.1.3.9 100.1.6.9 weight 20 maxconn 3000
12         server 1.1.1.1 2.2.2.2 weight 20 maxconn 20
13 backend www.bbb.com
14         server 100.2.1.9 100.2.3.9 weight 20 maxconn 3000
15         server 100.2.2.9 100.2.4.9 weight 20 maxconn 3000
16 backend www.ccc.com
17         server 100.3.2.9 100.3.4.9 weight 50 maxconn 50
file.bak

 

你可能感兴趣的:(Python练习_更改配置文件(3))