pull/156/head
midoks 3 years ago
parent 8daa136bc8
commit afd255c767
  1. 188
      plugins/postgresql/index.py
  2. 251
      plugins/postgresql/js/postgresql.js

@ -626,7 +626,7 @@ def sedConf(name, val):
def pgSetDbStatus():
'''
'''
保存pgsql性能调整信息
'''
args = getArgs()
@ -643,22 +643,27 @@ def pgSetDbStatus():
return mw.returnJson(True, '设置成功!')
def __createUser(dbname, username, password, address):
pdb = pMysqlDb()
def setUserPwd(version=''):
args = getArgs()
data = checkArgs(args, ['password', 'name'])
if not data[0]:
return data[1]
if username == 'root':
dbname = '*'
newpwd = args['password']
username = args['name']
uid = args['id']
try:
pdb = pgDb()
psdb = pSqliteDb('databases')
name = psdb.where('id=?', (uid,)).getField('name')
pdb.execute(
"CREATE USER `%s`@`localhost` IDENTIFIED BY '%s'" % (username, password))
pdb.execute(
"grant all privileges on %s.* to `%s`@`localhost`" % (dbname, username))
for a in address.split(','):
pdb.execute(
"CREATE USER `%s`@`%s` IDENTIFIED BY '%s'" % (username, a, password))
pdb.execute(
"grant all privileges on %s.* to `%s`@`%s`" % (dbname, username, a))
pdb.execute("flush privileges")
r = pdb.execute(
"alter user {} with password '{}'".format(username, newpwd))
psdb.where("id=?", (uid,)).setField('password', newpwd)
return mw.returnJson(True, mw.getInfo('修改数据库[{1}]密码成功!', (name,)))
except Exception as ex:
return mw.returnJson(False, mw.getInfo('修改数据库[{1}]密码失败[{2}]!', (name, str(ex),)))
def getDbBackupListFunc(dbname=''):
@ -859,12 +864,12 @@ def addDb():
if not re.match(r"(?:[0-9]{1,3}\.){3}[0-9]{1,3}/\d+", listen_ip):
return mw.returnJson(False, "你输入的权限不合法,添加失败!")
# # 修改监听所有地址
# if listen_ip not in ["127.0.0.1/32", "localhost", "127.0.0.1"]:
# sedConf("listen_addresses", "'*'")
# 修改监听所有地址
if listen_ip not in ["127.0.0.1/32", "localhost", "127.0.0.1"]:
sedConf("listen_addresses", "'*'")
reg = "^[\w\.-]+$"
if not re.match(reg, args['name']):
if not re.match(reg, dbname):
return mw.returnJson(False, '数据库名称不能带有特殊符号!')
checks = ['root', 'mysql', 'test', 'sys', 'postgres', 'postgresql']
@ -896,7 +901,7 @@ def addDb():
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
psdb.add('pid,name,username,password,accept,ps,addtime',
(0, dbname, dbuser, password, address, dbname, addTime))
(0, dbname, dbuser, password, listen_ip, dbname, addTime))
restart()
return mw.returnJson(True, '添加成功!')
@ -927,6 +932,135 @@ def delDb():
return mw.returnJson(True, '删除成功!')
def getDbAccess():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
psdb = pSqliteDb('databases')
accept = psdb.where("name=?", (name,)).getField('accept')
return mw.returnJson(True, accept)
def setDbAccess():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
return mw.returnJson(True, "设置成功")
def pgBack():
# 备份数据库
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
bk_path = mw.getBackupDir() + "/pg"
if not os.path.isdir(bk_path):
mw.execShell("mkdir -p {}/upload".format(bk_path))
bk_path_upload = bk_path + "/upload"
database = args['name']
port = getPgPort()
cmd = '''su - postgres -c "/www/server/pgsql/bin/pg_dump -c {} -p {} "| gzip > {}/{}_{}.gz '''.format(
database, port, bk_path_upload, database, time.strftime("%Y%m%d_%H%M%S"))
if mw.isAppleSystem():
cmd = '''{}/bin/pg_dump -c {} -p {} | gzip > {}/{}_{}.gz '''.format(
getServerDir(), database, port, bk_path_upload, database, time.strftime("%Y%m%d_%H%M%S"))
mw.execShell(cmd)
return mw.returnJson(True, '备份成功!')
def pgBackList():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
database = args['name']
bk_path = mw.getBackupDir() + "/pg"
if not os.path.isdir(bk_path):
mw.execShell("mkdir -p {}/upload".format(bk_path))
bk_path_upload = bk_path + "/upload"
file_list = os.listdir(bk_path_upload)
data = []
for i in file_list:
if i.split("_")[0].startswith(database):
file_path = os.path.join(bk_path_upload, i)
file_info = os.stat(file_path)
create_time = file_info.st_ctime
time_local = time.localtime(int(create_time))
create_time = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
file_size = file_info.st_size
file_size = mw.toSize(file_size)
data.append({"name": i, "time": create_time,
"size": file_size, "file": file_path})
return mw.returnJson(True, 'ok', data)
def importDbBackup():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
bk_path = mw.getBackupDir() + "/pg"
if not os.path.isdir(bk_path):
mw.execShell("mkdir -p {}/upload".format(bk_path))
bk_path_upload = bk_path + "/upload"
file_path = os.path.join(bk_path_upload, name)
if not os.path.exists(file_path):
return mw.returnJson(False, '备份文件不存在')
port = getPgPort()
cmd = '''gunzip -c {}|su - postgres -c " /www/server/pgsql/bin/psql -d {} -p {} " '''.format(
file, name, port)
if mw.isAppleSystem():
cmd = '''gunzip -c {} | {}/bin/psql -d {} -p {}'''.format(
name, getServerDir(), port)
# print(cmd)
mw.execShell(cmd)
return mw.returnJson(True, '恢复数据库成功')
def deleteDbBackup():
args = getArgs()
data = checkArgs(args, ['filename'])
if not data[0]:
return data[1]
bk_path = mw.getBackupDir() + "/pg"
if not os.path.isdir(bk_path):
mw.execShell("mkdir -p {}/upload".format(bk_path))
bk_path_upload = bk_path + "/upload"
os.remove(bk_path_upload + '/' + args['filename'])
return mw.returnJson(True, 'ok')
def installPreInspection(version):
return 'ok'
@ -980,6 +1114,8 @@ if __name__ == "__main__":
print(pgDbStatus())
elif func == 'set_db_status':
print(pgSetDbStatus())
elif func == 'set_user_pwd':
print(setUserPwd())
elif func == 'pg_port':
print(getPgPort())
elif func == 'set_pg_port':
@ -990,6 +1126,18 @@ if __name__ == "__main__":
print(addDb())
elif func == 'del_db':
print(delDb())
elif func == 'get_db_access':
print(getDbAccess())
elif func == 'set_db_access':
print(setDbAccess())
elif func == 'pg_back':
print(pgBack())
elif func == 'pg_back_list':
print(pgBackList())
elif func == 'import_db_backup':
print(importDbBackup())
elif func == 'delete_db_backup':
print(deleteDbBackup())
elif func == 'sync_get_databases':
print(syncGetDatabases())
else:

@ -127,30 +127,6 @@ function pgPort(){
}
//数据库存储信置
function changePgDataPath(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 = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function pgPerfOpt() {
//获取MySQL配置
@ -313,8 +289,8 @@ function setDbRw(id,username,val){
});
}
function setDbAccess(username){
myPost('get_db_access','username='+username, function(data){
function setDbAccess(name){
myPost('get_db_access','name='+name, function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
@ -334,30 +310,27 @@ function setDbAccess(username){
<span class='tname'>访问权限</span>\
<div class='info-r '>\
<select class='bt-input-text mr5' name='dataAccess' style='width:100px'>\
<option value='127.0.0.1'>本地服务器</option>\
<option value='127.0.0.1/32'>本地服务器</option>\
<option value=\"%\">所有人</option>\
<option value='ip'>指定IP</option>\
<option value='ip'>指定网段</option>\
</select>\
</div>\
</div>\
</form>",
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 == '%'){
if (rdata.msg == '127.0.0.1/32'){
$('select[name="dataAccess"]').find("option[value='127.0.0.1/32']").attr("selected",true);
} else if (rdata.msg == '0.0.0.0/0'){
$('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("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
} else {
$('select[name="dataAccess"]').find('option[value="ip"]').attr("selected",true);
$('select[name="dataAccess"]').after("<input value='"+rdata.msg+"' id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
$('select[name="dataAccess"]').after("<input value='"+rdata.msg+"' id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='如: 192.168.1.0/24' style='width: 230px; display: inline-block;'>");
}
$('select[name="dataAccess"]').change(function(){
$('select[name="dataAccess"]').change(function(){
var v = $(this).val();
if (v == 'ip'){
$(this).after("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
$(this).after("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='如: 192.168.1.0/24' style='width: 230px; display: inline-block;'>");
} else {
$('#dataAccess_subid').remove();
}
@ -377,7 +350,7 @@ function setDbAccess(username){
dataObj['access'] = dataObj['address'];
}
}
dataObj['username'] = username;
dataObj['name'] = name;
myPost('set_db_access', dataObj, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
@ -571,60 +544,6 @@ function setDbPs(id, name, obj) {
});
}
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('执行成功!');
@ -647,9 +566,10 @@ function importBackup(file,name){
}
function setBackup(db_name,obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
myPost('pg_back_list', {name:db_name}, function(data){
var rdata = $.parseJSON(data.data);
console.log(rdata);
var tbody = '';
for (var i = 0; i < rdata.data.length; i++) {
tbody += '<tr>\
@ -693,7 +613,7 @@ function setBackup(db_name,obj){
});
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
myPost('pg_back',{name:db_name}, function(data){
layer.msg('执行成功!');
setTimeout(function(){
@ -755,7 +675,7 @@ function dbList(page, search){
}
list += '<a href="javascript:;" class="btlink" onclick="setDbAccess(\''+rdata.data[i]['username']+'\')" title="设置数据库权限">权限</a> | ' +
list += '<a href="javascript:;" class="btlink" onclick="setDbAccess(\''+rdata.data[i]['name']+'\')" title="设置数据库权限">权限</a> | ' +
rw +
'<a href="javascript:;" class="btlink" onclick="setDbPass('+rdata.data[i]['id']+',\''+ rdata.data[i]['username'] +'\',\'' + rdata.data[i]['password'] + '\')">改密</a> | ' +
'<a href="javascript:;" class="btlink" onclick="delDb(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['name']+'\')" title="删除数据库">删除</a>' +
@ -809,146 +729,7 @@ function dbList(page, search){
readerTableChecked();
});
}
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 = '<button class="btn btn-default btn-sm" onclick="repDatabase(\'' + db_name + '\',null)">修复</button>\
<button class="btn btn-default btn-sm" onclick="optDatabase(\'' + db_name + '\',null)">优化</button>\
<button class="btn btn-default btn-sm" onclick="toDatabaseType(\'' + db_name + '\',null,\'InnoDB\')">转为InnoDB</button></button>\
<button class="btn btn-default btn-sm" onclick="toDatabaseType(\'' + db_name + '\',null,\'MyISAM\')">转为MyISAM</button>'
$("#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 += '<tr>\
<td><input value="dbtools_' + rdata.tables[i].table_name + '" class="check" onclick="selectedTools(null,\'' + db_name + '\');" type="checkbox"></td>\
<td><span style="width:220px;"> ' + rdata.tables[i].table_name + '</span></td>\
<td>' + rdata.tables[i].type + '</td>\
<td><span style="width:90px;"> ' + rdata.tables[i].collation + '</span></td>\
<td>' + rdata.tables[i].rows_count + '</td>\
<td>' + rdata.tables[i].data_size + '</td>\
<td style="text-align: right;">\
<a class="btlink" onclick="repDatabase(\''+ db_name + '\',\'' + rdata.tables[i].table_name + '\')">修复</a> |\
<a class="btlink" onclick="optDatabase(\''+ db_name + '\',\'' + rdata.tables[i].table_name + '\')">优化</a> |\
<a class="btlink" onclick="toDatabaseType(\''+ db_name + '\',\'' + rdata.tables[i].table_name + '\',\'' + types[rdata.tables[i].type] + '\')">转为' + types[rdata.tables[i].type] + '</a>\
</td>\
</tr> '
}
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: '<div class="pd15">\
<div class="db_list">\
<span><a>数据库名称'+ db_name + '</a>\
<a class="tools_size">大小'+ rdata.data_size + '</a></span>\
<span id="db_tools" style="float: right;"></span>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:360px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th><input class="check" onclick="selectedTools(this,\''+ db_name + '\');" type="checkbox"></th>\
<th>表名</th>\
<th>引擎</th>\
<th>字符集</th>\
<th>行数</th>\
<th>大小</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
</table>\
</div>\
</div>\
<ul class="help-info-text c7">\
<li>修复尝试使用REPAIR命令修复损坏的表仅能做简单修复若修复不成功请考虑使用myisamchk工具</li>\
<li>优化执行OPTIMIZE命令可回收未释放的磁盘空间建议每月执行一次</li>\
<li>转为InnoDB/MyISAM转换数据表引擎建议将所有表转为InnoDB</li>\
</ul></div>'
});
tableFixed('database_fix');
});
}
///////////////////////////////// 主从 /////////////////////////
function setDbMaster(name){

Loading…
Cancel
Save