diff --git a/class/core/config_api.py b/class/core/config_api.py index af27dc128..429b3346d 100755 --- a/class/core/config_api.py +++ b/class/core/config_api.py @@ -16,7 +16,7 @@ from flask import request class config_api: # mariadb 优化 - __version = '0.8.6.15' + __version = '0.8.6.16' def __init__(self): pass diff --git a/plugins/mariadb/index.py b/plugins/mariadb/index.py index feaf904c3..9ba058bd2 100755 --- a/plugins/mariadb/index.py +++ b/plugins/mariadb/index.py @@ -668,9 +668,8 @@ def setDbBackup(): if not data[0]: return data[1] - scDir = mw.getRunDir() + '/scripts/backup.py' - - cmd = 'python ' + scDir + ' database ' + args['name'] + ' 3' + scDir = getPluginDir() + '/scripts/backup.py' + cmd = 'python3 ' + scDir + ' database ' + args['name'] + ' 3' os.system(cmd) return mw.returnJson(True, 'ok') diff --git a/plugins/mariadb/scripts/backup.py b/plugins/mariadb/scripts/backup.py new file mode 100755 index 000000000..21ef91d10 --- /dev/null +++ b/plugins/mariadb/scripts/backup.py @@ -0,0 +1,125 @@ +# coding: utf-8 +#----------------------------- +# 网站备份工具 +#----------------------------- + +import sys +import os + +if sys.platform != 'darwin': + os.chdir('/www/server/mdserver-web') + + +chdir = os.getcwd() +sys.path.append(chdir + '/class/core') + +# reload(sys) +# sys.setdefaultencoding('utf-8') + + +import mw +import db +import time + + +class backupTools: + + def backupDatabase(self, name, count): + db_path = mw.getServerDir() + '/mariadb' + db_name = 'mysql' + name = mw.M('databases').dbPos(db_path, 'mysql').where( + 'name=?', (name,)).getField('name') + startTime = time.time() + if not name: + endDate = time.strftime('%Y/%m/%d %X', time.localtime()) + log = "数据库[" + name + "]不存在!" + print("★[" + endDate + "] " + log) + print( + "----------------------------------------------------------------------------") + return + + backup_path = mw.getRootDir() + '/backup/database' + if not os.path.exists(backup_path): + mw.execShell("mkdir -p " + backup_path) + + filename = backup_path + "/db_" + name + "_" + \ + time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz" + + import re + mysql_root = mw.M('config').dbPos(db_path, db_name).where( + "id=?", (1,)).getField('mysql_root') + + mycnf = mw.readFile(db_path + '/etc/my.cnf') + rep = "\[mysqldump\]\nuser=root" + sea = "[mysqldump]\n" + subStr = sea + "user=root\npassword=" + mysql_root + "\n" + mycnf = mycnf.replace(sea, subStr) + if len(mycnf) > 100: + mw.writeFile(db_path + '/etc/my.cnf', mycnf) + + # mw.execShell(db_path + "/bin/mysqldump --opt --default-character-set=utf8 " + + # name + " | gzip > " + filename) + + # mw.execShell(db_path + "/bin/mysqldump --skip-lock-tables --default-character-set=utf8 " + + # name + " | gzip > " + filename) + + mw.execShell(db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " + + name + " | gzip > " + filename) + + if not os.path.exists(filename): + endDate = time.strftime('%Y/%m/%d %X', time.localtime()) + log = "数据库[" + name + "]备份失败!" + print("★[" + endDate + "] " + log) + print( + "----------------------------------------------------------------------------") + return + + mycnf = mw.readFile(db_path + '/etc/my.cnf') + mycnf = mycnf.replace(subStr, sea) + if len(mycnf) > 100: + mw.writeFile(db_path + '/etc/my.cnf', mycnf) + + endDate = time.strftime('%Y/%m/%d %X', time.localtime()) + outTime = time.time() - startTime + pid = mw.M('databases').dbPos(db_path, db_name).where( + 'name=?', (name,)).getField('id') + + mw.M('backup').add('type,name,pid,filename,addtime,size', (1, os.path.basename( + filename), pid, filename, endDate, os.path.getsize(filename))) + log = "数据库[" + name + "]备份成功,用时[" + str(round(outTime, 2)) + "]秒" + mw.writeLog('计划任务', log) + print("★[" + endDate + "] " + log) + print("|---保留最新的[" + count + "]份备份") + print("|---文件名:" + filename) + + # 清理多余备份 + backups = mw.M('backup').where( + 'type=? and pid=?', ('1', pid)).field('id,filename').select() + + num = len(backups) - int(count) + if num > 0: + for backup in backups: + mw.execShell("rm -f " + backup['filename']) + mw.M('backup').where('id=?', (backup['id'],)).delete() + num -= 1 + print("|---已清理过期备份文件:" + backup['filename']) + if num < 1: + break + + def backupDatabaseAll(self, save): + db_path = mw.getServerDir() + '/mariadb' + db_name = 'mysql' + databases = mw.M('databases').dbPos( + db_path, db_name).field('name').select() + for database in databases: + self.backupDatabase(database['name'], save) + + +if __name__ == "__main__": + backup = backupTools() + type = sys.argv[1] + if type == 'database': + if sys.argv[2] == 'ALL': + backup.backupDatabaseAll(sys.argv[3]) + else: + backup.backupDatabase(sys.argv[2], sys.argv[3]) diff --git a/plugins/postgresql/js/postgresql.js b/plugins/postgresql/js/postgresql.js new file mode 100755 index 000000000..afcbdf340 --- /dev/null +++ b/plugins/postgresql/js/postgresql.js @@ -0,0 +1,2035 @@ +function str2Obj(str){ + var data = {}; + kv = str.split('&'); + for(i in kv){ + v = kv[i].split('='); + data[v[0]] = v[1]; + } + return data; +} + +function myPost(method,args,callback, title){ + + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(str2Obj(args)); + } else { + _args = JSON.stringify(args); + } + + var _title = '正在获取...'; + if (typeof(title) != 'undefined'){ + _title = title; + } + + var loadT = layer.msg(_title, { icon: 16, time: 0, shade: 0.3 }); + $.post('/plugins/run', {name:'postgresql', func:method, args:_args}, 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 myPostN(method,args,callback, title){ + + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(str2Obj(args)); + } else { + _args = JSON.stringify(args); + } + + var _title = '正在获取...'; + if (typeof(title) != 'undefined'){ + _title = title; + } + $.post('/plugins/run', {name:'postgresql', func:method, args:_args}, function(data) { + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +function myAsyncPost(method,args){ + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(str2Obj(args)); + } else { + _args = JSON.stringify(args); + } + + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + return syncPost('/plugins/run', {name:'mysql', func:method, args:_args}); +} + +function runInfo(){ + myPost('run_info','',function(data){ + + var rdata = $.parseJSON(data.data); + if (typeof(rdata['status']) != 'undefined'){ + layer.msg(rdata['msg'],{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + var cache_size = ((parseInt(rdata.Qcache_hits) / (parseInt(rdata.Qcache_hits) + parseInt(rdata.Qcache_inserts))) * 100).toFixed(2) + '%'; + if (cache_size == 'NaN%') cache_size = 'OFF'; + var Con = '
\ + \ + \ + \ + \ + \ + \ +
启动时间' + getLocalTime(rdata.Run) + '每秒查询' + parseInt(rdata.Questions / rdata.Uptime) + '
总连接次数' + rdata.Connections + '每秒事务' + parseInt((parseInt(rdata.Com_commit) + parseInt(rdata.Com_rollback)) / rdata.Uptime) + '
发送' + toSize(rdata.Bytes_sent) + 'File' + rdata.File + '
接收' + toSize(rdata.Bytes_received) + 'Position' + rdata.Position + '
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
活动/峰值连接数' + rdata.Threads_running + '/' + rdata.Max_used_connections + '若值过大,增加max_connections
线程缓存命中率' + ((1 - rdata.Threads_created / rdata.Connections) * 100).toFixed(2) + '%若过低,增加thread_cache_size
索引命中率' + ((1 - rdata.Key_reads / rdata.Key_read_requests) * 100).toFixed(2) + '%若过低,增加key_buffer_size
Innodb索引命中率' + ((1 - rdata.Innodb_buffer_pool_reads / rdata.Innodb_buffer_pool_read_requests) * 100).toFixed(2) + '%若过低,增加innodb_buffer_pool_size
查询缓存命中率' + cache_size + '' + lan.soft.mysql_status_ps5 + '
创建临时表到磁盘' + ((rdata.Created_tmp_disk_tables / rdata.Created_tmp_tables) * 100).toFixed(2) + '%若过大,尝试增加tmp_table_size
已打开的表' + rdata.Open_tables + '若过大,增加table_cache_size
没有使用索引的量' + rdata.Select_full_join + '若不为0,请检查数据表的索引是否合理
没有索引的JOIN量' + rdata.Select_range_check + '若不为0,请检查数据表的索引是否合理
排序后的合并次数' + rdata.Sort_merge_passes + '若值过大,增加sort_buffer_size
锁表次数' + rdata.Table_locks_waited + '若值过大,请考虑增加您的数据库性能
'; + $(".soft-man-con").html(Con); + }); +} + + +function myDbPos(){ + myPost('my_db_pos','',function(data){ + var con = '
\ +
\ + \ + \ + \ +
'; + $(".soft-man-con").html(con); + + $('#btn_change_path').click(function(){ + var datadir = $("input[name='datadir']").val(); + myPost('set_db_pos','datadir='+datadir,function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg,{icon:rdata.status ? 1 : 5,time:2000,shade: [0.3, '#000']}); + }); + }); + }); +} + +function myPort(){ + myPost('my_port','',function(data){ + var con = '
\ +
\ + \ + \ +
'; + $(".soft-man-con").html(con); + + $('#btn_change_port').click(function(){ + var port = $("input[name='port']").val(); + myPost('set_my_port','port='+port,function(data){ + var rdata = $.parseJSON(data.data); + if (rdata.status){ + layer.msg('修改成功!',{icon:1,time:2000,shade: [0.3, '#000']}); + } else { + layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']}); + } + }); + }); + }); +} + + +//数据库存储信置 +function changeMySQLDataPath(act) { + if (act != undefined) { + layer.confirm(lan.soft.mysql_to_msg, { closeBtn: 2, icon: 3 }, function() { + var datadir = $("#datadir").val(); + var data = 'datadir=' + datadir; + var loadT = layer.msg(lan.soft.mysql_to_msg1, { icon: 16, time: 0, shade: [0.3, '#000'] }); + $.post('/database?action=SetDataDir', data, function(rdata) { + layer.close(loadT) + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + }); + }); + return; + } + + $.post('/database?action=GetMySQLInfo', '', function(rdata) { + var LimitCon = '

\ + \ + \ +

'; + $(".soft-man-con").html(LimitCon); + }); +} + + + + +//数据库配置状态 +function myPerfOpt() { + //获取MySQL配置 + myPost('db_status','',function(data){ + var rdata = $.parseJSON(data.data); + // console.log(rdata); + var key_buffer_size = toSizeM(rdata.mem.key_buffer_size); + var query_cache_size = toSizeM(rdata.mem.query_cache_size); + var tmp_table_size = toSizeM(rdata.mem.tmp_table_size); + var innodb_buffer_pool_size = toSizeM(rdata.mem.innodb_buffer_pool_size); + var innodb_additional_mem_pool_size = toSizeM(rdata.mem.innodb_additional_mem_pool_size); + var innodb_log_buffer_size = toSizeM(rdata.mem.innodb_log_buffer_size); + + var sort_buffer_size = toSizeM(rdata.mem.sort_buffer_size); + var read_buffer_size = toSizeM(rdata.mem.read_buffer_size); + var read_rnd_buffer_size = toSizeM(rdata.mem.read_rnd_buffer_size); + var join_buffer_size = toSizeM(rdata.mem.join_buffer_size); + var thread_stack = toSizeM(rdata.mem.thread_stack); + var binlog_cache_size = toSizeM(rdata.mem.binlog_cache_size); + + var a = key_buffer_size + query_cache_size + tmp_table_size + innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size; + var b = sort_buffer_size + read_buffer_size + read_rnd_buffer_size + join_buffer_size + thread_stack + binlog_cache_size; + var memSize = a + rdata.mem.max_connections * b; + + + var memCon = '
\ +
最大使用内存: \ + \ + ' + lan.soft.mysql_set_maxmem + ': MB\ +
\ +

key_buffer_sizeMB, ' + lan.soft.mysql_set_key_buffer_size + '

\ +

query_cache_sizeMB, ' + lan.soft.mysql_set_query_cache_size + '

\ +

tmp_table_sizeMB, ' + lan.soft.mysql_set_tmp_table_size + '

\ +

innodb_buffer_pool_sizeMB, ' + lan.soft.mysql_set_innodb_buffer_pool_size + '

\ +

innodb_log_buffer_sizeMB, ' + lan.soft.mysql_set_innodb_log_buffer_size + '

\ +

innodb_additional_mem_pool_sizeMB

\ +

sort_buffer_sizeKB * ' + lan.soft.mysql_set_conn + ', ' + lan.soft.mysql_set_sort_buffer_size + '

\ +

read_buffer_sizeKB * ' + lan.soft.mysql_set_conn + ', ' + lan.soft.mysql_set_read_buffer_size + '

\ +

read_rnd_buffer_sizeKB * ' + lan.soft.mysql_set_conn + ', ' + lan.soft.mysql_set_read_rnd_buffer_size + '

\ +

join_buffer_sizeKB * ' + lan.soft.mysql_set_conn + ', ' + lan.soft.mysql_set_join_buffer_size + '

\ +

thread_stackKB * ' + lan.soft.mysql_set_conn + ', ' + lan.soft.mysql_set_thread_stack + '

\ +

binlog_cache_sizeKB * ' + lan.soft.mysql_set_conn + ', ' + lan.soft.mysql_set_binlog_cache_size + '

\ +

thread_cache_size ' + lan.soft.mysql_set_thread_cache_size + '

\ +

table_open_cache ' + lan.soft.mysql_set_table_open_cache + '

\ +

max_connections ' + lan.soft.mysql_set_max_connections + '

\ +
\ +
' + + $(".soft-man-con").html(memCon); + + $(".conf_p input[name*='size'],.conf_p input[name='max_connections'],.conf_p input[name='thread_stack']").change(function() { + comMySqlMem(); + }); + + $(".conf_p select[name='mysql_set']").change(function() { + mySQLMemOpt($(this).val()); + comMySqlMem(); + }); + }); +} + +function reBootMySqld(){ + pluginOpService('mysql','restart',''); +} + + +//设置MySQL配置参数 +function setMySQLConf() { + $.post('/system/system_total', '', function(memInfo) { + var memSize = memInfo['memTotal']; + var setSize = parseInt($("input[name='memSize']").val()); + + if(memSize < setSize){ + var errMsg = "错误,内存分配过高!

物理内存: {1}MB
最大使用内存: {2}MB
可能造成的后果: 导致数据库不稳定,甚至无法启动MySQLd服务!"; + var msg = errMsg.replace('{1}',memSize).replace('{2}',setSize); + layer.msg(msg,{icon:2,time:5000}); + return; + } + + var query_cache_size = parseInt($("input[name='query_cache_size']").val()); + var query_cache_type = 0; + if (query_cache_size > 0) { + query_cache_type = 1; + } + var data = { + key_buffer_size: parseInt($("input[name='key_buffer_size']").val()), + query_cache_size: query_cache_size, + query_cache_type: query_cache_type, + tmp_table_size: parseInt($("input[name='tmp_table_size']").val()), + max_heap_table_size: parseInt($("input[name='tmp_table_size']").val()), + innodb_buffer_pool_size: parseInt($("input[name='innodb_buffer_pool_size']").val()), + innodb_log_buffer_size: parseInt($("input[name='innodb_log_buffer_size']").val()), + sort_buffer_size: parseInt($("input[name='sort_buffer_size']").val()), + read_buffer_size: parseInt($("input[name='read_buffer_size']").val()), + read_rnd_buffer_size: parseInt($("input[name='read_rnd_buffer_size']").val()), + join_buffer_size: parseInt($("input[name='join_buffer_size']").val()), + thread_stack: parseInt($("input[name='thread_stack']").val()), + binlog_cache_size: parseInt($("input[name='binlog_cache_size']").val()), + thread_cache_size: parseInt($("input[name='thread_cache_size']").val()), + table_open_cache: parseInt($("input[name='table_open_cache']").val()), + max_connections: parseInt($("input[name='max_connections']").val()) + }; + + myPost('set_db_status', data, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + reBootMySqld(); + },{ icon: rdata.status ? 1 : 2 }); + }); + },'json'); +} + + +//MySQL内存优化方案 +function mySQLMemOpt(opt) { + var query_size = parseInt($("input[name='query_cache_size']").val()); + switch (opt) { + case '0': + $("input[name='key_buffer_size']").val(8); + if (query_size) $("input[name='query_cache_size']").val(4); + $("input[name='tmp_table_size']").val(8); + $("input[name='innodb_buffer_pool_size']").val(16); + $("input[name='sort_buffer_size']").val(256); + $("input[name='read_buffer_size']").val(256); + $("input[name='read_rnd_buffer_size']").val(128); + $("input[name='join_buffer_size']").val(128); + $("input[name='thread_stack']").val(256); + $("input[name='binlog_cache_size']").val(32); + $("input[name='thread_cache_size']").val(4); + $("input[name='table_open_cache']").val(32); + $("input[name='max_connections']").val(500); + break; + case '1': + $("input[name='key_buffer_size']").val(128); + if (query_size) $("input[name='query_cache_size']").val(64); + $("input[name='tmp_table_size']").val(64); + $("input[name='innodb_buffer_pool_size']").val(256); + $("input[name='sort_buffer_size']").val(768); + $("input[name='read_buffer_size']").val(768); + $("input[name='read_rnd_buffer_size']").val(512); + $("input[name='join_buffer_size']").val(1024); + $("input[name='thread_stack']").val(256); + $("input[name='binlog_cache_size']").val(64); + $("input[name='thread_cache_size']").val(64); + $("input[name='table_open_cache']").val(128); + $("input[name='max_connections']").val(100); + break; + case '2': + $("input[name='key_buffer_size']").val(256); + if (query_size) $("input[name='query_cache_size']").val(128); + $("input[name='tmp_table_size']").val(384); + $("input[name='innodb_buffer_pool_size']").val(384); + $("input[name='sort_buffer_size']").val(768); + $("input[name='read_buffer_size']").val(768); + $("input[name='read_rnd_buffer_size']").val(512); + $("input[name='join_buffer_size']").val(2048); + $("input[name='thread_stack']").val(256); + $("input[name='binlog_cache_size']").val(64); + $("input[name='thread_cache_size']").val(96); + $("input[name='table_open_cache']").val(192); + $("input[name='max_connections']").val(200); + break; + case '3': + $("input[name='key_buffer_size']").val(384); + if (query_size) $("input[name='query_cache_size']").val(192); + $("input[name='tmp_table_size']").val(512); + $("input[name='innodb_buffer_pool_size']").val(512); + $("input[name='sort_buffer_size']").val(1024); + $("input[name='read_buffer_size']").val(1024); + $("input[name='read_rnd_buffer_size']").val(768); + $("input[name='join_buffer_size']").val(2048); + $("input[name='thread_stack']").val(256); + $("input[name='binlog_cache_size']").val(128); + $("input[name='thread_cache_size']").val(128); + $("input[name='table_open_cache']").val(384); + $("input[name='max_connections']").val(300); + break; + case '4': + $("input[name='key_buffer_size']").val(512); + if (query_size) $("input[name='query_cache_size']").val(256); + $("input[name='tmp_table_size']").val(1024); + $("input[name='innodb_buffer_pool_size']").val(1024); + $("input[name='sort_buffer_size']").val(2048); + $("input[name='read_buffer_size']").val(2048); + $("input[name='read_rnd_buffer_size']").val(1024); + $("input[name='join_buffer_size']").val(4096); + $("input[name='thread_stack']").val(384); + $("input[name='binlog_cache_size']").val(192); + $("input[name='thread_cache_size']").val(192); + $("input[name='table_open_cache']").val(1024); + $("input[name='max_connections']").val(400); + break; + case '5': + $("input[name='key_buffer_size']").val(1024); + if (query_size) $("input[name='query_cache_size']").val(384); + $("input[name='tmp_table_size']").val(2048); + $("input[name='innodb_buffer_pool_size']").val(4096); + $("input[name='sort_buffer_size']").val(4096); + $("input[name='read_buffer_size']").val(4096); + $("input[name='read_rnd_buffer_size']").val(2048); + $("input[name='join_buffer_size']").val(8192); + $("input[name='thread_stack']").val(512); + $("input[name='binlog_cache_size']").val(256); + $("input[name='thread_cache_size']").val(256); + $("input[name='table_open_cache']").val(2048); + $("input[name='max_connections']").val(500); + break; + } +} + +//计算MySQL内存开销 +function comMySqlMem() { + var key_buffer_size = parseInt($("input[name='key_buffer_size']").val()); + var query_cache_size = parseInt($("input[name='query_cache_size']").val()); + var tmp_table_size = parseInt($("input[name='tmp_table_size']").val()); + var innodb_buffer_pool_size = parseInt($("input[name='innodb_buffer_pool_size']").val()); + var innodb_additional_mem_pool_size = parseInt($("input[name='innodb_additional_mem_pool_size']").val()); + var innodb_log_buffer_size = parseInt($("input[name='innodb_log_buffer_size']").val()); + + var sort_buffer_size = $("input[name='sort_buffer_size']").val() / 1024; + var read_buffer_size = $("input[name='read_buffer_size']").val() / 1024; + var read_rnd_buffer_size = $("input[name='read_rnd_buffer_size']").val() / 1024; + var join_buffer_size = $("input[name='join_buffer_size']").val() / 1024; + var thread_stack = $("input[name='thread_stack']").val() / 1024; + var binlog_cache_size = $("input[name='binlog_cache_size']").val() / 1024; + var max_connections = $("input[name='max_connections']").val(); + + var a = key_buffer_size + query_cache_size + tmp_table_size + innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size + var b = sort_buffer_size + read_buffer_size + read_rnd_buffer_size + join_buffer_size + thread_stack + binlog_cache_size + var memSize = a + max_connections * b + $("input[name='memSize']").val(memSize.toFixed(2)); +} + +function syncGetDatabase(){ + myPost('sync_get_databases', null, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + dbList(); + },{ icon: rdata.status ? 1 : 2 }); + }); +} + +function syncToDatabase(type){ + var data = []; + $('input[type="checkbox"].check:checked').each(function () { + if (!isNaN($(this).val())) data.push($(this).val()); + }); + var postData = 'type='+type+'&ids='+JSON.stringify(data); + myPost('sync_to_databases', postData, function(data){ + var rdata = $.parseJSON(data.data); + // console.log(rdata); + showMsg(rdata.msg,function(){ + dbList(); + },{ icon: rdata.status ? 1 : 2 }); + }); +} + +function setRootPwd(type, pwd){ + if (type==1){ + var data = $("#mod_pwd").serialize(); + myPost('set_root_pwd', data, function(data){ + var rdata = $.parseJSON(data.data); + // console.log(rdata); + showMsg(rdata.msg,function(){ + dbList(); + $('.layui-layer-close1').click(); + },{icon: rdata.status ? 1 : 2}); + }); + return; + } + + var index = layer.open({ + type: 1, + skin: 'demo-class', + area: '500px', + title: '修改数据库密码', + closeBtn: 1, + shift: 5, + shadeClose: true, + content: "

\ +
\ + root密码\ +
\ +
\ +
\ + \ + \ +
\ +
", + }); + + $('#my_mod_close').click(function(){ + $('.layui-layer-close1').click(); + }); +} + +function showHidePass(obj){ + var a = "glyphicon-eye-open"; + var b = "glyphicon-eye-close"; + + if($(obj).hasClass(a)){ + $(obj).removeClass(a).addClass(b); + $(obj).prev().text($(obj).prev().attr('data-pw')) + } + else{ + $(obj).removeClass(b).addClass(a); + $(obj).prev().text('***'); + } +} + +function copyPass(password){ + var clipboard = new ClipboardJS('#bt_copys'); + clipboard.on('success', function (e) { + layer.msg('复制成功',{icon:1,time:2000}); + }); + + clipboard.on('error', function (e) { + layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000}); + }); + $("#bt_copys").attr('data-clipboard-text',password); + $("#bt_copys").click(); +} + +function checkSelect(){ + setTimeout(function () { + var num = $('input[type="checkbox"].check:checked').length; + // console.log(num); + if (num == 1) { + $('button[batch="true"]').hide(); + $('button[batch="false"]').show(); + }else if (num>1){ + $('button[batch="true"]').show(); + $('button[batch="false"]').show(); + }else{ + $('button[batch="true"]').hide(); + $('button[batch="false"]').hide(); + } + },5) +} + +function setDbRw(id,username,val){ + myPost('get_db_rw',{id:id,username:username,rw:val}, function(data){ + var rdata = $.parseJSON(data.data); + // layer.msg(rdata.msg,{icon:rdata.status ? 1 : 5,shade: [0.3, '#000']}); + showMsg(rdata.msg, function(){ + dbList(); + },{icon:rdata.status ? 1 : 5,shade: [0.3, '#000']}, 2000); + + }); +} + +function setDbAccess(username){ + myPost('get_db_access','username='+username, function(data){ + var rdata = $.parseJSON(data.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']}); + return; + } + + var index = layer.open({ + type: 1, + area: '500px', + title: '设置数据库权限', + closeBtn: 1, + shift: 5, + btn:["提交","取消"], + shadeClose: true, + content: "
\ +
\ + 访问权限\ +
\ + \ +
\ +
\ +
", + success:function(){ + if (rdata.msg == '127.0.0.1'){ + $('select[name="dataAccess"]').find("option[value='127.0.0.1']").attr("selected",true); + } else if (rdata.msg == '%'){ + $('select[name="dataAccess"]').find('option[value="%"]').attr("selected",true); + } else if ( rdata.msg == 'ip' ){ + $('select[name="dataAccess"]').find('option[value="ip"]').attr("selected",true); + $('select[name="dataAccess"]').after(""); + } else { + $('select[name="dataAccess"]').find('option[value="ip"]').attr("selected",true); + $('select[name="dataAccess"]').after(""); + } + + $('select[name="dataAccess"]').change(function(){ + var v = $(this).val(); + if (v == 'ip'){ + $(this).after(""); + } else { + $('#dataAccess_subid').remove(); + } + }); + }, + yes:function(index){ + var data = $("#set_db_access").serialize(); + data = decodeURIComponent(data); + var dataObj = str2Obj(data); + if(!dataObj['access']){ + dataObj['access'] = dataObj['dataAccess']; + if ( dataObj['dataAccess'] == 'ip'){ + if (dataObj['address']==''){ + layer.msg('IP地址不能空!',{icon:2,shade: [0.3, '#000']}); + return; + } + dataObj['access'] = dataObj['address']; + } + } + dataObj['username'] = username; + myPost('set_db_access', dataObj, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + layer.close(index); + dbList(); + },{icon: rdata.status ? 1 : 2}); + }); + } + }); + + }); +} + +function setDbPass(id, username, password){ + + var index = layer.open({ + type: 1, + area: '500px', + title: '修改数据库密码', + closeBtn: 1, + shift: 5, + shadeClose: true, + btn:["提交","关闭"], + content: "
\ +
\ + 用户名\ +
\ +
\ +
\ + 密码\ +
\ +
\ + \ +
", + yes:function(index){ + var data = $("#mod_pwd").serialize(); + myPost('set_user_pwd', data, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + layer.close(index); + dbList(); + },{icon: rdata.status ? 1 : 2}); + }); + } + }); +} + +function addDatabase(type){ + if (type==1){ + var data = $("#add_db").serialize(); + data = decodeURIComponent(data); + var dataObj = str2Obj(data); + if(!dataObj['address']){ + dataObj['address'] = dataObj['dataAccess']; + } + myPost('add_db', dataObj, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + if (rdata.status){ + dbList(); + } + $('.layui-layer-close1').click(); + },{icon: rdata.status ? 1 : 2},600); + }); + return; + } + var index = layer.open({ + type: 1, + skin: 'demo-class', + area: '500px', + title: '添加数据库', + closeBtn: 1, + shift: 5, + shadeClose: true, + content: "
\ +
\ + 数据库名\ +
\ + \ +
\ +
\ +
用户名
\ +
\ + 密码\ +
\ +
\ +
\ + 访问权限\ +
\ + \ +
\ +
\ + \ +
\ + \ + \ +
\ +
", + }); + + $("input[name='name']").keyup(function(){ + var v = $(this).val(); + $("input[name='db_user']").val(v); + $("input[name='ps']").val(v); + }); + + $('#my_mod_close').click(function(){ + $('.layui-layer-close1').click(); + }); + $('select[name="dataAccess"]').change(function(){ + var v = $(this).val(); + if (v == 'ip'){ + $(this).after(""); + } else { + $('#dataAccess_subid').remove(); + } + }); +} + +function delDb(id, name){ + safeMessage('删除['+name+']','您真的要删除['+name+']吗?',function(){ + var data='id='+id+'&name='+name + myPost('del_db', data, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + dbList(); + $('.layui-layer-close1').click(); + },{icon: rdata.status ? 1 : 2}, 600); + }); + }); +} + +function delDbBatch(){ + var arr = []; + $('input[type="checkbox"].check:checked').each(function () { + var _val = $(this).val(); + var _name = $(this).parent().next().text(); + if (!isNaN(_val)) { + arr.push({'id':_val,'name':_name}); + } + }); + + safeMessage('批量删除数据库','您共选择了[2]个数据库,删除后将无法恢复,真的要删除吗?',function(){ + var i = 0; + $(arr).each(function(){ + var data = myAsyncPost('del_db', this); + var rdata = $.parseJSON(data.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']}); + } + i++; + }); + + var msg = '成功删除['+i+']个数据库!'; + showMsg(msg,function(){ + dbList(); + },{icon: 1}, 600); + }); +} + + +function setDbPs(id, name, obj) { + var _span = $(obj); + var _input = $(""); + _span.hide().after(_input); + _input.focus(); + _input.blur(function(){ + $(this).remove(); + var ps = _input.val(); + _span.text(ps).show(); + var data = {name:name,id:id,ps:ps}; + myPost('set_db_ps', data, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + }); + }); + _input.keyup(function(){ + if(event.keyCode == 13){ + _input.trigger('blur'); + } + }); +} + +function openPhpmyadmin(name,username,password){ + + data = syncPost('/plugins/check',{'name':'phpmyadmin'}); + + + if (!data.status){ + layer.msg(data.msg,{icon:2,shade: [0.3, '#000']}); + return; + } + + data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'status'}); + if (data.data != 'start'){ + layer.msg('phpMyAdmin未启动',{icon:2,shade: [0.3, '#000']}); + return; + } + // console.log(data); + data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'}); + var rdata = $.parseJSON(data.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']}); + return; + } + $("#toPHPMyAdmin").attr('action',rdata.data); + + if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){ + layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']}); + setTimeout(function(){ window.location.href = '/soft'; },3000); + return; + } + + //检查版本 + data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'version'}); + bigVer = data.data.split('.')[0] + if (bigVer>=4.5){ + + setTimeout(function(){ + $("#toPHPMyAdmin").submit(); + },3000); + layer.msg('phpMyAdmin['+data.data+']需要手动登录😭',{icon:16,shade: [0.3, '#000'],time:4000}); + + } else{ + var murl = $("#toPHPMyAdmin").attr('action'); + $("#pma_username").val(username); + $("#pma_password").val(password); + $("#db").val(name); + + layer.msg('正在打开phpMyAdmin',{icon:16,shade: [0.3, '#000'],time:2000}); + + setTimeout(function(){ + $("#toPHPMyAdmin").submit(); + },3000); + } +} + +function delBackup(filename,name){ + myPost('delete_db_backup',{filename:filename},function(){ + layer.msg('执行成功!'); + setTimeout(function(){ + $('.layui-layer-close2').click(); + setBackup(name); + },2000); + }); +} + +function downloadBackup(file){ + window.open('/files/download?filename='+encodeURIComponent(file)); +} + +function importBackup(file,name){ + myPost('import_db_backup',{file:file,name:name}, function(data){ + // console.log(data); + layer.msg('执行成功!'); + }); +} + +function setBackup(db_name,obj){ + myPost('get_db_backup_list', {name:db_name}, function(data){ + + var rdata = $.parseJSON(data.data); + var tbody = ''; + for (var i = 0; i < rdata.data.length; i++) { + tbody += '\ + ' + rdata.data[i]['name'] + '\ + ' + rdata.data[i]['size'] + '\ + ' + rdata.data[i]['time'] + '\ + \ + 导入 | \ + 下载 | \ + 删除\ + \ + '; + } + + var s = layer.open({ + type: 1, + title: "数据库备份详情", + area: ['600px', '280px'], + closeBtn: 2, + shadeClose: false, + content: '
\ +
\ + \ +
\ +
\ +
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + ' + tbody + '\ +
文件名称文件大小备份时间操作
\ +
\ +
\ +
' + }); + + $('#btn_backup').click(function(){ + myPost('set_db_backup',{name:db_name}, function(data){ + layer.msg('执行成功!'); + + setTimeout(function(){ + layer.close(s); + setBackup(db_name,obj); + },2000); + }); + }); + }); +} + + +function dbList(page, search){ + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + if(typeof(search) != 'undefined'){ + _data['search'] = search; + } + myPost('get_db_list', _data, function(data){ + var rdata = $.parseJSON(data.data); + var list = ''; + for(i in rdata.data){ + list += ''; + list +=''; + list += '' + rdata.data[i]['name'] +''; + list += '' + rdata.data[i]['username'] +''; + list += '' + + '***' + + ''+ + ''+ + ''; + + + list += ''+rdata.data[i]['ps']+''; + list += ''; + + list += ''+(rdata.data[i]['is_backup']?'备份':'未备份') +' | '; + + var rw = ''; + var rw_change = 'all'; + if (typeof(rdata.data[i]['rw'])!='undefined'){ + var rw_val = '读写'; + if (rdata.data[i]['rw'] == 'all'){ + rw_val = "所有"; + rw_change = 'rw'; + } else if (rdata.data[i]['rw'] == 'rw'){ + rw_val = "读写"; + rw_change = 'r'; + } else if (rdata.data[i]['rw'] == 'r'){ + rw_val = "只读"; + rw_change = 'all'; + } + rw = ''+rw_val+' | '; + } + + + list += '管理 | ' + + '工具 | ' + + '权限 | ' + + rw + + '改密 | ' + + '删除' + + ''; + list += ''; + } + + // + var con = '
\ + \ + \ + \ + \ + \ + \ + \ +
\ +
\ + \ + \ + \ + \ + \ + '+ + // ''+ + '\ + \ + \ + '+ list +'\ +
数据库名用户名密码备份备注操作
\ +
\ +
\ +
\ + 同步选中\ + 同步所有\ + 从服务器获取\ +
\ +
\ +
'; + + con += ''; + + $(".soft-man-con").html(con); + $('#databasePage').html(rdata.page); + + readerTableChecked(); + }); +} + + +function myLogs(){ + + myPost('bin_log', {status:1}, function(data){ + var rdata = $.parseJSON(data.data); + + var line_status = "" + if (rdata.status){ + line_status = '\ + '; + } else { + line_status = ''; + } + + var limitCon = '

\ + 二进制日志 ' + toSize(rdata.msg) + '\ + '+line_status+'\ +

错误日志

\ + \ +

'; + $(".soft-man-con").html(limitCon); + + //设置二进制日志 + $(".btn-bin").click(function () { + myPost('bin_log', 'close=change', function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){myLogs();}, 2000); + }); + }); + + $(".clean-btn-bin").click(function () { + myPost('clean_bin_log', '', function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){myLogs();}, 2000); + }); + }); + + //清空日志 + $(".btn-clear").click(function () { + myPost('error_log', 'close=1', function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){myLogs();}, 2000); + }); + }) + + myPost('error_log', 'p=1', function(data){ + var rdata = $.parseJSON(data.data); + var error_body = ''; + if (rdata.status){ + error_body = rdata.data; + } else { + error_body = rdata.msg; + } + $("#error_log").html(error_body); + var ob = document.getElementById('error_log'); + ob.scrollTop = ob.scrollHeight; + }); + }); +} + + +function repCheckeds(tables) { + var dbs = [] + if (tables) { + dbs.push(tables) + } else { + var db_tools = $("input[value^='dbtools_']"); + for (var i = 0; i < db_tools.length; i++) { + if (db_tools[i].checked) dbs.push(db_tools[i].value.replace('dbtools_', '')); + } + } + + if (dbs.length < 1) { + layer.msg('请至少选择一张表!', { icon: 2 }); + return false; + } + return dbs; +} + +function repDatabase(db_name, tables) { + dbs = repCheckeds(tables); + + myPost('repair_table', { db_name: db_name, tables: JSON.stringify(dbs) }, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + repTools(db_name, true); + },'已送修复指令,请稍候...'); +} + + +function optDatabase(db_name, tables) { + dbs = repCheckeds(tables); + + myPost('opt_table', { db_name: db_name, tables: JSON.stringify(dbs) }, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + repTools(db_name, true); + },'已送优化指令,请稍候...'); +} + +function toDatabaseType(db_name, tables, type){ + dbs = repCheckeds(tables); + myPost('alter_table', { db_name: db_name, tables: JSON.stringify(dbs),table_type: type }, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + repTools(db_name, true); + }, '已送引擎转换指令,请稍候...'); +} + + +function selectedTools(my_obj, db_name) { + var is_checked = false + + if (my_obj) is_checked = my_obj.checked; + var db_tools = $("input[value^='dbtools_']"); + var n = 0; + for (var i = 0; i < db_tools.length; i++) { + if (my_obj) db_tools[i].checked = is_checked; + if (db_tools[i].checked) n++; + } + if (n > 0) { + var my_btns = '\ + \ + \ + ' + $("#db_tools").html(my_btns); + } else { + $("#db_tools").html(''); + } +} + +function repTools(db_name, res){ + myPost('get_db_info', {name:db_name}, function(data){ + var rdata = $.parseJSON(data.data); + var types = { InnoDB: "MyISAM", MyISAM: "InnoDB" }; + var tbody = ''; + for (var i = 0; i < rdata.tables.length; i++) { + if (!types[rdata.tables[i].type]) continue; + tbody += '\ + \ + ' + rdata.tables[i].table_name + '\ + ' + rdata.tables[i].type + '\ + ' + rdata.tables[i].collation + '\ + ' + rdata.tables[i].rows_count + '\ + ' + rdata.tables[i].data_size + '\ + \ + 修复 |\ + 优化 |\ + 转为' + types[rdata.tables[i].type] + '\ + \ + ' + } + + if (res) { + $(".gztr").html(tbody); + $("#db_tools").html(''); + $("input[type='checkbox']").attr("checked", false); + $(".tools_size").html('大小:' + rdata.data_size); + return; + } + + layer.open({ + type: 1, + title: "MySQL工具箱【" + db_name + "】", + area: ['780px', '580px'], + closeBtn: 2, + shadeClose: false, + content: '
\ +
\ + 数据库名称:'+ db_name + '\ + 大小:'+ rdata.data_size + '\ + \ +
\ +
\ +
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + ' + tbody + '\ +
表名引擎字符集行数大小操作
\ +
\ +
\ +
' + }); + tableFixed('database_fix'); + }); +} + + +function setDbMaster(name){ + myPost('set_db_master', {name:name}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){ + masterOrSlaveConf(); + }, 2000); + }); +} + + +function setDbSlave(name){ + myPost('set_db_slave', {name:name}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){ + masterOrSlaveConf(); + }, 2000); + }); +} + + +function addMasterRepSlaveUser(){ + layer.open({ + type: 1, + area: '500px', + title: '添加同步账户', + closeBtn: 1, + shift: 5, + shadeClose: true, + btn:["提交","取消"], + content: "
\ +
用户名
\ +
\ + 密码\ +
\ +
\ + \ +
", + success:function(){ + $("input[name='name']").keyup(function(){ + var v = $(this).val(); + $("input[name='db_user']").val(v); + $("input[name='ps']").val(v); + }); + + $('select[name="dataAccess"]').change(function(){ + var v = $(this).val(); + if (v == 'ip'){ + $(this).after(""); + } else { + $('#dataAccess_subid').remove(); + } + }); + }, + yes:function(index){ + var data = $("#add_master").serialize(); + data = decodeURIComponent(data); + var dataObj = str2Obj(data); + if(!dataObj['address']){ + dataObj['address'] = dataObj['dataAccess']; + } + + myPost('add_master_rep_slave_user', dataObj, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + layer.close(index); + if (rdata.status){ + getMasterRepSlaveList(); + } + },{icon: rdata.status ? 1 : 2},600); + }); + } + }); +} + + + +function updateMasterRepSlaveUser(username){ + + var index = layer.open({ + type: 1, + area: '500px', + title: '更新账户', + closeBtn: 1, + shift: 5, + shadeClose: true, + content: "
\ +
用户名
\ +
\ + 密码\ +
\ +
\ + \ +
\ + \ +
\ +
", + }); + + $('#submit_update_master').click(function(){ + var data = $("#update_master").serialize(); + data = decodeURIComponent(data); + var dataObj = str2Obj(data); + myPost('update_master_rep_slave_user', data, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + if (rdata.status){ + getMasterRepSlaveList(); + } + $('.layui-layer-close1').click(); + },{icon: rdata.status ? 1 : 2},600); + }); + }); +} + +function getMasterRepSlaveUserCmd(username, db=''){ + myPost('get_master_rep_slave_user_cmd', {username:username,db:db}, function(data){ + var rdata = $.parseJSON(data.data); + + if (!rdata['status']){ + layer.msg(rdata['msg']); + return; + } + + var cmd = rdata.data['cmd']; + + var loadOpen = layer.open({ + type: 1, + title: '同步命令', + area: '500px', + content:"
\ +
"+cmd+"
\ +
\ + \ +
\ +
", + }); + + + copyPass(cmd); + $('.class-copy-cmd').click(function(){ + copyPass(cmd); + }); + }); +} + +function delMasterRepSlaveUser(username){ + myPost('del_master_rep_slave_user', {username:username}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg); + + $('.layui-layer-close1').click(); + + setTimeout(function(){ + getMasterRepSlaveList(); + },1000); + }); +} + + +function setDbMasterAccess(username){ + myPost('get_db_access','username='+username, function(data){ + var rdata = $.parseJSON(data.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']}); + return; + } + + var index = layer.open({ + type: 1, + area: '500px', + title: '设置数据库权限', + closeBtn: 1, + shift: 5, + btn:["提交","取消"], + shadeClose: true, + content: "
\ +
\ + 访问权限\ +
\ + \ +
\ +
\ +
", + success:function(){ + if (rdata.msg == '127.0.0.1'){ + $('select[name="dataAccess"]').find("option[value='127.0.0.1']").attr("selected",true); + } else if (rdata.msg == '%'){ + $('select[name="dataAccess"]').find('option[value="%"]').attr("selected",true); + } else if ( rdata.msg == 'ip' ){ + $('select[name="dataAccess"]').find('option[value="ip"]').attr("selected",true); + $('select[name="dataAccess"]').after(""); + } else { + $('select[name="dataAccess"]').find('option[value="ip"]').attr("selected",true); + $('select[name="dataAccess"]').after(""); + } + + $('select[name="dataAccess"]').change(function(){ + var v = $(this).val(); + if (v == 'ip'){ + $(this).after(""); + } else { + $('#dataAccess_subid').remove(); + } + }); + }, + yes:function(index){ + var data = $("#set_db_access").serialize(); + data = decodeURIComponent(data); + var dataObj = str2Obj(data); + if(!dataObj['access']){ + dataObj['access'] = dataObj['dataAccess']; + if ( dataObj['dataAccess'] == 'ip'){ + if (dataObj['address']==''){ + layer.msg('IP地址不能空!',{icon:2,shade: [0.3, '#000']}); + return; + } + dataObj['access'] = dataObj['address']; + } + } + dataObj['username'] = username; + myPost('set_dbmaster_access', dataObj, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + layer.close(index); + },{icon: rdata.status ? 1 : 2}); + }); + } + }); + + }); +} + +function getMasterRepSlaveList(){ + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + myPost('get_master_rep_slave_list', _data, function(data){ + // console.log(data); + var rdata = []; + try { + rdata = $.parseJSON(data.data); + } catch(e){ + console.log(e); + } + var list = ''; + // console.log(rdata['data']); + var user_list = rdata['data']; + for (i in user_list) { + // console.log(i); + var name = user_list[i]['username']; + list += ''+name+'\ + '+user_list[i]['password']+'\ + \ + 修改 | \ + 删除 | \ + 权限 | \ + 从库同步命令\ + \ + '; + } + + $('#get_master_rep_slave_list_page tbody').html(list); + $('.dataTables_paginate_4').html(rdata['page']); + }); +} + +function getMasterRepSlaveListPage(){ + var page = '
'; + page += '
添加同步账户
'; + + var loadOpen = layer.open({ + type: 1, + title: '同步账户列表', + area: '500px', + content:"
\ +
\ +
\ + \ + \ +
用户名密码操作
\ + "+page +"\ +
\ +
", + success:function(){ + getMasterRepSlaveList(); + } + }); +} + + +function deleteSlave(){ + myPost('delete_slave', {}, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata['msg'], function(){ + masterOrSlaveConf(); + },{},3000); + }); +} + + +function getFullSyncStatus(db){ + var timeId = null; + + var btn = '
开始
'; + var loadOpen = layer.open({ + type: 1, + title: '全量同步['+db+']', + area: '500px', + content:"
\ +
\ + \ +
\ +
0%
\ +
\ +
\ + "+btn+"\ +
", + cancel: function(){ + clearInterval(timeId); + } + }); + + function fullSync(db,begin){ + + myPostN('full_sync', {db:db,begin:begin}, function(data){ + var rdata = $.parseJSON(data.data); + $('#full_msg').text(rdata['msg']); + $('.progress-bar').css('width',rdata['progress']+'%'); + $('.progress-bar').text(rdata['progress']+'%'); + + if (rdata['code']==6 ||rdata['code']<0){ + layer.msg(rdata['msg']); + clearInterval(timeId); + $("#begin_full_sync").attr('data-status','init'); + } + }); + } + + $('#begin_full_sync').click(function(){ + var val = $(this).attr('data-status'); + if (val == 'init'){ + fullSync(db,1); + timeId = setInterval(function(){ + fullSync(db,0); + }, 1000); + $(this).attr('data-status','starting'); + } else { + layer.msg("正在同步中.."); + } + }); +} + +function addSlaveSSH(ip=''){ + + myPost('get_slave_ssh_by_ip', {ip:ip}, function(rdata){ + + var rdata = $.parseJSON(rdata.data); + + var ip = '127.0.0.1'; + var port = "22"; + var id_rsa = ''; + var db_user =''; + + if (rdata.data.length>0){ + ip = rdata.data[0]['ip']; + port = rdata.data[0]['port']; + id_rsa = rdata.data[0]['id_rsa']; + db_user = rdata.data[0]['db_user']; + } + + var index = layer.open({ + type: 1, + area: ['500px','480px'], + title: '添加SSH', + closeBtn: 1, + shift: 5, + shadeClose: true, + btn:["确认","取消"], + content: "
\ +
IP
\ +
端口
\ +
同步账户[DB]
\ +
\ + ID_RSA\ +
\ +
\ + \ +
", + success:function(){ + $('textarea[name="id_rsa"]').html(id_rsa); + }, + yes:function(index){ + var ip = $('input[name="ip"]').val(); + var port = $('input[name="port"]').val(); + var db_user = $('input[name="db_user"]').val(); + var id_rsa = $('textarea[name="id_rsa"]').val(); + + var data = {ip:ip,port:port,id_rsa:id_rsa,db_user:db_user}; + myPost('add_slave_ssh', data, function(data){ + layer.close(index); + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + if (rdata.status){ + getSlaveSSHPage(); + } + },{icon: rdata.status ? 1 : 2},600); + }); + } + }); + }); +} + + +function delSlaveSSH(ip){ + myPost('del_slave_ssh', {ip:ip}, function(rdata){ + var rdata = $.parseJSON(rdata.data); + layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2}); + getSlaveSSHPage(); + }); +} + +function getSlaveSSHPage(page=1){ + var _data = {}; + _data['page'] = page; + _data['page_size'] = 5; + _data['tojs'] ='getSlaveSSHPage'; + myPost('get_slave_ssh_list', _data, function(data){ + var layerId = null; + var rdata = []; + try { + rdata = $.parseJSON(data.data); + } catch(e) { + console.log(e); + } + var list = ''; + var ssh_list = rdata['data']; + for (i in ssh_list) { + var ip = ssh_list[i]['ip']; + var port = ssh_list[i]['port']; + + var id_rsa = '未设置'; + if ( ssh_list[i]['port'] != ''){ + id_rsa = '已设置'; + } + + var db_user = '未设置'; + if ( ssh_list[i]['db_user'] != ''){ + db_user = ssh_list[i]['db_user']; + } + + list += ''+ip+'\ + '+port+'\ + '+db_user+'\ + '+id_rsa+'\ + \ + 修改 | \ + 删除\ + \ + '; + } + + $('.get-slave-ssh-list tbody').html(list); + $('.dataTables_paginate_4').html(rdata['page']); + }); +} + + +function getSlaveSSHList(page=1){ + + var page = '
'; + page += '
添加SSH
'; + + layerId = layer.open({ + type: 1, + title: 'SSH列表', + area: '500px', + content:"
\ +
\ +
\ + \ + \ +
IPPORT同步账户SSH操作
\ + "+page +"\ +
\ +
", + success:function(){ + getSlaveSSHPage(1); + } + }); +} + +function handlerRun(){ + myPostN('get_slave_sync_cmd', {}, function(data){ + var rdata = $.parseJSON(data.data); + var cmd = rdata['data']; + var loadOpen = layer.open({ + type: 1, + title: '手动执行', + area: '500px', + content:"
\ +
"+cmd+"
\ +
\ + \ +
\ +
", + }); + copyPass(cmd); + $('.class-copy-cmd').click(function(){ + copyPass(cmd); + }); + }); +} + +function initSlaveStatus(){ + myPost('init_slave_status', '', function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + if (rdata.status){ + masterOrSlaveConf(); + } + },{icon:rdata.status?1:2},2000); + }); +} + +function masterOrSlaveConf(version=''){ + + function getMasterDbList(){ + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + + myPost('get_masterdb_list', _data, function(data){ + var rdata = $.parseJSON(data.data); + var list = ''; + for(i in rdata.data){ + list += ''; + list += '' + rdata.data[i]['name'] +''; + list += '' + (rdata.data[i]['master']?'是':'否') +''; + list += '' + + ''+(rdata.data[i]['master']?'退出':'加入')+' | ' + + '同步命令' + + ''; + list += ''; + } + + var con = '
\ +
\ + \ + \ + \ + \ + \ + \ + '+ list +'\ +
数据库名同步操作
\ +
\ +
\ +
\ + 同步账户列表\ +
\ +
'; + + $(".table_master_list").html(con); + $('#databasePage').html(rdata.page); + }); + } + + function getAsyncMasterDbList(){ + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + + myPost('get_slave_list', _data, function(data){ + var rdata = $.parseJSON(data.data); + var list = ''; + for(i in rdata.data){ + + var v = rdata.data[i]; + var status = "异常"; + if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){ + status = "正常"; + } + + list += ''; + list += '' + rdata.data[i]['Master_Host'] +''; + list += '' + rdata.data[i]['Master_Port'] +''; + list += '' + rdata.data[i]['Master_User'] +''; + list += '' + rdata.data[i]['Master_Log_File'] +''; + list += '' + rdata.data[i]['Slave_IO_Running'] +''; + list += '' + rdata.data[i]['Slave_SQL_Running'] +''; + list += '' + status +''; + list += '' + + '删除' + + ''; + list += ''; + } + + var con = '
\ +
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + '+ list +'\ +
主[服务]端口用户日志IOSQL状态操作
\ +
\ +
'; + + //
\ + //
\ + // 添加\ + //
+ $(".table_slave_status_list").html(con); + }); + } + + function getAsyncDataList(){ + var _data = {}; + if (typeof(page) =='undefined'){ + var page = 1; + } + + _data['page'] = page; + _data['page_size'] = 10; + myPost('get_masterdb_list', _data, function(data){ + var rdata = $.parseJSON(data.data); + var list = ''; + for(i in rdata.data){ + list += ''; + list += '' + rdata.data[i]['name'] +''; + list += '' + + ''+(rdata.data[i]['slave']?'退出':'加入')+' | ' + + '同步' + + ''; + list += ''; + } + + var con = '
\ +
\ + \ + \ + \ + \ + \ + '+ list +'\ +
本地库名操作
\ +
\ +
\ +
\ + 手动命令\ + 全量同步\ +
\ +
'; + + $(".table_slave_list").html(con); + $('#databasePage').html(rdata.page); + }); + } + + + + function getMasterStatus(){ + myPost('get_master_status', '', function(data){ + var rdata = $.parseJSON(data.data); + // console.log('mode:',rdata.data); + var rdata = rdata.data; + var limitCon = '\ +

\ + 主从同步模式\ + \ + \ +

\ +
\ +

\ + Master[主]配置\ + \ +

\ +
\ + \ +
\ +
\ + \ +

\ + Slave[从]配置\ + \ + \ + \ +

\ +
\ + \ +
\ + \ +
\ + '; + $(".soft-man-con").html(limitCon); + + //设置主服务器配置 + $(".btn-master").click(function () { + myPost('set_master_status', 'close=change', function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){ + getMasterStatus(); + }, 3000); + }); + }); + + $(".btn-slave").click(function () { + myPost('set_slave_status', 'close=change', function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 }); + setTimeout(function(){ + getMasterStatus(); + }, 3000); + }); + }); + + $('.db-mode').click(function(){ + if ($(this).hasClass('btn-success')){ + //no action + return; + } + + var mode = 'classic'; + if ($(this).hasClass('btn-gtid')){ + mode = 'gtid'; + } + + layer.open({ + type:1, + title:"MySQL主从模式切换", + shadeClose:false, + btnAlign: 'c', + btn: ['切换并重启', '切换不重启'], + yes: function(index, layero){ + this.change(index,mode,"yes"); + + }, + btn2: function(index, layero){ + this.change(index,mode,"no"); + return false; + }, + change:function(index,mode,reload){ + console.log(index,mode,reload); + myPost('set_dbrun_mode',{'mode':mode,'reload':reload},function(data){ + layer.close(index); + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg ,function(){ + getMasterStatus(); + },{ icon: rdata.status ? 1 : 5 }); + }); + } + }); + }); + + if (rdata.status){ + getMasterDbList(); + } + + if (rdata.slave_status){ + getAsyncMasterDbList(); + getAsyncDataList() + } + }); + } + getMasterStatus(); +} diff --git a/scripts/init.d/mw.tpl b/scripts/init.d/mw.tpl index 1dfbc7984..7d660dc77 100755 --- a/scripts/init.d/mw.tpl +++ b/scripts/init.d/mw.tpl @@ -3,7 +3,7 @@ # description: MW Cloud Service ### BEGIN INIT INFO -# Provides: bt +# Provides: Midoks # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5