From 9d1e934f9adae2c13f41fbbddc757a1d4366369f Mon Sep 17 00:00:00 2001 From: midoks Date: Tue, 8 Nov 2022 00:24:15 +0800 Subject: [PATCH] mysql-ya init --- plugins/mysql-yum/conf/my5.7.cnf | 97 + plugins/mysql-yum/conf/my8.0.cnf | 98 + plugins/mysql-yum/conf/mysql.sql | 28 + plugins/mysql-yum/ico.png | Bin 0 -> 1135 bytes plugins/mysql-yum/index.html | 58 + plugins/mysql-yum/index.py | 1939 ++++++++++++++++++++ plugins/mysql-yum/info.json | 17 + plugins/mysql-yum/init.d/mysql.service.tpl | 63 + plugins/mysql-yum/install.sh | 46 + plugins/mysql-yum/js/mysql-yum.js | 1736 ++++++++++++++++++ plugins/mysql-yum/scripts/backup.py | 119 ++ plugins/mysql-yum/versions/5.7/install.sh | 119 ++ plugins/mysql-yum/versions/8.0/install.sh | 121 ++ 13 files changed, 4441 insertions(+) create mode 100644 plugins/mysql-yum/conf/my5.7.cnf create mode 100644 plugins/mysql-yum/conf/my8.0.cnf create mode 100755 plugins/mysql-yum/conf/mysql.sql create mode 100644 plugins/mysql-yum/ico.png create mode 100755 plugins/mysql-yum/index.html create mode 100755 plugins/mysql-yum/index.py create mode 100755 plugins/mysql-yum/info.json create mode 100644 plugins/mysql-yum/init.d/mysql.service.tpl create mode 100755 plugins/mysql-yum/install.sh create mode 100755 plugins/mysql-yum/js/mysql-yum.js create mode 100755 plugins/mysql-yum/scripts/backup.py create mode 100755 plugins/mysql-yum/versions/5.7/install.sh create mode 100755 plugins/mysql-yum/versions/8.0/install.sh diff --git a/plugins/mysql-yum/conf/my5.7.cnf b/plugins/mysql-yum/conf/my5.7.cnf new file mode 100644 index 000000000..847bc276e --- /dev/null +++ b/plugins/mysql-yum/conf/my5.7.cnf @@ -0,0 +1,97 @@ +[client] +user = root +#password = your_password +port = 3376 +socket = {$SERVER_APP_PATH}/mysql.sock +default-character-set = UTF8MB4 + +[mysqld] +pid-file = {$SERVER_APP_PATH}/data/mysql.pid +user = mysql +port = 3376 +mysqlx_port = 33760 +socket = {$SERVER_APP_PATH}/mysql.sock +datadir = {$SERVER_APP_PATH}/data +log-error = {$SERVER_APP_PATH}/data/error.log +default_storage_engine = MyISAM + +key_buffer_size = 8M +table_open_cache = 32 +sort_buffer_size = 256K +net_buffer_length = 4K +read_buffer_size = 128K +read_rnd_buffer_size = 256K +myisam_sort_buffer_size = 4M +thread_cache_size = 4 +lower_case_table_names=0 +tmp_table_size = 8M +character-set-server = UTF8MB4 + +max_connections = 500 +max_connect_errors = 100 +open_files_limit = 2560 +max_allowed_packet = 128M + +#skip-external-locking +#skip-grant-tables +#loose-skip-innodb +#skip-networking +#skip-name-resolve + +log-bin=mysql-bin +binlog_format=mixed +server-id = 1 +slow_query_log=1 +slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log +long_query_time=3 +#log_queries_not_using_indexes=on + +relay-log=mdserver +relay-log-index=mdserver + +#master +#binlog-do-db +binlog-ignore-db = test +binlog-ignore-db = mysql +binlog-ignore-db = information_schema +binlog-ignore-db = performance_schema + +#slave +log-slave-updates +#replicate-do-db +replicate-ignore-db = information_schema +replicate-ignore-db = performance_schema +replicate-ignore-db = mysql +replicate-ignore-db = test + +default_storage_engine = InnoDB +innodb_data_home_dir = {$SERVER_APP_PATH}/data +innodb_data_file_path = ibdata1:10M:autoextend +innodb_log_group_home_dir = {$SERVER_APP_PATH}/data +innodb_buffer_pool_size = 16M +innodb_log_file_size = 5M +innodb_log_buffer_size = 8M +innodb_flush_log_at_trx_commit = 1 +innodb_lock_wait_timeout = 120 +innodb_max_dirty_pages_pct = 90 +innodb_read_io_threads = 1 +innodb_write_io_threads = 1 +innodb_file_per_table=1 +binlog_expire_logs_seconds=2592000 + +secure-file-priv={$SERVER_APP_PATH}/tmp + +[mysqldump] +quick + +[mysql] +no-auto-rehash + +[myisamchk] +key_buffer_size = 20M +sort_buffer_size = 20M +read_buffer = 2M +write_buffer = 2M + +[mysqlhotcopy] +interactive-timeout \ No newline at end of file diff --git a/plugins/mysql-yum/conf/my8.0.cnf b/plugins/mysql-yum/conf/my8.0.cnf new file mode 100644 index 000000000..934657c4b --- /dev/null +++ b/plugins/mysql-yum/conf/my8.0.cnf @@ -0,0 +1,98 @@ +[client] +user = root +#password = your_password +port = 3386 +socket = {$SERVER_APP_PATH}/mysql.sock +default-character-set = UTF8MB4 + +[mysqld] +default_authentication_plugin=mysql_native_password +pid-file = {$SERVER_APP_PATH}/data/mysql.pid +user = mysql +port = 3386 +mysqlx_port = 33860 +socket = {$SERVER_APP_PATH}/mysql.sock +datadir = {$SERVER_APP_PATH}/data +log-error = {$SERVER_APP_PATH}/data/error.log +default_storage_engine = MyISAM + +key_buffer_size = 8M +table_open_cache = 32 +sort_buffer_size = 256K +net_buffer_length = 4K +read_buffer_size = 128K +read_rnd_buffer_size = 256K +myisam_sort_buffer_size = 4M +thread_cache_size = 4 +lower_case_table_names=0 +tmp_table_size = 8M +character-set-server = UTF8MB4 + +max_connections = 500 +max_connect_errors = 100 +open_files_limit = 2560 +max_allowed_packet = 128M + +#skip-external-locking +#skip-grant-tables +#loose-skip-innodb +#skip-networking +#skip-name-resolve + +log-bin=mysql-bin +binlog_format=mixed +server-id = 1 +slow_query_log=1 +slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log +long_query_time=3 +#log_queries_not_using_indexes=on + +relay-log=mdserver +relay-log-index=mdserver + +#master +#binlog-do-db +binlog-ignore-db = test +binlog-ignore-db = mysql +binlog-ignore-db = information_schema +binlog-ignore-db = performance_schema + +#slave +log_replica_updates +#replicate-do-db +replicate-ignore-db = information_schema +replicate-ignore-db = performance_schema +replicate-ignore-db = mysql +replicate-ignore-db = test + +default_storage_engine = InnoDB +innodb_data_home_dir = {$SERVER_APP_PATH}/data +innodb_data_file_path = ibdata1:10M:autoextend +innodb_log_group_home_dir = {$SERVER_APP_PATH}/data +innodb_buffer_pool_size = 16M +innodb_log_file_size = 5M +innodb_log_buffer_size = 8M +innodb_flush_log_at_trx_commit = 1 +innodb_lock_wait_timeout = 120 +innodb_max_dirty_pages_pct = 90 +innodb_read_io_threads = 1 +innodb_write_io_threads = 1 +innodb_file_per_table=1 +binlog_expire_logs_seconds=2592000 + +secure-file-priv={$SERVER_APP_PATH}/tmp + +[mysqldump] +quick + +[mysql] +no-auto-rehash + +[myisamchk] +key_buffer_size = 20M +sort_buffer_size = 20M +read_buffer = 2M +write_buffer = 2M + +[mysqlhotcopy] +interactive-timeout \ No newline at end of file diff --git a/plugins/mysql-yum/conf/mysql.sql b/plugins/mysql-yum/conf/mysql.sql new file mode 100755 index 000000000..38b822738 --- /dev/null +++ b/plugins/mysql-yum/conf/mysql.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS `config` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, + `mysql_root` TEXT +); + +INSERT INTO `config` (`id`, `mysql_root`) VALUES (1, 'admin'); + +CREATE TABLE IF NOT EXISTS `databases` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, + `pid` INTEGER, + `name` TEXT, + `username` TEXT, + `password` TEXT, + `accept` TEXT, + `ps` TEXT, + `addtime` TEXT +); + +CREATE TABLE IF NOT EXISTS `master_replication_user` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, + `username` TEXT, + `password` TEXT, + `accept` TEXT, + `ps` TEXT, + `addtime` TEXT +); + + diff --git a/plugins/mysql-yum/ico.png b/plugins/mysql-yum/ico.png new file mode 100644 index 0000000000000000000000000000000000000000..ead815fc20cc747780967ef2871b83c000e4f82d GIT binary patch literal 1135 zcmV-#1d#iQP)>{3lQ%rYE>EIo|Bc9O8-^_)1agG}q9>-P216(B zK}1dolB(O#w(T^gZ+;f7TTURgp@*LLi%EvgY=cZDhv*1Q%s|VgV~ETx1Bb!tAi=x$ zUWdVBccSOOP0TAdp?2kNQqbh`6_+AM=z=O#FWZiQgf#GjdIS}L4KI9; zf}sTnN>=9>ibj?}Z*{;EbY?5sx1YxBZ7&Kol9MINSyjpHnF1j5xR->al|lgp3yToqeV zi#1Puj`)fuTy=C78)}wr|E;r9Us(3QJIL;u;2qai|6mNCx)=S2ZoTRgD-Cf~i(61M zx(o`X3N_1iVCx${VeI@Pv@i2P$%IaC9>B`SKIRNTVJVXE z2#%m|zDZ4GHL+7*QfNoPf=^*t~;eZXN43`ND z7cv<&LC*S9H$H{xrQ7Jlg9?E+DPi*uMqb|xC2+^ia|lk(@-ihrD=Xzh`OJFMEZYt$ z$xJyfgDMjpD9034i#I2DjNYWkmE7JWBqSsxeg^A1@>H +
+
+
+ +

服务

+

自启动

+

配置文件

+

存储位置

+

端口

+

当前状态

+

性能优化

+

日志

+

错误日志

+

慢日志

+

管理列表

+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/plugins/mysql-yum/index.py b/plugins/mysql-yum/index.py new file mode 100755 index 000000000..02a970347 --- /dev/null +++ b/plugins/mysql-yum/index.py @@ -0,0 +1,1939 @@ +# coding:utf-8 + +import sys +import io +import os +import time +import subprocess +import re +import json + + +# reload(sys) +# sys.setdefaultencoding('utf-8') + +sys.path.append(os.getcwd() + "/class/core") +import mw + + +if mw.isAppleSystem(): + cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\'' + info = mw.execShell(cmd) + p = "/usr/local/lib/" + info[0].strip() + "/site-packages" + sys.path.append(p) + + +app_debug = False +if mw.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'mysql-yum' + + +def getPluginDir(): + return mw.getPluginDir() + '/' + getPluginName() + + +def getServerDir(): + return mw.getServerDir() + '/' + getPluginName() + + +def getArgs(): + args = sys.argv[2:] + + tmp = {} + args_len = len(args) + + if args_len == 1: + t = args[0].strip('{').strip('}') + t = t.split(':') + tmp[t[0]] = t[1] + elif args_len > 1: + for i in range(len(args)): + t = args[i].split(':') + tmp[t[0]] = t[1] + + return tmp + + +def checkArgs(data, ck=[]): + for i in range(len(ck)): + if not ck[i] in data: + return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) + return (True, mw.returnJson(True, 'ok')) + + +def getConf(): + path = getServerDir() + '/etc/my.cnf' + return path + + +def getDataDir(): + file = getConf() + content = mw.readFile(file) + rep = 'datadir\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def getPidFile(): + file = getConf() + content = mw.readFile(file) + rep = 'pid-file\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def getDbPort(): + file = getConf() + content = mw.readFile(file) + rep = 'port\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def getSocketFile(): + file = getConf() + content = mw.readFile(file) + rep = 'socket\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def contentReplace(content): + service_path = mw.getServerDir() + content = content.replace('{$ROOT_PATH}', mw.getRootDir()) + content = content.replace('{$SERVER_PATH}', service_path) + content = content.replace('{$SERVER_APP_PATH}', + service_path + '/' + getPluginName()) + return content + + +def pSqliteDb(dbname='databases'): + file = getServerDir() + '/mysql.db' + name = 'mysql' + if not os.path.exists(file): + conn = mw.M(dbname).dbPos(getServerDir(), name) + csql = mw.readFile(getPluginDir() + '/conf/mysql.sql') + csql_list = csql.split(';') + for index in range(len(csql_list)): + conn.execute(csql_list[index], ()) + else: + # 现有run + # conn = mw.M(dbname).dbPos(getServerDir(), name) + # csql = mw.readFile(getPluginDir() + '/conf/mysql.sql') + # csql_list = csql.split(';') + # for index in range(len(csql_list)): + # conn.execute(csql_list[index], ()) + conn = mw.M(dbname).dbPos(getServerDir(), name) + return conn + + +def pMysqlDb(): + # mysql.connector + # db = mw.getMyORM() + # MySQLdb | + db = mw.getMyORMDb() + + # db = mw.getMyORM() + db.__DB_CNF = getConf() + db.setPort(getDbPort()) + db.setSocket(getSocketFile()) + db.setPwd(pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')) + return db + + +def initDreplace(version=''): + + mysql_conf_dir = getServerDir() + '/etc' + if not os.path.exists(mysql_conf_dir): + os.mkdir(mysql_conf_dir) + + mysql_tmp = getServerDir() + '/tmp' + if not os.path.exists(mysql_tmp): + os.mkdir(mysql_tmp) + mw.execShell("chown -R mysql:mysql " + mysql_tmp) + + mysql_conf = mysql_conf_dir + '/my.cnf' + if not os.path.exists(mysql_conf): + mysql_conf_tpl = getPluginDir() + '/conf/my' + version + '.cnf' + content = mw.readFile(mysql_conf_tpl) + content = contentReplace(content) + mw.writeFile(mysql_conf, content) + + # systemd + systemDir = mw.systemdCfgDir() + systemService = systemDir + '/mysql-yum.service' + systemServiceTpl = getPluginDir() + '/init.d/mysql.service.tpl' + if os.path.exists(systemDir) and not os.path.exists(systemService): + service_path = mw.getServerDir() + se_content = mw.readFile(systemServiceTpl) + se_content = se_content.replace('{$SERVER_PATH}', service_path) + mw.writeFile(systemService, se_content) + mw.execShell('systemctl daemon-reload') + + if mw.getOs() != 'darwin': + mw.execShell('chown -R mysql mysql ' + getServerDir()) + return 'ok' + + +def status(version=''): + pid = getPidFile() + if not os.path.exists(pid): + return 'stop' + return 'start' + + +def binLog(): + args = getArgs() + conf = getConf() + con = mw.readFile(conf) + + if con.find('#log-bin=mysql-bin') != -1: + if 'status' in args: + return mw.returnJson(False, '0') + con = con.replace('#log-bin=mysql-bin', 'log-bin=mysql-bin') + con = con.replace('#binlog_format=mixed', 'binlog_format=mixed') + mw.execShell('sync') + restart() + else: + path = getDataDir() + if 'status' in args: + dsize = 0 + for n in os.listdir(path): + if len(n) < 9: + continue + if n[0:9] == 'mysql-bin': + dsize += os.path.getsize(path + '/' + n) + return mw.returnJson(True, dsize) + con = con.replace('log-bin=mysql-bin', '#log-bin=mysql-bin') + con = con.replace('binlog_format=mixed', '#binlog_format=mixed') + mw.execShell('sync') + restart() + mw.execShell('rm -f ' + path + '/mysql-bin.*') + + mw.writeFile(conf, con) + return mw.returnJson(True, '设置成功!') + + +def setSkipGrantTables(v): + ''' + 设置是否密码验证 + ''' + conf = getConf() + con = mw.readFile(conf) + if v: + if con.find('#skip-grant-tables') != -1: + con = con.replace('#skip-grant-tables', 'skip-grant-tables') + else: + con = con.replace('skip-grant-tables', '#skip-grant-tables') + mw.writeFile(conf, con) + return True + + +# 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 getErrorLog(): + file = getConf() + content = mw.readFile(file) + rep = 'log-error\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +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( + "who | sed -n '2, 1p' |awk '{print $1}'")[0].strip() + return user + return 'mysql' + + +def initMysql57Data(): + datadir = getDataDir() + if not os.path.exists(datadir + '/mysql'): + serverdir = getServerDir() + myconf = serverdir + "/etc/my.cnf" + user = pGetDbUser() + cmd = 'mysqld --defaults-file=' + myconf + \ + ' --initialize-insecure --explicit_defaults_for_timestamp' + mw.execShell(cmd) + return False + return True + + +def initMysql8Data(): + datadir = getDataDir() + if not os.path.exists(datadir + '/mysql'): + serverdir = getServerDir() + user = pGetDbUser() + cmd = 'mysqld --basedir=/usr --datadir=' + datadir + ' --initialize-insecure' + mw.execShell(cmd) + mw.execShell('chown -R mysql mysql ' + getServerDir()) + return False + return True + + +def initMysql8Pwd(): + time.sleep(5) + pwd = mw.getRandomString(16) + + alter_root_pwd = 'flush privileges;' + alter_root_pwd = alter_root_pwd + \ + "alter user 'root'@'localhost' IDENTIFIED by '" + pwd + "';" + alter_root_pwd = alter_root_pwd + \ + "alter user 'root'@'localhost' IDENTIFIED WITH mysql_native_password by '" + pwd + "';" + alter_root_pwd = alter_root_pwd + "flush privileges;" + + cmd_pass = 'mysqladmin --defaults-file=' + \ + getServerDir() + '/etc/my.cnf -uroot password root' + data = mw.execShell(cmd_pass) + # print(data) + + tmp_file = "/tmp/mysql_ya_init_tmp.log" + mw.writeFile(tmp_file, alter_root_pwd) + cmd_pass = 'mysql --defaults-file=' + \ + getServerDir() + '/etc/my.cnf -uroot -proot < ' + tmp_file + + data = mw.execShell(cmd_pass) + # print(data) + os.remove(tmp_file) + + pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,)) + + return True + + +def my8cmd(version, method): + initDreplace(version) + # mysql 8.0 and 5.7 + try: + if version == '5.7': + isInited = initMysql57Data() + elif version == '8.0': + isInited = initMysql8Data() + + if not isInited: + mw.execShell('systemctl start ' + getPluginName()) + initMysql8Pwd() + mw.execShell('systemctl stop ' + getPluginName()) + + mw.execShell('systemctl ' + method + ' ' + getPluginName()) + return 'ok' + except Exception as e: + return str(e) + + +def appCMD(version, action): + return my8cmd(version, action) + + +def start(version=''): + return appCMD(version, 'start') + + +def stop(version=''): + return appCMD(version, 'stop') + + +def restart(version=''): + return appCMD(version, 'restart') + + +def reload(version=''): + return appCMD(version, 'reload') + + +def initdStatus(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + shell_cmd = 'systemctl status ' + \ + getPluginName() + ' | grep loaded | grep "enabled;"' + data = mw.execShell(shell_cmd) + if data[0] == '': + return 'fail' + return 'ok' + + +def initdInstall(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl enable ' + getPluginName()) + return 'ok' + + +def initdUinstall(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl disable ' + getPluginName()) + return 'ok' + + +def getMyDbPos(): + file = getConf() + content = mw.readFile(file) + rep = 'datadir\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def setMyDbPos(): + args = getArgs() + data = checkArgs(args, ['datadir']) + if not data[0]: + return data[1] + + s_datadir = getMyDbPos() + t_datadir = args['datadir'] + if t_datadir == s_datadir: + return mw.returnJson(False, '与当前存储目录相同,无法迁移文件!') + + if not os.path.exists(t_datadir): + mw.execShell('mkdir -p ' + t_datadir) + + # mw.execShell('/etc/init.d/mysqld stop') + stop() + mw.execShell('cp -rf ' + s_datadir + '/* ' + t_datadir + '/') + mw.execShell('chown -R mysql mysql ' + t_datadir) + mw.execShell('chmod -R 755 ' + t_datadir) + mw.execShell('rm -f ' + t_datadir + '/*.pid') + mw.execShell('rm -f ' + t_datadir + '/*.err') + + path = getServerDir() + myfile = path + '/etc/my.cnf' + mycnf = mw.readFile(myfile) + mw.writeFile(path + '/etc/my_backup.cnf', mycnf) + + mycnf = mycnf.replace(s_datadir, t_datadir) + mw.writeFile(myfile, mycnf) + start() + + result = mw.execShell( + 'ps aux|grep mysqld| grep -v grep|grep -v python') + if len(result[0]) > 10: + mw.writeFile('data/datadir.pl', t_datadir) + return mw.returnJson(True, '存储目录迁移成功!') + else: + mw.execShell('pkill -9 mysqld') + mw.writeFile(myfile, mw.readFile(path + '/etc/my_backup.cnf')) + start() + return mw.returnJson(False, '文件迁移失败!') + + +def getMyPort(): + file = getConf() + content = mw.readFile(file) + rep = 'port\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def setMyPort(): + args = getArgs() + data = checkArgs(args, ['port']) + if not data[0]: + return data[1] + + port = args['port'] + file = getConf() + content = mw.readFile(file) + rep = "port\s*=\s*([0-9]+)\s*\n" + content = re.sub(rep, 'port = ' + port + '\n', content) + mw.writeFile(file, content) + restart() + return mw.returnJson(True, '编辑成功!') + + +def runInfo(): + + if status(version) == 'stop': + return mw.returnJson(false, 'MySQL未启动', []) + + db = pMysqlDb() + data = db.query('show global status') + gets = ['Max_used_connections', 'Com_commit', 'Com_rollback', 'Questions', 'Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests', 'Key_reads', 'Key_read_requests', 'Key_writes', + 'Key_write_requests', 'Qcache_hits', 'Qcache_inserts', 'Bytes_received', 'Bytes_sent', 'Aborted_clients', 'Aborted_connects', + 'Created_tmp_disk_tables', 'Created_tmp_tables', 'Innodb_buffer_pool_pages_dirty', 'Opened_files', 'Open_tables', 'Opened_tables', 'Select_full_join', + 'Select_range_check', 'Sort_merge_passes', 'Table_locks_waited', 'Threads_cached', 'Threads_connected', 'Threads_created', 'Threads_running', 'Connections', 'Uptime'] + + try: + # print data + if data[0] == 1045 or data[0] == 2003: + pwd = db.getPwd() + return mw.returnJson(False, 'mysql password error:' + pwd + '!') + except Exception as e: + return mw.returnJson(False, str(e)) + + result = {} + # print(data) + for d in data: + for g in gets: + if d[0] == g: + result[g] = d[1] + + # print(result, int(result['Uptime'])) + result['Run'] = int(time.time()) - int(result['Uptime']) + tmp = db.query('show master status') + try: + result['File'] = tmp[0][0] + result['Position'] = tmp[0][1] + except: + result['File'] = 'OFF' + result['Position'] = 'OFF' + return mw.getJson(result) + + +def myDbStatus(): + result = {} + db = pMysqlDb() + data = db.query('show variables') + isError = isSqlError(data) + if isError != None: + return isError + + gets = ['table_open_cache', 'thread_cache_size', 'key_buffer_size', 'tmp_table_size', 'max_heap_table_size', 'innodb_buffer_pool_size', + 'innodb_additional_mem_pool_size', 'innodb_log_buffer_size', 'max_connections', 'sort_buffer_size', 'read_buffer_size', 'read_rnd_buffer_size', 'join_buffer_size', 'thread_stack', 'binlog_cache_size'] + result['mem'] = {} + for d in data: + for g in gets: + if d[0] == g: + result['mem'][g] = d[1] + # if result['mem']['query_cache_type'] != 'ON': + # result['mem']['query_cache_size'] = '0' + return mw.getJson(result) + + +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'] + 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) + return mw.returnJson(True, '设置成功!') + + +def isSqlError(mysqlMsg): + # 检测数据库执行错误 + mysqlMsg = str(mysqlMsg) + if "MySQLdb" in mysqlMsg: + return mw.returnJson(False, 'MySQLdb组件缺失!
进入SSH命令行输入: pip install mysql-python | pip install mysqlclient==2.0.3') + if "2002," in mysqlMsg: + return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!') + 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, '数据库管理密码错误!') + if "Connection refused" in mysqlMsg: + return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!') + if "1133" in mysqlMsg: + return mw.returnJson(False, '数据库用户不存在!') + if "1007" in mysqlMsg: + return mw.returnJson(False, '数据库已经存在!') + if "1045" in mysqlMsg: + return mw.returnJson(False, '数据库管理密码错误!') + return None + + +def mapToList(map_obj): + # map to list + try: + if type(map_obj) != list and type(map_obj) != str: + map_obj = list(map_obj) + return map_obj + except: + return [] + + +def __createUser(dbname, username, password, address): + pdb = pMysqlDb() + + if username == 'root': + dbname = '*' + + 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") + + +def getDbBackupListFunc(dbname=''): + bkDir = mw.getRootDir() + '/backup/database' + blist = os.listdir(bkDir) + r = [] + + bname = 'db_' + dbname + blen = len(bname) + for x in blist: + fbstr = x[0:blen] + if fbstr == bname: + r.append(x) + return r + + +def setDbBackup(): + args = getArgs() + data = checkArgs(args, ['name']) + if not data[0]: + return data[1] + + scDir = getPluginDir() + '/scripts/backup.py' + + cmd = 'python3 ' + scDir + ' database ' + args['name'] + ' 3' + os.system(cmd) + return mw.returnJson(True, 'ok') + + +def importDbBackup(): + args = getArgs() + data = checkArgs(args, ['file', 'name']) + if not data[0]: + return data[1] + + file = args['file'] + name = args['name'] + + file_path = mw.getRootDir() + '/backup/database/' + file + file_path_sql = mw.getRootDir() + '/backup/database/' + file.replace('.gz', '') + + if not os.path.exists(file_path_sql): + cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file + mw.execShell(cmd) + + pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root') + + mysql_cmd = mw.getRootDir() + '/server/mysql/bin/mysql -uroot -p' + pwd + \ + ' ' + name + ' < ' + file_path_sql + + # print(mysql_cmd) + os.system(mysql_cmd) + return mw.returnJson(True, 'ok') + + +def deleteDbBackup(): + args = getArgs() + data = checkArgs(args, ['filename']) + if not data[0]: + return data[1] + + bkDir = mw.getRootDir() + '/backup/database' + + os.remove(bkDir + '/' + args['filename']) + return mw.returnJson(True, 'ok') + + +def getDbBackupList(): + args = getArgs() + data = checkArgs(args, ['name']) + if not data[0]: + return data[1] + + r = getDbBackupListFunc(args['name']) + bkDir = mw.getRootDir() + '/backup/database' + rr = [] + for x in range(0, len(r)): + p = bkDir + '/' + r[x] + data = {} + data['name'] = r[x] + + 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 + + return mw.returnJson(True, 'ok', rr) + + +def getDbList(): + args = getArgs() + page = 1 + page_size = 10 + search = '' + data = {} + if 'page' in args: + page = int(args['page']) + + if 'page_size' in args: + page_size = int(args['page_size']) + + if 'search' in args: + search = args['search'] + + conn = pSqliteDb('databases') + limit = str((page - 1) * page_size) + ',' + str(page_size) + condition = '' + if not search == '': + condition = "name like '%" + search + "%'" + field = 'id,pid,name,username,password,accept,ps,addtime' + clist = conn.where(condition, ()).field( + field).limit(limit).order('id desc').select() + + for x in range(0, len(clist)): + dbname = clist[x]['name'] + blist = getDbBackupListFunc(dbname) + # print(blist) + clist[x]['is_backup'] = False + if len(blist) > 0: + clist[x]['is_backup'] = True + + count = conn.where(condition, ()).count() + _page = {} + _page['count'] = count + _page['p'] = page + _page['row'] = page_size + _page['tojs'] = 'dbList' + data['page'] = mw.getPage(_page) + data['data'] = clist + + info = {} + info['root_pwd'] = pSqliteDb('config').where( + 'id=?', (1,)).getField('mysql_root') + data['info'] = info + + return mw.getJson(data) + + +def syncGetDatabases(): + pdb = pMysqlDb() + psdb = pSqliteDb('databases') + data = pdb.query('show databases') + isError = isSqlError(data) + if isError != None: + return isError + users = pdb.query( + "select User,Host from mysql.user where User!='root' AND Host!='localhost' AND Host!=''") + nameArr = ['information_schema', 'performance_schema', 'mysql', 'sys'] + n = 0 + for value in data: + b = False + for key in nameArr: + if value[0] == key: + b = True + break + if b: + continue + if psdb.where("name=?", (value[0],)).count(): + continue + host = '127.0.0.1' + for user in users: + if value[0] == user[0]: + host = user[1] + break + + ps = mw.getMsg('INPUT_PS') + if value[0] == 'test': + ps = mw.getMsg('DATABASE_TEST') + addTime = time.strftime('%Y-%m-%d %X', time.localtime()) + if psdb.add('name,username,password,accept,ps,addtime', (value[0], value[0], '', host, ps, addTime)): + n += 1 + + msg = mw.getInfo('本次共从服务器获取了{1}个数据库!', (str(n),)) + return mw.returnJson(True, msg) + + +def toDbBase(find): + pdb = pMysqlDb() + psdb = pSqliteDb('databases') + if len(find['password']) < 3: + find['username'] = find['name'] + find['password'] = mw.md5(str(time.time()) + find['name'])[0:10] + psdb.where("id=?", (find['id'],)).save( + 'password,username', (find['password'], find['username'])) + + result = pdb.execute("create database `" + find['name'] + "`") + if "using password:" in str(result): + return -1 + if "Connection refused" in str(result): + return -1 + + password = find['password'] + __createUser(find['name'], find['username'], password, find['accept']) + return 1 + + +def syncToDatabases(): + args = getArgs() + data = checkArgs(args, ['type', 'ids']) + if not data[0]: + return data[1] + + pdb = pMysqlDb() + result = pdb.execute("show databases") + isError = isSqlError(result) + if isError: + return isError + + stype = int(args['type']) + psdb = pSqliteDb('databases') + n = 0 + + if stype == 0: + data = psdb.field('id,name,username,password,accept').select() + for value in data: + result = toDbBase(value) + if result == 1: + n += 1 + else: + data = json.loads(args['ids']) + for value in data: + find = psdb.where("id=?", (value,)).field( + 'id,name,username,password,accept').find() + # print find + result = toDbBase(find) + if result == 1: + n += 1 + msg = mw.getInfo('本次共同步了{1}个数据库!', (str(n),)) + return mw.returnJson(True, msg) + + +def setRootPwd(): + args = getArgs() + data = checkArgs(args, ['password']) + if not data[0]: + return data[1] + + password = args['password'] + try: + pdb = pMysqlDb() + result = pdb.query("show databases") + isError = isSqlError(result) + if isError != None: + return isError + + m_version = mw.readFile(getServerDir() + '/version.pl') + if m_version.find('5.7') == 0 or m_version.find('8.0') == 0: + pdb.execute( + "UPDATE mysql.user SET authentication_string='' WHERE user='root'") + pdb.execute( + "ALTER USER 'root'@'localhost' IDENTIFIED BY '%s'" % password) + pdb.execute( + "ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '%s'" % password) + else: + result = pdb.execute( + "update mysql.user set Password=password('" + password + "') where User='root'") + pdb.execute("flush privileges") + pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (password,)) + return mw.returnJson(True, '数据库root密码修改成功!') + except Exception as ex: + return mw.returnJson(False, '修改错误:' + str(ex)) + + +def setUserPwd(): + args = getArgs() + data = checkArgs(args, ['password', 'name']) + if not data[0]: + return data[1] + + newpassword = args['password'] + username = args['name'] + id = args['id'] + try: + pdb = pMysqlDb() + psdb = pSqliteDb('databases') + name = psdb.where('id=?', (id,)).getField('name') + + m_version = mw.readFile(getServerDir() + '/version.pl') + if m_version.find('5.7') == 0 or m_version.find('8.0') == 0: + tmp = pdb.query( + "select Host from mysql.user where User='" + name + "' AND Host!='localhost'") + accept = mapToList(tmp) + pdb.execute( + "update mysql.user set authentication_string='' where User='" + username + "'") + result = pdb.execute( + "ALTER USER `%s`@`localhost` IDENTIFIED BY '%s'" % (username, newpassword)) + for my_host in accept: + pdb.execute("ALTER USER `%s`@`%s` IDENTIFIED BY '%s'" % ( + username, my_host[0], newpassword)) + else: + result = pdb.execute("update mysql.user set Password=password('" + + newpassword + "') where User='" + username + "'") + isError = isSqlError(result) + if isError != None: + return isError + pdb.execute("flush privileges") + psdb.where("id=?", (id,)).setField('password', newpassword) + return mw.returnJson(True, mw.getInfo('修改数据库[{1}]密码成功!', (name,))) + except Exception as ex: + # print str(ex) + return mw.returnJson(False, mw.getInfo('修改数据库[{1}]密码失败!', (name,))) + + +def setDbPs(): + args = getArgs() + data = checkArgs(args, ['id', 'name', 'ps']) + if not data[0]: + return data[1] + + ps = args['ps'] + sid = args['id'] + name = args['name'] + try: + psdb = pSqliteDb('databases') + psdb.where("id=?", (sid,)).setField('ps', ps) + return mw.returnJson(True, mw.getInfo('修改数据库[{1}]备注成功!', (name,))) + except Exception as e: + return mw.returnJson(True, mw.getInfo('修改数据库[{1}]备注失败!', (name,))) + + +def addDb(): + args = getArgs() + data = checkArgs(args, + ['password', 'name', 'codeing', 'db_user', 'dataAccess', 'ps']) + if not data[0]: + return data[1] + + if not 'address' in args: + address = '' + else: + 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() + + reg = "^[\w\.-]+$" + if not re.match(reg, args['name']): + return mw.returnJson(False, '数据库名称不能带有特殊符号!') + checks = ['root', 'mysql', 'test', 'sys', 'panel_logs'] + if dbuser in checks or len(dbuser) < 1: + return mw.returnJson(False, '数据库用户名不合法!') + if dbname in checks or len(dbname) < 1: + return mw.returnJson(False, '数据库名称不合法!') + + 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 = pMysqlDb() + psdb = pSqliteDb('databases') + + if psdb.where("name=? or username=?", (dbname, dbuser)).count(): + return mw.returnJson(False, '数据库已存在!') + + result = pdb.execute("create database `" + dbname + + "` DEFAULT CHARACTER SET " + codeing + " COLLATE " + codeStr) + # print result + isError = isSqlError(result) + if isError != None: + return isError + + pdb.execute("drop user '" + dbuser + "'@'localhost'") + for a in address.split(','): + pdb.execute("drop user '" + dbuser + "'@'" + a + "'") + + __createUser(dbname, dbuser, password, address) + + 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)) + return mw.returnJson(True, '添加成功!') + + +def delDb(): + args = getArgs() + data = checkArgs(args, ['id', 'name']) + if not data[0]: + return data[1] + try: + id = args['id'] + name = args['name'] + psdb = pSqliteDb('databases') + pdb = pMysqlDb() + find = psdb.where("id=?", (id,)).field( + 'id,pid,name,username,password,accept,ps,addtime').find() + accept = find['accept'] + username = find['username'] + + # 删除MYSQL + result = pdb.execute("drop database `" + name + "`") + isError = isSqlError(result) + if isError != None: + return isError + + users = pdb.query( + "select Host from mysql.user where User='" + username + "' AND Host!='localhost'") + pdb.execute("drop user '" + username + "'@'localhost'") + for us in users: + pdb.execute("drop user '" + username + "'@'" + us[0] + "'") + pdb.execute("flush privileges") + + # 删除SQLITE + psdb.where("id=?", (id,)).delete() + return mw.returnJson(True, '删除成功!') + except Exception as ex: + return mw.returnJson(False, '删除失败!' + str(ex)) + + +def getDbAccess(): + args = getArgs() + data = checkArgs(args, ['username']) + if not data[0]: + return data[1] + username = args['username'] + pdb = pMysqlDb() + + users = pdb.query("select Host from mysql.user where User='" + + username + "' AND Host!='localhost'") + isError = isSqlError(users) + if isError != None: + return isError + + users = mapToList(users) + if len(users) < 1: + return mw.returnJson(True, "127.0.0.1") + accs = [] + for c in users: + accs.append(c[0]) + userStr = ','.join(accs) + return mw.returnJson(True, userStr) + + +def toSize(size): + d = ('b', 'KB', 'MB', 'GB', 'TB') + s = d[0] + for b in d: + if size < 1024: + return str(size) + ' ' + b + size = size / 1024 + s = b + _size = round(size, 2) + # print(size, _size) + return str(size) + ' ' + b + + +def setDbAccess(): + args = getArgs() + data = checkArgs(args, ['username', 'access']) + if not data[0]: + return data[1] + name = args['username'] + access = args['access'] + pdb = pMysqlDb() + psdb = pSqliteDb('databases') + + dbname = psdb.where('username=?', (name,)).getField('name') + + if name == 'root': + password = pSqliteDb('config').where( + 'id=?', (1,)).getField('mysql_root') + else: + password = psdb.where("username=?", (name,)).getField('password') + users = pdb.query("select Host from mysql.user where User='" + + name + "' AND Host!='localhost'") + for us in users: + pdb.execute("drop user '" + name + "'@'" + us[0] + "'") + + __createUser(dbname, name, password, access) + + psdb.where('username=?', (name,)).save('accept', (access,)) + return mw.returnJson(True, '设置成功!') + + +def getDbInfo(): + args = getArgs() + data = checkArgs(args, ['name']) + if not data[0]: + return data[1] + + db_name = args['name'] + pdb = pMysqlDb() + # print 'show tables from `%s`' % db_name + table_res = pdb.query('show tables from `%s`' % db_name) + isError = isSqlError(table_res) + if isError != None: + return isError + + tables = mapToList(table_res) + + ret = {} + if type(tables) == list: + try: + data = mapToList(pdb.query( + "select sum(DATA_LENGTH)+sum(INDEX_LENGTH) from information_schema.tables where table_schema='%s'" % db_name))[0][0] + except: + data = 0 + + if not data: + data = 0 + ret['data_size'] = mw.toSize(data) + # print ret + ret['database'] = db_name + + ret3 = [] + + for i in tables: + if i == 1049: + return mw.returnJson(False, '指定数据库不存在!') + table = mapToList( + pdb.query("show table status from `%s` where name = '%s'" % (db_name, i[0]))) + if not table: + continue + try: + ret2 = {} + ret2['type'] = table[0][1] + ret2['rows_count'] = table[0][4] + ret2['collation'] = table[0][14] + data_size = table[0][6] + table[0][8] + ret2['data_byte'] = data_size + ret2['data_size'] = mw.toSize(data_size) + ret2['table_name'] = i[0] + ret3.append(ret2) + except: + continue + ret['tables'] = (ret3) + + return mw.getJson(ret) + + +def repairTable(): + args = getArgs() + data = checkArgs(args, ['db_name', 'tables']) + if not data[0]: + return data[1] + + db_name = args['db_name'] + tables = json.loads(args['tables']) + pdb = pMysqlDb() + mysql_table = mapToList(pdb.query('show tables from `%s`' % db_name)) + ret = [] + if type(mysql_table) == list: + if len(mysql_table) > 0: + for i in mysql_table: + for i2 in tables: + if i2 == i[0]: + ret.append(i2) + if len(ret) > 0: + for i in ret: + pdb.execute('REPAIR TABLE `%s`.`%s`' % (db_name, i)) + return mw.returnJson(True, "修复完成!") + return mw.returnJson(False, "修复失败!") + + +def optTable(): + args = getArgs() + data = checkArgs(args, ['db_name', 'tables']) + if not data[0]: + return data[1] + + db_name = args['db_name'] + tables = json.loads(args['tables']) + pdb = pMysqlDb() + mysql_table = mapToList(pdb.query('show tables from `%s`' % db_name)) + ret = [] + if type(mysql_table) == list: + if len(mysql_table) > 0: + for i in mysql_table: + for i2 in tables: + if i2 == i[0]: + ret.append(i2) + if len(ret) > 0: + for i in ret: + pdb.execute('OPTIMIZE TABLE `%s`.`%s`' % (db_name, i)) + return mw.returnJson(True, "优化成功!") + return mw.returnJson(False, "优化失败或者已经优化过了!") + + +def alterTable(): + args = getArgs() + data = checkArgs(args, ['db_name', 'tables']) + if not data[0]: + return data[1] + + db_name = args['db_name'] + tables = json.loads(args['tables']) + table_type = args['table_type'] + pdb = pMysqlDb() + mysql_table = mapToList(pdb.query('show tables from `%s`' % db_name)) + ret = [] + if type(mysql_table) == list: + if len(mysql_table) > 0: + for i in mysql_table: + for i2 in tables: + if i2 == i[0]: + ret.append(i2) + if len(ret) > 0: + for i in ret: + pdb.execute('alter table `%s`.`%s` ENGINE=`%s`' % + (db_name, i, table_type)) + return mw.returnJson(True, "更改成功!") + return mw.returnJson(False, "更改失败!") + + +def getTotalStatistics(): + st = status() + data = {} + + isInstall = os.path.exists(getServerDir() + '/version.pl') + + if st == 'start' and isInstall: + data['status'] = True + data['count'] = pSqliteDb('databases').count() + data['ver'] = mw.readFile(getServerDir() + '/version.pl').strip() + return mw.returnJson(True, 'ok', data) + else: + data['status'] = False + data['count'] = 0 + return mw.returnJson(False, 'fail', data) + + +def findBinlogDoDb(): + conf = getConf() + con = mw.readFile(conf) + rep = r"binlog-do-db\s*?=\s*?(.*)" + dodb = re.findall(rep, con, re.M) + return dodb + + +def findBinlogSlaveDoDb(): + conf = getConf() + con = mw.readFile(conf) + rep = r"replicate-do-db\s*?=\s*?(.*)" + dodb = re.findall(rep, con, re.M) + return dodb + + +def getMasterDbList(version=''): + args = getArgs() + page = 1 + page_size = 10 + search = '' + data = {} + if 'page' in args: + page = int(args['page']) + + if 'page_size' in args: + page_size = int(args['page_size']) + + if 'search' in args: + search = args['search'] + + conn = pSqliteDb('databases') + limit = str((page - 1) * page_size) + ',' + str(page_size) + condition = '' + dodb = findBinlogDoDb() + data['dodb'] = dodb + + slave_dodb = findBinlogSlaveDoDb() + + if not search == '': + condition = "name like '%" + search + "%'" + field = 'id,pid,name,username,password,accept,ps,addtime' + clist = conn.where(condition, ()).field( + field).limit(limit).order('id desc').select() + count = conn.where(condition, ()).count() + + for x in range(0, len(clist)): + if clist[x]['name'] in dodb: + clist[x]['master'] = 1 + else: + clist[x]['master'] = 0 + + if clist[x]['name'] in slave_dodb: + clist[x]['slave'] = 1 + else: + clist[x]['slave'] = 0 + + _page = {} + _page['count'] = count + _page['p'] = page + _page['row'] = page_size + _page['tojs'] = 'dbList' + data['page'] = mw.getPage(_page) + data['data'] = clist + + return mw.getJson(data) + + +def setDbMaster(version): + args = getArgs() + data = checkArgs(args, ['name']) + if not data[0]: + return data[1] + + conf = getConf() + con = mw.readFile(conf) + rep = r"(binlog-do-db\s*?=\s*?(.*))" + dodb = re.findall(rep, con, re.M) + + isHas = False + for x in range(0, len(dodb)): + + if dodb[x][1] == args['name']: + isHas = True + + con = con.replace(dodb[x][0] + "\n", '') + mw.writeFile(conf, con) + + if not isHas: + prefix = '#binlog-do-db' + con = con.replace( + prefix, prefix + "\nbinlog-do-db=" + args['name']) + mw.writeFile(conf, con) + + restart(version) + time.sleep(4) + return mw.returnJson(True, '设置成功', [args, dodb]) + + +def setDbSlave(version): + args = getArgs() + data = checkArgs(args, ['name']) + if not data[0]: + return data[1] + + conf = getConf() + con = mw.readFile(conf) + rep = r"(replicate-do-db\s*?=\s*?(.*))" + dodb = re.findall(rep, con, re.M) + + isHas = False + for x in range(0, len(dodb)): + if dodb[x][1] == args['name']: + isHas = True + + con = con.replace(dodb[x][0] + "\n", '') + mw.writeFile(conf, con) + + if not isHas: + prefix = '#replicate-do-db' + con = con.replace( + prefix, prefix + "\nreplicate-do-db=" + args['name']) + mw.writeFile(conf, con) + + restart(version) + time.sleep(4) + return mw.returnJson(True, '设置成功', [args, dodb]) + + +def getMasterStatus(version=''): + + if status(version) == 'stop': + return mw.returnJson(false, 'MySQL未启动,或正在启动中...!', []) + + conf = getConf() + con = mw.readFile(conf) + master_status = False + if con.find('#log-bin') == -1 and con.find('log-bin') > 1: + dodb = findBinlogDoDb() + if len(dodb) > 0: + master_status = True + data = {} + data['status'] = master_status + + db = pMysqlDb() + dlist = db.query('show slave status') + # print(dlist, len(dlist)) + if len(dlist) > 0 and (dlist[0][10] == 'Yes' or dlist[0][11] == 'Yes'): + data['slave_status'] = True + + return mw.returnJson(master_status, '设置成功', data) + + +def setMasterStatus(version=''): + + conf = getConf() + con = mw.readFile(conf) + + if con.find('#log-bin') != -1: + return mw.returnJson(False, '必须开启二进制日志') + + sign = 'mdserver_ms_open' + + dodb = findBinlogDoDb() + if not sign in dodb: + prefix = '#binlog-do-db' + con = con.replace(prefix, prefix + "\nbinlog-do-db=" + sign) + mw.writeFile(conf, con) + else: + con = con.replace("binlog-do-db=" + sign + "\n", '') + rep = r"(binlog-do-db\s*?=\s*?(.*))" + dodb = re.findall(rep, con, re.M) + for x in range(0, len(dodb)): + con = con.replace(dodb[x][0] + "\n", '') + mw.writeFile(conf, con) + + restart(version) + return mw.returnJson(True, '设置成功') + + +def getMasterRepSlaveList(version=''): + args = getArgs() + page = 1 + page_size = 10 + search = '' + data = {} + if 'page' in args: + page = int(args['page']) + + if 'page_size' in args: + page_size = int(args['page_size']) + + if 'search' in args: + search = args['search'] + + conn = pSqliteDb('master_replication_user') + limit = str((page - 1) * page_size) + ',' + str(page_size) + condition = '' + + if not search == '': + condition = "name like '%" + search + "%'" + field = 'id,username,password,accept,ps,addtime' + clist = conn.where(condition, ()).field( + field).limit(limit).order('id desc').select() + count = conn.where(condition, ()).count() + + _page = {} + _page['count'] = count + _page['p'] = page + _page['row'] = page_size + _page['tojs'] = 'getMasterRepSlaveList' + data['page'] = mw.getPage(_page) + data['data'] = clist + + return mw.getJson(data) + + +def addMasterRepSlaveUser(version=''): + args = getArgs() + data = checkArgs(args, + ['username', 'password']) + if not data[0]: + return data[1] + + if not 'address' in args: + address = '' + else: + address = args['address'].strip() + + username = args['username'].strip() + password = args['password'].strip() + # ps = args['ps'].strip() + # address = args['address'].strip() + # dataAccess = args['dataAccess'].strip() + + reg = "^[\w\.-]+$" + if not re.match(reg, username): + return mw.returnJson(False, '用户名不能带有特殊符号!') + checks = ['root', 'mysql', 'test', 'sys', 'panel_logs'] + if username in checks or len(username) < 1: + return mw.returnJson(False, '用户名不合法!') + if password in checks or len(password) < 1: + return mw.returnJson(False, '密码不合法!') + + if len(password) < 1: + password = mw.md5(time.time())[0:8] + + pdb = pMysqlDb() + psdb = pSqliteDb('master_replication_user') + + if psdb.where("username=?", (username)).count(): + return mw.returnJson(False, '用户已存在!') + + result = pdb.execute("GRANT REPLICATION SLAVE ON *.* TO '" + + username + "'@'%' identified by '" + password + "';FLUSH PRIVILEGES;") + # print result + isError = isSqlError(result) + if isError != None: + return isError + + addTime = time.strftime('%Y-%m-%d %X', time.localtime()) + psdb.add('username,password,accept,ps,addtime', + (username, password, '%', '', addTime)) + return mw.returnJson(True, '添加成功!') + + +def getMasterRepSlaveUserCmd(version): + args = getArgs() + data = checkArgs(args, ['username', 'db']) + if not data[0]: + return data[1] + + psdb = pSqliteDb('master_replication_user') + f = 'username,password' + if args['username'] == '': + + count = psdb.count() + + if count == 0: + return mw.returnJson(False, '请添加同步账户!') + + clist = psdb.field(f).limit('1').order('id desc').select() + else: + clist = psdb.field(f).where("username=?", (args['username'],)).limit( + '1').order('id desc').select() + + ip = mw.getLocalIp() + port = getMyPort() + + db = pMysqlDb() + tmp = db.query('show master status') + + if len(tmp) == 0: + return mw.returnJson(False, '未开启!') + + sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \ + clist[0]['username'] + "', MASTER_PASSWORD='" + \ + clist[0]['password'] + \ + "', MASTER_LOG_FILE='" + tmp[0][0] + \ + "',MASTER_LOG_POS=" + str(tmp[0][1]) + "" + + # if args['db'] != '': + # replicate-do-table + + return mw.returnJson(True, 'OK!', sql) + + +def delMasterRepSlaveUser(version=''): + args = getArgs() + data = checkArgs(args, ['username']) + if not data[0]: + return data[1] + + pdb = pMysqlDb() + psdb = pSqliteDb('master_replication_user') + pdb.execute("drop user '" + args['username'] + "'@'%'") + psdb.where("username=?", (args['username'],)).delete() + + return mw.returnJson(True, '删除成功!') + + +def updateMasterRepSlaveUser(version=''): + args = getArgs() + data = checkArgs(args, ['username', 'password']) + if not data[0]: + return data[1] + + pdb = pMysqlDb() + psdb = pSqliteDb('master_replication_user') + pdb.execute("drop user '" + args['username'] + "'@'%'") + + pdb.execute("GRANT REPLICATION SLAVE ON *.* TO '" + + args['username'] + "'@'%' identified by '" + args['password'] + "'") + + psdb.where("username=?", (args['username'],)).save( + 'password', args['password']) + + return mw.returnJson(True, '更新成功!') + + +def getSlaveList(version=''): + + db = pMysqlDb() + dlist = db.query('show slave status') + + # print(dlist) + ret = [] + for x in range(0, len(dlist)): + tmp = {} + tmp['Master_User'] = dlist[x][2] + tmp['Master_Host'] = dlist[x][1] + tmp['Master_Port'] = dlist[x][3] + tmp['Master_Log_File'] = dlist[x][5] + tmp['Slave_IO_Running'] = dlist[x][10] + tmp['Slave_SQL_Running'] = dlist[x][11] + ret.append(tmp) + data = {} + data['data'] = ret + + return mw.getJson(data) + + +def setSlaveStatus(version=''): + db = pMysqlDb() + dlist = db.query('show slave status') + + if len(dlist) == 0: + return mw.returnJson(False, '需要手动添加主服务同步命令!') + + if len(dlist) > 0 and (dlist[0][10] == 'Yes' or dlist[0][11] == 'Yes'): + db.query('stop slave') + else: + db.query('start slave') + + return mw.returnJson(True, '设置成功!') + + +def deleteSlave(version=''): + db = pMysqlDb() + dlist = db.query('stop slave;reset slave all') + return mw.returnJson(True, '删除成功!') + + +def dumpMysqlData(version): + + args = getArgs() + data = checkArgs(args, ['db']) + if not data[0]: + return data[1] + + pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root') + if args['db'] == 'all' or args['db'] == 'ALL': + dlist = findBinlogDoDb() + cmd = getServerDir() + "/bin/mysqldump -uroot -p" + \ + pwd + " --databases " + ' '.join(dlist) + \ + " > /tmp/dump.sql" + else: + cmd = getServerDir() + "/bin/mysqldump -uroot -p" + pwd + \ + " --databases " + args['db'] + " > /tmp/dump.sql" + + ret = mw.execShell(cmd) + + if ret[0] == '': + return 'ok' + return 'fail' + + +from threading import Thread +from time import sleep + + +def mw_async(f): + def wrapper(*args, **kwargs): + thr = Thread(target=f, args=args, kwargs=kwargs) + thr.start() + return wrapper + + +def doFullSync(): + + args = getArgs() + data = checkArgs(args, ['db']) + if not data[0]: + return data[1] + + status_data = {} + status_data['progress'] = 5 + + db = pMysqlDb() + + dlist = db.query('show slave status') + if len(dlist) == 0: + status_data['code'] = -1 + status_data['msg'] = '没有启动...' + + ip = dlist[0][1] + print(ip) + + status_file = '/tmp/db_async_status.txt' + + status_data['code'] = 0 + status_data['msg'] = '运行中...' + mw.writeFile(status_file, json.dumps(status_data)) + + import paramiko + paramiko.util.log_to_file('paramiko.log') + ssh = paramiko.SSHClient() + + SSH_PRIVATE_KEY = '/root/.ssh/id_rsa' + + if mw.getOs() == 'darwin': + user = mw.execShell( + "who | sed -n '2, 1p' |awk '{print $1}'")[0].strip() + SSH_PRIVATE_KEY = '/Users/' + user + '/.ssh/id_rsa' + + print(SSH_PRIVATE_KEY) + if not os.path.exists(SSH_PRIVATE_KEY): + status_data['code'] = 0 + status_data['msg'] = '需要配置免登录...' + mw.writeFile(status_file, json.dumps(status_data)) + return + + try: + key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY) + # ssh.load_system_host_keys() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(hostname=ip, port=22, username='root', pkey=key) + except Exception as e: + status_data['code'] = 0 + status_data['msg'] = '需要配置免登录....' + mw.writeFile(status_file, json.dumps(status_data)) + return + + cmd = "cd /www/server/mdserver-web && python /www/server/mdserver-web/plugins/mysql/index.py dump_mysql_data {\"db\":'" + args[ + 'db'] + "'}" + stdin, stdout, stderr = ssh.exec_command(cmd) + result = stdout.read() + result_err = stderr.read() + + if result == 'ok': + status_data['code'] = 1 + status_data['msg'] = '主服务器备份完成...' + status_data['progress'] = 30 + mw.writeFile(status_file, json.dumps(status_data)) + + r = mw.execShell('scp root@' + ip + ':/tmp/dump.sql /tmp') + if r[0] == '': + status_data['code'] = 2 + status_data['msg'] = '数据同步本地完成...' + status_data['progress'] = 40 + mw.writeFile(status_file, json.dumps(status_data)) + + cmd = 'cd /www/server/mdserver-web && python /www/server/mdserver-web/plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}' + stdin, stdout, stderr = ssh.exec_command(cmd) + result = stdout.read() + result_err = stderr.read() + cmd_data = json.loads(result) + + db.query('stop slave') + status_data['code'] = 3 + status_data['msg'] = '停止从库完成...' + status_data['progress'] = 45 + mw.writeFile(status_file, json.dumps(status_data)) + + dlist = db.query(cmd_data['data']) + status_data['code'] = 4 + status_data['msg'] = '刷新库信息完成...' + status_data['progress'] = 50 + mw.writeFile(status_file, json.dumps(status_data)) + + pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root') + cmd = getServerDir() + "/bin/mysql -uroot -p" + pwd + " < /tmp/dump.sql" + print(mw.execShell(cmd)) + status_data['code'] = 5 + status_data['msg'] = '同步数据完成...' + status_data['progress'] = 90 + mw.writeFile(status_file, json.dumps(status_data)) + + db.query('start slave') + status_data['code'] = 6 + status_data['msg'] = '从库重启完成...' + status_data['progress'] = 100 + mw.writeFile(status_file, json.dumps(status_data)) + + return True + + +def fullSync(version=''): + args = getArgs() + data = checkArgs(args, ['db', 'begin']) + if not data[0]: + return data[1] + + status_file = '/tmp/db_async_status.txt' + if args['begin'] == '1': + cmd = 'cd ' + mw.getRunDir() + ' && python ' + \ + getPluginDir() + \ + '/index.py do_full_sync {"db":"' + args['db'] + '"} &' + mw.execShell(cmd) + return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0}) + + if os.path.exists(status_file): + c = mw.readFile(status_file) + d = json.loads(c) + + if d['code'] == 6: + os.remove(status_file) + return c + + return json.dumps({'code': 0, 'msg': '点击开始,开始同步!', 'progress': 0}) + + +# 安装预检查 +def installPreInspection(version): + sys = mw.execShell( + "cat /etc/*-release | grep PRETTY_NAME |awk -F = '{print $2}' | awk -F '\"' '{print $2}'| awk '{print $1}'") + + sys_id = mw.execShell( + "cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F '\"' '{print $2}'") + + sysName = sys[0].strip().lower() + sysId = sys_id[0].strip() + + if not sysName in ('centos'): + return '暂时仅支持centos' + + if version == '5.7' and int(sysId) > 7: + return 'MySQL[' + version + ']不支持安装在ceonts[' + sysId + ']' + if version == '8.0' and int(sysId) < 6: + return 'MySQL[' + version + ']不支持安装在ceonts[' + sysId + ']' + + return 'ok' + +if __name__ == "__main__": + func = sys.argv[1] + + version = "5.6" + if (len(sys.argv) > 2): + version = sys.argv[2] + + if func == 'status': + print(status(version)) + elif func == 'start': + print(start(version)) + elif func == 'stop': + print(stop(version)) + elif func == 'restart': + print(restart(version)) + elif func == 'reload': + print(reload(version)) + elif func == 'install_pre_inspection': + print(installPreInspection(version)) + elif func == 'initd_status': + print(initdStatus()) + elif func == 'initd_install': + print(initdInstall()) + elif func == 'initd_uninstall': + print(initdUinstall()) + elif func == 'run_info': + print(runInfo()) + elif func == 'db_status': + print(myDbStatus()) + elif func == 'set_db_status': + print(setDbStatus()) + elif func == 'conf': + print(getConf()) + elif func == 'bin_log': + print(binLog()) + elif func == 'error_log': + print(getErrorLog()) + elif func == 'show_log': + print(getShowLogFile()) + elif func == 'my_db_pos': + print(getMyDbPos()) + elif func == 'set_db_pos': + print(setMyDbPos()) + elif func == 'my_port': + print(getMyPort()) + elif func == 'set_my_port': + print(setMyPort()) + elif func == 'init_pwd': + print(initMysqlPwd()) + elif func == 'get_db_list': + print(getDbList()) + elif func == 'set_db_backup': + print(setDbBackup()) + elif func == 'import_db_backup': + print(importDbBackup()) + elif func == 'delete_db_backup': + print(deleteDbBackup()) + elif func == 'get_db_backup_list': + print(getDbBackupList()) + elif func == 'add_db': + print(addDb()) + elif func == 'del_db': + print(delDb()) + elif func == 'sync_get_databases': + print(syncGetDatabases()) + elif func == 'sync_to_databases': + print(syncToDatabases()) + elif func == 'set_root_pwd': + print(setRootPwd()) + elif func == 'set_user_pwd': + print(setUserPwd()) + elif func == 'get_db_access': + print(getDbAccess()) + elif func == 'set_db_access': + print(setDbAccess()) + elif func == 'set_db_ps': + print(setDbPs()) + elif func == 'get_db_info': + print(getDbInfo()) + elif func == 'repair_table': + print(repairTable()) + elif func == 'opt_table': + print(optTable()) + elif func == 'alter_table': + print(alterTable()) + elif func == 'get_total_statistics': + print(getTotalStatistics()) + elif func == 'get_masterdb_list': + print(getMasterDbList(version)) + elif func == 'get_master_status': + print(getMasterStatus(version)) + elif func == 'set_master_status': + print(setMasterStatus(version)) + elif func == 'set_db_master': + print(setDbMaster(version)) + elif func == 'set_db_slave': + print(setDbSlave(version)) + elif func == 'get_master_rep_slave_list': + print(getMasterRepSlaveList(version)) + elif func == 'add_master_rep_slave_user': + print(addMasterRepSlaveUser(version)) + elif func == 'del_master_rep_slave_user': + print(delMasterRepSlaveUser(version)) + elif func == 'update_master_rep_slave_user': + print(updateMasterRepSlaveUser(version)) + elif func == 'get_master_rep_slave_user_cmd': + print(getMasterRepSlaveUserCmd(version)) + elif func == 'get_slave_list': + print(getSlaveList(version)) + elif func == 'set_slave_status': + print(setSlaveStatus(version)) + elif func == 'delete_slave': + print(deleteSlave(version)) + elif func == 'full_sync': + print(fullSync(version)) + elif func == 'do_full_sync': + print(doFullSync()) + elif func == 'dump_mysql_data': + print(dumpMysqlData(version)) + else: + print('error') diff --git a/plugins/mysql-yum/info.json b/plugins/mysql-yum/info.json new file mode 100755 index 000000000..33f1edcd8 --- /dev/null +++ b/plugins/mysql-yum/info.json @@ -0,0 +1,17 @@ +{ + "title":"MySQL[YUM]", + "tip":"soft", + "name":"mysql-yum", + "type":"运行环境", + "ps":"[勿用]一种关系数据库管理系统(极速安装)!", + "todo_versions":["5.7","8.0"], + "versions":["5.7","8.0"], + "shell":"install.sh", + "install_pre_inspection":true, + "checks":"server/mysql-yum", + "path":"server/mysql-yum", + "author":"mysql", + "home":"https://dev.mysql.com/downloads/mysql", + "date":"2022-06-29", + "pid": "6" +} \ No newline at end of file diff --git a/plugins/mysql-yum/init.d/mysql.service.tpl b/plugins/mysql-yum/init.d/mysql.service.tpl new file mode 100644 index 000000000..8aa912c37 --- /dev/null +++ b/plugins/mysql-yum/init.d/mysql.service.tpl @@ -0,0 +1,63 @@ +# It's not recommended to modify this file in-place, because it will be +# overwritten during package upgrades. If you want to customize, the +# best way is to use systemctl edit: +# +# $ systemctl edit mysqld.service +# +# this will create file +# +# /etc/systemd/system/mysqld.service.d/override.conf +# +# which be parsed after the file mysqld.service itself is parsed. +# +# For example, if you want to increase mysql's open-files-limit to 20000 +# add following when editing with command above: +# +# [Service] +# LimitNOFILE=20000 +# +# Or if you require to execute pre and post scripts in the unit file as root, set +# PermissionsStartOnly=true +# +# For more info about custom unit files, see systemd.unit(5) or +# http://fedoraproject.org/wiki/Systemd#How_do_I_customize_a_unit_file.2F_add_a_custom_unit_file.3F +# +# Don't forget to reload systemd daemon after you change unit configuration: +# root> systemctl --system daemon-reload + +[Unit] +Description=MySQL 8.0 database server +After=syslog.target +After=network.target + +[Service] +Type=notify +User=mysql +Group=mysql + +ExecStartPre=/usr/libexec/mysql-check-socket +ExecStartPre=/usr/libexec/mysql-prepare-db-dir %n +# Note: we set --basedir to prevent probes that might trigger SELinux alarms, +# per bug #547485 +ExecStart=/usr/libexec/mysqld --defaults-file={$SERVER_PATH}/mysql-ya/etc/my.cnf --basedir=/usr --user=mysql +ExecStartPost=/usr/libexec/mysql-check-upgrade +ExecStopPost=/usr/libexec/mysql-wait-stop + +# Give a reasonable amount of time for the server to start up/shut down +TimeoutSec=300 + +# Place temp files in a secure directory, not /tmp +PrivateTmp=false + +Restart=on-failure + +RestartPreventExitStatus=1 + +# Sets open_files_limit +LimitNOFILE = 10000 + +# Set enviroment variable MYSQLD_PARENT_PID. This is required for SQL restart command. +Environment=MYSQLD_PARENT_PID=1 + +[Install] +WantedBy=multi-user.target diff --git a/plugins/mysql-yum/install.sh b/plugins/mysql-yum/install.sh new file mode 100755 index 000000000..591f8aff8 --- /dev/null +++ b/plugins/mysql-yum/install.sh @@ -0,0 +1,46 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") + + +# cd /www/server/mdserver-web/plugins/mysql-yum && bash install.sh install 8.0 +# cd /www/server/mdserver-web/plugins/mysql-yum && bash install.sh uninstall 8.0 +# cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/mysql-yum/index.py start 8.0 + +install_tmp=${rootPath}/tmp/mw_install.pl + + +action=$1 +type=$2 + + + +if [ "${2}" == "" ];then + echo '缺少安装脚本...' > $install_tmp + exit 0 +fi + +if [ ! -d $curPath/versions/$2 ];then + echo '缺少安装脚本2...' > $install_tmp + exit 0 +fi + +if [ "${action}" == "uninstall" ];then + + cd ${rootPath} && python3 plugins/mysql-yum/index.py stop ${type} + cd ${rootPath} && python3 plugins/mysql-yum/index.py initd_uninstall ${type} + cd $curPath +fi + +sh -x $curPath/versions/$2/install.sh $1 + +if [ "${action}" == "install" ];then +# #初始化 + cd ${rootPath} && python3 plugins/mysql-yum/index.py start ${type} + cd ${rootPath} && python3 plugins/mysql-yum/index.py initd_install ${type} +fi diff --git a/plugins/mysql-yum/js/mysql-yum.js b/plugins/mysql-yum/js/mysql-yum.js new file mode 100755 index 000000000..f1d5c44de --- /dev/null +++ b/plugins/mysql-yum/js/mysql-yum.js @@ -0,0 +1,1736 @@ +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:'mysql-yum', 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:'mysql-yum', 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-yum', 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 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, + shadeClose: true, + content: "
\ +
\ + 访问权限\ +
\ + \ +
\ +
\ +
\ + \ + \ +
\ +
", + }); + + layer.ready(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(""); + } + }); + + $('#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(); + } + }); + + $('#my_mod_save').click(function(){ + 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; + // console.log(data,dataObj); + myPost('set_db_access', dataObj, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + dbList(); + $('.layui-layer-close1').click(); + },{icon: rdata.status ? 1 : 2}); + }); + }); + }); +} + +function setDbPass(id, username, password){ + + var index = layer.open({ + type: 1, + skin: 'demo-class', + area: '500px', + title: '修改数据库密码', + closeBtn: 1, + shift: 5, + shadeClose: true, + content: "
\ +
\ + 用户名\ +
\ +
\ +
\ + 密码\ +
\ +
\ + \ +
\ + \ + \ +
\ +
", + }); + + $('#my_mod_close').click(function(){ + $('.layui-layer-close1').click(); + }); + + $('#my_mod_save').click(function(){ + var data = $("#mod_pwd").serialize(); + myPost('set_user_pwd', data, function(data){ + var rdata = $.parseJSON(data.data); + showMsg(rdata.msg,function(){ + dbList(); + $('.layui-layer-close1').click(); + },{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>=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']?'备份':'未备份') +' | '; + + list += '管理 | ' + + '工具 | ' + + '权限 | ' + + '改密 | ' + + '删除' + + ''; + 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 limitCon = '

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

错误日志

\ + \ +

' + $(".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); + }); + }); + + //清空日志 + $(".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").text(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: '
\ + \ +
\ +
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + ' + tbody + '\ +
表名引擎字符集行数大小操作
\ +
\ +
\ +
    \ +
  • 【修复】尝试使用REPAIR命令修复损坏的表,仅能做简单修复,若修复不成功请考虑使用myisamchk工具
  • \ +
  • 【优化】执行OPTIMIZE命令,可回收未释放的磁盘空间,建议每月执行一次
  • \ +
  • 【转为InnoDB/MyISAM】转换数据表引擎,建议将所有表转为InnoDB
  • \ +
' + }); + 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(){ + + + 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(); + } + }); + + $('#submit_add_master').click(function(){ + + var data = $("#add_master").serialize(); + data = decodeURIComponent(data); + var dataObj = str2Obj(data); + if(!dataObj['address']){ + dataObj['address'] = dataObj['dataAccess']; + } + // console.log(dataObj); + myPost('add_master_rep_slave_user', dataObj, 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 updateMasterRepSlaveUser(username){ + + + var index = layer.open({ + type: 1, + skin: 'demo-class', + 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); + // console.log(dataObj); + 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 loadOpen = layer.open({ + type: 1, + title: '同步命令', + area: '500px', + content:"
\ +
"+rdata.data+"
\ +
\ + \ +
\ +
", + }); + + copyPass(rdata.data); + $('.class-copy-cmd').click(function(){ + copyPass(rdata.data); + }); + }); +} + +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 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']+'\ + \ + 修改 | \ + 删除 | \ + 从库同步命令\ + \ + '; + } + + var page = '
'; + page += '
添加同步账户
'; + + var loadOpen = layer.open({ + type: 1, + title: '同步账户列表', + area: '500px', + content:"
\ +
\ +
\ + \ + " + list + "\ +
用户民密码操作
\ + "+page +"\ +
\ +
" + }); + + $('.dataTables_paginate_4').html(rdata['page']); + }); +} + + +function deleteSlave(){ + myPost('delete_slave', {}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata['msg']); + setTimeout(function(){ + masterOrSlaveConf(); + }, 3000); + + }); +} + + +function getFullSyncStatus(db){ + + var btn = '
开始
'; + var loadOpen = layer.open({ + type: 1, + title: '全量同步['+db+']', + area: '500px', + content:"
\ +
\ + \ +
\ +
0%
\ +
\ +
\ + "+btn+"\ +
" + }); + + var timeId = setInterval(function(){ + fullSync(db,0); + }, 1000); + + 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); + } + }); + } + + fullSync(db,0); + $('#begin_full_sync').click(function(){ + fullSync(db,1); + + timeId= setTimeout(function(){ + fullSync(db,0); + }, 1000); + }); + + $('.layui-layer-close1').click(function(){ + clearInterval(timeId); + }); +} + +function handlerRun(){ + cmd = 'cd /www/server/mdserver-web && python /www/server/mdserver-web/plugins/mysql/index.py do_full_sync {"db":"all"}'; + var loadOpen = layer.open({ + type: 1, + title: '手动执行', + area: '500px', + content:"
\ +
"+cmd+"
\ +
\ + \ +
\ +
", + }); + copyPass(cmd); + $('.class-copy-cmd').click(function(){ + copyPass(cmd); + }); +} + +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){ + 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 += '' + + '删除' + + ''; + 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); + 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); + }); + }); + + if (rdata.status){ + getMasterDbList(); + } + + if (rdata.data.slave_status){ + getAsyncMasterDbList(); + getAsyncDataList() + } + }); + } + getMasterStatus(); +} diff --git a/plugins/mysql-yum/scripts/backup.py b/plugins/mysql-yum/scripts/backup.py new file mode 100755 index 000000000..a5d7d51ed --- /dev/null +++ b/plugins/mysql-yum/scripts/backup.py @@ -0,0 +1,119 @@ +# 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() + '/mysql-ya' + 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) + + 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)) + u"]秒" + 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() + '/mysql-ya' + 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/mysql-yum/versions/5.7/install.sh b/plugins/mysql-yum/versions/5.7/install.sh new file mode 100755 index 000000000..1a8681346 --- /dev/null +++ b/plugins/mysql-yum/versions/5.7/install.sh @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +#!/bin/bash + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +#https://dev.mysql.com/downloads/mysql/5.7.html +#https://dev.mysql.com/downloads/file/?id=489855 + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") +sysName=`uname` + + +install_tmp=${rootPath}/tmp/mw_install.pl +mysqlDir=${serverPath}/source/mysql + + +_os=`uname` +if [ ${_os} == "Darwin" ]; then + OSNAME='macos' +elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then + OSNAME='centos' +elif grep -Eqi "Rocky" /etc/issue || grep -Eq "Rocky" /etc/*-release; then + OSNAME='rocky' +elif grep -Eqi "Red Hat Enterprise Linux Server" /etc/issue || grep -Eq "Red Hat Enterprise Linux Server" /etc/*-release; then + OSNAME='rhel' +elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun" /etc/*-release; then + OSNAME='aliyun' +elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then + OSNAME='fedora' +elif grep -Eqi "Amazon Linux AMI" /etc/issue || grep -Eq "Amazon Linux AMI" /etc/*-release; then + OSNAME='amazon' +elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then + OSNAME='debian' +elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then + OSNAME='ubuntu' +elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then + OSNAME='raspbian' +elif grep -Eqi "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then + OSNAME='deepin' +else + OSNAME='unknow' +fi + +VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'` + + + +YUM_INSTALL() +{ +####### +#http://repo.mysql.com/ + +if [ "${OSNAME}" == "centos" ] && [ "${VERSION_ID}" -le "7" ] ;then + wget -O /tmp/mysql57-community-release-el${VERSION_ID}.rpm http://repo.mysql.com/mysql57-community-release-el${VERSION_ID}.rpm + rpm -ivh /tmp/mysql57-community-release-el${VERSION_ID}.rpm + yum -y install mysql-server + rm -rf /tmp/mysql57-community-release-el${VERSION_ID}.rpm +fi +####### +} + +YUM_UNINSTALL() +{ +### YUM卸载 START ######## +yum remove -y mysql-server +### YUM卸载 END ######## +} + + + +Install_mysql() +{ + + echo '正在安装脚本文件...' > $install_tmp + + if id mysql &> /dev/null ;then + echo "mysql UID is `id -u mysql`" + echo "mysql Shell is `grep "^mysql:" /etc/passwd |cut -d':' -f7 `" + else + groupadd mysql + useradd -g mysql mysql + fi + + isYum=`which yum` + if [ "$isYum" != "" ];then + YUM_INSTALL + fi + + if [ "$?" == "0" ];then + mkdir -p $serverPath/mysql-yum + echo '5.7' > $serverPath/mysql-yum/version.pl + echo '安装完成' > $install_tmp + else + echo "暂时不支持该系统" > $install_tmp + fi +} + +Uninstall_mysql() +{ + isYum=`which yum` + if [ "$isYum" != "" ];then + YUM_UNINSTALL + fi + + + rm -rf $serverPath/mysql-yum + echo '卸载完成' > $install_tmp +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_mysql +else + Uninstall_mysql +fi diff --git a/plugins/mysql-yum/versions/8.0/install.sh b/plugins/mysql-yum/versions/8.0/install.sh new file mode 100755 index 000000000..4e033f508 --- /dev/null +++ b/plugins/mysql-yum/versions/8.0/install.sh @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +#!/bin/bash + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +#https://dev.mysql.com/downloads/mysql/5.7.html +#https://dev.mysql.com/downloads/file/?id=489855 + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") +sysName=`uname` + + +install_tmp=${rootPath}/tmp/mw_install.pl +mysqlDir=${serverPath}/source/mysql + + +_os=`uname` +if [ ${_os} == "Darwin" ]; then + OSNAME='macos' +elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then + OSNAME='centos' +elif grep -Eqi "Rocky" /etc/issue || grep -Eq "Rocky" /etc/*-release; then + OSNAME='rocky' +elif grep -Eqi "Red Hat Enterprise Linux Server" /etc/issue || grep -Eq "Red Hat Enterprise Linux Server" /etc/*-release; then + OSNAME='rhel' +elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun" /etc/*-release; then + OSNAME='aliyun' +elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then + OSNAME='fedora' +elif grep -Eqi "Amazon Linux AMI" /etc/issue || grep -Eq "Amazon Linux AMI" /etc/*-release; then + OSNAME='amazon' +elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then + OSNAME='debian' +elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then + OSNAME='ubuntu' +elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then + OSNAME='raspbian' +elif grep -Eqi "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then + OSNAME='deepin' +else + OSNAME='unknow' +fi + +VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'` + + + +YUM_INSTALL() +{ +####### + +if [ "${OSNAME}" == "centos" ];then + wget -O /tmp/mysql80-community-release.rpm http://repo.mysql.com/mysql80-community-release-el${VERSION}.rpm +else + wget -O /tmp/mysql80-community-release.rpm http://repo.mysql.com/mysql80-community-release-el8.rpm +fi +rpm -ivh /tmp/mysql80-community-release.rpm +yum -y install mysql-server + +rm -rf /tmp/mysql80-community-release.rpm +####### +} + +YUM_UNINSTALL() +{ +### YUM卸载 START ######## +yum -y remove mysql-server +### YUM卸载 END ######## +} + + +Install_mysql() +{ + + echo '正在安装脚本文件...' > $install_tmp + + if id mysql &> /dev/null ;then + echo "mysql UID is `id -u mysql`" + echo "mysql Shell is `grep "^mysql:" /etc/passwd |cut -d':' -f7 `" + else + groupadd mysql + useradd -g mysql mysql + fi + + isYum=`which yum` + if [ "$isYum" != "" ];then + YUM_INSTALL + fi + + + if [ "$?" == "0" ];then + mkdir -p $serverPath/mysql-yum + echo '8.0' > $serverPath/mysql-yum/version.pl + echo '安装完成' > $install_tmp + else + echo "暂时不支持该系统" > $install_tmp + fi +} + +Uninstall_mysql() +{ + isYum=`which yum` + if [ "$isYum" != "" ];then + YUM_UNINSTALL + fi + + + rm -rf $serverPath/mysql-ya + echo '卸载完成' > $install_tmp +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_mysql +else + Uninstall_mysql +fi