在使用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. asp.net网页上获取其中表格中的数据(爬数据)

    下面的方法获取页面中表格数据,每个页面不相同,获取的方式(主要是正则表达式)不一样,只是提供方法参考.大神勿喷,刚使用了,就记下来了. 其中数据怎么存,主要就看着怎么使用了.只是方便记录就都放在lis ...

  2. 复制命令(ROBOCOPY)

    ROBOCOPY 命令: // 描述: 相比较 xcopy.copy 来说,复制的功能就强大很多,  xcopy.copy 是单线程的,robocopy是多线程的,但是和一些专业的复制软件相比速度还是 ...

  3. spark-2.4.0-hadoop2.7-安装部署

    1. 主机规划 主机名称 IP地址 操作系统 部署软件 运行进程 备注 mini01 172.16.1.11[内网] 10.0.0.11  [外网] CentOS 7.5 Jdk-8.zookeepe ...

  4. SQLServer修改表数据

    使用SSMS数据库管理工具修改数据 修改任意一条或者多条都可以 1:打开数据库,选择数据表,右键点击->编辑所有行(如未配置,点击编辑前200行). 2.编辑需要修改的数据->编辑完成后, ...

  5. 【English】20190328

    Emotions情绪 [ɪ'moʊʃənz]  Run Your Life for Teens影响你的青少年生活[ti:nz] Don't Let Your Emotions Run Your Lif ...

  6. MySQL之初识数据库

    一 数据库管理软件的由来 基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上. 如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件 ...

  7. Error response from daemon: conflict: unable to remove repository reference 解决方案

    由于前一章演示用的镜像没什么用准备删除 docker image rm hello-world:latest Error response from daemon: conflict: unable ...

  8. Spring Security(三十四):10.4 Jackson Support

    Spring Security has added Jackson Support for persisting Spring Security related classes. This can i ...

  9. SegNet 理解与文章结构

    SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation 发表于2016年,作者 Vijay B ...

  10. 聊聊基准测试的MVP方案

    上篇博客介绍了基准测试的一些思路和方法策略,这篇博客,聊聊基准测试的MVP(最小可行性方案)... 思维导图 一.测试策略 策略名称 阈值 运行时间 性能指标 基线 注释 并发测试 CPU75%+Er ...