在使用python操作文件的时候,特别是对于网络设备,通常操作配置文件,会简化配置量,配置文件加载到内存中,运行时使用的是内存中的配置,内存中配置修改后立即生效,如果不将配置内容保存到硬盘中,则下次重新启动会导致配置丢失。下面模拟一下haproxy的backend的添加删除修改。

  示例的配置文件如下:

  

global
log 127.0.0.1 local2
daemon
maxconn
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 :
stats enable
stats uri /admin
stats auth admin: frontend cccc.org
bind 0.0.0.0:
option httplog
option httpclose
option forwardfor
log global
acl www hdr_reg(host) -i www. cccc.org
use_backend www. cccc.org if www backend www. cccc.org
server 100.1.7.9 100.1.7.9 weight maxconn
server 100.1.7.8 100.1.7.8 weight maxconn
server 100.1.7.7 100.1.7.7 weight maxconn
backend www.cccc.com
server server110 192.168.1.110 weight maxconn

  需求如下:

  1、当输入backend的名字时,要求能打印出属于该backend的所有server信息,格式化输出

  2、可以添加backend的server,输入相关属性字段后,完成添加

  3、可以删除backend的server信息。

  4、以上要求,要基于python 的文件操作来实现。

  

  想了好久之后,有以下几个点是需要注意的地方:

  1、配置文件是存放在硬盘中的,硬盘上的数据不能直接在中间插入修改,只能先将内容读取到内存中,在内存中进行修改

  2、主要修改的地方backend字段,backend字段在整个配置文件中的是有顺序的,修改了前后的内容,都需要在对应的位置上

  3、backend下可能存在多个server,每个server都有固定的属性配置,可能存在多个backend

  下面简单写了一个操作的方法。

  

#!/usr/bin/env python
#-*- coding:utf-8 -*- def get_configuration(configuration_name):
configuration = open(configuration_name,"r",encoding="utf-8")
configuration_dict = {}
configuration_full = []#定义一个列表,用来存放所有的配置信息
line_number = 0#定义一个计数器,用来记录关键位置的信息,比如backend开始时候的数字信息,在列表中的位置
configuration_position = []#定义一个列表,用来存放出现的backend的位置
for line in configuration:
# line = line.strip()#清除前后的空格
backend_server_configuration_all =[]
if line.strip().startswith("backend"):#如果开头是backend,证明后面是一个节点域名信息。记录第一个出现的行数信息
backend_position = line_number
line_list = line.strip().split(" ")
backend_name = line_list[1]
configuration_dict[backend_name] = []
configuration_position.append(line_number)#如果出现backend,记录出现的位置,到时候好用来恢复文件的位置。
elif line.strip().startswith("server"):
line_list = line.strip().split(" ")
server_name = line_list[1]
server_address = line_list[2]
server_weight = line_list[4]
server_maxconn = line_list[6]
backend_server_configuration = {"server_name":server_name,
"server_address":server_address,
"server_weight":server_weight,
"server_maxconn":server_maxconn}
configuration_dict[backend_name].append(backend_server_configuration)#列表增加一个配置项
else:
configuration_full.append(line)
line_number += 1
# print(line_number)
# print(configuration_position)
#将配置字典,完整的配置信息,和配置点的信息返回,完整配置信息中不包含配置字典信息
return configuration_dict,configuration_full,configuration_position #查询是否存在对应的backend,如果有,将server信息打印
def select_backend(configuration_dict):
backend_name = input("请输入要查询的backend名称:")
if backend_name in configuration_dict.keys():
backend_server_list = configuration_dict[backend_name]
print("backend :%s"%backend_name)
for backend_server_item in backend_server_list:
print_backend(backend_server_item)
else:
print("输入的backend不存在") #打印,格式化打印
def print_backend(backend_server_item):
print(
'''--------------------------
server_name:%s
server_address:%s
server_weight:%s
server_maxconn:%s'''%(backend_server_item["server_name"],backend_server_item["server_address"],backend_server_item["server_weight"],backend_server_item["server_maxconn"])) def configuration_input():#获取需要操作的对象信息
backend_name = input("backend name:")
server_name = input("server name:")
server_address = input("server address:")
server_weight = input("server weight:")
server_maxconn = input("server weight:")
return backend_name,server_name,server_address,server_weight,server_maxconn #增加节点
def add_backend(configuration_dict):
#获取当前配置文件的完整配置信息
#将添加节点的关键信息,整理成字典,如果该节点所属的名字在配置中存在,则追加新的配置项,如果不存在,则直接添加
configuration_new = configuration_input()
backend_name = configuration_new[0]
server_name = configuration_new[1]
server_address = configuration_new[2]
server_weight = configuration_new[3]
server_maxconn = configuration_new[4]
backend_server_configuration = {"server_name": server_name,
"server_address": server_address,
"server_weight": server_weight,
"server_maxconn": server_maxconn}
if backend_name in configuration_dict.keys():
configuration_dict[backend_name].append(backend_server_configuration)
else:
configuration_dict[backend_name] = [backend_server_configuration]
print("添加成功!")
return configuration_dict
#删除后台节点,返回字典文件
def delete_backend(configuration_dict):
configuration_new = configuration_input()
backend_name = configuration_new[0]
server_name = configuration_new[1]
server_address = configuration_new[2]
server_weight = configuration_new[2]
server_maxconn = configuration_new[4]
if backend_name in configuration_dict:
backend_server_configuration = {"server_name": server_name,
"server_address": server_address,
"server_weight": server_weight,
"server_maxconn": server_maxconn}
# for backend_server in configuration_dict[backend_name]:
if backend_server_configuration in configuration_dict[backend_name]:
configuration_dict[backend_name].remove(backend_server_configuration)
if configuration_dict[backend_name] == []:#如果配置中该节点下没有了后台站点,就把该配置项删除。
configuration_dict.pop(backend_name)
print("删除成功!")
else:
print("删除的backend不存在,请检查输入")
return configuration_dict def show_backend(configuration_dict):
for backend_name in configuration_dict.keys():
backend_server_list = configuration_dict[backend_name]
print("********************************")
print("backend :%s"%backend_name)
for backend_server_item in backend_server_list:
print_backend(backend_server_item)
print("********************************") #定义写文件的函数,将配置脚本传递进去,然后写入到某个文件中,如果配置中有其他配置,需要将配置内容插入到原配置内容的位置
def new_configuration(configuration_dict,configuration_full,configuration_position):
# configuration_new = open(configuration_name,'w',encoding='utf-8')
# configuration_full = get_configuration(configuration_name)[1]
# configuration_position = get_configuration(configuration_name)[2][0]#只取出第一个位置点,然后以该位置为基础,往后排
configuration = configuration_dict
# print(configuration)
# for item in configuration:
backend_servers = []
backend_server = []
for key in configuration:#取出backend的名字,以该名字为键,值是后端服务器列表
backend_name = key
backend_string = "backend %s\n"%backend_name
backend_server.append(backend_string)
for server_item in configuration[key]:
server_string = '''\t\tserver %s %s weight %s maxconn %s\n'''%(server_item["server_name"],server_item["server_address"],server_item["server_weight"],server_item["server_maxconn"])#格式化写入文件的内容,前后是可以用tab,中间必须是空格,因为在拆分的时候使用的空格,split
backend_server.append(server_string)#将同一个backend的后端多台服务器,放在同一个列表中
# print(backend_server)
position_tmp = 0
#将拿到的配置列表,写入到之前拿到的配置信息列表中,定向插入到之前的位置
while position_tmp < len(backend_server):
new_position = configuration_position + position_tmp
configuration_full.insert(new_position,backend_server[position_tmp])
position_tmp += 1
# print(configuration_full)
return configuration_full #返回整体的配置信息 #定义写文件的方法,将配置文件整体写入到文件中
def write_configuration(configuration_name,configuration_full):
configuration_new = open(configuration_name, 'w', encoding='utf-8')
for line in configuration_full:
configuration_new.write(line)
configuration_new.close() # string_format = '''--------------------------
# server_name:%s
# server_address:%s
# server_weight:%s
# server_maxconn:%s'''%(1,2,3,4)
# # print(string_format)
#查询
# select_backend("haproxy_configuration",'www.oldboy.org')
# configuration_dict = add_backend("111","www.cmcc.com",'server108','192.168.200.108',30,5000)
# configuration_dict = add_backend("haproxy_configuration","www.cmcc.com",'server108','192.168.200.108',30,5000)
# configuration_dict = delete_backend("haproxy_configuration","www.cmcc.com",'server108','192.168.200.108','30','5000')
# show_backend(configuration_dict)p # select_backend(configuration_dict,'www.cmcc.com')
# configuration_dict = get_configuration("haproxy_configuration")
# configuration_full = new_configuration(configuration_dict,'haproxy_configuration')
# write_configuration('haproxy_configuration',configuration_full)
if __name__ == '__main__':
configuration_name = "haproxy_configuration"
configuration_tuple = get_configuration(configuration_name)
configuration_dict = configuration_tuple[0]
configuration_full = configuration_tuple[1]
configuration_position = configuration_tuple[2][0]
option_list = ['查询','显示所有','增加backend','删除','保存退出']
exit_flag = True
while exit_flag: for No,option in enumerate(option_list,1):
print("%d:%s"%(No,option))
user_select = input("请输入操作的编号:")
# user_select = int(user_select)
if user_select == "":
select_backend(configuration_dict)
elif user_select == "":
show_backend(configuration_dict)
elif user_select == "":
configuration_dict = add_backend(configuration_dict)
elif user_select == "":
configuration_dict = delete_backend(configuration_dict)
elif user_select == "":
configuration_full = new_configuration(configuration_dict,configuration_full,configuration_position)
write_configuration(configuration_name,configuration_full)
exit_flag = False
else:
print("输入错误,请重新输入。")

  用到的主要方法还是文件的操作、字符串的操作、字典和列表的嵌套、循环。所有的方法之间,调用的输入参数和输出参数,都设置固定的格式字典,基于字典进行相关操作。最后能够实现全部查询、指定查询、删除、添加、保存退出。最后体现在文件上。

python操作文件练习,配置haproxy的更多相关文章

  1. Python操作文件、文件夹、字符串

    Python 字符串操作 去空格及特殊符号 s.strip().lstrip().rstrip(',') 复制字符串 #strcpy(sStr1,sStr2) sStr1 = 'strcpy' sSt ...

  2. Python操作文件和目录

    Python操作文件和目录 读写文件比较简单,有一点特别注意就好了 windows下Python默认打开的文件以gbk解码,而一般我们的文件是utf-8编码的,所以如果文本含有中文,就会出现异常或者乱 ...

  3. Python操作文件-20181121

    Python操作文件 Python操作文件和其他语言一样,操作的过程无非是先定位找到文件.打开文件,然后对文件进行操作,操作完成后关闭文件即可. 文件操作方式:对文件进行操作,主要就是读.写的方式,p ...

  4. 使用python操作文件实现购物车程序

    使用python操作文件实现购物车程序 题目要求如下: 实现思路 始终维护一张字典,该字典里保存有用户账号密码,购物车记录等信息.在程序开始的时候读进来,程序结束的时候写回文件里去.在登录注册的部分, ...

  5. 用Python操作文件

    用Python操作文件 用word操作一个文件的流程如下: 1.找到文件,双击打开. 2.读或修改. 3.保存&关闭. 用Python操作文件也差不多: f=open(filename) # ...

  6. python操作文件案例二则

    前言 python 对于文件及文件夹的操作. 涉及到 遍历文件夹下所有文件 ,文件的读写和操作 等等. 代码一 作用:查找文件夹下(包括子文件夹)下所有文件的名字,找出 名字中含有中文或者空格的文件 ...

  7. open -python操作文件

    一打开文件 二操作文件 三关闭文件 open(文件,模式,编码),打开文件----->0101010(以二进制的方式打开)------>编码(open默认utf-8编码)------> ...

  8. Python操作文件文档

    需要帮老师将44G的图书分类一下,人工当然累死了.所以用Python大法处理一下. 思路是读取文件目录下的书名,然后去百度百科查分类,如果还没有就去豆瓣,当当查.哪一个先找到其余的就不用找了.如果没有 ...

  9. Python 操作文件、文件夹、目录大全

    # -*- coding: utf-8 -*- import os import shutil # 一. 路径操作:判断.获取和删除 #1. 得到当前工作目录,即当前Python脚本工作的目录路径: ...

随机推荐

  1. IT java培训机构名单(不全)

    基本都是借着招聘的幌子来招生的 1 百影世纪(北京)文化传媒有限公司 2 北京博创智软科技有限公司 3 北京博达远创科技发展有限公司 4 北京春玉影视文化传媒有限公司 5 北京顶测科技有限公司 6 北 ...

  2. Web开发人员学习路线图

    http://www.runoob.com/w3cnote/2018-web-developer.html

  3. C# List集合去重使用lambda表达式

    name age sex Lucy 22 woman Lily 23 woman Tom 24 man Lucy 22 woman Lily 23 woman LiLei 25 man List< ...

  4. Operating system error 32(failed to retrieve text for this error. Reason: 15105)

    一台数据库服务器的事务日志备份作业偶尔会出现几次备份失败的情况,具体的错误信息为: DATE/TIME:    2018/7/30 12:10:52 DESCRIPTION: BackupDiskFi ...

  5. c/c++ linux 进程间通信系列4,使用共享内存

    linux 进程间通信系列4,使用共享内存 1,创建共享内存,用到的函数shmget, shmat, shmdt 函数名 功能描述 shmget 创建共享内存,返回pic key shmat 第一次创 ...

  6. 【eclipse】mybatis配置文件创建与mapper接口文件创建

    什么是mybatis: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射. mybatis配置文件: <?xml version="1.0" ...

  7. LeetCode算法题-Fibonacci Number(Java实现)

    这是悦乐书的第250次更新,第263篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第117题(顺位题号是509).Fibonacci数字,通常表示为F(n),形成一个称为 ...

  8. Django的认证系统

    Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...

  9. 面向对象_item项目

    详细见老师博客:http://www.cnblogs.com/Eva-J/articles/7351812.html#_label9 __getitem__\__setitem__\__delitem ...

  10. flink window的early计算

    Tumbing Windows:滚动窗口,窗口之间时间点不重叠.它是按照固定的时间,或固定的事件个数划分的,分别可以叫做滚动时间窗口和滚动事件窗口.Sliding Windows:滑动窗口,窗口之间时 ...