Compare commits

...
163 Commits
Author SHA1 Message Date
Mr Chen c17314b634 Merge pull request #434 from midoks/dev
MySQL,MariaDB数据库主从同步及多源同步
2023-08-10 11:32:24 +08:00
midoks 92a4b28fbf mariadb,mysql多源同步支持 2023-08-10 11:28:17 +08:00
midoks 733e4e81be update 2023-08-10 09:54:19 +08:00
midoks 8b99ae2515 update 2023-08-09 13:01:41 +08:00
midoks 2a72422402 update ad 2023-08-09 12:57:38 +08:00
midoks 145a259ef9 update 2023-08-09 08:57:49 +08:00
midoks a34b7719c8 update 2023-08-09 08:52:36 +08:00
midoks 4d98455c35 up 2023-08-08 21:17:49 +08:00
midoks c0c9def1fb Update index.py 2023-08-08 21:07:53 +08:00
midoks 02d8416466 update 2023-08-08 21:06:56 +08:00
midoks d505740269 Update index.py 2023-08-08 21:01:21 +08:00
midoks b1f6314df7 Update index.py 2023-08-08 16:54:17 +08:00
midoks 533653fe47 Update index.py 2023-08-08 16:48:21 +08:00
midoks dff4551fb1 update 2023-08-08 16:45:46 +08:00
midoks 79723149a5 Update install.sh 2023-08-08 16:32:07 +08:00
midoks 76da8a2ad5 Update install.sh 2023-08-08 16:25:40 +08:00
midoks 645538e633 Update index.py 2023-08-08 16:11:17 +08:00
midoks 1a1b4e9f3a Update index.py 2023-08-08 16:09:07 +08:00
midoks 3afde01f93 Update index.py 2023-08-08 16:07:44 +08:00
midoks a14db23971 Update index.py 2023-08-08 16:04:25 +08:00
midoks 316f06911b Update index.py 2023-08-08 16:01:34 +08:00
midoks 698d049314 up 2023-08-08 15:50:20 +08:00
midoks d397d74f73 Update index.py 2023-08-08 15:44:25 +08:00
midoks 8a7447a4ee Update mysql-apt.js 2023-08-08 15:37:45 +08:00
midoks 98414db41d update 2023-08-08 15:25:23 +08:00
midoks 7024185b59 Update my8.0.cnf 2023-08-08 14:52:57 +08:00
midoks 495f16f2cf Update mysql.js 2023-08-08 14:52:19 +08:00
midoks 62444b7b6d Update mysql.js 2023-08-08 14:51:59 +08:00
midoks 50b11457f7 update 2023-08-08 14:26:00 +08:00
midoks 393cbc3974 Merge branch 'master' into dev 2023-08-08 13:27:41 +08:00
midoks ce3bfc2ebd Merge branch 'master' into dev 2023-08-08 13:25:56 +08:00
Mr Chen b68e8f3650 Merge pull request #433 from midoks/midoks-patch-1
AD删除
2023-08-08 13:25:25 +08:00
Mr Chen 59a2765b2f AD删除 2023-08-08 13:24:29 +08:00
midoks 08c83edeb9 update 2023-08-08 13:17:39 +08:00
midoks c114e9aca8 Update index.py 2023-08-07 22:50:52 +08:00
midoks c5123268d0 Update index.py 2023-08-07 22:48:34 +08:00
midoks 54bbc3ff57 Update index.py 2023-08-07 22:39:24 +08:00
midoks 4658b991a9 Update index.py 2023-08-07 22:15:14 +08:00
midoks 52145e710b Update index.py 2023-08-07 22:05:01 +08:00
midoks 4acc48ded2 Update index.py 2023-08-07 22:04:00 +08:00
midoks 0d858f87ea Update index.py 2023-08-07 22:03:00 +08:00
midoks f37f08a9f5 Update index.py 2023-08-07 21:53:28 +08:00
midoks 0b5fc1de55 Update index.py 2023-08-07 21:52:53 +08:00
midoks 8748777101 Update index.py 2023-08-07 21:47:03 +08:00
midoks 48ed0b8034 Update index.py 2023-08-07 21:44:32 +08:00
midoks 41c9f6b7b6 Update mariadb.js 2023-08-07 21:24:42 +08:00
midoks c47336b65f update 2023-08-07 21:22:29 +08:00
midoks 24d7204ccc Update index.py 2023-08-07 21:05:22 +08:00
midoks 8c00fb8859 Update index.py 2023-08-07 20:42:08 +08:00
midoks c573b28f16 Update index.py 2023-08-07 20:41:11 +08:00
midoks afad548cf9 Update index.py 2023-08-07 20:22:26 +08:00
midoks 2605849de2 Update index.py 2023-08-07 20:02:18 +08:00
midoks 77598fa8a7 Update index.py 2023-08-07 19:44:47 +08:00
midoks b175ab735d Update index.py 2023-08-07 19:34:57 +08:00
midoks 54ed17ab8f Update index.py 2023-08-07 19:32:47 +08:00
midoks cadf72ea69 Update index.py 2023-08-07 17:53:33 +08:00
midoks dadb737f88 update 2023-08-07 15:59:00 +08:00
midoks fef2acf683 Update index.py 2023-08-07 15:56:59 +08:00
midoks 4b6dbf8887 Update mariadb.js 2023-08-07 15:46:10 +08:00
midoks 06c99e1cc1 Update index.py 2023-08-07 15:26:54 +08:00
midoks afb3e920f8 mariadb多住一从功能 2023-08-07 15:10:38 +08:00
midoks 2c346c9850 Update my.cnf 2023-08-06 14:38:47 +08:00
midoks 5b6c5be288 Update mariadb.js 2023-08-06 00:43:24 +08:00
midoks 63bd806222 Update index.py 2023-08-06 00:25:22 +08:00
midoks afe3848b71 update 2023-08-05 21:34:04 +08:00
midoks cd361ec7ec Update install.sh 2023-08-05 21:33:14 +08:00
midoks eb399fe799 Update install.sh 2023-08-05 21:32:25 +08:00
midoks 53e588b6fc Update install.sh 2023-08-05 21:31:58 +08:00
Mr Chen 612c104cca Merge pull request #432 from midoks/dev
PHP - libzip库修复
2023-08-05 17:35:09 +08:00
midoks 550ca7681a Update libzip.sh 2023-08-05 17:31:16 +08:00
midoks 6a09706362 Update libzip.sh 2023-08-05 17:30:26 +08:00
midoks ca040e8986 Update install.sh 2023-08-05 17:23:52 +08:00
midoks 6fcc980d5d Update libzip.sh 2023-08-05 17:19:39 +08:00
midoks b69adc9c7d Update libzip.sh 2023-08-05 17:09:10 +08:00
midoks 67da343705 Update libzip.sh 2023-08-05 17:05:48 +08:00
midoks 4b47e27a54 Update libzip.sh 2023-08-05 17:01:05 +08:00
midoks fba3ddc9a5 Update libzip.sh 2023-08-05 16:44:39 +08:00
Mr Chen 4769ce5be8 Merge pull request #431 from midoks/dev
0.15.2
2023-08-05 15:12:37 +08:00
midoks 8e16cbf7f9 0.15.2 2023-08-05 15:06:22 +08:00
midoks 4225d4c040 Update common.py 2023-08-05 14:43:14 +08:00
midoks b578f2fddc Update common.py 2023-08-05 14:42:43 +08:00
midoks 961c3423fd Update common.py 2023-08-05 14:29:52 +08:00
midoks 8040c8c67a Update common.py 2023-08-05 14:21:25 +08:00
midoks 5aca7d7c26 Update common.py 2023-08-05 14:17:16 +08:00
midoks d9f99e6b7c Update common.py 2023-08-05 14:17:01 +08:00
midoks 3addb46708 Update common.py 2023-08-05 13:46:19 +08:00
midoks e6b493237d 优化初始化安装SSH端口识别 2023-08-05 13:36:13 +08:00
midoks 7f42054a14 Update ubuntu.sh 2023-08-05 12:29:39 +08:00
midoks 501af3da15 Update plugins_api.py 2023-08-05 12:01:46 +08:00
midoks 68727cbe91 Update site_api.py 2023-08-05 11:28:33 +08:00
midoks c5207961f3 Update index.py 2023-08-05 01:52:49 +08:00
midoks a04e05c7e8 Update index.py 2023-08-05 01:19:42 +08:00
midoks 5b8cca24aa Update index.py 2023-08-05 00:46:41 +08:00
midoks cafe58f3fc Update index.py 2023-08-05 00:45:04 +08:00
midoks d1e2781eb9 Update index.py 2023-08-05 00:44:48 +08:00
midoks 67c899fc84 Update index.py 2023-08-05 00:43:06 +08:00
midoks 7432548ff9 Update index.py 2023-08-05 00:24:35 +08:00
midoks 0c2c136097 Update index.py 2023-08-04 23:58:21 +08:00
midoks 2a7e21951b Update my8.0.cnf 2023-08-04 22:49:18 +08:00
midoks 066185e404 网站设置反向代理升级功能 2023-08-04 20:27:20 +08:00
midoks bd431f1647 docker阶段性完成 2023-08-03 18:37:14 +08:00
midoks 0a6e88d81d update 2023-08-03 17:00:12 +08:00
midoks 02c9988ef7 Update docker.js 2023-08-03 00:24:13 +08:00
midoks 5ee7df4a46 Update nginx.conf 2023-08-03 00:14:16 +08:00
midoks 5f382c0034 update 2023-08-03 00:06:01 +08:00
midoks 63d17c4d77 Update docker.js 2023-08-02 23:24:10 +08:00
midoks 38722c1dc2 Update index.py 2023-08-02 17:51:29 +08:00
midoks ea982b7261 Update README.md 2023-08-02 17:50:22 +08:00
midoks 73d9edced8 使用mariadb二进制导入备份文件 2023-08-02 17:36:27 +08:00
midoks af03c004a3 Update rsyncd.js 2023-08-02 15:35:30 +08:00
midoks ddd9e70ac2 Update rsyncd.js 2023-08-02 15:29:32 +08:00
midoks 8976a7a147 Update rsyncd.js 2023-08-02 15:26:55 +08:00
midoks 677ff8ec0c Update README.md 2023-08-02 15:10:42 +08:00
midoks 47d240e2b8 rsyncd添加优化 2023-08-02 15:10:23 +08:00
midoks 1f7bd76875 Update crontab_api.py 2023-08-02 14:27:04 +08:00
midoks f04c70f022 计划任务自动脚本运行时间 2023-08-02 14:04:00 +08:00
midoks 5044cc5db9 Update README.md 2023-08-02 00:06:51 +08:00
midoks 4329b90ac4 Update info.json 2023-08-01 23:58:10 +08:00
midoks f7873b6dcd Update init_cmd.py 2023-07-25 00:03:20 +08:00
midoks a80d666786 update 2023-07-24 23:52:38 +08:00
Mr Chen 0598704dce Merge pull request #428 from midoks/dev
修复centos9源安装问题
2023-07-22 12:54:17 +08:00
midoks 8f19a05755 Update rhel.sh 2023-07-22 12:53:07 +08:00
midoks f320d7cc69 Update rhel.sh 2023-07-22 12:26:56 +08:00
midoks 1e97929a24 Update push_notice_msg.py 2023-07-21 12:10:55 +08:00
Mr Chen c66bbac97e Merge pull request #427 from midoks/dev
python3.7 urllib3在亚马逊降级
2023-07-20 16:14:22 +08:00
midoks 1f7a0d2795 Create r3.7.txt 2023-07-20 16:04:18 +08:00
midoks f05ce79e63 Update rhel.sh 2023-07-20 15:55:11 +08:00
midoks 9f3d06191a PHP提示优化 2023-07-19 18:35:27 +08:00
Mr Chen 2c6614a5ff Merge pull request #426 from midoks/dev
赞助换域名
2023-07-18 15:23:49 +08:00
midoks 905bad29cf Update README.md 2023-07-18 15:22:19 +08:00
midoks 9ba572a8ce AD修改 2023-07-16 17:23:45 +08:00
Mr Chen 85fc333d2c Merge pull request #424 from midoks/dev
0.15.1
2023-07-15 23:04:39 +08:00
midoks 5bc27a4725 Update config_api.py 2023-07-15 22:53:38 +08:00
midoks e5acf206f5 Update cli.sh 2023-07-15 20:43:13 +08:00
midoks ae7afc2eb5 Update rhel.sh 2023-07-15 20:34:46 +08:00
midoks 5c8527a5de 监控页面-自定义时间优化。 2023-07-15 19:33:17 +08:00
midoks 274592229e Update rhel.sh 2023-07-15 15:51:03 +08:00
midoks 60ddb13f8e Update rhel.sh 2023-07-15 15:50:35 +08:00
midoks f62af00fb7 Update rhel.sh 2023-07-15 15:49:28 +08:00
midoks 9c6faefffd Update rhel.sh 2023-07-15 15:38:14 +08:00
midoks c9e27c2add 优化
* [插件]docker - 添加IP地址池。
* PHP下载中国优化。
2023-07-15 15:00:00 +08:00
midoks 97b1e8b9b3 Update rhel.sh 2023-07-15 12:34:47 +08:00
midoks 18cdcd1436 修复子目录绑定-伪静态问题。 2023-07-13 10:36:16 +08:00
midoks 7d783c64b6 OP防火墙优化
站点配置-状态关闭后,不再防御。
2023-07-13 00:40:46 +08:00
midoks 0b65d69750 Update __init__.py 2023-07-12 22:18:55 +08:00
midoks 693dbb8cf1 Update __init__.py 2023-07-12 22:17:58 +08:00
midoks 117a99e729 增加标识 2023-07-12 09:46:58 +08:00
midoks 45d4b8a5de update 2023-07-11 16:25:34 +08:00
midoks a5791051b1 Update debian.sh 2023-07-11 16:11:20 +08:00
midoks dc3f8f8e0b 自动同步gitee 2023-07-11 12:21:48 +08:00
midoks bf1d00c012 Update config_api.py 2023-07-10 22:41:13 +08:00
midoks 51cf851cea Update site.js 2023-07-10 22:38:37 +08:00
midoks 1e09408eb9 Update index.py 2023-07-10 22:13:46 +08:00
midoks 7659865caf Update lib.sh 2023-07-05 22:19:44 +08:00
Mr Chen ad1851d068 Merge pull request #423 from midoks/dev
requests兼容低版本
2023-07-05 18:05:33 +08:00
midoks e174652afc Update requirements.txt 2023-07-05 18:02:40 +08:00
midoks a95e7aacd7 Update r3.6.txt 2023-07-05 18:00:36 +08:00
Mr Chen 6aa638ef9a Merge pull request #422 from midoks/dev
Update requirements.txt
2023-07-05 13:03:14 +08:00
midoks 6f3d50bae5 Update requirements.txt 2023-07-05 13:01:08 +08:00
Mr Chen 301a5a95b8 Merge pull request #421 from midoks/dev
AD
2023-07-05 12:51:37 +08:00
midoks d35b9dccc7 AD信息 2023-07-05 12:49:47 +08:00
midoks 82680605ac mvirtua ad 2023-07-05 12:47:05 +08:00
midoks 5b148b3d1a Update requirements.txt 2023-07-05 10:20:04 +08:00
97 changed files with 3650 additions and 1951 deletions
+16
View File
@@ -0,0 +1,16 @@
name: sync2gitee
on: [push]
jobs:
repo-sync:
runs-on: ubuntu-latest
steps:
- name: Mirror the Github organization repos to Gitee.
uses: Yikun/hub-mirror-action@master
with:
src: 'github/midoks'
dst: 'gitee/midoks'
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
dst_token: ${{ secrets.GITEE_TOKEN }}
static_list: "mdserver-web"
force_update: true
+9 -9
View File
@@ -79,7 +79,7 @@ PHP[72-82]支持phpMyAdmin[5.2.0]
# 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.la/)
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.pw/)
# AD - VPS推荐 - 🙏
@@ -99,15 +99,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.15.0
### 版本更新 0.15.2
* debian12适配。
* 添加nezha插件。
* 优化域名ssl保存功能。
* 修复PHP扩展intl不加载问题(debian/ubuntu)。
* 修复redhat安装openresty缺少openssl-devel。
* docker插件-将就能用。
* tgbot接收和push任务分离。
* OpenResty升级到1.21.4.2
* 计划任务自动脚本运行时间
* rsyncd添加优化
* 使用mariadb二进制导入备份文件
* docker插件-镜像导入导出功能
* 网站设置反向代理升级功能
* 优化初始化安装SSH端口识别
### JSDelivr安装地址
+12
View File
@@ -33,6 +33,7 @@ from flask import redirect
def init():
initDB()
initDBSshPort()
initUserInfo()
initInitD()
initInitTask()
@@ -62,6 +63,17 @@ def initDB():
print(str(ex))
def initDBSshPort():
# SSH端口必须放开
import firewall_api
cmd_data = mw.execShell(
"cat /etc/ssh/sshd_config | grep '^Port \d*' | tail -1")
ssh_port = cmd_data[0].replace("Port ", '').strip()
if ssh_port == '':
ssh_port = '22'
firewall_api.firewall_api().addAcceptPortArgs(ssh_port, 'SSH远程管理服务', 'port')
def doContentReplace(src, dst):
content = mw.readFile(src)
content = content.replace("{$SERVER_PATH}", mw.getRunDir())
+1 -1
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api:
__version = '0.15.0'
__version = '0.15.3'
__api_addr = 'data/api.json'
def __init__(self):
+21 -2
View File
@@ -508,6 +508,22 @@ class crontab_api:
else:
head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n"
start_head = '''
SCRIPT_RUN_TIME="0s"
MW_ToSeconds()
{
SEC=$1
if [ $SEC -lt 60 ]; then
SCRIPT_RUN_TIME="${SEC}s"
elif [ $SEC -ge 60 ] && [ $SEC -lt 3600 ];then
SCRIPT_RUN_TIME="$(( SEC / 60 ))m$(( SEC % 60 ))s"
elif [ $SEC -ge 3600 ]; then
SCRIPT_RUN_TIME="$(( SEC / 3600 ))h$(( (SEC % 3600) / 60 ))m$(( (SEC % 3600) % 60 ))s"
fi
}
START_MW_SHELL_TIME=`date +%s`
'''
source_bin_activate = '''
export LANG=en_US.UTF-8
MW_PATH=%s/bin/activate
@@ -515,7 +531,7 @@ if [ -f $MW_PATH ];then
source $MW_PATH
fi''' % (mw.getRunDir(),)
head = head + source_bin_activate + "\n"
head = head + start_head + source_bin_activate + "\n"
log = '.log'
script_dir = mw.getRunDir() + "/scripts"
@@ -557,7 +573,10 @@ fi''' % (mw.getRunDir(),)
shell += '''
echo "----------------------------------------------------------------------------"
endDate=`date +"%Y-%m-%d %H:%M:%S"`
echo "★[$endDate] Successful"
END_MW_SHELL_TIME=`date +"%s"`
((SHELL_COS_TIME=($END_MW_SHELL_TIME-$START_MW_SHELL_TIME)))
MW_ToSeconds $SHELL_COS_TIME
echo "★[$endDate] Successful | Script Run [$SCRIPT_RUN_TIME] "
echo "----------------------------------------------------------------------------"
'''
cronPath = mw.getServerDir() + '/cron'
+6
View File
@@ -1215,6 +1215,12 @@ def formatDate(format="%Y-%m-%d %H:%M:%S", times=None):
return time.strftime(format, time_local)
def strfToTime(sdate):
# 转换时间
import time
return time.strftime('%Y-%m-%d', time.strptime(sdate, '%b %d %H:%M:%S %Y %Z'))
def checkIp(ip):
# 检查是否为IPv4地址
import re
+1 -1
View File
@@ -139,7 +139,7 @@ class plugins_api:
def initApi(self):
plugin_names = {
'openresty': '1.21.4.1',
'openresty': '1.21.4.2',
'php': '56',
'swap': '1.1',
'mysql': '5.7',
+105 -51
View File
@@ -1435,6 +1435,8 @@ class site_api:
data['data'] = mw.readFile(filename)
data['rlist'] = []
for ds in os.listdir(self.rewritePath):
if ds[0:1] == '.':
continue
if ds == 'list.txt':
continue
data['rlist'].append(ds[0:len(ds) - 5])
@@ -1868,19 +1870,16 @@ class site_api:
if _id == '' or _siteName == '':
return mw.returnJson(False, "必填项不能为空!")
_old_config = mw.readFile(
"{}/{}/{}.conf".format(self.proxyPath, _siteName, _id))
if _old_config == False:
return mw.returnJson(False, "非法操作")
mw.writeFile("{}/{}/{}.conf".format(self.proxyPath,
_siteName, _id), _config)
proxy_file = "{}/{}/{}.conf".format(self.proxyPath, _siteName, _id)
mw.backFile(proxy_file)
mw.writeFile(proxy_file, _config)
rule_test = mw.checkWebConfig()
if rule_test != True:
mw.writeFile("{}/{}/{}.conf".format(self.proxyPath,
_siteName, _id), _old_config)
mw.restoreFile(proxy_file)
mw.removeBackFile(proxy_file)
return mw.returnJson(False, "OpenResty 配置测试不通过, 请重试: {}".format(rule_test))
mw.removeBackFile(proxy_file)
self.operateRedirectConf(_siteName, 'start')
mw.restartWeb()
return mw.returnJson(True, "ok")
@@ -1921,21 +1920,20 @@ class site_api:
_from = request.form.get('from', '')
_to = request.form.get('to', '')
_host = request.form.get('host', '')
_name = request.form.get('name', '')
_open_proxy = request.form.get('open_proxy', '')
_open_cache = request.form.get('open_cache', '')
_cache_time = request.form.get('cache_time', '')
_id = request.form.get('id', '')
if _siteName == "" or _from == "" or _to == "" or _host == "":
# print(_name, _siteName, _from, _to, _host)
if _name == "" or _siteName == "" or _from == "" or _to == "" or _host == "":
return mw.returnJson(False, "必填项不能为空")
data_path = self.getProxyDataPath(_siteName)
data_content = mw.readFile(
data_path) if os.path.exists(data_path) else ""
data = json.loads(data_content) if data_content != "" else []
rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
if not re.match(rep, _to):
return mw.returnJson(False, "错误的目标地址!")
# _to = _to.strip("/")
# get host from url
try:
if _host == "$host":
@@ -1944,7 +1942,11 @@ class site_api:
except:
return mw.returnJson(False, "错误的目标地址")
# location ~* ^{from}(.*)$ {
proxy_site_path = self.getProxyDataPath(_siteName)
data_content = mw.readFile(
proxy_site_path) if os.path.exists(proxy_site_path) else ""
data = json.loads(data_content) if data_content != "" else []
tpl = "#PROXY-START\n\
location ^~ {from} {\n\
proxy_pass {to};\n\
@@ -1952,12 +1954,29 @@ location ^~ {from} {\n\
proxy_set_header X-Real-IP $remote_addr;\n\
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\
proxy_set_header REMOTE-HOST $remote_addr;\n\
proxy_set_header Upgrade $http_upgrade;\n\
proxy_set_header Connection $connection_upgrade;\n\
proxy_http_version 1.1;\n\
\n\
add_header X-Cache $upstream_cache_status;\n\
proxy_ignore_headers Set-Cookie Cache-Control expires;\n\
add_header Cache-Control no-cache;\n\
\n\
set $static_files_app 0;\n\
{proxy_cache}\n\
}\n\
# PROXY-END"
tpl_proxy_cache = "\n\
if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\
{\n\
expires {cache_time}m;\n\
}\n\
proxy_ignore_headers Set-Cookie Cache-Control expires;\n\
proxy_cache mw_cache;\n\
proxy_cache_key \"$host$uri$is_args$args\";\n\
proxy_cache_valid 200 304 301 302 {cache_time}m;\n\
"
tpl_proxy_nocache = "\n\
set $static_files_app 0; \n\
if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\
{\n\
set $static_files_app 1;\n\
@@ -1967,8 +1986,7 @@ location ^~ {from} {\n\
{\n\
add_header Cache-Control no-cache;\n\
}\n\
}\n\
#PROXY-END"
"
# replace
if _from[0] != '/':
@@ -1976,28 +1994,69 @@ location ^~ {from} {\n\
tpl = tpl.replace("{from}", _from, 999)
tpl = tpl.replace("{to}", _to)
tpl = tpl.replace("{host}", _host, 999)
tpl = tpl.replace("{cache_time}", _cache_time, 999)
_id = mw.md5("{}+{}+{}".format(_from, _to, _siteName))
for item in data:
if item["id"] == _id:
return mw.returnJson(False, "已存在该规则!")
if item["from"] == _from:
return mw.returnJson(False, "代理目录已存在!")
data.append({
"from": _from,
"to": _to,
"host": _host,
"id": _id
})
if _open_cache == 'on':
tpl_proxy_cache = tpl_proxy_cache.replace(
"{cache_time}", _cache_time, 999)
tpl = tpl.replace("{proxy_cache}", tpl_proxy_cache, 999)
else:
tpl = tpl.replace("{proxy_cache}", tpl_proxy_nocache, 999)
proxy_action = 'add'
if _id == "":
_id = mw.md5("{}".format(_name))
else:
proxy_action = 'edit'
conf_proxy = "{}/{}.conf".format(self.getProxyPath(_siteName), _id)
conf_bk = "{}/{}.conf.txt".format(self.getProxyPath(_siteName), _id)
mw.writeFile(conf_proxy, tpl)
rule_test = mw.checkWebConfig()
if rule_test != True:
os.remove(conf_proxy)
return mw.returnJson(False, "OpenResty配置测试不通过, 请重试: {}".format(rule_test))
if proxy_action == "add":
# 添加代理
_id = mw.md5("{}".format(_name))
for item in data:
if item["name"] == _name:
return mw.returnJson(False, "名称重复!")
if item["from"] == _from:
return mw.returnJson(False, "代理目录已存在!")
data.append({
"name": _name,
"from": _from,
"to": _to,
"host": _host,
"open_cache": _open_cache,
"open_proxy": _open_proxy,
"cache_time": _cache_time,
"id": _id,
})
else:
# 修改代理
dindex = -1
for x in range(len(data)):
if data[x]["id"] == _id:
dindex = x
break
if dindex < 0:
return mw.returnJson(False, "异常请求")
data[dindex]['from'] = _from
data[dindex]['to'] = _to
data[dindex]['host'] = _host
data[dindex]['open_cache'] = _open_cache
data[dindex]['open_proxy'] = _open_proxy
data[dindex]['cache_time'] = _cache_time
conf_file = "{}/{}.conf".format(self.getProxyPath(_siteName), _id)
if _open_proxy != 'on':
conf_file = "{}/{}.conf.txt".format(
self.getProxyPath(_siteName), _id)
mw.writeFile(data_path, json.dumps(data))
mw.writeFile(conf_file, tpl)
os.rename(conf_proxy, conf_bk)
mw.writeFile(proxy_site_path, json.dumps(data))
self.operateProxyConf(_siteName, 'start')
mw.restartWeb()
return mw.returnJson(True, "ok", {"hash": _id})
@@ -2028,10 +2087,10 @@ location ^~ {from} {\n\
self.getProxyPath(_siteName), _id)
mw.execShell(cmd)
except:
return mw.returnJson(False, "删除失败!")
return mw.returnJson(False, "删除反代失败!")
mw.restartWeb()
return mw.returnJson(True, "删除成功!")
return mw.returnJson(True, "删除反代成功!")
def getSiteTypesApi(self):
# 取网站分类
@@ -2098,7 +2157,7 @@ location ^~ {from} {\n\
##### ----- end ----- ###
# 域名编码转换
# 域名编码转换
def toPunycode(self, domain):
import re
if sys.version_info[0] == 2:
@@ -2106,7 +2165,7 @@ location ^~ {from} {\n\
tmp = domain.split('.')
newdomain = ''
for dkey in tmp:
# 匹配非ascii字符
# 匹配非ascii字符
match = re.search(u"[\x80-\xff]+", dkey)
if not match:
newdomain += dkey + '.'
@@ -2661,7 +2720,7 @@ location ^~ {from} {\n\
mw.writeLog('TYPE_SITE', '设置成功,站点到期后将自动停止!', (siteName, edate))
return mw.returnJson(True, '设置成功,站点到期后将自动停止!')
# ssl相关方法 start
# ssl相关方法 start
def setSslConf(self, siteName):
file = self.getHostConf(siteName)
conf = mw.readFile(file)
@@ -2760,9 +2819,4 @@ location ^~ {from} {\n\
mw.execShell("chattr +i " + filename)
return mw.returnJson(True, '已打开防跨站设置!')
# 转换时间
def strfToTime(self, sdate):
import time
return time.strftime('%Y-%m-%d', time.strptime(sdate, '%b %d %H:%M:%S %Y %Z'))
# ssl相关方法 end
# ssl相关方法 end
+10
View File
@@ -755,6 +755,8 @@ class system_api:
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
P_VER=`python3 -V | awk '{print $2}'`
if [ ! -f /www/server/mdserver-web/bin/activate ];then
cd /www/server/mdserver-web && python3 -m venv .
cd /www/server/mdserver-web && source /www/server/mdserver-web/bin/activate
@@ -769,6 +771,14 @@ if [ ! -z "$cn" ];then
fi
cd /www/server/mdserver-web && pip3 install -r /www/server/mdserver-web/requirements.txt -i $PIPSRC
P_VER_D=`echo "$P_VER"|awk -F '.' '{print $1}'`
P_VER_M=`echo "$P_VER"|awk -F '.' '{print $2}'`
NEW_P_VER=${P_VER_D}.${P_VER_M}
if [ -f /www/server/mdserver-web/version/r${NEW_P_VER}.txt ];then
cd /www/server/mdserver-web && pip3 install -r /www/server/mdserver-web/version/r${NEW_P_VER}.txt -i $PIPSRC
fi
'''
os.system(update_env)
self.restartMw()
+2 -2
View File
@@ -16,7 +16,7 @@ mw_start_task()
{
isStart=$(ps aux |grep 'task.py'|grep -v grep|awk '{print $2}')
if [ "$isStart" == '' ];then
echo -e "Starting mw-tasks... \c"
echo -e "starting mw-tasks... \c"
cd $DIR && python3 task.py >> ${DIR}/logs/task.log 2>&1 &
sleep 0.3
isStart=$(ps aux |grep 'task.py'|grep -v grep|awk '{print $2}')
@@ -30,7 +30,7 @@ mw_start_task()
fi
echo -e "\033[32mdone\033[0m"
else
echo "Starting mw-tasks... mw-tasks (pid $(echo $isStart)) already running"
echo "starting mw-tasks... mw-tasks (pid $(echo $isStart)) already running"
fi
}
+2 -3
View File
@@ -46,9 +46,8 @@ CREATE TABLE IF NOT EXISTS `firewall` (
INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES
(1, '80', '网站默认端口', '0000-00-00 00:00:00'),
(2, '22', 'SSH远程管理服务', '0000-00-00 00:00:00'),
(3, '443', 'HTTPS', '0000-00-00 00:00:00'),
(4, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
(2, '443', 'HTTPS', '0000-00-00 00:00:00'),
(3, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
+2 -9
View File
@@ -39,20 +39,13 @@ server
allow all;
}
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
{
expires 30d;
error_log off;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\\.(js|css)?$
{
expires 12h;
error_log off;
access_log /dev/null;
}
access_log {$LOGPATH}/{$SERVER_NAME}.log main;
error_log {$LOGPATH}/{$SERVER_NAME}.error.log;
}
+3 -10
View File
@@ -35,18 +35,11 @@ server
allow all;
}
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
{
expires 30d;
error_log off;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\\.(js|css)?$
{
expires 12h;
error_log off;
access_log /dev/null;
expires 30d;
}
access_log {$LOGPATH}/{$SERVER_MAIN}_{$DIRBIND}.log;
+2
View File
@@ -40,6 +40,8 @@
<p onclick="pluginInitD('docker');">自启动</p>
<p onclick="dockerConList();">容器列表</p>
<p onclick="dockerImageList();">镜像列表</p>
<p onclick="dockerImageOutput();">镜像导出</p>
<p onclick="dockerIpList();">IP地址池</p>
<p onclick="repoList();">仓库</p>
</div>
<div class="bt-w-con pd15">
+193 -2
View File
@@ -429,6 +429,92 @@ def dockerRemoveImage():
return mw.returnJson(False, '删除失败, 当前镜像正在使用!')
def getImageListFunc(dbname=''):
bkDir = mw.getRootDir() + '/backup/docker'
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 dockerImagePickDir():
bkDir = mw.getRootDir() + '/backup/docker'
return mw.returnJson(True, 'ok', bkDir)
def dockerImagePickList():
bkDir = mw.getRootDir() + '/backup/docker'
if not os.path.exists(bkDir):
os.mkdir(bkDir)
r = os.listdir(bkDir)
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 dockerImagePickSave():
# image 导出
args = getArgs()
data = checkArgs(args, ['images'])
if not data[0]:
return data[1]
bkDir = mw.getRootDir() + '/backup/docker/'
images = args['images']
try:
file_name = bkDir + \
str(time.strftime('%Y%m%d_%H%M%S', time.localtime())) + '.tar.gz'
mw.execShell('docker image save %s | gzip > %s' %
(images, file_name))
return mw.returnJson(True, '导出镜像 {} 成功!'.format(file_name))
except docker.errors.APIError as ex:
return mw.returnJson(False, '操作失败: ' + str(ex))
def dockerImagePickLoad():
# 镜像文件导入
args = getArgs()
data = checkArgs(args, ['file'])
if not data[0]:
return data[1]
try:
file_path = args['file']
if not os.path.exists(file_path):
return mw.returnJson(False, '文件不存在')
if file_path.endswith('.tar'):
mw.execShell('docker image load < %s' % file_path)
elif file_path.endswith('.tar.gz'):
mw.execShell('gunzip -c %s | docker image load' % file_path)
else:
return mw.returnJson(False, '不支持改文件类型!')
return mw.returnJson(True, '导入镜像文件成功!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '操作失败: ' + str(ex))
def dockerLoginCheck(user_name, user_pass, registry):
# 登陆验证
cmd = 'docker login -u=%s -p %s %s' % (user_name, user_pass, registry)
@@ -443,7 +529,7 @@ def dockerLoginCheck(user_name, user_pass, registry):
return False
def getDockerIpList():
def getDockerIpListData():
# 取IP列表
path = getServerDir()
ipConf = path + '/iplist.json'
@@ -453,13 +539,63 @@ def getDockerIpList():
return iplist
def getDockerIpList():
data = getDockerIpListData()
return mw.returnJson(True, 'ok!', data)
def dockerAddIP():
# 添加IP
args = getArgs()
data = checkArgs(args, ['address', 'netmask', 'gateway'])
if not data[0]:
return data[1]
path = getServerDir()
ipConf = path + '/iplist.json'
if not os.path.exists(ipConf):
iplist = []
mw.writeFile(ipConf, json.dumps(iplist))
iplist = json.loads(mw.readFile(ipConf))
ipInfo = {
'address': args['address'],
'netmask': args['netmask'],
'gateway': args['gateway'],
}
iplist.append(ipInfo)
mw.writeFile(ipConf, json.dumps(iplist))
return mw.returnJson(True, '添加成功!')
def dockerDelIP():
# 删除IP
args = getArgs()
data = checkArgs(args, ['address'])
if not data[0]:
return data[1]
path = getServerDir()
ipConf = path + '/iplist.json'
if not os.path.exists(ipConf):
return mw.returnJson(False, '指定的IP不存在。!')
iplist = json.loads(mw.readFile(ipConf))
newList = []
for ipInfo in iplist:
if ipInfo['address'] == args['address']:
continue
newList.append(ipInfo)
mw.writeFile(ipConf, json.dumps(newList))
return mw.returnJson(True, '成功删除!')
def getDockerCreateInfo():
# 取创建依赖
import psutil
data = {}
data['images'] = imageList()
data['memSize'] = int(psutil.virtual_memory().total / 1024 / 1024)
data['iplist'] = getDockerIpList()
data['iplist'] = getDockerIpListData()
return mw.returnJson(True, 'ok!', data)
@@ -473,6 +609,45 @@ def __release_port(port):
return "Release failed {}".format(e)
def dockerPortCheck():
args = getArgs()
data = checkArgs(args, ['port'])
if not data[0]:
return data[1]
port = args['port']
is_ok = IsPortExists(port)
if is_ok:
return mw.returnJson(True, 'ok')
return mw.returnJson(False, 'fail')
def IsPortExists(port):
# 判断端口是否被占用
ret = __check_dst_port(ip='localhost', port=port)
ret2 = __check_dst_port(ip='0.0.0.0', port=port)
if ret:
return ret
if not ret and ret2:
return ret2
if not ret and not ret2:
return False
def __check_dst_port(ip, port, timeout=3):
# 端口检测
import socket
ok = True
try:
s = socket.socket()
s.settimeout(timeout)
s.connect((ip, port))
s.close()
except:
ok = False
return ok
def dockerCreateCon():
args = getArgs()
data = checkArgs(args, ['environments', 'command',
@@ -653,12 +828,28 @@ if __name__ == "__main__":
print(dockerPullReg())
elif func == 'image_list':
print(imageListData())
elif func == 'image_pick_dir':
print(dockerImagePickDir())
elif func == 'image_pick_save':
print(dockerImagePickSave())
elif func == 'image_pick_load':
print(dockerImagePickLoad())
elif func == 'image_pick_list':
print(dockerImagePickList())
elif func == 'docker_get_iplist':
print(getDockerIpList())
elif func == 'docker_del_ip':
print(dockerDelIP())
elif func == 'docker_add_ip':
print(dockerAddIP())
elif func == 'get_docker_create_info':
print(getDockerCreateInfo())
elif func == 'docker_create_con':
print(dockerCreateCon())
elif func == 'docker_remove_image':
print(dockerRemoveImage())
elif func == 'docker_port_check':
print(dockerPortCheck())
elif func == 'docker_login':
print(dockerLogin())
elif func == 'docker_logout':
+1 -1
View File
@@ -1,6 +1,6 @@
{
"sort": 7,
"ps": "Docker 是一个开源的应用容器引擎(开发测试中)",
"ps": "Docker是一个开源的应用容器引擎",
"name": "docker",
"title": "Docker",
"shell": "install.sh",
File diff suppressed because it is too large Load Diff
+1
View File
@@ -65,6 +65,7 @@ binlog-ignore-db = performance_schema
#slave
log-slave-updates
slave_skip_errors=1062
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
+2 -7
View File
@@ -2,7 +2,7 @@
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<script type="text/javascript">console.log($('.plugin_version').attr('version'));</script>
<!-- <script type="text/javascript">console.log($('.plugin_version').attr('version'));</script> -->
<p class="bgw" onclick="pluginService('mariadb', $('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('mariadb', $('.plugin_version').attr('version'));">自启动</p>
<p onclick="pluginConfig('mariadb', $('.plugin_version').attr('version'));">配置文件</p>
@@ -15,14 +15,12 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<style type="text/css">
.db_list{
padding: 0px 0 10px 0;
@@ -52,10 +50,7 @@
</style>
<script type="text/javascript">
resetPluginWinWidth(800);
var loading = layer.msg("资源加载中...", { icon: 16, time: 0, shade: 0.3 });
$.getScript( "/plugins/file?name=mariadb&f=js/mariadb.js", function(){
layer.close(loading);
pluginService('mariadb',$('.plugin_version').attr('version'));
});
</script>
+260 -205
View File
@@ -48,19 +48,19 @@ def getInitDFile():
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = args[0].strip('{').strip('}').strip()
if (t == ''):
return tmp
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
@@ -107,6 +107,14 @@ def getDbPort():
return tmp.groups()[0].strip()
def getDbServerId():
file = getConf()
content = mw.readFile(file)
rep = 'server-id\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
@@ -664,15 +672,15 @@ def isSqlError(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 "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -739,7 +747,7 @@ def importDbBackup():
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
mysql_cmd = getServerDir() + '/bin/mariadb -S ' + sock + ' -uroot -p' + pwd + \
' ' + name + ' < ' + file_path_sql
# print(mysql_cmd)
@@ -800,7 +808,7 @@ def importDbExternal():
sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \
mysql_cmd = getServerDir() + '/bin/mariadb -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql
# print(mysql_cmd)
@@ -940,7 +948,7 @@ def getDbList():
def syncGetDatabases():
pdb = pMysqlDb()
pdb = pMysqlDb('mysql')
psdb = pSqliteDb('databases')
data = pdb.query('show databases')
isError = isSqlError(data)
@@ -1706,12 +1714,14 @@ def getMasterStatus(version=''):
data['mode'] = recognizeDbMode()
data['status'] = master_status
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb('mysql')
dlist = pdb.query('show slave status')
if len(dlist) < 1:
dlist = pdb.query("show all slaves status")
# print(dlist[0])
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
data['slave_status'] = True
for v in dlist:
if v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes':
data['slave_status'] = True
return mw.returnJson(master_status, '设置成功', data)
except Exception as e:
@@ -1855,6 +1865,9 @@ def getMasterRepSlaveUserCmd(version):
clist = psdb.field(f).where("username=?", (username,)).limit(
'1').order('id desc').select()
if len(clist) == 0:
return mw.returnJson(False, '错误同步账户!')
ip = mw.getLocalIp()
port = getMyPort()
db = pMysqlDb()
@@ -1868,15 +1881,23 @@ def getMasterRepSlaveUserCmd(version):
# 查找同步点
# SELECT BINLOG_GTID_POS('master1-bin.000002', 561866201);
sid = getDbServerId()
connection_name = ""
if sid != '':
connection_name = "'r{}' ".format(sid)
# MASTER_USE_GTID={current_pos|slave_pos|no}
# current_pos 依赖-> select @@global.gtid_current_pos;
# slave_pos 依赖-> select @@global.gtid_slave_pos;
# no -> 啥都不依赖,保证多主同步成功。同步出现问题,根据日志查找问题。
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
sql = "CHANGE MASTER " + connection_name + "TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', " + "MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + \
str(mstatus[0]["Position"]) + \
",MASTER_USE_GTID=slave_pos,MASTER_CONNECT_RETRY=10;"
"',MASTER_USE_GTID=no,MASTER_CONNECT_RETRY=10;"
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
sql = "CHANGE MASTER " + connection_name + "TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
@@ -2151,48 +2172,20 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
tmp['Last_Error'] = dlist[x]["Last_Error"]
tmp['Last_IO_Error'] = dlist[x]["Last_IO_Error"]
tmp['Last_SQL_Error'] = dlist[x]["Last_SQL_Error"]
tmp['Slave_SQL_Running_State'] = dlist[x]["Slave_SQL_Running_State"]
if len(dlist) == 0:
dlist = db.query('show all slaves status')
tmp['Error'] = ''
if tmp['Last_Error'] != '':
tmp['Error'] = tmp['Last_Error']
if tmp['Last_IO_Error'] != '':
tmp['Error'] = tmp['Last_IO_Error']
if tmp['Last_SQL_Error'] != '':
tmp['Error'] = tmp['Last_SQL_Error']
if tmp['Error'] == '':
tmp['Error'] = tmp['Slave_SQL_Running_State']
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
cmd = 'cd ' + root + ' && python3 ' + root + \
'/plugins/mysql/index.py do_full_sync {"db":"all"}'
'/plugins/mariadb/index.py do_full_sync {"db":"all","sign":""}'
return mw.returnJson(True, 'ok', cmd)
@@ -2208,102 +2201,151 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version)
def parseSlaveSyncCmd(cmd):
a = {}
vlist = cmd.split(',')
has_connection_name = vlist[0]
pattern_c = r"CHANGE MASTER \'(.*)\' TO MASTER_HOST"
match_val = re.match(pattern_c, has_connection_name, re.I)
if match_val:
m_groups = match_val.groups()
a['Connection_name'] = m_groups[0]
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('id,ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
msg = ''
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb.query("stop slave")
pdb.query("stop all slaves")
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
# print(u['cmd'])
t = db.query(u['cmd'])
# print(t)
db.query("start slave")
return mw.returnJson(True, '初始化成功!')
mode_name = 'classic'
if slave_data[x]['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
pdb.query(cmd_sql)
pdb.query("start slave")
pdb.query("start all slaves ")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
if len(dlist) == 0:
dlist = db.query('show all slaves status')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa,db_user').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
for data in ssh_list:
ip = data['ip']
master_port = data['port']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
time.sleep(1)
ssh.close()
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
cmd_data = json.loads(result)
time.sleep(1)
ssh.close()
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
db.query('stop all slaves')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
# print(cmd)
db.query(cmd)
db.query("start slave")
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# print(cmd)
db.query(cmd)
db.query("start slave")
db.query("start all slaves")
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
os.system("rm -rf " + SSH_PRIVATE_KEY)
return mw.returnJson(True, '初始化成功!')
@@ -2312,61 +2354,39 @@ def setSlaveStatus(version=''):
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
dlist = pdb.query('show all slaves status')
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Connection_name' in v:
connection_name = v['Connection_name']
cmd = "slave '{}'".format(connection_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行[初始化]!')
# print(dlist)
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
db.query("start slave")
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave '{}'".format(sign))
db.query("reset slave '{}' all".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2402,14 +2422,54 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mariadb_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
def fullSync(version=''):
args = getArgs()
data = checkArgs(args, ['db', 'begin'])
if not data[0]:
return data[1]
sign = ''
if 'sign' in args:
sign = args['sign']
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
if os.path.exists(status_file):
c = mw.readFile(status_file)
tmp = json.loads(c)
if tmp['code'] == 1:
sys_dump_sql = "/tmp/dump.sql"
if os.path.exists(sys_dump_sql):
dump_size = os.path.getsize(sys_dump_sql)
tmp['msg'] = tmp['msg'] + ":" + "同步文件:" + mw.toSize(dump_size)
c = json.dumps(tmp)
# if tmp['code'] == 6:
# os.remove(status_file)
return c
return json.dumps({'code': 0, 'msg': '点击开始,开始同步!', 'progress': 0})
def doFullSync(version=''):
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
@@ -2424,16 +2484,23 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
# print(sync_sign, sync_db)
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2442,12 +2509,12 @@ def doFullSyncUser(version=''):
bak_file = '/tmp/tmp.sql'
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 10})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file
print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
@@ -2458,24 +2525,38 @@ def doFullSyncUser(version=''):
' ' + sync_db + ' < ' + bak_file
mw.execShell(my_import_cmd)
db.query("start slave")
pinfo = parseSlaveSyncCmd(data['cmd'])
# print(pinfo)
if 'Connection_name' in pinfo:
db.query("start slave '{}'".format(pinfo['Connection_name']))
else:
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
db = pMysqlDb()
sync_db = args['db']
sync_sign = args['sign']
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2498,7 +2579,6 @@ def doFullSyncSSH(version=''):
return 'fail'
try:
# ssh.load_system_host_keys()
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
@@ -2516,7 +2596,7 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && python3 plugins/mariadb/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 plugins/mariadb/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2539,13 +2619,19 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result == '':
writeDbSyncStatus({'code': 1, 'msg': '同步命令获取失败!', 'progress': 100})
return 'fail'
cmd_data = json.loads(result)
db.query('stop slave')
db.query('stop all slaves')
writeDbSyncStatus({'code': 3, 'msg': '停止从库完成...', 'progress': 45})
cmd = cmd_data['data']['cmd']
@@ -2578,6 +2664,7 @@ def doFullSyncSSH(version=''):
return 'fail'
db.query("start slave")
db.query("start all slaves")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2585,38 +2672,6 @@ def doFullSyncSSH(version=''):
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() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
if os.path.exists(status_file):
c = mw.readFile(status_file)
tmp = json.loads(c)
if tmp['code'] == 1:
sys_dump_sql = "/tmp/dump.sql"
if os.path.exists(sys_dump_sql):
dump_size = os.path.getsize(sys_dump_sql)
tmp['msg'] = tmp['msg'] + ":" + "同步文件:" + mw.toSize(dump_size)
c = json.dumps(tmp)
# if tmp['code'] == 6:
# os.remove(status_file)
return c
return json.dumps({'code': 0, 'msg': '点击开始,开始同步!', 'progress': 0})
def installPreInspection(version):
swap_path = mw.getServerDir() + "/swap"
if not os.path.exists(swap_path):
+178 -86
View File
@@ -431,7 +431,6 @@ function syncToDatabase(type){
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 });
@@ -439,18 +438,6 @@ function syncToDatabase(type){
}
function setRootPwd(type, pwd){
if (type==1){
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
$('.layui-layer-close1').click();
},{icon: rdata.status ? 1 : 2});
});
return;
}
var index = layer.open({
type: 1,
area: '500px',
@@ -467,8 +454,16 @@ function setRootPwd(type, pwd){
</div>\
</div>\
</form>",
yes:function(){
setRootPwd(1);
yes:function(index,layero){
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
layer.close(index);
},{icon: rdata.status ? 1 : 2});
});
return;
}
});
}
@@ -490,7 +485,6 @@ function showHidePass(obj){
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();
@@ -861,7 +855,6 @@ function downloadBackup(file){
function importBackup(file,name){
myPost('import_db_backup',{file:file,name:name}, function(data){
// console.log(data);
layer.msg('执行成功!');
});
}
@@ -1619,7 +1612,6 @@ function getMasterRepSlaveList(){
_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);
@@ -1672,12 +1664,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign = ''){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1685,28 +1677,72 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Connection_name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
function fullSync(db, sign, begin){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1715,23 +1751,11 @@ function getFullSyncStatus(db){
if (rdata['code']==6 ||rdata['code']<0){
layer.msg(rdata['msg']);
clearInterval(timeId);
$("#begin_full_sync").attr('data-status','init');
$("#begin_full_sync").data('status','init');
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -2077,7 +2101,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2101,7 +2125,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2142,11 +2166,15 @@ function handlerRun(){
function initSlaveStatus(){
myPost('init_slave_status', '', function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status ){
layer.msg(rdata.msg,{icon:2,time:10000});
return;
}
showMsg(rdata.msg,function(){
if (rdata.status){
masterOrSlaveConf();
}
},{icon:rdata.status?1:2},2000);
},{icon:1},2000);
});
}
@@ -2204,33 +2232,48 @@ function masterOrSlaveConf(version=''){
}
_data['page'] = page;
_data['page_size'] = 10;
_data['page_size'] = 100;
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Connection_name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
list += '<tr>';
list += '<td>' + rdata.data[i]['Master_Host'] +'</td>';
list += '<td>' + rdata.data[i]['Master_Port'] +'</td>';
list += '<td>' + rdata.data[i]['Master_User'] +'</td>';
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
list += '<td>' + v['Master_Host'] +'</td>';
list += '<td>' + v['Master_Port'] +'</td>';
list += '<td>' + v['Master_User'] +'</td>';
list += '<td>' + v['Master_Log_File'] +'</td>';
list += '<td>' + v['Slave_IO_Running'] +'</td>';
list += '<td>' + v['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Connection_name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'</td>';
list += '<td style="text-align:right">\
<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>\
</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2241,6 +2284,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2255,22 +2299,75 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Connection_name' in v){
deleteSlave(v['Connection_name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
@@ -2320,14 +2417,12 @@ function masterOrSlaveConf(version=''){
});
}
function getMasterStatus(){
myPost('get_master_status', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log('mode:',rdata.data);
if ( typeof(rdata.status) != 'undefined' && !rdata.status && rdata.data == 'pwd'){
layer.msg(rdata.msg, {icon:2});
layer.msg(rdata.msg, {icon:2,time:2000});
return;
}
@@ -2409,7 +2504,6 @@ function masterOrSlaveConf(version=''){
return false;
},
change:function(index,mode,reload){
console.log(index,mode,reload);
myPost('set_dbrun_mode',{'mode':mode,'reload':reload},function(data){
layer.close(index);
var rdata = $.parseJSON(data.data);
@@ -2425,10 +2519,8 @@ function masterOrSlaveConf(version=''){
getMasterDbList();
}
// if (rdata.slave_status){
getAsyncMasterDbList();
getAsyncDataList()
// }
getAsyncMasterDbList();
getAsyncDataList()
});
}
getMasterStatus();
+10 -1
View File
@@ -71,10 +71,19 @@ Install_app()
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
+10 -1
View File
@@ -73,8 +73,17 @@ Install_app()
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
+9 -1
View File
@@ -72,9 +72,17 @@ Install_app()
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
+4
View File
@@ -14,6 +14,10 @@ if mw.isAppleSystem():
app_debug = True
import warnings
warnings.filterwarnings('ignore', category=DeprecationWarning)
def getPluginName():
return 'memcached'
+6 -1
View File
@@ -14,6 +14,9 @@ port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
language={$SERVER_APP_PATH}/bin/usr/share/mysql/english
@@ -45,7 +48,6 @@ skip-ssl
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
@@ -71,6 +73,9 @@ replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+6 -1
View File
@@ -16,6 +16,9 @@ mysqlx_port = 33260
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
key_buffer_size = 8M
@@ -43,7 +46,6 @@ max_allowed_packet = 128M
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
@@ -68,6 +70,9 @@ replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+1 -1
View File
@@ -15,7 +15,7 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
+214 -140
View File
@@ -28,6 +28,10 @@ def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -116,6 +120,10 @@ def contentReplace(content):
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$SERVER_APP_PATH}',
service_path + '/' + getPluginName())
server_id = int(time.time())
content = content.replace('{$SERVER_ID}', str(server_id))
return content
@@ -161,6 +169,10 @@ def pMysqlDb():
def initDreplace(version=''):
t = getServerDir()
if not os.path.exists(t):
return
conf_dir = getServerDir() + '/etc'
mode_dir = conf_dir + '/mode'
@@ -654,15 +666,15 @@ def isSqlError(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 "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -1885,27 +1897,34 @@ def getMasterRepSlaveUserCmd(version):
mode = recognizeDbMode()
sid = getDbServerId()
channel_name = ""
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"])
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + str(mstatus[0]["Position"])
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2217,7 +2236,7 @@ def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
cmd = 'cd ' + root + ' && python3 ' + root + \
'/plugins/mysql/index.py do_full_sync {"db":"all"}'
'/plugins/mysql/index.py do_full_sync {"db":"all","sign":""}'
return mw.returnJson(True, 'ok', cmd)
@@ -2233,100 +2252,151 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version)
def parseSlaveSyncCmd(cmd):
a = {}
if cmd.lower().find('for') > 0:
cmd_tmp = cmd.split('for')
cmd = cmd_tmp[0].strip()
pattern_c = r"channel \'(.*)\';"
match_val = re.match(pattern_c, cmd_tmp[1].strip(), re.I)
if match_val:
m_groups = match_val.groups()
a['channel'] = m_groups[0]
vlist = cmd.split(',')
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
msg = ''
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
mode_name = 'classic'
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
t = db.query(u['cmd'])
# print(t)
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
if slave_t['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
t = pdb.query(cmd_sql)
isError = isSqlError(t)
if isError:
return isError
# pdb.query("start slave user='{}' password='{}';".format(
# u['user'], u['pass']))
pdb.query("start slave")
pdb.query("start all slaves")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
local_mode = recognizeDbMode()
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
db.query('stop slave')
db.query('reset slave all')
for data in ssh_list:
ip = data['ip']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
cmd_data = json.loads(result)
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']:【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
u = cmd_data['data']['info']
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ps = u['username'] + "|" + u['password']
print(ps)
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
db.query("start slave user='{}' password='{}';".format(
u['username'], u['password']))
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ssh.close()
time.sleep(1)
os.system("rm -rf " + SSH_PRIVATE_KEY)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
ssh.close()
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
db.query('start slave')
return mw.returnJson(True, '初始化成功!')
@@ -2336,60 +2406,37 @@ def setSlaveStatus(version=''):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Channel_Name' in v:
ch_name = v['Channel_Name']
cmd = "slave for channel '{}'".format(ch_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行[初始化]!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
u = data['ps'].split("|")
db.query("start slave user='{}' password='{}';".format(u[0], u[1]))
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2425,11 +2472,13 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mysql_apt_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
@@ -2447,16 +2496,22 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2473,16 +2528,17 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
dump_sql_data = getServerDir() + "/bin/usr/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
if os.path.exists(bak_file):
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
my_import_cmd = getServerDir() + '/bin/usr/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db + ' < ' + bak_file
mw.execShell(my_import_cmd)
@@ -2492,21 +2548,30 @@ def doFullSyncUser(version=''):
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2548,7 +2613,8 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && python3 plugins/mysql/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 " + \
getSPluginDir() + "/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2571,7 +2637,10 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
@@ -2583,10 +2652,12 @@ def doFullSyncSSH(version=''):
cmd = cmd_data['data']['cmd']
# 保证同步IP一致
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
uinfo = cmd_data['data']['info']
@@ -2598,8 +2669,10 @@ def doFullSyncSSH(version=''):
root_dir = getServerDir()
msock = root_dir + "/mysql.sock"
mw.execShell("cd /tmp && gzip -d dump.sql.gz")
cmd = root_dir + "/bin/mysql -S " + msock + \
cmd = root_dir + "/bin/usr/bin/mysql -S " + msock + \
" -uroot -p" + pwd + " < /tmp/dump.sql"
print(cmd)
import_data = mw.execShell(cmd)
if import_data[0] == '':
print(import_data[1])
@@ -2609,8 +2682,9 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
db.query("start slave user='{}' password='{}';".format(
uinfo['username'], uinfo['password']))
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2624,12 +2698,12 @@ def fullSync(version=''):
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
+5 -1
View File
@@ -48,7 +48,11 @@ fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ];then
# #初始化
#初始化
if [ "$?" != "0" ];then
exit $?
fi
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py start ${type}
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py initd_install ${type}
fi
+165 -81
View File
@@ -162,34 +162,6 @@ function myPort(){
});
}
//数据库存储信置
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 = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function myPerfOpt() {
//获取MySQL配置
@@ -1691,12 +1663,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1704,28 +1676,73 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Channel_Name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
function fullSync(db,sign,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1734,23 +1751,10 @@ function getFullSyncStatus(db){
if (rdata['code']==6 ||rdata['code']<0){
layer.msg(rdata['msg']);
clearInterval(timeId);
$("#begin_full_sync").attr('data-status','init');
$("#begin_full_sync").data('data','init');
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -1920,18 +1924,29 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[最好填好]</span>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
val = cmd_tmp[0].trim();
const channel_str = cmd_tmp[1].trim();
const ch_reg = /channel \'(.*)\';/;
var match_val = channel_str.match(ch_reg);
if (match_val.length>1){
a['channel'] = match_val[1];
}
}
var vlist = val.split(',');
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
@@ -2098,7 +2113,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2122,7 +2137,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2230,10 +2245,16 @@ function masterOrSlaveConf(version=''){
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Channel_Name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
@@ -2245,13 +2266,23 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Channel_Name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2262,6 +2293,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2276,22 +2308,74 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$('.db_error').click(function(){
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Channel_Name' in v){
deleteSlave(v['Channel_Name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
+16 -1
View File
@@ -35,7 +35,22 @@ if [ "$OSNAME" == "ubuntu" ];then
VERSION_ID="18.04"
fi
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_amd64
ARCH="amd64"
TMP_ARCH=`arch`
if [ "$TMP_ARCH" == "x86_64" ];then
ARCH="amd64"
elif [ "$TMP_ARCH" == "aarch64" ];then
ARCH="arm64"
else
ARCH="amd64"
fi
if [ "$ARCH" != "amd64" ];then
echo "暂时不支持该${ARCH}" > $install_tmp
exit 0
fi
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_${ARCH}
APT_INSTALL()
{
+18 -2
View File
@@ -22,8 +22,25 @@ VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -
# cd /www/server/mdserver-web/plugins/mysql-apt && bash install.sh install 8.0
ARCH="amd64"
TMP_ARCH=`arch`
if [ "$TMP_ARCH" == "x86_64" ];then
ARCH="amd64"
elif [ "$TMP_ARCH" == "aarch64" ];then
ARCH="arm64"
else
ARCH="amd64"
fi
if [ "$ARCH" != "amd64" ];then
echo "暂时不支持该${ARCH}" > $install_tmp
exit 1
fi
MYSQL_VER=8.0.30
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_amd64
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_${ARCH}
# /lib/systemd/system/mysql.service
@@ -81,7 +98,6 @@ Install_mysql()
useradd -g mysql mysql
fi
isApt=`which apt`
if [ "$isApt" != "" ];then
APT_INSTALL
+6 -1
View File
@@ -14,6 +14,9 @@ port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
language={$SERVER_APP_PATH}/bin/usr/share/mysql/english
@@ -46,7 +49,6 @@ skip-ssl
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
@@ -72,6 +74,9 @@ replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+6 -1
View File
@@ -16,6 +16,9 @@ mysqlx_port = 33260
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
key_buffer_size = 8M
@@ -43,7 +46,6 @@ max_allowed_packet = 128M
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
@@ -68,6 +70,9 @@ replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+1 -1
View File
@@ -15,7 +15,7 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
+219 -152
View File
@@ -36,6 +36,10 @@ def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -101,6 +105,14 @@ def getDbPort():
return tmp.groups()[0].strip()
def getDbServerId():
file = getConf()
content = mw.readFile(file)
rep = 'server-id\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
@@ -123,6 +135,9 @@ def contentReplace(content):
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$SERVER_APP_PATH}',
service_path + '/' + getPluginName())
server_id = int(time.time())
content = content.replace('{$SERVER_ID}', str(server_id))
return content
@@ -640,15 +655,15 @@ def isSqlError(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 "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -1863,27 +1878,34 @@ def getMasterRepSlaveUserCmd(version):
mode = recognizeDbMode()
sid = getDbServerId()
channel_name = ""
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"])
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + str(mstatus[0]["Position"])
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2154,22 +2176,10 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
@@ -2193,100 +2203,149 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version)
def parseSlaveSyncCmd(cmd):
a = {}
if cmd.lower().find('for') > 0:
cmd_tmp = cmd.split('for')
cmd = cmd_tmp[0].strip()
pattern_c = r"channel \'(.*)\';"
match_val = re.match(pattern_c, cmd_tmp[1].strip(), re.I)
if match_val:
m_groups = match_val.groups()
a['channel'] = m_groups[0]
vlist = cmd.split(',')
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
msg = ''
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
mode_name = 'classic'
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
t = db.query(u['cmd'])
# print(t)
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
if slave_t['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
# print(u['cmd'])
t = pdb.query(cmd_sql)
isError = isSqlError(t)
if isError:
return isError
# pdb.query("start slave user='{}' password='{}';".format(
# u['user'], u['pass']))
pdb.query("start slave")
pdb.query("start all slaves")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
local_mode = recognizeDbMode()
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
db.query('stop slave')
db.query('reset slave all')
for data in ssh_list:
ip = data['ip']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql-yum/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
cmd_data = json.loads(result)
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']:【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
u = cmd_data['data']['info']
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ps = u['username'] + "|" + u['password']
print(ps)
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
db.query("start slave user='{}' password='{}';".format(
u['username'], u['password']))
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ssh.close()
time.sleep(1)
os.system("rm -rf " + SSH_PRIVATE_KEY)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
ssh.close()
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
db.query('start slave')
return mw.returnJson(True, '初始化成功!')
@@ -2296,60 +2355,37 @@ def setSlaveStatus(version=''):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Channel_Name' in v:
ch_name = v['Channel_Name']
cmd = "slave for channel '{}'".format(ch_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行[初始化]!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
u = data['ps'].split("|")
db.query("start slave user='{}' password='{}';".format(u[0], u[1]))
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2385,11 +2421,13 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mysql_yum_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
@@ -2407,16 +2445,22 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2433,16 +2477,17 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
dump_sql_data = getServerDir() + "/bin/usr/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
if os.path.exists(bak_file):
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
my_import_cmd = getServerDir() + '/bin/usr/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db + ' < ' + bak_file
mw.execShell(my_import_cmd)
@@ -2452,21 +2497,30 @@ def doFullSyncUser(version=''):
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2508,7 +2562,8 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && python3 plugins/mysql/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 " + \
getSPluginDir() + "/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2531,7 +2586,10 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
@@ -2543,10 +2601,12 @@ def doFullSyncSSH(version=''):
cmd = cmd_data['data']['cmd']
# 保证同步IP一致
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
uinfo = cmd_data['data']['info']
@@ -2558,8 +2618,10 @@ def doFullSyncSSH(version=''):
root_dir = getServerDir()
msock = root_dir + "/mysql.sock"
mw.execShell("cd /tmp && gzip -d dump.sql.gz")
cmd = root_dir + "/bin/mysql -S " + msock + \
cmd = root_dir + "/bin/usr/bin/mysql -S " + msock + \
" -uroot -p" + pwd + " < /tmp/dump.sql"
print(cmd)
import_data = mw.execShell(cmd)
if import_data[0] == '':
print(import_data[1])
@@ -2569,8 +2631,9 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
db.query("start slave user='{}' password='{}';".format(
uinfo['username'], uinfo['password']))
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2584,12 +2647,16 @@ def fullSync(version=''):
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
sign = ''
if 'sign' in args:
sign = args['sign']
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
+164 -80
View File
@@ -162,34 +162,6 @@ function myPort(){
});
}
//数据库存储信置
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 = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function myPerfOpt() {
//获取MySQL配置
@@ -1691,12 +1663,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1704,28 +1676,73 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Channel_Name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
function fullSync(db,sign,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1738,19 +1755,6 @@ function getFullSyncStatus(db){
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -1920,18 +1924,29 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[最好填好]</span>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
val = cmd_tmp[0].trim();
const channel_str = cmd_tmp[1].trim();
const ch_reg = /channel \'(.*)\';/;
var match_val = channel_str.match(ch_reg);
if (match_val.length>1){
a['channel'] = match_val[1];
}
}
var vlist = val.split(',');
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
@@ -2098,7 +2113,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2122,7 +2137,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2230,10 +2245,16 @@ function masterOrSlaveConf(version=''){
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Channel_Name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
@@ -2245,13 +2266,23 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Channel_Name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2262,6 +2293,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2276,22 +2308,74 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$('.db_error').click(function(){
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Channel_Name' in v){
deleteSlave(v['Channel_Name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
+1
View File
@@ -18,6 +18,7 @@ basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
+3
View File
@@ -16,6 +16,7 @@ basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
explicit_defaults_for_timestamp=true
default_storage_engine = InnoDB
@@ -80,6 +81,8 @@ replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+5 -2
View File
@@ -8,8 +8,8 @@ default-character-set = UTF8MB4
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
sha256_password_private_key_path=mysql.pem
sha256_password_public_key_path=mysql.pub
sha256_password_private_key_path={$SERVER_APP_PATH}/data/mysql.pem
sha256_password_public_key_path={$SERVER_APP_PATH}/data/mysql.pub
authentication_policy=mysql_native_password
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
@@ -20,6 +20,7 @@ basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
@@ -77,6 +78,8 @@ replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+1 -1
View File
@@ -15,7 +15,7 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
+232 -188
View File
@@ -36,6 +36,10 @@ def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -85,6 +89,14 @@ def getDbPort():
return tmp.groups()[0].strip()
def getDbServerId():
file = getConf()
content = mw.readFile(file)
rep = 'server-id\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
@@ -167,7 +179,6 @@ def pMysqlDb():
def makeInitRsaKey(version=''):
datadir = getServerDir() + "/data"
mysql_pem = datadir + "/mysql.pem"
if not os.path.exists(mysql_pem):
rdata = mw.execShell(
@@ -176,12 +187,11 @@ def makeInitRsaKey(version=''):
rdata = mw.execShell(
'cd ' + datadir + ' && openssl rsa -in mysql.pem -pubout -out mysql.pub')
# print(rdata)
if not mw.isAppleSystem():
mw.execShell('cd ' + datadir + ' && chmod 400 mysql.pem')
mw.execShell('cd ' + datadir + ' && chmod 444 mysql.pub')
mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pem')
mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pub')
if not mw.isAppleSystem():
mw.execShell('cd ' + datadir + ' && chmod 400 mysql.pem')
mw.execShell('cd ' + datadir + ' && chmod 444 mysql.pub')
mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pem')
mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pub')
def initDreplace(version=''):
@@ -251,6 +261,14 @@ def initDreplace(version=''):
return file_bin
def process_status():
cmd = "ps -ef|grep mysql |grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def status(version=''):
path = getConf()
if not os.path.exists(path):
@@ -450,7 +468,7 @@ def initMysqlPwd():
def initMysql8Pwd():
time.sleep(2)
time.sleep(8)
serverdir = getServerDir()
myconf = serverdir + "/etc/my.cnf"
@@ -540,7 +558,12 @@ def my8cmd(version, method):
else:
mw.execShell('systemctl start mysql')
initMysql8Pwd()
for x in range(10):
mydb_status = process_status()
if mydb_status == 'start':
initMysql8Pwd()
break
time.sleep(1)
if mw.isAppleSystem():
cmd_init_stop = init_file + ' stop'
@@ -562,11 +585,11 @@ def my8cmd(version, method):
def appCMD(version, action):
makeInitRsaKey(version)
if version == '8.0' or version == '5.7':
status = my8cmd(version, action)
else:
status = myOp(version, action)
makeInitRsaKey(version)
return status
@@ -791,15 +814,15 @@ def isSqlError(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 "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -1876,13 +1899,14 @@ def getMasterStatus(version=''):
data = {}
data['mode'] = recognizeDbMode()
data['status'] = master_status
data['slave_status'] = False
db = pMysqlDb()
dlist = db.query('show slave status')
# print(dlist[0])
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
data['slave_status'] = True
for v in dlist:
if v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes':
data['slave_status'] = True
return mw.returnJson(master_status, '设置成功', data)
except Exception as e:
@@ -2046,27 +2070,34 @@ def getMasterRepSlaveUserCmd(version):
mode = recognizeDbMode()
sid = getDbServerId()
channel_name = ""
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"])
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + str(mstatus[0]["Position"])
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2337,48 +2368,17 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
tmp['Last_Error'] = dlist[x]["Last_Error"]
tmp['Last_IO_Error'] = dlist[x]["Last_IO_Error"]
tmp['Last_SQL_Error'] = dlist[x]["Last_SQL_Error"]
tmp['Slave_SQL_Running_State'] = dlist[x]["Slave_SQL_Running_State"]
tmp['Error'] = ''
if tmp['Last_Error'] != '':
tmp['Error'] = tmp['Last_Error']
if tmp['Last_IO_Error'] != '':
tmp['Error'] = tmp['Last_IO_Error']
if tmp['Last_SQL_Error'] != '':
tmp['Error'] = tmp['Last_SQL_Error']
if tmp['Error'] == '':
tmp['Error'] = tmp['Slave_SQL_Running_State']
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
cmd = 'cd ' + root + ' && python3 ' + root + \
'/plugins/mysql/index.py do_full_sync {"db":"all"}'
'/plugins/mysql/index.py do_full_sync {"db":"all","sign",""}'
return mw.returnJson(True, 'ok', cmd)
@@ -2413,111 +2413,152 @@ def makeSyncUsercmd(u, version=''):
return sql
def parseSlaveSyncCmd(cmd):
a = {}
if cmd.lower().find('for') > 0:
cmd_tmp = cmd.split('for')
cmd = cmd_tmp[0].strip()
pattern_c = r"channel \'(.*)\';"
match_val = re.match(pattern_c, cmd_tmp[1].strip(), re.I)
if match_val:
m_groups = match_val.groups()
a['channel'] = m_groups[0]
vlist = cmd.split(',')
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
msg = ''
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
mode_name = 'classic'
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
if u['cmd'] == '' and local_mode == 'gtid':
sql = makeSyncUsercmd(u, version)
# print(sql)
t = db.query(sql)
else:
if u['cmd'] == '':
return mw.returnJson(False, '经典模式下,必须手写同步命令!')
if slave_t['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
# print(u['cmd'])
t = db.query(u['cmd'])
isError = isSqlError(t)
if isError:
return isError
t = pdb.query(cmd_sql)
isError = isSqlError(t)
if isError:
return isError
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
# pdb.query("start slave user='{}' password='{}';".format(
# u['user'], u['pass']))
pdb.query("start slave")
pdb.query("start all slaves")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
return mw.returnJson(False, '需要先添加SSH配置!')
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
local_mode = recognizeDbMode()
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
db.query('stop slave')
db.query('reset slave all')
for data in ssh_list:
ip = data['ip']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
cmd_data = json.loads(result)
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']:【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
u = cmd_data['data']['info']
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ps = u['username'] + "|" + u['password']
print(ps)
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
db.query("start slave user='{}' password='{}';".format(
u['username'], u['password']))
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ssh.close()
time.sleep(1)
os.system("rm -rf " + SSH_PRIVATE_KEY)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
ssh.close()
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
db.query('start slave')
return mw.returnJson(True, '初始化成功!')
@@ -2527,60 +2568,37 @@ def setSlaveStatus(version=''):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Channel_Name' in v:
ch_name = v['Channel_Name']
cmd = "slave for channel '{}'".format(ch_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
u = data['ps'].split("|")
db.query("start slave user='{}' password='{}';".format(u[0], u[1]))
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2617,11 +2635,13 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mysql_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
@@ -2639,16 +2659,22 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2685,21 +2711,30 @@ def doFullSyncUser(version=''):
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2741,7 +2776,8 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 " + \
getSPluginDir() + "/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2764,7 +2800,10 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
@@ -2806,8 +2845,9 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
db.query("start slave user='{}' password='{}';".format(
uinfo['username'], uinfo['password']))
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2821,12 +2861,16 @@ def fullSync(version=''):
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
sign = ''
if 'sign' in args:
sign = args['sign']
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
+164 -80
View File
@@ -162,34 +162,6 @@ function myPort(){
});
}
//数据库存储信置
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 = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="changePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function myPerfOpt() {
//获取MySQL配置
@@ -1691,12 +1663,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1704,28 +1676,73 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Channel_Name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
function fullSync(db,sign,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1738,19 +1755,6 @@ function getFullSyncStatus(db){
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -1920,18 +1924,29 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[最好填好]</span>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
val = cmd_tmp[0].trim();
const channel_str = cmd_tmp[1].trim();
const ch_reg = /channel \'(.*)\';/;
var match_val = channel_str.match(ch_reg);
if (match_val.length>1){
a['channel'] = match_val[1];
}
}
var vlist = val.split(',');
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
@@ -2098,7 +2113,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2122,7 +2137,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2230,10 +2245,16 @@ function masterOrSlaveConf(version=''){
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Channel_Name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
@@ -2245,13 +2266,23 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Channel_Name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2262,6 +2293,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2276,22 +2308,74 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$('.db_error').click(function(){
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Channel_Name' in v){
deleteSlave(v['Channel_Name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
+1 -1
View File
@@ -29,7 +29,7 @@ class App:
self.__agent_cfg = self.__setupPath + '/agent.cfg'
def getArgs(self):
args = sys.argv[2:]
args = sys.argv[3:]
tmp = {}
args_len = len(args)
+43 -41
View File
@@ -533,49 +533,51 @@ end
function waf()
min_route()
-- C:D("min_route")
-- white ip
if waf_ip_white() then return true end
-- C:D("waf_ip_white")
-- url white
if waf_url_white() then return true end
-- C:D("waf_url_white")
-- black ip
if waf_ip_black() then return true end
-- C:D("waf_ip_black")
-- 封禁ip返回
if waf_drop_ip() then return true end
-- C:D("waf_drop_ip")
-- ua check
if waf_user_agent() then return true end
-- C:D("waf_user_agent")
if waf_url() then return true end
-- C:D("waf_url")
-- cc setting
if waf_cc_increase() then return true end
-- C:D("waf_cc_increase")
if waf_cc() then return true end
-- C:D("waf_cc")
-- cookie检查
if waf_cookie() then return true end
-- C:D("waf_cookie")
-- args参数拦截
if waf_get_args() then return true end
-- C:D("waf_get_args")
-- 扫描软件禁止
if waf_scan_black() then return true end
-- C:D("waf_scan_black")
if waf_post() then return true end
-- C:D("waf_post")
if site_config[server_name] and site_config[server_name]['open'] then
-- white ip
if waf_ip_white() then return true end
-- C:D("waf_ip_white")
-- url white
if waf_url_white() then return true end
-- C:D("waf_url_white")
-- black ip
if waf_ip_black() then return true end
-- C:D("waf_ip_black")
-- 封禁ip返回
if waf_drop_ip() then return true end
-- C:D("waf_drop_ip")
-- ua check
if waf_user_agent() then return true end
-- C:D("waf_user_agent")
if waf_url() then return true end
-- C:D("waf_url")
-- cc setting
if waf_cc_increase() then return true end
-- C:D("waf_cc_increase")
if waf_cc() then return true end
-- C:D("waf_cc")
-- cookie检查
if waf_cookie() then return true end
-- C:D("waf_cookie")
-- args参数拦截
if waf_get_args() then return true end
-- C:D("waf_get_args")
-- 扫描软件禁止
if waf_scan_black() then return true end
-- C:D("waf_scan_black")
if waf_post() then return true end
-- C:D("waf_post")
--------------------------------------------------------
--------------------------------------------------------
if X_Forwarded() then return true end
-- C:D("X_Forwarded")
if post_X_Forwarded() then return true end
+19 -12
View File
@@ -60,19 +60,26 @@ http
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server_tokens off;
access_log off;
# CACEH_BEGIN
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_cache_path {$SERVER_PATH}/openresty/nginx/proxy_cache_temp levels=1:2 keys_zone=mw_cache:512m inactive=5m max_size=2g use_temp_path=off;
#proxy timeout
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
server {
listen 80;
listen [::]:80;
server_name 127.0.0.1;
allow 127.0.0.1;
location /nginx_status {
stub_status on;
access_log off;
}
}
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_path {$SERVER_PATH}/openresty/nginx/fastcgi_cache_temp levels=1:2 keys_zone=mw_cache_fcgi:100m inactive=60m max_size=5g;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# CACEH_END
server_tokens off;
access_log /dev/null;
include {$SERVER_PATH}/web_conf/nginx/vhost/*.conf;
}
@@ -0,0 +1,10 @@
server {
listen 80;
listen [::]:80;
server_name 127.0.0.1;
allow 127.0.0.1;
location /nginx_status {
stub_status on;
access_log off;
}
}
@@ -0,0 +1,4 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
+12
View File
@@ -180,6 +180,17 @@ def confReplace():
cmd_s = 'chmod u+s ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_s))
# vhost
vhost_dir = mw.getServerDir() + '/web_conf/nginx/vhost'
vhost_tpl_dir = getPluginDir() + '/conf/vhost'
# print(vhost_dir, vhost_tpl_dir)
vhost_list = ['0.websocket.conf', '0.nginx_status.conf']
for f in vhost_list:
a_conf = vhost_dir + '/' + f
a_conf_tpl = vhost_tpl_dir + '/' + f
if not os.path.exists(a_conf):
mw.writeFile(a_conf, mw.readFile(a_conf_tpl))
def initDreplace():
@@ -290,6 +301,7 @@ def restart():
def reload():
confReplace()
return restyOp('reload')
+2 -2
View File
@@ -12,6 +12,6 @@
"home":"http://openresty.org",
"date":"2017-11-24",
"pid": "1",
"versions": ["1.17.8.2","1.19.3.1","1.21.4.1"],
"updates": ["1.17.8.2","1.19.3.1","1.21.4.1"]
"versions": ["1.17.8.2","1.19.3.1","1.21.4.2"],
"updates": ["1.17.8.2","1.19.3.1","1.21.4.2"]
}
+1 -1
View File
@@ -658,7 +658,7 @@ function phpLibConfig(version){
//安装扩展
function installPHPLib(version, name, title, pathinfo) {
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
layer.confirm('您真的要卸载{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
name = name.toLowerCase();
var data = "name=" + name + "&version=" + version + "&type=1";
+1 -1
View File
@@ -672,7 +672,7 @@ function installPHPLib(version, name, title, pathinfo) {
//卸载扩展
function uninstallPHPLib(version, name, title, pathinfo) {
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
layer.confirm('您真的要卸载{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
name = name.toLowerCase();
var data = 'name=' + name + '&version=' + version;
phpPost('uninstall_lib', version, data, function(data){
+2 -2
View File
@@ -12,9 +12,9 @@ version=$1
action=$2
if [ -f /lib/systemd/system/php${version}-php-fpm.service ];then
systemctl ${action} php${version}
systemctl ${action} php${version}-php-fpm
elif [[ -f /usr/lib/systemd/system/php${version}-php-fpm.service ]]; then
systemctl ${action} php${version}
systemctl ${action} php${version}-php-fpm
else
$serverPath/php/init.d/php${version} ${action}
fi
+1
View File
@@ -49,6 +49,7 @@ fi
cd ${curPath} && sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then
#初始化
+1 -1
View File
@@ -665,7 +665,7 @@ function installPHPLib(version, name, title, pathinfo) {
//卸载扩展
function uninstallPHPLib(version, name, title, pathinfo) {
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
layer.confirm('您真的要卸载{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
name = name.toLowerCase();
var data = 'name=' + name + '&version=' + version;
phpPost('uninstall_lib', version, data, function(data){
+14 -5
View File
@@ -15,11 +15,20 @@ SOURCE_ROOT=$rootPath/source/lib
if [ ! -d ${SERVER_ROOT}/freetype ];then
cd $SOURCE_ROOT
wget -O freetype-2.12.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.gz -T 5
tar zxvf freetype-2.12.1.tar.gz
cd freetype-2.12.1
if [ ! -f $SOURCE_ROOT/freetype-2.12.1.tar.gz ];then
wget -O freetype-2.12.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.gz -T 5
fi
if [ ! -d $SOURCE_ROOT/freetype-2.12.1 ];then
tar zxvf freetype-2.12.1.tar.gz
cd freetype-2.12.1
else
cd freetype-2.12.1
fi
./configure --prefix=${SERVER_ROOT}/freetype && make && make install
cd $SOURCE_ROOT
cd $SOURCE_ROOT && rm -rf freetype-2.12.1
#rm -rf freetype-2.12.1.tar.gz
#rm -rf freetype-2.12.1
fi
+14 -5
View File
@@ -15,11 +15,20 @@ SOURCE_ROOT=$rootPath/source/lib
if [ ! -d ${SERVER_ROOT}/freetype_old ];then
cd $SOURCE_ROOT
wget -O freetype-2.7.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.7.1.tar.gz -T 5
tar zxvf freetype-2.7.1.tar.gz
cd freetype-2.7.1
if [ ! -f $SOURCE_ROOT/freetype-2.7.1.tar.gz ];then
wget -O freetype-2.7.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.7.1.tar.gz -T 5
fi
if [ ! -d $SOURCE_ROOT/freetype-2.7.1 ];then
tar zxvf freetype-2.7.1.tar.gz
cd freetype-2.7.1
else
cd freetype-2.7.1
fi
./configure --prefix=${SERVER_ROOT}/freetype_old && make && make install
#cd $SOURCE_ROOT
cd $SOURCE_ROOT && rm -rf freetype-2.7.1
#rm -rf freetype-2.7.1.tar.gz
#rm -rf freetype-2.7.1
fi
+15 -5
View File
@@ -13,19 +13,29 @@ rootPath=$(dirname "$rootPath")
SERVER_ROOT=$rootPath/lib
SOURCE_ROOT=$rootPath/source/lib
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
HTTP_PREFIX="https://ghproxy.com/"
fi
if [ ! -d ${SERVER_ROOT}/libzip ];then
cd $SOURCE_ROOT
if [ ! -f ${SOURCE_ROOT}/libzip-1.3.2.tar.gz ];then
wget --no-check-certificate -O libzip-1.3.2.tar.gz --no-check-certificate https://nih.at/libzip/libzip-1.3.2.tar.gz -T 20
wget --no-check-certificate -O libzip-1.3.2.tar.gz ${HTTP_PREFIX}github.com/midoks/mdserver-web/releases/download/init/libzip-1.3.2.tar.gz -T 20
fi
tar -zxvf libzip-1.3.2.tar.gz
cd libzip-1.3.2
cd ${SOURCE_ROOT}/libzip-1.3.2
./configure --prefix=${SERVER_ROOT}/libzip && make && make install
#cd $SOURCE_ROOT
#rm -rf libzip-1.3.2
#rm -rf libzip-1.3.2.tar.gz
if [ "$?" == "0" ];then
rm -rf ${SOURCE_ROOT}/libzip-1.3.2
rm -rf ${SOURCE_ROOT}/libzip-1.3.2.tar.gz
fi
fi
+16
View File
@@ -24,6 +24,22 @@ mkdir -p $serverPath/php
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.gz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.gz https://museum.php.net/php5/php-${version}.tar.gz
fi
+16
View File
@@ -24,6 +24,22 @@ mkdir -p $serverPath/php
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz
fi
+16
View File
@@ -24,6 +24,22 @@ mkdir -p $serverPath/php
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.gz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.gz https://museum.php.net/php5/php-${version}.tar.gz
fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz
fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz
fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz
fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz
fi
+16
View File
@@ -24,6 +24,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz
fi
+15
View File
@@ -28,6 +28,21 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz
+16 -1
View File
@@ -36,6 +36,21 @@ fi
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz
fi
@@ -109,7 +124,7 @@ fi
if [ ! -d $serverPath/php/${PHP_VER} ];then
cd $sourcePath/php/php${PHP_VER} && make clean
./buildconf --force
# ./buildconf --force
./configure \
--prefix=$serverPath/php/${PHP_VER} \
--exec-prefix=$serverPath/php/${PHP_VER} \
+16
View File
@@ -35,6 +35,22 @@ if [ "$?" == "0" ];then
fi
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://www.php.net/distributions/php-${version}.tar.xz
+16
View File
@@ -36,6 +36,22 @@ fi
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://www.php.net/distributions/php-${version}.tar.xz
fi
+16
View File
@@ -36,6 +36,22 @@ fi
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://www.php.net/distributions/php-${version}.tar.xz
fi
+11 -11
View File
@@ -782,20 +782,20 @@ def lsyncdAdd():
info['rsync'] = rsync
if not 'exclude' in info:
info["exclude"] = [
"/**.upload.tmp",
"**/*.log",
"**/*.tmp",
"**/*.temp",
".git",
".gitignore",
".user.ini",
]
data = getDefaultConf()
slist = data['send']["list"]
res = lsyncdListFindName(slist, info['name'])
if not 'exclude' in info:
if res[0]:
info["exclude"] = slist[res[1]]['exclude']
else:
info["exclude"] = [
"/**.upload.tmp", "**/*.log", "**/*.tmp",
"**/*.temp", ".git", ".gitignore", ".user.ini",
]
if res[0]:
list_index = res[1]
slist[list_index] = info
+4 -4
View File
@@ -476,7 +476,7 @@ function lsyncdExclude(name){
}
function lsyncdConfLog(){
pluginStandAloneLogs("rsyncd","","lsyncd_conf_log");;
pluginRollingLogs("rsyncd","","lsyncd_conf_log");;
}
function lsyncdSend(){
@@ -492,7 +492,7 @@ function lsyncdSend(){
con += '<div style="padding-top:1px;">\
<button class="btn btn-success btn-sm" onclick="createSendTask();">创建发送任务</button>\
<button class="btn btn-success btn-sm" onclick="lsyncdConfLog();">日志</button>\
<button class="btn btn-success btn-sm" onclick="lsyncdConfLog();">自动同步日志</button>\
</div>';
con += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
@@ -532,7 +532,7 @@ function lsyncdSend(){
'<td>' + period +'</td>' +
'<td>\
<a class="btlink" onclick="lsyncdRun(\''+list[i]['name']+'\')">同步</a>\
| <a class="btlink" onclick="lsyncdLog(\''+list[i]['name']+'\')">日志</a>\
| <a class="btlink" onclick="lsyncdLog(\''+list[i]['name']+'\')">手动日志</a>\
| <a class="btlink" onclick="lsyncdExclude(\''+list[i]['name']+'\')">过滤器</a>\
| <a class="btlink" onclick="createSendTask(\''+list[i]['name']+'\')">编辑</a>\
| <a class="btlink" onclick="lsyncdDelete(\''+list[i]['name']+'\')">删除</a>\
@@ -562,7 +562,7 @@ function rsyncdConf(){
}
function rsyncdLog(){
pluginStandAloneLogs("rsyncd","","run_log");
pluginRollingLogs("rsyncd","","run_log");
}
+1 -1
View File
@@ -22,6 +22,6 @@ def init(bot):
bot.set_my_commands(
commands=[
telebot.types.BotCommand("start", "查看帮助信息"),
telebot.types.BotCommand("faq", "查看bbs帖子主题【不要忘记:冒号】"),
telebot.types.BotCommand("faq", "查看bbs帖子主题【?:】"),
],
)
+7 -7
View File
@@ -42,9 +42,9 @@ def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|end
# https://t.me/gjgzs2022 | 22/m
# 代付支付宝微信❤️淘宝帮付/💰流量变现💰集团收量/🕵️‍♀️实名认证/接码✅过人脸👤 | 28/m
# https://zhaoziyuan.la/ | 15/m | 2m | next,7/15
# 香港高防CDN |9/m
# 高价收量 👑 集团收量 ❤️ 流量变现/支付宝代付 ❤️ 微信代付/实名认证/过人脸🕵️‍♀️各种账号处理✅ | 28/m
# https://zhaoziyuan.la/ | web | 15/m | 2m | next,7/15
# 腾云机场 |9/m
keyboard = [
[
types.InlineKeyboardButton(
@@ -52,19 +52,19 @@ def send_msg(bot, tag='ad', trigger_time=300):
],
[
types.InlineKeyboardButton(
text="香港高防CDN、免实名、试用30天", url='https://www.100dun.com')
text="🚀腾云机场|解锁流媒体和ChatGPT", url='https://www.tencloud.net/#/register?code=OGvXSTsc')
],
[
types.InlineKeyboardButton(
text="🕵️‍♀️实名认证/接码✅过人脸👤", url='https://t.me/zhanzhangyewu')
text="实名认证/过人脸🕵️‍♀️各种账号处理✅", url='https://t.me/zhanzhangyewu')
],
[
types.InlineKeyboardButton(
text="代付支付宝微信❤️淘宝帮付", url='https://t.me/Uxuanzhenpin')
text="支付宝代付 ❤️ 微信代付", url='https://t.me/Uxuanzhenpin')
],
[
types.InlineKeyboardButton(
text="💰流量变现💰集团收量", url='https://t.me/taohaozhan')
text="高价收量 👑 集团收量 ❤️ 流量变现", url='https://t.me/maccms_jccms/93')
],
[
types.InlineKeyboardButton(
@@ -51,8 +51,9 @@ def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|end
# https://t.me/gjgzs2022 | 22/m
# 代付支付宝微信❤️淘宝帮付/💰流量变现💰集团收量/🕵️‍♀️实名认证/接码✅过人脸👤 | 28/m
# 香港高防CDN |9/m
# 高价收量 👑 集团收量 ❤️ 流量变现/支付宝代付 ❤️ 微信代付/实名认证/过人脸🕵️‍♀️各种账号处理✅ | 28/m
# https://zhaoziyuan.la/ | web | 15/m | 2m | next,9/15
# 腾云机场 |9/m
keyboard = [
[
types.InlineKeyboardButton(
@@ -60,19 +61,19 @@ def send_msg(bot, tag='ad', trigger_time=300):
],
[
types.InlineKeyboardButton(
text="香港高防CDN、免实名、试用30天", url='https://www.100dun.com')
text="🚀腾云机场|解锁流媒体和ChatGPT", url='https://www.tencloud.net/#/register?code=OGvXSTsc')
],
[
types.InlineKeyboardButton(
text="🕵️‍♀️实名认证/接码✅过人脸👤", url='https://t.me/zhanzhangyewu')
text="实名认证/过人脸🕵️‍♀️各种账号处理✅", url='https://t.me/zhanzhangyewu')
],
[
types.InlineKeyboardButton(
text="代付支付宝微信❤️淘宝帮付", url='https://t.me/Uxuanzhenpin')
text="支付宝代付 ❤️ 微信代付", url='https://t.me/Uxuanzhenpin')
],
[
types.InlineKeyboardButton(
text="💰流量变现💰集团收量", url='https://t.me/taohaozhan')
text="高价收量 👑 集团收量 ❤️ 流量变现", url='https://t.me/maccms_jccms/93')
],
[
types.InlineKeyboardButton(
+13 -17
View File
@@ -189,26 +189,22 @@ def run(bot, message):
return bot
# print(text_body)
if isThisCmd('/faq:', text_body):
cmd_text = getReadCmd('/faq:', text_body)
if isThisCmd('/?:', text_body):
cmd_text = getReadCmd('/?:', text_body)
return searchFaq(bot, message, cmd_text)
# if isThisCmd('/debug', text_body):
# cmd_text = getReadCmd('/debug', text_body)
# return searchDebug(bot, message, cmd_text)
# if text_body.find('?') > -1 or text_body.find('?') > -1:
# return_msg = "你似乎在寻找【" + text_body + "】答案:\n"
# return_msg += "/faq:开始寻找你的问题\n"
# keyboard = [
# [
# types.InlineKeyboardButton(
# text="如未找到,可以在论坛补充你的提问!", url='https://bbs.midoks.me'),
# ]
if text_body.find('?') > -1 or text_body.find('?') > -1:
return_msg = "你似乎在寻找【" + text_body + "】答案:\n"
return_msg += "/faq:开始寻找你的问题\n"
keyboard = [
[
types.InlineKeyboardButton(
text="如未找到,可以在论坛补充你的提问!", url='https://bbs.midoks.me'),
]
]
markup = types.InlineKeyboardMarkup(keyboard)
bot.reply_to(message, return_msg, reply_markup=markup)
# ]
# markup = types.InlineKeyboardMarkup(keyboard)
# bot.reply_to(message, return_msg, reply_markup=markup)
return bot
+1 -1
View File
@@ -2,7 +2,7 @@ setuptools>=33.1.1
Werkzeug>=1.0.1
wheel>=0.37.1
gunicorn==20.1.0
requests==2.27.1
requests>=2.27.1
urllib3>=1.21.1
flask>=2.0.3
flask-session==0.3.2
+8 -2
View File
@@ -47,7 +47,7 @@ cache.init_app(app, config={'CACHE_TYPE': 'simple'})
try:
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/mw_session.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/py_mw_session.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SESSION_TYPE'] = 'sqlalchemy'
app.config['SESSION_SQLALCHEMY'] = sdb
@@ -60,7 +60,6 @@ except:
str(sys.version_info[0])
app.config['SESSION_FILE_THRESHOLD'] = 1024
app.config['SESSION_FILE_MODE'] = 384
mw.execShell("pip install flask_sqlalchemy &")
app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
app.config['SESSION_PERMANENT'] = True
@@ -178,6 +177,13 @@ def requestCheck():
return domain_check
@app.after_request
def requestAfter(response):
response.headers['soft'] = 'mdserver-web'
response.headers['mw-version'] = app.config.version
return response
def isLogined():
if 'login' in session and 'username' in session and session['login'] == True:
userInfo = mw.M('users').where(
+128 -221
View File
@@ -1,78 +1,100 @@
//默认显示7天周期图表
setTimeout(function(){
Wday(0,'getload');
},500);
},100);
setTimeout(function(){
Wday(0,'cpu');
},500);
},200);
setTimeout(function(){
Wday(0,'mem');
},1000);
},500);
setTimeout(function(){
Wday(0,'disk');
},1500);
},100);
setTimeout(function(){
Wday(0,'network');
},2000);
},1500);
$(".st").hover(function(){
$(".searcTime .st").click(function(){
var status = $(this).data('status');
if (status == 'show'){
$(this).next().hide();
$(this).data('status','hide');
} else{
$(this).next().show();
$(this).data('status','show');
}
});
//自定义时间-切换
$(".searcTime .st").hover(function(){
$(this).data('status','show');
$(this).next().show();
},function(){
$(this).next().hide();
$(this).next().hover(function(){
$(this).show();
},function(){
$(this).hide();
})
// $(this).next().hide();
// $(this).next().hover(function(){
// $(this).show();
// },function(){
// $(this).hide();
// })
})
$(".searcTime .gt").click(function(){
$(this).addClass("on").siblings().removeClass("on");
})
$(".loadbtn").click(function(){
$(this).parents(".searcTime").find("span").removeClass("on");
$(this).parents(".searcTime").find(".st").addClass("on");
var b = (new Date($(this).parent().find(".btime").val()).getTime())/1000;
var e = (new Date($(this).parent().find(".etime").val()).getTime())/1000;
//渲染日期时间范围 start
var render_dlist = [
'loadbtn_rtime',
'cpubtn_rtime',
'membtn_rtime',
'diskbtn_rtime',
'networkbtn_rtime'
];
for (var i = 0; i < render_dlist.length; i++) {
laydate.render({
elem: '#'+render_dlist[i]
,type: 'datetime'
,range: true
});
var b = getBeforeDate(28).replaceAll('/','-') + " 00:00:00";
var e = getBeforeDate(0).replaceAll('/','-') + " 23:59:59";
$('#'+render_dlist[i]).val(b + ' - ' + e);
}
//渲染日期时间范围 end
$('.sbtn').click(function(){
$(".searcTime .st").next().hide();
var rtime = $(this).parent().find(".rtime").val();
var rarr = rtime.split(' - ');
var b = (new Date(rarr[0]).getTime())/1000;
var e = (new Date(rarr[1]).getTime())/1000;
b = Math.round(b);
e = Math.round(e);
getload(b,e)
})
$(".cpubtn").click(function(){
$(this).parents(".searcTime").find("span").removeClass("on");
$(this).parents(".searcTime").find(".st").addClass("on");
var b = (new Date($(this).parent().find(".btime").val()).getTime())/1000;
var e = (new Date($(this).parent().find(".etime").val()).getTime())/1000;
b = Math.round(b);
e = Math.round(e);
cpu(b,e)
})
$(".membtn").click(function(){
$(this).parents(".searcTime").find("span").removeClass("on");
$(this).parents(".searcTime").find(".st").addClass("on");
var b = (new Date($(this).parent().find(".btime").val()).getTime())/1000;
var e = (new Date($(this).parent().find(".etime").val()).getTime())/1000;
b = Math.round(b);
e = Math.round(e);
mem(b,e)
})
$(".diskbtn").click(function(){
$(this).parents(".searcTime").find("span").removeClass("on");
$(this).parents(".searcTime").find(".st").addClass("on");
var b = (new Date($(this).parent().find(".btime").val()).getTime())/1000;
var e = (new Date($(this).parent().find(".etime").val()).getTime())/1000;
b = Math.round(b);
e = Math.round(e);
disk(b,e)
})
$(".networkbtn").click(function(){
$(this).parents(".searcTime").find("span").removeClass("on");
$(this).parents(".searcTime").find(".st").addClass("on");
var b = (new Date($(this).parent().find(".btime").val()).getTime())/1000;
var e = (new Date($(this).parent().find(".etime").val()).getTime())/1000;
b = Math.round(b);
e = Math.round(e);
network(b,e)
})
if ($(this).hasClass('loadbtn')){
getload(b,e);
} else if ($(this).hasClass('cpubtn')){
cpu(b,e);
}else if ($(this).hasClass('membtn')){
mem(b,e);
} else if ($(this).hasClass('diskbtn')){
disk(b,e);
}
});
//指定天数
function Wday(day,name){
var now = (new Date().getTime())/1000;
@@ -94,19 +116,19 @@ function Wday(day,name){
}
switch (name){
case "cpu":
cpu(b,e);
cpu(b, e);
break;
case "mem":
mem(b,e);
mem(b, e);
break;
case "disk":
disk(b,e);
disk(b, e);
break;
case "network":
network(b,e);
network(b, e);
break;
case "getload":
getload(b,e);
getload(b, e);
break;
}
}
@@ -119,6 +141,7 @@ function getToday(){
return str;
}
getStatus();
//取监控状态
function getStatus(){
loadT = layer.msg('正在读取,请稍候...',{icon:16,time:0})
@@ -141,7 +164,7 @@ function getStatus(){
},'json');
}
getStatus();
//设置监控状态
function setControl(act, value=false){
@@ -172,8 +195,9 @@ function setControl(act, value=false){
loadT = layer.msg('正在处理,请稍候...',{icon:16,time:0})
$.post('/system/set_control','type='+type+'&day='+day,function(rdata){
layer.close(loadT);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
showMsg(rdata.msg, function(){
layer.close(loadT);
},{icon:rdata.status?1:2})
},'json');
}
@@ -183,8 +207,9 @@ function closeControl(){
layer.confirm('您真的清空所有监控记录吗?',{title:'清空记录',icon:3,closeBtn:1}, function() {
loadT = layer.msg('正在处理,请稍候...',{icon:16,time:0})
$.post('/system/set_control','type=del',function(rdata){
layer.close(loadT);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
showMsg(rdata.msg, function(){
layer.close(loadT);
},{icon:rdata.status?1:2})
},'json');
});
}
@@ -199,19 +224,18 @@ function getBeforeDate(n){
var day=d.getDate();
if(day <= n){
if(mon>1) {
mon=mon-1;
}
else {
year = year-1;
mon = 12;
mon = mon-1;
} else {
year = year-1;
mon = 12;
}
}
d.setDate(d.getDate()-n);
year = d.getFullYear();
mon=d.getMonth()+1;
day=d.getDate();
s = year+"/"+(mon<10?('0'+mon):mon)+"/"+(day<10?('0'+day):day);
return s;
s = year+"/"+(mon<10?('0'+mon):mon)+"/"+(day<10?('0'+day):day);
return s;
}
//cpu
function cpu(b,e){
@@ -229,20 +253,14 @@ function cpu(b,e){
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
axisPointer: { type: 'cross' },
formatter: '{b}<br />{a}: {c}%'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xData,
axisLine:{
lineStyle:{
color:"#666"
}
}
axisLine:{ lineStyle:{ color:"#666"} }
},
yAxis: {
type: 'value',
@@ -250,16 +268,8 @@ function cpu(b,e){
boundaryGap: [0, '100%'],
min:0,
max: 100,
splitLine:{
lineStyle:{
color:"#ddd"
}
},
axisLine:{
lineStyle:{
color:"#666"
}
}
splitLine:{ lineStyle:{ color:"#ddd" } },
axisLine:{ lineStyle:{ color:"#666" } }
},
dataZoom: [{
type: 'inside',
@@ -286,17 +296,13 @@ function cpu(b,e){
smooth:true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgb(0, 153, 238)'
}
},
itemStyle: { normal: { color: 'rgb(0, 153, 238)' } },
data: yData
}
]
};
myChartCpu.setOption(option);
window.addEventListener("resize",function(){
window.addEventListener("resize",function(){
myChartCpu.resize();
});
},'json');
@@ -318,20 +324,14 @@ function mem(b,e){
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
axisPointer: { type: 'cross' },
formatter: '{b}<br />{a}: {c}%'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xData,
axisLine:{
lineStyle:{
color:"#666"
}
}
axisLine:{ lineStyle:{ color:"#666" } }
},
yAxis: {
type: 'value',
@@ -339,16 +339,8 @@ function mem(b,e){
boundaryGap: [0, '100%'],
min:0,
max: 100,
splitLine:{
lineStyle:{
color:"#ddd"
}
},
axisLine:{
lineStyle:{
color:"#666"
}
}
splitLine:{ lineStyle:{ color:"#ddd" } },
axisLine:{ lineStyle:{ color:"#666" } }
},
dataZoom: [{
type: 'inside',
@@ -375,11 +367,7 @@ function mem(b,e){
smooth:true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgb(0, 153, 238)'
}
},
itemStyle: { normal: { color: 'rgb(0, 153, 238)' } },
data: zData
}
]
@@ -423,26 +411,14 @@ function disk(b,e){
type: 'category',
boundaryGap: false,
data: xData,
axisLine:{
lineStyle:{
color:"#666"
}
}
axisLine:{ lineStyle:{ color:"#666" }}
},
yAxis: {
type: 'value',
name: '单位:KB/s',
boundaryGap: [0, '100%'],
splitLine:{
lineStyle:{
color:"#ddd"
}
},
axisLine:{
lineStyle:{
color:"#666"
}
}
splitLine:{ lineStyle:{ color:"#ddd"} },
axisLine:{ lineStyle:{ color:"#666" } }
},
dataZoom: [{
type: 'inside',
@@ -469,11 +445,7 @@ function disk(b,e){
smooth:true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgb(255, 70, 131)'
}
},
itemStyle: { normal: { color: 'rgb(255, 70, 131)' } },
data: rData
},
{
@@ -482,11 +454,7 @@ function disk(b,e){
smooth:true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgba(46, 165, 186, .7)'
}
},
itemStyle: { normal: { color: 'rgba(46, 165, 186, .7)'} },
data: wData
}
]
@@ -522,9 +490,7 @@ function network(b,e){
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
axisPointer: { type: 'cross' }
},
legend: {
data:[lan.index.net_up,lan.index.net_down]
@@ -533,26 +499,14 @@ function network(b,e){
type: 'category',
boundaryGap: false,
data: xData,
axisLine:{
lineStyle:{
color:"#666"
}
}
axisLine:{ lineStyle:{ color:"#666" } }
},
yAxis: {
type: 'value',
name: lan.index.unit+':KB/s',
boundaryGap: [0, '100%'],
splitLine:{
lineStyle:{
color:"#ddd"
}
},
axisLine:{
lineStyle:{
color:"#666"
}
}
splitLine:{ lineStyle:{ color:"#ddd" } },
axisLine:{ lineStyle:{ color:"#666" } }
},
dataZoom: [{
type: 'inside',
@@ -579,11 +533,7 @@ function network(b,e){
smooth:true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgb(255, 140, 0)'
}
},
itemStyle: { normal: { color: 'rgb(255, 140, 0)' } },
data: yData
},
{
@@ -592,11 +542,7 @@ function network(b,e){
smooth:true,
symbol: 'none',
sampling: 'average',
itemStyle: {
normal: {
color: 'rgb(30, 144, 255)'
}
},
itemStyle: { normal: { color: 'rgb(30, 144, 255)' } },
data: zData
}
]
@@ -879,17 +825,8 @@ function getload(b,e){
{
name: '资源使用率%',
type: 'line',
lineStyle: {
normal: {
width: 2,
color: 'rgb(255, 140, 0)'
}
},
itemStyle: {
normal: {
color: 'rgb(255, 140, 0)'
}
},
lineStyle: { normal: { width: 2, color: 'rgb(255, 140, 0)'}},
itemStyle: {normal: { color: 'rgb(255, 140, 0)' }},
data: yData
},
{
@@ -897,17 +834,8 @@ function getload(b,e){
yAxisIndex: 1,
name: '1分钟',
type: 'line',
lineStyle: {
normal: {
width: 2,
color: 'rgb(30, 144, 255)'
}
},
itemStyle: {
normal: {
color: 'rgb(30, 144, 255)'
}
},
lineStyle: { normal: {width: 2,color: 'rgb(30, 144, 255)' }},
itemStyle: { normal: { color: 'rgb(30, 144, 255)'} },
data: zData
},
{
@@ -915,17 +843,8 @@ function getload(b,e){
yAxisIndex: 1,
name: '5分钟',
type: 'line',
lineStyle: {
normal: {
width: 2,
color: 'rgb(0, 178, 45)'
}
},
itemStyle: {
normal: {
color: 'rgb(0, 178, 45)'
}
},
lineStyle: { normal: { width: 2, color: 'rgb(0, 178, 45)'} },
itemStyle: { normal: { color: 'rgb(0, 178, 45)' } },
data: aData
},
{
@@ -933,28 +852,16 @@ function getload(b,e){
yAxisIndex: 1,
name: '15分钟',
type: 'line',
lineStyle: {
normal: {
width: 2,
color: 'rgb(147, 38, 255)'
}
},
itemStyle: {
normal: {
color: 'rgb(147, 38, 255)'
}
},
lineStyle: { normal: { width: 2, color: 'rgb(147, 38, 255)'}},
itemStyle: { normal: { color: 'rgb(147, 38, 255)' } },
data: bData
}
],
textStyle: {
color: '#666',
fontSize: 12
}
textStyle: { color: '#666',fontSize: 12}
}
myChartgetload.setOption(option);
window.addEventListener("resize",function(){
myChartgetload.resize();
})
},'json')
},'json');
}
+10 -17
View File
@@ -789,18 +789,15 @@ function batchPasteTo(data,path){
function getSuffixName(fileName){
var extArr = fileName.split(".");
var exts = ['folder','folder-unempty','sql','c','cpp','cs','flv','css','js',
var exts = ['folder-unempty','sql','c','cpp','cs','flv','css','js',
'htm','html','java','log','mht','url','xml','ai','bmp','cdr','gif','ico',
'jpeg','jpg','JPG','png','psd','webp','ape','avi','flv','mkv','mov','mp3','mp4',
'jpeg','jpg','JPG','png','psd','webp','ape','avi','mkv','mov','mp3','mp4',
'mpeg','mpg','rm','rmvb','swf','wav','webm','wma','wmv','rtf','docx','fdf','potm',
'pptx','txt','xlsb','xlsx','7z','cab','iso','rar','zip','gz','bt','file','apk','bookfolder',
'folder','folder-empty','folder-unempty','fromchromefolder','documentfolder','fromphonefolder',
'mix','musicfolder','picturefolder','videofolder','sefolder','access','mdb','accdb','sql','c',
'cpp','cs','js','fla','flv','htm','html','java','mht','url','xml','ai','bmp','cdr',
'gif','ico','jpeg','jpg','JPG','png','psd','webp','ape','avi','flv','mkv','mov','mp3','mp4','mpeg',
'mpg','rm','rmvb','swf','wav','webm','wma','wmv','doc','docm','dotx','dotm','dot','rtf','docx','pdf',
'fdf','ppt','pptm','pot','potm','pptx','txt','xls','csv','xlsm','xlsb','xlsx','7z','gz','cab','iso',
'rar','zip','bt','file','apk','css','scss','svg','pl','py','php','md','json','sh'];
'folder','folder-empty','fromchromefolder','documentfolder','fromphonefolder',
'mix','musicfolder','picturefolder','videofolder','sefolder','access','mdb','accdb',
'fla','doc','docm','dotx','dotm','dot','pdf',
'ppt','pptm','pot','xls','csv','xlsm','scss','svg','pl','py','php','md','json','sh','conf'];
var extLastName = extArr[extArr.length - 1];
for(var i=0; i<exts.length; i++){
if(exts[i]==extLastName){
@@ -818,13 +815,9 @@ function getExtName(fileName){
'jpeg','jpg','JPG','png','psd','webp','ape','avi','flv','mkv','mov','mp3','mp4',
'mpeg','mpg','rm','rmvb','swf','wav','webm','wma','wmv','rtf','docx','fdf','potm',
'pptx','txt','xlsb','xlsx','7z','cab','iso','rar','zip','gz','bt','file','apk','bookfolder',
'folder','folder-empty','folder-unempty','fromchromefolder','documentfolder','fromphonefolder',
'mix','musicfolder','picturefolder','videofolder','sefolder','access','mdb','accdb','sql','c',
'cpp','cs','js','fla','flv','htm','html','java','log','mht','url','xml','ai','bmp','cdr',
'gif','ico','jpeg','jpg','JPG','png','psd','webp','ape','avi','flv','mkv','mov','mp3','mp4','mpeg',
'mpg','rm','rmvb','swf','wav','webm','wma','wmv','doc','docm','dotx','dotm','dot','rtf','docx','pdf',
'fdf','ppt','pptm','pot','potm','pptx','txt','xls','csv','xlsm','xlsb','xlsx','7z','gz','cab','iso',
'rar','zip','bt','file','apk','css'];
'folder-empty','fromchromefolder','documentfolder','fromphonefolder',
'mix','musicfolder','picturefolder','videofolder','sefolder','access','mdb','accdb',
'fla','flv','doc','docm','dotx','dotm','dot','pdf','ppt','pptm','pot','xls','csv','xlsm'];
var extLastName = extArr[extArr.length - 1];
for(var i=0; i<exts.length; i++){
if(exts[i]==extLastName){
@@ -842,7 +835,7 @@ function ShowEditMenu(){
$(this).removeClass("hover");
}).click(function(){
$(this).addClass("on").siblings().removeClass("on");
})
});
}
//取磁盘
+299 -145
View File
@@ -1301,7 +1301,7 @@ function showRewrite(rdata){
<select class='bt-input-text mr20' id='myRewrite' name='rewrite' style='width:30%;'>"+rList+"</select>\
<textarea class='bt-input-text mtb15' style='height: 260px; width: 470px; line-height:18px;padding:5px;' id='rewriteBody'>"+rdata.data+"</textarea>\
</div>\
<button id='SetRewriteBtn' class='btn btn-success btn-sm' onclick=\"SetRewrite('"+rdata.filename+"')\">保存</button>\
<button id='setRewriteBtn' class='btn btn-success btn-sm'>保存</button>\
<ul class='help-info-text c7 ptb10'>\
<li>请选择您的应用,若设置伪静态后,网站无法正常访问,请尝试设置回default</li>\
<li>您可以对伪静态规则进行修改,修改完后保存即可。</li>\
@@ -1314,14 +1314,21 @@ function showRewrite(rdata){
closeBtn: 1,
shift: 5,
shadeClose: true,
content:webBakHtml
});
$("#myRewrite").change(function(){
var rewriteName = $(this).val();
$.post('/files/get_body','path='+rdata['rewrite_dir']+'/'+rewriteName+'.conf',function(fileBody){
$("#rewriteBody").val(fileBody.data.data);
},'json');
content:webBakHtml,
success:function(){
$("#myRewrite").change(function(){
var rewriteName = $(this).val();
$.post('/files/get_body','path='+rdata['rewrite_dir']+'/'+rewriteName+'.conf',function(fileBody){
$("#rewriteBody").val(fileBody.data.data);
},'json');
});
$('#setRewriteBtn').click(function(){
var data = $("#rewriteBody").val();
setRewrite(rdata.filename, encodeURIComponent(data));
});
}
});
}
@@ -1334,7 +1341,7 @@ function addDirBinding(id){
return;
}
var data = 'id='+id+'&domain='+domain+'&dirName='+dirName
var data = 'id='+id+'&domain='+domain+'&dirName='+dirName;
$.post('/site/add_dir_bind',data,function(rdata){
dirBinding(id);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
@@ -1554,82 +1561,164 @@ function to301(siteName, type, obj){
}
function toProxySwitch(){
var status = $("input[name='open_proxy']").prop("checked")==true?1:0;
if(status==1){
$("input[name='open_proxy']").prop("checked",false);
}else{
$("input[name='open_proxy']").prop("checked",true);
}
}
//反向代理
function toProxy(siteName, type, obj) {
// 设置 页面展示
if(type == 1) {
var proxy_form = layer.open({
var proxy_title = "创建反向代理";
if (typeof(obj) != 'undefined'){
proxy_title = "编辑反向代理";
}
layer.open({
type: 1,
area: '650px',
title: "创建反向代理",
title: proxy_title,
closeBtn: 1,
shift: 5,
shadeClose: false,
btn: ['提交','关闭'],
content: "<form id='form_redirect' class='divtable pd15' style='padding-bottom: 10px'>" +
"<div class='line'>" +
'<span class="tname">开启代理</span>'+
"<div class='info-r ml0'>" +
"<input name='open_proxy' class='btswitch btswitch-ios' type='checkbox' checked><label id='open_proxy' class='btswitch-btn' for='openProxy' onclick='toProxySwitch();'></label>" +
"</div>" +
"</div>" +
"<div class='line'>"+
"<span class='tname'>代理目录</span>" +
"<div class='info-r ml0'>" +
"<input name='from' value='/' placeholder='/' class='bt-input-text mr5' type='text' style='width:200px''>" +
"</div>" +
"</div>" +
"<div class='line'>" +
"<span class='tname'>目标URL</span>" +
"<div class='info-r ml0'>" +
"<input name='to' class='bt-input-text mr5' type='text' style='width:200px;float: left;margin-right:0px''>" +
"<span class='tname' style='width:90px'>发送域名</span>" +
"<input name='host' value='$host' class='bt-input-text mr5' type='text' style='width:200px'>" +
"</div>" +
"</div>" +
"<div class='help-info-text c7'>" +
"<ul class='help-info-text c7'>" +
"<li>代理目录:访问这个目录时将会把目标URL的内容返回并显示</li>" +
"<li>目标URL:可以填写你需要代理的站点,目标URL必须为可正常访问的URL,否则将返回错误</li>" +
"<li>发送域名:将域名添加到请求头传递到代理服务器,默认为目标URL域名,若设置不当可能导致代理无法正常运行</li>" +
"</ul>" +
"</div>" +
"</form>",
yes:function(){
var data = $('#form_redirect').serializeArray();
content: "<form id='form_proxy' class='divtable pd15' style='padding-bottom: 10px'>\
<div class='line'>\
<span class='tname'>开启代理</span>\
<div class='info-r ml0 mt5'>\
<input name='open_proxy' class='btswitch btswitch-ios' type='checkbox' checked>\
<label id='open_proxy' class='btswitch-btn' for='openProxy' style='float:left'></label>\
<div style='display: inline-block'>\
<span class='tname' style='margin-left:15px;position: relative;top: -5px;'>是否缓存</span>\
<input class='btswitch btswitch-ios' type='checkbox' name='open_cache'>\
<label class='btswitch-btn' id='open_cache' for='openCache' style='float:left'></label>\
</div>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>名称</span>\
<div class='info-r ml0'>\
<input name='name' value='index' placeholder='请输入名称' class='bt-input-text mr5' type='text' style='width:200px''>\
</div>\
</div>\
<div class='line' style='display:none' id='cache_time'>\
<span class='tname'>缓存时间</span>\
<div class='info-r ml0'>\
<input name='cache_time' value='1' class='bt-input-text mr5' type='text' style='width:200px''>分钟\
</div>\
</div>\
<div class='line'>\
<span class='tname'>代理目录</span>\
<div class='info-r ml0'>\
<input name='from' value='/' placeholder='/' class='bt-input-text mr5' type='text' style='width:200px''>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>目标URL</span>\
<div class='info-r ml0'>\
<input name='to' class='bt-input-text mr5' type='text' style='width:200px;float: left;margin-right:0px''>\
<span class='tname' style='width:90px'>发送域名</span>\
<input name='host' value='$host' class='bt-input-text mr5' type='text' style='width:200px'>\
</div>\
</div>\
<input name='id' value='' type='hidden'>\
<div class='help-info-text c7'>\
<ul class='help-info-text c7'>\
<li>代理目录:访问这个目录时将会把目标URL的内容返回并显示</li>\
<li>目标URL:可以填写你需要代理的站点,目标URL必须为可正常访问的URL,否则将返回错误</li>\
<li>发送域名:将域名添加到请求头传递到代理服务器,默认为目标URL域名,若设置不当可能导致代理无法正常运行</li>\
</ul>\
</div>\
</form>",
success:function(){
if (typeof(obj) != 'undefined'){
// console.log(obj);
$('input[name="name"]').val(obj['name']).attr('readonly','readonly').addClass('disabled');
if (obj['open_cache'] == 'on'){
$("input[name='open_cache']").prop("checked",true);
$('#cache_time').show();
}
$('input[name="from"]').val(obj['from']);
$('input[name="to"]').val(obj['to']);
var url = obj['to'];
var ip_reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
url = url.replace(/^http[s]?:\/\//, '');
url = url.replace(/(:|\?|\/|\\)(.*)$/, '');
if (ip_reg.test(url)) {
$("[name='host']").val('$host');
} else {
$("[name='host']").val(url);
}
$('input[name="id"]').val(obj['id']);
$('input[name="cache_time"]').val(obj['cache_time']);
}
$('input[name="to"]').on('keyup', function(){
var url = $(this).val();
var ip_reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
url = url.replace(/^http[s]?:\/\//, '');
url = url.replace(/(:|\?|\/|\\)(.*)$/, '');
if (ip_reg.test(url)) {
$("[name='host']").val('$host');
} else {
$("[name='host']").val(url);
}
});
$("#open_proxy").click(function(){
var status = $("input[name='open_proxy']").prop("checked")==true?1:0;
if(status==1){
$("input[name='open_proxy']").prop("checked",false);
}else{
$("input[name='open_proxy']").prop("checked",true);
}
});
$('#open_cache').click(function(){
var status = $("input[name='open_cache']").prop("checked")==true?1:0;
if(status==1){
$('#cache_time').hide();
$("input[name='open_cache']").prop("checked",false);
}else{
$('#cache_time').show();
$("input[name='open_cache']").prop("checked",true);
}
});
},
yes:function(index,layer_ro){
var data = $('#form_proxy').serializeArray();
var t = {};
t['name'] = 'siteName';
t['value'] = siteName;
data.push(t);
var loading = layer.msg('添加中...',{icon:16,time:0,shade: [0.3, '#000']});
// console.log(data);
var loading = layer.msg('正在'+proxy_title+'...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/set_proxy',data, function(res) {
layer.close(loading);
if (res.status) {
layer.close(proxy_form);
toProxy(siteName)
} else {
layer.msg(res.msg, {icon: 2});
if (!res.status){
layer.msg(res.msg, {icon: 2,time:10000});
return;
}
showMsg(proxy_title+"成功!",function(){
layer.close(index);
toProxy(siteName);
},{icon: 1, time:2000});
},'json');
}
});
}
if (type == 2) {
var loading = layer.msg('正在删除中...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/del_proxy', {siteName: siteName,id: obj,}, function(res) {
layer.close(loading);
if (res.status == true) {
layer.msg('删除成功', {time: 1000,icon: 1});
toProxy(siteName)
showMsg('删除成功', function(){
toProxy(siteName);
},{time: 1000,icon: 1});
} else {
layer.msg(res.msg, {time: 1000,icon: 2});
}
@@ -1643,90 +1732,118 @@ function toProxy(siteName, type, obj) {
var data = {siteName: siteName,id: obj};
$.post('/site/get_proxy_conf', data, function(res) {
layer.close(laoding);
if (res.status == true) {
var mBody = "<div class='webEdit-box' style='padding: 20px'>\
<textarea style='height: 320px; width: 445px; margin-left: 20px; line-height:18px' id='configProxyBody'>"+res.data.result+"</textarea>\
<div class='info-r'>\
<ul class='help-info-text c7 ptb10'>\
<li>此处为反向代理配置文件,若您不了解配置规则,请勿随意修改.</li>\
</ul>\
</div>\
</div>";
var editor;
var index = layer.open({
type: 1,
title: '编辑配置文件',
closeBtn: 1,
shadeClose: true,
area: ['500px', '500px'],
btn: ['提交','关闭'],
content: mBody,
success: function () {
editor = CodeMirror.fromTextArea(document.getElementById("configProxyBody"), {
extraKeys: {"Ctrl-Space": "autocomplete"},
lineNumbers: true,
matchBrackets:true,
});
editor.focus();
$(".CodeMirror-scroll").css({"height":"300px","margin":0,"padding":0});
$("#onlineEditFileBtn").unbind('click');
},
yes:function(index,layero){
$("#configProxyBody").empty().text(editor.getValue());
var load = layer.load();
var data = {
siteName: siteName,
id: obj,
config: editor.getValue(),
};
$.post('/site/save_proxy_conf', data, function(res) {
layer.close(load)
if (res.status == true) {
layer.msg('保存成功', {icon: 1});
layer.close(index);
} else {
layer.msg(res.msg, {time: 3000,icon: 2});
}
},'json');
return true;
},
});
} else {
if (!res.status){
layer.msg('请求错误!!', {time: 3000,icon: 2});
return;
}
var mBody = "<div class='webEdit-box' style='padding: 20px'>\
<textarea style='height: 320px; width: 445px; margin-left: 20px; line-height:18px' id='configProxyBody'>"+res.data.result+"</textarea>\
<div class='info-r'>\
<ul class='help-info-text c7 ptb10'>\
<li>此处为反向代理配置文件,若您不了解配置规则,请勿随意修改.</li>\
</ul>\
</div>\
</div>";
var editor;
var index = layer.open({
type: 1,
title: '编辑配置文件',
closeBtn: 1,
shadeClose: true,
area: ['500px', '500px'],
btn: ['提交','关闭'],
content: mBody,
success: function () {
editor = CodeMirror.fromTextArea(document.getElementById("configProxyBody"), {
extraKeys: {"Ctrl-Space": "autocomplete"},
lineNumbers: true,
matchBrackets:true,
});
editor.focus();
$(".CodeMirror-scroll").css({"height":"300px","margin":0,"padding":0});
$("#onlineEditFileBtn").unbind('click');
},
yes:function(index,layero){
$("#configProxyBody").empty().text(editor.getValue());
var load = layer.load();
var data = {
siteName: siteName,
id: obj,
config: editor.getValue(),
};
$.post('/site/save_proxy_conf', data, function(res) {
layer.close(load)
if (res.status == true) {
layer.msg('保存成功', {icon: 1});
layer.close(index);
} else {
layer.msg(res.msg, {time: 3000,icon: 2});
}
},'json');
return true;
},
});
},'json');
return
return;
}
if (type == 10 || type == 11) {
//[11]启动 或 停止[10]
status = type==10 ? '0' : '1';
var loading = layer.msg(lan.site.the_msg,{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/set_proxy_status', {siteName: siteName,'status':status,'id':obj}, function(res) {
$.post('/site/set_proxy_status', {siteName: siteName,'status':status,'id':obj}, function(rdata) {
layer.close(loading);
if (res.status == true) {
layer.msg('设置成功', {icon: 1});
toProxy(siteName);
} else {
if (!rdata.status){
layer.msg(res.msg, {time: 3000,icon: 2});
return;
}
showMsg("设置成功",function(){
toProxy(siteName);
},{icon: 1,time:2000});
},'json');
return;
}
if (type == 20 || type == 21) {
//[20] 开始缓存 或 [21] 停止缓存
var status = type == 20 ? 'on' : '';
obj['open_cache'] = status;
obj['siteName'] = siteName;
var loading = layer.msg('正在提交请求...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/set_proxy',obj, function(rdata) {
layer.close(loading);
if (!rdata.status){
layer.msg(rdata.msg, {icon: 2,time:2000});
return;
}
showMsg("设置成功!",function(){
toProxy(siteName);
},{icon: 1, time:2000});
},'json');
return;
}
var body = '<div id="proxy_list" class="bt_table">\
<div style="padding-bottom: 10px">\
<button type="button" title="添加反向代理" class="btn btn-success btn-sm mr5" onclick="toProxy(\''+siteName+'\',1)" ><span>添加反向代理</span></button>\
<button type="button" title="添加反向代理" class="btn btn-success btn-sm mr5" onclick="toProxy(\''+siteName+'\',1)" >\
<span>添加反向代理</span>\
</button>\
</div>\
<div class="divtable" style="max-height:200px;">\
<table class="table table-hover" >\
<thead style="position: relative;z-index: 1;">\
<tr>\
<th><span data-index="1"><span>代理目录</span></span></th>\
<th><span data-index="2"><span>目标地址</span></span></th>\
<th><span data-index="2"><span>状态</span></span></th>\
<th><span data-index="3"><span>操作</span></span></th>\
<th>名称</th>\
<th>代理目录</th>\
<th>目标地址</th>\
<th>缓存</th>\
<th>状态</th>\
<th>操作</th>\
</tr>\
</thead>\
<tbody id="md-301-body"></tbody>\
@@ -1738,28 +1855,64 @@ function toProxy(siteName, type, obj) {
var loading = layer.msg(lan.site.the_msg,{icon:16,time:0,shade: [0.3, '#000']});
$.post("/site/get_proxy_list", {siteName: siteName},function (res) {
layer.close(loading);
if (res.status === true) {
let data = res.data.result;
data.forEach(function(item){
var switchProxy = '<span onclick="toProxy(\''+siteName+'\', 10, \''+ item.id +'\')" style="color:rgb(92, 184, 92);" class="btlink glyphicon glyphicon-play"></span>';
if (!item['status']){
switchProxy = '<span onclick="toProxy(\''+siteName+'\', 11, \''+ item.id +'\')" style="color:rgb(255, 0, 0);" class="btlink glyphicon glyphicon-pause"></span>';
}
let tmp = '<tr>\
<td><span data-index="1"><span>'+item.from+'</span></span></td>\
<td><span data-index="2"><span>'+item.to+'</span></span></td>\
<td>'+switchProxy+'</td>\
<td>\
<span data-index="4" onclick="toProxy(\''+siteName+'\', 3, \''+ item.id +'\')" class="btlink">详细</span> |\
<span data-index="4" onclick="toProxy(\''+siteName+'\', 2, \''+ item.id +'\')" class="btlink">删除</span>\
</td>\
</tr>';
$("#md-301-body").append(tmp);
})
} else {
if (!res.status){
layer.msg(res.msg, {icon:2});
return;
}
var data = res.data.result;
for (var i = 0; i < data.length; i++) {
var item = data[i];
var switchProxy = '<span onclick="toProxy(\''+siteName+'\', 10, \''+ item.id +'\')" style="color:rgb(92, 184, 92);" class="btlink glyphicon glyphicon-play"></span>';
if (!item['status']){
switchProxy = '<span onclick="toProxy(\''+siteName+'\', 11, \''+ item.id +'\')" style="color:rgb(255, 0, 0);" class="btlink glyphicon glyphicon-pause"></span>';
}
var openCache = '<span data-index="'+i+'" class="btlink cache off">未开启</span>';
if (item['open_cache'] == 'on'){
openCache = '<span data-index="'+i+'" class="btlink cache on">已开启</span>';
}
let tmp = '<tr>\
<td>'+item.name+'</td>\
<td>'+item.from+'</td>\
<td>'+item.to+'</td>\
<td>'+openCache+'</td>\
<td>'+switchProxy+'</td>\
<td>\
<span data-index="'+i+'" class="btlink detail">详细</span> |\
<span data-index="'+i+'" class="btlink edit">编辑</span> |\
<span data-index="'+i+'" class="btlink delete">删除</span>\
</td>\
</tr>';
$("#md-301-body").append(tmp);
}
$('#md-301-body .detail').click(function(){
var index = $(this).data('index');
toProxy(siteName, 3 ,data[index]['id']);
});
$('#md-301-body .edit').click(function(){
var index = $(this).data('index');
toProxy(siteName, 1 ,data[index]);
});
$('#md-301-body .delete').click(function(){
var index = $(this).data('index');
toProxy(siteName, 2 ,data[index]['id']);
});
$('#md-301-body .cache').click(function(){
var index = $(this).data('index');
if ($(this).hasClass('on')){
toProxy(siteName, 21 ,data[index]);
} else{
toProxy(siteName, 20 ,data[index]);
}
});
},'json');
/////////
}
@@ -1772,7 +1925,8 @@ function sslAdmin(siteName){
var rdata = data['data'];
var tbody = '';
for(var i=0;i<rdata.length;i++){
tbody += '<tr><td>'+rdata[i].subject+'</td>\
tbody += '<tr>\
<td>'+rdata[i].subject+'</td>\
<td>'+rdata[i].dns.join('<br>')+'</td>\
<td>'+rdata[i].notAfter+'</td>\
<td>'+rdata[i].issuer.split(' ')[0]+'</td>\
@@ -2428,7 +2582,7 @@ function rewrite(siteName){
$("#SetRewriteBtn").click(function(){
$("#rewriteBody").empty();
$("#rewriteBody").text(editor.getValue());
setRewrite(filename);
setRewrite(filename, encodeURIComponent(editor.getValue()));
});
$("#SetRewriteBtnTel").click(function(){
$("#rewriteBody").empty();
@@ -2460,8 +2614,8 @@ function rewrite(siteName){
//设置伪静态
function setRewrite(filename){
var data = 'data='+encodeURIComponent($("#rewriteBody").val())+'&path='+filename+'&encoding=utf-8';
function setRewrite(filename,data){
var data = 'data='+data+'&path='+filename+'&encoding=utf-8';
var loadT = layer.msg(lan.site.saving_txt,{icon:16,time:0,shade: [0.3, '#000']});
$.post('/site/set_rewrite',data,function(rdata){
layer.close(loadT);
+28 -9
View File
@@ -1805,7 +1805,7 @@ html .menu .menu_exit:hover {
.view1,
.view2 {
margin-bottom: 15px
margin-bottom: 15px;
}
.searcTime {
@@ -1840,7 +1840,7 @@ html .menu .menu_exit:hover {
display: inline-block;
position: relative;
float: left;
line-height: 16px
line-height: 16px;
}
.searcTime .ss .st {
@@ -1848,7 +1848,7 @@ html .menu .menu_exit:hover {
border: #ddd 1px solid;
margin-right: -1px;
cursor: pointer;
float: left
float: left;
}
.searcTime .ss .time {
@@ -1859,26 +1859,27 @@ html .menu .menu_exit:hover {
position: absolute;
right: -1px;
top: 27px;
width: 217px;
z-index: 99
width: 306px;
z-index: 99;
}
.searcTime .ss .time span {
margin-bottom: 10px;
display: block
display: block;
}
.searcTime .ss .time input {
border: 1px solid #ddd;
height: 22px;
padding: 0 5px;
width: 132px
margin-left:5px;
width: 227px;
}
.searcTime .ss .time input:focus {
border: #66afe9 1px solid;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6)
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
}
.searcTime .ss .sbtn {
@@ -4502,7 +4503,7 @@ html .menu .menu_exit:hover {
margin-right: 3px;
}
/*微信二维码*/
.boxConter {
.boxConter {
height: 458px;
position: relative;
overflow: auto;
@@ -4853,3 +4854,21 @@ select[disabled]{
font-weight: 400;
}
#form_proxy .sub-groud .bt-input-text{
margin-right: 10px;
}
#form_proxy .sub-groud {
margin-bottom: 15px;
}
#form_proxy .btswitch-btn{
display:inline-block;
}
#form_proxy .add-replace-prosy {
position: relative;
top: -10px;
}
#form_proxy .disabled{
background-color: #eee !important;
cursor: default;
border: 1px solid #dbdbea;
}
+41 -16
View File
@@ -51,14 +51,15 @@
<div class="ss">
<span class="st">自定义时间</span>
<div class="time">
<span class="bt">开始时间<input class="btime" type="text" value="2017/1/10 00:00:00"></span>
<span class="et">结束时间<input class="etime" type="text" value="2017/1/13 00:00:00"></span>
<span class="bt">时间范围
<input id="loadbtn_rtime" class="rtime" type="text" value="2023-07-06 00:00:00 - 2023-08-08 00:00:00">
</span>
<div class="sbtn loadbtn">提交</div>
</div>
</div>
</div>
</div>
<div id="getloadview" style="width:100%; height:330px"></div>
<div id="getloadview" style="width:100%; height:330px;"></div>
</div>
</div>
</div>
@@ -67,12 +68,18 @@
<div class="bgw pb15">
<div class="title c6 plr15">
<h3 class="c-tit f16">CPU</h3>
<div class="searcTime pull-right"><span class="tit">区间检索:</span><span class="gt" onclick="Wday(1,'cpu')">昨天</span><span class="gt on" onclick="Wday(0,'cpu')">今天</span><span class="gt" onclick="Wday(7,'cpu')">最近7天</span><span class="gt" onclick="Wday(30,'cpu')">最近30天</span>
<div class="searcTime pull-right">
<span class="tit">区间检索:</span>
<span class="gt" onclick="Wday(1,'cpu')">昨天</span>
<span class="gt on" onclick="Wday(0,'cpu')">今天</span>
<span class="gt" onclick="Wday(7,'cpu')">最近7天</span>
<span class="gt" onclick="Wday(30,'cpu')">最近30天</span>
<div class="ss">
<span class="st">自定义时间</span>
<div class="time">
<span class="bt">开始时间<input class="btime" type="text" value="2017/1/10 00:00:00"></span>
<span class="et">结束时间<input class="etime" type="text" value="2017/1/13 00:00:00"></span>
<span class="bt">时间范围
<input id="cpubtn_rtime" class="rtime" type="text" value="2023-07-06 00:00:00 - 2023-08-08 00:00:00">
</span>
<div class="sbtn cpubtn">提交</div>
</div>
</div>
@@ -87,12 +94,18 @@
<div class="bgw pb15">
<div class="title c6 plr15">
<h3 class="c-tit f16">内存</h3>
<div class="searcTime pull-right"><span class="tit">区间检索:</span><span class="gt" onclick="Wday(1,'mem')">昨天</span><span class="gt on" onclick="Wday(0,'mem')">今天</span><span class="gt" onclick="Wday(7,'mem')">最近7天</span><span class="gt" onclick="Wday(30,'mem')">最近30天</span>
<div class="searcTime pull-right">
<span class="tit">区间检索:</span>
<span class="gt" onclick="Wday(1,'mem')">昨天</span>
<span class="gt on" onclick="Wday(0,'mem')">今天</span>、
<span class="gt" onclick="Wday(7,'mem')">最近7天</span>
<span class="gt" onclick="Wday(30,'mem')">最近30天</span>
<div class="ss">
<span class="st">自定义时间</span>
<div class="time">
<span class="bt">开始时间<input class="btime" type="text" value="2017/1/10 00:00:00"></span>
<span class="et">结束时间<input class="etime" type="text" value="2017/1/13 00:00:00"></span>
<span class="bt">时间范围
<input id="membtn_rtime" class="rtime" type="text" value="2023-07-06 00:00:00 - 2023-08-08 00:00:00">
</span>
<div class="sbtn membtn">提交</div>
</div>
</div>
@@ -107,12 +120,18 @@
<div class="bgw pb15">
<div class="title c6 plr15 mb15">
<h3 class="c-tit f16">磁盘IO</h3>
<div class="searcTime pull-right"><span class="tit">$data['lan']['S1']</span><span class="gt" onclick="Wday(1,'disk')">昨天</span><span class="gt on" onclick="Wday(0,'disk')">今天</span><span class="gt" onclick="Wday(7,'disk')">最近7天</span><span class="gt" onclick="Wday(30,'disk')">最近30天</span>
<div class="searcTime pull-right">
<span class="tit">$data['lan']['S1']</span>
<span class="gt" onclick="Wday(1,'disk')">昨天</span>
<span class="gt on" onclick="Wday(0,'disk')">今天</span>
<span class="gt" onclick="Wday(7,'disk')">最近7天</span>
<span class="gt" onclick="Wday(30,'disk')">最近30天</span>
<div class="ss">
<span class="st">自定义时间</span>
<div class="time">
<span class="bt">开始时间<input class="btime" type="text" value="2017/1/10 00:00:00"></span>
<span class="et">结束时间<input class="etime" type="text" value="2017/1/13 00:00:00"></span>
<span class="bt">时间范围
<input id="diskbtn_rtime" class="rtime" type="text" value="2023-07-06 00:00:00 - 2023-08-08 00:00:00">
</span>
<div class="sbtn diskbtn">提交</div>
</div>
</div>
@@ -127,12 +146,18 @@
<div class="bgw pb15">
<div class="title c6 plr15 mb15">
<h3 class="c-tit f16">网络IO</h3>
<div class="searcTime pull-right"><span class="tit">$data['lan']['S1']</span><span class="gt" onclick="Wday(1,'network')">昨天</span><span class="gt on" onclick="Wday(0,'network')">今天</span><span class="gt" onclick="Wday(7,'network')">最近7天</span><span class="gt" onclick="Wday(30,'network')">最近30天</span>
<div class="searcTime pull-right">
<span class="tit">$data['lan']['S1']</span>
<span class="gt" onclick="Wday(1,'network')">昨天</span>
<span class="gt on" onclick="Wday(0,'network')">今天</span>
<span class="gt" onclick="Wday(7,'network')">最近7天</span>
<span class="gt" onclick="Wday(30,'network')">最近30天</span>
<div class="ss">
<span class="st">自定义时间</span>
<div class="time">
<span class="bt">开始时间<input class="btime" type="text" value="2017/1/10 00:00:00"></span>
<span class="et">结束时间<input class="etime" type="text" value="2017/1/13 00:00:00"></span>
<span class="bt">时间范围
<input id="networkbtn_rtime" class="rtime" type="text" value="2023-07-06 00:00:00 - 2023-08-08 00:00:00">
</span>
<div class="sbtn networkbtn">提交</div>
</div>
</div>
@@ -146,6 +171,6 @@
</div>
</div>
</div>
<script type="text/javascript" src="/static/laydate/laydate.js?v={{config.version}}"></script>
<script src="/static/app/control.js?v={{config.version}}"></script>
{% endblock %}
+4
View File
@@ -15,6 +15,10 @@ dnf install -y crontabs
dnf install -y mysql-devel
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
+4
View File
@@ -22,6 +22,10 @@ yum install -y mysql-devel
yum install -y expect
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
+4
View File
@@ -55,6 +55,10 @@ echo y | pacman -Syu icu
hwclock --systohc
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
+7
View File
@@ -26,8 +26,14 @@ fi
ntpdate $NTPHOST | logger -t NTP
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# choose lang cmd
# dpkg-reconfigure --frontend=noninteractive locales
if [ ! -f /usr/sbin/locale-gen ];then
@@ -141,6 +147,7 @@ apt install -y devscripts
apt install -y net-tools
apt install -y autoconf
apt install -y gcc
apt install -y patchelf
apt install -y libffi-dev
apt install -y cmake automake make
+4
View File
@@ -18,6 +18,10 @@ yum install -y expect
dnf install crontabs -y
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
+4
View File
@@ -40,6 +40,10 @@ pkg install -y harfbuzz
pkg autoremove -y
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
+4
View File
@@ -53,6 +53,10 @@ zypper install -y freetype2-devel
# zypper install -y php-config
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/iptables ];then
+30 -7
View File
@@ -31,6 +31,9 @@ fi
echo "install remi source"
if [ "$VERSION_ID" == "9" ];then
# dnf upgrade --refresh -y
dnf config-manager --set-enabled crb
echo "install remi start"
if [ ! -f /etc/yum.repos.d/remi.repo ];then
rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-9.rpm
@@ -45,6 +48,10 @@ if [ ! -d /root/.acme.sh ];then
fi
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
# redhat , iptables no default
@@ -88,16 +95,28 @@ echo "SSH PORT:${SSH_PORT}"
# fi
# echo "iptables wrap start"
echo "firewall open common port start"
if [ ! -f /usr/sbin/firewalld ];then
$PKGMGR install firewalld -y
systemctl enable firewalld
#取消服务锁定
systemctl unmask firewalld
systemctl start firewalld
sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload
#安装就开启
systemctl restart firewalld
fi
if [ -f /usr/sbin/firewalld ];then
# look
# firewall-cmd --list-all
# systemctl status firewalld
# firewall-cmd --zone=public --remove-port=80/tcp --permanent
if [ "$SSH_PORT" != "" ];then
firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp
else
@@ -110,12 +129,10 @@ if [ ! -f /usr/sbin/firewalld ];then
# firewall-cmd --permanent --zone=public --add-port=3306/tcp
# firewall-cmd --permanent --zone=public --add-port=30000-40000/tcp
sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload
#安装时不开启
systemctl stop firewalld
fi
echo "firewall open common port end"
$PKGMGR install -y epel-release
if [ ! -z "$cn" ];then
@@ -128,7 +145,7 @@ fi
$PKGMGR makecache
$PKGMGR groupinstall -y "Development Tools"
if [ $VERSION_ID -ge 8 ];then
if [ "$VERSION_ID" -ge "8" ];then
# EL8 及以上
# find repo
@@ -141,6 +158,12 @@ if [ $VERSION_ID -ge 8 ];then
REPOS="${REPOS},${REPO_VAR}"
fi
done
if [ "$REPOS" == "--enablerepo=" ];then
# if not find, reset emtpy
REPOS=''
fi
REPOS=${REPOS//=,/=}
echo "REPOS:${REPOS}"
+4
View File
@@ -25,6 +25,10 @@ locale-gen en_US.UTF-8
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
SSH_PORT_LINE=`cat /etc/ssh/sshd_config | grep "Port \d*" | tail -1`
SSH_PORT=${SSH_PORT_LINE/"Port "/""}
fi
echo "SSH PORT:${SSH_PORT}"
if [ -f /usr/sbin/ufw ];then
+1 -1
View File
@@ -8,7 +8,7 @@ function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
P_VER=`python3 -V | awk '{print $2}'`
echo "python:$P_VER"
sleep 3
sleep 1
curPath=`pwd`
rootPath=$(dirname "$curPath")
+2 -1
View File
@@ -1,3 +1,4 @@
cryptography==36.0.1
flask==2.0.3
pyOpenSSL==22.0.0
pyOpenSSL==22.0.0
requests==2.27.1
+1
View File
@@ -0,0 +1 @@
urllib3==1.21.1