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

时间:2022-03-28 14:46:24

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

 1、查
输入:www.oldboy.org
获取当前backend下的所有记录
2、新建
输入:
arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30
}
}
3、删除
输入:
arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30
}
}

需求

配置文件:

 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 100.1.7.9 weight 20 maxconn 3000

配置文件

                          我的实现思路:

一、流程图:

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

二、功能实现思路

查询操作:

  (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)

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

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

删除模块:

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

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

回滚功能:

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

三、代码模块

代码:

 #!/usr/bin/env python
# -*- coding:utf-8 -*- import flow if __name__ == '__main__':
print('''
*******************************************************************************
* -欢迎使用自动化修改工具- *
* \033[31m !请谨慎修改!\033[0m *
* *
* F \033[35m<查询>\033[0m A \033[35m<添加>\033[0m D\033[35m <删除>\033[0m G\033[35m <滚回配置>\033[0m *
* *
*******************************************************************************
''')
flow.log()

main主文件

 #!/usr/bin/env python
# -*- coding:utf-8 -*- def log():
while True :#开始循环
import func,time,os#加载func,函数全在里面
times = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())) #时间
sssd = "请输入操作(exit结束)["+times+"]:"
inpu = raw_input(sssd) #捕获操作
if inpu == 'f': #f表示查询
while True: #进入循环
opp = raw_input('请输入查询域名(exit退出):')#获取用户要查询的域名
if opp == 'exit': #如果为exit就退出
break
else: #否则进入查询模块
sss = func.aaa(opp) #进入查询模块并,拿到查询模块的值
aaa = len(sss) #判断返回值的列表是否为空
if aaa > 0 : #如果不是空则输出结果
print
print("\033[32m ----------------------- %s ---------------------\033[0m") %(opp)
func.ccc(sss) #调用输出的函数
print("\033[32m ---------------------------------------------------------\033[0m")
break
elif aaa == 0 : #如果是空则域名不存在
print("您输入的域名不存在!")
elif inpu == 'a' : #a表示添加
func.add_log() #调用添加逻辑函数
elif inpu == 'd':
func.rem()
elif inpu == 'g':
func.rest()
elif inpu == 'exit':
os._exit(0)

逻辑文件flow

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
#查找内容
backend_new = []#存放主机名称的列表
backend_newip = []#存放ip跟weight,maxconn的列表 用于后面的写入
backend_ser = []
#查询模块
def aaa(app):
pap_list1 = []#定义一个空列表用于存放查询的结果
pap_title = 'backend %s' %(app) #传入flow的opp的值
with open('file') as pen: #打开文件
flag = False #flag等于假
for lin in pen: #从pen按行读出
lin = lin.strip() #去除空
if lin == pap_title: #判断lin的内容跟pap_title的内容是否相同,因为我们要拿取backend加域名下面的地址地址地址地址
flag = True #将flag=真,这样就可以激活下面两个判断
continue #并且当前循环结束
elif flag and lin.startswith('backend'):#这里flag为真,但是还有一个条件也就是碰到下一个backend的时候,出发下面的代码
flag = False #将flag设置为false,并且退出循环,因为我们拿到我们需要的结果了
break
elif flag : #flag为真出发下面
pap_list1.append(lin) #将此时的lin 写入pap_list1列表中
return pap_list1 #将列表的值传出 #排序输出
def ccc(aad): #利用循环格式化输出
q = 1
ss = ' [{aa}]_____({bb})'
for i in aad:
ss.format(aa=q,bb=i)
print(ss.format(aa=q,bb=i))
q = q + 1 #生成域名列表用于,判断
def ddd():
pad_list1 = [] #生成空列表
with open('file') as ped: #打开文件
for lid in ped: #for循环读取文件
if lid.startswith('backend'): #碰到以backend开头的写入pad_list1列表
pad_list1.append(lid)
return pad_list1 #将 pad_list1 传出
#验证ip模块,判断用户输入ip是否正确 #用于判断id,这里写的不好等学会re进行更改
def ip():
ser_1 = raw_input("请输入主机1的ip地址:")#获取第一个ip
ser_2 = raw_input("请输入主机2的ip地址:")#获取第二个ip
ser1_list = ser_1.strip().split('.') #以·进行分割
ser2_list = ser_2.strip().split('.') #同理
ser1_list.extend(ser2_list) #将两个列表合成
ser1_list = set(ser1_list) #去除相同的
for ser in ser1_list: #开始循环取值
q_2 = str.isdigit(ser) #判断值是不是数字
if q_2 == True:#如果是进入循环
sea = int(ser)#转换成int类型
if sea < 255 : #比较是否小于255
seradd = True #如果小于则 seradd等于True
backend_newip.append(ser_1) #列表 backend_newip 传入值
backend_newip.append(ser_2)#列表 backend_newip 传入值
wm() #运行wm函数
break #退出循环
else: #否则
seradd = False#seradd= False
break #退出循环
else:#如果不是则直接推出,并返回值seradd = False,我用这个激活别的代码
print("--------------------\033[32m↓↓↓您输入的ip有误↓↓↓\033[0m--------------------")
seradd = False
break
return seradd #weight和maxconn
def wm(): #获取weight和maxconn的值
while True:
sew_1 = raw_input("请输入weight的值:")
sew_2 = raw_input("请输入maxconn的值:")
if str.isdigit(sew_1) and str.isdigit(sew_2): #判断类型是不是数字
backend_newip.append(sew_1) #是的话则写入
backend_newip.append(sew_2)
print(backend_newip)
print("ok")
break #退出循环
else: #不是的话则重新输入
print("-------------------\033[32m↓↓↓您输入有误↓↓↓\033[0m-------------------") #添加模块
def add_log():
while True:#进行添加循环
inp_d = raw_input('请输入添加的域名(exit退出):') #添加的域名
del backend_newip[:]#第二次添加时清空列表
del backend_ser[:]#第二次添加时清空列表
del backend_new[:]#第二次添加时清空列表
paa_title = 'backend %s\n' %(inp_d) #用于判断
ddd() #执行函数
rec_a = ddd() #得到文件中所有域名的类别
if paa_title in rec_a: #查看用户输入是否包含在当前文件中
inp_d1 = raw_input('当前域名已存在是否添加记录(y/n):') #如果包含,请用户判断是否添加记录
if inp_d1 == 'y':
backend_new.append(inp_d)
ip_result = ip()
print ip_result
if ip_result == True: #如果上面执行的结果为真那么就进行添加
aasd = aaa(inp_d)
for add_l in aasd:
backend_ser.append(add_l)
asp()
elif inp_d1 == 'n': #如果等于n 则退出
print("-------------------\033[32m已经退出\033[0m-------------------")
break
elif inp_d == 'exit': #等于exit则退出
print("-------------------\033[32m→已退出←\033[0m-------------------")
break
elif inp_d.count('.') != 2: #判断输入是否有两个 点 判断输入的类型,如果没有则提示错误
print("-------------------\033[32m↓↓↓您输入的域名有误↓↓↓\033[0m-------------------")
elif inp_d.count('.') == 2: #如果有两个点则进行添加,因为第一个if判断是否在文件中,所以处理到这里当前域名肯定不在文件中
inp_d2 = raw_input("您正在添加新的域名是否继续(y/n):") #判断是是否添加
if inp_d2 == 'y': #如果是y则执行添加
backend_new.append(inp_d) #将域名传入保存域名的列表
ip_result = ip() #执行ip函数并得到结果
print(backend_new) #打印结果
print ip_result #打印列表,包含ip等信息
if ip_result == True: #如果上面执行的结果为真那么就进行添加
asd() #添加模块
elif inp_d2 == 'n': #如果等于n 则退出
print("-------------------\033[32m已经退出\033[0m-------------------")
break #在末尾写入文件模块
def asd():
with open('file') as file_open,open('file_new','w') as new_open:#同时打开两个文件
back_ls = "backend %s\n" %(backend_new[0]) #生成backend条码
back_ls1 = " server %s %s weight %s maxconn %s\n" %(backend_newip[0],backend_newip[1],backend_newip[2],backend_newip[3])#生成server条目
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])
for a_new in file_open: #把老文件前内容都写入新文件中
new_open.write(a_new)
new_open.write(back_ls) #然后写入backend 语句
new_open.write(back_ls1) #写入server语句
print("ok") #输出
os.remove("file.bak")
os.rename('file','file.bak')
os.rename('file_new','file') #传入域名存在的配置
def asp():
asp_a = True #设定asp_a 等于True 这样就可以激活elif asp_a 从而执行添加
paa_title = 'backend %s\n' %(backend_new[0]) #生成用户输入的backend条目
asp_ls = "server %s %s weight %s maxconn %s" %(backend_newip[0],backend_newip[1],backend_newip[2],backend_newip[3])#生成server条目
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])
#上面一句是提示打印
backend_ser.append(asp_ls) #将新的server条目跟原来的server条目进行合成
with open('file') as file_open,open('file_new','w') as new_open: #打开两个文件
for sp_up in file_open: #循环读取file的内容
if sp_up == paa_title: #如果sp_up的内容等于用户输入的内容就将这行添加到file_new中,并且开始循环server的列表进行添加
print("正常")
new_open.write(sp_up)
for as_2 in backend_ser:
aaa = ' '*8+as_2+'\n'
new_open.write(aaa)
asp_a = False #为了不让最后一个elif继续添加这里进行false 停止
continue #并且结束当前循环,为了不触发下面的条目将asp_a变回True
elif sp_up.startswith('backend'): #因为上面输入了匹配backend条目的server所以直到碰到下一个backend才开始输入
new_open.write(sp_up) #输入backend,因为if判断将这个条目进入到这里这里不会去匹配下一个条件所以这里要添加进去
asp_a = True #并将asp_a变成True这样就重新激活了下面的elif,通过下面将剩下的文件写入
elif asp_a:
new_open.write(sp_up)
os.remove("file.bak")
os.rename('file','file.bak') #换名
os.rename('file_new','file') #换名
#删除逻辑处理
def rem():
while True:
del backend_ser[:]#第二次添加时清空列表
del backend_new[:]#第二次添加时清空列表
re_in = raw_input("请输入你要删除的域名(exit退出):")
re_inup = "backend %s\n" %(re_in)
re_up = ddd()
if re_in == "exit":
break
re_ins = raw_input("是否要删除\033[31m整个域名条目\033[0m(y/n)")
if re_ins == "y":
if re_inup in re_up:
backend_new.append(re_in)
delta()
elif re_ins == "n":
if re_inup in re_up:
backend_new.append(re_in)
re_up2 = aaa(re_in)
for isd in re_up2:
backend_ser.append(isd)
print("\033[32m ----------------------- %s ---------------------\033[0m") %(re_in)
ccc(re_up2)
print("\033[32m ---------------------------------------------------------\033[0m")
while True:
re_ser = raw_input("请输入你要删除的server第一个ip地址(exit退出):")
re_str = "server %s" %(re_ser)
if re_ser == "exit" :
break
elif re_ser.count('.') == 3:
for re_ups in re_up2:
if re_ups.startswith(re_str):
print('ok')
print("您要删除的条目:%s") %(re_ups)
backend_ser.remove(re_ups)
delt()
break
else:
print("!!!输入有误!!!")
else:
print("------------\033>>>>>[32m当前域名不存在\033[0m------------") #删除server功能函数
def delt():
asp_a = True #设定asp_a 等于True 这样就可以激活elif asp_a 从而执行添加
paa_title = 'backend %s\n' %(backend_new[0]) #生成用户输入的backend条目
with open('file') as file_open,open('file_new','w') as new_open: #打开两个文件
for sp_up in file_open: #循环读取file的内容
if sp_up == paa_title: #如果sp_up的内容等于用户输入的内容就将这行添加到file_new中,并且开始循环server的列表进行添加
new_open.write(sp_up)
for as_2 in backend_ser:
aaa = ' '*8+as_2+'\n'
new_open.write(aaa)
asp_a = False #为了不让最后一个elif继续添加这里进行false 停止
continue #并且结束当前循环,为了不触发下面的条目将asp_a变回True
elif sp_up.startswith('backend'): #因为上面输入了匹配backend条目的server所以直到碰到下一个backend才开始输入
new_open.write(sp_up) #输入backend,因为if判断将这个条目进入到这里这里不会去匹配下一个条件所以这里要添加进去
asp_a = True #并将asp_a变成True这样就重新激活了下面的elif,通过下面将剩下的文件写入
elif asp_a:
new_open.write(sp_up)
os.remove("file.bak")
os.rename('file','file.bak') #换名
os.rename('file_new','file') #换名
print("------------\033>>>>>[32m配置文件替换完成<<<<<\033[0m------------") #删除域名功能函数,实现方法很简单只需要匹配到相关项不添加即可
def delta():
asp_a = True #设定asp_a 等于True 这样就可以激活elif asp_a 从而执行添加
paa_title = 'backend %s\n' %(backend_new[0]) #生成用户输入的backend条目
with open('file') as file_open,open('file_new','w') as new_open: #打开两个文件
for sp_up in file_open: #循环读取file的内容
if sp_up == paa_title: #如果sp_up的内容等于用户输入的内容就将这行添加到file_new中,并且开始循环server的列表进行添加
asp_a = False #为了不让最后一个elif继续添加这里进行false 停止
continue #并且结束当前循环,为了不触发下面的条目将asp_a变回True
elif sp_up.startswith('backend'): #因为上面输入了匹配backend条目的server所以直到碰到下一个backend才开始输入
new_open.write(sp_up) #输入backend,因为if判断将这个条目进入到这里这里不会去匹配下一个条件所以这里要添加进去
asp_a = True #并将asp_a变成True这样就重新激活了下面的elif,通过下面将剩下的文件写入
elif asp_a:
new_open.write(sp_up)
os.remove("file.bak")
os.rename('file','file.bak') #换名
os.rename('file_new','file') #换名
print("配置文件替换完成") #还原最近一次配置
def rest():
ress = raw_input("请谨慎操是否回滚到最近一次配置(y):")
if ress == "y" :
os.rename("file","back")
os.rename('file.bak','file')
os.rename("back","file.bak")
else:
print("------------\033[32m>>>>>退出还原配置<<<<<\033[0m------------")

函数文件func

两个配置文件:

 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.aaa.com
server 100.1.2.9 100.1.5.9 weight 20 maxconn 3000
server 100.1.3.9 100.1.6.9 weight 20 maxconn 3000
backend www.bbb.com
server 100.2.1.9 100.2.3.9 weight 20 maxconn 3000
server 100.2.2.9 100.2.4.9 weight 20 maxconn 3000
backend www.ccc.com
server 100.3.2.9 100.3.4.9 weight 50 maxconn 50

file文件

 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.aaa.com
server 100.1.2.9 100.1.5.9 weight 20 maxconn 3000
server 100.1.3.9 100.1.6.9 weight 20 maxconn 3000
server 1.1.1.1 2.2.2.2 weight 20 maxconn 20
backend www.bbb.com
server 100.2.1.9 100.2.3.9 weight 20 maxconn 3000
server 100.2.2.9 100.2.4.9 weight 20 maxconn 3000
backend www.ccc.com
server 100.3.2.9 100.3.4.9 weight 50 maxconn 50

file.bak