diff --git a/plugins/clean/tool_task.py b/plugins/clean/tool_task.py index e7f27e86a..d61b4f41f 100644 --- a/plugins/clean/tool_task.py +++ b/plugins/clean/tool_task.py @@ -52,8 +52,8 @@ def createBgTask(): removeBgTask() args = { "period": "day", - "hour": "2", - "minute": "30", + "hour": "0", + "minute": "15", } createBgTaskByName(getPluginName(), args) diff --git a/plugins/mysql/conf/my5.5.cnf b/plugins/mysql/conf/my5.5.cnf index 5b257948b..3b9050e57 100644 --- a/plugins/mysql/conf/my5.5.cnf +++ b/plugins/mysql/conf/my5.5.cnf @@ -53,7 +53,7 @@ long_query_time=10 #log_queries_not_using_indexes=on #log_slow_admin_statements=1 #log_slow_slave_statements=1 -expire_logs_days=30 +expire_logs_days=7 relay-log=mdserver relay-log-index=mdserver diff --git a/plugins/mysql/conf/my5.6.cnf b/plugins/mysql/conf/my5.6.cnf index 983e95fdb..09404b10d 100644 --- a/plugins/mysql/conf/my5.6.cnf +++ b/plugins/mysql/conf/my5.6.cnf @@ -56,7 +56,7 @@ long_query_time=10 #log_queries_not_using_indexes=on #log_slow_admin_statements=1 #log_slow_slave_statements=1 -expire_logs_days=30 +expire_logs_days=7 relay-log=mdserver relay-log-index=mdserver diff --git a/plugins/mysql/conf/my5.7.cnf b/plugins/mysql/conf/my5.7.cnf index 95801b7cd..6c0e3d682 100644 --- a/plugins/mysql/conf/my5.7.cnf +++ b/plugins/mysql/conf/my5.7.cnf @@ -57,7 +57,7 @@ long_query_time=10 #log_queries_not_using_indexes=1 #log_slow_admin_statements=1 #log_slow_slave_statements=1 -expire_logs_days=30 +expire_logs_days=7 relay-log=mdserver relay-log-index=mdserver diff --git a/plugins/mysql/index.html b/plugins/mysql/index.html index 1789a0965..187869409 100755 --- a/plugins/mysql/index.html +++ b/plugins/mysql/index.html @@ -12,6 +12,7 @@
性能优化
日志
慢日志
+BINLOG
管理列表
主从配置
@@ -57,12 +58,14 @@ text-align: right; } + + \ No newline at end of file diff --git a/plugins/mysql/index.py b/plugins/mysql/index.py index a1c3da9d6..b4c7a0ff9 100755 --- a/plugins/mysql/index.py +++ b/plugins/mysql/index.py @@ -293,6 +293,14 @@ def getDataDir(): return tmp.groups()[0].strip() +def getLogBinName(): + file = getConf() + content = mw.readFile(file) + rep = 'log-bin\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + def getPidFile(): file = getConf() content = mw.readFile(file) @@ -333,6 +341,54 @@ def binLog(): return mw.returnJson(True, '设置成功!') +def binLogList(): + args = getArgs() + data = checkArgs(args, ['page', 'page_size', 'tojs']) + if not data[0]: + return data[1] + + page = int(args['page']) + page_size = int(args['page_size']) + + data_dir = getDataDir() + log_bin_name = getLogBinName() + + alist = os.listdir(data_dir) + log_bin_l = [] + for x in range(len(alist)): + f = alist[x] + t = {} + if f.startswith(log_bin_name) and not f.endswith('.index'): + abspath = data_dir + '/' + f + t['name'] = f + t['size'] = os.path.getsize(abspath) + t['time'] = mw.getDataFromInt(os.path.getctime(abspath)) + log_bin_l.append(t) + + log_bin_l = sorted(log_bin_l, key=lambda x: x['time'], reverse=True) + + # print(log_bin_l) + # print(data_dir, log_bin_name) + + count = len(log_bin_l) + + page_start = (page - 1) * page_size + page_end = page_start + page_size + if page_end > count: + page_end = count + + data = {} + page_args = {} + page_args['count'] = count + page_args['p'] = page + page_args['row'] = page_size + page_args['tojs'] = args['tojs'] + data['page'] = mw.getPage(page_args) + data['data'] = log_bin_l[page_start:page_end] + + return mw.getJson(data) + + def cleanBinLog(): db = pMysqlDb() cleanTime = time.strftime('%Y-%m-%d %H:%i:%s', time.localtime()) @@ -2431,11 +2487,65 @@ def getSlaveList(version=''): db = pMysqlDb() dlist = db.query('show slave status') + + # print(dlist) data = {} data['data'] = dlist return mw.getJson(data) +def trySlaveSyncBugfix(version=''): + if status(version) == 'stop': + return mw.returnJson(False, 'MySQL未启动', []) + + mode_file = getSyncModeFile() + if not os.path.exists(mode_file): + return mw.returnJson(False, '需要先设置同步配置') + + mode = mw.readFile(mode_file) + if mode != 'sync-user': + return mw.returnJson(False, '仅支持【同步账户】模式') + + conn = pSqliteDb('slave_sync_user') + slave_sync_data = conn.field('ip,port,user,pass,mode,cmd').select() + if len(slave_sync_data) < 1: + return mw.returnJson(False, '需要先添加【同步用户】配置!') + + # print(slave_sync_data) + # 本地从库 + sdb = pMysqlDb() + + gtid_purged = '' + + for i in range(len(slave_sync_data)): + port = slave_sync_data[i]['port'] + password = slave_sync_data[i]['pass'] + host = slave_sync_data[i]['ip'] + user = slave_sync_data[i]['user'] + + # print(port, password, host) + + mdb = mw.getMyORM() + mdb.setHost(host) + mdb.setPort(port) + mdb.setUser(user) + mdb.setPwd(password) + mdb.setSocket('') + + var_gtid = mdb.query('show VARIABLES like "%gtid_purged%"') + if len(var_gtid) > 0: + gtid_purged += var_gtid[0]['Value'] + ',' + + gtid_purged = gtid_purged.strip(',') + sql = "set @@global.gtid_purged='" + gtid_purged + "'" + + sdb.query('stop slave') + # print(sql) + sdb.query(sql) + sdb.query('start slave') + return mw.returnJson(True, '修复成功!') + + def getSlaveSyncCmd(version=''): root = mw.getRunDir() cmd = 'cd ' + root + ' && python3 ' + root + \ @@ -3021,6 +3131,10 @@ if __name__ == "__main__": print(getConf()) elif func == 'bin_log': print(binLog()) + elif func == 'binlog_list': + print(binLogList()) + elif func == 'binlog_look': + print(binLogListLook()) elif func == 'clean_bin_log': print(cleanBinLog()) elif func == 'error_log': @@ -3115,6 +3229,8 @@ if __name__ == "__main__": print(getMasterRepSlaveUserCmd(version)) elif func == 'get_slave_list': print(getSlaveList(version)) + elif func == 'try_slave_sync_bugfix': + print(trySlaveSyncBugfix(version)) elif func == 'get_slave_sync_cmd': print(getSlaveSyncCmd(version)) elif func == 'get_slave_ssh_list': diff --git a/plugins/mysql/index_mysql.py b/plugins/mysql/index_mysql.py new file mode 100644 index 000000000..791d9038f --- /dev/null +++ b/plugins/mysql/index_mysql.py @@ -0,0 +1,186 @@ +# coding:utf-8 + +import sys +import io +import os +import time +import subprocess +import re +import json + +sys.path.append(os.getcwd() + "/class/core") +import mw + + +if mw.isAppleSystem(): + cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\'' + info = mw.execShell(cmd) + p = "/usr/local/lib/" + info[0].strip() + "/site-packages" + sys.path.append(p) + + +app_debug = False +if mw.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'mysql' + + +def getPluginDir(): + return mw.getPluginDir() + '/' + getPluginName() + + +def getSPluginDir(): + return '/www/server/mdserver-web/plugins/' + getPluginName() + + +def getServerDir(): + return mw.getServerDir() + '/' + getPluginName() + + +def getConf(): + path = getServerDir() + '/etc/my.cnf' + return path + + +def getDataDir(): + file = getConf() + content = mw.readFile(file) + rep = 'datadir\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def getRelayLogName(): + file = getConf() + content = mw.readFile(file) + rep = 'relay-log\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def getLogBinName(): + file = getConf() + content = mw.readFile(file) + rep = 'log-bin\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def binLogListLook(args): + + file = args['file'] + line = args['line'] + + data_dir = getDataDir() + my_bin = getServerDir() + '/bin' + my_binlog_cmd = my_bin + '/mysqlbinlog' + + cmd = my_binlog_cmd + ' --no-defaults ' + \ + data_dir + '/' + file + '|tail -' + str(line) + + data = mw.execShell(cmd) + + rdata = {} + rdata['cmd'] = cmd + rdata['data'] = data[0] + + return rdata + + +def binLogListLookDecode(args): + + file = args['file'] + line = args['line'] + + data_dir = getDataDir() + my_bin = getServerDir() + '/bin' + my_binlog_cmd = my_bin + '/mysqlbinlog' + + cmd = my_binlog_cmd + ' --no-defaults --base64-output=decode-rows -vvvv ' + \ + data_dir + '/' + file + '|tail -' + str(line) + + data = mw.execShell(cmd) + + rdata = {} + rdata['cmd'] = cmd + rdata['data'] = data[0] + + return rdata + + +def binLogListTraceRelay(args): + rdata = {} + file = args['file'] + line = args['line'] + + relay_name = getRelayLogName() + data_dir = getDataDir() + alist = os.listdir(data_dir) + relay_list = [] + for x in range(len(alist)): + f = alist[x] + t = {} + if f.startswith(relay_name) and not f.endswith('.index'): + relay_list.append(f) + + relay_list = sorted(relay_list, reverse=True) + if len(relay_list) == 0: + rdata['cmd'] = '' + rdata['data'] = '无Relay日志' + return rdata + + file = relay_list[0] + + my_bin = getServerDir() + '/bin' + my_binlog_cmd = my_bin + '/mysqlbinlog' + + cmd = my_binlog_cmd + ' --no-defaults --base64-output=decode-rows -vvvv ' + \ + data_dir + '/' + file + '|tail -' + str(line) + + data = mw.execShell(cmd) + + rdata['cmd'] = cmd + rdata['data'] = data[0] + + return rdata + + +def binLogListTraceBinLog(args): + rdata = {} + file = args['file'] + line = args['line'] + + data_dir = getDataDir() + log_bin_name = getLogBinName() + + alist = os.listdir(data_dir) + log_bin_l = [] + for x in range(len(alist)): + f = alist[x] + t = {} + if f.startswith(log_bin_name) and not f.endswith('.index'): + log_bin_l.append(f) + + if len(log_bin_l) == 0: + rdata['cmd'] = '' + rdata['data'] = '无BINLOG' + return rdata + + log_bin_l = sorted(log_bin_l, reverse=True) + file = log_bin_l[0] + + my_bin = getServerDir() + '/bin' + my_binlog_cmd = my_bin + '/mysqlbinlog' + + cmd = my_binlog_cmd + ' --no-defaults --base64-output=decode-rows -vvvv ' + \ + data_dir + '/' + file + '|tail -' + str(line) + + data = mw.execShell(cmd) + + rdata['cmd'] = cmd + rdata['data'] = data[0] + + return rdata diff --git a/plugins/mysql/js/mysql.js b/plugins/mysql/js/mysql.js index 6754df892..bfb8ea425 100755 --- a/plugins/mysql/js/mysql.js +++ b/plugins/mysql/js/mysql.js @@ -59,6 +59,63 @@ function myAsyncPost(method,args){ return syncPost('/plugins/run', {name:'mysql', func:method, args:_args}); } + +function myPostCallbak(method, version, args,callback){ + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + + var req_data = {}; + req_data['name'] = 'mysql'; + req_data['func'] = method; + req_data['script']='index_mysql'; + args['version'] = version; + + + if (typeof(args) == 'string' && args == ''){ + req_data['args'] = JSON.stringify(toArrayObject(args)); + } else { + req_data['args'] = JSON.stringify(args); + } + + $.post('/plugins/callback', req_data, function(data) { + layer.close(loadT); + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +function myPostCallbakN(method, version, args,callback){ + + var req_data = {}; + req_data['name'] = 'mysql'; + req_data['func'] = method; + req_data['script']='index_mysql'; + args['version'] = version; + + + if (typeof(args) == 'string' && args == ''){ + req_data['args'] = JSON.stringify(toArrayObject(args)); + } else { + req_data['args'] = JSON.stringify(args); + } + + $.post('/plugins/callback', req_data, function(data) { + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + function vaildPhpmyadmin(url,username,password){ // console.log("Authorization: Basic " + btoa(username + ":" + password)); $.ajax({ @@ -1163,6 +1220,146 @@ function dbList(page, search){ } +function myBinRollingLogs(_name, func, _args, line){ + + var file_line = 100; + if ( typeof(line) != 'undefined' ){ + file_line = line; + } + + var reqTimer = null; + + function requestLogs(func,file,line){ + myPostCallbakN(func,'',{'file':file,"line":line}, function(rdata){ + var data = rdata.data.data; + var cmd = rdata.data.cmd; + if(data == '') { + data = '当前没有日志!'; + } + + $('#my_rolling_cmd').html(cmd); + + $('#my_rolling_copy').click(function(){ + copyText(cmd); + }); + + var ebody = ''; + $("#my_rolling_logs").html(ebody); + var ob = document.getElementById('roll_info_log'); + ob.scrollTop = ob.scrollHeight; + }); + } + + + layer.open({ + type: 1, + title: _name + '日志', + area: ['800px','700px'], + end: function(){ + if (reqTimer){ + clearInterval(reqTimer); + } + }, + content:'cmd | \ +\ + |
文件名称 | \ +大小 | \ +时间 | \ +操作 | \ +
---|