diff --git a/plugins/mysql-yum/index.html b/plugins/mysql-yum/index.html index 9f105f7a1..57d4d9f63 100755 --- a/plugins/mysql-yum/index.html +++ b/plugins/mysql-yum/index.html @@ -12,6 +12,7 @@

性能优化

日志

慢日志

+

BINLOG

管理列表

主从配置

diff --git a/plugins/mysql-yum/index.py b/plugins/mysql-yum/index.py index 8beae76a9..fb9c17cf8 100755 --- a/plugins/mysql-yum/index.py +++ b/plugins/mysql-yum/index.py @@ -129,6 +129,15 @@ def getErrorLogsFile(): tmp = re.search(rep, content) return tmp.groups()[0].strip() +def getAuthPolicy(): + file = getConf() + content = mw.readFile(file) + rep = 'authentication_policy\s*=\s*(.*)' + tmp = re.search(rep, content) + if tmp: + return tmp.groups()[0].strip() + # caching_sha2_password + return 'mysql_native_password' def contentReplace(content): service_path = mw.getServerDir() @@ -1270,6 +1279,55 @@ def setDbAccess(): psdb.where('username=?', (name,)).save('accept,rw', (access, 'rw',)) return mw.returnJson(True, '设置成功!') +def openSkipGrantTables(): + mycnf = getConf() + content = mw.readFile(mycnf) + content = content.replace('#skip-grant-tables','skip-grant-tables') + mw.writeFile(mycnf, content) + return True + +def closeSkipGrantTables(): + mycnf = getConf() + content = mw.readFile(mycnf) + content = content.replace('skip-grant-tables','#skip-grant-tables') + mw.writeFile(mycnf, content) + return True + + +def resetDbRootPwd(version): + serverdir = getServerDir() + myconf = serverdir + "/etc/my.cnf" + pwd = mw.getRandomString(16) + + pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,)) + + if float(version) < 5.7: + cmd_pass = serverdir + '/bin/mysql --defaults-file=' + myconf + ' -uroot -e' + cmd_pass = cmd_pass + '"UPDATE mysql.user SET password=PASSWORD(\'' + pwd + "') WHERE user='root';" + cmd_pass = cmd_pass + 'flush privileges;"' + data = mw.execShell(cmd_pass) + # print(data) + else: + auth_policy = getAuthPolicy() + + reset_pwd = 'flush privileges;' + reset_pwd = reset_pwd + \ + "UPDATE mysql.user SET authentication_string='' WHERE user='root';" + reset_pwd = reset_pwd + "flush privileges;" + reset_pwd = reset_pwd + \ + "alter user 'root'@'localhost' IDENTIFIED by '" + pwd + "';" + reset_pwd = reset_pwd + \ + "alter user 'root'@'localhost' IDENTIFIED WITH "+auth_policy+" by '" + pwd + "';" + reset_pwd = reset_pwd + "flush privileges;" + + tmp_file = "/tmp/mysql_init_tmp.log" + mw.writeFile(tmp_file, reset_pwd) + cmd_pass = serverdir + '/bin/mysql --defaults-file=' + myconf + ' -uroot -proot < ' + tmp_file + + data = mw.execShell(cmd_pass) + # print(data) + os.remove(tmp_file) + return True def fixDbAccess(version): try: @@ -1832,12 +1890,14 @@ def addMasterRepSlaveUser(version=''): pdb = pMysqlDb() psdb = pSqliteDb('master_replication_user') + auth_policy = getAuthPolicy() + if psdb.where("username=?", (username)).count() > 0: return mw.returnJson(False, '用户已存在!') if version == "8.0": sql = "CREATE USER '" + username + \ - "' IDENTIFIED WITH mysql_native_password BY '" + password + "';" + "' IDENTIFIED WITH "+auth_policy+" BY '" + password + "';" pdb.execute(sql) sql = "grant replication slave on *.* to '" + username + "'@'%';" result = pdb.execute(sql) diff --git a/plugins/mysql-yum/index_mysql_apt.py b/plugins/mysql-yum/index_mysql_apt.py new file mode 100644 index 000000000..956304f69 --- /dev/null +++ b/plugins/mysql-yum/index_mysql_apt.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-apt' + + +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-yum/js/mysql-yum.js b/plugins/mysql-yum/js/mysql-yum.js index fe7ca62e6..c6409a89a 100755 --- a/plugins/mysql-yum/js/mysql-yum.js +++ b/plugins/mysql-yum/js/mysql-yum.js @@ -59,6 +59,63 @@ function myAsyncPost(method,args){ return syncPost('/plugins/run', {name:'mysql-yum', 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-yum'; + req_data['func'] = method; + req_data['script']='index_mysql_apt'; + 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-yum'; + req_data['func'] = method; + req_data['script']='index_mysql_apt'; + 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({ @@ -1162,6 +1219,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
\ +
\ +
\ +
\ + \ +
', + success:function(){ + var fileName = _args['file']; + requestLogs(func,fileName,file_line); + reqTimer = setInterval(function(){ + requestLogs(func,fileName,file_line); + },1000); + } + }); +} + +function myBinLogsRender(page){ + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + _data['tojs'] = 'myBinLogsRender'; + myPost('binlog_list', _data, function(data){ + var rdata = $.parseJSON(data.data); + // console.log(rdata); + var list = ''; + for(i in rdata.data){ + list += ''; + + list += '' + rdata.data[i]['name'] +''; + list += '' + toSize(rdata.data[i]['size'])+''; + list += '' + rdata.data[i]['time'] +''; + + + list += ''; + list += '查看 | '; + list += '解码查看'; + list += ''; + } + + if (rdata.data.length ==0){ + list = '无数据'; + } + + $("#binlog_list tbody").html(list); + $('#binlog_page').html(rdata.page); + + + $('#binlog_list .look').click(function(){ + var i = $(this).data('index'); + var file = rdata.data[i]['name']; + myBinRollingLogs('查看BINLOG','binLogListLook',{'file':file },100); + }); + + $('#binlog_list .look_decode').click(function(){ + var i = $(this).data('index'); + var file = rdata.data[i]['name']; + myBinRollingLogs('查看解码BINLOG','binLogListLookDecode',{'file':file },100); + }); + }); +} + +function myBinLogs(){ + var con = '
\ + \ + \ +
\ +
\ + \ + \ + \ + \ + \ + \ + \ +
文件名称大小时间操作
\ +
\ +
\ +
\ +
'; + $(".soft-man-con").html(con); + myBinLogsRender(1); + + $('.soft-man-con .relay_trace').click(function(){ + myBinRollingLogs('中继日志跟踪','binLogListTraceRelay',{'file':''},100); + }); + + $('.soft-man-con .binlog_trace').click(function(){ + myBinRollingLogs('最新BINLOG日志跟踪','binLogListTraceBinLog',{'file':''},100); + }); +} function myLogs(){