在使用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. Python第六天 类型转换

    Python第六天   类型转换 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Python第二天  变量  运算符与表达式  input()与raw_inp ...

  2. PGSQL-通过SQL语句来计算两个日期相差的天数

    这是本人第一次写的~我在某次需求中遇到一个问题,如何在SQL语句中计算出两个日期的天数,然后用那个结果来进行数据的筛选呢?通过网上查阅了资料发现 date_part('day', cast(time1 ...

  3. python3 Queue(单向队列)

    创建队列 import queue q = queue.Queue() empty(如果队列为空,返回True) import queue q = queue.Queue() print(q.empt ...

  4. 英语口语练习系列-C10-up and down

    <长恨歌>·白居易 长恨歌朗读视频,点我可听,thanks 长恨歌-白居易 汉皇重色思倾国,御宇多年求不得.杨家有女初长成,养在深闺人未识. 天生丽质难自弃,一朝选在君王侧.回眸一笑百媚生 ...

  5. 日志学习系列(二)——Log4net的实例

    一.log4net简单实例创建步骤如下 1.第一步:在项目中添加对log4net.dll的引用,这里引用版本是2.0.8.0 2.第二步:程序启动时读取log4net的配置文件. 读取log4net的 ...

  6. audio

    // media.cpp : 定义控制台应用程序的入口点. // https://wenku.baidu.com/view/e910c474c5da50e2524d7fb4.html https:// ...

  7. ThreadLocal的使用及原理分析

    文章简介 ThreadLocal应该都比较熟悉,这篇文章会基于ThreadLocal的应用以及实现原理做一个全面的分析 内容导航 什么是ThreadLocal ThreadLocal的使用 分析Thr ...

  8. SQL UCASE() 函数

    UCASE() 函数 UCASE 函数把字段的值转换为大写. SQL UCASE() 语法 SELECT UCASE(column_name) FROM table_name SQL UCASE() ...

  9. 一本通 1223:An Easy Problem

    \[传送门qwq\] [题目描述] 给定一个正整数N,求最小的.比N大的正整数M,使得M与N的二进制表示中有相同数目的1. 举个例子,假如给定的N为78,其二进制表示为1001110,包含4个1,那么 ...

  10. SkylineGlobe TerraExplorer for Web 7.1.0版本 接口示例

    在SkylineGlobe TerraExplorer for Web 7.1.0版本(俗称H5免插件版本)中,如何使用SGWorld接口的三维视域分析方法呢? 请参考下面的示例: 通过下面的代码大家 ...