# -*- coding: utf-8 -*- # """ 1.执行参数规范检查 """ import random import string import os import re import sys # 安装地址 os_cmd = os.popen('grep -w ^tidb /etc/passwd').read() tidb_home = os_cmd.split(':')[5] base_path = "%s/scripts/normalcheck" %(tidb_home) config_file_sh = base_path + "/config/tidb_vars.config" config_file_para = base_path + "/config/tidb_parameter.config" script_dir = base_path + "/script" current_time = os.popen('date "+%Y%m%d%H%M%S"').read().strip('\n') # 判断一个unicode是否是汉字 def is_chinese(uchar): if u'\u4e00' <= uchar <= u'\u9fa5': return True else: return False # 将输入文字填充到width长度,不会进行裁剪 # 对齐方式为左对齐 def format_text(text, width, colored=False): str_text = str(text) unicode_text = str_text.decode("utf-8") # unicode_text = str_text cn_count = 0 color_char = 0 if colored: color_char = 9 for u in unicode_text: if is_chinese(u): cn_count += 1 return str_text + (width + color_char - cn_count - len(unicode_text)) * " " # 屏幕输出字符宽度定义 a0 = 8 a1 = 50 a2 = 20 a3 = 10 a4 = 30 a5 = 8 # 格式化各个指标并在屏幕输出 def format_line(str0, str1, str2, str3, str4, str5, colored_result=False): fmt = "| {0} | {1} | {2} | {3} | {4} | {5} |" return fmt.format(format_text(str0, a0), format_text(str1, a1), format_text(str2, a2), format_text(str3, a3, colored_result), format_text(str4, a4), format_text(str5, a5) ) # 屏幕输出打印行间隔 def print_linebreak(): print(("+ {0:{0}<%d} + {0:{0}<%d} + {0:{0}<%d} + {0:{0}<%d} + {0:{0}<%d} + {0:{0}<%d} + " % ( a0, a1, a2, a3, a4, a5)).format('-')) # 屏幕输出标题格式定义 def print_title(): print_linebreak() print(format_line("组件名称", "参数名称", "实际值", "检查结果", "规范值", "值类型")) print_linebreak() # 将一行的检查内容格式化并添加颜色,在屏幕输出 def print_text(check_class, check_name, check_curr_value, check_status, check_good_value, check_value_type): # 定义检查结果颜色 if check_status == "正常": check_status = "\033[32m%s\033[0m" % check_status else: check_status = "\033[31m%s\033[0m" % check_status print(format_line(check_class, check_name, check_curr_value, check_status, check_good_value, check_value_type, colored_result=True)) # 向结果报告中写入一行 def write_log(check_class, check_name, check_curr_value, check_status, check_good_value, check_value_type, last_appearance): output_log = base_path + "/output/tidb_parameter_check_report_" + shell_config_dict['CLUSTERNAME'] + "_" + current_time + ".csv" with open(output_log, 'a') as log: text = "%s||%s||%s||%s||%s||%s||%s\n" % (check_class, check_name, check_curr_value, check_status, check_good_value, check_value_type, last_appearance) log.write(text) # 读取环境变量配置文件 def read_sh_config(): global shell_config_dict shell_config_dict = {} with open(config_file_sh, mode='r') as f: for line in f: line_lst = line.strip().split('=') shell_config_dict[line_lst[0]] = line_lst[1] if "CLUSTERCOMPONENTS" not in shell_config_dict: shell_config_dict['CLUSTERCOMPONENTS'] = "" print(type(shell_config_dict), shell_config_dict) # 读取参数配置文件 def read_para_conifg(): global para_config_lst, checkpass_cnt, checkfail_cnt para_config_lst = [] checkpass_cnt = 0 checkfail_cnt = 0 clsrole_lst = ['tidb', 'pd', 'tikv'] for clsrole in shell_config_dict['CLUSTERCOMPONENTS'].split(','): clsrole_lst.append(clsrole) with open(config_file_para, mode='r') as fd: # lines = fd.readlines()[1:] var_class = '' for line in fd: line_lst = line.strip().split(',') if not line.startswith('enable') or len(line_lst) < 7: continue if line_lst[1] not in clsrole_lst: continue if len(line_lst) != 7: write_log(line_lst[1], line_lst[2], len(line_lst), 'csv行异常', '', '', current_time) print_text(line_lst[1], line_lst[2], len(line_lst), 'csv行异常', '', '') checkfail_cnt += 1 continue if line_lst[6] == '': write_log(line_lst[1], line_lst[2], line_lst[6], '参数值异常', '', '', current_time) print_text(line_lst[1], line_lst[2], line_lst[6], '参数值异常', '', '') checkfail_cnt += 1 continue if var_class != line_lst[1]: print_linebreak() (var_status, var_class, var_name, var_instance, var_table, var_recommend_value, var_good_value) = line_lst (check_result, check_value) = check_tidb_vars(var_class, var_table, var_name, var_good_value, var_instance) if check_result != '正常': # print(check_result, check_value, var_check_sql) checkfail_cnt += 1 else: checkpass_cnt += 1 #判断参数值类型 if line_lst[5] == line_lst[6]: value_type = '静态值' else: value_type = '动态值' print_text(var_class, var_name, check_value[:20], check_result, var_recommend_value[:30], value_type) write_log(var_class, var_name, check_value[:20], check_result, var_recommend_value[:30], value_type, current_time) print_linebreak() # 执行参数比对 def check_tidb_vars(check_class='', check_table='', check_iterm='', check_value='', check_instance=''): global var_check_sql if check_table.lower() == 'mysql.global_variables': var_check_sql = """select distinct VARIABLE_VALUE from %s where VARIABLE_NAME = '%s'""" % ( check_table, check_iterm) elif check_table.lower() == 'information_schema.cluster_config': #支持指定节点号的参数比对 if check_instance.strip() != 'all_node': instance_filter = "and INSTANCE = '%s'" %(check_instance) else: instance_filter = "" var_check_sql = """select distinct VALUE from %s where TYPE='%s' and \`KEY\` = '%s' %s""" % ( check_table, check_class.lower(), check_iterm.strip(), instance_filter) sql_cmd = """mysql --login-path=tidblogin -NBe "%s" """ % (var_check_sql) # print(sql_cmd) script_result = os.popen(sql_cmd).read().splitlines() if len(script_result) == 0: check_status = '无数据' return check_status, check_status elif len(script_result) == 1 and script_result[0] == check_value: check_status = '正常' elif len(script_result) == 1 and script_result[0].upper() == check_value.upper(): check_status = '正常' elif len(script_result) == 1 and script_result[0] != check_value: check_status = '异常' elif len(script_result) > 1: check_status = '异常_多个值' else: check_status = '未知错误' return check_status, script_result[0] def main(): read_sh_config() print_title() read_para_conifg() print(checkpass_cnt, checkfail_cnt) print('kv:TiDB参数合规检查,成功/失败:%s/%s' %(checkpass_cnt, checkfail_cnt)) print('kv:%s' %(checkfail_cnt)) if __name__ == '__main__': main()