mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-11 00:59:25 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
869d7795a6 | ||
|
|
0a3d976c6a | ||
|
|
c4d39ef9fb | ||
|
|
8e5b499601 | ||
|
|
e6dff6094c | ||
|
|
47dec45a27 | ||
|
|
4706af7423 | ||
|
|
1bc458eb8f | ||
|
|
dc3f872592 | ||
|
|
3d48289329 | ||
|
|
6126539929 | ||
|
|
cff5df6d13 | ||
|
|
23a0b74f9d | ||
|
|
5927a3abab | ||
|
|
4b176ad702 | ||
|
|
577103506d | ||
|
|
18f8d2b905 | ||
|
|
3a6b5339d2 | ||
|
|
c25d4305f7 | ||
|
|
b6ef87e97b | ||
|
|
4335668cd4 | ||
|
|
0fc2ab011d | ||
|
|
683035e6b7 | ||
|
|
f2dfa7ad48 | ||
|
|
2ae2c188e7 | ||
|
|
b5cd0564cb | ||
|
|
2f274ce202 | ||
|
|
0a67932473 | ||
|
|
7b7cb215c4 | ||
|
|
f6e98ae286 | ||
|
|
5958f6e067 | ||
|
|
6dadfb1019 | ||
|
|
f5aeb5664b | ||
|
|
ca1080937d | ||
|
|
1dd934ea3f | ||
|
|
a34512d057 | ||
|
|
575c1e48ae | ||
|
|
9f3ee4997b | ||
|
|
cfaa2d9f25 | ||
|
|
aded1fc731 | ||
|
|
4a6e847743 | ||
|
|
24fac51538 | ||
|
|
148b32fed3 | ||
|
|
fff19d2c4a | ||
|
|
a5e0332179 | ||
|
|
1349655570 | ||
|
|
b9e617bf0f | ||
|
|
f65d10e1e4 | ||
|
|
6d9ec087ce | ||
|
|
bfb9da0471 | ||
|
|
8a95a68c81 | ||
|
|
d9d81ded3d | ||
|
|
403660c980 | ||
|
|
ac06cfc83c | ||
|
|
c50012b9b5 | ||
|
|
baeb0ddc8f | ||
|
|
83f8c99275 | ||
|
|
2d2b454a31 | ||
|
|
aad41ce14b | ||
|
|
ebf8c82d33 | ||
|
|
d25100fec3 | ||
|
|
fe658d9009 | ||
|
|
f37c2c9bc6 | ||
|
|
a1550765aa | ||
|
|
b020f23161 | ||
|
|
4afe2061e2 | ||
|
|
ab64c01981 | ||
|
|
8a97734700 | ||
|
|
16b4c64aa5 | ||
|
|
df2a5919af | ||
|
|
40a81b794c | ||
|
|
8fc7ab3abf | ||
|
|
ca4205c89a | ||
|
|
c89b15a645 | ||
|
|
7a863c4544 | ||
|
|
5d81406fdf | ||
|
|
cce59c0521 | ||
|
|
0a5c5aae12 | ||
|
|
7478426206 | ||
|
|
c0ed736edb | ||
|
|
313eb25ccd | ||
|
|
f58595755b | ||
|
|
18a892a576 | ||
|
|
03d558092f | ||
|
|
3cffa9223a | ||
|
|
c0d5aff2f5 | ||
|
|
3fa4c7804b | ||
|
|
22acce8bc0 | ||
|
|
e53e5cd672 | ||
|
|
a7d861de22 | ||
|
|
ddeef3c17e | ||
|
|
af733ac28a | ||
|
|
148e2021dc | ||
|
|
50c3fe58f4 | ||
|
|
5ed3728d4f | ||
|
|
9bf06c9d21 | ||
|
|
08b3738cfd | ||
|
|
a04f59a3aa | ||
|
|
155b8d2b4c | ||
|
|
039d2794ab | ||
|
|
0d2721523c | ||
|
|
f042665c05 | ||
|
|
0118548c24 | ||
|
|
1ba6625525 | ||
|
|
293f8ab0af | ||
|
|
dc68868883 | ||
|
|
30f835b6b8 | ||
|
|
4d90fdfe4f | ||
|
|
bb4067aa6b | ||
|
|
5dbf89b872 | ||
|
|
cc244a8ea5 | ||
|
|
975cb988f7 | ||
|
|
5a11d1bff9 | ||
|
|
bab3501722 | ||
|
|
872d68e0f1 | ||
|
|
9a5878a90c | ||
|
|
e5e226b57a | ||
|
|
5d12218a3e | ||
|
|
7b3bbc8bdd | ||
|
|
67030e91f6 | ||
|
|
c03eb0aa40 | ||
|
|
2b5aaba0b7 | ||
|
|
c7a01b8c52 | ||
|
|
9bfb72ada5 | ||
|
|
5ab8936f6b | ||
|
|
43c5161085 | ||
|
|
7d90a6e99f | ||
|
|
9ba8028944 | ||
|
|
36fa3d7630 | ||
|
|
b6a2d7e3e8 | ||
|
|
99e73d1bda | ||
|
|
1083b46078 | ||
|
|
8bd081804d | ||
|
|
2536a79481 | ||
|
|
eab11680e5 | ||
|
|
651b7d6d1b | ||
|
|
75e181116e | ||
|
|
c0a981b5a1 | ||
|
|
61dc601d48 | ||
|
|
415a2a1f8f | ||
|
|
7c06a85ac7 | ||
|
|
7c8329bb78 | ||
|
|
5c8a50429f | ||
|
|
300bdc1eb1 | ||
|
|
a8a9e9033e | ||
|
|
77425dfc48 | ||
|
|
52eae4625f | ||
|
|
dafcf60633 | ||
|
|
79c1e81d2c | ||
|
|
b779a18de6 | ||
|
|
45f22d239a | ||
|
|
f7b688d6bf | ||
|
|
6f069c715a | ||
|
|
98ed286b50 | ||
|
|
e931fa526f | ||
|
|
ff17610732 | ||
|
|
13bbe07ac5 | ||
|
|
5380cd805c | ||
|
|
c0b056c18d | ||
|
|
e287086b36 | ||
|
|
8647300e16 | ||
|
|
636f7af8ef | ||
|
|
87cf208dfc | ||
|
|
579a84c6f1 | ||
|
|
54b90f4484 | ||
|
|
ebdaf5d395 | ||
|
|
1e5ecabbd1 | ||
|
|
0596dc243e | ||
|
|
7fa6ec7cd3 | ||
|
|
c21d8eed8b | ||
|
|
326f9f0e6b | ||
|
|
60c94f120e | ||
|
|
55c08a8916 | ||
|
|
cf944fb976 | ||
|
|
cda1ea93a8 | ||
|
|
46f02cae0d | ||
|
|
034d00a262 | ||
|
|
fe1a68208b | ||
|
|
f364cc4e2d | ||
|
|
5b35b5f38c | ||
|
|
2151b2c597 | ||
|
|
4f8e95210f | ||
|
|
b31297b47f | ||
|
|
e492a87160 | ||
|
|
47d6eb7993 | ||
|
|
3ddccea897 | ||
|
|
069d594e49 | ||
|
|
7c49609a2b | ||
|
|
70d260dd5a | ||
|
|
58503722c0 | ||
|
|
0a98b4dc09 | ||
|
|
5ab0f493e4 | ||
|
|
30580874fd | ||
|
|
26327d958c | ||
|
|
522eddd393 | ||
|
|
935df8d4d1 | ||
|
|
15b4ba9cbb | ||
|
|
c005e1f56d | ||
|
|
edbca430ee | ||
|
|
f8fedb8285 | ||
|
|
d9472709fd | ||
|
|
79bf1eae07 | ||
|
|
fab6df7097 | ||
|
|
b9416d58f9 | ||
|
|
96d86ce49e | ||
|
|
46f2d9f029 | ||
|
|
9d5fb77123 | ||
|
|
d0c903bf11 | ||
|
|
3c1b0e6708 | ||
|
|
340b72591a | ||
|
|
8f6a194a02 | ||
|
|
7e65993978 | ||
|
|
ca27a2d49d | ||
|
|
b941c9c71b | ||
|
|
e68c7b0346 | ||
|
|
c7c3d8fdb9 | ||
|
|
de383e0584 | ||
|
|
048463cf9d | ||
|
|
0c118613d5 | ||
|
|
aa8e9f173b | ||
|
|
c21c54198c | ||
|
|
e8ad9995d7 | ||
|
|
7a0b6be401 | ||
|
|
8b2a127ceb | ||
|
|
8a23fb18ff | ||
|
|
234eca3729 | ||
|
|
9c74eb6a77 | ||
|
|
0093af2661 | ||
|
|
482d9bdd86 | ||
|
|
d8f9b179ad | ||
|
|
d179328976 | ||
|
|
9aaa5e2a65 | ||
|
|
821a9ce2d1 | ||
|
|
7b39b28dcd | ||
|
|
c881ad7d18 | ||
|
|
82da5c2649 | ||
|
|
315ba990ec | ||
|
|
992fcb7e6f | ||
|
|
d7337239f5 | ||
|
|
224b91fe0b | ||
|
|
589dfe6da2 | ||
|
|
b1b47c3c38 | ||
|
|
106f5d897d | ||
|
|
c856d09b3b | ||
|
|
6bf8792bb6 | ||
|
|
75edb074b2 | ||
|
|
4a5df99f06 | ||
|
|
2c7536a138 | ||
|
|
a758fc2264 | ||
|
|
0d94fe2d26 | ||
|
|
630bdd5f96 | ||
|
|
411fc670fc | ||
|
|
cab35c7c28 | ||
|
|
b3c8a6365f | ||
|
|
b64f02ff2f | ||
|
|
7e9df9640e | ||
|
|
6c478be4df | ||
|
|
e919fac1d5 | ||
|
|
4854142f9a | ||
|
|
f37de275ba | ||
|
|
0c8f777452 | ||
|
|
9235affadf | ||
|
|
2001a3b5dc | ||
|
|
6ba1e4c19c | ||
|
|
231048a4a3 | ||
|
|
6b9aab3759 | ||
|
|
e8a152b1a3 | ||
|
|
1cf8e4ecb7 | ||
|
|
aa04235446 | ||
|
|
3acbc36297 | ||
|
|
85aba4f1ce | ||
|
|
f33f80cf34 | ||
|
|
1868b3197d | ||
|
|
b8e1fb2ca2 | ||
|
|
9aa9c4f799 | ||
|
|
344603f1b2 | ||
|
|
71b43e9f2f | ||
|
|
adba50bfc1 |
@@ -11,8 +11,7 @@ Debian x, Centos x, Centos x stream, Ubuntu x?
|
||||
|
||||
Ex:
|
||||
```bash
|
||||
................start mw success
|
||||
bash: line 149: ./scripts/init.d/mw: No such file or directory
|
||||
一个issue,一个问题。多余问题,视情况而答。
|
||||
```
|
||||
|
||||
## 错误截图 ?
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<img alt="logo" src="https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/logo.png" height="140" />
|
||||
<h3 align="center">mdserver-web</h3>
|
||||
<p align="center">一款简单Linux面板服务</p>
|
||||
<p align="center">强烈推荐系统:debian</p>
|
||||
</p>
|
||||
|
||||
### 简介
|
||||
@@ -10,10 +11,11 @@
|
||||
复制了后台管理界面,按照自己想要的方式写了一版。
|
||||
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
[](https://github.com/midoks/mdserver-web/wiki)
|
||||
[](https://www.jsdelivr.com/package/gh/midoks/mdserver-web)
|
||||
@@ -90,14 +92,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
|
||||
```
|
||||
|
||||
|
||||
### 版本更新 0.11.3
|
||||
### 版本更新 0.12.1
|
||||
|
||||
* 域名绑定修改。
|
||||
* 面板ssl配置加入。
|
||||
* 文件搜索优化。
|
||||
* php加入phalcon。
|
||||
* 文件管理UI优化。
|
||||
* phpmyadmin优化。
|
||||
* mysql/mariadb/mysql-apt/mysql-yum增加新的同步方式[同步账户]。
|
||||
* pureftp安装时自动放行端口。
|
||||
* 面板ssl,添加【申请Lets证书】功能。
|
||||
* 站点子域名绑定优化。
|
||||
* 修复添加数据库名字判断。
|
||||
* 增加PHP52的隐藏和显示指令。
|
||||
* 各种细节优化。
|
||||
|
||||
|
||||
### JSDelivr安装地址
|
||||
@@ -161,7 +164,7 @@ wget -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/s
|
||||
|
||||
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh | bash
|
||||
|
||||
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install_dev.sh | bash
|
||||
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/install_dev.sh | bash
|
||||
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash
|
||||
```
|
||||
|
||||
|
||||
@@ -825,7 +825,7 @@ fi
|
||||
ret_title, json.dumps(a_auth)))
|
||||
break
|
||||
|
||||
if number_of_checks == self._max_check_num:
|
||||
if number_of_checks == self.__max_check_num:
|
||||
raise StopIteration(
|
||||
"错误:已尝试验证{0}次. 最大验证次数为{1}. 验证时间间隔为{2}秒.".format(
|
||||
number_of_checks,
|
||||
|
||||
@@ -736,7 +736,7 @@ class cert_request:
|
||||
ret_title, json.dumps(a_auth)))
|
||||
break
|
||||
|
||||
if number_of_checks == self._max_check_num:
|
||||
if number_of_checks == self.__max_check_num:
|
||||
raise StopIteration(
|
||||
"错误:已尝试验证{0}次. 最大验证次数为{1}. 验证时间间隔为{2}秒.".format(
|
||||
number_of_checks,
|
||||
|
||||
@@ -27,7 +27,7 @@ from flask import request
|
||||
|
||||
class config_api:
|
||||
|
||||
__version = '0.11.3'
|
||||
__version = '0.12.1'
|
||||
__api_addr = 'data/api.json'
|
||||
|
||||
def __init__(self):
|
||||
@@ -340,11 +340,13 @@ class config_api:
|
||||
|
||||
# 获取面板证书
|
||||
def getPanelSslApi(self):
|
||||
cert = {}
|
||||
cert = self.getPanelSslData()
|
||||
return mw.getJson(cert)
|
||||
|
||||
def getPanelSslData(self):
|
||||
cert = {}
|
||||
keyPath = 'ssl/private.pem'
|
||||
certPath = 'ssl/cert.pem'
|
||||
|
||||
if not os.path.exists(certPath):
|
||||
mw.createSSL()
|
||||
|
||||
@@ -352,7 +354,7 @@ class config_api:
|
||||
cert['certPem'] = mw.readFile(certPath)
|
||||
cert['rep'] = os.path.exists('ssl/input.pl')
|
||||
cert['info'] = mw.getCertName(certPath)
|
||||
return mw.getJson(cert)
|
||||
return cert
|
||||
|
||||
# 保存面板证书
|
||||
def savePanelSslApi(self):
|
||||
@@ -378,6 +380,54 @@ class config_api:
|
||||
mw.writeFile('ssl/input.pl', 'True')
|
||||
return mw.returnJson(True, '证书已保存!')
|
||||
|
||||
# 申请面板let证书
|
||||
def applyPanelLetSslApi(self):
|
||||
|
||||
# check domain is bind?
|
||||
bind_domain = 'data/bind_domain.pl'
|
||||
if not os.path.exists(bind_domain):
|
||||
return mw.returnJson(False, '未绑定域名!')
|
||||
|
||||
siteName = mw.readFile(bind_domain).strip()
|
||||
auth_to = mw.getRunDir() + "/tmp"
|
||||
to_args = {
|
||||
'domains': [siteName],
|
||||
'auth_type': 'http',
|
||||
'auth_to': auth_to,
|
||||
}
|
||||
|
||||
src_letpath = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
|
||||
src_csrpath = src_letpath + "/fullchain.pem" # 生成证书路径
|
||||
src_keypath = src_letpath + "/privkey.pem" # 密钥文件路径
|
||||
|
||||
dst_letpath = mw.getRunDir() + '/ssl'
|
||||
dst_csrpath = dst_letpath + '/cert.pem'
|
||||
dst_keypath = dst_letpath + '/private.pem'
|
||||
|
||||
if not os.path.exists(src_letpath):
|
||||
import cert_api
|
||||
data = cert_api.cert_api().applyCertApi(to_args)
|
||||
if not data['status']:
|
||||
msg = data['msg']
|
||||
if type(data['msg']) != str:
|
||||
msg = data['msg'][0]
|
||||
emsg = data['msg'][1]['challenges'][0]['error']
|
||||
msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
|
||||
'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
|
||||
return mw.returnJson(data['status'], msg, data['msg'])
|
||||
|
||||
mw.buildSoftLink(src_csrpath, dst_csrpath, True)
|
||||
mw.buildSoftLink(src_keypath, dst_keypath, True)
|
||||
mw.execShell('echo "lets" > "' + dst_letpath + '/README"')
|
||||
|
||||
data = self.getPanelSslData()
|
||||
|
||||
tmp_well_know = auth_to + '/.well-known'
|
||||
if os.path.exists(tmp_well_know):
|
||||
mw.execShell('rm -rf ' + tmp_well_know)
|
||||
|
||||
return mw.returnJson(True, '申请成功!', data)
|
||||
|
||||
def setPanelDomainApi(self):
|
||||
domain = request.form.get('domain', '')
|
||||
|
||||
@@ -730,4 +780,13 @@ class config_api:
|
||||
data['username'] = mw.M('users').where(
|
||||
"id=?", (1,)).getField('username')
|
||||
|
||||
# databases hook 获取
|
||||
database_file = 'data/hook_database.json'
|
||||
if os.path.exists(database_file):
|
||||
df = mw.readFile(database_file)
|
||||
df = json.loads(df)
|
||||
data['hook_database'] = df
|
||||
else:
|
||||
data['hook_database'] = []
|
||||
|
||||
return data
|
||||
|
||||
+47
-22
@@ -94,7 +94,7 @@ class crontab_api:
|
||||
rdata['list'] = mw.getPage(_page)
|
||||
rdata['p'] = p
|
||||
|
||||
# backup hock
|
||||
# backup hook
|
||||
bh_file = mw.getPanelDataDir() + "/hook_backup.json"
|
||||
if os.path.exists(bh_file):
|
||||
hb_data = mw.readFile(bh_file)
|
||||
@@ -131,7 +131,7 @@ class crontab_api:
|
||||
# 参数校验
|
||||
def cronCheck(self, params):
|
||||
|
||||
if params['stype'] == 'site' or params['stype'] == 'database' or params['stype'] == 'logs':
|
||||
if params['stype'] == 'site' or params['stype'] == 'database' or params['stype'].find('database_') > -1 or params['stype'] == 'logs' or params['stype'] == 'path':
|
||||
if params['save'] == '':
|
||||
return False, '保留份数不能为空!'
|
||||
|
||||
@@ -230,8 +230,8 @@ class crontab_api:
|
||||
cronInfo['sbody'] = get['sbody']
|
||||
cronInfo['urladdress'] = get['urladdress']
|
||||
|
||||
addData = mw.M('crontab').where('id=?', (sid,)).save('name,type,where1,where_hour,where_minute,save,backup_to,sbody,urladdress', (get[
|
||||
'name'], field_type, get['where1'], get['hour'], get['minute'], get['save'], get['backup_to'], get['sbody'], get['urladdress']))
|
||||
addData = mw.M('crontab').where('id=?', (sid,)).save('name,type,where1,where_hour,where_minute,save,backup_to, sname, sbody,urladdress',
|
||||
(iname, field_type, get['where1'], get['hour'], get['minute'], get['save'], get['backup_to'], sname, get['sbody'], get['urladdress']))
|
||||
self.removeForCrond(cronInfo['echo'])
|
||||
self.syncToCrond(cronInfo)
|
||||
mw.writeLog('计划任务', '修改计划任务[' + cronInfo['name'] + ']成功')
|
||||
@@ -377,28 +377,46 @@ class crontab_api:
|
||||
stype = request.form.get('type', '')
|
||||
|
||||
bak_data = []
|
||||
|
||||
if stype == 'sites' or stype == 'databases':
|
||||
if stype == 'site' or stype == 'sites' or stype == 'database' or stype.find('database_') > -1 or stype == 'path':
|
||||
hookPath = mw.getPanelDataDir() + "/hook_backup.json"
|
||||
if os.path.exists(hookPath):
|
||||
t = mw.readFile(hookPath)
|
||||
bak_data = json.loads(t)
|
||||
|
||||
if stype == 'databases':
|
||||
if stype == 'database' or stype.find('database_') > -1:
|
||||
sqlite3_name = 'mysql'
|
||||
path = mw.getServerDir() + '/mysql'
|
||||
if stype != 'database':
|
||||
soft_name = stype.replace('database_', '')
|
||||
path = mw.getServerDir() + '/' + soft_name
|
||||
|
||||
if soft_name == 'postgresql':
|
||||
sqlite3_name = 'pgsql'
|
||||
|
||||
db_list = {}
|
||||
db_list['orderOpt'] = bak_data
|
||||
path = mw.getServerDir() + '/mysql'
|
||||
if not os.path.exists(path + '/mysql.db'):
|
||||
|
||||
if not os.path.exists(path + '/' + sqlite3_name + '.db'):
|
||||
db_list['data'] = []
|
||||
else:
|
||||
db_list['data'] = mw.M('databases').dbPos(
|
||||
path, 'mysql').field('name,ps').select()
|
||||
path, sqlite3_name).field('name,ps').select()
|
||||
return mw.getJson(db_list)
|
||||
|
||||
if stype == 'path':
|
||||
db_list = {}
|
||||
db_list['data'] = [{"name": mw.getWwwDir(), "ps": "www"}]
|
||||
db_list['orderOpt'] = bak_data
|
||||
return mw.getJson(db_list)
|
||||
|
||||
data = {}
|
||||
data['orderOpt'] = bak_data
|
||||
|
||||
data['data'] = mw.M(stype).field('name,ps').select()
|
||||
default_db = 'sites'
|
||||
# if stype == 'site' or stype == 'logs':
|
||||
# stype == 'sites'
|
||||
|
||||
data['data'] = mw.M(default_db).field('name,ps').select()
|
||||
return mw.getJson(data)
|
||||
##### ----- start ----- ###
|
||||
|
||||
@@ -495,13 +513,19 @@ export LANG=en_US.UTF-8
|
||||
MW_PATH=%s/bin/activate
|
||||
if [ -f $MW_PATH ];then
|
||||
source $MW_PATH
|
||||
fi
|
||||
''' % (mw.getRunDir(),)
|
||||
fi''' % (mw.getRunDir(),)
|
||||
|
||||
head = head + source_bin_activate + "\n"
|
||||
log = '.log'
|
||||
|
||||
script_dir = mw.getServerDir() + "/mdserver-web/scripts"
|
||||
script_dir = mw.getRunDir() + "/scripts"
|
||||
source_stype = 'database'
|
||||
if stype.find('database_') > -1:
|
||||
plugin_name = stype.replace('database_', '')
|
||||
script_dir = mw.getRunDir() + "/plugins/" + plugin_name + "/scripts"
|
||||
|
||||
source_stype = stype
|
||||
stype = 'database'
|
||||
|
||||
wheres = {
|
||||
'path': head + "python3 " + script_dir + "/backup.py path " + param['sname'] + " " + str(param['save']),
|
||||
@@ -513,13 +537,14 @@ fi
|
||||
if param['backup_to'] != 'localhost':
|
||||
cfile = mw.getPluginDir() + "/" + \
|
||||
param['backup_to'] + "/index.py"
|
||||
wheres = {
|
||||
'path': head + "python3 " + cfile + " path " + param['sname'] + " " + str(param['save']),
|
||||
'site': head + "python3 " + cfile + " site " + param['sname'] + " " + str(param['save']),
|
||||
'database': head + "python3 " + cfile + " database " + param['sname'] + " " + str(param['save']),
|
||||
'logs': head + "python3 " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
|
||||
'rememory': head + "/bin/bash " + script_dir + '/rememory.sh'
|
||||
}
|
||||
|
||||
wheres['path'] = head + "python3 " + cfile + \
|
||||
" path " + param['sname'] + " " + str(param['save'])
|
||||
wheres['site'] = head + "python3 " + cfile + \
|
||||
" site " + param['sname'] + " " + str(param['save'])
|
||||
wheres['database'] = head + "python3 " + cfile + " " + \
|
||||
source_stype + " " + \
|
||||
param['sname'] + " " + str(param['save'])
|
||||
try:
|
||||
shell = wheres[stype]
|
||||
except:
|
||||
@@ -583,9 +608,9 @@ echo "--------------------------------------------------------------------------
|
||||
# 重载配置
|
||||
def crondReload(self):
|
||||
if mw.isAppleSystem():
|
||||
# mw.execShell('/usr/sbin/cron restart')
|
||||
if os.path.exists('/etc/crontab'):
|
||||
pass
|
||||
# mw.execShell('/usr/sbin/cron restart')
|
||||
else:
|
||||
if os.path.exists('/etc/init.d/crond'):
|
||||
mw.execShell('/etc/init.d/crond reload')
|
||||
|
||||
@@ -117,6 +117,7 @@ class Sql():
|
||||
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \
|
||||
self.__OPT_WHERE + self.__OPT_GROUP + self.__OPT_ORDER + self.__OPT_LIMIT
|
||||
# print(sql)
|
||||
# print(self.__OPT_PARAM)
|
||||
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
|
||||
data = result.fetchall()
|
||||
# 构造字曲系列
|
||||
|
||||
@@ -240,6 +240,11 @@ class files_api:
|
||||
system_api.system_api().restartTask()
|
||||
except:
|
||||
system_api.system_api().restartTask()
|
||||
|
||||
# 删除日志
|
||||
task_log = mw.getRunDir() + "/tmp/panelTask.pl"
|
||||
if os.path.exists(task_log):
|
||||
os.remove(task_log)
|
||||
return mw.returnJson(True, '任务已删除!')
|
||||
|
||||
# 上传文件
|
||||
|
||||
@@ -342,6 +342,28 @@ class firewall_api:
|
||||
status = request.form.get('status', '1')
|
||||
return mw.getJson(self.setFw(status))
|
||||
|
||||
def setFwIptables(self, status):
|
||||
# iptables特殊处理
|
||||
if status == '1':
|
||||
mw.execShell('service iptables save')
|
||||
mw.execShell('service iptables stop')
|
||||
else:
|
||||
# 重新导入数据
|
||||
|
||||
_list = mw.M('firewall').field('id,port,ps,addtime').limit(
|
||||
'0,1000').order('id desc').select()
|
||||
|
||||
for x in _list:
|
||||
port = x['port']
|
||||
if mw.isIpAddr(port):
|
||||
cmd = 'iptables -I INPUT -s ' + port + ' -j DROP'
|
||||
mw.execShell(cmd)
|
||||
else:
|
||||
self.addAcceptPort(port)
|
||||
|
||||
mw.execShell('service iptables save')
|
||||
mw.execShell('service iptables start')
|
||||
|
||||
def setFw(self, status):
|
||||
if status == '1':
|
||||
if self.__isUfw:
|
||||
@@ -352,8 +374,7 @@ class firewall_api:
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
mw.execShell('/etc/init.d/iptables save')
|
||||
mw.execShell('/etc/init.d/iptables stop')
|
||||
self.setFwIptables(status)
|
||||
else:
|
||||
if self.__isUfw:
|
||||
mw.execShell("echo 'y'| ufw enable")
|
||||
@@ -363,8 +384,7 @@ class firewall_api:
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
mw.execShell('/etc/init.d/iptables save')
|
||||
mw.execShell('/etc/init.d/iptables restart')
|
||||
self.setFwIptables(status)
|
||||
|
||||
return mw.returnData(True, '设置成功!')
|
||||
|
||||
@@ -437,8 +457,8 @@ class firewall_api:
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
mw.execShell('/etc/init.d/iptables save')
|
||||
mw.execShell('/etc/init.d/iptables restart')
|
||||
mw.execShell('service iptables save')
|
||||
mw.execShell('service iptables restart')
|
||||
|
||||
def getFwStatus(self):
|
||||
if self.__isUfw:
|
||||
@@ -456,8 +476,8 @@ class firewall_api:
|
||||
elif self.__isMac:
|
||||
return False
|
||||
else:
|
||||
cmd = "ps -ef|grep iptables |grep -v grep | awk '{print $2}'"
|
||||
cmd = "systemctl status iptables | grep 'inactive'"
|
||||
data = mw.execShell(cmd)
|
||||
if data[0] == '':
|
||||
if data[0] != '':
|
||||
return False
|
||||
return True
|
||||
|
||||
+43
-1
@@ -219,6 +219,15 @@ def isInstalledWeb():
|
||||
return False
|
||||
|
||||
|
||||
def isIpAddr(ip):
|
||||
check_ip = re.compile(
|
||||
'^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$')
|
||||
if check_ip.match(ip):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def restartWeb():
|
||||
return opWeb("reload")
|
||||
|
||||
@@ -490,6 +499,18 @@ def backFile(file, act=None):
|
||||
execShell("cp -p {0} {1}".format(file, file + file_type))
|
||||
|
||||
|
||||
def removeBackFile(file, act=None):
|
||||
"""
|
||||
@name 删除备份配置文件
|
||||
@param file 需要删除备份文件
|
||||
@param act 如果存在,则还原默认配置
|
||||
"""
|
||||
file_type = "_bak"
|
||||
if act:
|
||||
file_type = "_def"
|
||||
execShell("rm -rf {0}".format(file + file_type))
|
||||
|
||||
|
||||
def restoreFile(file, act=None):
|
||||
"""
|
||||
@name 还原配置文件
|
||||
@@ -1060,7 +1081,7 @@ def makeConf():
|
||||
file = getRunDir() + '/data/json/config.json'
|
||||
if not os.path.exists(file):
|
||||
c = {}
|
||||
c['title'] = '猫王面板'
|
||||
c['title'] = '大圣面板'
|
||||
c['home'] = 'http://github/midoks/mdserver-web'
|
||||
c['recycle_bin'] = True
|
||||
c['template'] = 'default'
|
||||
@@ -1453,3 +1474,24 @@ def getMyORMDb():
|
||||
import ormDb
|
||||
o = ormDb.ORM()
|
||||
return o
|
||||
|
||||
# ---------------------------------------------------------------------------------
|
||||
# 打印相关
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def echoStart(tag):
|
||||
print("=" * 90)
|
||||
print("★开始{}[{}]".format(tag, formatDate()))
|
||||
print("=" * 90)
|
||||
|
||||
|
||||
def echoEnd(tag):
|
||||
print("=" * 90)
|
||||
print("☆{}完成[{}]".format(tag, formatDate()))
|
||||
print("=" * 90)
|
||||
print("\n")
|
||||
|
||||
|
||||
def echoInfo(msg):
|
||||
print("|-{}".format(msg))
|
||||
|
||||
@@ -236,7 +236,7 @@ class plugins_api:
|
||||
if 'hook' in info:
|
||||
hooks = info['hook']
|
||||
for x in hooks:
|
||||
if x in ['backup']:
|
||||
if x in ['backup', 'database']:
|
||||
self.hookInstallFile(x, info)
|
||||
return True
|
||||
return False
|
||||
@@ -245,7 +245,7 @@ class plugins_api:
|
||||
if 'hook' in info:
|
||||
hooks = info['hook']
|
||||
for x in hooks:
|
||||
if x in ['backup']:
|
||||
if x in ['backup', 'database']:
|
||||
self.hookUninstallFile(x, info)
|
||||
return True
|
||||
return False
|
||||
|
||||
+72
-35
@@ -76,16 +76,16 @@ class site_api:
|
||||
def listApi(self):
|
||||
limit = request.form.get('limit', '10')
|
||||
p = request.form.get('p', '1')
|
||||
type_id = request.form.get('type_id', '')
|
||||
type_id = request.form.get('type_id', '0').strip()
|
||||
|
||||
start = (int(p) - 1) * (int(limit))
|
||||
|
||||
siteM = mw.M('sites')
|
||||
if type_id != '' and type_id == '-1' and type_id == '0':
|
||||
siteM.where('type_id=?', (type_id))
|
||||
siteM = mw.M('sites').field('id,name,path,status,ps,addtime,edate')
|
||||
if type_id != '' and int(type_id) >= 0:
|
||||
siteM.where('type_id=?', (type_id,))
|
||||
|
||||
_list = siteM.field('id,name,path,status,ps,addtime,edate').limit(
|
||||
(str(start)) + ',' + limit).order('id desc').select()
|
||||
_list = siteM.limit((str(start)) + ',' +
|
||||
limit).order('id desc').select()
|
||||
|
||||
for i in range(len(_list)):
|
||||
_list[i]['backup_count'] = mw.M('backup').where(
|
||||
@@ -140,6 +140,10 @@ class site_api:
|
||||
return mw.getJson(data)
|
||||
|
||||
def getCliPhpVersionApi(self):
|
||||
php_dir = mw.getServerDir() + '/php'
|
||||
if not os.path.exists(php_dir):
|
||||
return mw.returnJson(False, '未安装PHP,无法设置')
|
||||
|
||||
php_bin = '/usr/bin/php'
|
||||
php_versions = self.getPhpVersion()
|
||||
php_versions = php_versions[1:]
|
||||
@@ -813,9 +817,9 @@ class site_api:
|
||||
if not len(domains):
|
||||
return mw.returnJson(False, '请选择域名')
|
||||
|
||||
file = self.getHostConf(siteName)
|
||||
if os.path.exists(file):
|
||||
siteConf = mw.readFile(file)
|
||||
host_conf_file = self.getHostConf(siteName)
|
||||
if os.path.exists(host_conf_file):
|
||||
siteConf = mw.readFile(host_conf_file)
|
||||
if siteConf.find('301-END') != -1:
|
||||
return mw.returnJson(False, '检测到您的站点做了301重定向设置,请先关闭重定向!')
|
||||
|
||||
@@ -833,25 +837,21 @@ class site_api:
|
||||
if os.path.exists(proxy_dir_file):
|
||||
return mw.returnJson(False, '检测到您的站点做了反向代理设置,请先关闭反向代理!')
|
||||
|
||||
auth_to = self.getSitePath(siteName)
|
||||
# fix binddir domain ssl apply question
|
||||
mw.backFile(host_conf_file)
|
||||
auth_to = self.getSitePath(siteName)
|
||||
rep = "\s*root\s*(.+);"
|
||||
replace_root = "\n\troot " + auth_to + ";"
|
||||
siteConf = re.sub(rep, replace_root, siteConf)
|
||||
mw.writeFile(host_conf_file, siteConf)
|
||||
mw.restartWeb()
|
||||
|
||||
to_args = {
|
||||
'domains': domains,
|
||||
'auth_type': 'http',
|
||||
'auth_to': auth_to,
|
||||
}
|
||||
|
||||
import cert_api
|
||||
data = cert_api.cert_api().applyCertApi(to_args)
|
||||
|
||||
if not data['status']:
|
||||
msg = data['msg']
|
||||
if type(data['msg']) != str:
|
||||
msg = data['msg'][0]
|
||||
emsg = data['msg'][1]['challenges'][0]['error']
|
||||
msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
|
||||
'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
|
||||
return mw.returnJson(data['status'], msg, data['msg'])
|
||||
|
||||
src_letpath = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
|
||||
src_csrpath = src_letpath + "/fullchain.pem" # 生成证书路径
|
||||
src_keypath = src_letpath + "/privkey.pem" # 密钥文件路径
|
||||
@@ -860,11 +860,23 @@ class site_api:
|
||||
dst_csrpath = dst_letpath + '/fullchain.pem'
|
||||
dst_keypath = dst_letpath + '/privkey.pem'
|
||||
|
||||
if not os.path.exists(dst_letpath):
|
||||
mw.execShell('mkdir -p ' + dst_letpath)
|
||||
mw.buildSoftLink(src_csrpath, dst_csrpath, True)
|
||||
mw.buildSoftLink(src_keypath, dst_keypath, True)
|
||||
mw.execShell('echo "lets" > "' + dst_letpath + '/README"')
|
||||
if not os.path.exists(src_letpath):
|
||||
import cert_api
|
||||
data = cert_api.cert_api().applyCertApi(to_args)
|
||||
mw.restoreFile(host_conf_file)
|
||||
if not data['status']:
|
||||
msg = data['msg']
|
||||
if type(data['msg']) != str:
|
||||
msg = data['msg'][0]
|
||||
emsg = data['msg'][1]['challenges'][0]['error']
|
||||
msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
|
||||
'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
|
||||
return mw.returnJson(data['status'], msg, data['msg'])
|
||||
|
||||
mw.execShell('mkdir -p ' + dst_letpath)
|
||||
mw.buildSoftLink(src_csrpath, dst_csrpath, True)
|
||||
mw.buildSoftLink(src_keypath, dst_keypath, True)
|
||||
mw.execShell('echo "lets" > "' + dst_letpath + '/README"')
|
||||
|
||||
# 写入配置文件
|
||||
result = self.setSslConf(siteName)
|
||||
@@ -873,6 +885,8 @@ class site_api:
|
||||
|
||||
result['csr'] = mw.readFile(src_csrpath)
|
||||
result['key'] = mw.readFile(src_keypath)
|
||||
|
||||
mw.restartWeb()
|
||||
return mw.returnJson(data['status'], data['msg'], result)
|
||||
|
||||
def getAcmeLogsApi(self):
|
||||
@@ -1115,6 +1129,26 @@ class site_api:
|
||||
host = self.getHostConf(siteName)
|
||||
return mw.getJson({'host': host})
|
||||
|
||||
def saveHostConfApi(self):
|
||||
path = request.form.get('path', '')
|
||||
data = request.form.get('data', '')
|
||||
encoding = request.form.get('encoding', '')
|
||||
|
||||
import files_api
|
||||
|
||||
mw.backFile(path)
|
||||
save_ret_data = files_api.files_api().saveBody(path, data, encoding)
|
||||
rdata = json.loads(save_ret_data)
|
||||
|
||||
if rdata['status']:
|
||||
isError = mw.checkWebConfig()
|
||||
if isError != True:
|
||||
mw.restoreFile(path)
|
||||
return mw.returnJson(False, 'ERROR: 检测到配置文件有错误,请先排除后再操作<br><br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
|
||||
mw.restartWeb()
|
||||
mw.removeBackFile(path)
|
||||
return save_ret_data
|
||||
|
||||
def getRewriteConfApi(self):
|
||||
siteName = request.form.get('siteName', '')
|
||||
rewrite = self.getRewriteConf(siteName)
|
||||
@@ -1208,14 +1242,15 @@ class site_api:
|
||||
return mw.returnJson(False, '端口范围不合法!')
|
||||
|
||||
opid = mw.M('domain').where(
|
||||
"name=? AND (port=? OR pid=?)", (domain, domain_port, pid)).getField('pid')
|
||||
if opid:
|
||||
if mw.M('sites').where('id=?', (opid,)).count():
|
||||
return mw.returnJson(False, '指定域名已绑定过!')
|
||||
mw.M('domain').where('pid=?', (opid,)).delete()
|
||||
"name=? AND (port=? OR pid=?)", (domain_name, domain_port, pid,)).getField('pid')
|
||||
if opid > 0:
|
||||
return mw.returnJson(False, '您添加的域名[{}],已绑定!'.format(domain_name))
|
||||
# if mw.M('sites').where('id=?', (opid,)).count():
|
||||
# return mw.returnJson(False, '指定域名已绑定过!')
|
||||
# mw.M('domain').where('pid=?', (opid,)).delete()
|
||||
|
||||
if mw.M('binding').where('domain=?', (domain,)).count():
|
||||
return mw.returnJson(False, '您添加的域名已存在!')
|
||||
return mw.returnJson(False, '您添加的域名,子目录已绑定!')
|
||||
|
||||
self.nginxAddDomain(webname, domain_name, domain_port)
|
||||
|
||||
@@ -1267,17 +1302,18 @@ class site_api:
|
||||
content = content.replace('{$ROOT_DIR}', webdir)
|
||||
content = content.replace('{$SERVER_MAIN}', siteInfo['name'])
|
||||
content = content.replace('{$OR_REWRITE}', self.rewritePath)
|
||||
content = content.replace('{$PHP_DIR}', self.setupPath + '/php')
|
||||
content = content.replace('{$LOGPATH}', mw.getLogsDir())
|
||||
|
||||
conf += "\r\n" + content
|
||||
shutil.copyfile(filename, '/tmp/backup.conf')
|
||||
mw.backFile(filename)
|
||||
mw.writeFile(filename, conf)
|
||||
conf = mw.readFile(filename)
|
||||
|
||||
# 检查配置是否有误
|
||||
isError = mw.checkWebConfig()
|
||||
if isError != True:
|
||||
shutil.copyfile('/tmp/backup.conf', filename)
|
||||
mw.restoreFile(filename)
|
||||
return mw.returnJson(False, 'ERROR: <br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
|
||||
|
||||
mw.M('binding').add('pid,domain,port,path,addtime',
|
||||
@@ -1287,6 +1323,7 @@ class site_api:
|
||||
(siteInfo['name'], dirName, domain))
|
||||
mw.writeLog('网站管理', msg)
|
||||
mw.restartWeb()
|
||||
mw.removeBackFile(filename)
|
||||
return mw.returnJson(True, '添加成功!')
|
||||
|
||||
def delDirBindApi(self):
|
||||
|
||||
@@ -17,7 +17,7 @@ server
|
||||
#ERROR-PAGE-END
|
||||
|
||||
#PHP-INFO-START
|
||||
include enable-php-{$PHPVER}.conf;
|
||||
include {$PHP_DIR}/conf/enable-php-{$PHPVER}.conf;
|
||||
#PHP-INFO-END
|
||||
|
||||
#REWRITE-START
|
||||
|
||||
@@ -80,11 +80,13 @@ class FtpPSClient:
|
||||
return default_config
|
||||
|
||||
def injection_config(self, data):
|
||||
host = data["ftp_host"].strip()
|
||||
self.__host = host = data["ftp_host"].strip()
|
||||
if host.find(':') == -1:
|
||||
self.__port = self.default_port
|
||||
else:
|
||||
self.__host = host.split(':')[0]
|
||||
self.__port = host.split(':')[1]
|
||||
|
||||
self.__host = data['ftp_host'].strip()
|
||||
self.__user = data['ftp_user'].strip()
|
||||
self.__password = data['ftp_pass'].strip()
|
||||
bp = data['backup_path'].strip()
|
||||
|
||||
+21
-13
@@ -57,9 +57,8 @@ def getArgs():
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
t = args[i].split(':', 1)
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
@@ -180,28 +179,37 @@ def backupAllFunc(stype):
|
||||
name = sys.argv[2]
|
||||
num = sys.argv[3]
|
||||
|
||||
args = stype + " " + name + " " + num
|
||||
|
||||
cmd = 'python3 ' + mw.getRunDir() + '/scripts/backup.py ' + args
|
||||
os.system(cmd)
|
||||
|
||||
# 开始执行上传信息
|
||||
|
||||
prefix_dict = {
|
||||
"site": "web",
|
||||
"database": "db",
|
||||
"path": "path",
|
||||
}
|
||||
|
||||
find_path = mw.getBackupDir() + '/' + stype + '/' + \
|
||||
prefix_dict[stype] + '_' + name
|
||||
args = stype + " " + name + " " + num
|
||||
cmd = 'python3 ' + mw.getRunDir() + '/scripts/backup.py ' + args
|
||||
if stype.find('database_') > -1:
|
||||
plugin_name = stype.replace('database_', '')
|
||||
args = "database " + name + " " + num
|
||||
cmd = 'python3 ' + mw.getRunDir() + '/plugins/' + plugin_name + \
|
||||
'/scripts/backup.py ' + args
|
||||
|
||||
os.system(cmd)
|
||||
# 开始执行上传信息
|
||||
|
||||
bk_prefix = prefix_dict[stype]
|
||||
bk_name = stype
|
||||
if stype.find('database_') > -1:
|
||||
bk_name = 'database'
|
||||
plugin_name = stype.replace('database_', '')
|
||||
bk_prefix = plugin_name + '/db'
|
||||
|
||||
find_path = mw.getBackupDir() + '/' + bk_name + '/' + bk_prefix + '_' + name
|
||||
find_new_file = "ls " + find_path + \
|
||||
"_* | grep '.gz' | cut -d \ -f 1 | awk 'END {print}'"
|
||||
|
||||
filename = mw.execShell(find_new_file)[0].strip()
|
||||
if filename == "":
|
||||
print("not find upload file!")
|
||||
mw.echoInfo("not find upload file!")
|
||||
return False
|
||||
|
||||
ftp = FtpPSClient()
|
||||
@@ -251,7 +259,7 @@ if __name__ == "__main__":
|
||||
print(deleteDir())
|
||||
elif func == 'delete_file':
|
||||
print(deleteFile())
|
||||
elif in_array(func, ['site', 'database', 'path']):
|
||||
elif in_array(func, ['site', 'database', 'path']) or func.find('database_') > -1:
|
||||
print(backupAllFunc(func))
|
||||
else:
|
||||
print('error')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sort": 7,
|
||||
"ps": "简单邮件服务[DEV]",
|
||||
"ps": "[<b style='color:red;'>DEV</b>]简单邮件服务",
|
||||
"name": "imail",
|
||||
"title": "邮件服务",
|
||||
"shell": "install.sh",
|
||||
|
||||
@@ -21,10 +21,13 @@ OSNAME_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F
|
||||
ARCH="amd64"
|
||||
|
||||
get_arch() {
|
||||
|
||||
TMP_ARCH=`arch`
|
||||
if [ "$TMP_ARCH" == "x86_64" ];then
|
||||
ARCH="amd64"
|
||||
else if [ "$TMP_ARCH" == "aarch64" ];then
|
||||
ARCH="arm64"
|
||||
else
|
||||
echo $ARCH
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -40,4 +40,18 @@ CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
-- 从库配置主库的[user]
|
||||
-- drop table `slave_user`;
|
||||
CREATE TABLE IF NOT EXISTS `slave_sync_user` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`ip` TEXT,
|
||||
`port` TEXT,
|
||||
`user` TEXT,
|
||||
`pass` TEXT,
|
||||
`mode` TEXT,
|
||||
`cmd` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ replicate-ignore-db = information_schema
|
||||
replicate-ignore-db = performance_schema
|
||||
replicate-ignore-db = mysql
|
||||
replicate-ignore-db = test
|
||||
replicate-wild-ignore-table=mysql.%
|
||||
|
||||
|
||||
innodb_data_home_dir = {$SERVER_APP_PATH}/data
|
||||
|
||||
+334
-24
@@ -71,6 +71,13 @@ def checkArgs(data, ck=[]):
|
||||
return (True, mw.returnJson(True, 'ok'))
|
||||
|
||||
|
||||
def getBackupDir():
|
||||
bk_path = mw.getBackupDir() + "/database/mariadb"
|
||||
if not os.path.isdir(bk_path):
|
||||
mw.execShell("mkdir -p {}".format(bk_path))
|
||||
return bk_path
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getServerDir() + '/etc/my.cnf'
|
||||
return path
|
||||
@@ -133,20 +140,27 @@ def contentReplace(content):
|
||||
def pSqliteDb(dbname='databases'):
|
||||
file = getServerDir() + '/mariadb.db'
|
||||
name = 'mysql'
|
||||
if not os.path.exists(file):
|
||||
|
||||
import_sql = mw.readFile(getPluginDir() + '/conf/mariadb.sql')
|
||||
md5_sql = mw.md5(import_sql)
|
||||
|
||||
import_sign = False
|
||||
save_md5_file = getServerDir() + '/import_sql.md5'
|
||||
if os.path.exists(save_md5_file):
|
||||
save_md5_sql = mw.readFile(save_md5_file)
|
||||
if save_md5_sql != md5_sql:
|
||||
import_sign = True
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
else:
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
|
||||
if not os.path.exists(file) or import_sql:
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
csql = mw.readFile(getPluginDir() + '/conf/mariadb.sql')
|
||||
csql_list = csql.split(';')
|
||||
csql_list = import_sql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
conn.execute(csql_list[index], ())
|
||||
else:
|
||||
# 现有run
|
||||
# conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
# csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
# csql_list = csql.split(';')
|
||||
# for index in range(len(csql_list)):
|
||||
# conn.execute(csql_list[index], ())
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
return conn
|
||||
|
||||
|
||||
@@ -273,6 +287,13 @@ def binLog():
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def cleanBinLog():
|
||||
db = pMysqlDb()
|
||||
cleanTime = time.strftime('%Y-%m-%d %H:%i:%s', time.localtime())
|
||||
db.execute("PURGE MASTER LOGS BEFORE '" + cleanTime + "';")
|
||||
return mw.returnJson(True, '清理BINLOG成功!')
|
||||
|
||||
|
||||
def setSkipGrantTables(v):
|
||||
'''
|
||||
设置是否密码验证
|
||||
@@ -675,7 +696,7 @@ def __createUser(dbname, username, password, address):
|
||||
|
||||
|
||||
def getDbBackupListFunc(dbname=''):
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
blist = os.listdir(bkDir)
|
||||
r = []
|
||||
|
||||
@@ -709,11 +730,11 @@ def importDbBackup():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
file_path = mw.getRootDir() + '/backup/database/' + file
|
||||
file_path_sql = mw.getRootDir() + '/backup/database/' + file.replace('.gz', '')
|
||||
file_path = getBackupDir() + '/' + file
|
||||
file_path_sql = getBackupDir() + '/' + file.replace('.gz', '')
|
||||
|
||||
if not os.path.exists(file_path_sql):
|
||||
cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file
|
||||
cmd = 'cd ' + mw.getBackupDir() + '/database/mariadb && gzip -d ' + file
|
||||
mw.execShell(cmd)
|
||||
|
||||
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
|
||||
@@ -735,7 +756,7 @@ def importDbExternal():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
import_dir = mw.getRootDir() + '/backup/import/'
|
||||
import_dir = mw.getBackupDir() + '/import/'
|
||||
|
||||
file_path = import_dir + file
|
||||
if not os.path.exists(file_path):
|
||||
@@ -797,7 +818,7 @@ def deleteDbBackup():
|
||||
|
||||
path = args['path']
|
||||
full_file = ""
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
full_file = bkDir + '/' + args['filename']
|
||||
if path != "":
|
||||
full_file = path + "/" + args['filename']
|
||||
@@ -812,7 +833,10 @@ def getDbBackupList():
|
||||
return data[1]
|
||||
|
||||
r = getDbBackupListFunc(args['name'])
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
if not os.path.exists(bkDir):
|
||||
os.mkdir(bkDir)
|
||||
|
||||
rr = []
|
||||
for x in range(0, len(r)):
|
||||
p = bkDir + '/' + r[x]
|
||||
@@ -835,7 +859,7 @@ def getDbBackupList():
|
||||
|
||||
def getDbBackupImportList():
|
||||
|
||||
bkImportDir = mw.getRootDir() + '/backup/import'
|
||||
bkImportDir = mw.getBackupDir() + '/import'
|
||||
if not os.path.exists(bkImportDir):
|
||||
os.mkdir(bkImportDir)
|
||||
|
||||
@@ -1775,7 +1799,7 @@ def addMasterRepSlaveUser(version=''):
|
||||
# address = args['address'].strip()
|
||||
# dataAccess = args['dataAccess'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, username):
|
||||
return mw.returnJson(False, '用户名不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1796,11 +1820,15 @@ def addMasterRepSlaveUser(version=''):
|
||||
sql = "GRANT REPLICATION SLAVE ON *.* TO '" + username + \
|
||||
"'@'%' identified by '" + password + "';"
|
||||
result = pdb.execute(sql)
|
||||
result = pdb.execute('FLUSH PRIVILEGES;')
|
||||
|
||||
isError = isSqlError(result)
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql_select = "grant select,lock tables,PROCESS on *.* to " + username + "@'%';"
|
||||
pdb.execute(sql_select)
|
||||
pdb.execute('FLUSH PRIVILEGES;')
|
||||
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
psdb.add('username,password,accept,ps,addtime',
|
||||
(username, password, '%', '', addTime))
|
||||
@@ -1837,10 +1865,16 @@ def getMasterRepSlaveUserCmd(version):
|
||||
|
||||
mode = recognizeDbMode()
|
||||
|
||||
# 查找同步点
|
||||
# SELECT BINLOG_GTID_POS('master1-bin.000002', 561866201);
|
||||
|
||||
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_LOG_FILE='" + mstatus[0]["File"] + \
|
||||
"',MASTER_LOG_POS=" + \
|
||||
str(mstatus[0]["Position"]) + \
|
||||
",MASTER_USE_GTID=slave_pos,MASTER_CONNECT_RETRY=10;"
|
||||
else:
|
||||
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
|
||||
clist[0]['username'] + "', MASTER_PASSWORD='" + \
|
||||
@@ -1926,6 +1960,123 @@ def getSlaveSSHList(version=''):
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSlaveSyncUserByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').where(
|
||||
"ip=?", (ip,)).select()
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def addSlaveSyncUser(version=''):
|
||||
import base64
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
if ip == "":
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
data = checkArgs(args, ['port', 'user', 'pass', 'mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
cmd = args['cmd']
|
||||
port = args['port']
|
||||
user = args['user']
|
||||
apass = args['pass']
|
||||
mode = args['mode']
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip').where("ip=?", (ip,)).select()
|
||||
if len(data) > 0:
|
||||
res = conn.where("ip=?", (ip,)).save(
|
||||
'port,user,pass,mode,cmd', (port, user, apass, mode, cmd))
|
||||
else:
|
||||
conn.add('ip,port,user,cmd,user,pass,mode,addtime',
|
||||
(ip, port, user, cmd, user, apass, mode, addTime))
|
||||
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def delSlaveSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
conn.where("ip=?", (ip,)).delete()
|
||||
return mw.returnJson(True, '删除成功!')
|
||||
|
||||
|
||||
def getSlaveSyncUserList(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['page', 'page_size'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
page = int(args['page'])
|
||||
page_size = int(args['page_size'])
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
limit = str((page - 1) * page_size) + ',' + str(page_size)
|
||||
|
||||
field = 'id,ip,port,user,pass,cmd,addtime'
|
||||
clist = conn.field(field).limit(limit).order('id desc').select()
|
||||
count = conn.count()
|
||||
|
||||
data = {}
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['p'] = page
|
||||
_page['row'] = page_size
|
||||
_page['tojs'] = args['tojs']
|
||||
data['page'] = mw.getPage(_page)
|
||||
data['data'] = clist
|
||||
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSyncModeFile():
|
||||
return getServerDir() + "/sync.mode"
|
||||
|
||||
|
||||
def getSlaveSyncMode(version):
|
||||
sync_mode = getSyncModeFile()
|
||||
if os.path.exists(sync_mode):
|
||||
mode = mw.readFile(sync_mode).strip()
|
||||
return mw.returnJson(True, 'ok', mode)
|
||||
return mw.returnJson(False, 'fail')
|
||||
|
||||
|
||||
def setSlaveSyncMode(version):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
mode = args['mode']
|
||||
sync_mode = getSyncModeFile()
|
||||
|
||||
if mode == 'none':
|
||||
os.remove(sync_mode)
|
||||
else:
|
||||
mw.writeFile(sync_mode, mode)
|
||||
return mw.returnJson(True, '设置成功', mode)
|
||||
|
||||
|
||||
def getSlaveSSHByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
@@ -2003,8 +2154,6 @@ def getSlaveList(version=''):
|
||||
|
||||
db = pMysqlDb()
|
||||
dlist = db.query('show slave status')
|
||||
|
||||
# print(dlist)
|
||||
ret = []
|
||||
for x in range(0, len(dlist)):
|
||||
tmp = {}
|
||||
@@ -2014,6 +2163,24 @@ def getSlaveList(version=''):
|
||||
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
|
||||
@@ -2030,6 +2197,47 @@ def getSlaveSyncCmd(version=''):
|
||||
|
||||
|
||||
def initSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return initSlaveStatusSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return initSlaveStatusSyncUser(version)
|
||||
|
||||
|
||||
def initSlaveStatusSyncUser(version=''):
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
if len(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'
|
||||
|
||||
local_mode = recognizeDbMode()
|
||||
if local_mode != mode_name:
|
||||
return mw.returnJson(False, '同步模式不一致!')
|
||||
|
||||
# print(u['cmd'])
|
||||
t = db.query(u['cmd'])
|
||||
# print(t)
|
||||
db.query("start slave")
|
||||
return mw.returnJson(True, '初始化成功!')
|
||||
|
||||
|
||||
def initSlaveStatusSSH(version=''):
|
||||
db = pMysqlDb()
|
||||
dlist = db.query('show slave status')
|
||||
if len(dlist) > 0:
|
||||
@@ -2100,6 +2308,41 @@ def initSlaveStatus(version=''):
|
||||
|
||||
|
||||
def setSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
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)
|
||||
|
||||
|
||||
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']
|
||||
|
||||
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')
|
||||
@@ -2168,6 +2411,61 @@ def writeDbSyncStatus(data):
|
||||
|
||||
|
||||
def doFullSync(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return doFullSyncSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return doFullSyncUser(version)
|
||||
|
||||
|
||||
def doFullSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
sync_db = args['db']
|
||||
|
||||
db = pMysqlDb()
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
user = data['user']
|
||||
apass = data['pass']
|
||||
port = data['port']
|
||||
ip = data['ip']
|
||||
|
||||
bak_file = '/tmp/tmp.sql'
|
||||
|
||||
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
|
||||
|
||||
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
|
||||
|
||||
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
|
||||
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 + \
|
||||
' ' + sync_db + ' < ' + bak_file
|
||||
mw.execShell(my_import_cmd)
|
||||
|
||||
db.query("start slave")
|
||||
|
||||
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
|
||||
os.system("rm -rf " + bak_file)
|
||||
return True
|
||||
|
||||
|
||||
def doFullSyncSSH(version=''):
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
@@ -2473,6 +2771,18 @@ if __name__ == "__main__":
|
||||
print(delSlaveSSH(version))
|
||||
elif func == 'update_slave_ssh':
|
||||
print(updateSlaveSSH(version))
|
||||
elif func == 'get_slave_sync_user_list':
|
||||
print(getSlaveSyncUserList(version))
|
||||
elif func == 'get_slave_sync_user_by_ip':
|
||||
print(getSlaveSyncUserByIp(version))
|
||||
elif func == 'add_slave_sync_user':
|
||||
print(addSlaveSyncUser(version))
|
||||
elif func == 'del_slave_sync_user':
|
||||
print(delSlaveSyncUser(version))
|
||||
elif func == 'get_slave_sync_mode':
|
||||
print(getSlaveSyncMode(version))
|
||||
elif func == 'set_slave_sync_mode':
|
||||
print(setSlaveSyncMode(version))
|
||||
elif func == 'init_slave_status':
|
||||
print(initSlaveStatus(version))
|
||||
elif func == 'set_slave_status':
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"hook":["database"],
|
||||
"title":"MariaDB",
|
||||
"tip":"soft",
|
||||
"name":"mariadb",
|
||||
|
||||
+273
-22
@@ -39,7 +39,7 @@ function myPostN(method,args,callback, title){
|
||||
if (typeof(title) != 'undefined'){
|
||||
_title = title;
|
||||
}
|
||||
$.post('/plugins/run', {name:'mysql', func:method, args:_args}, function(data) {
|
||||
$.post('/plugins/run', {name:'mariadb', func:method, args:_args}, function(data) {
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
@@ -487,19 +487,6 @@ function showHidePass(obj){
|
||||
}
|
||||
}
|
||||
|
||||
function copyPass(password){
|
||||
var clipboard = new ClipboardJS('#bt_copys');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg('复制成功',{icon:1,time:2000});
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000});
|
||||
});
|
||||
$("#bt_copys").attr('data-clipboard-text',password);
|
||||
$("#bt_copys").click();
|
||||
}
|
||||
|
||||
function checkSelect(){
|
||||
setTimeout(function () {
|
||||
var num = $('input[type="checkbox"].check:checked').length;
|
||||
@@ -668,8 +655,8 @@ function addDatabase(type){
|
||||
<span class='tname'>数据库名</span>\
|
||||
<div class='info-r'><input name='name' class='bt-input-text mr5' placeholder='新的数据库名称' type='text' style='width:65%' value=''>\
|
||||
<select class='bt-input-text mr5 codeing_a5nGsm' name='codeing' style='width:27%'>\
|
||||
<option value='utf8'>utf-8</option>\
|
||||
<option value='utf8mb4'>utf8mb4</option>\
|
||||
<option value='utf8'>utf-8</option>\
|
||||
<option value='gbk'>gbk</option>\
|
||||
<option value='big5'>big5</option>\
|
||||
</select>\
|
||||
@@ -1517,7 +1504,7 @@ function getMasterRepSlaveUserCmd(username, db=''){
|
||||
title: '同步命令',
|
||||
area: '500px',
|
||||
content:"<form class='bt-form pd20 pb70' id='add_master'>\
|
||||
<div class='line'>"+cmd+"</div>\
|
||||
<div class='line' style='word-wrap: break-word;word-break: normal;'>"+cmd+"</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' class='btn btn-success btn-sm btn-title class-copy-cmd'>复制</button>\
|
||||
</div>\
|
||||
@@ -1808,11 +1795,27 @@ function addSlaveSSH(ip=''){
|
||||
}
|
||||
|
||||
|
||||
|
||||
function delSlaveSSH(ip){
|
||||
myPost('del_slave_ssh', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2});
|
||||
getSlaveSSHPage();
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSSHPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function delSlaveSyncUser(ip){
|
||||
myPost('del_slave_sync_user', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1861,6 +1864,234 @@ function getSlaveSSHPage(page=1){
|
||||
});
|
||||
}
|
||||
|
||||
function addSlaveSyncUser(ip=''){
|
||||
|
||||
myPost('get_slave_sync_user_by_ip', {ip:ip}, function(rdata){
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
|
||||
var ip = '127.0.0.1';
|
||||
var port = "22";
|
||||
var cmd = '';
|
||||
var user = 'input_sync_user';
|
||||
var pass = 'input_sync_pwd';
|
||||
var mode = '0';
|
||||
|
||||
if (rdata.data.length>0){
|
||||
ip = rdata.data[0]['ip'];
|
||||
port = rdata.data[0]['port'];
|
||||
cmd = rdata.data[0]['cmd'];
|
||||
user = rdata.data[0]['user'];
|
||||
pass = rdata.data[0]['pass'];
|
||||
mode = rdata.data[0]['mode'];
|
||||
}
|
||||
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
area: ['500px','470px'],
|
||||
title: '同步账户',
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
btn:["确认","取消"],
|
||||
content: "<form class='bt-form pd20'>\
|
||||
<div class='line'><span class='tname'>IP</span><div class='info-r'><input name='ip' class='bt-input-text mr5' type='text' style='width:330px;' value='"+ip+"'></div></div>\
|
||||
<div class='line'><span class='tname'>端口</span><div class='info-r'><input name='port' class='bt-input-text mr5' type='number' style='width:330px;' value='"+port+"'></div></div>\
|
||||
<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>\
|
||||
<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 = {};
|
||||
for (var i in vlist) {
|
||||
var tmp = toTrim(vlist[i]);
|
||||
var tmp_a = tmp.split(" ");
|
||||
var real_tmp = tmp_a[tmp_a.length-1];
|
||||
var kv = real_tmp.split("=");
|
||||
a[kv[0]] = kv[1].replace("'",'').replace("'",'');
|
||||
}
|
||||
|
||||
$('input[name="ip"]').val(a['MASTER_HOST']);
|
||||
$('input[name="port"]').val(a['MASTER_PORT']);
|
||||
$('input[name="user"]').val(a['MASTER_USER']);
|
||||
$('input[name="pass"]').val(a['MASTER_PASSWORD']);
|
||||
|
||||
console.log(a['MASTER_USE_GTID'],typeof(a['MASTER_USE_GTID']));
|
||||
if (typeof(a['MASTER_USE_GTID']) != 'undefined' ){
|
||||
$('input[name="mode"]').val('1');
|
||||
}
|
||||
});
|
||||
},
|
||||
yes:function(index){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var user = $('input[name="user"]').val();
|
||||
var pass = $('input[name="pass"]').val();
|
||||
var cmd = $('textarea[name="cmd"]').val();
|
||||
var mode = $('input[name="mode"]').val();
|
||||
|
||||
var data = {ip:ip,port:port,cmd:cmd,user:user,pass:pass,mode:mode};
|
||||
myPost('add_slave_sync_user', data, function(ret_data){
|
||||
layer.close(index);
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSyncUserPage(page=1){
|
||||
var _data = {};
|
||||
_data['page'] = page;
|
||||
_data['page_size'] = 5;
|
||||
_data['tojs'] ='getSlaveSyncUserPage';
|
||||
myPost('get_slave_sync_user_list', _data, function(data){
|
||||
var layerId = null;
|
||||
var rdata = [];
|
||||
try {
|
||||
rdata = $.parseJSON(data.data);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var list = '';
|
||||
var user_list = rdata['data'];
|
||||
for (i in user_list) {
|
||||
var ip = user_list[i]['ip'];
|
||||
var port = user_list[i]['port'];
|
||||
var user = user_list[i]['user'];
|
||||
var apass = user_list[i]['pass'];
|
||||
|
||||
var cmd = '未设置';
|
||||
if (user_list[i]['cmd']!=''){
|
||||
cmd = '已设置';
|
||||
}
|
||||
|
||||
list += '<tr><td>'+ip+'</td>\
|
||||
<td>'+port+'</td>\
|
||||
<td>'+user+'</td>\
|
||||
<td>'+apass+'</td>\
|
||||
<td>'+cmd+'</td>\
|
||||
<td>\
|
||||
<a class="btlink" onclick="addSlaveSyncUser(\''+ip+'\');">修改</a> | \
|
||||
<a class="btlink" onclick="delSlaveSyncUser(\''+ip+'\');">删除</a>\
|
||||
</td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$('.get-slave-ssh-list tbody').html(list);
|
||||
$('.dataTables_paginate_4').html(rdata['page']);
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveCfg(){
|
||||
|
||||
myPost('get_slave_sync_mode', '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var mode_none = 'success';
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'danger';
|
||||
if(rdata.status){
|
||||
var mode_none = 'danger';
|
||||
if (rdata.data == 'ssh'){
|
||||
var mode_ssh = 'success';
|
||||
var mode_sync_user = 'danger';
|
||||
} else {
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步配置',
|
||||
area: ['400px','180px'],
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>当前从库同步模式</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-"+mode_none+" btn-xs slave-db-mode btn-none'>无</button>\
|
||||
<button class='btn btn-"+mode_ssh+" btn-xs slave-db-mode btn-ssh'>SSH</button>\
|
||||
<button class='btn btn-"+mode_sync_user+" btn-xs slave-db-mode btn-sync-user'>同步账户</button>\
|
||||
</p>\
|
||||
<hr />\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>配置设置</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-success btn-xs btn-slave-ssh'>SSH</button>\
|
||||
<button class='btn btn-success btn-xs btn-slave-user'>同步账户</button>\
|
||||
</p>\
|
||||
</div>",
|
||||
success:function(){
|
||||
$('.btn-slave-ssh').click(function(){
|
||||
getSlaveSSHList();
|
||||
});
|
||||
|
||||
$('.btn-slave-user').click(function(){
|
||||
getSlaveUserList();
|
||||
});
|
||||
|
||||
$('.slave-db-mode').click(function(){
|
||||
var _this = this;
|
||||
var mode = 'none';
|
||||
if ($(this).hasClass('btn-ssh')){
|
||||
mode = 'ssh';
|
||||
}
|
||||
if ($(this).hasClass('btn-sync-user')){
|
||||
mode = 'sync-user';
|
||||
}
|
||||
|
||||
myPost('set_slave_sync_mode', {mode:mode}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
$('.slave-db-mode').remove('btn-success').addClass('btn-danger');
|
||||
$(_this).removeClass('btn-danger').addClass('btn-success');
|
||||
},{icon:rdata.status?1:2},2000);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveUserList(){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
page += '<div class="table_toolbar" style="left:0px;"><span class="sync btn btn-default btn-sm" onclick="addSlaveSyncUser()" title="">添加同步账户</span></div>';
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步账户列表',
|
||||
area: '500px',
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div class='divtable mtb10'>\
|
||||
<div><table class='table table-hover get-slave-ssh-list'>\
|
||||
<thead><tr><th>IP</th><th>PORT</th><th>同步账户</th><th>同步密码</th><th>CMD</th><th>操作</th></tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table></div>\
|
||||
"+page +"\
|
||||
</div>\
|
||||
</div>",
|
||||
success:function(){
|
||||
getSlaveSyncUserPage(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSSHList(page=1){
|
||||
|
||||
@@ -1981,7 +2212,7 @@ function masterOrSlaveConf(version=''){
|
||||
for(i in rdata.data){
|
||||
|
||||
var v = rdata.data[i];
|
||||
var status = "异常";
|
||||
var status = "<a class='btlink db_error'>异常</>";
|
||||
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
|
||||
status = "正常";
|
||||
}
|
||||
@@ -2023,6 +2254,26 @@ function masterOrSlaveConf(version=''){
|
||||
// <span class="sync btn btn-default btn-sm" onclick="getMasterRepSlaveList()" title="">添加</span>\
|
||||
// </div>
|
||||
$(".table_slave_status_list").html(con);
|
||||
|
||||
$('.db_error').click(function(){
|
||||
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>\
|
||||
</div>\
|
||||
</form>",
|
||||
success:function(){
|
||||
copyText(v['Error']);
|
||||
$('.class-copy-db-err').click(function(){
|
||||
copyText(v['Error']);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2100,7 +2351,7 @@ function masterOrSlaveConf(version=''){
|
||||
<p class="conf_p">\
|
||||
<span class="f14 c6 mr20">Slave[从]配置</span><span class="f14 c6 mr20"></span>\
|
||||
<button class="btn '+(!rdata.slave_status ? 'btn-danger' : 'btn-success')+' btn-xs btn-slave">'+(!rdata.slave_status ? '未启动' : '已启动') +'</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveSSHList()" >[主]SSH配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveCfg()" >同步配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="initSlaveStatus()" >初始化</button>\
|
||||
</p>\
|
||||
<hr/>\
|
||||
@@ -2174,10 +2425,10 @@ function masterOrSlaveConf(version=''){
|
||||
getMasterDbList();
|
||||
}
|
||||
|
||||
if (rdata.slave_status){
|
||||
// if (rdata.slave_status){
|
||||
getAsyncMasterDbList();
|
||||
getAsyncDataList()
|
||||
}
|
||||
// }
|
||||
});
|
||||
}
|
||||
getMasterStatus();
|
||||
|
||||
@@ -40,7 +40,7 @@ class backupTools:
|
||||
"----------------------------------------------------------------------------")
|
||||
return
|
||||
|
||||
backup_path = mw.getRootDir() + '/backup/database'
|
||||
backup_path = mw.getRootDir() + '/backup/database/mariadb'
|
||||
if not os.path.exists(backup_path):
|
||||
mw.execShell("mkdir -p " + backup_path)
|
||||
|
||||
|
||||
@@ -36,11 +36,12 @@ max_connect_errors = 100
|
||||
open_files_limit = 2560
|
||||
max_allowed_packet = 128M
|
||||
|
||||
#skip-external-locking
|
||||
#skip-grant-tables
|
||||
#loose-skip-innodb
|
||||
skip_name_resolve = 1
|
||||
skip-ssl
|
||||
#skip-networking
|
||||
#skip-name-resolve
|
||||
#skip-external-locking
|
||||
#loose-skip-innodb
|
||||
#skip-grant-tables
|
||||
|
||||
log-bin=mysql-bin
|
||||
binlog_format=mixed
|
||||
|
||||
@@ -40,4 +40,17 @@ CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
-- 从库配置主库的[user]
|
||||
-- drop table `slave_user`;
|
||||
CREATE TABLE IF NOT EXISTS `slave_sync_user` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`ip` TEXT,
|
||||
`port` TEXT,
|
||||
`user` TEXT,
|
||||
`pass` TEXT,
|
||||
`mode` TEXT,
|
||||
`cmd` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<p onclick="myLogs();">日志</p>
|
||||
<p onclick="pluginLogs('mysql-apt',$('.plugin_version').attr('version'),'show_log');">慢日志</p>
|
||||
<p onclick="dbList()">管理列表</p>
|
||||
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
|
||||
+367
-35
@@ -67,6 +67,13 @@ def getArgs():
|
||||
return tmp
|
||||
|
||||
|
||||
def getBackupDir():
|
||||
bk_path = mw.getBackupDir() + "/database/mysql-apt"
|
||||
if not os.path.isdir(bk_path):
|
||||
mw.execShell("mkdir -p {}".format(bk_path))
|
||||
return bk_path
|
||||
|
||||
|
||||
def checkArgs(data, ck=[]):
|
||||
for i in range(len(ck)):
|
||||
if not ck[i] in data:
|
||||
@@ -115,20 +122,27 @@ def contentReplace(content):
|
||||
def pSqliteDb(dbname='databases'):
|
||||
file = getServerDir() + '/mysql.db'
|
||||
name = 'mysql'
|
||||
if not os.path.exists(file):
|
||||
|
||||
import_sql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
md5_sql = mw.md5(import_sql)
|
||||
|
||||
import_sign = False
|
||||
save_md5_file = getServerDir() + '/import_sql.md5'
|
||||
if os.path.exists(save_md5_file):
|
||||
save_md5_sql = mw.readFile(save_md5_file)
|
||||
if save_md5_sql != md5_sql:
|
||||
import_sign = True
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
else:
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
|
||||
if not os.path.exists(file) or import_sql:
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
csql_list = csql.split(';')
|
||||
csql_list = import_sql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
conn.execute(csql_list[index], ())
|
||||
else:
|
||||
# 现有run
|
||||
# conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
# csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
# csql_list = csql.split(';')
|
||||
# for index in range(len(csql_list)):
|
||||
# conn.execute(csql_list[index], ())
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
return conn
|
||||
|
||||
|
||||
@@ -147,9 +161,16 @@ def pMysqlDb():
|
||||
|
||||
def initDreplace(version=''):
|
||||
|
||||
my_dir = getServerDir() + '/etc'
|
||||
if not os.path.exists(my_dir):
|
||||
os.mkdir(my_dir)
|
||||
conf_dir = getServerDir() + '/etc'
|
||||
mode_dir = conf_dir + '/mode'
|
||||
|
||||
conf_list = [
|
||||
conf_dir,
|
||||
mode_dir,
|
||||
]
|
||||
for conf in conf_list:
|
||||
if not os.path.exists(conf):
|
||||
os.mkdir(conf)
|
||||
|
||||
tmp_dir = getServerDir() + '/tmp'
|
||||
if not os.path.exists(tmp_dir):
|
||||
@@ -157,12 +178,26 @@ def initDreplace(version=''):
|
||||
mw.execShell("chown -R mysql:mysql " + tmp_dir)
|
||||
mw.execShell("chmod 750 " + tmp_dir)
|
||||
|
||||
mysql_conf = my_dir + '/my.cnf'
|
||||
if not os.path.exists(mysql_conf):
|
||||
mysql_conf_tpl = getPluginDir() + '/conf/my' + version + '.cnf'
|
||||
content = mw.readFile(mysql_conf_tpl)
|
||||
my_conf = conf_dir + '/my.cnf'
|
||||
if not os.path.exists(my_conf):
|
||||
tpl = getPluginDir() + '/conf/my' + version + '.cnf'
|
||||
content = mw.readFile(tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(mysql_conf, content)
|
||||
mw.writeFile(my_conf, content)
|
||||
|
||||
classic_conf = mode_dir + '/classic.cnf'
|
||||
if not os.path.exists(classic_conf):
|
||||
tpl = getPluginDir() + '/conf/classic.cnf'
|
||||
content = mw.readFile(tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(classic_conf, content)
|
||||
|
||||
gtid_conf = mode_dir + '/gtid.cnf'
|
||||
if not os.path.exists(gtid_conf):
|
||||
tpl = getPluginDir() + '/conf/gtid.cnf'
|
||||
content = mw.readFile(tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(gtid_conf, content)
|
||||
|
||||
# systemd
|
||||
systemDir = mw.systemdCfgDir()
|
||||
@@ -650,7 +685,11 @@ def __createUser(dbname, username, password, address):
|
||||
|
||||
|
||||
def getDbBackupListFunc(dbname=''):
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
|
||||
bkDir = getBackupDir()
|
||||
if not os.path.exists(bkDir):
|
||||
os.mkdir(bkDir)
|
||||
|
||||
blist = os.listdir(bkDir)
|
||||
r = []
|
||||
|
||||
@@ -684,7 +723,7 @@ def importDbExternal():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
import_dir = mw.getRootDir() + '/backup/import/'
|
||||
import_dir = mw.getBackupDir() + '/import/'
|
||||
|
||||
file_path = import_dir + file
|
||||
if not os.path.exists(file_path):
|
||||
@@ -734,10 +773,13 @@ def importDbExternal():
|
||||
pwd + ' ' + name + ' < ' + import_sql
|
||||
|
||||
# print(mysql_cmd)
|
||||
os.system(mysql_cmd)
|
||||
rdata = mw.execShell(mysql_cmd)
|
||||
if ext != 'sql':
|
||||
os.remove(import_sql)
|
||||
|
||||
if rdata[1].lower().find('error') > -1:
|
||||
return mw.returnJson(False, rdata[1])
|
||||
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
|
||||
@@ -750,11 +792,11 @@ def importDbBackup():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
file_path = mw.getRootDir() + '/backup/database/' + file
|
||||
file_path_sql = mw.getRootDir() + '/backup/database/' + file.replace('.gz', '')
|
||||
file_path = mw.getBackupDir() + '/database/' + file
|
||||
file_path_sql = mw.getBackupDir() + '/database/' + file.replace('.gz', '')
|
||||
|
||||
if not os.path.exists(file_path_sql):
|
||||
cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file
|
||||
cmd = 'cd ' + mw.getBackupDir() + '/database && gzip -d ' + file
|
||||
mw.execShell(cmd)
|
||||
|
||||
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
|
||||
@@ -763,7 +805,12 @@ def importDbBackup():
|
||||
' ' + name + ' < ' + file_path_sql
|
||||
|
||||
# print(mysql_cmd)
|
||||
os.system(mysql_cmd)
|
||||
# os.system(mysql_cmd)
|
||||
|
||||
rdata = mw.execShell(mysql_cmd)
|
||||
if rdata[1].lower().find('error') > -1:
|
||||
return mw.returnJson(False, rdata[1])
|
||||
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
|
||||
@@ -775,7 +822,7 @@ def deleteDbBackup():
|
||||
|
||||
path = args['path']
|
||||
full_file = ""
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
full_file = bkDir + '/' + args['filename']
|
||||
if path != "":
|
||||
full_file = path + "/" + args['filename']
|
||||
@@ -790,7 +837,7 @@ def getDbBackupList():
|
||||
return data[1]
|
||||
|
||||
r = getDbBackupListFunc(args['name'])
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
rr = []
|
||||
for x in range(0, len(r)):
|
||||
p = bkDir + '/' + r[x]
|
||||
@@ -812,8 +859,7 @@ def getDbBackupList():
|
||||
|
||||
|
||||
def getDbBackupImportList():
|
||||
|
||||
bkImportDir = mw.getRootDir() + '/backup/import'
|
||||
bkImportDir = mw.getBackupDir() + '/import'
|
||||
if not os.path.exists(bkImportDir):
|
||||
os.mkdir(bkImportDir)
|
||||
|
||||
@@ -1094,7 +1140,7 @@ def addDb():
|
||||
dataAccess = args['dataAccess'].strip()
|
||||
ps = args['ps'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, args['name']):
|
||||
return mw.returnJson(False, '数据库名称不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1762,7 +1808,7 @@ def addMasterRepSlaveUser(version=''):
|
||||
# address = args['address'].strip()
|
||||
# dataAccess = args['dataAccess'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, username):
|
||||
return mw.returnJson(False, '用户名不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1790,17 +1836,18 @@ def addMasterRepSlaveUser(version=''):
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql = "FLUSH PRIVILEGES;"
|
||||
pdb.execute(sql)
|
||||
else:
|
||||
sql = "GRANT REPLICATION SLAVE ON *.* TO '" + username + \
|
||||
"'@'%' identified by '" + password + "';"
|
||||
result = pdb.execute(sql)
|
||||
result = pdb.execute('FLUSH PRIVILEGES;')
|
||||
isError = isSqlError(result)
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql_select = "grant select,lock tables,PROCESS on *.* to " + username + "@'%';"
|
||||
pdb.execute(sql_select)
|
||||
pdb.execute('FLUSH PRIVILEGES;')
|
||||
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
psdb.add('username,password,accept,ps,addtime',
|
||||
(username, password, '%', '', addTime))
|
||||
@@ -1937,6 +1984,123 @@ def getSlaveSSHList(version=''):
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSlaveSyncUserByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').where(
|
||||
"ip=?", (ip,)).select()
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def addSlaveSyncUser(version=''):
|
||||
import base64
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
if ip == "":
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
data = checkArgs(args, ['port', 'user', 'pass', 'mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
cmd = args['cmd']
|
||||
port = args['port']
|
||||
user = args['user']
|
||||
apass = args['pass']
|
||||
mode = args['mode']
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip').where("ip=?", (ip,)).select()
|
||||
if len(data) > 0:
|
||||
res = conn.where("ip=?", (ip,)).save(
|
||||
'port,user,pass,mode,cmd', (port, user, apass, mode, cmd))
|
||||
else:
|
||||
conn.add('ip,port,user,cmd,user,pass,mode,addtime',
|
||||
(ip, port, user, cmd, user, apass, mode, addTime))
|
||||
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def delSlaveSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
conn.where("ip=?", (ip,)).delete()
|
||||
return mw.returnJson(True, '删除成功!')
|
||||
|
||||
|
||||
def getSlaveSyncUserList(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['page', 'page_size'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
page = int(args['page'])
|
||||
page_size = int(args['page_size'])
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
limit = str((page - 1) * page_size) + ',' + str(page_size)
|
||||
|
||||
field = 'id,ip,port,user,pass,cmd,addtime'
|
||||
clist = conn.field(field).limit(limit).order('id desc').select()
|
||||
count = conn.count()
|
||||
|
||||
data = {}
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['p'] = page
|
||||
_page['row'] = page_size
|
||||
_page['tojs'] = args['tojs']
|
||||
data['page'] = mw.getPage(_page)
|
||||
data['data'] = clist
|
||||
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSyncModeFile():
|
||||
return getServerDir() + "/sync.mode"
|
||||
|
||||
|
||||
def getSlaveSyncMode(version):
|
||||
sync_mode = getSyncModeFile()
|
||||
if os.path.exists(sync_mode):
|
||||
mode = mw.readFile(sync_mode).strip()
|
||||
return mw.returnJson(True, 'ok', mode)
|
||||
return mw.returnJson(False, 'fail')
|
||||
|
||||
|
||||
def setSlaveSyncMode(version):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
mode = args['mode']
|
||||
sync_mode = getSyncModeFile()
|
||||
|
||||
if mode == 'none':
|
||||
os.remove(sync_mode)
|
||||
else:
|
||||
mw.writeFile(sync_mode, mode)
|
||||
return mw.returnJson(True, '设置成功', mode)
|
||||
|
||||
|
||||
def getSlaveSSHByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
@@ -2023,6 +2187,24 @@ def getSlaveList(version=''):
|
||||
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
|
||||
@@ -2039,6 +2221,47 @@ def getSlaveSyncCmd(version=''):
|
||||
|
||||
|
||||
def initSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return initSlaveStatusSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return initSlaveStatusSyncUser(version)
|
||||
|
||||
|
||||
def initSlaveStatusSyncUser(version=''):
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
if len(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'
|
||||
|
||||
local_mode = recognizeDbMode()
|
||||
if local_mode != mode_name:
|
||||
return mw.returnJson(False, '同步模式不一致!')
|
||||
|
||||
t = db.query(u['cmd'])
|
||||
# print(t)
|
||||
db.query("start slave user='{}' password='{}';".format(
|
||||
u['user'], u['pass']))
|
||||
return mw.returnJson(True, '初始化成功!')
|
||||
|
||||
|
||||
def initSlaveStatusSSH(version=''):
|
||||
db = pMysqlDb()
|
||||
dlist = db.query('show slave status')
|
||||
if len(dlist) > 0:
|
||||
@@ -2107,6 +2330,41 @@ def initSlaveStatus(version=''):
|
||||
|
||||
|
||||
def setSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
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)
|
||||
|
||||
|
||||
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']
|
||||
|
||||
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')
|
||||
@@ -2175,6 +2433,68 @@ def writeDbSyncStatus(data):
|
||||
|
||||
|
||||
def doFullSync(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return doFullSyncSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return doFullSyncUser(version)
|
||||
|
||||
|
||||
def doFullSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
sync_db = args['db']
|
||||
|
||||
db = pMysqlDb()
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
user = data['user']
|
||||
apass = data['pass']
|
||||
port = data['port']
|
||||
ip = data['ip']
|
||||
|
||||
bak_file = '/tmp/tmp.sql'
|
||||
|
||||
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
|
||||
dmp_option = ''
|
||||
mode = recognizeDbMode()
|
||||
if mode == 'gtid':
|
||||
dmp_option = ' --set-gtid-purged=off '
|
||||
|
||||
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 + " " + sync_db + " > " + bak_file
|
||||
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 + \
|
||||
' ' + sync_db + ' < ' + bak_file
|
||||
mw.execShell(my_import_cmd)
|
||||
|
||||
if version == '8.0':
|
||||
db.query("start slave user='{}' password='{}';".format(user, apass))
|
||||
else:
|
||||
db.query("start slave")
|
||||
|
||||
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
|
||||
os.system("rm -rf " + bak_file)
|
||||
return True
|
||||
|
||||
|
||||
def doFullSyncSSH(version=''):
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
@@ -2506,6 +2826,18 @@ if __name__ == "__main__":
|
||||
print(delSlaveSSH(version))
|
||||
elif func == 'update_slave_ssh':
|
||||
print(updateSlaveSSH(version))
|
||||
elif func == 'get_slave_sync_user_list':
|
||||
print(getSlaveSyncUserList(version))
|
||||
elif func == 'get_slave_sync_user_by_ip':
|
||||
print(getSlaveSyncUserByIp(version))
|
||||
elif func == 'add_slave_sync_user':
|
||||
print(addSlaveSyncUser(version))
|
||||
elif func == 'del_slave_sync_user':
|
||||
print(delSlaveSyncUser(version))
|
||||
elif func == 'get_slave_sync_mode':
|
||||
print(getSlaveSyncMode(version))
|
||||
elif func == 'set_slave_sync_mode':
|
||||
print(setSlaveSyncMode(version))
|
||||
elif func == 'init_slave_status':
|
||||
print(initSlaveStatus(version))
|
||||
elif func == 'set_slave_status':
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"hook":["database"],
|
||||
"title":"MySQL[APT]",
|
||||
"tip":"soft",
|
||||
"name":"mysql-apt",
|
||||
"type":"运行环境",
|
||||
"ps":"[<b style='color:red;'>潜龙勿用</b>]一种关系数据库管理系统[debian,ubuntu](极速安装)",
|
||||
"ps":"一种关系数据库管理系统[debian,ubuntu](极速安装)",
|
||||
"todo_versions":["5.7","8.0"],
|
||||
"versions":["5.7","8.0"],
|
||||
"shell":"install.sh",
|
||||
|
||||
@@ -509,19 +509,6 @@ function showHidePass(obj){
|
||||
}
|
||||
}
|
||||
|
||||
function copyPass(password){
|
||||
var clipboard = new ClipboardJS('#bt_copys');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg('复制成功',{icon:1,time:2000});
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000});
|
||||
});
|
||||
$("#bt_copys").attr('data-clipboard-text',password);
|
||||
$("#bt_copys").click();
|
||||
}
|
||||
|
||||
function checkSelect(){
|
||||
setTimeout(function () {
|
||||
var num = $('input[type="checkbox"].check:checked').length;
|
||||
@@ -744,7 +731,7 @@ function addDatabase(type){
|
||||
layer.close(index);
|
||||
dbList();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
},{icon: rdata.status ? 1 : 2}, 2000);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1558,13 +1545,9 @@ function getMasterRepSlaveUserCmd(username, db=''){
|
||||
function delMasterRepSlaveUser(username){
|
||||
myPost('del_master_rep_slave_user', {username:username}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg);
|
||||
|
||||
$('.layui-layer-close1').click();
|
||||
|
||||
setTimeout(function(){
|
||||
showMsg(rdata.msg, function(){
|
||||
getMasterRepSlaveList();
|
||||
},1000);
|
||||
},{icon: rdata.status ? 1 : 2},1000)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1834,8 +1817,23 @@ function addSlaveSSH(ip=''){
|
||||
function delSlaveSSH(ip){
|
||||
myPost('del_slave_ssh', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2});
|
||||
getSlaveSSHPage();
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSSHPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function delSlaveSyncUser(ip){
|
||||
myPost('del_slave_sync_user', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1885,6 +1883,237 @@ function getSlaveSSHPage(page=1){
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addSlaveSyncUser(ip=''){
|
||||
|
||||
myPost('get_slave_sync_user_by_ip', {ip:ip}, function(rdata){
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
|
||||
var ip = '127.0.0.1';
|
||||
var port = "22";
|
||||
var cmd = '';
|
||||
var user = 'input_sync_user';
|
||||
var pass = 'input_sync_pwd';
|
||||
var mode = '0';
|
||||
|
||||
if (rdata.data.length>0){
|
||||
ip = rdata.data[0]['ip'];
|
||||
port = rdata.data[0]['port'];
|
||||
cmd = rdata.data[0]['cmd'];
|
||||
user = rdata.data[0]['user'];
|
||||
pass = rdata.data[0]['pass'];
|
||||
mode = rdata.data[0]['mode'];
|
||||
}
|
||||
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
area: ['500px','470px'],
|
||||
title: '同步账户',
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
btn:["确认","取消"],
|
||||
content: "<form class='bt-form pd20'>\
|
||||
<div class='line'><span class='tname'>IP</span><div class='info-r'><input name='ip' class='bt-input-text mr5' type='text' style='width:330px;' value='"+ip+"'></div></div>\
|
||||
<div class='line'><span class='tname'>端口</span><div class='info-r'><input name='port' class='bt-input-text mr5' type='number' style='width:330px;' value='"+port+"'></div></div>\
|
||||
<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>\
|
||||
<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 = {};
|
||||
for (var i in vlist) {
|
||||
var tmp = toTrim(vlist[i]);
|
||||
var tmp_a = tmp.split(" ");
|
||||
var real_tmp = tmp_a[tmp_a.length-1];
|
||||
var kv = real_tmp.split("=");
|
||||
a[kv[0]] = kv[1].replace("'",'').replace("'",'');
|
||||
}
|
||||
|
||||
$('input[name="ip"]').val(a['MASTER_HOST']);
|
||||
$('input[name="port"]').val(a['MASTER_PORT']);
|
||||
$('input[name="user"]').val(a['MASTER_USER']);
|
||||
$('input[name="pass"]').val(a['MASTER_PASSWORD']);
|
||||
|
||||
console.log(a['MASTER_AUTO_POSITION'],typeof(a['MASTER_AUTO_POSITION']));
|
||||
if (typeof(a['MASTER_AUTO_POSITION']) != 'undefined' ){
|
||||
$('input[name="mode"]').val('1');
|
||||
}
|
||||
});
|
||||
},
|
||||
yes:function(index){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var user = $('input[name="user"]').val();
|
||||
var pass = $('input[name="pass"]').val();
|
||||
var cmd = $('textarea[name="cmd"]').val();
|
||||
var mode = $('input[name="mode"]').val();
|
||||
|
||||
var data = {ip:ip,port:port,cmd:cmd,user:user,pass:pass,mode:mode};
|
||||
myPost('add_slave_sync_user', data, function(ret_data){
|
||||
layer.close(index);
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSyncUserPage(page=1){
|
||||
var _data = {};
|
||||
_data['page'] = page;
|
||||
_data['page_size'] = 5;
|
||||
_data['tojs'] ='getSlaveSyncUserPage';
|
||||
myPost('get_slave_sync_user_list', _data, function(data){
|
||||
var layerId = null;
|
||||
var rdata = [];
|
||||
try {
|
||||
rdata = $.parseJSON(data.data);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var list = '';
|
||||
var user_list = rdata['data'];
|
||||
for (i in user_list) {
|
||||
var ip = user_list[i]['ip'];
|
||||
var port = user_list[i]['port'];
|
||||
var user = user_list[i]['user'];
|
||||
var apass = user_list[i]['pass'];
|
||||
|
||||
var cmd = '未设置';
|
||||
if (user_list[i]['cmd']!=''){
|
||||
cmd = '已设置';
|
||||
}
|
||||
|
||||
list += '<tr><td>'+ip+'</td>\
|
||||
<td>'+port+'</td>\
|
||||
<td>'+user+'</td>\
|
||||
<td>'+apass+'</td>\
|
||||
<td>'+cmd+'</td>\
|
||||
<td>\
|
||||
<a class="btlink" onclick="addSlaveSyncUser(\''+ip+'\');">修改</a> | \
|
||||
<a class="btlink" onclick="delSlaveSyncUser(\''+ip+'\');">删除</a>\
|
||||
</td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$('.get-slave-ssh-list tbody').html(list);
|
||||
$('.dataTables_paginate_4').html(rdata['page']);
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveCfg(){
|
||||
|
||||
myPost('get_slave_sync_mode', '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var mode_none = 'success';
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'danger';
|
||||
if(rdata.status){
|
||||
var mode_none = 'danger';
|
||||
if (rdata.data == 'ssh'){
|
||||
var mode_ssh = 'success';
|
||||
var mode_sync_user = 'danger';
|
||||
} else {
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步配置',
|
||||
area: ['400px','180px'],
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>当前从库同步模式</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-"+mode_none+" btn-xs slave-db-mode btn-none'>无</button>\
|
||||
<button class='btn btn-"+mode_ssh+" btn-xs slave-db-mode btn-ssh'>SSH</button>\
|
||||
<button class='btn btn-"+mode_sync_user+" btn-xs slave-db-mode btn-sync-user'>同步账户</button>\
|
||||
</p>\
|
||||
<hr />\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>配置设置</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-success btn-xs btn-slave-ssh'>SSH</button>\
|
||||
<button class='btn btn-success btn-xs btn-slave-user'>同步账户</button>\
|
||||
</p>\
|
||||
</div>",
|
||||
success:function(){
|
||||
$('.btn-slave-ssh').click(function(){
|
||||
getSlaveSSHList();
|
||||
});
|
||||
|
||||
$('.btn-slave-user').click(function(){
|
||||
getSlaveUserList();
|
||||
});
|
||||
|
||||
$('.slave-db-mode').click(function(){
|
||||
var _this = this;
|
||||
var mode = 'none';
|
||||
if ($(this).hasClass('btn-ssh')){
|
||||
mode = 'ssh';
|
||||
}
|
||||
if ($(this).hasClass('btn-sync-user')){
|
||||
mode = 'sync-user';
|
||||
}
|
||||
|
||||
myPost('set_slave_sync_mode', {mode:mode}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
$('.slave-db-mode').remove('btn-success').addClass('btn-danger');
|
||||
$(_this).removeClass('btn-danger').addClass('btn-success');
|
||||
},{icon:rdata.status?1:2},2000);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getSlaveUserList(){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
page += '<div class="table_toolbar" style="left:0px;"><span class="sync btn btn-default btn-sm" onclick="addSlaveSyncUser()" title="">添加同步账户</span></div>';
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步账户列表',
|
||||
area: '500px',
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div class='divtable mtb10'>\
|
||||
<div><table class='table table-hover get-slave-ssh-list'>\
|
||||
<thead><tr><th>IP</th><th>PORT</th><th>同步账户</th><th>同步密码</th><th>CMD</th><th>操作</th></tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table></div>\
|
||||
"+page +"\
|
||||
</div>\
|
||||
</div>",
|
||||
success:function(){
|
||||
getSlaveSyncUserPage(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSSHList(page=1){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
@@ -2004,7 +2233,7 @@ function masterOrSlaveConf(version=''){
|
||||
for(i in rdata.data){
|
||||
|
||||
var v = rdata.data[i];
|
||||
var status = "异常";
|
||||
var status = "<a class='btlink db_error'>异常</>";
|
||||
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
|
||||
status = "正常";
|
||||
}
|
||||
@@ -2046,6 +2275,26 @@ function masterOrSlaveConf(version=''){
|
||||
// <span class="sync btn btn-default btn-sm" onclick="getMasterRepSlaveList()" title="">添加</span>\
|
||||
// </div>
|
||||
$(".table_slave_status_list").html(con);
|
||||
|
||||
$('.db_error').click(function(){
|
||||
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>\
|
||||
</div>\
|
||||
</form>",
|
||||
success:function(){
|
||||
copyText(v['Error']);
|
||||
$('.class-copy-db-err').click(function(){
|
||||
copyText(v['Error']);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2092,7 +2341,6 @@ function masterOrSlaveConf(version=''){
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getMasterStatus(){
|
||||
myPost('get_master_status', '', function(rdata){
|
||||
@@ -2123,7 +2371,7 @@ function masterOrSlaveConf(version=''){
|
||||
<p class="conf_p">\
|
||||
<span class="f14 c6 mr20">Slave[从]配置</span><span class="f14 c6 mr20"></span>\
|
||||
<button class="btn '+(!rdata.slave_status ? 'btn-danger' : 'btn-success')+' btn-xs btn-slave">'+(!rdata.slave_status ? '未启动' : '已启动') +'</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveSSHList()" >[主]SSH配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveCfg()" >同步配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="initSlaveStatus()" >初始化</button>\
|
||||
</p>\
|
||||
<hr/>\
|
||||
@@ -2197,10 +2445,10 @@ function masterOrSlaveConf(version=''){
|
||||
getMasterDbList();
|
||||
}
|
||||
|
||||
if (rdata.slave_status){
|
||||
// if (rdata.slave_status){
|
||||
getAsyncMasterDbList();
|
||||
getAsyncDataList()
|
||||
}
|
||||
// }
|
||||
});
|
||||
}
|
||||
getMasterStatus();
|
||||
|
||||
@@ -44,7 +44,7 @@ class backupTools:
|
||||
"----------------------------------------------------------------------------")
|
||||
return
|
||||
|
||||
backup_path = mw.getRootDir() + '/backup/database'
|
||||
backup_path = mw.getRootDir() + '/backup/database/mysql-apt'
|
||||
if not os.path.exists(backup_path):
|
||||
mw.execShell("mkdir -p " + backup_path)
|
||||
|
||||
|
||||
@@ -37,11 +37,12 @@ max_connect_errors = 100
|
||||
open_files_limit = 2560
|
||||
max_allowed_packet = 128M
|
||||
|
||||
#skip-external-locking
|
||||
#skip-grant-tables
|
||||
#loose-skip-innodb
|
||||
skip_name_resolve = 1
|
||||
skip-ssl
|
||||
#skip-networking
|
||||
#skip-name-resolve
|
||||
#skip-external-locking
|
||||
#loose-skip-innodb
|
||||
#skip-grant-tables
|
||||
|
||||
log-bin=mysql-bin
|
||||
binlog_format=mixed
|
||||
|
||||
@@ -40,4 +40,17 @@ CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
-- 从库配置主库的[user]
|
||||
-- drop table `slave_user`;
|
||||
CREATE TABLE IF NOT EXISTS `slave_sync_user` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`ip` TEXT,
|
||||
`port` TEXT,
|
||||
`user` TEXT,
|
||||
`pass` TEXT,
|
||||
`mode` TEXT,
|
||||
`cmd` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<p onclick="myLogs();">日志</p>
|
||||
<p onclick="pluginLogs('mysql-yum',$('.plugin_version').attr('version'),'show_log');">慢日志</p>
|
||||
<p onclick="dbList()">管理列表</p>
|
||||
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
|
||||
+350
-37
@@ -65,6 +65,13 @@ def checkArgs(data, ck=[]):
|
||||
return (True, mw.returnJson(True, 'ok'))
|
||||
|
||||
|
||||
def getBackupDir():
|
||||
bk_path = mw.getBackupDir() + "/database/mysql-yum"
|
||||
if not os.path.isdir(bk_path):
|
||||
mw.execShell("mkdir -p {}".format(bk_path))
|
||||
return bk_path
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getServerDir() + '/etc/my.cnf'
|
||||
return path
|
||||
@@ -122,20 +129,27 @@ def contentReplace(content):
|
||||
def pSqliteDb(dbname='databases'):
|
||||
file = getServerDir() + '/mysql.db'
|
||||
name = 'mysql'
|
||||
if not os.path.exists(file):
|
||||
|
||||
import_sql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
md5_sql = mw.md5(import_sql)
|
||||
|
||||
import_sign = False
|
||||
save_md5_file = getServerDir() + '/import_sql.md5'
|
||||
if os.path.exists(save_md5_file):
|
||||
save_md5_sql = mw.readFile(save_md5_file)
|
||||
if save_md5_sql != md5_sql:
|
||||
import_sign = True
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
else:
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
|
||||
if not os.path.exists(file) or import_sql:
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
csql_list = csql.split(';')
|
||||
csql_list = import_sql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
conn.execute(csql_list[index], ())
|
||||
else:
|
||||
# 现有run
|
||||
# conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
# csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
# csql_list = csql.split(';')
|
||||
# for index in range(len(csql_list)):
|
||||
# conn.execute(csql_list[index], ())
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
return conn
|
||||
|
||||
|
||||
@@ -154,9 +168,16 @@ def pMysqlDb():
|
||||
|
||||
def initDreplace(version=''):
|
||||
|
||||
my_dir = getServerDir() + '/etc'
|
||||
if not os.path.exists(my_dir):
|
||||
os.mkdir(my_dir)
|
||||
conf_dir = getServerDir() + '/etc'
|
||||
mode_dir = conf_dir + '/mode'
|
||||
|
||||
conf_list = [
|
||||
conf_dir,
|
||||
mode_dir,
|
||||
]
|
||||
for conf in conf_list:
|
||||
if not os.path.exists(conf):
|
||||
os.mkdir(conf)
|
||||
|
||||
tmp_dir = getServerDir() + '/tmp'
|
||||
if not os.path.exists(tmp_dir):
|
||||
@@ -164,12 +185,26 @@ def initDreplace(version=''):
|
||||
mw.execShell("chown -R mysql:mysql " + tmp_dir)
|
||||
mw.execShell("chmod 750 " + tmp_dir)
|
||||
|
||||
mysql_conf = my_dir + '/my.cnf'
|
||||
if not os.path.exists(mysql_conf):
|
||||
mysql_conf_tpl = getPluginDir() + '/conf/my' + version + '.cnf'
|
||||
content = mw.readFile(mysql_conf_tpl)
|
||||
my_conf = conf_dir + '/my.cnf'
|
||||
if not os.path.exists(my_conf):
|
||||
tpl = getPluginDir() + '/conf/my' + version + '.cnf'
|
||||
content = mw.readFile(tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(mysql_conf, content)
|
||||
mw.writeFile(my_conf, content)
|
||||
|
||||
classic_conf = mode_dir + '/classic.cnf'
|
||||
if not os.path.exists(classic_conf):
|
||||
tpl = getPluginDir() + '/conf/classic.cnf'
|
||||
content = mw.readFile(tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(classic_conf, content)
|
||||
|
||||
gtid_conf = mode_dir + '/gtid.cnf'
|
||||
if not os.path.exists(gtid_conf):
|
||||
tpl = getPluginDir() + '/conf/gtid.cnf'
|
||||
content = mw.readFile(tpl)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(gtid_conf, content)
|
||||
|
||||
# systemd
|
||||
systemDir = mw.systemdCfgDir()
|
||||
@@ -226,6 +261,13 @@ def binLog():
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def cleanBinLog():
|
||||
db = pMysqlDb()
|
||||
cleanTime = time.strftime('%Y-%m-%d %H:%i:%s', time.localtime())
|
||||
db.execute("PURGE MASTER LOGS BEFORE '" + cleanTime + "';")
|
||||
return mw.returnJson(True, '清理BINLOG成功!')
|
||||
|
||||
|
||||
def setSkipGrantTables(v):
|
||||
'''
|
||||
设置是否密码验证
|
||||
@@ -629,7 +671,7 @@ def __createUser(dbname, username, password, address):
|
||||
|
||||
|
||||
def getDbBackupListFunc(dbname=''):
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
blist = os.listdir(bkDir)
|
||||
r = []
|
||||
|
||||
@@ -663,7 +705,7 @@ def importDbExternal():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
import_dir = mw.getRootDir() + '/backup/import/'
|
||||
import_dir = mw.getBackupDir() + '/import/'
|
||||
|
||||
file_path = import_dir + file
|
||||
if not os.path.exists(file_path):
|
||||
@@ -712,11 +754,13 @@ def importDbExternal():
|
||||
mysql_cmd = getServerDir() + '/bin/usr/bin/mysql -S ' + sock + ' -uroot -p' + \
|
||||
pwd + ' ' + name + ' < ' + import_sql
|
||||
|
||||
# print(mysql_cmd)
|
||||
os.system(mysql_cmd)
|
||||
rdata = mw.execShell(mysql_cmd)
|
||||
if ext != 'sql':
|
||||
os.remove(import_sql)
|
||||
|
||||
if rdata[1].lower().find('error') > -1:
|
||||
return mw.returnJson(False, rdata[1])
|
||||
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
|
||||
@@ -729,11 +773,11 @@ def importDbBackup():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
file_path = mw.getRootDir() + '/backup/database/' + file
|
||||
file_path_sql = mw.getRootDir() + '/backup/database/' + file.replace('.gz', '')
|
||||
file_path = getBackupDir() + '/' + file
|
||||
file_path_sql = getBackupDir() + '/' + file.replace('.gz', '')
|
||||
|
||||
if not os.path.exists(file_path_sql):
|
||||
cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file
|
||||
cmd = 'cd ' + mw.getBackupDir() + '/database && gzip -d ' + file
|
||||
mw.execShell(cmd)
|
||||
|
||||
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
|
||||
@@ -741,8 +785,10 @@ def importDbBackup():
|
||||
mysql_cmd = getServerDir() + '/bin/usr/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
|
||||
' ' + name + ' < ' + file_path_sql
|
||||
|
||||
# print(mysql_cmd)
|
||||
os.system(mysql_cmd)
|
||||
rdata = mw.execShell(mysql_cmd)
|
||||
if rdata[1].lower().find('error') > -1:
|
||||
return mw.returnJson(False, rdata[1])
|
||||
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
|
||||
@@ -754,7 +800,7 @@ def deleteDbBackup():
|
||||
|
||||
path = args['path']
|
||||
full_file = ""
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
full_file = bkDir + '/' + args['filename']
|
||||
if path != "":
|
||||
full_file = path + "/" + args['filename']
|
||||
@@ -769,7 +815,7 @@ def getDbBackupList():
|
||||
return data[1]
|
||||
|
||||
r = getDbBackupListFunc(args['name'])
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
rr = []
|
||||
for x in range(0, len(r)):
|
||||
p = bkDir + '/' + r[x]
|
||||
@@ -791,8 +837,7 @@ def getDbBackupList():
|
||||
|
||||
|
||||
def getDbBackupImportList():
|
||||
|
||||
bkImportDir = mw.getRootDir() + '/backup/import'
|
||||
bkImportDir = mw.getBackupDir() + '/import'
|
||||
if not os.path.exists(bkImportDir):
|
||||
os.mkdir(bkImportDir)
|
||||
|
||||
@@ -1073,7 +1118,7 @@ def addDb():
|
||||
dataAccess = args['dataAccess'].strip()
|
||||
ps = args['ps'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, args['name']):
|
||||
return mw.returnJson(False, '数据库名称不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1741,7 +1786,7 @@ def addMasterRepSlaveUser(version=''):
|
||||
# address = args['address'].strip()
|
||||
# dataAccess = args['dataAccess'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, username):
|
||||
return mw.returnJson(False, '用户名不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1769,17 +1814,18 @@ def addMasterRepSlaveUser(version=''):
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql = "FLUSH PRIVILEGES;"
|
||||
pdb.execute(sql)
|
||||
else:
|
||||
sql = "GRANT REPLICATION SLAVE ON *.* TO '" + username + \
|
||||
"'@'%' identified by '" + password + "';"
|
||||
result = pdb.execute(sql)
|
||||
result = pdb.execute('FLUSH PRIVILEGES;')
|
||||
isError = isSqlError(result)
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql_select = "grant select,lock tables,PROCESS on *.* to " + username + "@'%';"
|
||||
pdb.execute(sql_select)
|
||||
pdb.execute('FLUSH PRIVILEGES;')
|
||||
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
psdb.add('username,password,accept,ps,addtime',
|
||||
(username, password, '%', '', addTime))
|
||||
@@ -1916,6 +1962,123 @@ def getSlaveSSHList(version=''):
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSlaveSyncUserByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').where(
|
||||
"ip=?", (ip,)).select()
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def addSlaveSyncUser(version=''):
|
||||
import base64
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
if ip == "":
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
data = checkArgs(args, ['port', 'user', 'pass', 'mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
cmd = args['cmd']
|
||||
port = args['port']
|
||||
user = args['user']
|
||||
apass = args['pass']
|
||||
mode = args['mode']
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip').where("ip=?", (ip,)).select()
|
||||
if len(data) > 0:
|
||||
res = conn.where("ip=?", (ip,)).save(
|
||||
'port,user,pass,mode,cmd', (port, user, apass, mode, cmd))
|
||||
else:
|
||||
conn.add('ip,port,user,cmd,user,pass,mode,addtime',
|
||||
(ip, port, user, cmd, user, apass, mode, addTime))
|
||||
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def delSlaveSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
conn.where("ip=?", (ip,)).delete()
|
||||
return mw.returnJson(True, '删除成功!')
|
||||
|
||||
|
||||
def getSlaveSyncUserList(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['page', 'page_size'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
page = int(args['page'])
|
||||
page_size = int(args['page_size'])
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
limit = str((page - 1) * page_size) + ',' + str(page_size)
|
||||
|
||||
field = 'id,ip,port,user,pass,cmd,addtime'
|
||||
clist = conn.field(field).limit(limit).order('id desc').select()
|
||||
count = conn.count()
|
||||
|
||||
data = {}
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['p'] = page
|
||||
_page['row'] = page_size
|
||||
_page['tojs'] = args['tojs']
|
||||
data['page'] = mw.getPage(_page)
|
||||
data['data'] = clist
|
||||
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSyncModeFile():
|
||||
return getServerDir() + "/sync.mode"
|
||||
|
||||
|
||||
def getSlaveSyncMode(version):
|
||||
sync_mode = getSyncModeFile()
|
||||
if os.path.exists(sync_mode):
|
||||
mode = mw.readFile(sync_mode).strip()
|
||||
return mw.returnJson(True, 'ok', mode)
|
||||
return mw.returnJson(False, 'fail')
|
||||
|
||||
|
||||
def setSlaveSyncMode(version):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
mode = args['mode']
|
||||
sync_mode = getSyncModeFile()
|
||||
|
||||
if mode == 'none':
|
||||
os.remove(sync_mode)
|
||||
else:
|
||||
mw.writeFile(sync_mode, mode)
|
||||
return mw.returnJson(True, '设置成功', mode)
|
||||
|
||||
|
||||
def getSlaveSSHByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
@@ -2018,6 +2181,47 @@ def getSlaveSyncCmd(version=''):
|
||||
|
||||
|
||||
def initSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return initSlaveStatusSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return initSlaveStatusSyncUser(version)
|
||||
|
||||
|
||||
def initSlaveStatusSyncUser(version=''):
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
if len(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'
|
||||
|
||||
local_mode = recognizeDbMode()
|
||||
if local_mode != mode_name:
|
||||
return mw.returnJson(False, '同步模式不一致!')
|
||||
|
||||
t = db.query(u['cmd'])
|
||||
# print(t)
|
||||
db.query("start slave user='{}' password='{}';".format(
|
||||
u['user'], u['pass']))
|
||||
return mw.returnJson(True, '初始化成功!')
|
||||
|
||||
|
||||
def initSlaveStatusSSH(version=''):
|
||||
db = pMysqlDb()
|
||||
dlist = db.query('show slave status')
|
||||
if len(dlist) > 0:
|
||||
@@ -2086,6 +2290,41 @@ def initSlaveStatus(version=''):
|
||||
|
||||
|
||||
def setSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
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)
|
||||
|
||||
|
||||
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']
|
||||
|
||||
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')
|
||||
@@ -2154,6 +2393,68 @@ def writeDbSyncStatus(data):
|
||||
|
||||
|
||||
def doFullSync(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return doFullSyncSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return doFullSyncUser(version)
|
||||
|
||||
|
||||
def doFullSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
sync_db = args['db']
|
||||
|
||||
db = pMysqlDb()
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
user = data['user']
|
||||
apass = data['pass']
|
||||
port = data['port']
|
||||
ip = data['ip']
|
||||
|
||||
bak_file = '/tmp/tmp.sql'
|
||||
|
||||
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
|
||||
dmp_option = ''
|
||||
mode = recognizeDbMode()
|
||||
if mode == 'gtid':
|
||||
dmp_option = ' --set-gtid-purged=off '
|
||||
|
||||
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 + " " + sync_db + " > " + bak_file
|
||||
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 + \
|
||||
' ' + sync_db + ' < ' + bak_file
|
||||
mw.execShell(my_import_cmd)
|
||||
|
||||
if version == '8.0':
|
||||
db.query("start slave user='{}' password='{}';".format(user, apass))
|
||||
else:
|
||||
db.query("start slave")
|
||||
|
||||
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
|
||||
os.system("rm -rf " + bak_file)
|
||||
return True
|
||||
|
||||
|
||||
def doFullSyncSSH(version=''):
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
@@ -2479,6 +2780,18 @@ if __name__ == "__main__":
|
||||
print(delSlaveSSH(version))
|
||||
elif func == 'update_slave_ssh':
|
||||
print(updateSlaveSSH(version))
|
||||
elif func == 'get_slave_sync_user_list':
|
||||
print(getSlaveSyncUserList(version))
|
||||
elif func == 'get_slave_sync_user_by_ip':
|
||||
print(getSlaveSyncUserByIp(version))
|
||||
elif func == 'add_slave_sync_user':
|
||||
print(addSlaveSyncUser(version))
|
||||
elif func == 'del_slave_sync_user':
|
||||
print(delSlaveSyncUser(version))
|
||||
elif func == 'get_slave_sync_mode':
|
||||
print(getSlaveSyncMode(version))
|
||||
elif func == 'set_slave_sync_mode':
|
||||
print(setSlaveSyncMode(version))
|
||||
elif func == 'init_slave_status':
|
||||
print(initSlaveStatus(version))
|
||||
elif func == 'set_slave_status':
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"hook":["database"],
|
||||
"title":"MySQL[YUM]",
|
||||
"tip":"soft",
|
||||
"name":"mysql-yum",
|
||||
"type":"运行环境",
|
||||
"ps":"[<b style='color:red;'>潜龙勿用</b>]一种关系数据库管理系统[centos](极速安装)",
|
||||
"ps":"一种关系数据库管理系统[centos](极速安装)",
|
||||
"todo_versions":["5.7","8.0"],
|
||||
"versions":["5.7","8.0"],
|
||||
"shell":"install.sh",
|
||||
|
||||
@@ -265,7 +265,7 @@ function myPerfOpt() {
|
||||
}
|
||||
|
||||
function reBootMySqld(){
|
||||
pluginOpService('mysql-apt','restart','');
|
||||
pluginOpService('mysql-yum','restart','');
|
||||
}
|
||||
|
||||
|
||||
@@ -509,19 +509,6 @@ function showHidePass(obj){
|
||||
}
|
||||
}
|
||||
|
||||
function copyPass(password){
|
||||
var clipboard = new ClipboardJS('#bt_copys');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg('复制成功',{icon:1,time:2000});
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000});
|
||||
});
|
||||
$("#bt_copys").attr('data-clipboard-text',password);
|
||||
$("#bt_copys").click();
|
||||
}
|
||||
|
||||
function checkSelect(){
|
||||
setTimeout(function () {
|
||||
var num = $('input[type="checkbox"].check:checked').length;
|
||||
@@ -744,7 +731,7 @@ function addDatabase(type){
|
||||
layer.close(index);
|
||||
dbList();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
},{icon: rdata.status ? 1 : 2}, 2000);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -831,7 +818,7 @@ function openPhpmyadmin(name,username,password){
|
||||
|
||||
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_cfg'});
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (rdata.choose != 'mysql-apt'){
|
||||
if (rdata.choose != 'mysql-yum'){
|
||||
layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
@@ -1220,7 +1207,7 @@ function myLogs(){
|
||||
var limitCon = '<p class="conf_p">\
|
||||
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
|
||||
'+line_status+'\
|
||||
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;">清理日志</button></p>\
|
||||
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
|
||||
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
|
||||
</p>';
|
||||
$(".soft-man-con").html(limitCon);
|
||||
@@ -1558,13 +1545,9 @@ function getMasterRepSlaveUserCmd(username, db=''){
|
||||
function delMasterRepSlaveUser(username){
|
||||
myPost('del_master_rep_slave_user', {username:username}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg);
|
||||
|
||||
$('.layui-layer-close1').click();
|
||||
|
||||
setTimeout(function(){
|
||||
showMsg(rdata.msg, function(){
|
||||
getMasterRepSlaveList();
|
||||
},1000);
|
||||
},{icon: rdata.status ? 1 : 2},1000)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1834,8 +1817,23 @@ function addSlaveSSH(ip=''){
|
||||
function delSlaveSSH(ip){
|
||||
myPost('del_slave_ssh', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2});
|
||||
getSlaveSSHPage();
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSSHPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function delSlaveSyncUser(ip){
|
||||
myPost('del_slave_sync_user', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1885,6 +1883,237 @@ function getSlaveSSHPage(page=1){
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addSlaveSyncUser(ip=''){
|
||||
|
||||
myPost('get_slave_sync_user_by_ip', {ip:ip}, function(rdata){
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
|
||||
var ip = '127.0.0.1';
|
||||
var port = "22";
|
||||
var cmd = '';
|
||||
var user = 'input_sync_user';
|
||||
var pass = 'input_sync_pwd';
|
||||
var mode = '0';
|
||||
|
||||
if (rdata.data.length>0){
|
||||
ip = rdata.data[0]['ip'];
|
||||
port = rdata.data[0]['port'];
|
||||
cmd = rdata.data[0]['cmd'];
|
||||
user = rdata.data[0]['user'];
|
||||
pass = rdata.data[0]['pass'];
|
||||
mode = rdata.data[0]['mode'];
|
||||
}
|
||||
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
area: ['500px','470px'],
|
||||
title: '同步账户',
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
btn:["确认","取消"],
|
||||
content: "<form class='bt-form pd20'>\
|
||||
<div class='line'><span class='tname'>IP</span><div class='info-r'><input name='ip' class='bt-input-text mr5' type='text' style='width:330px;' value='"+ip+"'></div></div>\
|
||||
<div class='line'><span class='tname'>端口</span><div class='info-r'><input name='port' class='bt-input-text mr5' type='number' style='width:330px;' value='"+port+"'></div></div>\
|
||||
<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>\
|
||||
<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 = {};
|
||||
for (var i in vlist) {
|
||||
var tmp = toTrim(vlist[i]);
|
||||
var tmp_a = tmp.split(" ");
|
||||
var real_tmp = tmp_a[tmp_a.length-1];
|
||||
var kv = real_tmp.split("=");
|
||||
a[kv[0]] = kv[1].replace("'",'').replace("'",'');
|
||||
}
|
||||
|
||||
$('input[name="ip"]').val(a['MASTER_HOST']);
|
||||
$('input[name="port"]').val(a['MASTER_PORT']);
|
||||
$('input[name="user"]').val(a['MASTER_USER']);
|
||||
$('input[name="pass"]').val(a['MASTER_PASSWORD']);
|
||||
|
||||
console.log(a['MASTER_AUTO_POSITION'],typeof(a['MASTER_AUTO_POSITION']));
|
||||
if (typeof(a['MASTER_AUTO_POSITION']) != 'undefined' ){
|
||||
$('input[name="mode"]').val('1');
|
||||
}
|
||||
});
|
||||
},
|
||||
yes:function(index){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var user = $('input[name="user"]').val();
|
||||
var pass = $('input[name="pass"]').val();
|
||||
var cmd = $('textarea[name="cmd"]').val();
|
||||
var mode = $('input[name="mode"]').val();
|
||||
|
||||
var data = {ip:ip,port:port,cmd:cmd,user:user,pass:pass,mode:mode};
|
||||
myPost('add_slave_sync_user', data, function(ret_data){
|
||||
layer.close(index);
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSyncUserPage(page=1){
|
||||
var _data = {};
|
||||
_data['page'] = page;
|
||||
_data['page_size'] = 5;
|
||||
_data['tojs'] ='getSlaveSyncUserPage';
|
||||
myPost('get_slave_sync_user_list', _data, function(data){
|
||||
var layerId = null;
|
||||
var rdata = [];
|
||||
try {
|
||||
rdata = $.parseJSON(data.data);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var list = '';
|
||||
var user_list = rdata['data'];
|
||||
for (i in user_list) {
|
||||
var ip = user_list[i]['ip'];
|
||||
var port = user_list[i]['port'];
|
||||
var user = user_list[i]['user'];
|
||||
var apass = user_list[i]['pass'];
|
||||
|
||||
var cmd = '未设置';
|
||||
if (user_list[i]['cmd']!=''){
|
||||
cmd = '已设置';
|
||||
}
|
||||
|
||||
list += '<tr><td>'+ip+'</td>\
|
||||
<td>'+port+'</td>\
|
||||
<td>'+user+'</td>\
|
||||
<td>'+apass+'</td>\
|
||||
<td>'+cmd+'</td>\
|
||||
<td>\
|
||||
<a class="btlink" onclick="addSlaveSyncUser(\''+ip+'\');">修改</a> | \
|
||||
<a class="btlink" onclick="delSlaveSyncUser(\''+ip+'\');">删除</a>\
|
||||
</td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$('.get-slave-ssh-list tbody').html(list);
|
||||
$('.dataTables_paginate_4').html(rdata['page']);
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveCfg(){
|
||||
|
||||
myPost('get_slave_sync_mode', '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var mode_none = 'success';
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'danger';
|
||||
if(rdata.status){
|
||||
var mode_none = 'danger';
|
||||
if (rdata.data == 'ssh'){
|
||||
var mode_ssh = 'success';
|
||||
var mode_sync_user = 'danger';
|
||||
} else {
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步配置',
|
||||
area: ['400px','180px'],
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>当前从库同步模式</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-"+mode_none+" btn-xs slave-db-mode btn-none'>无</button>\
|
||||
<button class='btn btn-"+mode_ssh+" btn-xs slave-db-mode btn-ssh'>SSH</button>\
|
||||
<button class='btn btn-"+mode_sync_user+" btn-xs slave-db-mode btn-sync-user'>同步账户</button>\
|
||||
</p>\
|
||||
<hr />\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>配置设置</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-success btn-xs btn-slave-ssh'>SSH</button>\
|
||||
<button class='btn btn-success btn-xs btn-slave-user'>同步账户</button>\
|
||||
</p>\
|
||||
</div>",
|
||||
success:function(){
|
||||
$('.btn-slave-ssh').click(function(){
|
||||
getSlaveSSHList();
|
||||
});
|
||||
|
||||
$('.btn-slave-user').click(function(){
|
||||
getSlaveUserList();
|
||||
});
|
||||
|
||||
$('.slave-db-mode').click(function(){
|
||||
var _this = this;
|
||||
var mode = 'none';
|
||||
if ($(this).hasClass('btn-ssh')){
|
||||
mode = 'ssh';
|
||||
}
|
||||
if ($(this).hasClass('btn-sync-user')){
|
||||
mode = 'sync-user';
|
||||
}
|
||||
|
||||
myPost('set_slave_sync_mode', {mode:mode}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
$('.slave-db-mode').remove('btn-success').addClass('btn-danger');
|
||||
$(_this).removeClass('btn-danger').addClass('btn-success');
|
||||
},{icon:rdata.status?1:2},2000);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getSlaveUserList(){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
page += '<div class="table_toolbar" style="left:0px;"><span class="sync btn btn-default btn-sm" onclick="addSlaveSyncUser()" title="">添加同步账户</span></div>';
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步账户列表',
|
||||
area: '500px',
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div class='divtable mtb10'>\
|
||||
<div><table class='table table-hover get-slave-ssh-list'>\
|
||||
<thead><tr><th>IP</th><th>PORT</th><th>同步账户</th><th>同步密码</th><th>CMD</th><th>操作</th></tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table></div>\
|
||||
"+page +"\
|
||||
</div>\
|
||||
</div>",
|
||||
success:function(){
|
||||
getSlaveSyncUserPage(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSSHList(page=1){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
@@ -2004,7 +2233,7 @@ function masterOrSlaveConf(version=''){
|
||||
for(i in rdata.data){
|
||||
|
||||
var v = rdata.data[i];
|
||||
var status = "异常";
|
||||
var status = "<a class='btlink db_error'>异常</>";
|
||||
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
|
||||
status = "正常";
|
||||
}
|
||||
@@ -2046,6 +2275,26 @@ function masterOrSlaveConf(version=''){
|
||||
// <span class="sync btn btn-default btn-sm" onclick="getMasterRepSlaveList()" title="">添加</span>\
|
||||
// </div>
|
||||
$(".table_slave_status_list").html(con);
|
||||
|
||||
$('.db_error').click(function(){
|
||||
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>\
|
||||
</div>\
|
||||
</form>",
|
||||
success:function(){
|
||||
copyText(v['Error']);
|
||||
$('.class-copy-db-err').click(function(){
|
||||
copyText(v['Error']);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2092,7 +2341,6 @@ function masterOrSlaveConf(version=''){
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getMasterStatus(){
|
||||
myPost('get_master_status', '', function(rdata){
|
||||
@@ -2123,7 +2371,7 @@ function masterOrSlaveConf(version=''){
|
||||
<p class="conf_p">\
|
||||
<span class="f14 c6 mr20">Slave[从]配置</span><span class="f14 c6 mr20"></span>\
|
||||
<button class="btn '+(!rdata.slave_status ? 'btn-danger' : 'btn-success')+' btn-xs btn-slave">'+(!rdata.slave_status ? '未启动' : '已启动') +'</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveSSHList()" >[主]SSH配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveCfg()" >同步配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="initSlaveStatus()" >初始化</button>\
|
||||
</p>\
|
||||
<hr/>\
|
||||
@@ -2197,10 +2445,10 @@ function masterOrSlaveConf(version=''){
|
||||
getMasterDbList();
|
||||
}
|
||||
|
||||
if (rdata.slave_status){
|
||||
// if (rdata.slave_status){
|
||||
getAsyncMasterDbList();
|
||||
getAsyncDataList()
|
||||
}
|
||||
// }
|
||||
});
|
||||
}
|
||||
getMasterStatus();
|
||||
|
||||
@@ -44,7 +44,7 @@ class backupTools:
|
||||
"----------------------------------------------------------------------------")
|
||||
return
|
||||
|
||||
backup_path = mw.getRootDir() + '/backup/database'
|
||||
backup_path = mw.getRootDir() + '/backup/database/mysql-yum'
|
||||
if not os.path.exists(backup_path):
|
||||
mw.execShell("mkdir -p " + backup_path)
|
||||
|
||||
|
||||
@@ -67,7 +67,8 @@ binlog-ignore-db = performance_schema
|
||||
|
||||
#slave
|
||||
log-slave-updates = 1
|
||||
skip-slave-start = 1
|
||||
# Prevent replication from starting automatically with MySQL
|
||||
#skip-slave-start = 1
|
||||
#replicate-do-db
|
||||
replicate-ignore-db = information_schema
|
||||
replicate-ignore-db = performance_schema
|
||||
|
||||
@@ -69,7 +69,8 @@ binlog-ignore-db = performance_schema
|
||||
|
||||
#slave
|
||||
log-slave-updates = 1
|
||||
skip-slave-start = 1
|
||||
# Prevent replication from starting automatically with MySQL
|
||||
#skip-slave-start = 1
|
||||
#replicate-do-db
|
||||
replicate-ignore-db = information_schema
|
||||
replicate-ignore-db = performance_schema
|
||||
|
||||
@@ -8,9 +8,6 @@ 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
|
||||
|
||||
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
|
||||
user = mysql
|
||||
port = 3306
|
||||
@@ -44,6 +41,7 @@ open_files_limit = 2560
|
||||
max_allowed_packet = 128M
|
||||
|
||||
skip_name_resolve = 1
|
||||
skip-ssl
|
||||
#skip-networking
|
||||
#skip-external-locking
|
||||
#loose-skip-innodb
|
||||
@@ -70,8 +68,10 @@ binlog-ignore-db = information_schema
|
||||
binlog-ignore-db = performance_schema
|
||||
|
||||
#slave
|
||||
log-slave-updates = 1
|
||||
skip-slave-start = 1
|
||||
# 5.7 It can not be opened later
|
||||
#log-slave-updates = 1
|
||||
# Prevent replication from starting automatically with MySQL
|
||||
#skip-slave-start = 1
|
||||
#replicate-do-db
|
||||
replicate-ignore-db = information_schema
|
||||
replicate-ignore-db = performance_schema
|
||||
|
||||
@@ -68,7 +68,8 @@ binlog-ignore-db = performance_schema
|
||||
|
||||
#slave
|
||||
log_replica_updates = 1
|
||||
skip_replica_start = 1
|
||||
# Prevent replication from starting automatically with MySQL
|
||||
#skip_replica_start = 1
|
||||
#replicate-do-db
|
||||
replicate-ignore-db = information_schema
|
||||
replicate-ignore-db = performance_schema
|
||||
|
||||
@@ -40,4 +40,17 @@ CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
-- 从库配置主库的[user]
|
||||
-- drop table `slave_user`;
|
||||
CREATE TABLE IF NOT EXISTS `slave_sync_user` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`ip` TEXT,
|
||||
`port` TEXT,
|
||||
`user` TEXT,
|
||||
`pass` TEXT,
|
||||
`mode` TEXT,
|
||||
`cmd` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
.conf_p span {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
width: 135px;
|
||||
width: 115px;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
+328
-23
@@ -127,20 +127,27 @@ def contentReplace(content):
|
||||
def pSqliteDb(dbname='databases'):
|
||||
file = getServerDir() + '/mysql.db'
|
||||
name = 'mysql'
|
||||
if not os.path.exists(file):
|
||||
|
||||
import_sql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
md5_sql = mw.md5(import_sql)
|
||||
|
||||
import_sign = False
|
||||
save_md5_file = getServerDir() + '/import_sql.md5'
|
||||
if os.path.exists(save_md5_file):
|
||||
save_md5_sql = mw.readFile(save_md5_file)
|
||||
if save_md5_sql != md5_sql:
|
||||
import_sign = True
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
else:
|
||||
mw.writeFile(save_md5_file, md5_sql)
|
||||
|
||||
if not os.path.exists(file) or import_sql:
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
csql_list = csql.split(';')
|
||||
csql_list = import_sql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
conn.execute(csql_list[index], ())
|
||||
else:
|
||||
# 现有run
|
||||
# conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
# csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
|
||||
# csql_list = csql.split(';')
|
||||
# for index in range(len(csql_list)):
|
||||
# conn.execute(csql_list[index], ())
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
|
||||
conn = mw.M(dbname).dbPos(getServerDir(), name)
|
||||
return conn
|
||||
|
||||
|
||||
@@ -899,11 +906,13 @@ def importDbExternal():
|
||||
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \
|
||||
pwd + ' ' + name + ' < ' + import_sql
|
||||
|
||||
# print(mysql_cmd)
|
||||
os.system(mysql_cmd)
|
||||
rdata = mw.execShell(mysql_cmd)
|
||||
if ext != 'sql':
|
||||
os.remove(import_sql)
|
||||
|
||||
if rdata[1].lower().find('error') > -1:
|
||||
return mw.returnJson(False, rdata[1])
|
||||
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
|
||||
@@ -923,13 +932,23 @@ def importDbBackup():
|
||||
cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file
|
||||
mw.execShell(cmd)
|
||||
|
||||
local_mode = recognizeDbMode()
|
||||
if local_mode == 'gtid':
|
||||
pdb = pMysqlDb()
|
||||
pdb.execute('reset master')
|
||||
|
||||
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
|
||||
sock = getSocketFile()
|
||||
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
|
||||
' ' + name + ' < ' + file_path_sql
|
||||
|
||||
# print(mysql_cmd)
|
||||
os.system(mysql_cmd)
|
||||
# os.system(mysql_cmd)
|
||||
|
||||
rdata = mw.execShell(mysql_cmd)
|
||||
if rdata[1].lower().find('error') > -1:
|
||||
return mw.returnJson(False, rdata[1])
|
||||
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
|
||||
@@ -1260,7 +1279,7 @@ def addDb():
|
||||
dataAccess = args['dataAccess'].strip()
|
||||
ps = args['ps'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, args['name']):
|
||||
return mw.returnJson(False, '数据库名称不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1928,7 +1947,7 @@ def addMasterRepSlaveUser(version=''):
|
||||
# address = args['address'].strip()
|
||||
# dataAccess = args['dataAccess'].strip()
|
||||
|
||||
reg = "^[\w\.-]+$"
|
||||
reg = "^[\w-]+$"
|
||||
if not re.match(reg, username):
|
||||
return mw.returnJson(False, '用户名不能带有特殊符号!')
|
||||
checks = ['root', 'mysql', 'test', 'sys', 'panel_logs']
|
||||
@@ -1956,17 +1975,18 @@ def addMasterRepSlaveUser(version=''):
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql = "FLUSH PRIVILEGES;"
|
||||
pdb.execute(sql)
|
||||
else:
|
||||
sql = "GRANT REPLICATION SLAVE ON *.* TO '" + username + \
|
||||
sql = "grant replication SLAVE ON *.* TO '" + username + \
|
||||
"'@'%' identified by '" + password + "';"
|
||||
result = pdb.execute(sql)
|
||||
result = pdb.execute('FLUSH PRIVILEGES;')
|
||||
isError = isSqlError(result)
|
||||
if isError != None:
|
||||
return isError
|
||||
|
||||
sql_select = "grant select,lock tables,PROCESS on *.* to " + username + "@'%';"
|
||||
pdb.execute(sql_select)
|
||||
pdb.execute('FLUSH PRIVILEGES;')
|
||||
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
psdb.add('username,password,accept,ps,addtime',
|
||||
(username, password, '%', '', addTime))
|
||||
@@ -2103,6 +2123,123 @@ def getSlaveSSHList(version=''):
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSlaveSyncUserByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').where(
|
||||
"ip=?", (ip,)).select()
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def addSlaveSyncUser(version=''):
|
||||
import base64
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
if ip == "":
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
data = checkArgs(args, ['port', 'user', 'pass', 'mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
cmd = args['cmd']
|
||||
port = args['port']
|
||||
user = args['user']
|
||||
apass = args['pass']
|
||||
mode = args['mode']
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip').where("ip=?", (ip,)).select()
|
||||
if len(data) > 0:
|
||||
res = conn.where("ip=?", (ip,)).save(
|
||||
'port,user,pass,mode,cmd', (port, user, apass, mode, cmd))
|
||||
else:
|
||||
conn.add('ip,port,user,cmd,user,pass,mode,addtime',
|
||||
(ip, port, user, cmd, user, apass, mode, addTime))
|
||||
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def delSlaveSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
ip = args['ip']
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
conn.where("ip=?", (ip,)).delete()
|
||||
return mw.returnJson(True, '删除成功!')
|
||||
|
||||
|
||||
def getSlaveSyncUserList(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['page', 'page_size'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
page = int(args['page'])
|
||||
page_size = int(args['page_size'])
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
limit = str((page - 1) * page_size) + ',' + str(page_size)
|
||||
|
||||
field = 'id,ip,port,user,pass,cmd,addtime'
|
||||
clist = conn.field(field).limit(limit).order('id desc').select()
|
||||
count = conn.count()
|
||||
|
||||
data = {}
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['p'] = page
|
||||
_page['row'] = page_size
|
||||
_page['tojs'] = args['tojs']
|
||||
data['page'] = mw.getPage(_page)
|
||||
data['data'] = clist
|
||||
|
||||
return mw.getJson(data)
|
||||
|
||||
|
||||
def getSyncModeFile():
|
||||
return getServerDir() + "/sync.mode"
|
||||
|
||||
|
||||
def getSlaveSyncMode(version):
|
||||
sync_mode = getSyncModeFile()
|
||||
if os.path.exists(sync_mode):
|
||||
mode = mw.readFile(sync_mode).strip()
|
||||
return mw.returnJson(True, 'ok', mode)
|
||||
return mw.returnJson(False, 'fail')
|
||||
|
||||
|
||||
def setSlaveSyncMode(version):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['mode'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
mode = args['mode']
|
||||
sync_mode = getSyncModeFile()
|
||||
|
||||
if mode == 'none':
|
||||
os.remove(sync_mode)
|
||||
else:
|
||||
mw.writeFile(sync_mode, mode)
|
||||
return mw.returnJson(True, '设置成功', mode)
|
||||
|
||||
|
||||
def getSlaveSSHByIp(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['ip'])
|
||||
@@ -2160,7 +2297,7 @@ def delSlaveSSH(version=''):
|
||||
|
||||
conn = pSqliteDb('slave_id_rsa')
|
||||
conn.where("ip=?", (ip,)).delete()
|
||||
return mw.returnJson(True, 'ok')
|
||||
return mw.returnJson(True, '删除SSH成功!')
|
||||
|
||||
|
||||
def updateSlaveSSH(version=''):
|
||||
@@ -2189,6 +2326,24 @@ def getSlaveList(version=''):
|
||||
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
|
||||
@@ -2205,6 +2360,47 @@ def getSlaveSyncCmd(version=''):
|
||||
|
||||
|
||||
def initSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return initSlaveStatusSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return initSlaveStatusSyncUser(version)
|
||||
|
||||
|
||||
def initSlaveStatusSyncUser(version=''):
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
if len(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'
|
||||
|
||||
local_mode = recognizeDbMode()
|
||||
if local_mode != mode_name:
|
||||
return mw.returnJson(False, '同步模式不一致!')
|
||||
|
||||
t = db.query(u['cmd'])
|
||||
# print(t)
|
||||
db.query("start slave user='{}' password='{}';".format(
|
||||
u['user'], u['pass']))
|
||||
return mw.returnJson(True, '初始化成功!')
|
||||
|
||||
|
||||
def initSlaveStatusSSH(version=''):
|
||||
db = pMysqlDb()
|
||||
dlist = db.query('show slave status')
|
||||
if len(dlist) > 0:
|
||||
@@ -2214,7 +2410,7 @@ def initSlaveStatus(version=''):
|
||||
data = conn.field('ip,port,id_rsa').find()
|
||||
|
||||
if len(data) < 1:
|
||||
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
|
||||
return mw.returnJson(False, '需要先添加SSH配置!')
|
||||
|
||||
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
|
||||
ip = data['ip']
|
||||
@@ -2273,11 +2469,46 @@ def initSlaveStatus(version=''):
|
||||
|
||||
|
||||
def setSlaveStatus(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
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)
|
||||
|
||||
|
||||
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']
|
||||
|
||||
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, '需要手动添加主服务命令或者执行[初始化]!')
|
||||
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')
|
||||
@@ -2342,6 +2573,68 @@ def writeDbSyncStatus(data):
|
||||
|
||||
|
||||
def doFullSync(version=''):
|
||||
mode_file = getSyncModeFile()
|
||||
if not os.path.exists(mode_file):
|
||||
return mw.returnJson(False, '需要先设置同步配置')
|
||||
|
||||
mode = mw.readFile(mode_file)
|
||||
if mode == 'ssh':
|
||||
return doFullSyncSSH(version)
|
||||
if mode == 'sync-user':
|
||||
return doFullSyncUser(version)
|
||||
|
||||
|
||||
def doFullSyncUser(version=''):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
sync_db = args['db']
|
||||
|
||||
db = pMysqlDb()
|
||||
|
||||
conn = pSqliteDb('slave_sync_user')
|
||||
data = conn.field('ip,port,user,pass,mode,cmd').find()
|
||||
user = data['user']
|
||||
apass = data['pass']
|
||||
port = data['port']
|
||||
ip = data['ip']
|
||||
|
||||
bak_file = '/tmp/tmp.sql'
|
||||
|
||||
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
|
||||
dmp_option = ''
|
||||
mode = recognizeDbMode()
|
||||
if mode == 'gtid':
|
||||
dmp_option = ' --set-gtid-purged=off '
|
||||
|
||||
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 + " " + sync_db + " > " + bak_file
|
||||
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 + \
|
||||
' ' + sync_db + ' < ' + bak_file
|
||||
mw.execShell(my_import_cmd)
|
||||
|
||||
if version == '8.0':
|
||||
db.query("start slave user='{}' password='{}';".format(user, apass))
|
||||
else:
|
||||
db.query("start slave")
|
||||
|
||||
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
|
||||
os.system("rm -rf " + bak_file)
|
||||
return True
|
||||
|
||||
|
||||
def doFullSyncSSH(version=''):
|
||||
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['db'])
|
||||
@@ -2653,6 +2946,18 @@ if __name__ == "__main__":
|
||||
print(delSlaveSSH(version))
|
||||
elif func == 'update_slave_ssh':
|
||||
print(updateSlaveSSH(version))
|
||||
elif func == 'get_slave_sync_user_list':
|
||||
print(getSlaveSyncUserList(version))
|
||||
elif func == 'get_slave_sync_user_by_ip':
|
||||
print(getSlaveSyncUserByIp(version))
|
||||
elif func == 'add_slave_sync_user':
|
||||
print(addSlaveSyncUser(version))
|
||||
elif func == 'del_slave_sync_user':
|
||||
print(delSlaveSyncUser(version))
|
||||
elif func == 'get_slave_sync_mode':
|
||||
print(getSlaveSyncMode(version))
|
||||
elif func == 'set_slave_sync_mode':
|
||||
print(setSlaveSyncMode(version))
|
||||
elif func == 'init_slave_status':
|
||||
print(initSlaveStatus(version))
|
||||
elif func == 'set_slave_status':
|
||||
|
||||
+275
-27
@@ -509,19 +509,6 @@ function showHidePass(obj){
|
||||
}
|
||||
}
|
||||
|
||||
function copyPass(password){
|
||||
var clipboard = new ClipboardJS('#bt_copys');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg('复制成功',{icon:1,time:2000});
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000});
|
||||
});
|
||||
$("#bt_copys").attr('data-clipboard-text',password);
|
||||
$("#bt_copys").click();
|
||||
}
|
||||
|
||||
function checkSelect(){
|
||||
setTimeout(function () {
|
||||
var num = $('input[type="checkbox"].check:checked').length;
|
||||
@@ -744,7 +731,7 @@ function addDatabase(type){
|
||||
layer.close(index);
|
||||
dbList();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
},{icon: rdata.status ? 1 : 2}, 2000);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1558,13 +1545,9 @@ function getMasterRepSlaveUserCmd(username, db=''){
|
||||
function delMasterRepSlaveUser(username){
|
||||
myPost('del_master_rep_slave_user', {username:username}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg);
|
||||
|
||||
$('.layui-layer-close1').click();
|
||||
|
||||
setTimeout(function(){
|
||||
showMsg(rdata.msg, function(){
|
||||
getMasterRepSlaveList();
|
||||
},1000);
|
||||
},{icon: rdata.status ? 1 : 2},1000)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1834,8 +1817,23 @@ function addSlaveSSH(ip=''){
|
||||
function delSlaveSSH(ip){
|
||||
myPost('del_slave_ssh', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2});
|
||||
getSlaveSSHPage();
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSSHPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function delSlaveSyncUser(ip){
|
||||
myPost('del_slave_sync_user', {ip:ip}, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1885,6 +1883,237 @@ function getSlaveSSHPage(page=1){
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addSlaveSyncUser(ip=''){
|
||||
|
||||
myPost('get_slave_sync_user_by_ip', {ip:ip}, function(rdata){
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
|
||||
var ip = '127.0.0.1';
|
||||
var port = "22";
|
||||
var cmd = '';
|
||||
var user = 'input_sync_user';
|
||||
var pass = 'input_sync_pwd';
|
||||
var mode = '0';
|
||||
|
||||
if (rdata.data.length>0){
|
||||
ip = rdata.data[0]['ip'];
|
||||
port = rdata.data[0]['port'];
|
||||
cmd = rdata.data[0]['cmd'];
|
||||
user = rdata.data[0]['user'];
|
||||
pass = rdata.data[0]['pass'];
|
||||
mode = rdata.data[0]['mode'];
|
||||
}
|
||||
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
area: ['500px','470px'],
|
||||
title: '同步账户',
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
btn:["确认","取消"],
|
||||
content: "<form class='bt-form pd20'>\
|
||||
<div class='line'><span class='tname'>IP</span><div class='info-r'><input name='ip' class='bt-input-text mr5' type='text' style='width:330px;' value='"+ip+"'></div></div>\
|
||||
<div class='line'><span class='tname'>端口</span><div class='info-r'><input name='port' class='bt-input-text mr5' type='number' style='width:330px;' value='"+port+"'></div></div>\
|
||||
<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>\
|
||||
<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 = {};
|
||||
for (var i in vlist) {
|
||||
var tmp = toTrim(vlist[i]);
|
||||
var tmp_a = tmp.split(" ");
|
||||
var real_tmp = tmp_a[tmp_a.length-1];
|
||||
var kv = real_tmp.split("=");
|
||||
a[kv[0]] = kv[1].replace("'",'').replace("'",'');
|
||||
}
|
||||
|
||||
$('input[name="ip"]').val(a['MASTER_HOST']);
|
||||
$('input[name="port"]').val(a['MASTER_PORT']);
|
||||
$('input[name="user"]').val(a['MASTER_USER']);
|
||||
$('input[name="pass"]').val(a['MASTER_PASSWORD']);
|
||||
|
||||
console.log(a['MASTER_AUTO_POSITION'],typeof(a['MASTER_AUTO_POSITION']));
|
||||
if (typeof(a['MASTER_AUTO_POSITION']) != 'undefined' ){
|
||||
$('input[name="mode"]').val('1');
|
||||
}
|
||||
});
|
||||
},
|
||||
yes:function(index){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var user = $('input[name="user"]').val();
|
||||
var pass = $('input[name="pass"]').val();
|
||||
var cmd = $('textarea[name="cmd"]').val();
|
||||
var mode = $('input[name="mode"]').val();
|
||||
|
||||
var data = {ip:ip,port:port,cmd:cmd,user:user,pass:pass,mode:mode};
|
||||
myPost('add_slave_sync_user', data, function(ret_data){
|
||||
layer.close(index);
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
if (rdata.status){
|
||||
getSlaveSyncUserPage();
|
||||
}
|
||||
},{icon: rdata.status ? 1 : 2},600);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSyncUserPage(page=1){
|
||||
var _data = {};
|
||||
_data['page'] = page;
|
||||
_data['page_size'] = 5;
|
||||
_data['tojs'] ='getSlaveSyncUserPage';
|
||||
myPost('get_slave_sync_user_list', _data, function(data){
|
||||
var layerId = null;
|
||||
var rdata = [];
|
||||
try {
|
||||
rdata = $.parseJSON(data.data);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var list = '';
|
||||
var user_list = rdata['data'];
|
||||
for (i in user_list) {
|
||||
var ip = user_list[i]['ip'];
|
||||
var port = user_list[i]['port'];
|
||||
var user = user_list[i]['user'];
|
||||
var apass = user_list[i]['pass'];
|
||||
|
||||
var cmd = '未设置';
|
||||
if (user_list[i]['cmd']!=''){
|
||||
cmd = '已设置';
|
||||
}
|
||||
|
||||
list += '<tr><td>'+ip+'</td>\
|
||||
<td>'+port+'</td>\
|
||||
<td>'+user+'</td>\
|
||||
<td>'+apass+'</td>\
|
||||
<td>'+cmd+'</td>\
|
||||
<td>\
|
||||
<a class="btlink" onclick="addSlaveSyncUser(\''+ip+'\');">修改</a> | \
|
||||
<a class="btlink" onclick="delSlaveSyncUser(\''+ip+'\');">删除</a>\
|
||||
</td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$('.get-slave-ssh-list tbody').html(list);
|
||||
$('.dataTables_paginate_4').html(rdata['page']);
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveCfg(){
|
||||
|
||||
myPost('get_slave_sync_mode', '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var mode_none = 'success';
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'danger';
|
||||
if(rdata.status){
|
||||
var mode_none = 'danger';
|
||||
if (rdata.data == 'ssh'){
|
||||
var mode_ssh = 'success';
|
||||
var mode_sync_user = 'danger';
|
||||
} else {
|
||||
var mode_ssh = 'danger';
|
||||
var mode_sync_user = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步配置',
|
||||
area: ['400px','180px'],
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>当前从库同步模式</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-"+mode_none+" btn-xs slave-db-mode btn-none'>无</button>\
|
||||
<button class='btn btn-"+mode_ssh+" btn-xs slave-db-mode btn-ssh'>SSH</button>\
|
||||
<button class='btn btn-"+mode_sync_user+" btn-xs slave-db-mode btn-sync-user'>同步账户</button>\
|
||||
</p>\
|
||||
<hr />\
|
||||
<p class='conf_p'>\
|
||||
<span class='f14 c6 mr20'>配置设置</span>\
|
||||
<b class='f14 c6 mr20'></b>\
|
||||
<button class='btn btn-success btn-xs btn-slave-ssh'>SSH</button>\
|
||||
<button class='btn btn-success btn-xs btn-slave-user'>同步账户</button>\
|
||||
</p>\
|
||||
</div>",
|
||||
success:function(){
|
||||
$('.btn-slave-ssh').click(function(){
|
||||
getSlaveSSHList();
|
||||
});
|
||||
|
||||
$('.btn-slave-user').click(function(){
|
||||
getSlaveUserList();
|
||||
});
|
||||
|
||||
$('.slave-db-mode').click(function(){
|
||||
var _this = this;
|
||||
var mode = 'none';
|
||||
if ($(this).hasClass('btn-ssh')){
|
||||
mode = 'ssh';
|
||||
}
|
||||
if ($(this).hasClass('btn-sync-user')){
|
||||
mode = 'sync-user';
|
||||
}
|
||||
|
||||
myPost('set_slave_sync_mode', {mode:mode}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
$('.slave-db-mode').remove('btn-success').addClass('btn-danger');
|
||||
$(_this).removeClass('btn-danger').addClass('btn-success');
|
||||
},{icon:rdata.status?1:2},2000);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getSlaveUserList(){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
page += '<div class="table_toolbar" style="left:0px;"><span class="sync btn btn-default btn-sm" onclick="addSlaveSyncUser()" title="">添加同步账户</span></div>';
|
||||
|
||||
layerId = layer.open({
|
||||
type: 1,
|
||||
title: '同步账户列表',
|
||||
area: '500px',
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div class='divtable mtb10'>\
|
||||
<div><table class='table table-hover get-slave-ssh-list'>\
|
||||
<thead><tr><th>IP</th><th>PORT</th><th>同步账户</th><th>同步密码</th><th>CMD</th><th>操作</th></tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table></div>\
|
||||
"+page +"\
|
||||
</div>\
|
||||
</div>",
|
||||
success:function(){
|
||||
getSlaveSyncUserPage(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getSlaveSSHList(page=1){
|
||||
|
||||
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
|
||||
@@ -2004,7 +2233,7 @@ function masterOrSlaveConf(version=''){
|
||||
for(i in rdata.data){
|
||||
|
||||
var v = rdata.data[i];
|
||||
var status = "异常";
|
||||
var status = "<a class='btlink db_error'>异常</>";
|
||||
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
|
||||
status = "正常";
|
||||
}
|
||||
@@ -2046,6 +2275,26 @@ function masterOrSlaveConf(version=''){
|
||||
// <span class="sync btn btn-default btn-sm" onclick="getMasterRepSlaveList()" title="">添加</span>\
|
||||
// </div>
|
||||
$(".table_slave_status_list").html(con);
|
||||
|
||||
$('.db_error').click(function(){
|
||||
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>\
|
||||
</div>\
|
||||
</form>",
|
||||
success:function(){
|
||||
copyText(v['Error']);
|
||||
$('.class-copy-db-err').click(function(){
|
||||
copyText(v['Error']);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2092,7 +2341,6 @@ function masterOrSlaveConf(version=''){
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getMasterStatus(){
|
||||
myPost('get_master_status', '', function(rdata){
|
||||
@@ -2123,7 +2371,7 @@ function masterOrSlaveConf(version=''){
|
||||
<p class="conf_p">\
|
||||
<span class="f14 c6 mr20">Slave[从]配置</span><span class="f14 c6 mr20"></span>\
|
||||
<button class="btn '+(!rdata.slave_status ? 'btn-danger' : 'btn-success')+' btn-xs btn-slave">'+(!rdata.slave_status ? '未启动' : '已启动') +'</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveSSHList()" >[主]SSH配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="getSlaveCfg()" >同步配置</button>\
|
||||
<button class="btn btn-success btn-xs" onclick="initSlaveStatus()" >初始化</button>\
|
||||
</p>\
|
||||
<hr/>\
|
||||
@@ -2197,10 +2445,10 @@ function masterOrSlaveConf(version=''){
|
||||
getMasterDbList();
|
||||
}
|
||||
|
||||
if (rdata.slave_status){
|
||||
// if (rdata.slave_status){
|
||||
getAsyncMasterDbList();
|
||||
getAsyncDataList()
|
||||
}
|
||||
// }
|
||||
});
|
||||
}
|
||||
getMasterStatus();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"name": "php-apt",
|
||||
"title": "PHP[APT]",
|
||||
"coexist": true,
|
||||
"versions": ["56","70","71","72","73","74","80","81"],
|
||||
"versions": ["56","70","71","72","73","74","80","81","82"],
|
||||
"install_pre_inspection":true,
|
||||
"tip": "soft",
|
||||
"checks": "server/php-apt/VERSION",
|
||||
|
||||
@@ -89,6 +89,12 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php-apt/${type} ];then
|
||||
cd ${rootPath}/plugins/php-apt/versions && bash common.sh ${type:0:1}.${type:1:2} install redis
|
||||
cd ${rootPath}/plugins/php-apt/versions && bash common.sh ${type:0:1}.${type:1:2} install memcached
|
||||
echo "install PHP-APT[${type}] extend end"
|
||||
|
||||
if [ ! -f /usr/local/bin/composer ];then
|
||||
cd /tmp
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source
|
||||
sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
|
||||
#获取信息和版本
|
||||
# bash /www/server/mdsever-web/scripts/getos.sh
|
||||
bash ${rootPath}/scripts/getos.sh
|
||||
OSNAME=`cat ${rootPath}/data/osname.pl`
|
||||
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
|
||||
|
||||
version=8.2
|
||||
PHP_VER=82
|
||||
|
||||
|
||||
Install_php()
|
||||
{
|
||||
#------------------------ install start ------------------------------------#
|
||||
apt -y install php${version} php${version}-fpm php${version}-dev
|
||||
if [ "$?" == "0" ];then
|
||||
mkdir -p $serverPath/php-apt/${PHP_VER}
|
||||
fi
|
||||
|
||||
#------------------------ install end ------------------------------------#
|
||||
}
|
||||
|
||||
Uninstall_php()
|
||||
{
|
||||
#------------------------ uninstall start ------------------------------------#
|
||||
apt -y remove php${version} php${version}-*
|
||||
rm -rf $serverPath/php-apt/${PHP_VER}
|
||||
echo "卸载php-${version}..." > $install_tmp
|
||||
#------------------------ uninstall start ------------------------------------#
|
||||
}
|
||||
|
||||
action=${1}
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_php
|
||||
else
|
||||
Uninstall_php
|
||||
fi
|
||||
@@ -78,6 +78,12 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php-yum/${type} ];then
|
||||
cd ${rootPath}/plugins/php-yum/versions && bash common.sh ${type} install redis
|
||||
cd ${rootPath}/plugins/php-yum/versions && bash common.sh ${type} install memcached
|
||||
echo "install PHP-YUM[${type}] extend end"
|
||||
|
||||
if [ ! -f /usr/local/bin/composer ];then
|
||||
cd /tmp
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
+16
-3
@@ -32,9 +32,9 @@ if [ ! -d $curPath/versions/$2 ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ "${action}" == "install" ] && [ -d $serverPath/php/${type} ];then
|
||||
exit 0
|
||||
fi
|
||||
# if [ "${action}" == "install" ] && [ -d $serverPath/php/${type} ];then
|
||||
# exit 0
|
||||
# fi
|
||||
|
||||
if [ "${action}" == "uninstall" ];then
|
||||
|
||||
@@ -61,6 +61,7 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then
|
||||
# cd /www/server/mdserver-web/plugins/php/versions/common && bash iconv.sh install 53
|
||||
# cd /www/server/mdserver-web/plugins/php/versions/common && bash gd.sh install 56
|
||||
# cd /www/server/mdserver-web/plugins/php/versions/common && bash openssl.sh install 56
|
||||
# cd /www/server/mdserver-web/plugins/php/versions/common && bash sodium.sh install 81
|
||||
cd ${rootPath}/plugins/php/versions/common && bash gd.sh install ${type}
|
||||
cd ${rootPath}/plugins/php/versions/common && bash iconv.sh install ${type}
|
||||
cd ${rootPath}/plugins/php/versions/common && bash exif.sh install ${type}
|
||||
@@ -71,7 +72,19 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then
|
||||
cd ${rootPath}/plugins/php/versions/common && bash gettext.sh install ${type}
|
||||
cd ${rootPath}/plugins/php/versions/common && bash redis.sh install ${type}
|
||||
cd ${rootPath}/plugins/php/versions/common && bash memcached.sh install ${type}
|
||||
cd ${rootPath}/plugins/php/versions/common && bash zlib.sh install ${type}
|
||||
|
||||
if [ "${type}" -gt "72" ];then
|
||||
cd ${rootPath}/plugins/php/versions/common && bash zip.sh install ${type}
|
||||
fi
|
||||
|
||||
echo "install PHP${type} extend end"
|
||||
|
||||
if [ ! -f /usr/local/bin/composer ];then
|
||||
cd /tmp
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -13,10 +13,16 @@ 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}/icu ];then
|
||||
|
||||
if [ ! -f ${SOURCE_ROOT}/icu4c-52_2-src.tgz ];then
|
||||
wget -O ${SOURCE_ROOT}/icu4c-52_2-src.tgz https://github.com/unicode-org/icu/releases/download/release-52-2/icu4c-52_2-src.tgz
|
||||
wget --no-check-certificate -O ${SOURCE_ROOT}/icu4c-52_2-src.tgz ${HTTP_PREFIX}github.com/unicode-org/icu/releases/download/release-52-2/icu4c-52_2-src.tgz
|
||||
fi
|
||||
|
||||
if [ ! -d ${SERVER_ROOT}/icu/52.2 ];then
|
||||
|
||||
@@ -13,9 +13,15 @@ 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}/libiconv ];then
|
||||
cd $SOURCE_ROOT
|
||||
wget -O libiconv-1.15.tar.gz https://github.com/midoks/mdserver-web/releases/download/init/libiconv-1.15.tar.gz -T 5
|
||||
wget --no-check-certificate -O libiconv-1.15.tar.gz ${HTTP_PREFIX}github.com/midoks/mdserver-web/releases/download/init/libiconv-1.15.tar.gz -T 5
|
||||
tar zxvf libiconv-1.15.tar.gz
|
||||
cd libiconv-1.15
|
||||
./configure --prefix=${SERVER_ROOT}/libiconv --enable-static && make && make install
|
||||
|
||||
@@ -25,7 +25,7 @@ done
|
||||
if [ $ISFIND == "0" ];then
|
||||
cd $SOURCE_ROOT
|
||||
if [ ! -f ${SOURCE_ROOT}/libmcrypt-2.5.8.tar.gz ];then
|
||||
wget -O libmcrypt-2.5.8.tar.gz --no-check-certificate https://sourceforge.net/projects/mcrypt/files/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.gz -T 20
|
||||
wget --no-check-certificate -O libmcrypt-2.5.8.tar.gz https://sourceforge.net/projects/mcrypt/files/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.gz -T 20
|
||||
fi
|
||||
|
||||
tar -zxvf libmcrypt-2.5.8.tar.gz
|
||||
|
||||
@@ -30,7 +30,7 @@ SOURCE_ROOT=$rootPath/source/lib
|
||||
if [ ! -d ${SERVER_ROOT}/libmemcached ];then
|
||||
cd ${SOURCE_ROOT}
|
||||
if [ ! -f ${SOURCE_ROOT}/libmemcached-1.0.18.tar.gz ];then
|
||||
wget -O libmemcached-1.0.18.tar.gz https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz -T 20
|
||||
wget --no-check-certificate -O libmemcached-1.0.18.tar.gz https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz -T 20
|
||||
fi
|
||||
tar -zxf libmemcached-1.0.18.tar.gz
|
||||
cd libmemcached-1.0.18
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
|
||||
# echo $rootPath
|
||||
|
||||
SERVER_ROOT=$rootPath/lib
|
||||
SOURCE_ROOT=$rootPath/source/lib
|
||||
|
||||
|
||||
VERSION=1.0.18
|
||||
#----------------------------- libsodium start -------------------------#
|
||||
if [ ! -f /usr/local/lib/libsodium.so ];then
|
||||
cd ${SOURCE_ROOT}
|
||||
if [ ! -f ${SOURCE_ROOT}/libsodium-${VERSION}-stable.tar.gz ];then
|
||||
# wget --no-check-certificate -O libsodium-1.0.18-stable.tar.gz https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz -T 20
|
||||
wget --no-check-certificate -O libsodium-${VERSION}-stable.tar.gz https://download.libsodium.org/libsodium/releases/libsodium-${VERSION}-stable.tar.gz -T 20
|
||||
fi
|
||||
tar -zxvf libsodium-${VERSION}-stable.tar.gz
|
||||
cd libsodium-stable
|
||||
./configure && make && make check && sudo make install
|
||||
fi
|
||||
#----------------------------- libsodium end -------------------------#
|
||||
@@ -17,7 +17,7 @@ if [ ! -d ${SERVER_ROOT}/libzip ];then
|
||||
|
||||
cd $SOURCE_ROOT
|
||||
if [ ! -f ${SOURCE_ROOT}/libzip-1.3.2.tar.gz ];then
|
||||
wget -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 --no-check-certificate https://nih.at/libzip/libzip-1.3.2.tar.gz -T 20
|
||||
fi
|
||||
|
||||
tar -zxvf libzip-1.3.2.tar.gz
|
||||
|
||||
@@ -13,11 +13,17 @@ 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
|
||||
|
||||
which onig-config
|
||||
if [ "$?" != "0" ];then
|
||||
cd ${SOURCE_ROOT}
|
||||
if [ ! -f ${SOURCE_ROOT}/oniguruma-6.9.4.tar.gz ];then
|
||||
wget -O ${SOURCE_ROOT}/oniguruma-6.9.4.tar.gz https://github.com/kkos/oniguruma/archive/v6.9.4.tar.gz
|
||||
wget --no-check-certificate -O ${SOURCE_ROOT}/oniguruma-6.9.4.tar.gz ${HTTP_PREFIX}github.com/kkos/oniguruma/archive/v6.9.4.tar.gz
|
||||
fi
|
||||
cd ${SOURCE_ROOT} && tar -zxvf oniguruma-6.9.4.tar.gz
|
||||
cd ${SOURCE_ROOT}/oniguruma-6.9.4 && ./autogen.sh && ./configure --prefix=/usr && make && make install
|
||||
|
||||
@@ -16,7 +16,7 @@ SOURCE_ROOT=$rootPath/source/lib
|
||||
if [ ! -d ${SERVER_ROOT}/openssl ];then
|
||||
cd ${SOURCE_ROOT}
|
||||
if [ ! -f ${SOURCE_ROOT}/openssl-1.1.1p.tar.gz ];then
|
||||
wget -O ${SOURCE_ROOT}/openssl-1.1.1p.tar.gz https://www.openssl.org/source/openssl-1.1.1p.tar.gz
|
||||
wget --no-check-certificate -O ${SOURCE_ROOT}/openssl-1.1.1p.tar.gz https://www.openssl.org/source/openssl-1.1.1p.tar.gz
|
||||
fi
|
||||
tar -zxvf openssl-1.1.1p.tar.gz
|
||||
cd openssl-1.1.1p
|
||||
|
||||
@@ -13,10 +13,16 @@ 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}/openssl10 ];then
|
||||
cd ${SOURCE_ROOT}
|
||||
if [ ! -f ${SOURCE_ROOT}/openssl-1.0.2q.tar.gz ];then
|
||||
wget https://github.com/midoks/mdserver-web/releases/download/init/openssl-1.0.2q.tar.gz -T 20
|
||||
wget --no-check-certificate ${HTTP_PREFIX}github.com/midoks/mdserver-web/releases/download/init/openssl-1.0.2q.tar.gz -T 20
|
||||
fi
|
||||
tar -zxf openssl-1.0.2q.tar.gz
|
||||
cd openssl-1.0.2q
|
||||
|
||||
@@ -13,11 +13,17 @@ 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}/zlib ];then
|
||||
|
||||
cd $SOURCE_ROOT
|
||||
if [ ! -f ${SOURCE_ROOT}/zlib-1.2.11.tar.gz ];then
|
||||
wget -O zlib-1.2.11.tar.gz --no-check-certificate https://github.com/madler/zlib/archive/v1.2.11.tar.gz -T 20
|
||||
wget --no-check-certificate -O zlib-1.2.11.tar.gz ${HTTP_PREFIX}github.com/madler/zlib/archive/v1.2.11.tar.gz -T 20
|
||||
fi
|
||||
|
||||
tar -zxvf zlib-1.2.11.tar.gz
|
||||
|
||||
@@ -106,7 +106,8 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
|
||||
$OPTIONS \
|
||||
--enable-fastcgi \
|
||||
--enable-fpm
|
||||
make ZEND_EXTRA_LIBS='-liconv' && make install && make clean
|
||||
# ZEND_EXTRA_LIBS='-liconv'
|
||||
make && make install && make clean
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ];then
|
||||
|
||||
@@ -47,8 +47,9 @@ Install_lib()
|
||||
cd $php_lib && tar xvf ${LIBNAME}-${LIBV}.tgz
|
||||
cd ${LIBNAME}-${LIBV}
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config \
|
||||
--with-icu-dir=${serverPath}/lib/icu
|
||||
|
||||
# --with-icu-dir=${serverPath}/lib/icu
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
make clean && make && make install && make clean
|
||||
|
||||
fi
|
||||
|
||||
@@ -16,7 +16,7 @@ function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
|
||||
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
|
||||
|
||||
|
||||
version=8.2.0RC7
|
||||
version=8.2.0
|
||||
PHP_VER=82
|
||||
Install_php()
|
||||
{
|
||||
@@ -32,8 +32,7 @@ cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
|
||||
if [ ! -d $sourcePath/php/php${PHP_VER} ];then
|
||||
|
||||
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
|
||||
# wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://downloads.php.net/~pierrick/php-${version}.tar.xz
|
||||
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://downloads.php.net/~pierrick/php-${version}.tar.xz
|
||||
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://www.php.net/distributions/php-${version}.tar.xz
|
||||
fi
|
||||
|
||||
cd $sourcePath/php && tar -Jxf $sourcePath/php/php-${version}.tar.xz
|
||||
|
||||
@@ -49,6 +49,7 @@ Install_lib()
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
if [ ! -d $sourcePath/php${version}/ext ];then
|
||||
echo "cd ${rootPath}/plugins/php && /bin/bash install.sh install ${version}"
|
||||
cd ${rootPath}/plugins/php && /bin/bash install.sh install ${version}
|
||||
fi
|
||||
|
||||
@@ -57,9 +58,23 @@ Install_lib()
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
|
||||
|
||||
# It is considered as a temporary bug
|
||||
if [ "$version" == "81" ] || [ "$version" == "82" ];then
|
||||
bash ${rootPath}/scripts/getos.sh
|
||||
OSNAME=`cat ${rootPath}/data/osname.pl`
|
||||
if [ "$OSNAME" == 'centos' ];then
|
||||
FILE_softmagic=$sourcePath/php${version}/ext/${LIBNAME}/libmagic/softmagic.c
|
||||
FIND_UNDEF_STRNDUP=`cat $FILE_softmagic|grep '#undef strndup'`
|
||||
if [ "$version" -gt "74" ] && [ "$FIND_UNDEF_STRNDUP" == "" ];then
|
||||
sed -i $BAK "s/char \*strndup/#undef strndup\nchar \*strndup/g" $FILE_softmagic
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
FIND_C99=`cat Makefile|grep c99`
|
||||
if [ "$FIND_C99" == "" ];then
|
||||
sed -i $BAK 's/CFLAGS \=/CFLAGS \= -std=c99/g' Makefile
|
||||
if [ "$version" -gt "74" ] && [ "$FIND_C99" == "" ];then
|
||||
sed -i $BAK 's/CFLAGS \=/CFLAGS \= -std=gnu99/g' Makefile
|
||||
fi
|
||||
|
||||
make clean && make && make install && make clean
|
||||
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
appPath=$(dirname "$curPath")
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
|
||||
LIBNAME=gmp
|
||||
LIBV=0
|
||||
|
||||
if [ "$version" == "53" ];then
|
||||
echo "i wont support it"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
LIB_PATH_NAME=lib/php
|
||||
if [ -d $serverPath/php/${version}/lib64 ];then
|
||||
LIB_PATH_NAME=lib64
|
||||
fi
|
||||
|
||||
NON_ZTS_FILENAME=`ls $serverPath/php/${version}/${LIB_PATH_NAME}/extensions | grep no-debug-non-zts`
|
||||
extFile=$serverPath/php/${version}/${LIB_PATH_NAME}/extensions/${NON_ZTS_FILENAME}/${LIBNAME}.so
|
||||
|
||||
sysName=`uname`
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
BAK='_bak'
|
||||
else
|
||||
BAK=''
|
||||
fi
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php-$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
if [ ! -d $sourcePath/php${version}/ext ];then
|
||||
cd ${rootPath}/plugins/php && /bin/bash install.sh install ${version}
|
||||
fi
|
||||
|
||||
cd $sourcePath/php${version}/ext/${LIBNAME}
|
||||
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
|
||||
# FIND_C99=`cat Makefile|grep c99`
|
||||
# if [ "$FIND_C99" == "" ];then
|
||||
# sed -i $BAK 's/CFLAGS \=/CFLAGS \= -std=c99/g' Makefile
|
||||
# fi
|
||||
|
||||
make clean && make && make install && make clean
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "" >> $serverPath/php/$version/etc/php.ini
|
||||
echo "[${LIBNAME}]" >> $serverPath/php/$version/etc/php.ini
|
||||
echo "extension=${LIBNAME}.so" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
bash ${rootPath}/plugins/php/versions/lib.sh $version restart
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php-$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php-$version 未安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
echo $serverPath/php/$version/etc/php.ini
|
||||
sed -i $BAK "/${LIBNAME}.so/d" $serverPath/php/$version/etc/php.ini
|
||||
sed -i $BAK "/${LIBNAME}/d" $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
bash ${rootPath}/plugins/php/versions/lib.sh $version restart
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -20,12 +20,10 @@ LIBV=4.1.2
|
||||
if [ "$version" -lt "73" ];then
|
||||
echo "not support!"
|
||||
exit 1
|
||||
else
|
||||
fi
|
||||
|
||||
if [ "$version" -gt "74" ];then
|
||||
LIBV=5.1.2
|
||||
else
|
||||
echo "not support!"
|
||||
fi
|
||||
|
||||
LIB_PATH_NAME=lib/php
|
||||
|
||||
@@ -21,6 +21,8 @@ if [ "$version" == "52" ];then
|
||||
LIBV=2.2.7
|
||||
elif [ "$version" -lt "70" ];then
|
||||
LIBV=4.2.0
|
||||
elif [ "$version" -gt "74" ];then
|
||||
LIBV=5.3.5
|
||||
else
|
||||
echo 'ok'
|
||||
fi
|
||||
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
|
||||
sysName=`uname`
|
||||
LIBNAME=sodium
|
||||
LIBV=2.0.23
|
||||
|
||||
|
||||
LIB_PATH_NAME=lib/php
|
||||
if [ -d $serverPath/php/${version}/lib64 ];then
|
||||
LIB_PATH_NAME=lib64
|
||||
fi
|
||||
|
||||
NON_ZTS_FILENAME=`ls $serverPath/php/${version}/${LIB_PATH_NAME}/extensions | grep no-debug-non-zts`
|
||||
extFile=$serverPath/php/${version}/${LIB_PATH_NAME}/extensions/${NON_ZTS_FILENAME}/${LIBNAME}.so
|
||||
|
||||
if [ "$sysName" == "Darwin" ];then
|
||||
BAK='_bak'
|
||||
else
|
||||
BAK=''
|
||||
fi
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php-$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
cd ${rootPath}/plugins/php/lib && bash libsodium.sh
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
php_lib=$sourcePath/php_lib
|
||||
mkdir -p $php_lib
|
||||
if [ ! -d $php_lib/${LIBNAME}-${LIBV} ];then
|
||||
wget -O $php_lib/${LIBNAME}-${LIBV}.tgz http://pecl.php.net/get/lib${LIBNAME}-${LIBV}.tgz
|
||||
cd $php_lib && tar xvf ${LIBNAME}-${LIBV}.tgz
|
||||
fi
|
||||
cd $php_lib/lib${LIBNAME}-${LIBV}
|
||||
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config --with-sodium=$serverPath/lib/libsodium
|
||||
make clean && make && make install && make clean
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return;
|
||||
fi
|
||||
|
||||
echo "" >> $serverPath/php/$version/etc/php.ini
|
||||
echo "[${LIBNAME}]" >> $serverPath/php/$version/etc/php.ini
|
||||
echo "extension=${LIBNAME}.so" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
bash ${rootPath}/plugins/php/versions/lib.sh $version restart
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php-$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php-$version 未安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
echo $serverPath/php/$version/etc/php.ini
|
||||
sed -i $BAK "/${LIBNAME}.so/d" $serverPath/php/$version/etc/php.ini
|
||||
sed -i $BAK "/\[${LIBNAME}\]/d" $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -rf $extFile
|
||||
bash ${rootPath}/plugins/php/versions/lib.sh $version restart
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -31,11 +31,6 @@ if [ "$version" -eq "72" ] || [ "$version" -eq "73" ];then
|
||||
LIBV=3.2.5
|
||||
fi
|
||||
|
||||
if [ "$version" -eq "82" ];then
|
||||
echo "not need"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
LIB_PATH_NAME=lib/php
|
||||
if [ -d $serverPath/php/${version}/lib64 ];then
|
||||
|
||||
@@ -21,12 +21,6 @@ if [ "$version" -lt "70" ];then
|
||||
LIBV=1.2.5
|
||||
fi
|
||||
|
||||
if [ "$version" -eq "82" ];then
|
||||
echo "wait php82 release"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
LIB_PATH_NAME=lib/php
|
||||
if [ -d $serverPath/php/${version}/lib64 ];then
|
||||
LIB_PATH_NAME=lib64
|
||||
|
||||
@@ -62,6 +62,40 @@
|
||||
"shell": "ioncube.sh",
|
||||
"check": "ioncube.so"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"versions": [
|
||||
"70",
|
||||
"71",
|
||||
"72",
|
||||
"73",
|
||||
"74",
|
||||
"80",
|
||||
"81",
|
||||
"82"
|
||||
],
|
||||
"type": "加密库",
|
||||
"msg": "Sodium加密库的包装器",
|
||||
"shell": "sodium.sh",
|
||||
"check": "sodium.so"
|
||||
},
|
||||
{
|
||||
"name": "gmp",
|
||||
"versions": [
|
||||
"70",
|
||||
"71",
|
||||
"72",
|
||||
"73",
|
||||
"74",
|
||||
"80",
|
||||
"81",
|
||||
"82"
|
||||
],
|
||||
"type": "运算库",
|
||||
"msg": "一个开源的数学运算库",
|
||||
"shell": "gmp.sh",
|
||||
"check": "gmp.so"
|
||||
},
|
||||
{
|
||||
"name": "opcache",
|
||||
"versions": [
|
||||
@@ -520,8 +554,7 @@
|
||||
"73",
|
||||
"74",
|
||||
"80",
|
||||
"81",
|
||||
"82"
|
||||
"81"
|
||||
],
|
||||
"type": "框架",
|
||||
"msg": "Yaf是一个C语言编写的PHP框架",
|
||||
@@ -541,8 +574,7 @@
|
||||
"73",
|
||||
"74",
|
||||
"80",
|
||||
"81",
|
||||
"82"
|
||||
"81"
|
||||
],
|
||||
"type": "框架",
|
||||
"msg": "Yar是一个RPC框架",
|
||||
|
||||
@@ -1,3 +1,30 @@
|
||||
<style type="text/css">
|
||||
.db_list{
|
||||
padding: 0px 0 10px 0;
|
||||
font-size: 13px;
|
||||
line-height: 35px;
|
||||
height: 45px;
|
||||
}
|
||||
.db_list a{
|
||||
margin-right: 15px;
|
||||
color: #555;
|
||||
font-weight: 600;
|
||||
}
|
||||
.db_list span:nth-child(1){
|
||||
display: block;
|
||||
float: left;
|
||||
padding-left: 15px;
|
||||
background: #ececec;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#db_tools button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
#db_tools button:last-child{
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="bt-form">
|
||||
<div class='plugin_version'></div>
|
||||
<div class="bt-w-main">
|
||||
|
||||
@@ -70,12 +70,10 @@ def getArgs():
|
||||
|
||||
|
||||
def getBackupDir():
|
||||
bk_path = mw.getBackupDir() + "/pg"
|
||||
bk_path = mw.getBackupDir() + "/database/postgresql"
|
||||
if not os.path.isdir(bk_path):
|
||||
mw.execShell("mkdir -p {}/upload".format(bk_path))
|
||||
|
||||
bk_path_upload = bk_path + "/upload"
|
||||
return bk_path_upload
|
||||
mw.execShell("mkdir -p {}".format(bk_path))
|
||||
return bk_path
|
||||
|
||||
|
||||
def checkArgs(data, ck=[]):
|
||||
@@ -674,7 +672,7 @@ def setUserPwd(version=''):
|
||||
|
||||
|
||||
def getDbBackupListFunc(dbname=''):
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
blist = os.listdir(bkDir)
|
||||
r = []
|
||||
|
||||
@@ -708,11 +706,11 @@ def importDbBackup():
|
||||
file = args['file']
|
||||
name = args['name']
|
||||
|
||||
file_path = mw.getRootDir() + '/backup/database/' + file
|
||||
file_path_sql = mw.getRootDir() + '/backup/database/' + file.replace('.gz', '')
|
||||
file_path = getBackupDir() + '/' + file
|
||||
file_path_sql = getBackupDir() + '/' + file.replace('.gz', '')
|
||||
|
||||
if not os.path.exists(file_path_sql):
|
||||
cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file
|
||||
cmd = 'cd ' + getBackupDir() + ' && gzip -d ' + file
|
||||
mw.execShell(cmd)
|
||||
|
||||
pwd = pSqliteDb('config').where('id=?', (1,)).getField('pg_root')
|
||||
@@ -731,8 +729,7 @@ def deleteDbBackup():
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
|
||||
bkDir = getBackupDir()
|
||||
os.remove(bkDir + '/' + args['filename'])
|
||||
return mw.returnJson(True, 'ok')
|
||||
|
||||
@@ -744,7 +741,7 @@ def getDbBackupList():
|
||||
return data[1]
|
||||
|
||||
r = getDbBackupListFunc(args['name'])
|
||||
bkDir = mw.getRootDir() + '/backup/database'
|
||||
bkDir = getBackupDir()
|
||||
rr = []
|
||||
for x in range(0, len(r)):
|
||||
p = bkDir + '/' + r[x]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"hook":["database"],
|
||||
"title":"PostgreSQL",
|
||||
"tip":"soft",
|
||||
"name":"postgresql",
|
||||
|
||||
@@ -259,19 +259,6 @@ function showHidePass(obj){
|
||||
}
|
||||
}
|
||||
|
||||
function copyPass(password){
|
||||
var clipboard = new ClipboardJS('#bt_copys');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg('复制成功',{icon:1,time:2000});
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000});
|
||||
});
|
||||
$("#bt_copys").attr('data-clipboard-text',password);
|
||||
$("#bt_copys").click();
|
||||
}
|
||||
|
||||
function checkSelect(){
|
||||
setTimeout(function () {
|
||||
var num = $('input[type="checkbox"].check:checked').length;
|
||||
|
||||
@@ -17,6 +17,7 @@ AntiWarez yes
|
||||
Bind 0.0.0.0,21
|
||||
Umask 133:022
|
||||
MinUID 100
|
||||
PassivePortRange 39000 40000
|
||||
AllowUserFXP no
|
||||
AllowAnonymousFXP no
|
||||
ProhibitDotFilesWrite no
|
||||
|
||||
@@ -81,6 +81,22 @@ def contentReplace(content):
|
||||
return content
|
||||
|
||||
|
||||
def ftp_release_port(port):
|
||||
from collections import namedtuple
|
||||
try:
|
||||
import firewall_api
|
||||
firewall_api.firewall_api().addAcceptPortArgs(port, 'pure-ftpd', 'port')
|
||||
return port
|
||||
except Exception as e:
|
||||
return "Release failed {}".format(e)
|
||||
|
||||
|
||||
def openFtpPort():
|
||||
for i in ["21", "39000:40000"]:
|
||||
ftp_release_port(i)
|
||||
return True
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
file_tpl = getInitDTpl()
|
||||
@@ -89,6 +105,7 @@ def initDreplace():
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
if not os.path.exists(initD_path):
|
||||
os.mkdir(initD_path)
|
||||
openFtpPort()
|
||||
file_bin = initD_path + '/' + getPluginName()
|
||||
|
||||
# initd replace
|
||||
|
||||
@@ -53,8 +53,8 @@ Install_pureftp()
|
||||
|
||||
# curl -sSLo pure-ftpd-1.0.49.tar.gz https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.49.tar.gz
|
||||
if [ ! -f $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz ];then
|
||||
wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
# curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
# wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
|
||||
fi
|
||||
|
||||
#检测文件是否损坏.
|
||||
|
||||
@@ -108,6 +108,10 @@ Install_App()
|
||||
echo '安装完成' > $install_tmp
|
||||
|
||||
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py start
|
||||
|
||||
|
||||
# delete install data
|
||||
rm -rf $serverPath/source/webstats
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
setuptools>=33.1.1
|
||||
Werkzeug>=1.0.1
|
||||
wheel==0.33.6
|
||||
wheel==0.37.1
|
||||
gunicorn==20.1.0
|
||||
requests==2.27.1
|
||||
urllib3>=1.21.1
|
||||
@@ -27,3 +27,4 @@ Jinja2>=2.11.2
|
||||
flask-caching>=1.10.1
|
||||
bcrypt==3.1.3
|
||||
PyMySQL==1.0.2
|
||||
whitenoise==5.3.0
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
location / {
|
||||
set $replace 'tmplate_replace';
|
||||
set $spider_request '0';
|
||||
|
||||
if ($http_user_agent ~* '(baiduspider|360sipder|Sogou Orion spider|Sogou News Spider|Sogou blog|Sogou spider2|Sogou inst spider|Sogou web spider|Sogou spider|trendiction|Yahoo|semrush|Toutiao|Google|qihoobot|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|MSNBot|ia_archiver|Tomato Bot)') {
|
||||
set $spider_request '1';
|
||||
}
|
||||
|
||||
if ($spider_request = '0' ) {
|
||||
set $replace 'tmplate_replace';
|
||||
}
|
||||
|
||||
sub_filter 'tmplate_replace' $replace;
|
||||
sub_filter_once on;
|
||||
sub_filter_types *;
|
||||
}
|
||||
+21
-7
@@ -27,6 +27,8 @@ from flask import render_template_string, abort
|
||||
from flask_caching import Cache
|
||||
from flask_session import Session
|
||||
|
||||
from whitenoise import WhiteNoise
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
|
||||
import db
|
||||
@@ -36,6 +38,9 @@ import config_api
|
||||
app = Flask(__name__, template_folder='templates/default')
|
||||
app.config.version = config_api.config_api().getVersion()
|
||||
|
||||
app.wsgi_app = WhiteNoise(
|
||||
app.wsgi_app, root="route/static/", prefix="static/", max_age=604800)
|
||||
|
||||
cache = Cache(config={'CACHE_TYPE': 'simple'})
|
||||
cache.init_app(app, config={'CACHE_TYPE': 'simple'})
|
||||
|
||||
@@ -186,11 +191,11 @@ def isLogined():
|
||||
|
||||
return True
|
||||
|
||||
if os.path.exists('data/api_login.txt'):
|
||||
content = mw.readFile('data/api_login.txt')
|
||||
session['login'] = True
|
||||
session['username'] = content
|
||||
os.remove('data/api_login.txt')
|
||||
# if os.path.exists('data/api_login.txt'):
|
||||
# content = mw.readFile('data/api_login.txt')
|
||||
# session['login'] = True
|
||||
# session['username'] = content
|
||||
# os.remove('data/api_login.txt')
|
||||
return False
|
||||
|
||||
|
||||
@@ -218,9 +223,18 @@ def publicObject(toObject, func, action=None, get=None):
|
||||
# print(os)
|
||||
# return mw.getLocalIp()
|
||||
|
||||
# 仅针对webhook插件
|
||||
@app.route("/.well-known/acme-challenge/<val>")
|
||||
def wellknow(val=None):
|
||||
# 申请面板ssl使用
|
||||
f = mw.getRunDir() + "/tmp/.well-known/acme-challenge/" + val
|
||||
if os.path.exists(f):
|
||||
return mw.readFile(f)
|
||||
return ''
|
||||
|
||||
|
||||
@app.route("/hook")
|
||||
def webhook():
|
||||
# 仅针对webhook插件
|
||||
input_args = {
|
||||
'access_key': request.args.get('access_key', '').strip(),
|
||||
'params': request.args.get('params', '').strip()
|
||||
@@ -336,7 +350,7 @@ def doLogin():
|
||||
# session['overdue'] = int(time.time()) + 7
|
||||
|
||||
# fix 跳转时,数据消失,可能是跨域问题
|
||||
mw.writeFile('data/api_login.txt', userInfo['username'])
|
||||
# mw.writeFile('data/api_login.txt', userInfo['username'])
|
||||
return mw.returnJson(True, '登录成功,正在跳转...')
|
||||
|
||||
|
||||
|
||||
+44
-21
@@ -364,11 +364,11 @@ function getPanelSSL(){
|
||||
var cert_data = '';
|
||||
if (cert['info']){
|
||||
cert_data = "<div class='ssl_state_info'><div class='state_info_flex'>\
|
||||
<div class='state_item'><span>证书品牌:</span><span class='ellipsis_text'>"+cert['info']['issuer']+"</span></div>\
|
||||
<div class='state_item'><span>到期时间:</span><span class='btlink'>剩余"+cert['info']['endtime']+"天到期</span></div>\
|
||||
<div class='state_item'><span>证书品牌:</span><span class='ellipsis_text ssl_issue'>"+cert['info']['issuer']+"</span></div>\
|
||||
<div class='state_item'><span>到期时间:</span><span class='btlink ssl_endtime'>剩余"+cert['info']['endtime']+"天到期</span></div>\
|
||||
</div>\
|
||||
<div class='state_info_flex'>\
|
||||
<div class='state_item'><span>认证域名:</span><span class='ellipsis_text'>"+cert['info']['subject']+"</span></div>\
|
||||
<div class='state_item'><span>认证域名:</span><span class='ellipsis_text ssl_subject'>"+cert['info']['subject']+"</span></div>\
|
||||
</div></div>";
|
||||
}
|
||||
|
||||
@@ -384,7 +384,8 @@ function getPanelSSL(){
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="ssl-btn pull-left mtb15" style="width:100%">\
|
||||
<button class="btn btn-success btn-sm" onclick="savePanelSSL()">保存</button>\
|
||||
<button class="btn btn-success btn-sm save-panel-ssl">保存</button>\
|
||||
<button class="btn btn-success btn-sm apply-lets-ssl">申请Lets证书</button>\
|
||||
</div>\
|
||||
</div>\
|
||||
<ul class="help-info-text c7 pull-left">\
|
||||
@@ -399,28 +400,50 @@ function getPanelSSL(){
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content:certBody
|
||||
content:certBody,
|
||||
success:function(layero, layer_id){
|
||||
|
||||
//保存SSL
|
||||
$('.save-panel-ssl').click(function(){
|
||||
var data = {
|
||||
privateKey:$("#key").val(),
|
||||
certPem:$("#csr").val()
|
||||
}
|
||||
var loadT = layer.msg('正在安装并设置SSL组件,这需要几分钟时间...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/config/save_panel_ssl',data,function(rdata){
|
||||
layer.close(loadT);
|
||||
if(rdata.status){
|
||||
layer.closeAll();
|
||||
}
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
},'json');
|
||||
});
|
||||
|
||||
//申请Lets证书
|
||||
$('.apply-lets-ssl').click(function(){
|
||||
showSpeedWindow('正在申请...', 'site.get_let_logs', function(layers,index){
|
||||
$.post('/config/apply_panel_let_ssl',{},function(rdata){
|
||||
layer.close(loadT);
|
||||
if(rdata.status){
|
||||
layer.close(index);
|
||||
var tdata = rdata['data'];
|
||||
$('.ssl_issue').text(tdata['info']['issuer']);
|
||||
$('.ssl_endtime').text("剩余"+tdata['info']['endtime']+"天到期");
|
||||
$('.ssl_subject').text(tdata['info']['subject']);
|
||||
|
||||
$('textarea[name="key"]').val(tdata['info']['privateKey']);
|
||||
$('textarea[name="csr"]').val(tdata['info']['certPem']);
|
||||
}
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
},'json');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function savePanelSSL(){
|
||||
var data = {
|
||||
privateKey:$("#key").val(),
|
||||
certPem:$("#csr").val()
|
||||
}
|
||||
var loadT = layer.msg('正在安装并设置SSL组件,这需要几分钟时间...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/config/save_panel_ssl',data,function(rdata){
|
||||
layer.close(loadT);
|
||||
if(rdata.status){
|
||||
layer.closeAll();
|
||||
}
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function removeTempAccess(id){
|
||||
$.post('/config/remove_temp_login', {id:id}, function(rdata){
|
||||
showMsg(rdata.msg, function(){
|
||||
|
||||
+263
-196
@@ -1,13 +1,3 @@
|
||||
function isURL(str_url){
|
||||
var strRegex = '^(https|http|ftp|rtsp|mms)?://.+';
|
||||
var re=new RegExp(strRegex);
|
||||
if (re.test(str_url)){
|
||||
return (true);
|
||||
}else{
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
var num = 0;
|
||||
//查看任务日志
|
||||
function getLogs(id){
|
||||
@@ -40,6 +30,16 @@ function getLogs(id){
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function getBackupName(hook_data, name){
|
||||
for (var i = 0; i < hook_data.length; i++) {
|
||||
if (hook_data[i]['name'] == 'backup_ftp'){
|
||||
return hook_data[i]['title'];
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function getCronData(page){
|
||||
var load = layer.msg(lan.public.the,{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post("/crontab/list?p="+page,'', function(rdata){
|
||||
@@ -61,10 +61,10 @@ function getCronData(page){
|
||||
}
|
||||
|
||||
var cron_backupto = '-';
|
||||
if (rdata.data[i]['stype'] == 'site' || rdata.data[i]['stype']=='database' ){
|
||||
if (rdata.data[i]['stype'] == 'site' || rdata.data[i]['stype']=='logs' || rdata.data[i]['stype']=='path' || rdata.data[i]['stype']=='database' || rdata.data[i]['stype'].indexOf('database_')>-1 ){
|
||||
cron_backupto = '本地磁盘';
|
||||
if (rdata.data[i]['backup_to'] != 'localhost'){
|
||||
cron_backupto = rdata.data[i]['backup_to'];
|
||||
cron_backupto = getBackupName(rdata['backup_hook'],rdata.data[i]['backup_to']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,19 +228,21 @@ function planAdd(){
|
||||
|
||||
var sType = $(".planjs").find("b").attr("val");
|
||||
var sBody = encodeURIComponent($("#implement textarea[name='sBody']").val());
|
||||
|
||||
if(sType == 'toFile'){
|
||||
if($("#viewfile").val() == ''){
|
||||
layer.msg('请选择脚本文件!',{icon:2});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (sType == 'toShell'){
|
||||
if(sBody == ''){
|
||||
$("#implement textarea[name='sBody']").focus();
|
||||
layer.msg('脚本代码不能为空!',{icon:2});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(sType == 'toFile'){
|
||||
if($("#viewfile").val() == ''){
|
||||
layer.msg('请选择脚本文件!',{icon:2});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var urladdress = $("#urladdress").val();
|
||||
if(sType == 'toUrl'){
|
||||
@@ -295,7 +297,6 @@ function planAdd(){
|
||||
$("#set-Config input[name='sName']").val(sName);
|
||||
layer.msg('正在添加,请稍候...!',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
var data = $("#set-Config").serialize() + '&sBody='+sBody + '&urladdress=' + urladdress;
|
||||
// console.log(data);
|
||||
$.post('/crontab/add',data,function(rdata){
|
||||
if(!rdata.status) {
|
||||
layer.msg(rdata.msg,{icon:2, time:2000});
|
||||
@@ -413,10 +414,18 @@ function initDropdownMenu(){
|
||||
toBackup('sites');
|
||||
$(".controls").html('备份网站');
|
||||
break;
|
||||
case 'database_mariadb':
|
||||
case 'database_postgresql':
|
||||
case 'database_mysql-apt':
|
||||
case 'database_mysql-yum':
|
||||
case 'database':
|
||||
toBackup('databases');
|
||||
toBackup(type);
|
||||
$(".controls").html('备份数据库');
|
||||
break;
|
||||
case 'path':
|
||||
toBackup('path');
|
||||
$(".controls").html('备份目录');
|
||||
break;
|
||||
case 'logs':
|
||||
toBackup('logs');
|
||||
$(".controls").html('切割网站');
|
||||
@@ -438,49 +447,72 @@ function toBackup(type){
|
||||
sMsg = '备份网站';
|
||||
sType = "sites";
|
||||
break;
|
||||
case 'databases':
|
||||
case 'database_mariadb':
|
||||
case 'database_postgresql':
|
||||
case 'database_mysql-apt':
|
||||
case 'database_mysql-yum':
|
||||
case 'database':
|
||||
sMsg = '备份数据库';
|
||||
sType = "databases";
|
||||
suffix = type.replace('database','')
|
||||
if (suffix != ''){
|
||||
suffix = suffix.replace('_','')
|
||||
sMsg = '备份数据库['+suffix+']';
|
||||
}
|
||||
sType = type;
|
||||
break;
|
||||
case 'logs':
|
||||
sMsg = '切割日志';
|
||||
sType = "sites";
|
||||
sType = "logs";
|
||||
break;
|
||||
case 'path':
|
||||
sMsg = '备份目录';
|
||||
sType = "path";
|
||||
break;
|
||||
}
|
||||
var data='type='+sType
|
||||
var data = 'type='+sType;
|
||||
|
||||
$.post('/crontab/get_data_list',data,function(rdata){
|
||||
$(".planname input[name='name']").attr('readonly','true').css({"background-color":"#f6f6f6","color":"#666"});
|
||||
var sOpt = "";
|
||||
if(rdata.data.length == 0){
|
||||
layer.msg(lan.public.list_empty,{icon:2})
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
for(var i=0;i<rdata.data.length;i++){
|
||||
if(i==0){
|
||||
$(".planname input[name='name']").val(sMsg+'['+rdata.data[i].name+']');
|
||||
}
|
||||
sOpt += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="'+rdata.data[i].name+'">'+rdata.data[i].name+'['+rdata.data[i].ps+']</a></li>';
|
||||
}
|
||||
|
||||
|
||||
if (sType != 'path'){
|
||||
sOpt = '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="backupAll">所有</a></li>' + sOpt;
|
||||
}
|
||||
|
||||
var orderOpt = '';
|
||||
for (var i=0;i<rdata.orderOpt.length;i++){
|
||||
orderOpt += '<li><a role="menuitem" tabindex="-1" href="javascript:;" value="'+rdata.orderOpt[i].name+'">'+rdata.orderOpt[i].title+'</a></li>'
|
||||
}
|
||||
|
||||
|
||||
var changeDir = '';
|
||||
if (sType == 'path'){
|
||||
changeDir = '<span class="glyphicon glyphicon-folder-open cursor mr20 changePathDir" style="float:left;line-height: 30px;"></span>';
|
||||
}
|
||||
|
||||
var sBody = '<div class="dropdown pull-left mr20">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="backdata" data-toggle="dropdown" style="width:auto">\
|
||||
var sBody = '<div class="dropdown pull-left mr20 check">\
|
||||
<button class="btn btn-default dropdown-toggle sname" type="button" id="backdata" data-toggle="dropdown" style="width:auto">\
|
||||
<b id="sName" val="'+rdata.data[0].name+'">'+rdata.data[0].name+'['+rdata.data[0].ps+']</b> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="backdata">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="backupAll">所有</a></li>\
|
||||
'+sOpt+'\
|
||||
</ul>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="backdata">'+sOpt+'</ul>\
|
||||
</div>\
|
||||
'+ changeDir +'\
|
||||
<div class="textname pull-left mr20">备份到</div>\
|
||||
<div class="dropdown planBackupTo pull-left mr20">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto;">\
|
||||
<b val="localhost">服务器磁盘</b> <span class="caret"></span>\
|
||||
<b val="localhost">服务器磁盘</b><span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">\
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="localhost">服务器磁盘</a></li>\
|
||||
@@ -493,12 +525,22 @@ function toBackup(type){
|
||||
</div>';
|
||||
$("#implement").html(sBody);
|
||||
getselectname();
|
||||
|
||||
$('.changePathDir').click(function(){
|
||||
changePathCallback($('#sName').val(),function(select_dir){
|
||||
$(".planname input[name='name']").val('备份目录['+select_dir+']');
|
||||
$('#implement .sname b').attr('val',select_dir).text(select_dir);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$(".dropdown ul li a").click(function(){
|
||||
var sName = $("#sName").attr("val");
|
||||
if(!sName) return;
|
||||
$(".planname input[name='name']").val(sMsg+'['+sName+']');
|
||||
});
|
||||
},'json');
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -531,11 +573,17 @@ function editTaskInfo(id){
|
||||
sNameArray:[],
|
||||
backupsArray:[],
|
||||
create:function(callback){
|
||||
for(var i = 0; i <obj['sTypeArray'].length; i++){
|
||||
if(obj.from['stype'] == obj['sTypeArray'][i][0]){
|
||||
sTypeName = obj['sTypeArray'][i][1];
|
||||
if (obj.from['stype'].indexOf('database_')>-1){
|
||||
name = obj.from['stype'].replace('database_','');
|
||||
sTypeName = '备份数据库['+name+']';
|
||||
sTypeDom += '<li><a role="menuitem" href="javascript:;" value="'+ obj.from['stype'] +'">'+ sTypeName +'</a></li>';
|
||||
} else {
|
||||
for(var i = 0; i <obj['sTypeArray'].length; i++){
|
||||
if(obj.from['stype'] == obj['sTypeArray'][i][0]){
|
||||
sTypeName = obj['sTypeArray'][i][1];
|
||||
}
|
||||
sTypeDom += '<li><a role="menuitem" href="javascript:;" value="'+ obj['sTypeArray'][i][0] +'">'+ obj['sTypeArray'][i][1] +'</a></li>';
|
||||
}
|
||||
sTypeDom += '<li><a role="menuitem" href="javascript:;" value="'+ obj['sTypeArray'][i][0] +'">'+ obj['sTypeArray'][i][1] +'</a></li>';
|
||||
}
|
||||
|
||||
for(var i = 0; i <obj['cycleArray'].length; i++){
|
||||
@@ -548,8 +596,8 @@ function editTaskInfo(id){
|
||||
weekDom += '<li><a role="menuitem" href="javascript:;" value="'+ obj['weekArray'][i][0] +'">'+ obj['weekArray'][i][1] +'</a></li>';
|
||||
}
|
||||
|
||||
if(obj.from.stype == 'site' || obj.from.stype == 'database' || obj.from.stype == 'path' || obj.from.stype == 'logs'){
|
||||
$.post('/crontab/get_data_list',{type:obj.from.stype == 'databases'?'database':'sites'},function(rdata){
|
||||
if(obj.from.stype == 'site' || obj.from.stype == 'database' || obj.from.stype == 'path' || obj.from.stype == 'logs' || obj.from['stype'].indexOf('database_')>-1){
|
||||
$.post('/crontab/get_data_list',{type:obj.from.stype},function(rdata){
|
||||
// console.log(rdata);
|
||||
obj.sNameArray = rdata.data;
|
||||
obj.sNameArray.unshift({name:'ALL',ps:'所有'});
|
||||
@@ -575,10 +623,16 @@ function editTaskInfo(id){
|
||||
}
|
||||
};
|
||||
obj.create(function(){
|
||||
|
||||
var changeDir = '';
|
||||
if (obj.from.stype == 'path'){
|
||||
changeDir = '<span class="glyphicon glyphicon-folder-open cursor mr20 changePathDir" style="float:left;line-height: 30px;"></span>';
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type:1,
|
||||
title:'编辑计划任务-['+rdata.name+']',
|
||||
area: ['850px','450px'],
|
||||
area: ['850px','440px'],
|
||||
skin:'layer-create-content',
|
||||
shadeClose:false,
|
||||
closeBtn:1,
|
||||
@@ -622,7 +676,7 @@ function editTaskInfo(id){
|
||||
<div class="clearfix plan ptb10 site_list" style="display:none">\
|
||||
<span class="typename controls c4 pull-left f14 text-right mr20">'+ sTypeName +'</span>\
|
||||
<div style="line-height:34px"><div class="dropdown pull-left mr20 sName_btn" style="display:'+ (obj.from.sType != "path"?'block;':'none') +'">\
|
||||
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" style="width:auto" disabled="disabled">\
|
||||
<button class="btn btn-default dropdown-toggle sname" type="button" data-toggle="dropdown" style="width:auto" disabled="disabled">\
|
||||
<b id="sName" val="'+ obj.from.sname +'">'+ obj.from.sname +'</b>\
|
||||
<span class="caret"></span>\
|
||||
</button>\
|
||||
@@ -631,6 +685,7 @@ function editTaskInfo(id){
|
||||
<div class="info-r" style="float: left;margin-right: 25px;display:'+ (obj.from.sType == "path"?'block;':'none') +'">\
|
||||
<input id="inputPath" class="bt-input-text mr5 " type="text" name="path" value="'+ obj.from.sName +'" placeholder="备份目录" style="width:208px;height:33px;" disabled="disabled">\
|
||||
</div>\
|
||||
'+changeDir+'\
|
||||
<div class="textname pull-left mr20">备份到</div>\
|
||||
<div class="dropdown pull-left mr20">\
|
||||
<button class="btn btn-default dropdown-toggle backup_btn" type="button" data-toggle="dropdown" style="width:auto;">\
|
||||
@@ -660,165 +715,177 @@ function editTaskInfo(id){
|
||||
<div class="clearfix plan ptb10">\
|
||||
<div class="bt-submit plan-submits " style="margin-left: 141px;">保存编辑</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
</div>',
|
||||
|
||||
success:function(){
|
||||
|
||||
$('.changePathDir').click(function(){
|
||||
changePathCallback($('#sName').val(),function(select_dir){
|
||||
$('input[name="name"]').val('备份目录['+select_dir+']');
|
||||
$('.sName_btn .sname b').attr('val',select_dir).text(select_dir);
|
||||
obj.from.sname = select_dir;
|
||||
});
|
||||
});
|
||||
|
||||
if(obj.from.stype == 'toShell'){
|
||||
$('.site_list').hide();
|
||||
} else if (obj.from.stype == 'rememory') {
|
||||
$('.site_list').hide();
|
||||
} else if ( obj.from.stype == 'toUrl'){
|
||||
$('.site_list').hide();
|
||||
} else {
|
||||
$('.site_list').show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
obj.from.minute = $('.minute_create').val();
|
||||
obj.from.hour = $('.hour_create').val();
|
||||
obj.from.where1 = $('.where1_create').val();
|
||||
|
||||
$('.sName_create').blur(function () {
|
||||
obj.from.name = $(this).val();
|
||||
});
|
||||
$('.where1_create').blur(function () {
|
||||
obj.from.where1 = $(this).val();
|
||||
});
|
||||
|
||||
$('.hour_create').blur(function () {
|
||||
obj.from.hour = $(this).val();
|
||||
});
|
||||
|
||||
$('.minute_create').blur(function () {
|
||||
obj.from.minute = $(this).val();
|
||||
});
|
||||
|
||||
$('.save_create').blur(function () {
|
||||
obj.from.save = $(this).val();
|
||||
});
|
||||
|
||||
$('.sBody_create').blur(function () {
|
||||
obj.from.sbody = $(this).val();
|
||||
});
|
||||
$('.url_create').blur(function () {
|
||||
obj.from.urladdress = $(this).val();
|
||||
});
|
||||
|
||||
$('[aria-labelledby="cycle"] a').unbind().click(function () {
|
||||
$('.cycle_btn').find('b').attr('val',$(this).attr('value')).html($(this).html());
|
||||
var type = $(this).attr('value');
|
||||
switch(type){
|
||||
case 'day':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').show().find('input').val('1');
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.type = '';
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'day-n':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').show().find('input').val('1');
|
||||
$('.hour_input').show().find('input').val('1');
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = 1;
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'hour':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').hide();
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = '';
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'hour-n':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').show().find('input').val('1');
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'minute-n':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').hide();
|
||||
$('.minute_input').show();
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = '';
|
||||
obj.from.minute = 30;
|
||||
console.log(obj.from);
|
||||
break;
|
||||
case 'week':
|
||||
$('.week_btn').show();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').show();
|
||||
$('.minute_input').show();
|
||||
obj.from.week = 1;
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'month':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').show();
|
||||
$('.hour_input').show();
|
||||
$('.minute_input').show();
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = 1;
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
}
|
||||
obj.from.type = $(this).attr('value');
|
||||
});
|
||||
|
||||
$('[aria-labelledby="week"] a').unbind().click(function () {
|
||||
$('.week_btn').find('b').attr('val',$(this).attr('value')).html($(this).html());
|
||||
obj.from.week = $(this).attr('value');
|
||||
});
|
||||
|
||||
$('[aria-labelledby="backupTo"] a').unbind().click(function () {
|
||||
$('.backup_btn').find('b').attr('val',$(this).attr('value')).html($(this).html());
|
||||
obj.from.backup_to = $(this).attr('value');
|
||||
});
|
||||
$('.plan-submits').unbind().click(function(){
|
||||
if(obj.from.type == 'hour-n'){
|
||||
obj.from.where1 = obj.from.hour;
|
||||
obj.from.hour = '';
|
||||
} else if(obj.from.type == 'minute-n') {
|
||||
obj.from.where1 = obj.from.minute;
|
||||
obj.from.minute = '';
|
||||
}
|
||||
var loadT = layer.msg('正在保存编辑内容,请稍后...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/crontab/modify_crond',obj.from,function(rdata){
|
||||
|
||||
if (!rdata.status){
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
return;
|
||||
}
|
||||
|
||||
showMsg(rdata.msg, function(){
|
||||
layer.closeAll();
|
||||
getCronData(1);
|
||||
initDropdownMenu();
|
||||
},{icon:rdata.status?1:2}, 2000);
|
||||
|
||||
},'json');
|
||||
});
|
||||
}
|
||||
,cancel: function(){
|
||||
initDropdownMenu();
|
||||
}
|
||||
});
|
||||
setTimeout(function(){
|
||||
if(obj.from.stype == 'toShell'){
|
||||
$('.site_list').hide();
|
||||
}else if(obj.from.stype == 'rememory'){
|
||||
$('.site_list').hide();
|
||||
}else if( obj.from.stype == 'toUrl'){
|
||||
$('.site_list').hide();
|
||||
}else{
|
||||
$('.site_list').show();
|
||||
}
|
||||
|
||||
obj.from.minute = $('.minute_create').val();
|
||||
obj.from.hour = $('.hour_create').val();
|
||||
obj.from.where1 = $('.where1_create').val();
|
||||
|
||||
$('.sName_create').blur(function () {
|
||||
obj.from.name = $(this).val();
|
||||
});
|
||||
$('.where1_create').blur(function () {
|
||||
obj.from.where1 = $(this).val();
|
||||
});
|
||||
|
||||
$('.hour_create').blur(function () {
|
||||
obj.from.hour = $(this).val();
|
||||
});
|
||||
|
||||
$('.minute_create').blur(function () {
|
||||
obj.from.minute = $(this).val();
|
||||
});
|
||||
|
||||
$('.save_create').blur(function () {
|
||||
obj.from.save = $(this).val();
|
||||
});
|
||||
|
||||
$('.sBody_create').blur(function () {
|
||||
obj.from.sbody = $(this).val();
|
||||
});
|
||||
$('.url_create').blur(function () {
|
||||
obj.from.urladdress = $(this).val();
|
||||
});
|
||||
|
||||
$('[aria-labelledby="cycle"] a').unbind().click(function () {
|
||||
$('.cycle_btn').find('b').attr('val',$(this).attr('value')).html($(this).html());
|
||||
var type = $(this).attr('value');
|
||||
switch(type){
|
||||
case 'day':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').show().find('input').val('1');
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.type = '';
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'day-n':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').show().find('input').val('1');
|
||||
$('.hour_input').show().find('input').val('1');
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = 1;
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'hour':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').hide();
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = '';
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'hour-n':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').show().find('input').val('1');
|
||||
$('.minute_input').show().find('input').val('30');
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'minute-n':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').hide();
|
||||
$('.minute_input').show();
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = '';
|
||||
obj.from.minute = 30;
|
||||
console.log(obj.from);
|
||||
break;
|
||||
case 'week':
|
||||
$('.week_btn').show();
|
||||
$('.where1_input').hide();
|
||||
$('.hour_input').show();
|
||||
$('.minute_input').show();
|
||||
obj.from.week = 1;
|
||||
obj.from.where1 = '';
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
case 'month':
|
||||
$('.week_btn').hide();
|
||||
$('.where1_input').show();
|
||||
$('.hour_input').show();
|
||||
$('.minute_input').show();
|
||||
obj.from.week = '';
|
||||
obj.from.where1 = 1;
|
||||
obj.from.hour = 1;
|
||||
obj.from.minute = 30;
|
||||
break;
|
||||
}
|
||||
obj.from.type = $(this).attr('value');
|
||||
});
|
||||
|
||||
$('[aria-labelledby="week"] a').unbind().click(function () {
|
||||
$('.week_btn').find('b').attr('val',$(this).attr('value')).html($(this).html());
|
||||
obj.from.week = $(this).attr('value');
|
||||
});
|
||||
|
||||
$('[aria-labelledby="backupTo"] a').unbind().click(function () {
|
||||
$('.backup_btn').find('b').attr('val',$(this).attr('value')).html($(this).html());
|
||||
obj.from.backup_to = $(this).attr('value');
|
||||
});
|
||||
$('.plan-submits').unbind().click(function(){
|
||||
if(obj.from.type == 'hour-n'){
|
||||
obj.from.where1 = obj.from.hour;
|
||||
obj.from.hour = '';
|
||||
} else if(obj.from.type == 'minute-n') {
|
||||
obj.from.where1 = obj.from.minute;
|
||||
obj.from.minute = '';
|
||||
}
|
||||
var loadT = layer.msg('正在保存编辑内容,请稍后...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/crontab/modify_crond',obj.from,function(rdata){
|
||||
|
||||
if (!rdata.status){
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
return;
|
||||
}
|
||||
|
||||
showMsg(rdata.msg, function(){
|
||||
layer.closeAll();
|
||||
getCronData(1);
|
||||
initDropdownMenu();
|
||||
},{icon:rdata.status?1:2}, 2000);
|
||||
|
||||
},'json');
|
||||
});
|
||||
},100);
|
||||
});
|
||||
},'json');
|
||||
}
|
||||
|
||||
@@ -300,13 +300,12 @@ function openFilename(obj){
|
||||
if (inArray(ext,['svg'])){
|
||||
|
||||
$.post("/files/get_body", "path=" + encodeURIComponent(path), function(rdata) {
|
||||
|
||||
if (rdata.data.status){
|
||||
layer.open({
|
||||
type:1,
|
||||
closeBtn: 1,
|
||||
title:false,
|
||||
area: '600px',
|
||||
title:"SVG预览",
|
||||
area: '400px',
|
||||
shadeClose: true,
|
||||
content: '<div class="showpicdiv">'+rdata.data.data+'</div>'
|
||||
});
|
||||
@@ -1365,11 +1364,12 @@ function getImage(fileName){
|
||||
var imgUrl = '/files/download?filename='+fileName;
|
||||
layer.open({
|
||||
type:1,
|
||||
offset: '150px',
|
||||
closeBtn: 1,
|
||||
title:false,
|
||||
area: '500px',
|
||||
title:"图片预览",
|
||||
area: '400px',
|
||||
shadeClose: true,
|
||||
content: '<div class="showpicdiv"><img src="'+imgUrl+'"></div>'
|
||||
content: '<div class="showpicdiv"><img style="max-width:400px;" src="'+imgUrl+'"></div>'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ function toSize(a) {
|
||||
}
|
||||
}
|
||||
|
||||
function toTrim(x) {
|
||||
return x.replace(/^\s+|\s+$/gm,'');
|
||||
}
|
||||
|
||||
function inArray(f, arr){
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (f == arr[i]) {
|
||||
@@ -219,6 +223,47 @@ function getFormatTime(tm, format) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function changePathCallback(default_dir, callback) {
|
||||
|
||||
var c = layer.open({
|
||||
type: 1,
|
||||
area: "650px",
|
||||
title: '选择目录',
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='changepath'><div class='path-top'><button type='button' class='btn btn-default btn-sm' onclick='backFile()'><span class='glyphicon glyphicon-share-alt'></span>返回</button>\
|
||||
<div class='place' id='PathPlace'>当前路径:<span></span></div></div><div class='path-con'><div class='path-con-left'><dl><dt id='changecomlist' onclick='backMyComputer()'>计算机</dt></dl></div>\
|
||||
<div class='path-con-right'><ul class='default' id='computerDefautl'></ul><div class='file-list divtable'>\
|
||||
<table class='table table-hover' style='border:0 none'>\
|
||||
<thead><tr class='file-list-head'><th width='40%'>文件名</th><th width='20%'>修改时间</th><th width='10%'>权限</th><th width='10%'>所有者</th><th width='10%'></th></tr></thead>\
|
||||
<tbody id='tbody' class='list-list'></tbody></table></div></div></div></div><div class='getfile-btn' style='margin-top:0'>\
|
||||
<button type='button' class='btn btn-default btn-sm pull-left' onclick='createFolder()'>新建文件夹</button>\
|
||||
<button type='button' class='btn btn-danger btn-sm mr5 btn-close'>关闭</button>\
|
||||
<button type='button' class='btn btn-success btn-sm btn-choose'>选择</button>\
|
||||
</div>",
|
||||
success:function(layero,layer_index){
|
||||
$('.btn-close').click(function(){
|
||||
layer.close(layer_index);
|
||||
});
|
||||
|
||||
$('.btn-choose').click(function(){
|
||||
var a = $("#PathPlace").find("span").text();
|
||||
a = a.replace(new RegExp(/(\\)/g), "/");
|
||||
a_len = a.length;
|
||||
if (a[a_len-1] == '/'){
|
||||
a = a.substr(0,a_len-1);
|
||||
}
|
||||
callback(a);
|
||||
layer.close(layer_index);
|
||||
});
|
||||
}
|
||||
});
|
||||
getDiskList(default_dir);
|
||||
activeDisk();
|
||||
}
|
||||
|
||||
function changePath(d) {
|
||||
setCookie('SetId', d);
|
||||
setCookie('SetName', '');
|
||||
@@ -236,11 +281,11 @@ function changePath(d) {
|
||||
<thead><tr class='file-list-head'><th width='40%'>文件名</th><th width='20%'>修改时间</th><th width='10%'>权限</th><th width='10%'>所有者</th><th width='10%'></th></tr></thead>\
|
||||
<tbody id='tbody' class='list-list'></tbody></table></div></div></div></div><div class='getfile-btn' style='margin-top:0'>\
|
||||
<button type='button' class='btn btn-default btn-sm pull-left' onclick='createFolder()'>新建文件夹</button>\
|
||||
<button type='button' class='btn btn-danger btn-sm mr5' onclick=\"layer.close(getCookie('ChangePath'))\">关闭</button>\
|
||||
<button type='button' class='btn btn-danger btn-sm mr5' onclick=\"layer.close(getCookie('changePath'))\">关闭</button>\
|
||||
<button type='button' class='btn btn-success btn-sm' onclick='getfilePath()'>选择</button>\
|
||||
</div>"
|
||||
});
|
||||
setCookie("ChangePath", c);
|
||||
setCookie("changePath", c);
|
||||
var b = $("#" + d).val();
|
||||
tmp = b.split(".");
|
||||
if(tmp[tmp.length - 1] == "gz") {
|
||||
@@ -421,7 +466,8 @@ function getfilePath() {
|
||||
}
|
||||
|
||||
$("#" + getCookie("SetId")).val(a + getCookie("SetName"));
|
||||
layer.close(getCookie("ChangePath"));
|
||||
layer.close(getCookie("changePath"));
|
||||
return a;
|
||||
}
|
||||
|
||||
function setCookie(a, c) {
|
||||
@@ -639,7 +685,7 @@ function divcenter() {
|
||||
}
|
||||
|
||||
function copyText(value) {
|
||||
var clipboard = new ClipboardJS('#bt_copys');
|
||||
var clipboard = new ClipboardJS('#mw_copys');
|
||||
clipboard.on('success', function (e) {
|
||||
layer.msg('复制成功',{icon:1,time:2000});
|
||||
});
|
||||
@@ -647,8 +693,12 @@ function copyText(value) {
|
||||
clipboard.on('error', function (e) {
|
||||
layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000});
|
||||
});
|
||||
$("#bt_copys").attr('data-clipboard-text',value);
|
||||
$("#bt_copys").click();
|
||||
$("#mw_copys").attr('data-clipboard-text',value);
|
||||
$("#mw_copys").click();
|
||||
}
|
||||
|
||||
function copyPass(value){
|
||||
copyText(value);
|
||||
}
|
||||
|
||||
function isChineseChar(b) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
var type = '';
|
||||
if ( typeof(type_id) == 'undefined' ){
|
||||
type = '&type_id=0';
|
||||
type = '&type_id=-1';
|
||||
} else {
|
||||
type = '&type_id='+type_id;
|
||||
}
|
||||
@@ -2379,7 +2379,7 @@ function configFile(webSite){
|
||||
function saveConfigFile(webSite,encoding,path){
|
||||
var data = 'encoding='+encoding+'&data='+encodeURIComponent($("#configBody").val())+'&path='+path;
|
||||
var loadT = layer.msg('保存中...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/files/save_body',data,function(rdata){
|
||||
$.post('/site/save_host_conf',data,function(rdata){
|
||||
layer.close(loadT);
|
||||
if(rdata.status){
|
||||
layer.msg(rdata.msg,{icon:1});
|
||||
@@ -2538,7 +2538,6 @@ function changeDefault(type){
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function getClassType(){
|
||||
var select = $('.site_type > select');
|
||||
$.post('/site/get_site_types',function(rdata){
|
||||
@@ -2557,9 +2556,6 @@ function getClassType(){
|
||||
}
|
||||
getClassType();
|
||||
|
||||
|
||||
|
||||
|
||||
function setClassType(){
|
||||
$.post('/site/get_site_types',function(rdata){
|
||||
var list = '';
|
||||
|
||||
+13
-11
@@ -1887,33 +1887,35 @@ html .menu .menu_exit:hover {
|
||||
color: #fff;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
cursor: pointer
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.plan {
|
||||
padding: 10px 20px;
|
||||
margin-bottom: 10px
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.plan .typename {
|
||||
line-height: 34px;
|
||||
width: 120px
|
||||
width: 120px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.plan .textname {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
float: left
|
||||
float: left;
|
||||
}
|
||||
|
||||
.plan .planname input {
|
||||
height: 34px;
|
||||
width: 260px;
|
||||
padding: 0 12px
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.plan .dropdown button b {
|
||||
font-weight: normal
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.plan .dropdown-menu {
|
||||
@@ -2901,23 +2903,23 @@ html .menu .menu_exit:hover {
|
||||
}
|
||||
|
||||
.table>tbody>tr>td {
|
||||
vertical-align: middle
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.showpicdiv {
|
||||
max-height: 500px;
|
||||
max-height: 400px;
|
||||
overflow: hidden;
|
||||
width: 500px
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
#BarTools {
|
||||
font-size: 16px;
|
||||
float: left;
|
||||
margin-right: 20px
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#BarTools>button {
|
||||
top: 0
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.comlist {
|
||||
|
||||
+2
File diff suppressed because one or more lines are too long
@@ -3,138 +3,142 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="main-content">
|
||||
<div class="container-fluid" style="padding-bottom:54px">
|
||||
<div class="pos-box bgw mtb15">
|
||||
<div class="position f14 c9 pull-left">
|
||||
<a class="plr10 c4" href="/">首页</a>/<span class="plr10 c4">计划任务</span>
|
||||
</div>
|
||||
<div class="container-fluid" style="padding-bottom:54px">
|
||||
<div class="pos-box bgw mtb15">
|
||||
<div class="position f14 c9 pull-left">
|
||||
<a class="plr10 c4" href="/">首页</a>/<span class="plr10 c4">计划任务</span>
|
||||
</div>
|
||||
<div class="setbox bgw mtb15">
|
||||
<div class="title c6 plr15">
|
||||
<h3 class="f16">添加计划任务</h3>
|
||||
</div>
|
||||
<div class="setbox bgw mtb15">
|
||||
<div class="title c6 plr15">
|
||||
<h3 class="f16">添加计划任务</h3>
|
||||
</div>
|
||||
<div class="setting-con ptb20">
|
||||
<div class="clearfix plan">
|
||||
<span class="typename c4 pull-left f14 text-right mr20">任务类型</span>
|
||||
<div class="dropdown planjs pull-left mr20">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto">
|
||||
<b val="toShell">Shell脚本</b>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="toShell">Shell脚本</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="site">备份网站</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="database">备份数据库</a></li>
|
||||
{% for db in data['hook_database'] %}
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="database_{{db['name']}}">备份数据库【{{db['title']}}】</a></li>
|
||||
{% endfor %}
|
||||
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="path">备份目录</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="logs">日志切割</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="rememory">释放内存</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="toUrl">访问URL</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<span class="planSign"><i>*</i>任务类型包含以下部分:Shell脚本、备份网站、备份数据库、备份目录、日志切割、释放内存、访问URL</span>
|
||||
</div>
|
||||
<div class="setting-con ptb20">
|
||||
<div class="clearfix plan">
|
||||
<span class="typename c4 pull-left f14 text-right mr20">任务类型</span>
|
||||
<div class="dropdown planjs pull-left mr20">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown" style="width:auto">
|
||||
<b val="toShell">Shell脚本</b>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<div class="clearfix plan">
|
||||
<span class="typename c4 pull-left f14 text-right mr20">任务名称</span>
|
||||
<div class="planname pull-left"><input type="text" name="name" class="bt-input-text"></div>
|
||||
</div>
|
||||
<div class="clearfix plan">
|
||||
<span class="typename c4 pull-left f14 text-right mr20">执行周期</span>
|
||||
<div class="dropdown plancycle pull-left mr20">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="cycle" data-toggle="dropdown" style="width:94px">
|
||||
<b val="week">每星期</b>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="cycle">
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="day">每天</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="day-n">N天</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="hour">每小时</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="hour-n">N小时</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="minute-n">N分钟</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="week">每星期</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="month">每月</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="ptime" class="pull-left">
|
||||
<div class="dropdown planweek pull-left mr20">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown">
|
||||
<b val="1">周一</b>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="toShell">Shell脚本</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="site">备份网站</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="database">备份数据库</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="logs">日志切割</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="rememory">释放内存</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="toUrl">访问URL</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="1">周一</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="2">周二</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="3">周三</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="4">周四</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="5">周五</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="6">周六</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="0">周日</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<span class="planSign"><i>*</i>任务类型包含以下部分:Shell脚本、备份网站、备份数据库、日志切割、释放内存、访问URL</span>
|
||||
</div>
|
||||
<div class="clearfix plan">
|
||||
<span class="typename c4 pull-left f14 text-right mr20">任务名称</span>
|
||||
<div class="planname pull-left"><input type="text" name="name" class="bt-input-text"></div>
|
||||
</div>
|
||||
<div class="clearfix plan">
|
||||
<span class="typename c4 pull-left f14 text-right mr20">执行周期</span>
|
||||
<div class="dropdown plancycle pull-left mr20">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="cycle" data-toggle="dropdown" style="width:94px">
|
||||
<b val="week">每星期</b>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="cycle">
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="day">每天</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="day-n">N天</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="hour">每小时</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="hour-n">N小时</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="minute-n">N分钟</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="week">每星期</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="month">每月</a></li>
|
||||
</ul>
|
||||
<div class="plan_hms pull-left mr20 bt-input-text">
|
||||
<span><input type="number" name="hour" value="1" maxlength="2" max="23" min="0"></span>
|
||||
<span class="name">小时</span>
|
||||
</div>
|
||||
<div id="ptime" class="pull-left">
|
||||
<div class="dropdown planweek pull-left mr20">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="excode" data-toggle="dropdown">
|
||||
<b val="1">周一</b>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="excode">
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="1">周一</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="2">周二</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="3">周三</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="4">周四</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="5">周五</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="6">周六</a></li>
|
||||
<li><a role="menuitem" tabindex="-1" href="javascript:;" value="0">周日</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="plan_hms pull-left mr20 bt-input-text">
|
||||
<span><input type="number" name="hour" value="1" maxlength="2" max="23" min="0"></span>
|
||||
<span class="name">小时</span>
|
||||
</div>
|
||||
<div class="plan_hms pull-left mr20 bt-input-text">
|
||||
<span><input type="number" name="minute" value="30" maxlength="2" max="59" min="0"></span>
|
||||
<span class="name">分钟</span>
|
||||
</div>
|
||||
<div class="plan_hms pull-left mr20 bt-input-text">
|
||||
<span><input type="number" name="minute" value="30" maxlength="2" max="59" min="0"></span>
|
||||
<span class="name">分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix plan">
|
||||
<span class="typename controls c4 pull-left f14 text-right mr20">脚本内容</span>
|
||||
<div id="implement" style="line-height:34px"><textarea class="txtsjs bt-input-text" name="sBody"></textarea></div>
|
||||
</div>
|
||||
<div class="clearfix plan">
|
||||
<div class="bt-submit plan-submit" onclick="planAdd();">添加任务</div>
|
||||
</div>
|
||||
<ul class="help-info-text c7 ptb15 mlr20">
|
||||
<li>当添加完备份任务,应该手动运行一次,并检查备份包是否完整</li>
|
||||
<li>磁盘容量不够、数据库密码错误、网络不稳定等原因,可能导致数据备份不完整</li>
|
||||
</ul>
|
||||
</div>
|
||||
<form id="set-Config" action="/crontab/add" enctype="multipart/form-data" method="post" style="display: none;">
|
||||
<input type="text" name="name" value="" />
|
||||
<input type="text" name="type" value="" />
|
||||
<input type="number" name="where1" value="" />
|
||||
<input type="number" name="hour" value="" />
|
||||
<input type="number" name="minute" value="" />
|
||||
<input type="text" name="week" value="" />
|
||||
<input type="text" name="sType" value="" />
|
||||
<textarea name='sBody'></textarea>
|
||||
<input id="sFile" type="file" name="sFile" value="" />
|
||||
<input id="sName" type="text" name="sName" value="" />
|
||||
<input id="backupTo" type="text" name="backupTo" value="localhost" />
|
||||
<input id="urladdress" type="text" name="urladdress" value="" />
|
||||
<input type="number" name="save" value="" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
<div class="clearfix plan">
|
||||
<span class="typename controls c4 pull-left f14 text-right mr20">脚本内容</span>
|
||||
<div id="implement" style="line-height:34px"><textarea class="txtsjs bt-input-text" name="sBody"></textarea></div>
|
||||
</div>
|
||||
<div class="clearfix plan">
|
||||
<div class="bt-submit plan-submit" onclick="planAdd();">添加任务</div>
|
||||
</div>
|
||||
<ul class="help-info-text c7 ptb15 mlr20">
|
||||
<li>当添加完备份任务,应该手动运行一次,并检查备份包是否完整</li>
|
||||
<li>磁盘容量不够、数据库密码错误、网络不稳定等原因,可能导致数据备份不完整</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="setbox bgw mtb15">
|
||||
<div class="title c6 plr15">
|
||||
<h3 class="f16">任务列表</h3>
|
||||
<span id="allDelete" style="float: right;display: none;">
|
||||
<button onclick="allDeleteCron();" class="btn btn-default btn-sm">删除选中</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="setting-con divtable pd15">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width='30px'><input onclick="checkSelect();" type="checkbox" id="setBox"></th>
|
||||
<th>任务名称</th>
|
||||
<th>状态</th>
|
||||
<th>周期</th>
|
||||
<th>执行时机</th>
|
||||
<th>保存数量</th>
|
||||
<th>备份到</th>
|
||||
<th>添加时间</th>
|
||||
<th width="190">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="cronbody"></tbody>
|
||||
</table>
|
||||
<div class="dataTables_paginate paging_bootstrap pagination">
|
||||
<ul id="softPage" class="page"></ul>
|
||||
</div>
|
||||
<form id="set-Config" action="/crontab/add" enctype="multipart/form-data" method="post" style="display: none;">
|
||||
<input type="text" name="name" value="" />
|
||||
<input type="text" name="type" value="" />
|
||||
<input type="number" name="where1" value="" />
|
||||
<input type="number" name="hour" value="" />
|
||||
<input type="number" name="minute" value="" />
|
||||
<input type="text" name="week" value="" />
|
||||
<input type="text" name="sType" value="" />
|
||||
<textarea name='sBody'></textarea>
|
||||
<input id="sFile" type="file" name="sFile" value="" />
|
||||
<input type="text" name="sName" value="" />
|
||||
<input id="backupTo" type="text" name="backupTo" value="localhost" />
|
||||
<input id="urladdress" type="text" name="urladdress" value="" />
|
||||
<input type="number" name="save" value="" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="setbox bgw mtb15">
|
||||
<div class="title c6 plr15">
|
||||
<h3 class="f16">任务列表</h3>
|
||||
<span id="allDelete" style="float: right;display: none;">
|
||||
<button onclick="allDeleteCron();" class="btn btn-default btn-sm">删除选中</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="setting-con divtable pd15">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width='30px'><input onclick="checkSelect();" type="checkbox" id="setBox"></th>
|
||||
<th>任务名称</th>
|
||||
<th>状态</th>
|
||||
<th>周期</th>
|
||||
<th>执行时机</th>
|
||||
<th>保存数量</th>
|
||||
<th>备份到</th>
|
||||
<th>添加时间</th>
|
||||
<th width="190">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="cronbody"></tbody>
|
||||
</table>
|
||||
<div class="dataTables_paginate paging_bootstrap pagination">
|
||||
<ul id="softPage" class="page"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="btpc-plus" onclick="bindPanel(0,'b')">+</div>
|
||||
</div>
|
||||
</div>
|
||||
<button style="display: none;" id="bt_copys" class="bt_copy" data-clipboard-text=""></button>
|
||||
<button style="display: none;" id="mw_copys" class="mw_copy" data-clipboard-text=""></button>
|
||||
<link rel="stylesheet" href="/static/build/xterm.css?v={{config.version}}">
|
||||
<link rel="stylesheet" href="/static/build/addons/fullscreen/fullscreen.css?v={{config.version}}">
|
||||
<script src="/static/js/jquery-1.10.2.min.js?v={{config.version}}"></script>
|
||||
|
||||
+56
-3
@@ -181,17 +181,70 @@ class backupTools:
|
||||
for database in databases:
|
||||
self.backupDatabase(database['name'], save)
|
||||
|
||||
def findPathName(self, path, filename):
|
||||
f = os.scandir(path)
|
||||
l = []
|
||||
for ff in f:
|
||||
if ff.name.find(filename) > -1:
|
||||
l.append(ff.name)
|
||||
return l
|
||||
|
||||
def backupPath(self, path, count):
|
||||
|
||||
mw.echoStart('备份')
|
||||
|
||||
backup_path = mw.getBackupDir() + '/path'
|
||||
if not os.path.exists(backup_path):
|
||||
mw.execShell("mkdir -p " + backup_path)
|
||||
|
||||
dirname = os.path.basename(path)
|
||||
fname = 'path_{}_{}.tar.gz'.format(
|
||||
dirname, mw.formatDate("%Y%m%d_%H%M%S"))
|
||||
dfile = os.path.join(backup_path, fname)
|
||||
|
||||
p_size = mw.getPathSize(path)
|
||||
stime = time.time()
|
||||
|
||||
cmd = "cd " + os.path.dirname(path) + " && tar zcvf '" + dfile + "' '" + dirname + "' 2>{err_log} 1> /dev/null".format(
|
||||
err_log='/tmp/backup_err.log')
|
||||
mw.execShell(cmd)
|
||||
|
||||
tar_size = os.path.getsize(dfile)
|
||||
|
||||
mw.echoInfo('备份目录:' + path)
|
||||
mw.echoInfo('目录已备份到:' + dfile)
|
||||
mw.echoInfo("目录大小:{}".format(mw.toSize(p_size)))
|
||||
mw.echoInfo("开始压缩文件:{}".format(mw.formatDate(times=stime)))
|
||||
mw.echoInfo("文件压缩完成,耗时{:.2f}秒,压缩包大小:{}".format(
|
||||
time.time() - stime, mw.toSize(tar_size)))
|
||||
mw.echoInfo('保留最新的备份数:' + count + '份')
|
||||
|
||||
backups = self.findPathName(backup_path, 'path_{}'.format(dirname))
|
||||
num = len(backups) - int(count)
|
||||
backups.sort()
|
||||
if num > 0:
|
||||
for backup in backups:
|
||||
abspath_bk = backup_path + "/" + backup
|
||||
mw.execShell("rm -f " + abspath_bk)
|
||||
mw.echoInfo("|---已清理过期备份文件:" + abspath_bk)
|
||||
num -= 1
|
||||
if num < 1:
|
||||
break
|
||||
|
||||
mw.echoEnd('备份')
|
||||
|
||||
if __name__ == "__main__":
|
||||
backup = backupTools()
|
||||
type = sys.argv[1]
|
||||
if type == 'site':
|
||||
stype = sys.argv[1]
|
||||
if stype == 'site':
|
||||
if sys.argv[2] == 'ALL':
|
||||
backup.backupSiteAll(sys.argv[3])
|
||||
else:
|
||||
backup.backupSite(sys.argv[2], sys.argv[3])
|
||||
elif type == 'database':
|
||||
elif stype == 'database':
|
||||
if sys.argv[2] == 'ALL':
|
||||
backup.backupDatabaseAll(sys.argv[3])
|
||||
else:
|
||||
backup.backupDatabase(sys.argv[2], sys.argv[3])
|
||||
elif stype == 'path':
|
||||
backup.backupPath(sys.argv[2], sys.argv[3])
|
||||
|
||||
@@ -331,7 +331,8 @@ case "$1" in
|
||||
echo -e "=================================================================="
|
||||
echo -e "$address"
|
||||
echo -e `python3 $mw_path/tools.py username`
|
||||
echo -e "password: $password"
|
||||
echo -e `python3 $mw_path/tools.py password`
|
||||
# echo -e "password: $password"
|
||||
echo -e "\033[33mWarning:\033[0m"
|
||||
echo -e "\033[33mIf you cannot access the panel. \033[0m"
|
||||
echo -e "\033[33mrelease the following port (${show_panel_ip}888|80|443|22) in the security group.\033[0m"
|
||||
|
||||
+39
-19
@@ -4,6 +4,8 @@ export PATH
|
||||
# LANG=en_US.UTF-8
|
||||
is64bit=`getconf LONG_BIT`
|
||||
|
||||
{
|
||||
|
||||
if [ -f /etc/motd ];then
|
||||
echo "welcome to mdserver-web panel" > /etc/motd
|
||||
fi
|
||||
@@ -18,38 +20,37 @@ if [ "$EUID" -ne 0 ]
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if [ ${_os} == "Darwin" ]; then
|
||||
OSNAME='macos'
|
||||
elif grep -Eq "openSUSE" /etc/*-release; then
|
||||
OSNAME='opensuse'
|
||||
zypper refresh
|
||||
zypper install cron wget curl zip unzip
|
||||
elif grep -Eq "FreeBSD" /etc/*-release; then
|
||||
OSNAME='freebsd'
|
||||
elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
|
||||
OSNAME='centos'
|
||||
yum install -y wget zip unzip
|
||||
OSNAME='rhel'
|
||||
yum install -y wget curl zip unzip tar crontabs
|
||||
elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then
|
||||
OSNAME='fedora'
|
||||
yum install -y wget zip unzip
|
||||
yum install -y wget curl zip unzip tar crontabs
|
||||
elif grep -Eqi "Rocky" /etc/issue || grep -Eq "Rocky" /etc/*-release; then
|
||||
OSNAME='rocky'
|
||||
yum install -y wget zip unzip
|
||||
OSNAME='rhel'
|
||||
yum install -y wget curl zip unzip tar crontabs
|
||||
elif grep -Eqi "AlmaLinux" /etc/issue || grep -Eq "AlmaLinux" /etc/*-release; then
|
||||
OSNAME='alma'
|
||||
yum install -y wget zip unzip
|
||||
OSNAME='rhel'
|
||||
yum install -y wget curl zip unzip tar crontabs
|
||||
elif grep -Eqi "Amazon Linux" /etc/issue || grep -Eq "Amazon Linux" /etc/*-release; then
|
||||
OSNAME='amazon'
|
||||
yum install -y wget zip unzip
|
||||
elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
|
||||
yum install -y wget curl zip unzip tar crontabs
|
||||
elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/os-release; then
|
||||
OSNAME='debian'
|
||||
apt update -y
|
||||
apt install -y devscripts
|
||||
apt install -y wget zip unzip
|
||||
elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
|
||||
apt install -y wget curl zip unzip tar cron
|
||||
elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/os-release; then
|
||||
OSNAME='ubuntu'
|
||||
apt install -y wget zip unzip
|
||||
apt update -y
|
||||
apt install -y wget curl zip unzip tar cron
|
||||
else
|
||||
OSNAME='unknow'
|
||||
fi
|
||||
@@ -69,12 +70,11 @@ if [ $OSNAME != "macos" ];then
|
||||
mkdir -p /www/backup/database
|
||||
mkdir -p /www/backup/site
|
||||
|
||||
|
||||
# https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh
|
||||
|
||||
if [ ! -d /www/server/mdserver-web ];then
|
||||
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
|
||||
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
if [ ! -d /www/server/mdserver-web ];then
|
||||
if [ ! -z "$cn" ];then
|
||||
curl -sSLo /tmp/master.zip https://gitee.com/midoks/mdserver-web/repository/archive/master.zip
|
||||
else
|
||||
@@ -86,12 +86,28 @@ if [ $OSNAME != "macos" ];then
|
||||
rm -rf /tmp/master.zip
|
||||
rm -rf /tmp/mdserver-web-master
|
||||
fi
|
||||
|
||||
# install acme.sh
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
if [ ! -z "$cn" ];then
|
||||
curl -sSL -o /tmp/acme.tar.gz https://ghproxy.com/github.com/acmesh-official/acme.sh/archive/master.tar.gz
|
||||
tar xvzf /tmp/acme.tar.gz -C /tmp
|
||||
cd /tmp/acme.sh-master
|
||||
bash acme.sh install
|
||||
cd -
|
||||
fi
|
||||
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "use system version: ${OSNAME}"
|
||||
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh
|
||||
|
||||
|
||||
cd /www/server/mdserver-web && bash cli.sh start
|
||||
isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'`
|
||||
n=0
|
||||
@@ -121,3 +137,7 @@ endTime=`date +%s`
|
||||
((outTime=(${endTime}-${startTime})/60))
|
||||
echo -e "Time consumed:\033[32m $outTime \033[0mMinute!"
|
||||
|
||||
} 1> >(tee mw-install.log) 2>&1
|
||||
|
||||
echo -e "\nInstall completed. If error occurs, please contact us with the log file mw-install.log ."
|
||||
echo "安装完毕,如果出现错误,请带上同目录下的安装日志 mw-install.log 联系我们反馈."
|
||||
@@ -14,13 +14,8 @@ dnf install -y python-devel
|
||||
dnf install -y crontabs
|
||||
dnf install -y mysql-devel
|
||||
|
||||
#https need
|
||||
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
|
||||
if [ -f /etc/init.d/iptables ];then
|
||||
if [ -f /usr/sbin/iptables ];then
|
||||
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
||||
@@ -41,7 +36,7 @@ if [ -f /etc/init.d/iptables ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f /etc/init.d/iptables ];then
|
||||
if [ ! -f /usr/sbin/iptables ];then
|
||||
yum install firewalld -y
|
||||
systemctl enable firewalld
|
||||
systemctl start firewalld
|
||||
|
||||
@@ -21,14 +21,7 @@ yum install -y curl-devel libmcrypt libmcrypt-devel
|
||||
yum install -y mysql-devel
|
||||
yum install -y expect
|
||||
|
||||
|
||||
|
||||
#https need
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
|
||||
if [ -f /etc/init.d/iptables ];then
|
||||
if [ -f /usr/sbin/iptables ];then
|
||||
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
||||
@@ -49,7 +42,7 @@ if [ -f /etc/init.d/iptables ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f /etc/init.d/iptables ];then
|
||||
if [ ! -f /usr/sbin/iptables ];then
|
||||
yum install firewalld -y
|
||||
systemctl enable firewalld
|
||||
#取消服务锁定
|
||||
|
||||
@@ -54,12 +54,7 @@ echo y | pacman -Syu icu
|
||||
|
||||
hwclock --systohc
|
||||
|
||||
#https need
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
|
||||
if [ -f /etc/init.d/iptables ];then
|
||||
if [ -f /usr/sbin/iptables ];then
|
||||
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
||||
@@ -80,7 +75,7 @@ if [ -f /etc/init.d/iptables ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f /etc/init.d/iptables ];then
|
||||
if [ ! -f /usr/sbin/iptables ];then
|
||||
echo y | pacman -Sy firewalld
|
||||
systemctl enable firewalld
|
||||
systemctl start firewalld
|
||||
|
||||
@@ -23,13 +23,7 @@ yum install -y mysql-devel
|
||||
yum install -y expect
|
||||
|
||||
|
||||
|
||||
#https need
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
|
||||
if [ -f /etc/init.d/iptables ];then
|
||||
if [ -f /usr/sbin/iptables ];then
|
||||
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
||||
@@ -50,7 +44,7 @@ if [ -f /etc/init.d/iptables ];then
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f /etc/init.d/iptables ];then
|
||||
if [ ! -f /usr/sbin/iptables ];then
|
||||
yum install firewalld -y
|
||||
systemctl enable firewalld
|
||||
#取消服务锁定
|
||||
|
||||
+48
-54
@@ -2,19 +2,13 @@
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
export LANG=en_US.UTF-8
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# RED='\e[1;31m' # 红色
|
||||
# GREEN='\e[1;32m' # 绿色
|
||||
# YELLOW='\e[1;33m' # 黄色
|
||||
# BLUE='\e[1;34m' # 蓝色
|
||||
# PURPLE='\e[1;35m' # 紫色
|
||||
# CYAN='\e[1;36m' # 蓝绿色
|
||||
# WHITE='\e[1;37m' # 白色
|
||||
# NC='\e[0m' # 没有颜色
|
||||
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
|
||||
|
||||
if grep -Eq "Debian" /etc/*-release; then
|
||||
ln -sf /bin/bash /bin/sh
|
||||
fi
|
||||
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
|
||||
|
||||
ln -sf /bin/bash /bin/sh
|
||||
|
||||
__GET_BIT=`getconf LONG_BIT`
|
||||
if [ "$__GET_BIT" == "32" ];then
|
||||
@@ -25,26 +19,27 @@ fi
|
||||
|
||||
# synchronize time first
|
||||
apt-get install ntpdate -y
|
||||
ntpdate time.nist.gov | logger -t NTP
|
||||
|
||||
apt update -y
|
||||
apt-get update -y
|
||||
|
||||
|
||||
apt install -y wget curl lsof unzip
|
||||
apt install -y python3-pip
|
||||
apt install -y python3-dev
|
||||
apt install -y python3-venv
|
||||
apt install -y cron
|
||||
apt install -y expect
|
||||
|
||||
apt install -y locate
|
||||
locale-gen en_US.UTF-8
|
||||
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
|
||||
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
NTPHOST='time.nist.gov'
|
||||
if [ ! -z "$cn" ];then
|
||||
NTPHOST='ntp1.aliyun.com'
|
||||
fi
|
||||
ntpdate $NTPHOST | logger -t NTP
|
||||
|
||||
if [ ! -f /usr/sbin/locale-gen ];then
|
||||
apt install -y locales
|
||||
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
|
||||
locale-gen en_US.UTF-8
|
||||
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
|
||||
dpkg-reconfigure --frontend=noninteractive locales
|
||||
update-locale LANG=en_US.UTF-8
|
||||
else
|
||||
locale-gen en_US.UTF-8
|
||||
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
|
||||
fi
|
||||
|
||||
apt-get update -y
|
||||
apt install -y wget curl lsof unzip tar cron expect locate
|
||||
apt install -y python3-pip python3-dev python3-venv
|
||||
|
||||
if [ -f /usr/sbin/ufw ];then
|
||||
|
||||
@@ -59,12 +54,9 @@ if [ -f /usr/sbin/ufw ];then
|
||||
fi
|
||||
|
||||
if [ -f /usr/sbin/ufw ];then
|
||||
|
||||
ufw disable
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f /usr/sbin/ufw ];then
|
||||
apt install -y firewalld
|
||||
systemctl enable firewalld
|
||||
@@ -88,7 +80,6 @@ fi
|
||||
#安装时不开启
|
||||
systemctl stop firewalld
|
||||
|
||||
|
||||
#fix zlib1g-dev fail
|
||||
echo -e "\e[0;32mfix zlib1g-dev install question start\e[0m"
|
||||
Install_TmpFile=/tmp/debian-fix-zlib1g-dev.txt
|
||||
@@ -118,14 +109,13 @@ rm -rf ${Install_TmpFile}
|
||||
echo -e "\e[0;32mfix libunwind-dev install question end\e[0m"
|
||||
|
||||
|
||||
apt install -y libvpx-dev
|
||||
apt install -y libvpx-dev
|
||||
apt install -y libxpm-dev
|
||||
apt install -y libwebp-dev
|
||||
apt install -y libfreetype6-dev
|
||||
|
||||
sudo localedef -i en_US -f UTF-8 en_US.UTF-8
|
||||
localedef -i en_US -f UTF-8 en_US.UTF-8
|
||||
|
||||
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
|
||||
if [ "$VERSION_ID" == "9" ];then
|
||||
sed "s/flask==2.0.3/flask==1.1.1/g" -i /www/server/mdserver-web/requirements.txt
|
||||
sed "s/cryptography==3.3.2/cryptography==2.5/g" -i /www/server/mdserver-web/requirements.txt
|
||||
@@ -135,9 +125,10 @@ if [ "$VERSION_ID" == "9" ];then
|
||||
# pip3 install -r /www/server/mdserver-web/requirements.txt
|
||||
fi
|
||||
|
||||
apt install -y build-essential
|
||||
apt install -y devscripts
|
||||
|
||||
apt install -y net-tools
|
||||
apt install -y python3-dev
|
||||
apt install -y autoconf
|
||||
apt install -y gcc
|
||||
|
||||
@@ -164,35 +155,38 @@ apt install -y dia pkg-config
|
||||
apt install -y zlib1g-dev
|
||||
apt install -y libjpeg-dev libpng-dev
|
||||
apt install -y libfreetype6
|
||||
apt install -y libjpeg62-turbo-dev
|
||||
apt install -y libfreetype6-dev
|
||||
apt install -y libevent-dev libncurses5-dev libldap2-dev
|
||||
apt install -y libzip-dev
|
||||
apt install -y libicu-dev
|
||||
|
||||
apt install -y build-essential
|
||||
|
||||
apt install -y libcurl4-openssl-dev
|
||||
apt install -y curl libcurl4-gnutls-dev
|
||||
|
||||
# Disabled due to dependency issues
|
||||
#apt install --ignore-missing -y autoconf automake cmake curl dia gcc imagemagick libbz2-dev libcurl4-gnutls-dev\
|
||||
# libcurl4-openssl-dev libevent-dev libffi-dev libfreetype6 libfreetype6-dev libgmp-dev libgmp3-dev libicu-dev \
|
||||
# libjpeg-dev libldap2-dev libmagickwand-dev libmcrypt-dev libmemcached-dev libncurses5-dev \
|
||||
# libpcre3 libpcre3-dev libpng-dev libpspell-dev libreadline-dev librecode-dev libsasl2-dev libssl-dev \
|
||||
# libunwind-dev libwebp-dev libxml2 libxml2-dev libxpm-dev libzip-dev lzma lzma-dev make net-tools openssl \
|
||||
# pkg-config python3-dev scons webp zlib1g-dev
|
||||
|
||||
if [ "$VERSION_ID" != "9" ]; then
|
||||
apt install -y libjpeg62-turbo-dev
|
||||
fi
|
||||
|
||||
#https://blog.csdn.net/qq_36228377/article/details/123154344
|
||||
# ln -s /usr/include/x86_64-linux-gnu/curl /usr/include/curl
|
||||
if [ ! -d /usr/include/curl ];then
|
||||
ln -s /usr/include/x86_64-linux-gnu/curl /usr/include/curl
|
||||
fi
|
||||
|
||||
apt install -y graphviz bison re2c flex libsqlite3-dev libonig-dev perl g++ libtool libxslt1-dev
|
||||
apt install -y libmariadb-dev libmariadb-dev-compat
|
||||
|
||||
apt install -y graphviz bison re2c flex
|
||||
apt install -y libsqlite3-dev
|
||||
apt install -y libonig-dev
|
||||
|
||||
apt install -y perl g++ libtool
|
||||
apt install -y libxslt1-dev
|
||||
|
||||
apt install -y libmariadb-dev
|
||||
#apt install -y libmysqlclient-dev
|
||||
apt install -y libmariadb-dev-compat
|
||||
#apt install -y libmysqlclient-dev
|
||||
#apt install -y libmariadbclient-dev
|
||||
|
||||
cd /www/server/mdserver-web/scripts && bash lib.sh
|
||||
chmod 755 /www/server/mdserver-web/data
|
||||
|
||||
|
||||
cd /www/server/mdserver-web/scripts && bash lib.sh
|
||||
chmod 755 /www/server/mdserver-web/data
|
||||
@@ -17,13 +17,7 @@ yum install -y wget curl lsof unzip
|
||||
yum install -y expect
|
||||
dnf install crontabs -y
|
||||
|
||||
#https need
|
||||
|
||||
if [ ! -d /root/.acme.sh ];then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
|
||||
if [ -f /etc/init.d/iptables ];then
|
||||
if [ -f /usr/sbin/iptables ];then
|
||||
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
||||
@@ -46,7 +40,7 @@ fi
|
||||
|
||||
|
||||
if [ "${isVersion}" == '' ];then
|
||||
if [ ! -f "/etc/init.d/iptables" ];then
|
||||
if [ ! -f "/usr/sbin/iptables" ];then
|
||||
yum install firewalld -y
|
||||
systemctl enable firewalld
|
||||
systemctl start firewalld
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user