Python-修改配置檔案
阿新 • • 發佈:2019-02-15
配置檔案的修改
功能:
主要用來作為功能選單選擇及相關模組的選擇、處理功能,包括:
1 檢視所有 backend 的配置資訊
2 新增配置資訊
3 刪除配置資訊
設計思路:
檢視功能: 開啟配置檔案,一行一行的進行讀取,當發現有 backend開頭行時,再判斷後面的 域名是否等於要查詢的名稱,如果是則做一個標記,判斷標記
為True時開始寫到變數中,直到找到下一個backend時將標誌位置False
新增配置資訊:新建一個臨時檔案,同查詢功能一樣一行一行讀取寫入臨時檔案,同時判斷當找到指定backend的記錄後,置標誌位,到下一個backend記錄時
將新增加的記錄寫入檔案,再將剩下的配置資訊寫入到檔案中。最後進行重新命名操作替換到以前的配置檔案
刪除配置資訊: 同新增類似,一行一行讀取。當找到與要刪除的配置一樣時,就把那一行跳過不寫入檔案
2 haconfig.py haproxy 自定義類
功能:
此檔案主要是將要操作的配置檔案進行一個類的封裝。
使用者的新增、刪除、查詢等操作都在類實現了具體的方法。並增加了 IP 地址合法性的判斷。將使用者輸入的配置引數中的: IP地址、weight值、maxconn值
作為類的一個屬性進行處理,在類內部通過字串的拼接生成配置串
包括方法:
1 獲取所有backend下的配置資訊 : show_show_backend()
2 新增配置資訊: add_backend()
3 刪除配置資訊: del_backend()
4 檢查ip合法性:check_ip_available
5 字串拼接:union_str
功能:
主要用來作為功能選單選擇及相關模組的選擇、處理功能,包括:
1 檢視所有 backend 的配置資訊
2 新增配置資訊
3 刪除配置資訊
設計思路:
檢視功能: 開啟配置檔案,一行一行的進行讀取,當發現有 backend開頭行時,再判斷後面的 域名是否等於要查詢的名稱,如果是則做一個標記,判斷標記
為True時開始寫到變數中,直到找到下一個backend時將標誌位置False
新增配置資訊:新建一個臨時檔案,同查詢功能一樣一行一行讀取寫入臨時檔案,同時判斷當找到指定backend的記錄後,置標誌位,到下一個backend記錄時
將新增加的記錄寫入檔案,再將剩下的配置資訊寫入到檔案中。最後進行重新命名操作替換到以前的配置檔案
刪除配置資訊: 同新增類似,一行一行讀取。當找到與要刪除的配置一樣時,就把那一行跳過不寫入檔案
2 haconfig.py haproxy 自定義類
功能:
此檔案主要是將要操作的配置檔案進行一個類的封裝。
使用者的新增、刪除、查詢等操作都在類實現了具體的方法。並增加了 IP 地址合法性的判斷。將使用者輸入的配置引數中的: IP地址、weight值、maxconn值
作為類的一個屬性進行處理,在類內部通過字串的拼接生成配置串
包括方法:
1 獲取所有backend下的配置資訊 : show_show_backend()
2 新增配置資訊: add_backend()
3 刪除配置資訊: del_backend()
4 檢查ip合法性:check_ip_available
5 字串拼接:union_str
6 獲取backend的所有節點名; get_backend_name
流程圖:
原始碼;
haconfig.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import shutil import re _default_path = os.path.dirname(os.path.abspath("__file__")) class haproxy(object): _default_path = os.path.dirname(os.path.abspath("__file__")) _default_file = os.path.join(_default_path, "config.ini") _tmp_file = os.path.join(_default_path, "tmp.ini") def __init__(self, ip='', weight=20, max_conn=100, file=_default_file): self.config_file = file self.ip_address = ip self.weight = weight self.max_conn = max_conn self.backend_contant = '' self.backend_name = list() # 檢查ip是否合法,變為一個屬性 @property def check_ip_available(self): rule = "((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$" # (200-240 | 250- 255|0-199|). 重複3次 IP r = re.compile(rule) if r.match(self.ip_address): return True else: return False # 拼接字串 def union_str(self): """ 新增或修改backend的內容時,呼叫此類方法,將輸入的引數值拼接成一行完成配置資訊 :return: 更新到self.backend_value屬性中, """ _default_str = 'server {ip} {ip} weight {weight} maxconn {maxconn}' self.backend_contant = _default_str.format(ip=self.ip_address, weight=self.weight, maxconn=self.max_conn) def get_backend_name(self): """ 獲取配置檔案中的所有 backend 節點資訊 :return: 無返回值,儲存在 self.backend_name 中 """ with open(self.config_file, 'r') as fr: for line in fr: if line.startswith("backend"): self.backend_name.append(line.split()[1]) # 查詢指定 backend 節點下的配置資訊 def show_backend(self, backend): """ 根據使用者輸入的 backend 節點值獲取對應的配置檔案 :param backend: 查詢的鍵值,如: test.oldboy.org :return: 返回一個列表 list """ result = list() # 定位到查詢的行標識 line_locked_flag = False with open(self.config_file, 'r', encoding='utf-8') as f: for line in f: # 如果找到 backend 配置節 if line.startswith('backend'): # 獲取backend的內容,test.oldboy.com url_addr = line.split()[1] # 如果內容和搜尋的內容一樣,則將定位標識置為True if url_addr == backend: line_locked_flag = True continue else: line_locked_flag = False # 如果定位到內容則將配置寫入到結果列表中 if line_locked_flag: result.append(line) return result # 增加backend內容 def add_backend(self, backend): """ 根據輸入的backend查詢檔案: 如果存在 backend,則在配置末尾增加一條記錄 如果不存在 backend,則在最後新增加一個 :param backend: 要增加的backend,如:test.oldboy.com :return: """ # 是否存在指定的backend標識,如果存在就在指定下面新增配置,沒有就新建一個backend,再新增配置 backend_is_exists_flag = False # 定位到查詢的行標識 line_locked_flag = False try: with open(self.config_file, 'r') as fr,open(self._tmp_file, 'a+') as fw: for line in fr: if line.startswith('backend'): url_addr = line.split()[1] if url_addr == backend: backend_is_exists_flag = True line_locked_flag = True else: # 找到"backend"字元標識,且定位標識為True,說明到了定位的下一個backend,這時需要先追加一條配置 if line_locked_flag: fw.write(" {content}\n".format(content=self.backend_contant)) line_locked_flag = False fw.write(line) # 檔案中沒有要新增的 backend 節點,那在最後新增加一個節點 if not backend_is_exists_flag: fw.write("backend {url}\n".format(url=backend)) fw.write(" {content}\n".format(content=self.backend_contant)) # 將臨時檔案重新命名,替換原來的配置檔案 shutil.move(self._tmp_file, self.config_file) return True except Exception as e: return e # 刪除指定 backend 的配置 def del_backend(self, backend): is_locked_flag = False # 是否找到指定的 IP 配置資訊 is_delete_flag = False try: with open(self.config_file, 'r') as fr, open(self._tmp_file, 'a+') as fw: for line in fr: # 找到backend行 if line.startswith("backend"): url_addr = line.split()[1] # 找到指定的backend節點 if url_addr == backend: is_locked_flag = True else: # 找到指定 backend 節點的下一個backend, 定位標識別改為False if is_locked_flag: is_locked_flag = False else: if is_locked_flag: # 在定位的 backend 節點下找到符合的 IP ,則把這一行跳過,不寫到tmp檔案中 if line.count(self.ip_address) > 0: is_delete_flag = True continue fw.write(line) shutil.move(self._tmp_file, self.config_file) if not is_delete_flag: return False else: return True except Exception as e: return e
Modify_ini.py:
#!/usr/bin/env python # -*- coding: utf-8 -*- from haconfig import haproxy welcome_title_str = "%s\n#%s#\n#%s#\n#%s#\n%s" % ("".ljust(50, '#'), ''.ljust(48, ' '), 'HAProxy 配置管理程式'.center(43, ' '), ''.ljust(48, ' '), ''.ljust(50, '#') ) menu_str = "\n1.查詢配置\n2.新增配置\n3.刪除配置\n4.退出程式\n" # 返回一個非空的輸入 def input_string(show_message, is_int=False): """ 對input函式進行重新改造,增加判斷不能為空, :param show_message: input()中的提示資訊 :param is_int: 是否要求輸入必須為數字,預設為False,如果為True就要檢查是否為數字 :return: 返回使用者輸入的值 """ not_null_flag = False while not not_null_flag: # 獲得使用者的輸入資訊 input_value = input("{message}".format(message=show_message)).strip().lower() if not input_value: continue else: # 如果要求輸入必須為數字,則做以下驗證 if is_int: if not input_value.isdigit(): print("\n\033[1;30m非法輸入,請輸入一個數字!\033[0m") continue not_null_flag = True return input_value if __name__ == "__main__": print(welcome_title_str) # 退出系統標識 exit_flag = False while not exit_flag: print(menu_str) choose = input("請選擇功能模組:").strip().lower() # 退出系統 if choose == '4': exit_flag = True continue if choose not in ('1', '2', '3'): print("\n\033[1;31m輸入錯誤!請輸入正確的功能編號.\033[0m") else: # 例項化配置檔案物件 proxyobj = haproxy() # 1. 查詢節點配置資訊 if choose == "1": # 獲取所有 backend 的節點名稱 proxyobj.get_backend_name() print("\n當前配置檔案所有 backend 節點名稱:") for name in proxyobj.backend_name: print(name) search_backend = input_string("\n請輸入要查詢的 backend 域名:") # 呼叫類方法獲取配置資訊列表 search_result = proxyobj.show_backend(search_backend) if not search_result: print("\n\033[1;30m沒有找到要查詢的記錄!\033[1m\n ") else: for record in search_result: print(record.strip()) # 2. 新增配置 if choose == "2": search_backend = input_string("請輸入要新增的 backend 域名:") # 對配置檔案物件進行賦值 proxyobj.ip_address = input_string("請輸入新增的 IP 地址:") # 判斷IP是否合法 while not proxyobj.check_ip_available: proxyobj.ip_address = input_string("\nIP地址不合法! 請重新輸入 IP 地址:") proxyobj.weight = input_string("請輸入新增的 weight 值:", is_int=True) proxyobj.max_conn = input_string("請輸入新增的 max conn 值:", is_int=True) # 根據使用者輸入的資訊,呼叫類的格式化字串方法生成配置檔案串 proxyobj.union_str() # 呼叫新增方法進行新增配置操作 if proxyobj.add_backend(search_backend): print("\n新增成功! 節點當前配置更新為:") # 將新增成功的資訊打印出來,直接呼叫類的檢視方法 search_result = proxyobj.show_backend(search_backend) for line in search_result: print(line.strip()) # 3. 刪除配置 if choose == "3": # 重新獲取一下當前配置檔案中的節點名稱列表 proxyobj.get_backend_name() # 要刪除的 backend 節點是否存在標識 is_exist_flag = False while not is_exist_flag: search_backend = input_string("請指定要刪除配置的 backend 節點名稱: ") if search_backend not in proxyobj.backend_name: print("\n當前配置檔案中未找到 %s 的 backend 節點!" %search_backend) continue else: is_exist_flag = True proxyobj.ip_address = input_string("請輸入要刪除的 IP 地址:") # 判斷IP是否合法 while not proxyobj.check_ip_available: proxyobj.ip_address = input_string("\nIP地址不合法! 請重新輸入 IP 地址:") # 呼叫類的刪除方法進行刪除操作 if proxyobj.del_backend(search_backend): print("\n刪除成功!當前節點配置更新為: ") else: print("\n刪除失敗!請檢查 IP 地址是否存在!\n") # 將修改後的資訊打印出來,直接呼叫類的檢視方法 search_result = proxyobj.show_backend(search_backend) for line in search_result: print(line.strip())