mariadb加入修复功能和外部导入功能

pull/244/head
midoks 3 years ago
parent 176112b332
commit ea20cc6e89
  1. 132
      plugins/mariadb/index.py
  2. 238
      plugins/mariadb/js/mariadb.js
  3. 8
      plugins/mariadb/scripts/backup.py
  4. 102
      plugins/mysql/js/mysql.js

@ -628,7 +628,7 @@ def isSqlError(mysqlMsg):
if "2003," in mysqlMsg:
return mw.returnJson(False, "Can't connect to MySQL server on '127.0.0.1' (61)")
if "using password:" in mysqlMsg:
return mw.returnJson(False, '数据库管理密码错误!')
return mw.returnJson(False, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
@ -712,15 +712,82 @@ def importDbBackup():
return mw.returnJson(True, 'ok')
def importDbExternal():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
import_dir = mw.getRootDir() + '/backup/import/'
file_path = import_dir + file
if not os.path.exists(file_path):
return mw.returnJson(False, '文件突然消失?')
exts = ['sql', 'gz', 'zip']
tmp = file.split('.')
ext = tmp[len(tmp) - 1]
if ext not in exts:
return mw.returnJson(False, '导入数据库格式不对!')
tmp = file.split('/')
tmpFile = tmp[len(tmp) - 1]
tmpFile = tmpFile.replace('.sql.' + ext, '.sql')
tmpFile = tmpFile.replace('.' + ext, '.sql')
tmpFile = tmpFile.replace('tar.', '')
# print(tmpFile)
import_sql = ""
if file.find("sql.gz") > -1:
cmd = 'cd ' + import_dir + ' && gzip -dc ' + \
file + " > " + import_dir + tmpFile
info = mw.execShell(cmd)
if info[1] == "":
import_sql = import_dir + tmpFile
if file.find(".zip") > -1:
cmd = 'cd ' + import_dir + ' && unzip -o ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if file.find("tar.gz") > -1:
cmd = 'cd ' + import_dir + ' && tar -zxvf ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if import_sql == "":
return mw.returnJson(False, '未找SQL文件')
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql
# print(mysql_cmd)
os.system(mysql_cmd)
os.remove(import_sql)
return mw.returnJson(True, 'ok')
def deleteDbBackup():
args = getArgs()
data = checkArgs(args, ['filename'])
data = checkArgs(args, ['filename', 'path'])
if not data[0]:
return data[1]
path = args['path']
full_file = ""
bkDir = mw.getRootDir() + '/backup/database'
os.remove(bkDir + '/' + args['filename'])
full_file = bkDir + '/' + args['filename']
if path != "":
full_file = path + "/" + args['filename']
os.remove(full_file)
return mw.returnJson(True, 'ok')
@ -752,6 +819,39 @@ def getDbBackupList():
return mw.returnJson(True, 'ok', rr)
def getDbBackupImportList():
bkImportDir = mw.getRootDir() + '/backup/import'
if not os.path.exists(bkImportDir):
os.mkdir(bkImportDir)
blist = os.listdir(bkImportDir)
rr = []
for x in range(0, len(blist)):
name = blist[x]
p = bkImportDir + '/' + name
data = {}
data['name'] = name
rsize = os.path.getsize(p)
data['size'] = mw.toSize(rsize)
t = os.path.getctime(p)
t = time.localtime(t)
data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', t)
rr.append(data)
data['file'] = p
rdata = {
"list": rr,
"upload_dir": bkImportDir,
}
return mw.returnJson(True, 'ok', rdata)
def getDbList():
args = getArgs()
page = 1
@ -1122,6 +1222,22 @@ def setDbAccess():
return mw.returnJson(True, '设置成功!')
def fixDbAccess(version):
try:
pdb = pMysqlDb()
psdb = pSqliteDb('databases')
data = pdb.query('show databases')
isError = isSqlError(data)
if isError != None:
appCMD(version, 'stop')
mw.execShell("rm -rf " + getServerDir() + "/data")
appCMD(version, 'start')
return mw.returnJson(True, '修复成功!')
return mw.returnJson(True, '正常无需修复!')
except Exception as e:
return mw.returnJson(False, '修复失败请重试!')
def setDbRw(version=''):
args = getArgs()
data = checkArgs(args, ['username', 'id', 'rw'])
@ -2200,7 +2316,7 @@ def uninstallPreInspection(version):
if __name__ == "__main__":
func = sys.argv[1]
version = "5.6"
version = "10.6"
version_pl = getServerDir() + "/version.pl"
if os.path.exists(version_pl):
version = mw.readFile(version_pl).strip()
@ -2257,10 +2373,14 @@ if __name__ == "__main__":
print(setDbBackup())
elif func == 'import_db_backup':
print(importDbBackup())
elif func == 'import_db_external':
print(importDbExternal())
elif func == 'delete_db_backup':
print(deleteDbBackup())
elif func == 'get_db_backup_list':
print(getDbBackupList())
elif func == 'get_db_backup_import_list':
print(getDbBackupImportList())
elif func == 'add_db':
print(addDb())
elif func == 'del_db':
@ -2277,6 +2397,8 @@ if __name__ == "__main__":
print(getDbAccess())
elif func == 'set_db_access':
print(setDbAccess())
elif func == 'fix_db_access':
print(fixDbAccess(version))
elif func == 'get_db_rw':
print(setDbRw(version))
elif func == 'set_db_ps':

@ -601,6 +601,15 @@ function setDbAccess(username){
});
}
function fixDbAccess(username){
myPost('fix_db_access', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
dbList();
},{icon: rdata.status ? 1 : 2});
});
}
function setDbPass(id, username, password){
var index = layer.open({
@ -661,7 +670,6 @@ function addDatabase(type){
}
var index = layer.open({
type: 1,
skin: 'demo-class',
area: '500px',
title: '添加数据库',
closeBtn: 1,
@ -850,12 +858,14 @@ function openPhpmyadmin(name,username,password){
}
}
function delBackup(filename,name){
myPost('delete_db_backup',{filename:filename},function(){
function delBackup(filename, name, path){
if(typeof(path) == "undefined"){
path = "";
}
myPost('delete_db_backup',{filename:filename,path:path},function(){
layer.msg('执行成功!');
setTimeout(function(){
$('.layui-layer-close2').click();
setBackup(name);
setBackupReq(name);
},2000);
});
}
@ -871,9 +881,180 @@ function importBackup(file,name){
});
}
function setBackup(db_name,obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
function importDbExternal(file,name){
myPost('import_db_external',{file:file,name:name}, function(data){
layer.msg('执行成功!');
});
}
function setLocalImport(db_name){
//上传文件
function uploadDbFiles(upload_dir){
var up_db = layer.open({
type:1,
closeBtn: 1,
title:"上传导入文件["+upload_dir+']',
area: ['500px','300px'],
shadeClose:false,
content:'<div class="fileUploadDiv">\
<input type="hidden" id="input-val" value="'+upload_dir+'" />\
<input type="file" id="file_input" multiple="true" autocomplete="off" />\
<button type="button" id="opt" autocomplete="off">添加文件</button>\
<button type="button" id="up" autocomplete="off" >开始上传</button>\
<span id="totalProgress" style="position: absolute;top: 7px;right: 147px;"></span>\
<span style="float:right;margin-top: 9px;">\
<font>文件编码:</font>\
<select id="fileCodeing" >\
<option value="byte">二进制</option>\
<option value="utf-8">UTF-8</option>\
<option value="gb18030">GB2312</option>\
</select>\
</span>\
<button type="button" id="filesClose" autocomplete="off">关闭</button>\
<ul id="up_box"></ul>\
</div>',
success:function(){
$('#filesClose').click(function(){
layer.close(up_db);
});
}
});
uploadStart(function(){
getList();
layer.close(up_db);
});
}
function getList(){
myPost('get_db_backup_import_list',{}, function(data){
var rdata = $.parseJSON(data.data);
var file_list = rdata.data.list;
var upload_dir = rdata.data.upload_dir;
var tbody = '';
for (var i = 0; i < file_list.length; i++) {
tbody += '<tr>\
<td><span> ' + file_list[i]['name'] + '</span></td>\
<td><span> ' + file_list[i]['size'] + '</span></td>\
<td><span> ' + file_list[i]['time'] + '</span></td>\
<td style="text-align: right;">\
<a class="btlink" onclick="importDbExternal(\'' + file_list[i]['name'] + '\',\'' +db_name+ '\')">导入</a> | \
<a class="btlink del" index="'+i+'">删除</a>\
</td>\
</tr>';
}
$('#import_db_file_list').html(tbody);
$('input[name="upload_dir"]').val(upload_dir);
$("#import_db_file_list .del").on('click',function(){
var index = $(this).attr('index');
var filename = file_list[index]["name"];
myPost('delete_db_backup',{filename:filename,path:upload_dir},function(){
showMsg('执行成功!', function(){
getList();
},{icon:1},2000);
});
});
});
}
var layerIndex = layer.open({
type: 1,
title: "从文件导入数据",
area: ['600px', '380px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_file_upload" class="btn btn-success btn-sm" type="button">从本地上传</button>\
</div >\
<div class="divtable">\
<input type="hidden" name="upload_dir" value=""> \
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody id="import_db_file_list" class="gztr"></tbody>\
</table>\
</div>\
<ul class="help-info-text c7">\
<li>仅支持sqlzipsql.gz(tar.gz|gz|tgz)</li>\
<li>ziptar.gz压缩包结构test.zip或test.tar.gz压缩包内必需包含test.sql</li>\
<li>若文件过大您还可以使用SFTP工具将数据库文件上传到/www/backup/import</li>\
</ul>\
</div>\
</div>',
success:function(index){
$('#btn_file_upload').click(function(){
var upload_dir = $('input[name="upload_dir"]').val();
uploadDbFiles(upload_dir);
});
getList();
},
});
}
function setBackup(db_name){
var layerIndex = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
<button id="btn_local_import" class="btn btn-success btn-sm" type="button">外部导入</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table id="database_table" class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="list"></tbody>\
</table>\
</div>\
</div>\
</div>',
success:function(index){
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
showMsg('执行成功!', function(){
setBackupReq(db_name);
}, {icon:1}, 2000);
});
});
$('#btn_local_import').click(function(){
setLocalImport(db_name);
});
setBackupReq(db_name);
},
});
}
function setBackupReq(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++) {
@ -888,45 +1069,7 @@ function setBackup(db_name,obj){
</td>\
</tr> ';
}
var s = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 2,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
</table>\
</div>\
</div>\
</div>'
});
$('#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);
});
});
$('#database_table tbody').html(tbody);
});
}
@ -960,7 +1103,7 @@ function dbList(page, search){
list += '<td><span class="c9 input-edit" onclick="setDbPs(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['name']+'\',this)" style="display: inline-block;">'+rdata.data[i]['ps']+'</span></td>';
list += '<td style="text-align:right">';
list += '<a href="javascript:;" class="btlink" class="btlink" onclick="setBackup(\''+rdata.data[i]['name']+'\',this)" title="数据库备份">'+(rdata.data[i]['is_backup']?'备份':'未备份') +'</a> | ';
list += '<a href="javascript:;" class="btlink" class="btlink" onclick="setBackup(\''+rdata.data[i]['name']+'\')" title="数据库备份">'+(rdata.data[i]['is_backup']?'备份':'未备份') +'</a> | ';
var rw = '';
var rw_change = 'all';
@ -996,6 +1139,7 @@ function dbList(page, search){
<button onclick="setRootPwd(0,\''+rdata.info['root_pwd']+'\')" title="设置MySQL管理员密码" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">root密码</button>\
<button onclick="openPhpmyadmin(\'\',\'root\',\''+rdata.info['root_pwd']+'\')" title="打开phpMyadmin" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">phpMyAdmin</button>\
<button onclick="setDbAccess(\'root\')" title="ROOT权限" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">ROOT权限</button>\
<button onclick="fixDbAccess(\'root\')" title="修复" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">修复</button>\
<span style="float:right"> \
<button batch="true" style="float: right;display: none;margin-left:10px;" onclick="delDbBatch();" title="删除选中项" class="btn btn-default btn-sm">删除选中</button>\
</span>\

@ -26,6 +26,7 @@ class backupTools:
def backupDatabase(self, name, count):
db_path = mw.getServerDir() + '/mariadb'
db_sock = mw.getServerDir() + '/mariadb/'
db_name = 'mysql'
name = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('name')
@ -63,8 +64,11 @@ class backupTools:
# 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)
cmd = db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " + \
name + " | gzip > " + filename
# print(cmd)
mw.execShell(cmd)
if not os.path.exists(filename):
endDate = time.strftime('%Y/%m/%d %X', time.localtime())

@ -879,15 +879,14 @@ function openPhpmyadmin(name,username,password){
}
}
function delBackup(filename,name,path){
function delBackup(filename, name, path){
if(typeof(path) == "undefined"){
path = "";
}
myPost('delete_db_backup',{filename:filename,path:path},function(){
layer.msg('执行成功!');
setTimeout(function(){
$('.layui-layer-close2').click();
setBackup(name);
setBackupReq(name);
},2000);
});
}
@ -946,6 +945,7 @@ function setLocalImport(db_name){
});
uploadStart(function(){
getList();
layer.close(up_db);
});
}
@ -1029,9 +1029,55 @@ function setLocalImport(db_name){
}
function setBackup(db_name,obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
function setBackup(db_name){
var layerIndex = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
<button id="btn_local_import" class="btn btn-success btn-sm" type="button">外部导入</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table id="database_table" class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="list"></tbody>\
</table>\
</div>\
</div>\
</div>',
success:function(index){
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
showMsg('执行成功!', function(){
setBackupReq(db_name);
}, {icon:1}, 2000);
});
});
$('#btn_local_import').click(function(){
setLocalImport(db_name);
});
setBackupReq(db_name);
},
});
}
function setBackupReq(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++) {
@ -1041,57 +1087,15 @@ function setBackup(db_name,obj){
<td><span> ' + rdata.data[i]['time'] + '</span></td>\
<td style="text-align: right;">\
<a class="btlink" onclick="importBackup(\'' + rdata.data[i]['name'] + '\',\'' +db_name+ '\')">导入</a> | \
<a class="btlink" onclick="downloadBackup(\'' + rdata.data[i]['file'] + '\')">下载</a> | \
<a class="btlink" onclick="delBackup(\'' + rdata.data[i]['name'] + '\',\'' +db_name+ '\')">删除</a>\
</td>\
</tr> ';
}
var layerIndex = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
<button id="btn_local_import" class="btn btn-success btn-sm" type="button">外部导入</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
</table>\
</div>\
</div>\
</div>',
success:function(index){
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
showMsg('执行成功!', function(){
layer.close(layerIndex);
setBackup(db_name,obj);
}, {icon:1}, 2000);
});
});
$('#btn_local_import').click(function(){
setLocalImport(db_name);
});
},
});
$('#database_table tbody').html(tbody);
});
}
function dbList(page, search){
var _data = {};
if (typeof(page) =='undefined'){

Loading…
Cancel
Save