学习完成第三阶段,我们来写一个功能:也就是实现对配置文件的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
我的实现思路:
一、流程图:
(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信息加入到列表中,在写入,这里用到了老师的方法
(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()
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)
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------------")
两个配置文件:
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
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