From 8daa136bc81d11695c63b6d3e09f3a253c5c957e Mon Sep 17 00:00:00 2001 From: midoks Date: Tue, 9 Aug 2022 23:05:48 +0800 Subject: [PATCH] pgxx6 --- plugins/postgresql/class/pg.py | 2 + plugins/postgresql/index.html | 6 +- plugins/postgresql/index.py | 200 ++++++++++---------- plugins/postgresql/js/postgresql.js | 284 ++++++++-------------------- 4 files changed, 184 insertions(+), 308 deletions(-) diff --git a/plugins/postgresql/class/pg.py b/plugins/postgresql/class/pg.py index c984a9350..9338bc1bc 100755 --- a/plugins/postgresql/class/pg.py +++ b/plugins/postgresql/class/pg.py @@ -39,7 +39,9 @@ class ORM: self.__DB_CONN = psycopg2.connect(database='postgres', user=self.__DB_USER, password=self.__DB_PASS, host=self.__DB_HOST, port=int(self.__DB_PORT)) + self.__DB_CONN.autocommit = True self.__DB_CUR = self.__DB_CONN.cursor() + return True except Exception as e: self.__DB_ERR = e diff --git a/plugins/postgresql/index.html b/plugins/postgresql/index.html index bc4973629..1b418ddd5 100755 --- a/plugins/postgresql/index.html +++ b/plugins/postgresql/index.html @@ -2,15 +2,15 @@
-

服务

自启动

-

配置文件

- +

配置文件

+

客服端认证

端口

当前状态

性能优化

日志

+

慢日志

管理列表

diff --git a/plugins/postgresql/index.py b/plugins/postgresql/index.py index 5eb86769b..f0bb2f170 100755 --- a/plugins/postgresql/index.py +++ b/plugins/postgresql/index.py @@ -87,6 +87,10 @@ def configTpl(): return mw.getJson(clist) +def pgHbaConf(): + return getServerDir() + "/data/pg_hba.conf" + + def readConfigTpl(): args = getArgs() data = checkArgs(args, ['file']) @@ -174,7 +178,7 @@ def initDreplace(version=''): init_pl = conf_dir + "/init.pl" if not os.path.exists(init_pl): - # mw.writeFile(init_pl, 'ok') + mw.writeFile(init_pl, 'ok') pg_conf = conf_dir + '/data/postgresql.conf' tpl = getPluginDir() + '/conf/postgresql.conf' content = mw.readFile(tpl) @@ -221,50 +225,6 @@ def status(version=''): return 'start' -def getDataDir(): - file = getConf() - content = mw.readFile(file) - rep = 'datadir\s*=\s*(.*)' - tmp = re.search(rep, content) - return tmp.groups()[0].strip() - - -def getPidFile(): - file = getConf() - content = mw.readFile(file) - rep = 'pid-file\s*=\s*(.*)' - tmp = re.search(rep, content) - return tmp.groups()[0].strip() - - -def getErrorLog(): - args = getArgs() - path = getDataDir() - filename = '' - for n in os.listdir(path): - if len(n) < 5: - continue - if n == 'error.log': - filename = path + '/' + n - break - # print filename - if not os.path.exists(filename): - return mw.returnJson(False, '指定文件不存在!') - if 'close' in args: - mw.writeFile(filename, '') - return mw.returnJson(False, '日志已清空') - info = mw.getNumLines(filename, 18) - return mw.returnJson(True, 'OK', info) - - -def getShowLogFile(): - file = getConf() - content = mw.readFile(file) - rep = 'slow-query-log-file\s*=\s*(.*)' - tmp = re.search(rep, content) - return tmp.groups()[0].strip() - - def pGetDbUser(): if mw.isAppleSystem(): user = mw.execShell( @@ -398,7 +358,7 @@ def getMyDbPos(): return tmp.groups()[0].strip() -def setMyDbPos(): +def setPgDbPos(): args = getArgs() data = checkArgs(args, ['datadir']) if not data[0]: @@ -522,6 +482,11 @@ def runLog(): return getServerDir() + "/logs/server.log" +def getSlowLog(): + # pgsql慢日志查询 + return getServerDir() + "/logs/" + time.strftime("postgresql-%Y-%m-%d.log") + + def getUnit(args): unit = '' if "GB" in args: @@ -550,7 +515,7 @@ def pgDbStatus(): shared_buffers_num = re.match( r'\d+', shared_buffers.strip()).group() if re.match(r'\d+', shared_buffers.strip()) else "" data['shared_buffers'] = [shared_buffers_num, "MB", - "PG通过shared_buffers和内核和磁盘打交道,通常设置为实际内存的10%。"] + "PG通过shared_buffers和内核和磁盘打交道,通常设置为实际内存的10%."] if i.strip().startswith("work_mem"): work_mem = i.split("=")[1] @@ -560,7 +525,7 @@ def pgDbStatus(): work_mem_num = re.match( r'\d+', work_mem.strip()).group() if re.match(r'\d+', work_mem.strip()) else "" data['work_mem'] = [work_mem_num, "MB", - "增加work_mem有助于提高排序的速度。通常设置为实际RAM的2% -4%。"] + "增加work_mem有助于提高排序的速度。通常设置为实际RAM的2% -4%."] if i.strip().startswith("effective_cache_size"): effective_cache_size = i.split("=")[1] @@ -570,7 +535,7 @@ def pgDbStatus(): effective_cache_size_num = re.match(r'\d+', effective_cache_size.strip( )).group() if re.match(r'\d+', effective_cache_size.strip()) else "" data['effective_cache_size'] = [effective_cache_size_num, - "GB", "pgsql能够使用的最大缓存,比如4G的内存,可以设置为3GB."] + "GB", "PG能够使用的最大缓存,比如4G的内存,可以设置为3GB."] if i.strip().startswith("temp_buffers "): temp_buffers = i.split("=")[1] @@ -647,28 +612,34 @@ def pgDbStatus(): return mw.getJson(data) -def setDbStatus(): - gets = ['key_buffer_size', 'tmp_table_size', 'max_heap_table_size', 'innodb_buffer_pool_size', 'innodb_log_buffer_size', 'max_connections', - 'table_open_cache', 'thread_cache_size', 'sort_buffer_size', 'read_buffer_size', 'read_rnd_buffer_size', 'join_buffer_size', 'thread_stack', 'binlog_cache_size'] - emptys = ['max_connections', 'thread_cache_size', 'table_open_cache'] +def sedConf(name, val): + path = getServerDir() + "/data/postgresql.conf" + content = '' + with open(path) as f: + for i in f: + if i.strip().startswith(name): + i = "{} = {} \n".format(name, val) + content += i + + mw.writeFile(path, content) + return True + + +def pgSetDbStatus(): + ''' + 保存pgsql性能调整信息 + ''' args = getArgs() - conFile = getConf() - content = mw.readFile(conFile) - n = 0 - for g in gets: - s = 'M' - if n > 5: - s = 'K' - if g in emptys: - s = '' - rep = '\s*' + g + '\s*=\s*\d+(M|K|k|m|G)?\n' - c = g + ' = ' + args[g] + s + '\n' - if content.find(g) != -1: - content = re.sub(rep, '\n' + c, content, 1) - else: - content = content.replace('[mysqld]\n', '[mysqld]\n' + c) - n += 1 - mw.writeFile(conFile, content) + data = checkArgs(args, ['shared_buffers', 'work_mem', 'effective_cache_size', + 'temp_buffers', 'max_connections', 'max_prepared_transactions', + 'max_stack_depth', 'bgwriter_lru_maxpages', 'max_worker_processes']) + if not data[0]: + return data[1] + + for k, v in args.items(): + sedConf(k, v) + + restart() return mw.returnJson(True, '设置成功!') @@ -868,28 +839,35 @@ def syncGetDatabases(): def addDb(): args = getArgs() - data = checkArgs( - args, ['password', 'name', 'codeing', 'db_user', 'dataAccess', 'ps']) + data = checkArgs(args, ['password', 'name', 'db_user', 'dataAccess']) if not data[0]: return data[1] - if not 'address' in args: - address = '' - else: + address = '' + if 'address' in args: address = args['address'].strip() dbname = args['name'].strip() dbuser = args['db_user'].strip() - codeing = args['codeing'].strip() password = args['password'].strip() dataAccess = args['dataAccess'].strip() - ps = args['ps'].strip() + + listen_ip = "127.0.0.1/32" + if 'listen_ip' in args: + listen_ip = args['listen_ip'].strip() + + 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", "'*'") reg = "^[\w\.-]+$" if not re.match(reg, args['name']): return mw.returnJson(False, '数据库名称不能带有特殊符号!') - checks = ['root', 'mysql', 'test', 'sys', 'panel_logs'] + checks = ['root', 'mysql', 'test', 'sys', 'postgres', 'postgresql'] if dbuser in checks or len(dbuser) < 1: return mw.returnJson(False, '数据库用户名不合法!') if dbname in checks or len(dbname) < 1: @@ -898,37 +876,57 @@ def addDb(): if len(password) < 1: password = mw.md5(time.time())[0:8] - wheres = { - 'utf8': 'utf8_general_ci', - 'utf8mb4': 'utf8mb4_general_ci', - 'gbk': 'gbk_chinese_ci', - 'big5': 'big5_chinese_ci' - } - - codeStr = wheres[codeing] - pdb = pgDb() psdb = pSqliteDb('databases') if psdb.where("name=? or username=?", (dbname, dbuser)).count(): - return mw.returnJson(False, '数据库已存在!') - - result = pdb.execute("create database " + dbname) + return mw.returnJson(False, '数据库或用户已存在!') - print(result) - return + r = pdb.execute("create database " + dbname) + r = pdb.execute("create user " + dbuser) + pdb.execute("alter user {} with password '{}'".format(dbuser, password,)) + pdb.execute( + "GRANT ALL PRIVILEGES ON DATABASE {} TO {}".format(dbname, dbuser,)) - # pdb.execute("drop user '" + dbuser + "'@'localhost'") - # for a in address.split(','): - # pdb.execute("drop user '" + dbuser + "'@'" + a + "'") + pg_hba = getServerDir() + "/data/pg_hba.conf" - # __createUser(dbname, dbuser, password, address) + content = mw.readFile(pg_hba) + content += "\nhost {} {} {} md5".format( + dbname, dbuser, listen_ip) + mw.writeFile(pg_hba, content) addTime = time.strftime('%Y-%m-%d %X', time.localtime()) psdb.add('pid,name,username,password,accept,ps,addtime', - (0, dbname, dbuser, password, address, ps, addTime)) + (0, dbname, dbuser, password, address, dbname, addTime)) + + restart() return mw.returnJson(True, '添加成功!') +def delDb(): + args = getArgs() + data = checkArgs(args, ['id', 'name']) + if not data[0]: + return data[1] + + did = args['id'] + name = args['name'] + + pdb = pgDb() + psdb = pSqliteDb('databases') + pdb.execute("drop database " + name) + + username = psdb.where('id=?', (did,)).getField('username') + pdb.execute("drop user " + username) + + pg_hba = getServerDir() + "/data/pg_hba.conf" + old_config = mw.readFile(pg_hba) + new_config = re.sub(r'host\s*{}.*'.format(name), '', old_config).strip() + mw.writeFile(pg_hba, new_config) + + psdb.where("id=?", (did,)).delete() + return mw.returnJson(True, '删除成功!') + + def installPreInspection(version): return 'ok' @@ -966,6 +964,8 @@ if __name__ == "__main__": print(uninstallPreInspection(version)) elif func == 'conf': print(getConf()) + elif func == 'pg_hba_conf': + print(pgHbaConf()) elif func == 'config_tpl': print(configTpl()) elif func == 'read_config_tpl': @@ -974,8 +974,12 @@ if __name__ == "__main__": print(runInfo()) elif func == 'run_log': print(runLog()) + elif func == 'slow_log': + print(getSlowLog()) elif func == 'db_status': print(pgDbStatus()) + elif func == 'set_db_status': + print(pgSetDbStatus()) elif func == 'pg_port': print(getPgPort()) elif func == 'set_pg_port': @@ -984,6 +988,8 @@ if __name__ == "__main__": print(getDbList()) elif func == 'add_db': print(addDb()) + elif func == 'del_db': + print(delDb()) elif func == 'sync_get_databases': print(syncGetDatabases()) else: diff --git a/plugins/postgresql/js/postgresql.js b/plugins/postgresql/js/postgresql.js index 20927503f..13c52846f 100755 --- a/plugins/postgresql/js/postgresql.js +++ b/plugins/postgresql/js/postgresql.js @@ -103,26 +103,6 @@ function runInfo(){ } -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 pgPort(){ myPost('pg_port','',function(data){ var con = '
\ @@ -148,7 +128,7 @@ function pgPort(){ //数据库存储信置 -function changeMySQLDataPath(act) { +function changePgDataPath(act) { if (act != undefined) { layer.confirm(lan.soft.mysql_to_msg, { closeBtn: 2, icon: 3 }, function() { var datadir = $("#datadir").val(); @@ -176,155 +156,48 @@ function pgPerfOpt() { //获取MySQL配置 myPost('db_status','',function(data){ var rdata = $.parseJSON(data.data); - - console.log(rdata); var html_p = ''; for (i in rdata){ - if (i!='status'){ + if (i != 'status' ){ var v = rdata[i]; - html_p += '

'+i+''+v[1] +', ' + v[2] + '

' + html_p += '

'+i+''+v[1] +', ' + v[2] + '

' } } - - var memCon = '
\ -
最大使用内存: \ - \ - 最大使用内存: MB\ -
\ - '+html_p+'\ -
' + var memCon = '
'+html_p + +'
\ +
\ + \ +
\ +
' + +'
' $(".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='pg_set']").change(function() { - pgSQLMemOpt($(this).val()); - comMySqlMem(); + $("#pg_conf").change(function (e) { +   e.preventDefault(); + var data = {}; + $('#pg_conf p input').each(function (index, element) { + data[$(this).attr('name')] = $(this).val() + ($(this).attr('unit') || ''); + }) + // console.log(data); + myPost('set_db_status', data, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + },{ icon: rdata.status ? 1 : 2 }); + }); + return false; }); }); } -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 pgSQLMemOpt(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; - } +function reBootPgSqld(){ + pluginOpService('postgresql','restart',''); } -//计算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)); +//设置PG配置参数 +function setPgConf() { + return false; } function syncGetDatabase(){ @@ -360,33 +233,28 @@ function setRootPwd(type, pwd){ showMsg(rdata.msg,function(){ dbList(); $('.layui-layer-close1').click(); - },{icon: rdata.status ? 1 : 2}); + },{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: "

\ + btn:["取消","提交"], + content: "\
\ root密码\
\
\ -
\ - \ - \ -
\ -
", - }); - - $('#my_mod_close').click(function(){ - $('.layui-layer-close1').click(); + ", + yes:function(){ + setRootPwd(1); + } }); } @@ -557,85 +425,86 @@ function setDbPass(id, username, password){ }); } -function addDatabase(type){ - if (type==1){ +function addDatabase(type,layer_index){ + if (type == 1){ var data = $("#add_db").serialize(); data = decodeURIComponent(data); var dataObj = str2Obj(data); if(!dataObj['address']){ dataObj['address'] = dataObj['dataAccess']; } + + var ip_segment = $('[name="dataAccess"]').val(); + if ($('[name="dataAccess"]').val() == 'ip'){ + dataObj['listen_ip'] = ip_segment; + } myPost('add_db', dataObj, function(data){ var rdata = $.parseJSON(data.data); showMsg(rdata.msg,function(){ + layer.close(layer_index); if (rdata.status){ dbList(); } - $('.layui-layer-close1').click(); - },{icon: rdata.status ? 1 : 2},600); + },{icon: rdata.status ? 1 : 2},2000); }); return; } - var index = layer.open({ + + layer.open({ type: 1, - skin: 'demo-class', - area: '500px', + area: '450px', title: '添加数据库', closeBtn: 1, shift: 5, shadeClose: true, - content: "
\ + btn:["提交","取消"], + content: "\
\ 数据库名\ -
\ - \ +
\ + \
\
\ -
用户名
\ +
用户名
\
\ 密码\ -
\ +
\ +
\
\
\ 访问权限\ -
\ +
\ \ + \
\
\ - \ -
\ - \ - \ -
\ ", - }); + success:function(){ - $("input[name='name']").keyup(function(){ - var v = $(this).val(); - $("input[name='db_user']").val(v); - $("input[name='ps']").val(v); - }); + $("input[name='name']").keyup(function(){ + var v = $(this).val(); + $("input[name='db_user']").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(); + $('select[name="dataAccess"]').change(function(){ + var v = $(this).val(); + if (v == 'ip'){ + $('input[name="ip_segment"]').show(); + } else { + $('input[name="ip_segment"]').hide(); + + } + }); + }, + yes:function(index){ + addDatabase(1,index); } }); + } function delDb(id, name){ @@ -886,8 +755,7 @@ function dbList(page, search){ } - list += '工具 | ' + - '权限 | ' + + list += '权限 | ' + rw + '改密 | ' + '删除' +