Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9615fb2203 | ||
|
|
49c181c577 | ||
|
|
0fa5e4fb48 | ||
|
|
8e7130c382 | ||
|
|
33c1ac82c8 | ||
|
|
df5aec2e8f | ||
|
|
6c864177ee | ||
|
|
9ee09b0e7d | ||
|
|
b7da91f92b | ||
|
|
17e6703c07 | ||
|
|
a5f77a37f2 | ||
|
|
78fc9fd90f | ||
|
|
700f042033 | ||
|
|
e44768e608 | ||
|
|
2acef86207 | ||
|
|
6256bb02da | ||
|
|
04f5a27492 | ||
|
|
7cd476696a | ||
|
|
2ecaf0e2a3 | ||
|
|
c5d3494a94 | ||
|
|
af0658fd41 | ||
|
|
cccbd88145 | ||
|
|
48aad5b248 | ||
|
|
d843213c39 | ||
|
|
7ad33c5c59 | ||
|
|
ee56cfe5ab | ||
|
|
c6b38aa996 | ||
|
|
c5205c2d55 | ||
|
|
1be07f96ff | ||
|
|
9f4af88c1e | ||
|
|
ebc0559dff | ||
|
|
fe320ecd3b | ||
|
|
02c06e7ff1 | ||
|
|
6d90d6fde5 | ||
|
|
bfc0b9efa3 | ||
|
|
6e4e7bcf68 | ||
|
|
5da505084d | ||
|
|
f19df17ef5 | ||
|
|
d99e89744d | ||
|
|
9695fe4b9b | ||
|
|
5907dc36c5 | ||
|
|
d694af9358 | ||
|
|
4dc2828c59 | ||
|
|
37519b4c92 | ||
|
|
90999c7ae1 | ||
|
|
f16d9ea269 | ||
|
|
86098541e0 | ||
|
|
9ef04a4d9e | ||
|
|
752f8fae5a | ||
|
|
c5fdecf459 | ||
|
|
19284cd5ef | ||
|
|
da92ab1c89 | ||
|
|
18ca47e8b3 | ||
|
|
8b624297ba | ||
|
|
f0d9ff2ae9 | ||
|
|
21b2c17220 | ||
|
|
0df898a7d9 | ||
|
|
cf1f4c8538 | ||
|
|
89ecdcd29a | ||
|
|
0c8fa5e616 | ||
|
|
f9252da1b0 | ||
|
|
e31cbad7dd | ||
|
|
5bed9f0802 | ||
|
|
1ae4b54779 | ||
|
|
2b2a75adf0 | ||
|
|
55184341d7 | ||
|
|
6504decc30 | ||
|
|
843d798b91 | ||
|
|
087a6b4809 | ||
|
|
44438bd9aa | ||
|
|
c33cba0e85 | ||
|
|
cdc3c95367 | ||
|
|
222cebe1b3 | ||
|
|
2fc2eff97e | ||
|
|
79f8baeeb3 | ||
|
|
0399219df6 | ||
|
|
cd0d5ede16 | ||
|
|
1e6d1c6127 | ||
|
|
ff87dbe258 | ||
|
|
7d6ddb40db | ||
|
|
1cb57d3f65 | ||
|
|
9ed434d274 | ||
|
|
f532a376a7 | ||
|
|
4405f7720b | ||
|
|
fbde4aab88 | ||
|
|
864691d357 | ||
|
|
95bf0cb1e8 | ||
|
|
126f2d553d | ||
|
|
2fb88be080 | ||
|
|
fa307cdb49 | ||
|
|
0850b6ed44 | ||
|
|
ec1e99f9ca | ||
|
|
546dc4d7eb | ||
|
|
9b0b4ac305 | ||
|
|
23a1f3936d | ||
|
|
4cb22a1e35 | ||
|
|
3e3cdbe18c | ||
|
|
bdc46d9401 | ||
|
|
64986dd125 | ||
|
|
7ee00ab0b5 | ||
|
|
488d92ba19 | ||
|
|
9cebfb64cb | ||
|
|
7800429f8d | ||
|
|
7954714bb7 | ||
|
|
1d396b73f0 | ||
|
|
5f95a1d56a | ||
|
|
51951a2685 | ||
|
|
737453600d | ||
|
|
17ef460f4c | ||
|
|
38be955738 | ||
|
|
daf5c7c2b0 | ||
|
|
acdb35f395 | ||
|
|
5e8a15c230 | ||
|
|
34bcdd915c | ||
|
|
aa718adfea | ||
|
|
936592661b | ||
|
|
c740b4affb | ||
|
|
042b07efa2 | ||
|
|
6a6d22fd2d | ||
|
|
f99502d2c8 | ||
|
|
1cf41348b7 | ||
|
|
acdb226df9 | ||
|
|
6259f21196 | ||
|
|
6ad1292003 | ||
|
|
a682ba3e43 | ||
|
|
7509b259e7 | ||
|
|
8d170d87e4 | ||
|
|
bc4e5f6a87 | ||
|
|
954f66c8dc | ||
|
|
a7f860de2b | ||
|
|
6e7e291da3 | ||
|
|
2bca78c32d | ||
|
|
fb4311cdbf | ||
|
|
d889bf2cf3 | ||
|
|
511a7ac12b | ||
|
|
03e126cb48 | ||
|
|
2acbe56e21 | ||
|
|
8425aa4942 | ||
|
|
17ad9abe6b | ||
|
|
11166bbab1 | ||
|
|
f5f3f7ded5 | ||
|
|
26bae283be | ||
|
|
bfb12692a6 | ||
|
|
6bc6f17783 | ||
|
|
cd6f86ebfa | ||
|
|
5abb2613a1 | ||
|
|
a08dee242a | ||
|
|
2700b6b67b | ||
|
|
e41148d72d | ||
|
|
9b5c80bc72 | ||
|
|
958755d18d | ||
|
|
9af7e0f95b | ||
|
|
90e86cda0d | ||
|
|
ea2ed9d003 | ||
|
|
67eb3590c7 | ||
|
|
e66afbbb2d | ||
|
|
f959391b85 | ||
|
|
663e95288a | ||
|
|
0af3c7622d | ||
|
|
40e2186a5b | ||
|
|
121c972951 | ||
|
|
229cb977a1 | ||
|
|
ae845a702c | ||
|
|
35b0b1d153 | ||
|
|
4801850373 | ||
|
|
8b3d0cbba4 | ||
|
|
4f580d0427 | ||
|
|
2f794c5b73 | ||
|
|
21cd34d272 | ||
|
|
c58e1f7278 | ||
|
|
5b49f24a8d | ||
|
|
ce89a2a275 | ||
|
|
35f905e94c | ||
|
|
1c431286e4 | ||
|
|
705cef730b | ||
|
|
2a5da5593b | ||
|
|
22692d8ed4 | ||
|
|
5cdae707e9 | ||
|
|
5be9f1ae66 | ||
|
|
ba931a0c2a | ||
|
|
5b87572bff | ||
|
|
d51de312ac | ||
|
|
bcd2e7298b | ||
|
|
a985511b3b | ||
|
|
abb9fb72f0 | ||
|
|
b36ad3a595 | ||
|
|
a118f33f57 | ||
|
|
58b888edcd | ||
|
|
43d906139e | ||
|
|
b91bc040d4 | ||
|
|
c6eba5bbf1 | ||
|
|
1adbf733d8 | ||
|
|
913d483e63 | ||
|
|
9951f7151e | ||
|
|
167a386a0d | ||
|
|
5473ee74cb | ||
|
|
dbeefc06c8 | ||
|
|
444730e553 | ||
|
|
8a2e17198e | ||
|
|
bc41788d49 | ||
|
|
ebd8e93b16 | ||
|
|
a45994c3c7 | ||
|
|
f41f616daf | ||
|
|
da5b9351e2 | ||
|
|
3c080e0264 | ||
|
|
dc62aabfd4 | ||
|
|
c6da2e56ee | ||
|
|
461f3dcb0a | ||
|
|
ee5b9f35ad | ||
|
|
3ad8496daf | ||
|
|
77023263a6 | ||
|
|
6497627931 | ||
|
|
2ae3426c82 | ||
|
|
dbeb919f05 | ||
|
|
2106746f6c | ||
|
|
31d5b90670 | ||
|
|
ceaf9c42db | ||
|
|
9067778bf3 | ||
|
|
99053b67ce | ||
|
|
07b8d91f31 | ||
|
|
e9d4e09049 | ||
|
|
629416760f | ||
|
|
d1ade4355e | ||
|
|
4508e30ea7 | ||
|
|
b1c5c90bef | ||
|
|
e9a7db2c1d | ||
|
|
63e5f26491 | ||
|
|
ed93ccc0ee | ||
|
|
929a50c137 | ||
|
|
fe87092750 | ||
|
|
c144cead18 | ||
|
|
afdc9720fc | ||
|
|
194c7b9d45 | ||
|
|
162557230a | ||
|
|
f4dfe502cb | ||
|
|
7a3d49a9cf | ||
|
|
49f1407c42 | ||
|
|
319f72865d | ||
|
|
0eaa6f38e0 | ||
|
|
eeef8d488c | ||
|
|
4e69f9540a | ||
|
|
a0e8d75af7 | ||
|
|
f54f7d4ce3 | ||
|
|
5f4893c115 | ||
|
|
a48b869fe9 | ||
|
|
266a8cf806 | ||
|
|
13e4dcf8ad | ||
|
|
1ca469518d | ||
|
|
4284a3daf4 | ||
|
|
84995650ee | ||
|
|
fa662d75d6 | ||
|
|
842c0daf70 | ||
|
|
798608287e | ||
|
|
437225374e | ||
|
|
3a442570db | ||
|
|
366c3677c2 | ||
|
|
6dcf1db856 | ||
|
|
b3ca295e51 | ||
|
|
03f06ee384 | ||
|
|
2dc96cd04e | ||
|
|
a875293116 | ||
|
|
8735fb9238 | ||
|
|
58fcf0e8f9 | ||
|
|
fccc30ebb1 | ||
|
|
6b9da57ff2 | ||
|
|
cd6b2ad65e | ||
|
|
60b2834adf | ||
|
|
c74e0428fd | ||
|
|
20d486629e | ||
|
|
f984e4ecc7 | ||
|
|
0bdea14560 | ||
|
|
0c3599facb | ||
|
|
05eb434bf8 | ||
|
|
12dccc1df0 | ||
|
|
11e7316911 | ||
|
|
26a6a80504 | ||
|
|
498799578a | ||
|
|
6a5b009766 | ||
|
|
8e23411be8 | ||
|
|
b597255d68 | ||
|
|
8979011ec3 | ||
|
|
11a21f9a8b | ||
|
|
1a12f625cd | ||
|
|
11e44d5b0e | ||
|
|
47c1394de6 | ||
|
|
5e7fa28feb | ||
|
|
d04f891ee7 | ||
|
|
3d28e0a3cb | ||
|
|
37112546b9 | ||
|
|
cb719c9973 | ||
|
|
7ec5fe84b2 | ||
|
|
c68cce0198 | ||
|
|
0d7fd11de5 | ||
|
|
643a2e8cf8 | ||
|
|
35ee7d3d10 | ||
|
|
2ce3871ee2 | ||
|
|
812ce86187 | ||
|
|
3d44b3014f | ||
|
|
092494a216 | ||
|
|
a21ad254b7 | ||
|
|
ebd6b9f389 | ||
|
|
33b90a976b | ||
|
|
2518d32019 | ||
|
|
4ded4679f3 | ||
|
|
28d3996d17 | ||
|
|
b76950ed3b | ||
|
|
d49aa168eb | ||
|
|
5304d0b228 | ||
|
|
56e4ef1a4e | ||
|
|
91fc83e0ba | ||
|
|
fc0fdd5772 | ||
|
|
0d0007d9a1 | ||
|
|
a74ace856a | ||
|
|
f46af799a9 | ||
|
|
3e4facbf57 | ||
|
|
ff9466d0a4 | ||
|
|
9cbcff5dbc | ||
|
|
90834415bf | ||
|
|
c2862ab5d4 | ||
|
|
664a7864bc | ||
|
|
9cf6a40493 | ||
|
|
028422337e | ||
|
|
5f10d9433c | ||
|
|
ed49f0b0bd | ||
|
|
090fc0f243 | ||
|
|
f2df81694f | ||
|
|
6cf2e2d6b6 | ||
|
|
defdc3d3b8 | ||
|
|
6d1d1b882e | ||
|
|
54f90c9300 | ||
|
|
a1aa7d465d | ||
|
|
62214c2a88 | ||
|
|
d5a4958566 | ||
|
|
0bca4a3589 | ||
|
|
30bc8b1ec1 | ||
|
|
0472102a3a | ||
|
|
2da863d98a | ||
|
|
88bab4b15b | ||
|
|
d1b4a1cde1 | ||
|
|
d88f6903da | ||
|
|
3a53b360b7 | ||
|
|
3e5b951a41 | ||
|
|
272b6fdeea | ||
|
|
49ac781e87 | ||
|
|
b4f9fa0976 | ||
|
|
96baa99bdc | ||
|
|
5db4f39c76 | ||
|
|
23dadd7f6f | ||
|
|
7d8d48f3d5 | ||
|
|
74fd4bbe08 | ||
|
|
30240443e6 | ||
|
|
e069c3a24e | ||
|
|
73e75abb5f | ||
|
|
b35d516a8e | ||
|
|
aa1875612b | ||
|
|
b189d5b485 | ||
|
|
33b43b253c | ||
|
|
86cfb1b9cf | ||
|
|
f93afb772c | ||
|
|
bd49bd3004 | ||
|
|
db26b09eba | ||
|
|
85da65ad1e | ||
|
|
d9a409ffcc | ||
|
|
ea923a45a6 | ||
|
|
7480cfb5d8 | ||
|
|
be513af18e | ||
|
|
1c5e61a3de | ||
|
|
d26474f222 | ||
|
|
03c796775a | ||
|
|
182d434f84 | ||
|
|
7c1d409e61 | ||
|
|
dab12535f2 | ||
|
|
deffb3d61b | ||
|
|
a4a45f2005 | ||
|
|
32d6a89bd4 | ||
|
|
f41c2454ee | ||
|
|
76dba077c0 | ||
|
|
1c34488abb | ||
|
|
6742d971eb | ||
|
|
3de01da4ba | ||
|
|
4ba526ca2b | ||
|
|
a4e8b6a137 | ||
|
|
50ad3ed7e7 | ||
|
|
64d29659f7 | ||
|
|
2794f49df4 | ||
|
|
3e27f85719 | ||
|
|
a4d70f2294 | ||
|
|
f3cd1f597e | ||
|
|
489c363daf | ||
|
|
77f44481b3 | ||
|
|
fcd4ba024a | ||
|
|
ce6b15939d | ||
|
|
baaccb7960 | ||
|
|
fb559e9f11 | ||
|
|
283a2c052b | ||
|
|
a7bd9e3290 | ||
|
|
b64dbb9aa4 | ||
|
|
d9f63c3a9a | ||
|
|
3c02af41bc | ||
|
|
ac87a6c8b1 | ||
|
|
f19dd2a2b9 | ||
|
|
cef7215fdc | ||
|
|
edb4fc96e1 | ||
|
|
af9f8b73ba | ||
|
|
c85152e85a | ||
|
|
2ee2440c68 | ||
|
|
ecfafc9723 | ||
|
|
dbb4414e65 | ||
|
|
a028e93881 | ||
|
|
475cb5176d | ||
|
|
8b07bd80e6 | ||
|
|
50d26d932f | ||
|
|
22b5ab1179 | ||
|
|
f7c76fb261 | ||
|
|
6531f686ad | ||
|
|
b716f05fb4 | ||
|
|
9a98f1c859 | ||
|
|
e92fc4cfd1 | ||
|
|
da1a76cbef | ||
|
|
fa6b7c21ac | ||
|
|
11748fd33b | ||
|
|
267bbe3865 | ||
|
|
dd27e4b076 | ||
|
|
459229ba15 | ||
|
|
94c5161fde | ||
|
|
5646d1404c | ||
|
|
ef8a10b68d | ||
|
|
c772696f3e | ||
|
|
45faf4e9dd | ||
|
|
5cbca9232c | ||
|
|
742bb6d86d | ||
|
|
b14accd83e | ||
|
|
8ae01d8d36 | ||
|
|
5db1e58e6a | ||
|
|
a2e6d2f280 | ||
|
|
83f3d224ed | ||
|
|
73693620df | ||
|
|
72eb67dfda | ||
|
|
c55b4a02c8 | ||
|
|
721efd6a16 | ||
|
|
61c8ce4b6f | ||
|
|
ce95ca6905 | ||
|
|
01dee5fe1f | ||
|
|
1a72edee9a | ||
|
|
27b6ad0280 | ||
|
|
ae9e6921c3 | ||
|
|
b51eb99027 | ||
|
|
2e584c540d | ||
|
|
bbf258e1a7 | ||
|
|
53d57716aa | ||
|
|
e9a6e5477d | ||
|
|
46ca8a6b44 | ||
|
|
d6f88caf3d | ||
|
|
abc85902a2 | ||
|
|
9edc8bbea2 | ||
|
|
443d3efd37 | ||
|
|
948bcde358 | ||
|
|
83aa3cfca6 | ||
|
|
976c88ed44 | ||
|
|
0db16797b5 | ||
|
|
b7802fc898 | ||
|
|
741dffd5db | ||
|
|
2c9f11bcfe | ||
|
|
16893e51e6 | ||
|
|
34a43a6af9 | ||
|
|
4dd5d946d9 | ||
|
|
7e63f686b9 | ||
|
|
7b57972179 | ||
|
|
a758a36bdc | ||
|
|
84123c603d | ||
|
|
33f9c09a07 |
@@ -1,5 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: midoks
|
||||
|
||||
custom: https://afdian.net/a/mdserver-web
|
||||
@@ -1,29 +0,0 @@
|
||||
---
|
||||
name: BUG提交
|
||||
about: 问题描述
|
||||
---
|
||||
|
||||
## 什么系统 ?
|
||||
|
||||
Debian x, Centos x, Centos x stream, Ubuntu x?
|
||||
|
||||
## 错误信息 ?
|
||||
|
||||
Ex:
|
||||
```bash
|
||||
一个issue,一个问题。多余问题,视情况而答。
|
||||
```
|
||||
|
||||
## 错误截图 ?
|
||||
|
||||
...
|
||||
|
||||
|
||||
## 浏览器版本 ?
|
||||
|
||||
...
|
||||
|
||||
|
||||
## 软件版本(插件/面板) ?
|
||||
|
||||
...
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
name: 需求提交
|
||||
about: 需求描述
|
||||
---
|
||||
|
||||
## 需求
|
||||
|
||||
想开发一个什么插件?
|
||||
想有什么功能?
|
||||
|
||||
|
||||
## 提供参考
|
||||
|
||||
给开发者提供参考!
|
||||
@@ -1,24 +0,0 @@
|
||||
name: Bug提交
|
||||
description: 提交错误报告以帮助我们改进
|
||||
labels: ["\U0001F48A bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您花时间填写此错误报告!
|
||||
|
||||
- 如有疑问,请讨论[Discussions](https://github.com/midoks/mdserver-web/discussions).
|
||||
- 检查以确保尚未有人打开类似的[issue](https://github.com/midoks/mdserver-web/issues).
|
||||
- type: input
|
||||
attributes:
|
||||
label: 操作系统
|
||||
description: |
|
||||
请指定您报告的确切操作系统名称和版本,例如"CentOS 7"、"Ubuntu 20.04"。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 描述错误
|
||||
description: 对bug的清晰而简洁的描述。
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,8 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 提出问题
|
||||
url: https://github.com/midoks/mdserver-web/discussions
|
||||
about: 请在讨论中提出问题。
|
||||
- name: 提出建议
|
||||
url: https://github.com/midoks/mdserver-web/discussions/categories/proposal
|
||||
about: 请在讨论中提出建议。
|
||||
@@ -1,24 +0,0 @@
|
||||
name: Bug提交
|
||||
description: 提交错误报告以帮助我们改进
|
||||
labels: ["\U0001F48A bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您花时间填写此错误报告!
|
||||
|
||||
- 如有疑问,请讨论[Discussions](https://github.com/midoks/mdserver-web/discussions).
|
||||
- 检查以确保尚未有人打开类似的[issue](https://github.com/midoks/mdserver-web/issues).
|
||||
- type: input
|
||||
attributes:
|
||||
label: 操作系统
|
||||
description: |
|
||||
请指定您报告的确切操作系统名称和版本,例如"CentOS 7"、"Ubuntu 20.04"。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 描述错误
|
||||
description: 对bug的清晰而简洁的描述。
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,24 +0,0 @@
|
||||
name: Bug提交
|
||||
description: 提交错误报告以帮助我们改进
|
||||
labels: ["\U0001F48A bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您花时间填写此错误报告!
|
||||
|
||||
- 如有疑问,请讨论[Discussions](https://github.com/midoks/mdserver-web/discussions).
|
||||
- 检查以确保尚未有人打开类似的[issue](https://github.com/midoks/mdserver-web/issues).
|
||||
- type: input
|
||||
attributes:
|
||||
label: 操作系统
|
||||
description: |
|
||||
请指定您报告的确切操作系统名称和版本,例如"CentOS 7"、"Ubuntu 20.04"。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 描述错误
|
||||
description: 对bug的清晰而简洁的描述。
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,3 +0,0 @@
|
||||
### 合并描述
|
||||
|
||||
- 我添加了测试用例来覆盖新代码。
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: MW APP MySQL55
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "run_test" ]
|
||||
pull_request:
|
||||
branches: [ "run_test" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-22.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
#runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install MW
|
||||
run: |
|
||||
sudo bash scripts/install_dev.sh
|
||||
- name: Install MySQL55
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/mysql && sudo bash install.sh install 5.5
|
||||
- name: Start DEBUG
|
||||
run: |
|
||||
gunicorn -c setting.py app:app
|
||||
python3 task.py &
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: MW APP MySQL56
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "run_test" ]
|
||||
pull_request:
|
||||
branches: [ "run_test" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-22.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
#runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install MW
|
||||
run: |
|
||||
sudo bash scripts/install_dev.sh
|
||||
- name: Install MySQL56
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/mysql && sudo bash install.sh install 5.6
|
||||
- name: Start DEBUG
|
||||
run: |
|
||||
gunicorn -c setting.py app:app
|
||||
python3 task.py &
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: MW APP MySQL57
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "run_test" ]
|
||||
pull_request:
|
||||
branches: [ "run_test" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-22.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
#runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install MW
|
||||
run: |
|
||||
sudo bash scripts/install_dev.sh
|
||||
- name: Install MySQL57
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/mysql && sudo bash install.sh install 5.7
|
||||
- name: Start DEBUG
|
||||
run: |
|
||||
gunicorn -c setting.py app:app
|
||||
python3 task.py &
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: MW APP MySQL80
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "run_test" ]
|
||||
pull_request:
|
||||
branches: [ "run_test" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-22.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
#runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install MW
|
||||
run: |
|
||||
sudo bash scripts/install_dev.sh
|
||||
- name: Install MySQL80
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/mysql && sudo bash install.sh install 8.0
|
||||
- name: Start DEBUG
|
||||
run: |
|
||||
gunicorn -c setting.py app:app
|
||||
python3 task.py &
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: MW APP OpenResty
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "dev" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
#runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install MW
|
||||
run: |
|
||||
sudo bash scripts/install_dev.sh
|
||||
- name: Install OpenResty
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/openresty && sudo bash install.sh install 1.21.4.1
|
||||
- name: Start DEBUG
|
||||
run: |
|
||||
gunicorn -c setting.py app:app
|
||||
python3 task.py &
|
||||
@@ -1,68 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: MW APP PHP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "run_test" ]
|
||||
pull_request:
|
||||
branches: [ "run_test" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
#runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install MW
|
||||
run: |
|
||||
sudo bash scripts/install_dev.sh
|
||||
- name: Install PHP53
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 53
|
||||
- name: Install PHP54
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 54
|
||||
- name: Install PHP55
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 55
|
||||
- name: Install PHP56
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 56
|
||||
- name: Install PHP70
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 70
|
||||
- name: Install PHP71
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 71
|
||||
- name: Install PHP72
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 72
|
||||
- name: Install PHP73
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 73
|
||||
- name: Install PHP74
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 74
|
||||
- name: Install PHP80
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 80
|
||||
- name: Install PHP81
|
||||
run: |
|
||||
cd /www/server/mdserver-web/plugins/php && sudo bash install.sh install 81
|
||||
- name: Start DEBUG
|
||||
run: |
|
||||
gunicorn -c setting.py app:app
|
||||
python3 task.py &
|
||||
@@ -8,6 +8,7 @@ __pycache__/
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
@@ -104,79 +105,13 @@ venv.bak/
|
||||
.DS_Store
|
||||
.idea/*.xml
|
||||
.idea/*.iml
|
||||
tmp/*
|
||||
tmp/*.pl
|
||||
tmp/*.log
|
||||
*.swp
|
||||
*.pem
|
||||
*.zip
|
||||
scripts/init.d/mw
|
||||
logs/*
|
||||
data/*.db
|
||||
data/control.conf
|
||||
data/iplist.txt
|
||||
data/json/index.json
|
||||
data/json/config.json
|
||||
data/site.pl
|
||||
data/admin_path.pl
|
||||
data/close.pl
|
||||
data/datadir.pl
|
||||
data/502Task.pl
|
||||
data/default.pl
|
||||
data/backup.pl
|
||||
data/debug.pl
|
||||
data/default_site.pl
|
||||
|
||||
ssl/input.pl
|
||||
|
||||
lib/python*
|
||||
|
||||
bin
|
||||
pyvenv.cfg
|
||||
include
|
||||
share
|
||||
pip-selfcheck.json
|
||||
|
||||
scripts/init.d/mw
|
||||
scripts/mdserver-web
|
||||
|
||||
data/api_login.txt
|
||||
data/sessions
|
||||
data/ssl.pl
|
||||
data/port.pl
|
||||
data/ipv6.pl
|
||||
data/restart.pl
|
||||
data/ssl.pl
|
||||
data/edate.pl
|
||||
data/osname.pl
|
||||
data/only_netio_counters.pl
|
||||
data/system.db-journal
|
||||
data/hook_*.json
|
||||
data/letsencrypt.json
|
||||
data/basic_auth.json
|
||||
data/notify.json
|
||||
data/api.json
|
||||
data/bind_domain.pl
|
||||
data/unauthorized_status.pl
|
||||
|
||||
plugins/vip_*
|
||||
plugins/own_*
|
||||
plugins/my_*
|
||||
plugins/l2tp
|
||||
plugins/openlitespeed
|
||||
plugins/system_safe
|
||||
plugins/tamper_proof
|
||||
plugins/tamper_proof_*
|
||||
plugins/cryptocurrency_trade
|
||||
plugins/op_load_balance
|
||||
plugins/gdrive
|
||||
plugins/mtproxy
|
||||
plugins/zimg
|
||||
plugins/bk_demo
|
||||
plugins/mail
|
||||
plugins/fastdfs
|
||||
plugins/v2ray
|
||||
plugins/frp
|
||||
plugins/file_search
|
||||
debug.out
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,7 @@
|
||||
# mdserver-web
|
||||
简单的Linux面板
|
||||
|
||||
### 自动安装
|
||||
```
|
||||
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | sh
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import config
|
||||
|
||||
app = config.config().makeApp(__name__)
|
||||
|
||||
try:
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
except Exception as ex:
|
||||
print ex
|
||||
@@ -0,0 +1,114 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf8')
|
||||
|
||||
from flask import Flask, session
|
||||
from datetime import timedelta
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import db
|
||||
import public
|
||||
|
||||
|
||||
class middleWare:
|
||||
|
||||
def __init__(self, wsgi_app):
|
||||
self.wsgi_app = wsgi_app
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.wsgi_app(*args, **kwargs)
|
||||
|
||||
|
||||
class config:
|
||||
__version = '0.0.1'
|
||||
__app = None
|
||||
__modules = None
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def makeApp(self, name):
|
||||
app = Flask(name)
|
||||
self.__app = app
|
||||
|
||||
app.config.version = self.__version
|
||||
app.config['SECRET_KEY'] = os.urandom(24)
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
|
||||
|
||||
self.initDB()
|
||||
self.initInitD()
|
||||
self.initRoute()
|
||||
# self.startDebug()
|
||||
app.wsgi_app = middleWare(app.wsgi_app)
|
||||
return app
|
||||
|
||||
def startDebug(self):
|
||||
self.__app.debug = True
|
||||
self.__app.config.version = self.__version + str(time.time())
|
||||
|
||||
def initDB(self):
|
||||
try:
|
||||
sql = db.Sql().dbfile('default')
|
||||
csql = public.readFile('data/sql/default.sql')
|
||||
csql_list = csql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
sql.execute(csql_list[index], ())
|
||||
except Exception, ex:
|
||||
print str(ex)
|
||||
|
||||
def initUser(self):
|
||||
pass
|
||||
|
||||
def initInitD(self):
|
||||
script = public.getRunDir() + '/scripts/init.d/mw.tpl'
|
||||
script_bin = public.getRunDir() + '/scripts/init.d/mw'
|
||||
if os.path.exists(script_bin):
|
||||
return
|
||||
|
||||
content = public.readFile(script)
|
||||
content = content.replace("{$SERVER_PATH}", public.getRunDir())
|
||||
|
||||
public.writeFile(script_bin, content)
|
||||
public.execShell('chmod +x ' + script_bin)
|
||||
|
||||
if public.getOs() != 'darwin':
|
||||
initd_bin = '/etc/init.d/mw'
|
||||
if not os.path.exists(initd_bin):
|
||||
shutil.copyfile(script_bin, initd_bin)
|
||||
public.execShell('chmod +x ' + initd_bin)
|
||||
|
||||
def getVersion(self):
|
||||
return self.__version
|
||||
|
||||
def getApp(self):
|
||||
return self.__app
|
||||
|
||||
def initRoute(self):
|
||||
import route
|
||||
DEFAULT_MODULES = (
|
||||
(route.dashboard, "/"),
|
||||
(route.site, "/site"),
|
||||
(route.files, "/files"),
|
||||
(route.soft, "/soft"),
|
||||
(route.config, "/config"),
|
||||
(route.plugins, "/plugins"),
|
||||
(route.task, "/task"),
|
||||
(route.system, "/system"),
|
||||
(route.database, "/database"),
|
||||
(route.crontab, "/crontab"),
|
||||
(route.firewall, "/firewall"),
|
||||
(route.control, "/control")
|
||||
)
|
||||
self.modules = DEFAULT_MODULES
|
||||
self.settingModules(self.__app, DEFAULT_MODULES)
|
||||
|
||||
def settingModules(self, app, modules):
|
||||
for module, url_prefix in modules:
|
||||
app.register_blueprint(module, url_prefix=url_prefix)
|
||||
@@ -0,0 +1,276 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
|
||||
|
||||
class Sql():
|
||||
#------------------------------
|
||||
# 数据库操作类 For sqlite3
|
||||
#------------------------------
|
||||
__DB_FILE = None # 数据库文件
|
||||
__DB_CONN = None # 数据库连接对象
|
||||
__DB_TABLE = "" # 被操作的表名称
|
||||
__OPT_WHERE = "" # where条件
|
||||
__OPT_LIMIT = "" # limit条件
|
||||
__OPT_ORDER = "" # order条件
|
||||
__OPT_FIELD = "*" # field条件
|
||||
__OPT_PARAM = () # where值
|
||||
|
||||
def __init__(self):
|
||||
self.__DB_FILE = 'data/default.db'
|
||||
|
||||
def __GetConn(self):
|
||||
# 取数据库对象
|
||||
try:
|
||||
if self.__DB_CONN == None:
|
||||
self.__DB_CONN = sqlite3.connect(self.__DB_FILE)
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def dbfile(self, name):
|
||||
self.__DB_FILE = 'data/' + name + '.db'
|
||||
return self
|
||||
|
||||
def table(self, table):
|
||||
# 设置表名
|
||||
self.__DB_TABLE = table
|
||||
return self
|
||||
|
||||
def where(self, where, param):
|
||||
# WHERE条件
|
||||
if where:
|
||||
self.__OPT_WHERE = " WHERE " + where
|
||||
self.__OPT_PARAM = param
|
||||
return self
|
||||
|
||||
def order(self, order):
|
||||
# ORDER条件
|
||||
if len(order):
|
||||
self.__OPT_ORDER = " ORDER BY " + order
|
||||
return self
|
||||
|
||||
def limit(self, limit):
|
||||
# LIMIT条件
|
||||
if len(limit):
|
||||
self.__OPT_LIMIT = " LIMIT " + limit
|
||||
return self
|
||||
|
||||
def field(self, field):
|
||||
# FIELD条件
|
||||
if len(field):
|
||||
self.__OPT_FIELD = field
|
||||
return self
|
||||
|
||||
def select(self):
|
||||
# 查询数据集
|
||||
self.__GetConn()
|
||||
try:
|
||||
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \
|
||||
self.__OPT_WHERE + self.__OPT_ORDER + self.__OPT_LIMIT
|
||||
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
|
||||
data = result.fetchall()
|
||||
# 构造字曲系列
|
||||
if self.__OPT_FIELD != "*":
|
||||
field = self.__OPT_FIELD.split(',')
|
||||
tmp = []
|
||||
for row in data:
|
||||
i = 0
|
||||
tmp1 = {}
|
||||
for key in field:
|
||||
tmp1[key] = row[i]
|
||||
i += 1
|
||||
tmp.append(tmp1)
|
||||
del(tmp1)
|
||||
data = tmp
|
||||
del(tmp)
|
||||
else:
|
||||
# 将元组转换成列表
|
||||
tmp = map(list, data)
|
||||
data = tmp
|
||||
del(tmp)
|
||||
self.__close()
|
||||
return data
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def getField(self, keyName):
|
||||
# 取回指定字段
|
||||
result = self.field(keyName).select()
|
||||
if len(result) == 1:
|
||||
return result[0][keyName]
|
||||
return result
|
||||
|
||||
def setField(self, keyName, keyValue):
|
||||
# 更新指定字段
|
||||
return self.save(keyName, (keyValue,))
|
||||
|
||||
def find(self):
|
||||
# 取一行数据
|
||||
result = self.limit("1").select()
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
return result
|
||||
|
||||
def count(self):
|
||||
# 取行数
|
||||
key = "COUNT(*)"
|
||||
data = self.field(key).select()
|
||||
try:
|
||||
return int(data[0][key])
|
||||
except:
|
||||
return 0
|
||||
|
||||
def add(self, keys, param):
|
||||
# 插入数据
|
||||
self.__GetConn()
|
||||
self.__DB_CONN.text_factory = str
|
||||
try:
|
||||
values = ""
|
||||
for key in keys.split(','):
|
||||
values += "?,"
|
||||
values = self.checkInput(values[0:len(values) - 1])
|
||||
sql = "INSERT INTO " + self.__DB_TABLE + \
|
||||
"(" + keys + ") " + "VALUES(" + values + ")"
|
||||
result = self.__DB_CONN.execute(sql, param)
|
||||
id = result.lastrowid
|
||||
self.__close()
|
||||
self.__DB_CONN.commit()
|
||||
return id
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def checkInput(self, data):
|
||||
if not data:
|
||||
return data
|
||||
if type(data) != str:
|
||||
return data
|
||||
checkList = [
|
||||
{'d': '<', 'r': '<'},
|
||||
{'d': '>', 'r': '>'},
|
||||
{'d': '\'', 'r': '‘'},
|
||||
{'d': '"', 'r': '“'},
|
||||
{'d': '&', 'r': '&'},
|
||||
{'d': '#', 'r': '#'},
|
||||
{'d': '<', 'r': '<'}
|
||||
]
|
||||
for v in checkList:
|
||||
data = data.replace(v['d'], v['r'])
|
||||
return data
|
||||
|
||||
def addAll(self, keys, param):
|
||||
# 插入数据
|
||||
self.__GetConn()
|
||||
self.__DB_CONN.text_factory = str
|
||||
try:
|
||||
values = ""
|
||||
for key in keys.split(','):
|
||||
values += "?,"
|
||||
values = values[0:len(values) - 1]
|
||||
sql = "INSERT INTO " + self.__DB_TABLE + \
|
||||
"(" + keys + ") " + "VALUES(" + values + ")"
|
||||
result = self.__DB_CONN.execute(sql, param)
|
||||
return True
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def commit(self):
|
||||
self.__close()
|
||||
self.__DB_CONN.commit()
|
||||
|
||||
def save(self, keys, param):
|
||||
# 更新数据
|
||||
self.__GetConn()
|
||||
self.__DB_CONN.text_factory = str
|
||||
try:
|
||||
opt = ""
|
||||
for key in keys.split(','):
|
||||
opt += key + "=?,"
|
||||
opt = opt[0:len(opt) - 1]
|
||||
sql = "UPDATE " + self.__DB_TABLE + " SET " + opt + self.__OPT_WHERE
|
||||
|
||||
import public
|
||||
public.writeFile('/tmp/test.pl', sql)
|
||||
|
||||
# 处理拼接WHERE与UPDATE参数
|
||||
tmp = list(param)
|
||||
for arg in self.__OPT_PARAM:
|
||||
tmp.append(arg)
|
||||
self.__OPT_PARAM = tuple(tmp)
|
||||
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
|
||||
self.__close()
|
||||
self.__DB_CONN.commit()
|
||||
return result.rowcount
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def delete(self, id=None):
|
||||
# 删除数据
|
||||
self.__GetConn()
|
||||
try:
|
||||
if id:
|
||||
self.__OPT_WHERE = " WHERE id=?"
|
||||
self.__OPT_PARAM = (id,)
|
||||
sql = "DELETE FROM " + self.__DB_TABLE + self.__OPT_WHERE
|
||||
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
|
||||
self.__close()
|
||||
self.__DB_CONN.commit()
|
||||
return result.rowcount
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def execute(self, sql, param):
|
||||
# 执行SQL语句返回受影响行
|
||||
self.__GetConn()
|
||||
try:
|
||||
result = self.__DB_CONN.execute(sql, param)
|
||||
self.__DB_CONN.commit()
|
||||
return result.rowcount
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def query(self, sql, param):
|
||||
# 执行SQL语句返回数据集
|
||||
self.__GetConn()
|
||||
try:
|
||||
result = self.__DB_CONN.execute(sql, param)
|
||||
# 将元组转换成列表
|
||||
data = map(list, result)
|
||||
return data
|
||||
except Exception, ex:
|
||||
return "error: " + str(ex)
|
||||
|
||||
def create(self, name):
|
||||
# 创建数据表
|
||||
self.__GetConn()
|
||||
import public
|
||||
script = public.readFile('data/' + name + '.sql')
|
||||
result = self.__DB_CONN.executescript(script)
|
||||
self.__DB_CONN.commit()
|
||||
return result.rowcount
|
||||
|
||||
def fofile(self, filename):
|
||||
# 执行脚本
|
||||
self.__GetConn()
|
||||
import public
|
||||
script = public.readFile(filename)
|
||||
result = self.__DB_CONN.executescript(script)
|
||||
self.__DB_CONN.commit()
|
||||
return result.rowcount
|
||||
|
||||
def __close(self):
|
||||
# 清理条件属性
|
||||
self.__OPT_WHERE = ""
|
||||
self.__OPT_FIELD = "*"
|
||||
self.__OPT_ORDER = ""
|
||||
self.__OPT_LIMIT = ""
|
||||
self.__OPT_PARAM = ()
|
||||
|
||||
def close(self):
|
||||
# 释放资源
|
||||
try:
|
||||
self.__DB_CONN.close()
|
||||
self.__DB_CONN = None
|
||||
except:
|
||||
pass
|
||||
@@ -0,0 +1,250 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
|
||||
class file_api:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def setFileAccept(self, filename):
|
||||
auth = 'www:www'
|
||||
if public.getOs() == 'darwin':
|
||||
user = public.execShell(
|
||||
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
|
||||
auth = user + ':staff'
|
||||
os.system('chown -R ' + auth + ' ' + filename)
|
||||
os.system('chmod -R 755 ' + filename)
|
||||
|
||||
# 移动到回收站
|
||||
def mvRecycleBin(self, path):
|
||||
rPath = public.getRootDir() + '/recycle_bin/'
|
||||
if not os.path.exists(rPath):
|
||||
os.system('mkdir -p ' + rPath)
|
||||
|
||||
rFile = rPath + path.replace('/', '_mw_') + '_t_' + str(time.time())
|
||||
try:
|
||||
import shutil
|
||||
shutil.move(path, rFile)
|
||||
public.writeLog('TYPE_FILE', public.getInfo(
|
||||
'移动文件[{1}]到回收站成功!', (path)))
|
||||
return True
|
||||
except:
|
||||
public.writeLog('TYPE_FILE', public.getInfo(
|
||||
'移动文件[{1}]到回收站失败!', (path)))
|
||||
return False
|
||||
|
||||
def getBody(self, path):
|
||||
if not os.path.exists(path):
|
||||
return public.returnJson(False, '文件不存在', (path,))
|
||||
|
||||
if os.path.getsize(path) > 2097152:
|
||||
return public.returnJson(False, u'不能在线编辑大于2MB的文件!')
|
||||
|
||||
fp = open(path, 'rb')
|
||||
data = {}
|
||||
data['status'] = True
|
||||
try:
|
||||
if fp:
|
||||
from chardet.universaldetector import UniversalDetector
|
||||
detector = UniversalDetector()
|
||||
srcBody = b""
|
||||
for line in fp.readlines():
|
||||
detector.feed(line)
|
||||
srcBody += line
|
||||
detector.close()
|
||||
char = detector.result
|
||||
data['encoding'] = char['encoding']
|
||||
if char['encoding'] == 'GB2312' or not char['encoding'] or char[
|
||||
'encoding'] == 'TIS-620' or char['encoding'] == 'ISO-8859-9':
|
||||
data['encoding'] = 'GBK'
|
||||
if char['encoding'] == 'ascii' or char[
|
||||
'encoding'] == 'ISO-8859-1':
|
||||
data['encoding'] = 'utf-8'
|
||||
if char['encoding'] == 'Big5':
|
||||
data['encoding'] = 'BIG5'
|
||||
if not char['encoding'] in ['GBK', 'utf-8',
|
||||
'BIG5']:
|
||||
data['encoding'] = 'utf-8'
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
data['data'] = srcBody.decode(
|
||||
data['encoding']).encode('utf-8', errors='ignore')
|
||||
else:
|
||||
data['data'] = srcBody.decode(data['encoding'])
|
||||
except:
|
||||
data['encoding'] = char['encoding']
|
||||
if sys.version_info[0] == 2:
|
||||
data['data'] = srcBody.decode(
|
||||
data['encoding']).encode('utf-8', errors='ignore')
|
||||
else:
|
||||
data['data'] = srcBody.decode(data['encoding'])
|
||||
else:
|
||||
if sys.version_info[0] == 2:
|
||||
data['data'] = srcBody.decode('utf-8').encode('utf-8')
|
||||
else:
|
||||
data['data'] = srcBody.decode('utf-8')
|
||||
data['encoding'] = u'utf-8'
|
||||
|
||||
return public.returnJson(True, 'OK', data)
|
||||
except Exception as ex:
|
||||
return public.returnJson(False, u'文件编码不被兼容,无法正确读取文件!' + str(ex))
|
||||
|
||||
def saveBody(self, path, data, encoding='utf-8'):
|
||||
if not os.path.exists(path):
|
||||
return public.returnJson(False, '文件不存在')
|
||||
try:
|
||||
if encoding == 'ascii':
|
||||
encoding = 'utf-8'
|
||||
if sys.version_info[0] == 2:
|
||||
data = data.encode(encoding, errors='ignore')
|
||||
fp = open(path, 'w+')
|
||||
else:
|
||||
data = data.encode(
|
||||
encoding, errors='ignore').decode(encoding)
|
||||
fp = open(path, 'w+', encoding=encoding)
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
|
||||
public.writeLog('TYPE_FILE', '文件保存成功', (path,))
|
||||
return public.returnJson(True, '文件保存成功')
|
||||
except Exception as ex:
|
||||
return public.returnJson(False, 'FILE_SAVE_ERR:' + str(ex))
|
||||
|
||||
def zip(self, sfile, dfile, stype, path):
|
||||
if sfile.find(',') == -1:
|
||||
if not os.path.exists(path + '/' + sfile):
|
||||
return public.returnMsg(False, '指定文件不存在!')
|
||||
|
||||
try:
|
||||
tmps = public.getRunDir() + '/tmp/panelExec.log'
|
||||
if stype == 'zip':
|
||||
os.system("cd '" + path + "' && zip '" + dfile +
|
||||
"' -r '" + sfile + "' > " + tmps + " 2>&1")
|
||||
else:
|
||||
sfiles = ''
|
||||
for sfile in sfile.split(','):
|
||||
if not sfile:
|
||||
continue
|
||||
sfiles += " '" + sfile + "'"
|
||||
os.system("cd '" + path + "' && tar -zcvf '" +
|
||||
dfile + "' " + sfiles + " > " + tmps + " 2>&1")
|
||||
self.setFileAccept(dfile)
|
||||
public.writeLog("TYPE_FILE", '文件压缩成功!', (sfile, dfile))
|
||||
return public.returnJson(True, '文件压缩成功!')
|
||||
except:
|
||||
return public.returnJson(False, '文件压缩失败!')
|
||||
|
||||
def delete(self, path):
|
||||
|
||||
if not os.path.exists(path):
|
||||
return public.returnJson(False, '指定文件不存在!')
|
||||
|
||||
# 检查是否为.user.ini
|
||||
if path.find('.user.ini') >= 0:
|
||||
os.system("chattr -i '" + path + "'")
|
||||
|
||||
try:
|
||||
if os.path.exists('data/recycle_bin.pl'):
|
||||
if self.mvRecycleBin(path):
|
||||
return public.returnJson(True, '已将文件移动到回收站!')
|
||||
os.remove(path)
|
||||
public.writeLog('TYPE_FILE', public.getInfo(
|
||||
'删除文件[{1}]成功!', (path)))
|
||||
return public.returnJson(True, '删除文件成功!')
|
||||
except:
|
||||
return public.returnJson(False, '删除文件失败!')
|
||||
|
||||
def getAccess(self, filename):
|
||||
data = {}
|
||||
try:
|
||||
stat = os.stat(filename)
|
||||
data['chmod'] = str(oct(stat.st_mode)[-3:])
|
||||
data['chown'] = pwd.getpwuid(stat.st_uid).pw_name
|
||||
except:
|
||||
data['chmod'] = 755
|
||||
data['chown'] = 'www'
|
||||
return data
|
||||
|
||||
# 计算文件数量
|
||||
def getCount(self, path, search):
|
||||
i = 0
|
||||
for name in os.listdir(path):
|
||||
if search:
|
||||
if name.lower().find(search) == -1:
|
||||
continue
|
||||
# if name[0:1] == '.':
|
||||
# continue
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def getDir(self, path, page=1, page_size=10, search=None):
|
||||
data = {}
|
||||
dirnames = []
|
||||
filenames = []
|
||||
|
||||
info = {}
|
||||
info['count'] = self.getCount(path, search)
|
||||
info['row'] = page_size
|
||||
info['p'] = page
|
||||
info['tojs'] = 'getFiles'
|
||||
pageObj = public.getPageObject(info, '1,2,3,4,5,6,7,8')
|
||||
data['PAGE'] = pageObj[0]
|
||||
|
||||
i = 0
|
||||
n = 0
|
||||
for filename in os.listdir(path):
|
||||
if search:
|
||||
if filename.lower().find(search) == -1:
|
||||
continue
|
||||
i += 1
|
||||
if n >= pageObj[1].ROW:
|
||||
break
|
||||
if i < pageObj[1].SHIFT:
|
||||
continue
|
||||
|
||||
try:
|
||||
filePath = (path + '/' + filename).encode('utf8')
|
||||
link = ''
|
||||
if os.path.islink(filePath):
|
||||
filePath = os.readlink(filePath)
|
||||
link = ' -> ' + filePath
|
||||
if not os.path.exists(filePath):
|
||||
filePath = path + '/' + filePath
|
||||
if not os.path.exists(filePath):
|
||||
continue
|
||||
|
||||
stat = os.stat(filePath)
|
||||
accept = str(oct(stat.st_mode)[-3:])
|
||||
mtime = str(int(stat.st_mtime))
|
||||
user = ''
|
||||
try:
|
||||
user = pwd.getpwuid(stat.st_uid).pw_name
|
||||
except:
|
||||
user = str(stat.st_uid)
|
||||
size = str(stat.st_size)
|
||||
if os.path.isdir(filePath):
|
||||
dirnames.append(filename + ';' + size + ';' +
|
||||
mtime + ';' + accept + ';' + user + ';' + link)
|
||||
else:
|
||||
filenames.append(filename + ';' + size + ';' +
|
||||
mtime + ';' + accept + ';' + user + ';' + link)
|
||||
n += 1
|
||||
except:
|
||||
continue
|
||||
|
||||
data['DIR'] = sorted(dirnames)
|
||||
data['FILES'] = sorted(filenames)
|
||||
if path[0:2] == '//':
|
||||
data['PATH'] = path[1:]
|
||||
else:
|
||||
data['PATH'] = path
|
||||
return public.getJson(data)
|
||||
@@ -0,0 +1,56 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
|
||||
class firewall_api:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def getList(self, page, limit):
|
||||
|
||||
start = (page - 1) * limit
|
||||
|
||||
_list = public.M('firewall').field('id,port,ps,addtime').limit(
|
||||
str(start) + ',' + str(limit)).order('id desc').select()
|
||||
data = {}
|
||||
data['data'] = _list
|
||||
|
||||
count = public.M('firewall').count()
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['tojs'] = 'showAccept'
|
||||
_page['p'] = page
|
||||
|
||||
data['page'] = public.getPage(_page)
|
||||
return public.getJson(data)
|
||||
|
||||
def getLogList(self, page, limit, search=''):
|
||||
find_search = ''
|
||||
if search != '':
|
||||
find_search = "type like '%" + search + "%' or log like '%" + \
|
||||
search + "%' or addtime like '%" + search + "%'"
|
||||
|
||||
start = (page - 1) * limit
|
||||
|
||||
_list = public.M('logs').where(find_search, ()).field(
|
||||
'id,type,log,addtime').limit(str(start) + ',' + str(limit)).order('id desc').select()
|
||||
data = {}
|
||||
data['data'] = _list
|
||||
|
||||
count = public.M('logs').where(find_search, ()).count()
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['tojs'] = 'getLogs'
|
||||
_page['p'] = page
|
||||
|
||||
data['page'] = public.getPage(_page)
|
||||
return public.getJson(data)
|
||||
@@ -0,0 +1,222 @@
|
||||
# coding: utf-8
|
||||
|
||||
import math
|
||||
import string
|
||||
import public
|
||||
|
||||
|
||||
class Page():
|
||||
#--------------------------
|
||||
# 分页类 - JS回调版
|
||||
#--------------------------
|
||||
__PREV = '上一页'
|
||||
__NEXT = '下一页'
|
||||
__START = '首页'
|
||||
__END = '尾页'
|
||||
__COUNT_START = '共'
|
||||
__COUNT_END = '条数据'
|
||||
__FO = '从'
|
||||
__LINE = '条'
|
||||
__LIST_NUM = 4
|
||||
SHIFT = None # 偏移量
|
||||
ROW = None # 每页行数
|
||||
__C_PAGE = None # 当前页
|
||||
__COUNT_PAGE = None # 总页数
|
||||
__COUNT_ROW = None # 总行数
|
||||
__URI = None # URI
|
||||
__RTURN_JS = False # 是否返回JS回调
|
||||
__START_NUM = None # 起始行
|
||||
__END_NUM = None # 结束行
|
||||
|
||||
def __init__(self):
|
||||
tmp = public.getMsg('PAGE')
|
||||
if tmp:
|
||||
self.__PREV = tmp['PREV']
|
||||
self.__NEXT = tmp['NEXT']
|
||||
self.__START = tmp['START']
|
||||
self.__END = tmp['END']
|
||||
self.__COUNT_START = tmp['COUNT_START']
|
||||
self.__COUNT_END = tmp['COUNT_END']
|
||||
self.__FO = tmp['FO']
|
||||
self.__LINE = tmp['LINE']
|
||||
|
||||
def GetPage(self, pageInfo, limit='1,2,3,4,5,6,7,8'):
|
||||
# 取分页信息
|
||||
# @param pageInfo 传入分页参数字典
|
||||
# @param limit 返回系列
|
||||
self.__RTURN_JS = pageInfo['return_js']
|
||||
self.__COUNT_ROW = pageInfo['count']
|
||||
self.ROW = pageInfo['row']
|
||||
self.__C_PAGE = self.__GetCpage(pageInfo['p'])
|
||||
self.__START_NUM = self.__StartRow()
|
||||
self.__END_NUM = self.__EndRow()
|
||||
self.__COUNT_PAGE = self.__GetCountPage()
|
||||
self.__URI = self.__SetUri(pageInfo['uri'])
|
||||
self.SHIFT = self.__START_NUM - 1
|
||||
|
||||
keys = limit.split(',')
|
||||
|
||||
pages = {}
|
||||
# 起始页
|
||||
pages['1'] = self.__GetStart()
|
||||
# 上一页
|
||||
pages['2'] = self.__GetPrev()
|
||||
# 分页
|
||||
pages['3'] = self.__GetPages()
|
||||
# 下一页
|
||||
pages['4'] = self.__GetNext()
|
||||
# 尾页
|
||||
pages['5'] = self.__GetEnd()
|
||||
|
||||
# 当前显示页与总页数
|
||||
pages['6'] = "<span class='Pnumber'>" + \
|
||||
bytes(self.__C_PAGE) + "/" + bytes(self.__COUNT_PAGE) + "</span>"
|
||||
# 本页显示开始与结束行
|
||||
pages['7'] = "<span class='Pline'>" + self.__FO + \
|
||||
bytes(self.__START_NUM) + "-" + \
|
||||
bytes(self.__END_NUM) + self.__LINE + "</span>"
|
||||
# 行数
|
||||
pages['8'] = "<span class='Pcount'>" + self.__COUNT_START + \
|
||||
bytes(self.__COUNT_ROW) + self.__COUNT_END + "</span>"
|
||||
|
||||
# 构造返回数据
|
||||
retuls = '<div>'
|
||||
for value in keys:
|
||||
retuls += pages[value]
|
||||
retuls += '</div>'
|
||||
|
||||
# 返回分页数据
|
||||
return retuls
|
||||
|
||||
def __GetEnd(self):
|
||||
# 构造尾页
|
||||
endStr = ""
|
||||
if self.__C_PAGE >= self.__COUNT_PAGE:
|
||||
endStr = ''
|
||||
else:
|
||||
if self.__RTURN_JS == "":
|
||||
endStr = "<a class='Pend' href='" + self.__URI + "p=" + \
|
||||
bytes(self.__COUNT_PAGE) + "'>" + self.__END + "</a>"
|
||||
else:
|
||||
endStr = "<a class='Pend' onclick='" + self.__RTURN_JS + \
|
||||
"(" + bytes(self.__COUNT_PAGE) + ")'>" + self.__END + "</a>"
|
||||
return endStr
|
||||
|
||||
def __GetNext(self):
|
||||
# 构造下一页
|
||||
nextStr = ""
|
||||
if self.__C_PAGE >= self.__COUNT_PAGE:
|
||||
nextStr = ''
|
||||
else:
|
||||
if self.__RTURN_JS == "":
|
||||
nextStr = "<a class='Pnext' href='" + self.__URI + "p=" + \
|
||||
bytes(self.__C_PAGE + 1) + "'>" + self.__NEXT + "</a>"
|
||||
else:
|
||||
nextStr = "<a class='Pnext' onclick='" + self.__RTURN_JS + \
|
||||
"(" + bytes(self.__C_PAGE + 1) + ")'>" + self.__NEXT + "</a>"
|
||||
|
||||
return nextStr
|
||||
|
||||
def __GetPages(self):
|
||||
# 构造分页
|
||||
pages = ''
|
||||
num = 0
|
||||
# 当前页之前
|
||||
if (self.__COUNT_PAGE - self.__C_PAGE) < self.__LIST_NUM:
|
||||
num = self.__LIST_NUM + \
|
||||
(self.__LIST_NUM - (self.__COUNT_PAGE - self.__C_PAGE))
|
||||
else:
|
||||
num = self.__LIST_NUM
|
||||
n = 0
|
||||
for i in range(num):
|
||||
n = num - i
|
||||
page = self.__C_PAGE - n
|
||||
if page > 0:
|
||||
if self.__RTURN_JS == "":
|
||||
pages += "<a class='Pnum' href='" + self.__URI + \
|
||||
"p=" + bytes(page) + "'>" + bytes(page) + "</a>"
|
||||
else:
|
||||
pages += "<a class='Pnum' onclick='" + self.__RTURN_JS + \
|
||||
"(" + bytes(page) + ")'>" + bytes(page) + "</a>"
|
||||
|
||||
# 当前页
|
||||
if self.__C_PAGE > 0:
|
||||
pages += "<span class='Pcurrent'>" + \
|
||||
bytes(self.__C_PAGE) + "</span>"
|
||||
|
||||
# 当前页之后
|
||||
if self.__C_PAGE <= self.__LIST_NUM:
|
||||
num = self.__LIST_NUM + (self.__LIST_NUM - self.__C_PAGE) + 1
|
||||
else:
|
||||
num = self.__LIST_NUM
|
||||
for i in range(num):
|
||||
if i == 0:
|
||||
continue
|
||||
page = self.__C_PAGE + i
|
||||
if page > self.__COUNT_PAGE:
|
||||
break
|
||||
if self.__RTURN_JS == "":
|
||||
pages += "<a class='Pnum' href='" + self.__URI + \
|
||||
"p=" + bytes(page) + "'>" + bytes(page) + "</a>"
|
||||
else:
|
||||
pages += "<a class='Pnum' onclick='" + self.__RTURN_JS + \
|
||||
"(" + bytes(page) + ")'>" + bytes(page) + "</a>"
|
||||
|
||||
return pages
|
||||
|
||||
def __GetPrev(self):
|
||||
# 构造上一页
|
||||
startStr = ''
|
||||
if self.__C_PAGE == 1:
|
||||
startStr = ''
|
||||
else:
|
||||
if self.__RTURN_JS == "":
|
||||
startStr = "<a class='Ppren' href='" + self.__URI + "p=" + \
|
||||
bytes(self.__C_PAGE - 1) + "'>" + self.__PREV + "</a>"
|
||||
else:
|
||||
startStr = "<a class='Ppren' onclick='" + self.__RTURN_JS + \
|
||||
"(" + bytes(self.__C_PAGE - 1) + ")'>" + self.__PREV + "</a>"
|
||||
return startStr
|
||||
|
||||
def __GetStart(self):
|
||||
# 构造起始分页
|
||||
startStr = ''
|
||||
if self.__C_PAGE == 1:
|
||||
startStr = ''
|
||||
else:
|
||||
if self.__RTURN_JS == "":
|
||||
startStr = "<a class='Pstart' href='" + \
|
||||
self.__URI + "p=1'>" + self.__START + "</a>"
|
||||
else:
|
||||
startStr = "<a class='Pstart' onclick='" + \
|
||||
self.__RTURN_JS + "(1)'>" + self.__START + "</a>"
|
||||
return startStr
|
||||
|
||||
def __GetCpage(self, p):
|
||||
# 取当前页
|
||||
if p:
|
||||
return p
|
||||
return 1
|
||||
|
||||
def __StartRow(self):
|
||||
# 从多少行开始
|
||||
return (self.__C_PAGE - 1) * self.ROW + 1
|
||||
|
||||
def __EndRow(self):
|
||||
# 从多少行结束
|
||||
if self.ROW > self.__COUNT_ROW:
|
||||
return self.__COUNT_ROW
|
||||
return self.__C_PAGE * self.ROW
|
||||
|
||||
def __GetCountPage(self):
|
||||
# 取总页数
|
||||
return int(math.ceil(self.__COUNT_ROW / float(self.ROW)))
|
||||
|
||||
def __SetUri(self, input):
|
||||
# 构造URI
|
||||
uri = '?'
|
||||
for key in input:
|
||||
if key == 'p':
|
||||
continue
|
||||
uri += key + '=' + input[key] + '&'
|
||||
return str(uri)
|
||||
@@ -0,0 +1,512 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
|
||||
import threading
|
||||
import multiprocessing
|
||||
|
||||
|
||||
class pa_thread(threading.Thread):
|
||||
|
||||
def __init__(self, func, args, name=''):
|
||||
threading.Thread.__init__(self)
|
||||
self.name = name
|
||||
self.func = func
|
||||
self.args = args
|
||||
self.result = self.func(*self.args)
|
||||
|
||||
def getResult(self):
|
||||
try:
|
||||
return self.result
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
class plugin_api:
|
||||
__tasks = None
|
||||
__plugin_dir = 'plugins'
|
||||
__type = 'data/json/type.json'
|
||||
__index = 'data/json/index.json'
|
||||
setupPath = None
|
||||
|
||||
def __init__(self):
|
||||
self.setupPath = 'server'
|
||||
# self.__plugin_dir = public.getRunDir() + '/plugins'
|
||||
|
||||
# 进程是否存在
|
||||
def processExists(self, pname, exe=None):
|
||||
try:
|
||||
if not self.pids:
|
||||
self.pids = psutil.pids()
|
||||
for pid in self.pids:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
if p.name() == pname:
|
||||
if not exe:
|
||||
return True
|
||||
else:
|
||||
if p.exe() == exe:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
except:
|
||||
return True
|
||||
|
||||
# 检查是否正在安装
|
||||
def checkSetupTask(self, sName):
|
||||
if not self.__tasks:
|
||||
self.__tasks = public.M('tasks').where(
|
||||
"status!=?", ('1',)).field('status,name').select()
|
||||
|
||||
if sName.find('php-') != -1:
|
||||
tmp = sName.split('-')
|
||||
sName = tmp[0]
|
||||
version = tmp[1]
|
||||
isTask = '1'
|
||||
for task in self.__tasks:
|
||||
tmpt = public.getStrBetween('[', ']', task['name'])
|
||||
if not tmpt:
|
||||
continue
|
||||
tmp1 = tmpt.split('-')
|
||||
name1 = tmp1[0].lower()
|
||||
if sName == 'php':
|
||||
if name1 == sName and tmp1[1] == version:
|
||||
isTask = task['status']
|
||||
else:
|
||||
if name1 == 'pure':
|
||||
name1 = 'pure-ftpd'
|
||||
if name1 == sName:
|
||||
isTask = task['status']
|
||||
return isTask
|
||||
|
||||
def checkStatus(self, info):
|
||||
|
||||
if not info['setup']:
|
||||
return False
|
||||
|
||||
data = self.run(info['name'], 'status', info['setup_version'])
|
||||
if data[0] == 'start':
|
||||
return True
|
||||
return False
|
||||
|
||||
def checkStatusProcess(self, info, i, return_dict):
|
||||
|
||||
if not info['setup']:
|
||||
return_dict[i] = False
|
||||
return
|
||||
|
||||
data = self.run(info['name'], 'status', info['setup_version'])
|
||||
if data[0] == 'start':
|
||||
return_dict[i] = True
|
||||
else:
|
||||
return_dict[i] = False
|
||||
|
||||
def checkStatusMProcess(self, plugins_info):
|
||||
manager = multiprocessing.Manager()
|
||||
return_dict = manager.dict()
|
||||
jobs = []
|
||||
ntmp_list = range(len(plugins_info))
|
||||
for i in ntmp_list:
|
||||
p = multiprocessing.Process(
|
||||
target=self.checkStatusProcess, args=(plugins_info[i], i, return_dict))
|
||||
jobs.append(p)
|
||||
p.start()
|
||||
|
||||
for proc in jobs:
|
||||
proc.join()
|
||||
|
||||
returnData = return_dict.values()
|
||||
for i in ntmp_list:
|
||||
plugins_info[i]['status'] = returnData[i]
|
||||
|
||||
return plugins_info
|
||||
|
||||
def checkDisplayIndex(self, name, version):
|
||||
if not os.path.exists(self.__index):
|
||||
public.writeFile(self.__index, '[]')
|
||||
|
||||
indexList = json.loads(public.readFile(self.__index))
|
||||
if type(version) == list:
|
||||
for index in range(len(version)):
|
||||
vname = name + '-' + version[index]
|
||||
if vname in indexList:
|
||||
return True
|
||||
else:
|
||||
vname = name + '-' + version
|
||||
if vname in indexList:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getVersion(self, path):
|
||||
version_f = path + '/version.pl'
|
||||
if os.path.exists(version_f):
|
||||
return public.readFile(version_f).strip()
|
||||
return ''
|
||||
|
||||
# 构造本地插件信息
|
||||
def getPluginInfo(self, info):
|
||||
checks = ''
|
||||
path = ''
|
||||
coexist = False
|
||||
|
||||
if info["checks"][0:1] == '/':
|
||||
checks = info["checks"]
|
||||
else:
|
||||
checks = public.getRootDir() + '/' + info['checks']
|
||||
|
||||
if info.has_key('path'):
|
||||
path = info['path']
|
||||
|
||||
if path[0:1] != '/':
|
||||
path = public.getRootDir() + '/' + path
|
||||
|
||||
if info.has_key('coexist') and info['coexist']:
|
||||
coexist = True
|
||||
|
||||
pluginInfo = {
|
||||
"id": 10000,
|
||||
"pid": info['pid'],
|
||||
"type": 1000,
|
||||
"name": info['name'],
|
||||
"title": info['title'],
|
||||
"ps": info['ps'],
|
||||
"dependnet": "",
|
||||
"mutex": "",
|
||||
"path": path,
|
||||
"install_checks": checks,
|
||||
"uninsatll_checks": checks,
|
||||
"coexist": coexist,
|
||||
"versions": info['versions'],
|
||||
# "updates": info['updates'],
|
||||
"display": False,
|
||||
"setup": False,
|
||||
"setup_version": "",
|
||||
"status": False,
|
||||
}
|
||||
|
||||
pluginInfo['task'] = self.checkSetupTask(pluginInfo['name'])
|
||||
|
||||
if checks.find('VERSION') > -1:
|
||||
pluginInfo['install_checks'] = checks.replace(
|
||||
'VERSION', info['versions'])
|
||||
|
||||
if path.find('VERSION') > -1:
|
||||
pluginInfo['path'] = path.replace(
|
||||
'VERSION', info['versions'])
|
||||
|
||||
pluginInfo['display'] = self.checkDisplayIndex(
|
||||
info['name'], pluginInfo['versions'])
|
||||
|
||||
pluginInfo['setup'] = os.path.exists(pluginInfo['install_checks'])
|
||||
|
||||
if coexist and pluginInfo['setup']:
|
||||
pluginInfo['setup_version'] = info['versions']
|
||||
else:
|
||||
pluginInfo['setup_version'] = self.getVersion(
|
||||
pluginInfo['install_checks'])
|
||||
# pluginInfo['status'] = self.checkStatus(pluginInfo)
|
||||
return pluginInfo
|
||||
|
||||
def makeCoexist(self, data):
|
||||
plugins_info = []
|
||||
for index in range(len(data['versions'])):
|
||||
tmp = data.copy()
|
||||
tmp['title'] = tmp['title'] + \
|
||||
'-' + data['versions'][index]
|
||||
tmp['versions'] = data['versions'][index]
|
||||
pg = self.getPluginInfo(tmp)
|
||||
plugins_info.append(pg)
|
||||
|
||||
return plugins_info
|
||||
|
||||
def makeList(self, data, sType='0'):
|
||||
plugins_info = []
|
||||
|
||||
if (data['pid'] == sType):
|
||||
if type(data['versions']) == list and data.has_key('coexist') and data['coexist']:
|
||||
tmp_data = self.makeCoexist(data)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
else:
|
||||
pg = self.getPluginInfo(data)
|
||||
plugins_info.append(pg)
|
||||
return plugins_info
|
||||
|
||||
if sType == '0':
|
||||
if type(data['versions']) == list and data.has_key('coexist') and data['coexist']:
|
||||
tmp_data = self.makeCoexist(data)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
else:
|
||||
pg = self.getPluginInfo(data)
|
||||
plugins_info.append(pg)
|
||||
|
||||
# print plugins_info, data
|
||||
return plugins_info
|
||||
|
||||
def getAllList(self, sType='0'):
|
||||
plugins_info = []
|
||||
for dirinfo in os.listdir(self.__plugin_dir):
|
||||
if dirinfo[0:1] == '.':
|
||||
continue
|
||||
path = self.__plugin_dir + '/' + dirinfo
|
||||
if os.path.isdir(path):
|
||||
json_file = path + '/info.json'
|
||||
if os.path.exists(json_file):
|
||||
try:
|
||||
data = json.loads(public.readFile(json_file))
|
||||
tmp_data = self.makeList(data, sType)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
except Exception, e:
|
||||
print e
|
||||
return plugins_info
|
||||
|
||||
def getAllListPage(self, sType='0', page=1, pageSize=10):
|
||||
plugins_info = []
|
||||
for dirinfo in os.listdir(self.__plugin_dir):
|
||||
if dirinfo[0:1] == '.':
|
||||
continue
|
||||
path = self.__plugin_dir + '/' + dirinfo
|
||||
if os.path.isdir(path):
|
||||
json_file = path + '/info.json'
|
||||
if os.path.exists(json_file):
|
||||
try:
|
||||
data = json.loads(public.readFile(json_file))
|
||||
tmp_data = self.makeList(data, sType)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
start = (page - 1) * pageSize
|
||||
end = start + pageSize
|
||||
_plugins_info = plugins_info[start:end]
|
||||
|
||||
_plugins_info = self.checkStatusMProcess(_plugins_info)
|
||||
return (_plugins_info, len(plugins_info))
|
||||
|
||||
def makeListThread(self, data, sType='0'):
|
||||
plugins_info = []
|
||||
|
||||
if (data['pid'] == sType):
|
||||
if type(data['versions']) == list and data.has_key('coexist') and data['coexist']:
|
||||
tmp_data = self.makeCoexist(data)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
else:
|
||||
pg = self.getPluginInfo(data)
|
||||
plugins_info.append(pg)
|
||||
return plugins_info
|
||||
|
||||
if sType == '0':
|
||||
if type(data['versions']) == list and data.has_key('coexist') and data['coexist']:
|
||||
tmp_data = self.makeCoexist(data)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
else:
|
||||
pg = self.getPluginInfo(data)
|
||||
plugins_info.append(pg)
|
||||
|
||||
# print plugins_info, data
|
||||
return plugins_info
|
||||
|
||||
def getAllListThread(self, sType='0'):
|
||||
plugins_info = []
|
||||
tmp_list = []
|
||||
threads = []
|
||||
for dirinfo in os.listdir(self.__plugin_dir):
|
||||
if dirinfo[0:1] == '.':
|
||||
continue
|
||||
path = self.__plugin_dir + '/' + dirinfo
|
||||
if os.path.isdir(path):
|
||||
json_file = path + '/info.json'
|
||||
if os.path.exists(json_file):
|
||||
data = json.loads(public.readFile(json_file))
|
||||
if sType == '0':
|
||||
tmp_list.append(data)
|
||||
|
||||
if (data['pid'] == sType):
|
||||
tmp_list.append(data)
|
||||
|
||||
ntmp_list = range(len(tmp_list))
|
||||
for i in ntmp_list:
|
||||
t = pa_thread(self.makeListThread, (tmp_list[i], sType))
|
||||
threads.append(t)
|
||||
for i in ntmp_list:
|
||||
threads[i].start()
|
||||
for i in ntmp_list:
|
||||
threads[i].join()
|
||||
|
||||
for i in ntmp_list:
|
||||
t = threads[i].getResult()
|
||||
for index in range(len(t)):
|
||||
plugins_info.append(t[index])
|
||||
|
||||
return plugins_info
|
||||
|
||||
def makeListProcess(self, data, sType, i, return_dict):
|
||||
plugins_info = []
|
||||
|
||||
if (data['pid'] == sType):
|
||||
if type(data['versions']) == list and data.has_key('coexist') and data['coexist']:
|
||||
tmp_data = self.makeCoexist(data)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
else:
|
||||
pg = self.getPluginInfo(data)
|
||||
plugins_info.append(pg)
|
||||
# return plugins_info
|
||||
|
||||
if sType == '0':
|
||||
if type(data['versions']) == list and data.has_key('coexist') and data['coexist']:
|
||||
tmp_data = self.makeCoexist(data)
|
||||
for index in range(len(tmp_data)):
|
||||
plugins_info.append(tmp_data[index])
|
||||
else:
|
||||
pg = self.getPluginInfo(data)
|
||||
plugins_info.append(pg)
|
||||
|
||||
return_dict[i] = plugins_info
|
||||
# return plugins_info
|
||||
|
||||
def getAllListProcess(self, sType='0'):
|
||||
plugins_info = []
|
||||
tmp_list = []
|
||||
manager = multiprocessing.Manager()
|
||||
return_dict = manager.dict()
|
||||
jobs = []
|
||||
for dirinfo in os.listdir(self.__plugin_dir):
|
||||
if dirinfo[0:1] == '.':
|
||||
continue
|
||||
path = self.__plugin_dir + '/' + dirinfo
|
||||
if os.path.isdir(path):
|
||||
json_file = path + '/info.json'
|
||||
if os.path.exists(json_file):
|
||||
data = json.loads(public.readFile(json_file))
|
||||
if sType == '0':
|
||||
tmp_list.append(data)
|
||||
|
||||
if (data['pid'] == sType):
|
||||
tmp_list.append(data)
|
||||
|
||||
ntmp_list = range(len(tmp_list))
|
||||
for i in ntmp_list:
|
||||
p = multiprocessing.Process(
|
||||
target=self.makeListProcess, args=(tmp_list[i], sType, i, return_dict))
|
||||
jobs.append(p)
|
||||
p.start()
|
||||
|
||||
for proc in jobs:
|
||||
proc.join()
|
||||
|
||||
returnData = return_dict.values()
|
||||
for i in ntmp_list:
|
||||
for index in range(len(returnData[i])):
|
||||
plugins_info.append(returnData[i][index])
|
||||
|
||||
return plugins_info
|
||||
|
||||
def getPluginList(self, sType, sPage=1, sPageSize=10):
|
||||
|
||||
ret = {}
|
||||
ret['type'] = json.loads(public.readFile(self.__type))
|
||||
# plugins_info = self.getAllListThread(sType)
|
||||
# plugins_info = self.getAllListProcess(sType)
|
||||
data = self.getAllListPage(sType, sPage, sPageSize)
|
||||
ret['data'] = data[0]
|
||||
|
||||
args = {}
|
||||
args['count'] = data[1]
|
||||
args['p'] = sPage
|
||||
args['tojs'] = 'getSList'
|
||||
args['row'] = sPageSize
|
||||
|
||||
ret['list'] = public.getPage(args)
|
||||
return ret
|
||||
|
||||
def getIndexList(self):
|
||||
if not os.path.exists(self.__index):
|
||||
public.writeFile(self.__index, '[]')
|
||||
|
||||
indexList = json.loads(public.readFile(self.__index))
|
||||
|
||||
plist = []
|
||||
app = []
|
||||
for i in indexList:
|
||||
info = i.split('-')
|
||||
if not info[0] in app:
|
||||
app.append(info[0])
|
||||
path = self.__plugin_dir + '/' + info[0]
|
||||
if os.path.isdir(path):
|
||||
json_file = path + '/info.json'
|
||||
if os.path.exists(json_file):
|
||||
try:
|
||||
data = json.loads(public.readFile(json_file))
|
||||
tmp_data = self.makeList(data)
|
||||
for index in range(len(tmp_data)):
|
||||
if tmp_data[index]['versions'] == info[1] or info[1] in tmp_data[index]['versions']:
|
||||
tmp_data[index]['display'] = True
|
||||
plist.append(tmp_data[index])
|
||||
continue
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
plist = self.checkStatusMProcess(plist)
|
||||
return plist
|
||||
|
||||
def setIndexSort(self, sort):
|
||||
data = sort.split('|')
|
||||
public.writeFile(self.__index, json.dumps(data))
|
||||
return True
|
||||
|
||||
def addIndex(self, name, version):
|
||||
if not os.path.exists(self.__index):
|
||||
public.writeFile(self.__index, '[]')
|
||||
|
||||
indexList = json.loads(public.readFile(self.__index))
|
||||
vname = name + '-' + version
|
||||
|
||||
if vname in indexList:
|
||||
return public.returnJson(False, '请不要重复添加!')
|
||||
if len(indexList) >= 12:
|
||||
return public.returnJson(False, '首页最多只能显示12个软件!')
|
||||
|
||||
indexList.append(vname)
|
||||
public.writeFile(self.__index, json.dumps(indexList))
|
||||
return public.returnJson(True, '添加成功!')
|
||||
|
||||
def removeIndex(self, name, version):
|
||||
if not os.path.exists(self.__index):
|
||||
public.writeFile(self.__index, '[]')
|
||||
|
||||
indexList = json.loads(public.readFile(self.__index))
|
||||
vname = name + '-' + version
|
||||
if not vname in indexList:
|
||||
return public.returnJson(True, '删除成功!')
|
||||
indexList.remove(vname)
|
||||
public.writeFile(self.__index, json.dumps(indexList))
|
||||
return public.returnJson(True, '删除成功!')
|
||||
|
||||
def run(self, name, func, version, args='', script='index'):
|
||||
path = public.getRunDir() + '/' + self.__plugin_dir + \
|
||||
'/' + name + '/' + script + '.py'
|
||||
py = 'python ' + path
|
||||
if args == '':
|
||||
py_cmd = py + ' ' + func + ' ' + version
|
||||
else:
|
||||
py_cmd = py + ' ' + func + ' ' + version + ' ' + args
|
||||
|
||||
if not os.path.exists(path):
|
||||
return ('', '')
|
||||
data = public.execShell(py_cmd)
|
||||
|
||||
print py_cmd
|
||||
# print os.path.exists(py_cmd)
|
||||
return (data[0].strip(), data[1].strip())
|
||||
@@ -0,0 +1,723 @@
|
||||
# coding: utf-8
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import string
|
||||
import json
|
||||
import hashlib
|
||||
import shlex
|
||||
import datetime
|
||||
import subprocess
|
||||
import re
|
||||
import hashlib
|
||||
|
||||
import db
|
||||
|
||||
from random import Random
|
||||
|
||||
|
||||
def execShell(cmdstring, cwd=None, timeout=None, shell=True):
|
||||
|
||||
if shell:
|
||||
cmdstring_list = cmdstring
|
||||
else:
|
||||
cmdstring_list = shlex.split(cmdstring)
|
||||
if timeout:
|
||||
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
|
||||
|
||||
sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE,
|
||||
shell=shell, bufsize=4096, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
while sub.poll() is None:
|
||||
time.sleep(0.1)
|
||||
if timeout:
|
||||
if end_time <= datetime.datetime.now():
|
||||
raise Exception("Timeout:%s" % cmdstring)
|
||||
|
||||
return sub.communicate()
|
||||
|
||||
|
||||
def getRunDir():
|
||||
return os.getcwd()
|
||||
|
||||
|
||||
def getRootDir():
|
||||
return os.path.dirname(os.path.dirname(getRunDir()))
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return getRunDir() + '/plugins'
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return getRootDir() + '/server'
|
||||
|
||||
|
||||
def getWwwDir():
|
||||
return getRootDir() + '/wwwroot'
|
||||
|
||||
|
||||
def getLogsDir():
|
||||
return getRootDir() + '/wwwlogs'
|
||||
|
||||
|
||||
def getOs():
|
||||
os = execShell('uname')
|
||||
return os[0].lower().strip()
|
||||
|
||||
|
||||
def isAppleSystem():
|
||||
if getOs() == 'darwin':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def isInstalledWeb():
|
||||
path = getServerDir() + '/openresty/nginx/sbin/nginx'
|
||||
if os.path.exists(path):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def restartWeb():
|
||||
if isInstalledWeb():
|
||||
initd = getServerDir() + '/openresty/init.d/openresty'
|
||||
execShell(initd + ' ' + 'reload')
|
||||
|
||||
|
||||
def M(table):
|
||||
sql = db.Sql()
|
||||
return sql.table(table)
|
||||
|
||||
|
||||
def getPage(args, result='1,2,3,4,5,8'):
|
||||
data = getPageObject(args, result)
|
||||
return data[0]
|
||||
|
||||
|
||||
def getPageObject(args, result='1,2,3,4,5,8'):
|
||||
# 取分页
|
||||
import page
|
||||
# 实例化分页类
|
||||
page = page.Page()
|
||||
info = {}
|
||||
|
||||
info['count'] = 0
|
||||
if args.has_key('count'):
|
||||
info['count'] = int(args['count'])
|
||||
|
||||
info['row'] = 10
|
||||
if args.has_key('row'):
|
||||
info['row'] = int(args['row'])
|
||||
|
||||
info['p'] = 1
|
||||
if args.has_key('p'):
|
||||
info['p'] = int(args['p'])
|
||||
info['uri'] = {}
|
||||
info['return_js'] = ''
|
||||
if args.has_key('tojs'):
|
||||
info['return_js'] = args['tojs']
|
||||
|
||||
return (page.GetPage(info, result), page)
|
||||
|
||||
|
||||
def md5(str):
|
||||
# 生成MD5
|
||||
try:
|
||||
m = hashlib.md5()
|
||||
m.update(str)
|
||||
return m.hexdigest()
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def getFileMd5(filename):
|
||||
# 文件的MD5值
|
||||
if not os.path.isfile(filename):
|
||||
return False
|
||||
|
||||
myhash = hashlib.md5()
|
||||
f = file(filename, 'rb')
|
||||
while True:
|
||||
b = f.read(8096)
|
||||
if not b:
|
||||
break
|
||||
myhash.update(b)
|
||||
f.close()
|
||||
return myhash.hexdigest()
|
||||
|
||||
|
||||
def getRandomString(length):
|
||||
# 取随机字符串
|
||||
str = ''
|
||||
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
|
||||
chrlen = len(chars) - 1
|
||||
random = Random()
|
||||
for i in range(length):
|
||||
str += chars[random.randint(0, chrlen)]
|
||||
return str
|
||||
|
||||
|
||||
def getJson(data):
|
||||
import json
|
||||
return json.dumps(data)
|
||||
|
||||
|
||||
def returnJson(status, msg, args=()):
|
||||
# 取通用Json返回
|
||||
return getJson(returnMsg(status, msg, args))
|
||||
|
||||
|
||||
def returnMsg(status, msg, args=()):
|
||||
# 取通用字曲返回
|
||||
pjson = 'static/language/' + getLanguage() + '/public.json'
|
||||
logMessage = json.loads(readFile(pjson))
|
||||
keys = logMessage.keys()
|
||||
|
||||
if msg in keys:
|
||||
msg = logMessage[msg]
|
||||
for i in range(len(args)):
|
||||
rep = '{' + str(i + 1) + '}'
|
||||
msg = msg.replace(rep, args[i])
|
||||
return {'status': status, 'msg': msg, 'data': args}
|
||||
|
||||
|
||||
def getInfo(msg, args=()):
|
||||
# 取提示消息
|
||||
for i in range(len(args)):
|
||||
rep = '{' + str(i + 1) + '}'
|
||||
msg = msg.replace(rep, args[i])
|
||||
return msg
|
||||
|
||||
|
||||
def getMsg(key, args=()):
|
||||
# 取提示消息
|
||||
try:
|
||||
logMessage = json.loads(
|
||||
readFile('static/language/' + getLanguage() + '/public.json'))
|
||||
keys = logMessage.keys()
|
||||
msg = None
|
||||
if key in keys:
|
||||
msg = logMessage[key]
|
||||
for i in range(len(args)):
|
||||
rep = '{' + str(i + 1) + '}'
|
||||
msg = msg.replace(rep, args[i])
|
||||
return msg
|
||||
except:
|
||||
return key
|
||||
|
||||
|
||||
def getLan(key):
|
||||
# 取提示消息
|
||||
logMessage = json.loads(
|
||||
readFile('static/language/' + getLanguage() + '/template.json'))
|
||||
keys = logMessage.keys()
|
||||
msg = None
|
||||
if key in keys:
|
||||
msg = logMessage[key]
|
||||
return msg
|
||||
|
||||
|
||||
def readFile(filename):
|
||||
# 读文件内容
|
||||
try:
|
||||
fp = open(filename, 'r')
|
||||
fBody = fp.read()
|
||||
fp.close()
|
||||
return fBody
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def getDate():
|
||||
# 取格式时间
|
||||
import time
|
||||
return time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
|
||||
def getLanguage():
|
||||
path = 'data/language.pl'
|
||||
if not os.path.exists(path):
|
||||
return 'Simplified_Chinese'
|
||||
return readFile(path).strip()
|
||||
|
||||
|
||||
def writeLog(type, logMsg, args=()):
|
||||
# 写日志
|
||||
try:
|
||||
import time
|
||||
import db
|
||||
import json
|
||||
logMessage = json.loads(
|
||||
readFile('static/language/' + getLanguage() + '/log.json'))
|
||||
keys = logMessage.keys()
|
||||
if logMsg in keys:
|
||||
logMsg = logMessage[logMsg]
|
||||
for i in range(len(args)):
|
||||
rep = '{' + str(i + 1) + '}'
|
||||
logMsg = logMsg.replace(rep, args[i])
|
||||
if type in keys:
|
||||
type = logMessage[type]
|
||||
sql = db.Sql()
|
||||
mDate = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
data = (type, logMsg, mDate)
|
||||
result = sql.table('logs').add('type,log,addtime', data)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def writeFile(filename, str):
|
||||
# 写文件内容
|
||||
try:
|
||||
fp = open(filename, 'w+')
|
||||
fp.write(str)
|
||||
fp.close()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def httpGet(url, timeout=30):
|
||||
# 发送GET请求
|
||||
try:
|
||||
import urllib2
|
||||
import ssl
|
||||
try:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except:
|
||||
pass
|
||||
response = urllib2.urlopen(url, timeout=timeout)
|
||||
return response.read()
|
||||
except Exception, ex:
|
||||
# WriteLog('网络诊断',str(ex) + '['+url+']');
|
||||
return str(ex)
|
||||
|
||||
|
||||
def httpPost(url, data, timeout=30):
|
||||
# 发送POST请求
|
||||
try:
|
||||
import urllib
|
||||
import urllib2
|
||||
import ssl
|
||||
try:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except:
|
||||
pass
|
||||
data = urllib.urlencode(data)
|
||||
req = urllib2.Request(url, data)
|
||||
response = urllib2.urlopen(req, timeout=timeout)
|
||||
return response.read()
|
||||
except Exception, ex:
|
||||
# WriteLog('网络诊断',str(ex) + '['+url+']');
|
||||
return str(ex)
|
||||
|
||||
|
||||
def writeSpeed(title, used, total, speed=0):
|
||||
# 写进度
|
||||
if not title:
|
||||
data = {'title': None, 'progress': 0,
|
||||
'total': 0, 'used': 0, 'speed': 0}
|
||||
else:
|
||||
progress = int((100.0 * used / total))
|
||||
data = {'title': title, 'progress': progress,
|
||||
'total': total, 'used': used, 'speed': speed}
|
||||
writeFile('/tmp/panelSpeed.pl', json.dumps(data))
|
||||
return True
|
||||
|
||||
|
||||
def getSpeed():
|
||||
# 取进度
|
||||
data = readFile('/tmp/panelSpeed.pl')
|
||||
if not data:
|
||||
data = json.dumps({'title': None, 'progress': 0,
|
||||
'total': 0, 'used': 0, 'speed': 0})
|
||||
writeFile('/tmp/panelSpeed.pl', data)
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
def getLastLine(inputfile, lineNum):
|
||||
# 读文件指定倒数行数
|
||||
try:
|
||||
fp = open(inputfile, 'r')
|
||||
lastLine = ""
|
||||
|
||||
lines = fp.readlines()
|
||||
count = len(lines)
|
||||
if count > lineNum:
|
||||
num = lineNum
|
||||
else:
|
||||
num = count
|
||||
i = 1
|
||||
lastre = []
|
||||
for i in range(1, (num + 1)):
|
||||
if lines:
|
||||
n = -i
|
||||
lastLine = lines[n].strip()
|
||||
fp.close()
|
||||
lastre.append(lastLine)
|
||||
|
||||
result = ''
|
||||
num -= 1
|
||||
while num >= 0:
|
||||
result += lastre[num] + "\n"
|
||||
num -= 1
|
||||
return result
|
||||
except:
|
||||
return getMsg('TASK_SLEEP')
|
||||
|
||||
|
||||
def downloadFile(url, filename):
|
||||
import urllib
|
||||
urllib.urlretrieve(url, filename=filename, reporthook=downloadHook)
|
||||
|
||||
|
||||
def downloadHook(count, blockSize, totalSize):
|
||||
speed = {'total': totalSize, 'block': blockSize, 'count': count}
|
||||
print speed
|
||||
print '%02d%%' % (100.0 * count * blockSize / totalSize)
|
||||
|
||||
|
||||
def getLocalIp():
|
||||
# 取本地外网IP
|
||||
try:
|
||||
import re
|
||||
filename = 'data/iplist.txt'
|
||||
ipaddress = readFile(filename)
|
||||
if not ipaddress:
|
||||
import urllib2
|
||||
url = 'http://pv.sohu.com/cityjson?ie=utf-8'
|
||||
opener = urllib2.urlopen(url)
|
||||
str = opener.read()
|
||||
ipaddress = re.search('\d+.\d+.\d+.\d+', str).group(0)
|
||||
writeFile(filename, ipaddress)
|
||||
|
||||
ipaddress = re.search('\d+.\d+.\d+.\d+', ipaddress).group(0)
|
||||
return ipaddress
|
||||
except:
|
||||
return '127.0.0.1'
|
||||
|
||||
|
||||
def inArray(arrays, searchStr):
|
||||
# 搜索数据中是否存在
|
||||
for key in arrays:
|
||||
if key == searchStr:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def checkIp(ip):
|
||||
# 检查是否为IPv4地址
|
||||
import re
|
||||
p = re.compile(
|
||||
'^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
|
||||
if p.match(ip):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def checkPort(port):
|
||||
# 检查端口是否合法
|
||||
ports = ['21', '25', '443', '8080', '888', '8888', '8443']
|
||||
if port in ports:
|
||||
return False
|
||||
intport = int(port)
|
||||
if intport < 1 or intport > 65535:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def getStrBetween(startStr, endStr, srcStr):
|
||||
# 字符串取中间
|
||||
start = srcStr.find(startStr)
|
||||
if start == -1:
|
||||
return None
|
||||
end = srcStr.find(endStr)
|
||||
if end == -1:
|
||||
return None
|
||||
return srcStr[start + 1:end]
|
||||
|
||||
|
||||
def getCpuType():
|
||||
# 取CPU类型
|
||||
cpuinfo = open('/proc/cpuinfo', 'r').read()
|
||||
rep = "model\s+name\s+:\s+(.+)"
|
||||
tmp = re.search(rep, cpuinfo)
|
||||
cpuType = None
|
||||
if tmp:
|
||||
cpuType = tmp.groups()[0]
|
||||
return cpuType
|
||||
|
||||
|
||||
def isRestart():
|
||||
# 检查是否允许重启
|
||||
num = M('tasks').where('status!=?', ('1',)).count()
|
||||
if num > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def isUpdateLocalSoft():
|
||||
num = M('tasks').where('status!=?', ('1',)).count()
|
||||
if os.path.exists('mdserver-web.zip'):
|
||||
return True
|
||||
|
||||
if num > 0:
|
||||
data = M('tasks').where('status!=?', ('1',)).field(
|
||||
'id,type,execstr').limit('1').select()
|
||||
argv = data[0]['execstr'].split('|dl|')
|
||||
if data[0]['type'] == 'download' and argv[1] == 'mdserver-web.zip':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def hasPwd(password):
|
||||
# 加密密码字符
|
||||
import crypt
|
||||
return crypt.crypt(password, password)
|
||||
|
||||
|
||||
def getTimeout(url):
|
||||
start = time.time()
|
||||
result = httpGet(url)
|
||||
if result != 'True':
|
||||
return False
|
||||
return int((time.time() - start) * 1000)
|
||||
|
||||
|
||||
def auth_decode(data):
|
||||
# 解密数据
|
||||
token = GetToken()
|
||||
# 是否有生成Token
|
||||
if not token:
|
||||
return returnMsg(False, 'REQUEST_ERR')
|
||||
|
||||
# 校验access_key是否正确
|
||||
if token['access_key'] != data['btauth_key']:
|
||||
return returnMsg(False, 'REQUEST_ERR')
|
||||
|
||||
# 解码数据
|
||||
import binascii
|
||||
import hashlib
|
||||
import urllib
|
||||
import hmac
|
||||
import json
|
||||
tdata = binascii.unhexlify(data['data'])
|
||||
|
||||
# 校验signature是否正确
|
||||
signature = binascii.hexlify(
|
||||
hmac.new(token['secret_key'], tdata, digestmod=hashlib.sha256).digest())
|
||||
if signature != data['signature']:
|
||||
return returnMsg(False, 'REQUEST_ERR')
|
||||
|
||||
# 返回
|
||||
return json.loads(urllib.unquote(tdata))
|
||||
|
||||
|
||||
# 数据加密
|
||||
def auth_encode(data):
|
||||
token = GetToken()
|
||||
pdata = {}
|
||||
|
||||
# 是否有生成Token
|
||||
if not token:
|
||||
return returnMsg(False, 'REQUEST_ERR')
|
||||
|
||||
# 生成signature
|
||||
import binascii
|
||||
import hashlib
|
||||
import urllib
|
||||
import hmac
|
||||
import json
|
||||
tdata = urllib.quote(json.dumps(data))
|
||||
# 公式 hex(hmac_sha256(data))
|
||||
pdata['signature'] = binascii.hexlify(
|
||||
hmac.new(token['secret_key'], tdata, digestmod=hashlib.sha256).digest())
|
||||
|
||||
# 加密数据
|
||||
pdata['btauth_key'] = token['access_key']
|
||||
pdata['data'] = binascii.hexlify(tdata)
|
||||
pdata['timestamp'] = time.time()
|
||||
|
||||
# 返回
|
||||
return pdata
|
||||
|
||||
|
||||
def checkToken(get):
|
||||
# 检查Token
|
||||
tempFile = 'data/tempToken.json'
|
||||
if not os.path.exists(tempFile):
|
||||
return False
|
||||
import json
|
||||
import time
|
||||
tempToken = json.loads(readFile(tempFile))
|
||||
if time.time() > tempToken['timeout']:
|
||||
return False
|
||||
if get.token != tempToken['token']:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def checkInput(data):
|
||||
# 过滤输入
|
||||
if not data:
|
||||
return data
|
||||
if type(data) != str:
|
||||
return data
|
||||
checkList = [
|
||||
{'d': '<', 'r': '<'},
|
||||
{'d': '>', 'r': '>'},
|
||||
{'d': '\'', 'r': '‘'},
|
||||
{'d': '"', 'r': '“'},
|
||||
{'d': '&', 'r': '&'},
|
||||
{'d': '#', 'r': '#'},
|
||||
{'d': '<', 'r': '<'}
|
||||
]
|
||||
for v in checkList:
|
||||
data = data.replace(v['d'], v['r'])
|
||||
return data
|
||||
|
||||
|
||||
def getNumLines(path, num, p=1):
|
||||
# 取文件指定尾行数
|
||||
try:
|
||||
import cgi
|
||||
if not os.path.exists(path):
|
||||
return ""
|
||||
start_line = (p - 1) * num
|
||||
count = start_line + num
|
||||
fp = open(path)
|
||||
buf = ""
|
||||
fp.seek(-1, 2)
|
||||
if fp.read(1) == "\n":
|
||||
fp.seek(-1, 2)
|
||||
data = []
|
||||
b = True
|
||||
n = 0
|
||||
for i in range(count):
|
||||
while True:
|
||||
newline_pos = string.rfind(buf, "\n")
|
||||
pos = fp.tell()
|
||||
if newline_pos != -1:
|
||||
if n >= start_line:
|
||||
line = buf[newline_pos + 1:]
|
||||
try:
|
||||
data.insert(0, cgi.escape(line))
|
||||
except:
|
||||
pass
|
||||
buf = buf[:newline_pos]
|
||||
n += 1
|
||||
break
|
||||
else:
|
||||
if pos == 0:
|
||||
b = False
|
||||
break
|
||||
to_read = min(4096, pos)
|
||||
fp.seek(-to_read, 1)
|
||||
buf = fp.read(to_read) + buf
|
||||
fp.seek(-to_read, 1)
|
||||
if pos - to_read == 0:
|
||||
buf = "\n" + buf
|
||||
if not b:
|
||||
break
|
||||
fp.close()
|
||||
except:
|
||||
data = []
|
||||
return "\n".join(data)
|
||||
|
||||
|
||||
def checkCert(certPath='ssl/certificate.pem'):
|
||||
# 验证证书
|
||||
openssl = '/usr/local/openssl/bin/openssl'
|
||||
if not os.path.exists(openssl):
|
||||
openssl = 'openssl'
|
||||
certPem = readFile(certPath)
|
||||
s = "\n-----BEGIN CERTIFICATE-----"
|
||||
tmp = certPem.strip().split(s)
|
||||
for tmp1 in tmp:
|
||||
if tmp1.find('-----BEGIN CERTIFICATE-----') == -1:
|
||||
tmp1 = s + tmp1
|
||||
writeFile(certPath, tmp1)
|
||||
result = execShell(openssl + " x509 -in " +
|
||||
certPath + " -noout -subject")
|
||||
if result[1].find('-bash:') != -1:
|
||||
return True
|
||||
if len(result[1]) > 2:
|
||||
return False
|
||||
if result[0].find('error:') != -1:
|
||||
return False
|
||||
return True
|
||||
|
||||
# 获取面板地址
|
||||
|
||||
|
||||
# def getPanelAddr():
|
||||
# import web
|
||||
# protocol = 'https://' if os.path.exists("data/ssl.pl") else 'http://'
|
||||
# h = web.ctx.host.split(':')
|
||||
# try:
|
||||
# result = protocol + h[0] + ':' + h[1]
|
||||
# except:
|
||||
# result = protocol + h[0] + ':' + readFile('data/port.pl').strip()
|
||||
# return result
|
||||
|
||||
|
||||
def toSize(size):
|
||||
# 字节单位转换
|
||||
d = ('b', 'KB', 'MB', 'GB', 'TB')
|
||||
s = d[0]
|
||||
for b in d:
|
||||
if size < 1024:
|
||||
return str(size) + ' ' + b
|
||||
size = size / 1024
|
||||
s = b
|
||||
return str(size) + ' ' + b
|
||||
|
||||
|
||||
def getMacAddress():
|
||||
# 获取mac
|
||||
import uuid
|
||||
mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])
|
||||
|
||||
|
||||
def get_string(t):
|
||||
if t != -1:
|
||||
max = 126
|
||||
m_types = [{'m': 122, 'n': 97}, {'m': 90, 'n': 65}, {'m': 57, 'n': 48}, {
|
||||
'm': 47, 'n': 32}, {'m': 64, 'n': 58}, {'m': 96, 'n': 91}, {'m': 125, 'n': 123}]
|
||||
else:
|
||||
max = 256
|
||||
t = 0
|
||||
m_types = [{'m': 255, 'n': 0}]
|
||||
arr = []
|
||||
for i in range(max):
|
||||
if i < m_types[t]['n'] or i > m_types[t]['m']:
|
||||
continue
|
||||
arr.append(chr(i))
|
||||
return arr
|
||||
|
||||
|
||||
def get_string_find(t):
|
||||
if type(t) != list:
|
||||
t = [t]
|
||||
return_str = ''
|
||||
for s1 in t:
|
||||
return_str += get_string(int(s1[0]))[int(s1[1:])]
|
||||
return return_str
|
||||
|
||||
|
||||
def get_string_arr(t):
|
||||
s_arr = {}
|
||||
t_arr = []
|
||||
for s1 in t:
|
||||
for i in range(6):
|
||||
if not i in s_arr:
|
||||
s_arr[i] = get_string(i)
|
||||
for j in range(len(s_arr[i])):
|
||||
if s1 == s_arr[i][j]:
|
||||
t_arr.append(str(i) + str(j))
|
||||
return t_arr
|
||||
@@ -0,0 +1,399 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
|
||||
class site_api:
|
||||
siteName = None # 网站名称
|
||||
sitePath = None # 根目录
|
||||
sitePort = None # 端口
|
||||
phpVersion = None # PHP版本
|
||||
setupPath = None # 安装路径
|
||||
isWriteLogs = None # 是否写日志
|
||||
|
||||
def __init__(self):
|
||||
self.setupPath = public.getServerDir()
|
||||
path = self.setupPath + '/openresty/nginx/conf/vhost'
|
||||
if not os.path.exists(path):
|
||||
public.execShell("mkdir -p " + path + " && chmod -R 755 " + path)
|
||||
path = self.setupPath + '/openresty/nginx/conf/rewrite'
|
||||
if not os.path.exists(path):
|
||||
public.execShell("mkdir -p " + path + " && chmod -R 755 " + path)
|
||||
|
||||
# 域名编码转换
|
||||
def toPunycode(self, domain):
|
||||
import re
|
||||
if sys.version_info[0] == 2:
|
||||
domain = domain.encode('utf8')
|
||||
tmp = domain.split('.')
|
||||
newdomain = ''
|
||||
for dkey in tmp:
|
||||
# 匹配非ascii字符
|
||||
match = re.search(u"[\x80-\xff]+", dkey)
|
||||
if not match:
|
||||
newdomain += dkey + '.'
|
||||
else:
|
||||
newdomain += 'xn--' + \
|
||||
dkey.decode('utf-8').encode('punycode') + '.'
|
||||
return newdomain[0:-1]
|
||||
|
||||
# 中文路径处理
|
||||
def toPunycodePath(self, path):
|
||||
if sys.version_info[0] == 2:
|
||||
path = path.encode('utf-8')
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
import re
|
||||
match = re.search(u"[\x80-\xff]+", path)
|
||||
if not match:
|
||||
return path
|
||||
npath = ''
|
||||
for ph in path.split('/'):
|
||||
npath += '/' + self.toPunycode(ph)
|
||||
return npath.replace('//', '/')
|
||||
|
||||
# 路径处理
|
||||
def getPath(self, path):
|
||||
if path[-1] == '/':
|
||||
return path[0:-1]
|
||||
return path
|
||||
|
||||
def getHostConf(self, siteName):
|
||||
return public.getServerDir() + '/openresty/nginx/conf/vhost/' + siteName + '.conf'
|
||||
|
||||
def getRewriteConf(self, siteName):
|
||||
return public.getServerDir() + '/openresty/nginx/conf/rewrite/' + siteName + '.conf'
|
||||
|
||||
def getIndexConf(self):
|
||||
return public.getServerDir() + '/openresty/nginx/conf/nginx.conf'
|
||||
|
||||
def list(self):
|
||||
_list = public.M('sites').where('', ()).field(
|
||||
'id,name,path,status,ps,addtime,edate').limit('0,5').order('id desc').select()
|
||||
_ret = {}
|
||||
_ret['data'] = _list
|
||||
|
||||
count = public.M('sites').where('', ()).count()
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['tojs'] = 'getWeb'
|
||||
|
||||
_ret['page'] = public.getPage(_page)
|
||||
return public.getJson(_ret)
|
||||
|
||||
def getDomain(self, pid):
|
||||
_list = public.M('domain').where("pid=?", (pid,)).field(
|
||||
'id,pid,name,port,addtime').select()
|
||||
return public.getJson(_list)
|
||||
|
||||
def getLogs(self, siteName):
|
||||
logPath = public.getLogsDir() + '/' + siteName + '.log'
|
||||
if not os.path.exists(logPath):
|
||||
return public.returnJson(False, '日志为空')
|
||||
return public.returnJson(True, public.getNumLines(logPath, 1000))
|
||||
|
||||
def getSitePhpVersion(self, siteName):
|
||||
conf = public.readFile(self.getHostConf(siteName))
|
||||
rep = "enable-php-([0-9]{2,3})\.conf"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
data = {}
|
||||
data['phpversion'] = tmp[0]
|
||||
return public.getJson(data)
|
||||
|
||||
def getIndex(self, sid):
|
||||
print sid
|
||||
siteName = public.M('sites').where("id=?", (sid,)).getField('name')
|
||||
file = self.getHostConf(siteName)
|
||||
conf = public.readFile(file)
|
||||
rep = "\s+index\s+(.+);"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
return tmp[0].replace(' ', ',')
|
||||
|
||||
def setIndex(self, sid, index):
|
||||
if index.find('.') == -1:
|
||||
return public.returnJson(False, '默认文档格式不正确,例:index.html')
|
||||
|
||||
index = index.replace(' ', '')
|
||||
index = index.replace(',,', ',')
|
||||
|
||||
if len(index) < 3:
|
||||
return public.returnJson(False, '默认文档不能为空!')
|
||||
|
||||
siteName = public.M('sites').where("id=?", (sid,)).getField('name')
|
||||
index_l = index.replace(",", " ")
|
||||
file = self.getHostConf(siteName)
|
||||
conf = public.readFile(file)
|
||||
if conf:
|
||||
rep = "\s+index\s+.+;"
|
||||
conf = re.sub(rep, "\n\tindex " + index_l + ";", conf)
|
||||
public.writeFile(file, conf)
|
||||
|
||||
public.writeLog('TYPE_SITE', 'SITE_INDEX_SUCCESS', (siteName, index_l))
|
||||
return public.returnJson(True, '设置成功!')
|
||||
|
||||
def getLimitNet(self, sid):
|
||||
siteName = public.M('sites').where("id=?", (sid,)).getField('name')
|
||||
filename = self.getHostConf(siteName)
|
||||
# 站点总并发
|
||||
data = {}
|
||||
conf = public.readFile(filename)
|
||||
try:
|
||||
rep = "\s+limit_conn\s+perserver\s+([0-9]+);"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
data['perserver'] = int(tmp[0])
|
||||
|
||||
# IP并发限制
|
||||
rep = "\s+limit_conn\s+perip\s+([0-9]+);"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
data['perip'] = int(tmp[0])
|
||||
|
||||
# 请求并发限制
|
||||
rep = "\s+limit_rate\s+([0-9]+)\w+;"
|
||||
tmp = re.search(rep, conf).groups()
|
||||
data['limit_rate'] = int(tmp[0])
|
||||
except:
|
||||
data['perserver'] = 0
|
||||
data['perip'] = 0
|
||||
data['limit_rate'] = 0
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
def checkIndexConf(self):
|
||||
limit = self.getIndexConf()
|
||||
nginxConf = public.readFile(limit)
|
||||
limitConf = "limit_conn_zone $binary_remote_addr zone=perip:10m;\n\t\tlimit_conn_zone $server_name zone=perserver:10m;"
|
||||
nginxConf = nginxConf.replace(
|
||||
"#limit_conn_zone $binary_remote_addr zone=perip:10m;", limitConf)
|
||||
public.writeFile(limit, nginxConf)
|
||||
|
||||
def saveLimitNet(self, sid, perserver, perip, limit_rate):
|
||||
|
||||
str_perserver = 'limit_conn perserver ' + perserver + ';'
|
||||
str_perip = 'limit_conn perip ' + perip + ';'
|
||||
str_limit_rate = 'limit_rate ' + limit_rate + 'k;'
|
||||
|
||||
siteName = public.M('sites').where("id=?", (sid,)).getField('name')
|
||||
filename = self.getHostConf(siteName)
|
||||
|
||||
conf = public.readFile(filename)
|
||||
if(conf.find('limit_conn perserver') != -1):
|
||||
# 替换总并发
|
||||
rep = "limit_conn\s+perserver\s+([0-9]+);"
|
||||
conf = re.sub(rep, str_perserver, conf)
|
||||
|
||||
# 替换IP并发限制
|
||||
rep = "limit_conn\s+perip\s+([0-9]+);"
|
||||
conf = re.sub(rep, str_perip, conf)
|
||||
|
||||
# 替换请求流量限制
|
||||
rep = "limit_rate\s+([0-9]+)\w+;"
|
||||
conf = re.sub(rep, str_limit_rate, conf)
|
||||
else:
|
||||
conf = conf.replace('#error_page 404/404.html;', "#error_page 404/404.html;\n " +
|
||||
str_perserver + "\n " + str_perip + "\n " + str_limit_rate)
|
||||
|
||||
public.writeFile(filename, conf)
|
||||
public.restartWeb()
|
||||
public.writeLog('TYPE_SITE', 'SITE_NETLIMIT_OPEN_SUCCESS', (siteName,))
|
||||
return public.returnJson(True, '设置成功!')
|
||||
|
||||
def closeLimitNet(self, sid):
|
||||
siteName = public.M('sites').where("id=?", (sid,)).getField('name')
|
||||
filename = self.getHostConf(siteName)
|
||||
conf = public.readFile(filename)
|
||||
# 清理总并发
|
||||
rep = "\s+limit_conn\s+perserver\s+([0-9]+);"
|
||||
conf = re.sub(rep, '', conf)
|
||||
|
||||
# 清理IP并发限制
|
||||
rep = "\s+limit_conn\s+perip\s+([0-9]+);"
|
||||
conf = re.sub(rep, '', conf)
|
||||
|
||||
# 清理请求流量限制
|
||||
rep = "\s+limit_rate\s+([0-9]+)\w+;"
|
||||
conf = re.sub(rep, '', conf)
|
||||
public.writeFile(filename, conf)
|
||||
public.restartWeb()
|
||||
public.writeLog(
|
||||
'TYPE_SITE', 'SITE_NETLIMIT_CLOSE_SUCCESS', (siteName,))
|
||||
return public.returnJson(True, '已关闭流量限制!')
|
||||
|
||||
def getSecurity(self, sid, name):
|
||||
filename = self.getHostConf(name)
|
||||
conf = public.readFile(filename)
|
||||
data = {}
|
||||
if conf.find('SECURITY-START') != -1:
|
||||
rep = "#SECURITY-START(\n|.){1,500}#SECURITY-END"
|
||||
tmp = re.search(rep, conf).group()
|
||||
data['fix'] = re.search(
|
||||
"\(.+\)\$", tmp).group().replace('(', '').replace(')$', '').replace('|', ',')
|
||||
data['domains'] = ','.join(re.search(
|
||||
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp).groups()[0].split())
|
||||
data['status'] = True
|
||||
else:
|
||||
data['fix'] = 'jpg,jpeg,gif,png,js,css'
|
||||
domains = public.M('domain').where(
|
||||
'pid=?', (sid,)).field('name').select()
|
||||
tmp = []
|
||||
for domain in domains:
|
||||
tmp.append(domain['name'])
|
||||
data['domains'] = ','.join(tmp)
|
||||
data['status'] = False
|
||||
return public.getJson(data)
|
||||
|
||||
def setSecurity(self, sid, name, fix, domains, status):
|
||||
if len(fix) < 2:
|
||||
return public.returnJson(False, 'URL后缀不能为空!')
|
||||
file = self.getHostConf(name)
|
||||
if os.path.exists(file):
|
||||
conf = public.readFile(file)
|
||||
if conf.find('SECURITY-START') != -1:
|
||||
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
|
||||
conf = re.sub(rep, '', conf)
|
||||
public.writeLog('网站管理', '站点[' + name + ']已关闭防盗链设置!')
|
||||
else:
|
||||
rconf = '''#SECURITY-START 防盗链配置
|
||||
location ~ .*\.(%s)$
|
||||
{
|
||||
expires 30d;
|
||||
access_log /dev/null;
|
||||
valid_referers none blocked %s;
|
||||
if ($invalid_referer){
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
#SECURITY-END
|
||||
include enable-php-''' % (fix.strip().replace(',', '|'), domains.strip().replace(',', ' '))
|
||||
conf = re.sub("include\s+enable-php-", rconf, conf)
|
||||
public.writeLog('网站管理', '站点[' + name + ']已开启防盗链!')
|
||||
public.writeFile(file, conf)
|
||||
public.restartWeb()
|
||||
return public.returnJson(True, '设置成功!')
|
||||
|
||||
def getPhpVersion(self):
|
||||
phpVersions = ('00', '52', '53', '54', '55',
|
||||
'56', '70', '71', '72', '73', '74')
|
||||
data = []
|
||||
for val in phpVersions:
|
||||
tmp = {}
|
||||
if val == '00':
|
||||
tmp['name'] = '纯静态'
|
||||
data.append(tmp)
|
||||
|
||||
checkPath = public.getServerDir() + '/php/' + val + '/bin/php'
|
||||
if os.path.exists(checkPath):
|
||||
tmp['version'] = val
|
||||
tmp['name'] = 'PHP-' + val
|
||||
data.append(tmp)
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
def getRewriteList(self):
|
||||
rewriteList = {}
|
||||
rewriteList['rewrite'] = []
|
||||
rewriteList['rewrite'].append('0.当前')
|
||||
for ds in os.listdir('rewrite/nginx'):
|
||||
rewriteList['rewrite'].append(ds[0:len(ds) - 5])
|
||||
rewriteList['rewrite'] = sorted(rewriteList['rewrite'])
|
||||
return rewriteList
|
||||
|
||||
def createRootDir(self, path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
if not public.isAppleSystem():
|
||||
public.execShell('chown -R www:www ' + path)
|
||||
public.execShell('chmod -R 755 ' + path)
|
||||
|
||||
def addDomain(self, domain, webname, pid):
|
||||
pass
|
||||
|
||||
def nginxAddConf(self):
|
||||
source_tpl = public.getRunDir() + '/data/tpl/nginx.conf'
|
||||
vhost_file = self.setupPath + '/openresty/nginx/conf/vhost/' + self.siteName + '.conf'
|
||||
content = public.readFile(source_tpl)
|
||||
|
||||
content = content.replace('{$PORT}', self.sitePort)
|
||||
content = content.replace('{$SERVER_NAME}', self.siteName)
|
||||
content = content.replace('{$ROOT_DIR}', self.sitePath)
|
||||
content = content.replace('{$PHPVER}', self.phpVersion)
|
||||
|
||||
or_rewrite = self.setupPath + '/openresty/nginx/conf/rewrite'
|
||||
content = content.replace('{$OR_REWRITE}', or_rewrite)
|
||||
|
||||
logsPath = public.getLogsDir()
|
||||
content = content.replace('{$LOGPATH}', logsPath)
|
||||
public.writeFile(vhost_file, content)
|
||||
|
||||
rewrite_file = self.setupPath + \
|
||||
'/openresty/nginx/conf/rewrite/' + self.siteName + '.conf'
|
||||
public.writeFile(rewrite_file, '')
|
||||
|
||||
def add(self, webname, port, ps, path, version):
|
||||
|
||||
siteMenu = json.loads(webname)
|
||||
self.siteName = self.toPunycode(
|
||||
siteMenu['domain'].strip().split(':')[0]).strip()
|
||||
self.sitePath = self.toPunycodePath(
|
||||
self.getPath(path.replace(' ', '')))
|
||||
self.sitePort = port.strip().replace(' ', '')
|
||||
self.phpVersion = version
|
||||
|
||||
siteM = public.M('sites')
|
||||
if siteM.where("name=?", (self.siteName,)).count():
|
||||
return public.returnJson(False, '您添加的站点已存在!')
|
||||
|
||||
# 写入数据库
|
||||
pid = siteM.add('name,path,status,ps,edate,addtime',
|
||||
(self.siteName, self.sitePath, '1', ps, '0000-00-00', public.getDate()))
|
||||
opid = public.M('domain').where(
|
||||
"name=?", (self.siteName,)).getField('pid')
|
||||
if opid:
|
||||
if public.M('sites').where('id=?', (opid,)).count():
|
||||
return public.returnJson(False, '您添加的域名已存在!')
|
||||
public.M('domain').where('pid=?', (opid,)).delete()
|
||||
|
||||
# 添加更多域名
|
||||
for domain in siteMenu['domainlist']:
|
||||
sdomain = domain
|
||||
swebname = self.siteName
|
||||
spid = str(get.pid)
|
||||
# self.addDomain(domain, webname, pid)
|
||||
|
||||
public.M('domain').add('pid,name,port,addtime',
|
||||
(pid, self.siteName, self.sitePort, public.getDate()))
|
||||
|
||||
self.createRootDir(self.sitePath)
|
||||
|
||||
self.nginxAddConf()
|
||||
|
||||
data = {}
|
||||
data['siteStatus'] = False
|
||||
public.restartWeb()
|
||||
return public.getJson(data)
|
||||
|
||||
def delete(self, sid, webname):
|
||||
|
||||
confFile = self.setupPath + '/openresty/nginx/conf/vhost/' + webname + '.conf'
|
||||
if os.path.exists(confFile):
|
||||
os.remove(confFile)
|
||||
|
||||
rewriteFile = self.setupPath + '/openresty/nginx/conf/rewrite/' + webname + '.conf'
|
||||
if os.path.exists(rewriteFile):
|
||||
os.remove(rewriteFile)
|
||||
|
||||
public.M('sites').where("id=?", (sid,)).delete()
|
||||
return public.returnJson(True, '站点删除成功!')
|
||||
|
||||
def setEndDate(self, sid, edate):
|
||||
result = public.M('sites').where(
|
||||
'id=?', (sid,)).setField('edate', edate)
|
||||
siteName = public.M('sites').where('id=?', (sid,)).getField('name')
|
||||
public.writeLog('TYPE_SITE', '设置成功,站点到期后将自动停止!', (siteName, edate))
|
||||
return public.returnJson(True, '设置成功,站点到期后将自动停止!')
|
||||
@@ -0,0 +1,643 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import re
|
||||
import math
|
||||
import json
|
||||
|
||||
from flask import Flask, session
|
||||
|
||||
import db
|
||||
import public
|
||||
import config
|
||||
|
||||
|
||||
class system_api:
|
||||
setupPath = None
|
||||
pids = None
|
||||
|
||||
def __init__(self):
|
||||
self.setupPath = public.getServerDir()
|
||||
|
||||
# 名取PID
|
||||
def getPid(self, pname):
|
||||
try:
|
||||
if not self.pids:
|
||||
self.pids = psutil.pids()
|
||||
for pid in self.pids:
|
||||
if psutil.Process(pid).name() == pname:
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
# 检查端口是否占用
|
||||
def isOpen(self, port):
|
||||
import socket
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect(('127.0.0.1', int(port)))
|
||||
s.shutdown(2)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
# 检测指定进程是否存活
|
||||
def checkProcess(self, pid):
|
||||
try:
|
||||
if not self.pids:
|
||||
self.pids = psutil.pids()
|
||||
if int(pid) in self.pids:
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
def getPanelInfo(self, get=None):
|
||||
# 取面板配置
|
||||
address = public.GetLocalIp()
|
||||
try:
|
||||
try:
|
||||
port = web.ctx.host.split(':')[1]
|
||||
except:
|
||||
port = public.readFile('data/port.pl')
|
||||
except:
|
||||
port = '8888'
|
||||
domain = ''
|
||||
if os.path.exists('data/domain.conf'):
|
||||
domain = public.readFile('data/domain.conf')
|
||||
|
||||
autoUpdate = ''
|
||||
if os.path.exists('data/autoUpdate.pl'):
|
||||
autoUpdate = 'checked'
|
||||
limitip = ''
|
||||
if os.path.exists('data/limitip.conf'):
|
||||
limitip = public.readFile('data/limitip.conf')
|
||||
|
||||
templates = []
|
||||
for template in os.listdir('templates/'):
|
||||
if os.path.isdir('templates/' + template):
|
||||
templates.append(template)
|
||||
template = public.readFile('data/templates.pl')
|
||||
|
||||
check502 = ''
|
||||
if os.path.exists('data/502Task.pl'):
|
||||
check502 = 'checked'
|
||||
return {'port': port, 'address': address, 'domain': domain, 'auto': autoUpdate, '502': check502, 'limitip': limitip, 'templates': templates, 'template': template}
|
||||
|
||||
def getSystemTotal(self, interval=1):
|
||||
# 取系统统计信息
|
||||
data = self.getMemInfo()
|
||||
cpu = self.getCpuInfo(interval)
|
||||
data['cpuNum'] = cpu[1]
|
||||
data['cpuRealUsed'] = cpu[0]
|
||||
data['time'] = self.getBootTime()
|
||||
data['system'] = self.getSystemVersion()
|
||||
data['isuser'] = public.M('users').where(
|
||||
'username=?', ('admin',)).count()
|
||||
data['version'] = '0.0.1'
|
||||
return data
|
||||
|
||||
def getLoadAverage(self, get=None):
|
||||
c = os.getloadavg()
|
||||
data = {}
|
||||
data['one'] = float(c[0])
|
||||
data['five'] = float(c[1])
|
||||
data['fifteen'] = float(c[2])
|
||||
data['max'] = psutil.cpu_count() * 2
|
||||
data['limit'] = data['max']
|
||||
data['safe'] = data['max'] * 0.75
|
||||
return data
|
||||
|
||||
def getAllInfo(self, get):
|
||||
data = {}
|
||||
data['load_average'] = self.GetLoadAverage(get)
|
||||
data['title'] = self.GetTitle()
|
||||
data['network'] = self.GetNetWorkApi(get)
|
||||
data['panel_status'] = not os.path.exists(
|
||||
'/www/server/panel/data/close.pl')
|
||||
import firewalls
|
||||
ssh_info = firewalls.firewalls().GetSshInfo(None)
|
||||
data['enable_ssh_status'] = ssh_info['status']
|
||||
data['disable_ping_status'] = not ssh_info['ping']
|
||||
data['time'] = self.GetBootTime()
|
||||
# data['system'] = self.GetSystemVersion();
|
||||
# data['mem'] = self.GetMemInfo();
|
||||
data['version'] = web.ctx.session.version
|
||||
return data
|
||||
|
||||
def getTitle(self):
|
||||
titlePl = 'data/title.pl'
|
||||
title = '宝塔Linux面板'
|
||||
if os.path.exists(titlePl):
|
||||
title = public.readFile(titlePl).strip()
|
||||
return title
|
||||
|
||||
def getSystemVersion(self):
|
||||
# 取操作系统版本
|
||||
os = public.getOs()
|
||||
if os == 'darwin':
|
||||
data = public.execShell('sw_vers')[0]
|
||||
data_list = data.strip().split("\n")
|
||||
mac_version = ''
|
||||
for x in data_list:
|
||||
mac_version += x.split("\t")[1] + ' '
|
||||
return mac_version
|
||||
|
||||
version = public.readFile('/etc/redhat-release')
|
||||
if not version:
|
||||
version = public.readFile(
|
||||
'/etc/issue').strip().split("\n")[0].replace('\\n', '').replace('\l', '').strip()
|
||||
else:
|
||||
version = version.replace('release ', '').strip()
|
||||
return version
|
||||
|
||||
def getBootTime(self):
|
||||
# 取系统启动时间
|
||||
start_time = psutil.boot_time()
|
||||
run_time = time.time() - start_time
|
||||
# conf = public.readFile('/proc/uptime').split()
|
||||
tStr = float(run_time)
|
||||
min = tStr / 60
|
||||
hours = min / 60
|
||||
days = math.floor(hours / 24)
|
||||
hours = math.floor(hours - (days * 24))
|
||||
min = math.floor(min - (days * 60 * 24) - (hours * 60))
|
||||
return public.getInfo('已不间断运行: {1}天{2}小时{3}分钟', (str(int(days)), str(int(hours)), str(int(min))))
|
||||
|
||||
def getCpuInfo(self, interval=1):
|
||||
# 取CPU信息
|
||||
cpuCount = psutil.cpu_count()
|
||||
used = psutil.cpu_percent(interval=interval)
|
||||
return used, cpuCount
|
||||
|
||||
def getMemInfo(self, get=None):
|
||||
# 取内存信息
|
||||
mem = psutil.virtual_memory()
|
||||
if public.getOs() == 'darwin':
|
||||
memInfo = {
|
||||
'memTotal': mem.total / 1024 / 1024
|
||||
}
|
||||
memInfo['memRealUsed'] = memInfo['memTotal'] * (mem.percent / 100)
|
||||
else:
|
||||
memInfo = {
|
||||
'memTotal': mem.total / 1024 / 1024,
|
||||
'memFree': mem.free / 1024 / 1024,
|
||||
'memBuffers': mem.buffers / 1024 / 1024,
|
||||
'memCached': mem.cached / 1024 / 1024
|
||||
}
|
||||
|
||||
memInfo['memRealUsed'] = memInfo['memTotal'] - \
|
||||
memInfo['memFree'] - memInfo['memBuffers'] - \
|
||||
memInfo['memCached']
|
||||
return memInfo
|
||||
|
||||
def getMemUsed(self):
|
||||
# 取内存使用率
|
||||
try:
|
||||
import psutil
|
||||
mem = psutil.virtual_memory()
|
||||
|
||||
if public.getOs() == 'darwin':
|
||||
return mem.percent
|
||||
|
||||
memInfo = {'memTotal': mem.total / 1024 / 1024, 'memFree': mem.free / 1024 / 1024,
|
||||
'memBuffers': mem.buffers / 1024 / 1024, 'memCached': mem.cached / 1024 / 1024}
|
||||
tmp = memInfo['memTotal'] - memInfo['memFree'] - \
|
||||
memInfo['memBuffers'] - memInfo['memCached']
|
||||
tmp1 = memInfo['memTotal'] / 100
|
||||
return (tmp / tmp1)
|
||||
except Exception, ex:
|
||||
return 1
|
||||
|
||||
def getDiskInfo(self, get=None):
|
||||
return self.getDiskInfo2()
|
||||
# 取磁盘分区信息
|
||||
diskIo = psutil.disk_partitions()
|
||||
diskInfo = []
|
||||
|
||||
for disk in diskIo:
|
||||
if disk[1] == '/mnt/cdrom':
|
||||
continue
|
||||
if disk[1] == '/boot':
|
||||
continue
|
||||
tmp = {}
|
||||
tmp['path'] = disk[1]
|
||||
tmp['size'] = psutil.disk_usage(disk[1])
|
||||
diskInfo.append(tmp)
|
||||
return diskInfo
|
||||
|
||||
def getDiskInfo2(self):
|
||||
# 取磁盘分区信息
|
||||
temp = public.execShell(
|
||||
"df -h -P|grep '/'|grep -v tmpfs | grep -v devfs")[0]
|
||||
tempInodes = public.execShell(
|
||||
"df -i -P|grep '/'|grep -v tmpfs | grep -v devfs")[0]
|
||||
temp1 = temp.split('\n')
|
||||
tempInodes1 = tempInodes.split('\n')
|
||||
diskInfo = []
|
||||
n = 0
|
||||
cuts = ['/mnt/cdrom', '/boot', '/boot/efi', '/dev',
|
||||
'/dev/shm', '/run/lock', '/run', '/run/shm', '/run/user']
|
||||
for tmp in temp1:
|
||||
n += 1
|
||||
inodes = tempInodes1[n - 1].split()
|
||||
disk = tmp.split()
|
||||
if len(disk) < 5:
|
||||
continue
|
||||
if disk[1].find('M') != -1:
|
||||
continue
|
||||
if disk[1].find('K') != -1:
|
||||
continue
|
||||
if len(disk[5].split('/')) > 4:
|
||||
continue
|
||||
if disk[5] in cuts:
|
||||
continue
|
||||
arr = {}
|
||||
arr['path'] = disk[5]
|
||||
tmp1 = [disk[1], disk[2], disk[3], disk[4]]
|
||||
arr['size'] = tmp1
|
||||
arr['inodes'] = [inodes[1], inodes[2], inodes[3], inodes[4]]
|
||||
if disk[5] == '/':
|
||||
bootLog = os.getcwd() + '/tmp/panelBoot.pl'
|
||||
if disk[2].find('M') != -1:
|
||||
if os.path.exists(bootLog):
|
||||
os.system('rm -f ' + bootLog)
|
||||
else:
|
||||
if not os.path.exists(bootLog):
|
||||
pass
|
||||
if inodes[2] != '0':
|
||||
diskInfo.append(arr)
|
||||
return diskInfo
|
||||
|
||||
# 清理系统垃圾
|
||||
def clearSystem(self, get):
|
||||
count = total = 0
|
||||
tmp_total, tmp_count = self.ClearMail()
|
||||
count += tmp_count
|
||||
total += tmp_total
|
||||
tmp_total, tmp_count = self.ClearOther()
|
||||
count += tmp_count
|
||||
total += tmp_total
|
||||
return count, total
|
||||
|
||||
# 清理邮件日志
|
||||
def clearMail(self):
|
||||
rpath = '/var/spool'
|
||||
total = count = 0
|
||||
import shutil
|
||||
con = ['cron', 'anacron', 'mail']
|
||||
for d in os.listdir(rpath):
|
||||
if d in con:
|
||||
continue
|
||||
dpath = rpath + '/' + d
|
||||
time.sleep(0.2)
|
||||
num = size = 0
|
||||
for n in os.listdir(dpath):
|
||||
filename = dpath + '/' + n
|
||||
fsize = os.path.getsize(filename)
|
||||
size += fsize
|
||||
if os.path.isdir(filename):
|
||||
shutil.rmtree(filename)
|
||||
else:
|
||||
os.remove(filename)
|
||||
print '\t\033[1;32m[OK]\033[0m'
|
||||
num += 1
|
||||
total += size
|
||||
count += num
|
||||
return total, count
|
||||
|
||||
# 清理其它
|
||||
def clearOther(self):
|
||||
clearPath = [
|
||||
{'path': '/www/server/panel', 'find': 'testDisk_'},
|
||||
{'path': '/www/wwwlogs', 'find': 'log'},
|
||||
{'path': '/tmp', 'find': 'panelBoot.pl'},
|
||||
{'path': '/www/server/panel/install', 'find': '.rpm'}
|
||||
]
|
||||
|
||||
total = count = 0
|
||||
for c in clearPath:
|
||||
for d in os.listdir(c['path']):
|
||||
if d.find(c['find']) == -1:
|
||||
continue
|
||||
filename = c['path'] + '/' + d
|
||||
fsize = os.path.getsize(filename)
|
||||
total += fsize
|
||||
if os.path.isdir(filename):
|
||||
shutil.rmtree(filename)
|
||||
else:
|
||||
os.remove(filename)
|
||||
count += 1
|
||||
public.serviceReload()
|
||||
os.system('echo > /tmp/panelBoot.pl')
|
||||
return total, count
|
||||
|
||||
def getNetWork(self, get=None):
|
||||
# return self.GetNetWorkApi(get);
|
||||
# 取网络流量信息
|
||||
try:
|
||||
# 取网络流量信息
|
||||
networkIo = psutil.net_io_counters()[:4]
|
||||
if not "otime" in session:
|
||||
session['up'] = networkIo[0]
|
||||
session['down'] = networkIo[1]
|
||||
session['otime'] = time.time()
|
||||
|
||||
ntime = time.time()
|
||||
networkInfo = {}
|
||||
networkInfo['upTotal'] = networkIo[0]
|
||||
networkInfo['downTotal'] = networkIo[1]
|
||||
networkInfo['up'] = round(float(
|
||||
networkIo[0] - session['up']) / 1024 / (ntime - session['otime']), 2)
|
||||
networkInfo['down'] = round(
|
||||
float(networkIo[1] - session['down']) / 1024 / (ntime - session['otime']), 2)
|
||||
networkInfo['downPackets'] = networkIo[3]
|
||||
networkInfo['upPackets'] = networkIo[2]
|
||||
|
||||
# print networkIo[1], session['down'], ntime, session['otime']
|
||||
session['up'] = networkIo[0]
|
||||
session['down'] = networkIo[1]
|
||||
session['otime'] = time.time()
|
||||
|
||||
networkInfo['cpu'] = self.getCpuInfo()
|
||||
networkInfo['load'] = self.getLoadAverage(get)
|
||||
networkInfo['mem'] = self.getMemInfo(get)
|
||||
|
||||
return networkInfo
|
||||
except Exception, e:
|
||||
print e
|
||||
return None
|
||||
|
||||
def getNetWorkApi(self, get=None):
|
||||
# 取网络流量信息
|
||||
try:
|
||||
tmpfile = 'data/network.temp'
|
||||
networkIo = psutil.net_io_counters()[:4]
|
||||
|
||||
if not os.path.exists(tmpfile):
|
||||
public.writeFile(tmpfile, str(
|
||||
networkIo[0]) + '|' + str(networkIo[1]) + '|' + str(int(time.time())))
|
||||
|
||||
lastValue = public.readFile(tmpfile).split('|')
|
||||
|
||||
ntime = time.time()
|
||||
networkInfo = {}
|
||||
networkInfo['upTotal'] = networkIo[0]
|
||||
networkInfo['downTotal'] = networkIo[1]
|
||||
networkInfo['up'] = round(
|
||||
float(networkIo[0] - int(lastValue[0])) / 1024 / (ntime - int(lastValue[2])), 2)
|
||||
networkInfo['down'] = round(
|
||||
float(networkIo[1] - int(lastValue[1])) / 1024 / (ntime - int(lastValue[2])), 2)
|
||||
networkInfo['downPackets'] = networkIo[3]
|
||||
networkInfo['upPackets'] = networkIo[2]
|
||||
|
||||
public.writeFile(tmpfile, str(
|
||||
networkIo[0]) + '|' + str(networkIo[1]) + '|' + str(int(time.time())))
|
||||
|
||||
# networkInfo['cpu'] = self.GetCpuInfo(0.1)
|
||||
return networkInfo
|
||||
except:
|
||||
return None
|
||||
|
||||
def restartServer(self, get):
|
||||
if not public.isRestart():
|
||||
return public.returnMsg(False, 'EXEC_ERR_TASK')
|
||||
public.ExecShell("sync && /etc/init.d/bt stop && init 6 &")
|
||||
return public.returnMsg(True, 'SYS_REBOOT')
|
||||
|
||||
# 释放内存
|
||||
def reMemory(self, get):
|
||||
os.system('sync')
|
||||
scriptFile = 'script/rememory.sh'
|
||||
if not os.path.exists(scriptFile):
|
||||
public.downloadFile(web.ctx.session.home +
|
||||
'/script/rememory.sh', scriptFile)
|
||||
public.ExecShell("/bin/bash " + self.setupPath +
|
||||
'/panel/' + scriptFile)
|
||||
return self.GetMemInfo()
|
||||
|
||||
def getNetWorkIoData(self, start, end):
|
||||
# 取指定时间段的网络Io
|
||||
data = public.M('network').dbfile('system').where("addtime>=? AND addtime<=?", (start, end)).field(
|
||||
'id,up,down,total_up,total_down,down_packets,up_packets,addtime').order('id asc').select()
|
||||
return self.toAddtime(data)
|
||||
|
||||
def getDiskIoData(self, start, end):
|
||||
# 取指定时间段的磁盘Io
|
||||
data = public.M('diskio').dbfile('system').where("addtime>=? AND addtime<=?", (start, end)).field(
|
||||
'id,read_count,write_count,read_bytes,write_bytes,read_time,write_time,addtime').order('id asc').select()
|
||||
return self.toAddtime(data)
|
||||
|
||||
def getCpuIoData(self, start, end):
|
||||
# 取指定时间段的CpuIo
|
||||
data = public.M('cpuio').dbfile('system').where("addtime>=? AND addtime<=?",
|
||||
(start, end)).field('id,pro,mem,addtime').order('id asc').select()
|
||||
return self.toAddtime(data, True)
|
||||
|
||||
def getLoadAverageData(self, start, end):
|
||||
data = public.M('load_average').dbfile('system').where("addtime>=? AND addtime<=?", (
|
||||
start, end)).field('id,pro,one,five,fifteen,addtime').order('id asc').select()
|
||||
return self.toAddtime(data)
|
||||
|
||||
# 格式化addtime列
|
||||
def toAddtime(self, data, tomem=False):
|
||||
import time
|
||||
if tomem:
|
||||
import psutil
|
||||
mPre = (psutil.virtual_memory().total / 1024 / 1024) / 100
|
||||
length = len(data)
|
||||
he = 1
|
||||
if length > 100:
|
||||
he = 1
|
||||
if length > 1000:
|
||||
he = 3
|
||||
if length > 10000:
|
||||
he = 15
|
||||
if he == 1:
|
||||
for i in range(length):
|
||||
data[i]['addtime'] = time.strftime(
|
||||
'%m/%d %H:%M', time.localtime(float(data[i]['addtime'])))
|
||||
if tomem and data[i]['mem'] > 100:
|
||||
data[i]['mem'] = data[i]['mem'] / mPre
|
||||
|
||||
return data
|
||||
else:
|
||||
count = 0
|
||||
tmp = []
|
||||
for value in data:
|
||||
if count < he:
|
||||
count += 1
|
||||
continue
|
||||
value['addtime'] = time.strftime(
|
||||
'%m/%d %H:%M', time.localtime(float(value['addtime'])))
|
||||
if tomem and value['mem'] > 100:
|
||||
value['mem'] = value['mem'] / mPre
|
||||
tmp.append(value)
|
||||
count = 0
|
||||
return tmp
|
||||
|
||||
def setControl(self, stype, day):
|
||||
|
||||
filename = 'data/control.conf'
|
||||
|
||||
if stype == '0':
|
||||
public.execShell("rm -f " + filename)
|
||||
elif stype == '1':
|
||||
_day = int(day)
|
||||
if _day < 1:
|
||||
return public.returnJson(False, "设置失败!")
|
||||
public.writeFile(filename, day)
|
||||
elif stype == 'del':
|
||||
if not public.isRestart():
|
||||
return public.returnJson(False, '请等待所有安装任务完成再执行')
|
||||
os.remove("data/system.db")
|
||||
|
||||
sql = db.Sql().dbfile('system')
|
||||
csql = public.readFile('data/sql/system.sql')
|
||||
csql_list = csql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
sql.execute(csql_list[index], ())
|
||||
return public.returnJson(True, "监控服务已关闭")
|
||||
else:
|
||||
data = {}
|
||||
if os.path.exists(filename):
|
||||
try:
|
||||
data['day'] = int(public.readFile(filename))
|
||||
except:
|
||||
data['day'] = 30
|
||||
data['status'] = True
|
||||
else:
|
||||
data['day'] = 30
|
||||
data['status'] = False
|
||||
return public.getJson(data)
|
||||
|
||||
return public.returnJson(True, "设置成功!")
|
||||
|
||||
def versionDiff(self, old, new):
|
||||
'''
|
||||
test 测试
|
||||
new 有新版本
|
||||
none 没有新版本
|
||||
'''
|
||||
new_list = new.split('.')
|
||||
if len(new_list) > 3:
|
||||
return 'test'
|
||||
|
||||
old_list = old.split('.')
|
||||
|
||||
ret = 'none'
|
||||
for i in range(len(old_list)):
|
||||
tm_new = int(new_list[i])
|
||||
tm_old = int(new_list[i])
|
||||
if tm_new > tm_old:
|
||||
return 'new'
|
||||
return ret
|
||||
|
||||
def getServerInfo(self):
|
||||
|
||||
upAddr = 'https://raw.githubusercontent.com/midoks/mdserver-web/master/version'
|
||||
try:
|
||||
version = public.httpGet(
|
||||
upAddr + '/info.json')
|
||||
version = json.loads(version)
|
||||
return version[0]
|
||||
except Exception as e:
|
||||
print e
|
||||
return {}
|
||||
|
||||
def updateServer(self, stype, version=''):
|
||||
# 更新服务
|
||||
try:
|
||||
|
||||
if public.isUpdateLocalSoft():
|
||||
if stype == 'check' or stype == 'info' or stype == 'update':
|
||||
return public.returnJson(True, '正在安装中...', 'download')
|
||||
if stype == 'update_status':
|
||||
|
||||
data = public.readFile('tmp/panelExec.log')
|
||||
if data == 'done':
|
||||
return public.returnJson(True, '进度!', 100)
|
||||
else:
|
||||
_data = json.loads(data)
|
||||
return public.returnJson(True, '进度!', _data['pre'])
|
||||
|
||||
if os.path.exists('mdserver-web.zip'):
|
||||
return public.returnJson(True, '进度!', 100)
|
||||
|
||||
if not public.isRestart():
|
||||
return public.returnJson(False, '请等待所有安装任务完成再执行!')
|
||||
if stype == 'check':
|
||||
version_now = config.config().getVersion()
|
||||
version_new_info = self.getServerInfo()
|
||||
if not 'version' in version_new_info:
|
||||
return public.returnJson(False, '服务器数据有问题!')
|
||||
|
||||
diff = self.versionDiff(
|
||||
version_now, version_new_info['version'])
|
||||
if diff == 'new':
|
||||
return public.returnJson(True, '有新版本!', version_new_info['version'])
|
||||
elif diff == 'test':
|
||||
return public.returnJson(True, '有测试版本!', version_new_info['version'])
|
||||
else:
|
||||
return public.returnJson(False, '已经是最新,无需更新!')
|
||||
|
||||
if stype == 'info':
|
||||
version_new_info = self.getServerInfo()
|
||||
version_now = config.config().getVersion()
|
||||
|
||||
if not 'version' in version_new_info:
|
||||
return public.returnJson(False, '服务器数据有问题!')
|
||||
diff = self.versionDiff(
|
||||
version_now, version_new_info['version'])
|
||||
return public.returnJson(True, '更新信息!', version_new_info)
|
||||
|
||||
if stype == 'update':
|
||||
if version == '':
|
||||
return public.returnJson(False, '缺少版本信息!')
|
||||
|
||||
v_new_info = self.getServerInfo()
|
||||
if v_new_info['version'] != version:
|
||||
return public.returnJson(False, '更新失败,请重试!')
|
||||
|
||||
if not 'path' in v_new_info or v_new_info['path'] == '':
|
||||
return public.returnJson(False, '下载地址不存在!')
|
||||
|
||||
execstr = v_new_info['path'] + '|dl|mdserver-web.zip'
|
||||
taskAdd = (None, '下载[mdserver-web-' + v_new_info['version'] + ']',
|
||||
'download', '0', time.strftime('%Y-%m-%d %H:%M:%S'), execstr)
|
||||
|
||||
public.M('tasks').add(
|
||||
'id,name,type,status,addtime, execstr', taskAdd)
|
||||
return public.returnJson(True, '下载中...')
|
||||
|
||||
if stype == 'update_install':
|
||||
public.execShell('unzip -o mdserver-web.zip -d ./')
|
||||
public.execShell('rm -f mdserver-web.zip')
|
||||
return public.returnJson(True, '安装更新成功!')
|
||||
|
||||
return public.returnJson(False, '已经是最新,无需更新!')
|
||||
except Exception as ex:
|
||||
print ex
|
||||
return public.returnJson(False, "连接服务器失败!")
|
||||
|
||||
# 重启面板
|
||||
def reWeb(self, get):
|
||||
if not public.isRestart():
|
||||
public.returnMsg(False, '请等待所有安装任务完成再执行!')
|
||||
|
||||
# public.ExecShell('/etc/init.d/bt restart &')
|
||||
public.returnMsg(True, '执行成功!')
|
||||
|
||||
# 修复面板
|
||||
def repPanel(self, get):
|
||||
vp = ''
|
||||
if public.readFile('/www/server/panel/class/common.py').find('checkSafe') != -1:
|
||||
vp = '_pro'
|
||||
public.ExecShell("wget -O update.sh " + public.get_url() +
|
||||
"/install/update" + vp + ".sh && bash update.sh")
|
||||
if hasattr(web.ctx.session, 'getCloudPlugin'):
|
||||
del(web.ctx.session['getCloudPlugin'])
|
||||
return True
|
||||
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
import random
|
||||
import math
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||
|
||||
|
||||
class vieCode:
|
||||
__fontSize = 20 # 字体大小
|
||||
__width = 120 # 画布宽度
|
||||
__heigth = 45 # 画布高度
|
||||
__length = 4 # 验证码长度
|
||||
__draw = None # 画布
|
||||
__img = None # 图片资源
|
||||
__code = None # 验证码字符
|
||||
__str = None # 自定义验证码字符集
|
||||
__inCurve = True # 是否画干扰线
|
||||
__inNoise = True # 是否画干扰点
|
||||
__type = 2 # 验证码类型 1、纯字母 2、数字字母混合
|
||||
__fontPatn = 'class/fonts/2.ttf' # 字体
|
||||
|
||||
def GetCodeImage(self, size=80, length=4):
|
||||
'''获取验证码图片
|
||||
@param int size 验证码大小
|
||||
@param int length 验证码长度
|
||||
'''
|
||||
# 准备基础数据
|
||||
self.__length = length
|
||||
self.__fontSize = size
|
||||
self.__width = self.__fontSize * self.__length
|
||||
self.__heigth = int(self.__fontSize * 1.5)
|
||||
|
||||
# 生成验证码图片
|
||||
self.__createCode()
|
||||
self.__createImage()
|
||||
self.__createNoise()
|
||||
self.__printString()
|
||||
self.__cerateFilter()
|
||||
|
||||
return self.__img, self.__code
|
||||
|
||||
def __cerateFilter(self):
|
||||
'''模糊处理'''
|
||||
self.__img = self.__img.filter(ImageFilter.BLUR)
|
||||
filter = ImageFilter.ModeFilter(8)
|
||||
self.__img = self.__img.filter(filter)
|
||||
|
||||
def __createCode(self):
|
||||
'''创建验证码字符'''
|
||||
# 是否自定义字符集合
|
||||
if not self.__str:
|
||||
# 源文本
|
||||
number = "3456789"
|
||||
srcLetter = "qwertyuipasdfghjkzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
|
||||
srcUpper = srcLetter.upper()
|
||||
if self.__type == 1:
|
||||
self.__str = number
|
||||
else:
|
||||
self.__str = srcLetter + srcUpper + number
|
||||
|
||||
# 构造验证码
|
||||
self.__code = random.sample(self.__str, self.__length)
|
||||
|
||||
def __createImage(self):
|
||||
'''创建画布'''
|
||||
bgColor = (random.randint(200, 255), random.randint(
|
||||
200, 255), random.randint(200, 255))
|
||||
self.__img = Image.new('RGB', (self.__width, self.__heigth), bgColor)
|
||||
self.__draw = ImageDraw.Draw(self.__img)
|
||||
|
||||
def __createNoise(self):
|
||||
'''画干扰点'''
|
||||
if not self.__inNoise:
|
||||
return
|
||||
font = ImageFont.truetype(self.__fontPatn, int(self.__fontSize / 1.5))
|
||||
for i in xrange(5):
|
||||
# 杂点颜色
|
||||
noiseColor = (random.randint(150, 200), random.randint(
|
||||
150, 200), random.randint(150, 200))
|
||||
putStr = random.sample(self.__str, 2)
|
||||
for j in range(2):
|
||||
# 绘杂点
|
||||
size = (random.randint(-10, self.__width),
|
||||
random.randint(-10, self.__heigth))
|
||||
self.__draw.text(size, putStr[j], font=font, fill=noiseColor)
|
||||
pass
|
||||
|
||||
def __createCurve(self):
|
||||
'''画干扰线'''
|
||||
if not self.__inCurve:
|
||||
return
|
||||
x = y = 0
|
||||
|
||||
# 计算曲线系数
|
||||
a = random.uniform(1, self.__heigth / 2)
|
||||
b = random.uniform(-self.__width / 4, self.__heigth / 4)
|
||||
f = random.uniform(-self.__heigth / 4, self.__heigth / 4)
|
||||
t = random.uniform(self.__heigth, self.__width * 2)
|
||||
xend = random.randint(self.__width / 2, self.__width * 2)
|
||||
w = (2 * math.pi) / t
|
||||
|
||||
# 画曲线
|
||||
color = (random.randint(30, 150), random.randint(
|
||||
30, 150), random.randint(30, 150))
|
||||
for x in xrange(xend):
|
||||
if w != 0:
|
||||
for k in xrange(int(self.__heigth / 10)):
|
||||
y = a * math.sin(w * x + f) + b + self.__heigth / 2
|
||||
i = int(self.__fontSize / 5)
|
||||
while i > 0:
|
||||
px = x + i
|
||||
py = y + i + k
|
||||
self.__draw.point((px, py), color)
|
||||
i -= i
|
||||
|
||||
def __printString(self):
|
||||
'''打印验证码字符串'''
|
||||
font = ImageFont.truetype(self.__fontPatn, self.__fontSize)
|
||||
x = 0
|
||||
# 打印字符到画板
|
||||
for i in xrange(self.__length):
|
||||
# 设置字体随机颜色
|
||||
color = (random.randint(30, 150), random.randint(
|
||||
30, 150), random.randint(30, 150))
|
||||
# 计算座标
|
||||
x = random.uniform(self.__fontSize * i * 0.95,
|
||||
self.__fontSize * i * 1.1)
|
||||
y = self.__fontSize * random.uniform(0.3, 0.5)
|
||||
# 打印字符
|
||||
self.__draw.text((x, y), self.__code[i], font=font, fill=color)
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
|
||||
|
||||
|
||||
mw_start(){
|
||||
gunicorn -c setting.py app:app &
|
||||
python task.py &
|
||||
}
|
||||
|
||||
|
||||
mw_start_debug(){
|
||||
# gunicorn -c setting.py app:app
|
||||
python task.py &
|
||||
gunicorn -b :7200 app:app
|
||||
# gunicorn -c setting.py app:app
|
||||
|
||||
}
|
||||
|
||||
mw_stop()
|
||||
{
|
||||
ps -ef|grep app:app |grep -v grep|awk '{print $2}'|xargs kill -9
|
||||
ps -ef|grep task.py |grep -v grep|awk '{print $2}'|xargs kill -9
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start') mw_start;;
|
||||
'stop') mw_stop;;
|
||||
'restart')
|
||||
mw_stop
|
||||
mw_start
|
||||
;;
|
||||
'debug')
|
||||
mw_stop
|
||||
mw_start_debug
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"title":"全部",
|
||||
"type":0,
|
||||
"ps":""
|
||||
},
|
||||
{
|
||||
"title":"运行环境",
|
||||
"type":1,
|
||||
"ps":""
|
||||
},
|
||||
{
|
||||
"title":"数据软件",
|
||||
"type":2,
|
||||
"ps":""
|
||||
},
|
||||
{
|
||||
"title":"代码管理",
|
||||
"type":3,
|
||||
"ps":""
|
||||
},
|
||||
{
|
||||
"title":"系统工具",
|
||||
"type":4,
|
||||
"ps":""
|
||||
},
|
||||
{
|
||||
"title":"其他插件",
|
||||
"type":5,
|
||||
"ps":""
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
7200
|
||||
@@ -0,0 +1 @@
|
||||
True
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `backup` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`type` INTEGER,
|
||||
`name` TEXT,
|
||||
`pid` INTEGER,
|
||||
`filename` TEXT,
|
||||
`size` INTEGER,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `binding` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pid` INTEGER,
|
||||
`domain` TEXT,
|
||||
`path` TEXT,
|
||||
`port` INTEGER,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `config` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`webserver` TEXT,
|
||||
`backup_path` TEXT,
|
||||
`sites_path` TEXT,
|
||||
`status` INTEGER,
|
||||
`mysql_root` TEXT
|
||||
);
|
||||
|
||||
INSERT INTO `config` (`id`, `webserver`, `backup_path`, `sites_path`, `status`, `mysql_root`) VALUES
|
||||
(1, 'nginx', '/www/backup', '/www/wwwroot', 0, 'admin');
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `crontab` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`name` TEXT,
|
||||
`type` TEXT,
|
||||
`where1` TEXT,
|
||||
`where_hour` INTEGER,
|
||||
`where_minute` INTEGER,
|
||||
`echo` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `databases` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pid` INTEGER,
|
||||
`name` TEXT,
|
||||
`username` TEXT,
|
||||
`password` TEXT,
|
||||
`accept` TEXT,
|
||||
`ps` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `firewall` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`port` TEXT,
|
||||
`ps` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES
|
||||
(2, '80', '网站默认端口', '0000-00-00 00:00:00'),
|
||||
(3, '8888', 'WEB面板', '0000-00-00 00:00:00'),
|
||||
(4, '21', 'FTP服务', '0000-00-00 00:00:00'),
|
||||
(5, '22', 'SSH远程管理服务', '0000-00-00 00:00:00');
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ftps` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pid` INTEGER,
|
||||
`name` TEXT,
|
||||
`password` TEXT,
|
||||
`path` TEXT,
|
||||
`status` TEXT,
|
||||
`ps` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `logs` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`type` TEXT,
|
||||
`log` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sites` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`name` TEXT,
|
||||
`path` TEXT,
|
||||
`status` TEXT,
|
||||
`index` TEXT,
|
||||
`ps` TEXT,
|
||||
`edate` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `domain` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pid` INTEGER,
|
||||
`name` TEXT,
|
||||
`port` INTEGER,
|
||||
`addtime` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`username` TEXT,
|
||||
`password` TEXT,
|
||||
`login_ip` TEXT,
|
||||
`login_time` TEXT,
|
||||
`phone` TEXT,
|
||||
`email` TEXT
|
||||
);
|
||||
|
||||
INSERT INTO `users` (`id`, `username`, `password`, `login_ip`, `login_time`, `phone`, `email`) VALUES
|
||||
(1, 'admin', '21232f297a57a5a743894a0e4a801fc3', '192.168.0.10', '2016-12-10 15:12:56', 0, '287962566@qq.com');
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `tasks` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`name` TEXT,
|
||||
`type` TEXT,
|
||||
`status` TEXT,
|
||||
`addtime` TEXT,
|
||||
`start` INTEGER,
|
||||
`end` INTEGER,
|
||||
`execstr` TEXT
|
||||
);
|
||||
@@ -0,0 +1,37 @@
|
||||
CREATE TABLE IF NOT EXISTS `network` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`up` INTEGER,
|
||||
`down` INTEGER,
|
||||
`total_up` INTEGER,
|
||||
`total_down` INTEGER,
|
||||
`down_packets` INTEGER,
|
||||
`up_packets` INTEGER,
|
||||
`addtime` INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cpuio` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pro` INTEGER,
|
||||
`mem` INTEGER,
|
||||
`addtime` INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `diskio` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`read_count` INTEGER,
|
||||
`write_count` INTEGER,
|
||||
`read_bytes` INTEGER,
|
||||
`write_bytes` INTEGER,
|
||||
`read_time` INTEGER,
|
||||
`write_time` INTEGER,
|
||||
`addtime` INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `load_average` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pro` REAL,
|
||||
`one` REAL,
|
||||
`five` REAL,
|
||||
`fifteen` REAL,
|
||||
`addtime` INTEGER
|
||||
);
|
||||
@@ -0,0 +1,52 @@
|
||||
server
|
||||
{
|
||||
listen {$PORT};
|
||||
server_name {$SERVER_NAME};
|
||||
index index.php index.html index.htm default.php default.htm default.html;
|
||||
root {$ROOT_DIR};
|
||||
|
||||
#SSL-START %s
|
||||
#error_page 404/404.html;
|
||||
#SSL-END
|
||||
|
||||
#ERROR-PAGE-START %s
|
||||
error_page 404 /404.html;
|
||||
error_page 502 /502.html;
|
||||
#ERROR-PAGE-END
|
||||
|
||||
#PHP-INFO-START %s
|
||||
include enable-php-{$PHPVER}.conf;
|
||||
#PHP-INFO-END
|
||||
|
||||
#REWRITE-START %s
|
||||
include {$OR_REWRITE}/{$SERVER_NAME}.conf;
|
||||
#REWRITE-END
|
||||
|
||||
#禁止访问的文件或目录
|
||||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
|
||||
{
|
||||
return 404;
|
||||
}
|
||||
|
||||
#一键申请SSL证书验证目录相关设置
|
||||
location ~ \.well-known{
|
||||
allow all;
|
||||
}
|
||||
|
||||
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$
|
||||
{
|
||||
expires 30d;
|
||||
error_log off;
|
||||
access_log /dev/null;
|
||||
}
|
||||
|
||||
location ~ .*\\.(js|css)?$
|
||||
{
|
||||
expires 12h;
|
||||
error_log off;
|
||||
access_log /dev/null;
|
||||
}
|
||||
|
||||
access_log {$LOGPATH}/{$SERVER_NAME}.log;
|
||||
error_log {$LOGPATH}/{$SERVER_NAME}.error.log;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 55 KiB |
@@ -1,96 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="icon" type="image/x-icon" href="./static/images/logo.png">
|
||||
<link type="text/css" href="./static/css/pages.css" media="all" rel="stylesheet">
|
||||
|
||||
<title>mdserver-web | Linux开源面板</title>
|
||||
<meta name="generator" content="Jekyll v3.9.3">
|
||||
<meta property="og:title" content="Linux开源面板">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta name="description" content="Linux开源面板">
|
||||
<meta property="og:description" content="Linux开源面板">
|
||||
<link rel="canonical" href="https://www.midoks.me/">
|
||||
<meta property="og:url" content="https://www.midoks.me/">
|
||||
<meta property="og:site_name" content="Linux开源面板">
|
||||
<meta property="og:type" content="website">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta property="twitter:title" content="Linux开源面板">
|
||||
<meta name="twitter:site" content="@github">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7736695762519033"
|
||||
crossorigin="anonymous"></script>
|
||||
</head>
|
||||
|
||||
<body class="home" style="">
|
||||
|
||||
<section id="hero-spot" class="hero-spot">
|
||||
<a href="https://pages.github.com/">
|
||||
<img src="./static/images/logo.png" alt="Linux开源面板" class="logo">
|
||||
</a>
|
||||
|
||||
<h1>管理你的服务器</h1>
|
||||
|
||||
<a href="https://github.com/midoks/mdserver-web" class="help-link">Github</a>
|
||||
|
||||
<div id="slideshow">
|
||||
<img src="./static/images/mw.jpg" alt="mdserver-web" class="slide active" width="893">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="tutorial" class="tutorial">
|
||||
<h1>准备好开始了吗?</h1>
|
||||
|
||||
|
||||
<!-- ### Start of tutorials -->
|
||||
<ul id="user-site" class="tutorial-list wrapper active">
|
||||
|
||||
|
||||
<li id="terminal-step-1" class="option-terminal">
|
||||
<h4>安装面板</h4>
|
||||
|
||||
<div class="terminal">
|
||||
<div class="header"></div>
|
||||
<div class="shell">
|
||||
<p><span class="path">~</span><span class="prompt">$</span>curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh | bash</p>
|
||||
<p><span class="path">~</span><span class="prompt">$</span>mw default</p>
|
||||
<p>==================================================================</p>
|
||||
<p>MW-Panel default info!</p>
|
||||
<p>==================================================================</p>
|
||||
<p>MW-Panel-Url: http://0.0.0.0:13148/xxx</p>
|
||||
<p>username: yrajbw9q</p>
|
||||
<p>password: oqxotjgb</p>
|
||||
<p>Warning:</p>
|
||||
<p>If you cannot access the panel. </p>
|
||||
<p>release the following port (44010|888|80|443|22) in the security group.</p>
|
||||
<p>==================================================================</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<!-- End of user site tutorial -->
|
||||
|
||||
</section>
|
||||
<!-- End of tutorial section -->
|
||||
|
||||
<script src="./static/js/jquery.js"></script>
|
||||
<script>window.slides = {"mdserver-web":"mw","mw-php":"php",}</script>
|
||||
<script src="./static/js/application.js"></script>
|
||||
|
||||
<footer class="page-footer">
|
||||
<ul class="site-footer-links right">
|
||||
<li><a href="https://bbs.midoks.icu">论坛</a></li>
|
||||
</ul>
|
||||
|
||||
<ul class="site-footer-links">
|
||||
<li>mdserver-web ©2018-∞ Linux面板</li>
|
||||
<li><a href="https://github.com/midoks/mdserver-web">Github</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 181 B |
@@ -0,0 +1,16 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('abkill');">服务</p>
|
||||
<p onclick="pluginInitD('abkill');">自启动</p>
|
||||
<p onclick="pluginConfig('abkill');">黑名单</p>
|
||||
<p onclick="pluginConfig('abkill');">异常日志</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=abkill&f=js/abkill.js");
|
||||
</script>
|
||||
@@ -0,0 +1,172 @@
|
||||
# coding: utf-8
|
||||
|
||||
import time
|
||||
import random
|
||||
import os
|
||||
import urllib
|
||||
import binascii
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
app_debug = False
|
||||
if public.getOs() == 'darwin':
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'abkill'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getInitDFile():
|
||||
if app_debug:
|
||||
return '/tmp/' + getPluginName()
|
||||
return '/etc/init.d/' + getPluginName()
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def initDreplace():
|
||||
initd_file = getInitDFile()
|
||||
|
||||
if not os.path.exists(initd_file):
|
||||
return getServerDir()
|
||||
|
||||
return initd_file
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def csvnOp(method):
|
||||
|
||||
if app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_initd_csvn = '/etc/init.d/csvn'
|
||||
_initd_csvn_httpd = '/etc/init.d/csvn-httpd'
|
||||
#_csvn = getServerDir() + '/bin/csvn'
|
||||
#_csvn_httpd = getServerDir() + '/bin/csvn-httpd'
|
||||
|
||||
ret_csvn_httpd = public.execShell(_initd_csvn_httpd + ' ' + method)
|
||||
# ret_csvn = public.execShell(_initd_csvn + ' ' + method)
|
||||
subprocess.Popen(_initd_csvn + ' ' + method,
|
||||
stdout=subprocess.PIPE, shell=True)
|
||||
if ret_csvn_httpd[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def start():
|
||||
return csvnOp('start')
|
||||
|
||||
|
||||
def stop():
|
||||
return csvnOp('stop')
|
||||
|
||||
|
||||
def restart():
|
||||
return csvnOp('restart')
|
||||
|
||||
|
||||
def reload():
|
||||
return csvnOp('reload')
|
||||
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_initd_csvn = '/etc/init.d/csvn'
|
||||
_initd_csvn_httpd = '/etc/init.d/csvn-httpd'
|
||||
|
||||
if os.path.exists(_initd_csvn) and os.path.exists(_initd_csvn_httpd):
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_csvn = getServerDir() + '/bin/csvn'
|
||||
_csvn_httpd = getServerDir() + '/bin/csvn-httpd'
|
||||
|
||||
ret_csvn = public.execShell(_csvn + ' install')
|
||||
ret_csvn_httpd = public.execShell(_csvn_httpd + ' install')
|
||||
if ret_csvn[1] == '' and ret_csvn_httpd[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_csvn = getServerDir() + '/bin/csvn'
|
||||
_csvn_httpd = getServerDir() + '/bin/csvn-httpd'
|
||||
|
||||
ret_csvn = public.execShell(_csvn + ' remove')
|
||||
ret_csvn_httpd = public.execShell(_csvn_httpd + ' remove')
|
||||
return 'ok'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
elif func == 'start':
|
||||
print start()
|
||||
elif func == 'stop':
|
||||
print stop()
|
||||
elif func == 'restart':
|
||||
print restart()
|
||||
elif func == 'reload':
|
||||
print reload()
|
||||
elif func == 'initd_status':
|
||||
print initdStatus()
|
||||
elif func == 'initd_install':
|
||||
print initdInstall()
|
||||
elif func == 'initd_uninstall':
|
||||
print initdUinstall()
|
||||
else:
|
||||
print 'fail'
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"sort": 7,
|
||||
"ps": "异常程序监控和KILL",
|
||||
"shell": "install.sh",
|
||||
"name": "abkill",
|
||||
"title": "异常程序监控",
|
||||
"versions": "0.1",
|
||||
"updates":"0.1",
|
||||
"tip": "soft",
|
||||
"checks": "server/abkill",
|
||||
"author": "midoks",
|
||||
"date": "201-04-01",
|
||||
"home": "https://www.collab.net",
|
||||
"type": "异常程序监控和KILL",
|
||||
"pid": "4"
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
|
||||
ak_path={$SERVER_PATH}/abkill
|
||||
|
||||
ak_start(){
|
||||
isStart=$(ps aux |grep 'abkill.py'|grep -v grep|awk '{print $2}')
|
||||
if [ "$isStart" == '' ];then
|
||||
echo -e "Starting abkill... \c"
|
||||
cd $ak_path && nohup python abkill.py >> $ak_path/task.log 2>&1 &
|
||||
sleep 0.3
|
||||
isStart=$(ps aux |grep 'abkill.py'|grep -v grep|awk '{print $2}')
|
||||
if [ "$isStart" == '' ];then
|
||||
echo -e "\033[31mfailed\033[0m"
|
||||
echo '------------------------------------------------------'
|
||||
tail -n 20 $ak_path/task.log
|
||||
echo '------------------------------------------------------'
|
||||
echo -e "\033[31mError: abkill service startup failed.\033[0m"
|
||||
return;
|
||||
fi
|
||||
echo -e "\033[32mdone\033[0m"
|
||||
else
|
||||
echo "Starting abkill(pid $isStart) already running"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
ak_stop()
|
||||
{
|
||||
echo -e "Stopping abkill... \c";
|
||||
pids=$(ps aux | grep 'abkill.py' | grep -v grep|awk '{print $2}')
|
||||
arr=($pids)
|
||||
|
||||
for p in ${arr[@]}
|
||||
do
|
||||
kill -9 $p
|
||||
done
|
||||
echo -e "\033[32mdone\033[0m"
|
||||
|
||||
}
|
||||
|
||||
ak_status()
|
||||
{
|
||||
isStart=$(ps aux|grep 'abkill.py'|grep -v grep|awk '{print $2}')
|
||||
if [ "$isStart" != '' ];then
|
||||
echo -e "\033[32mabkill (pid $(echo $isStart)) already running\033[0m"
|
||||
else
|
||||
echo -e "\033[31mabkill not running\033[0m"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
ak_reload()
|
||||
{
|
||||
isStart=$(ps aux|grep 'abkill.py'|grep -v grep|awk '{print $2}')
|
||||
|
||||
if [ "$isStart" != '' ];then
|
||||
ak_stop
|
||||
ak_start
|
||||
else
|
||||
echo -e "\033[31mmw not running\033[0m"
|
||||
mw_start
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
'start') ak_start;;
|
||||
'stop') ak_stop;;
|
||||
'reload') ak_reload;;
|
||||
'restart')
|
||||
ak_stop
|
||||
sleep 0.3
|
||||
ak_start;;
|
||||
'status') ak_status;;
|
||||
esac
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/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")
|
||||
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
Install_abkill()
|
||||
{
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
mkdir -p $serverPath/abkill
|
||||
echo '0.1' > $serverPath/abkill/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_abkill()
|
||||
{
|
||||
rm -f $serverPath/abkill
|
||||
echo "卸载完成" > $install_tmp
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_abkill
|
||||
else
|
||||
Uninstall_abkill
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
pluginService('abkill');
|
||||
@@ -0,0 +1,85 @@
|
||||
# coding: utf-8
|
||||
|
||||
# 使用示例:
|
||||
# 1、将此文件重命名为btkill.py , 然后上传到服务器/root目录
|
||||
# 2、执行 python /root/btkill.py
|
||||
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
sys.path.append("/usr/local/lib/python2.7/site-packages")
|
||||
import psutil
|
||||
|
||||
|
||||
class btkill:
|
||||
__limit = 10 # Cpu使用率触发上限
|
||||
__vmsize = 1048576 / 4 # 虚拟内存触发上限(字节)
|
||||
|
||||
def checkMain(self):
|
||||
pids = psutil.pids()
|
||||
print pids
|
||||
num = 0
|
||||
for pid in pids:
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
if p.exe() == "":
|
||||
continue
|
||||
name = p.name()
|
||||
if self.whiteList(name):
|
||||
continue
|
||||
cputimes = p.cpu_times()
|
||||
if cputimes.user < 0.1:
|
||||
continue
|
||||
print p
|
||||
percent = p.cpu_percent(interval=1)
|
||||
vm = p.memory_info().vms
|
||||
if percent > self.__limit or vm > self.__vmsize:
|
||||
log = time.strftime('%Y-%m-%d %X', time.localtime()) + " (PID=" + str(
|
||||
pid) + ", NAME=" + name + ", VMS=" + str(vm) + ", PERCENT=" + str(percent) + "%)"
|
||||
# p.kill()
|
||||
num += 1
|
||||
print log + " >> killed\n"
|
||||
except Exception as ex:
|
||||
print str(ex)
|
||||
return num
|
||||
|
||||
# 检查白名单
|
||||
def whiteList(self, name):
|
||||
wlist = ['yum', 'apt-get', 'apt', 'redis-cli', 'memcached', 'sshd', 'vm', 'vim', 'htop', 'top', 'sh', 'bash', 'zip', 'gzip', 'rsync',
|
||||
'tar', 'unzip', 'php', 'composer', 'pkill', 'mongo', 'mongod', 'php-fpm', 'nginx', 'httpd', 'lsof', 'ps', 'redis-server',
|
||||
'mysqld', 'mysqld_safe', 'mysql', 'pure-ftpd', 'sparse_dd', 'stunnel', 'squeezed', 'vncterm', 'awk', 'ruby', 'postgres',
|
||||
'mpathalert', 'vncterm', 'multipathd', 'fe', 'elasticsyslog', 'syslogd', 'v6d', 'xapi', 'screen', 'runsvdir', 'svlogd',
|
||||
'java', 'udevd', 'ntpd', 'irqbalance', 'qmgr', 'wpa_supplicant', 'mysqld_safe', 'sftp-server', 'lvmetad', 'gitlab-web',
|
||||
'pure-ftpd', 'auditd', 'master', 'dbus-daemon', 'tapdisk', 'sshd', 'init', 'ksoftirqd', 'kworker', 'kmpathd',
|
||||
'kmpath_handlerd', 'python', 'kdmflush', 'bioset', 'crond', 'kthreadd', 'migration', 'rcu_sched', 'kjournald',
|
||||
'gcc', 'gcc++', 'nginx', 'mysqld', 'php-cgi', 'login', 'firewalld', 'iptables', 'systemd', 'network', 'dhclient',
|
||||
'systemd-journald', 'NetworkManager', 'systemd-logind', 'systemd-udevd', 'polkitd', 'tuned', 'rsyslogd', 'AliYunDunUpdate', 'AliYunDun', 'sendmail']
|
||||
wslist = ['vif', 'qemu', 'scsi_eh', 'xcp',
|
||||
'xen', 'docker', 'yunsuo', 'aliyun', 'PM2']
|
||||
|
||||
for key in wlist:
|
||||
if key == name:
|
||||
return True
|
||||
|
||||
for key in wslist:
|
||||
if name.find(key) != -1:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# 开始处理
|
||||
def start(self):
|
||||
num = 0
|
||||
while True:
|
||||
num += self.checkMain()
|
||||
print "查杀完成, 共查杀[" + str(num) + "]个异常进程!"
|
||||
time.sleep(3)
|
||||
print '======================================='
|
||||
print "查杀完成, 共查杀[" + str(num) + "]个异常进程!"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print "正在检测异常进程..."
|
||||
print '======================================='
|
||||
c = btkill()
|
||||
c.start()
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export LC_CTYPE=zh_CN.UTF-8
|
||||
|
||||
|
||||
REPOS="$1"
|
||||
REV="$2"
|
||||
TXN_NAME="$3"
|
||||
|
||||
|
||||
WEB_PATH={$PROJECT_DIR}/wwwroot/$REPOS
|
||||
SVN_PATH=http://127.0.0.1:{$PORT}/svn/$REPOS
|
||||
|
||||
if [ ! -d $WEB_PATH ]; then
|
||||
svn co $SVN_PATH $WEB_PATH \
|
||||
--username={$CSVN_USER} \
|
||||
--password={$CSVN_PWD} \
|
||||
--no-auth-cache \
|
||||
--non-interactive
|
||||
fi
|
||||
|
||||
cd $WEB_PATH && svn update --username={$CSVN_USER} --password={$CSVN_PWD}
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
|
||||
REPOS="$1"
|
||||
REV="$2"
|
||||
TXN_NAME="$3"
|
||||
|
||||
REPOS_NAME=${REPOS##*/}
|
||||
|
||||
sh -x $REPOS/hooks/commit $REPOS_NAME $REV $TXN_NAME 2>$REPOS/sh.log
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,37 @@
|
||||
<style type="text/css">
|
||||
.outline_no {
|
||||
outline:none;
|
||||
}
|
||||
</style>
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('csvn');">服务</p>
|
||||
<p onclick="pluginInitD('csvn');">自启动</p>
|
||||
<p onclick="csvnEdit();">手动编辑</p>
|
||||
<p onclick="csvnUserList(1);">用户管理</p>
|
||||
<p onclick="csvnProjectList(1);">项目管理</p>
|
||||
<p onclick="csvnReadme();">使用说明</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
resetPluginWinWidth(700);
|
||||
|
||||
$.getScript( "/plugins/file?name=csvn&f=js/csvn.js");
|
||||
|
||||
function csvnReadme(){
|
||||
var html = '<p>* 注意:在启动时会比较慢,需要耐心等待一会</p>';
|
||||
html += '<p>* 注意:csvn需要java环境,在安装会自动检查并安装</p>';
|
||||
html += '<p>* 注意:默认后台密码admin:admin,最好马上修改</p>';
|
||||
html += '<p>* 注意:牢记admin的密码,在后csvn的管理后台和这里不同步</p>';
|
||||
html += '<p>* 注意:在这里添加用户和csvn后台并不同步</p>';
|
||||
html += '<p>* 注意:项目管理的地址一般是正确的,但在特殊环境下,地址可能不一致</p>';
|
||||
|
||||
$('.bt-w-main .soft-man-con').html(html);
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,692 @@
|
||||
# coding: utf-8
|
||||
|
||||
import time
|
||||
import random
|
||||
import os
|
||||
import urllib
|
||||
import binascii
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
app_debug = False
|
||||
if public.getOs() == 'darwin':
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'csvn'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getInitDFile():
|
||||
if app_debug:
|
||||
return '/tmp/' + getPluginName()
|
||||
return '/etc/init.d/' + getPluginName()
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def initDreplace():
|
||||
initd_file = getInitDFile()
|
||||
|
||||
if not os.path.exists(initd_file):
|
||||
return getServerDir()
|
||||
|
||||
return initd_file
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def csvnOp(method):
|
||||
|
||||
if app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_initd_csvn = '/etc/init.d/csvn'
|
||||
_initd_csvn_httpd = '/etc/init.d/csvn-httpd'
|
||||
#_csvn = getServerDir() + '/bin/csvn'
|
||||
#_csvn_httpd = getServerDir() + '/bin/csvn-httpd'
|
||||
|
||||
ret_csvn_httpd = public.execShell(_initd_csvn_httpd + ' ' + method)
|
||||
# ret_csvn = public.execShell(_initd_csvn + ' ' + method)
|
||||
subprocess.Popen(_initd_csvn + ' ' + method,
|
||||
stdout=subprocess.PIPE, shell=True)
|
||||
if ret_csvn_httpd[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def start():
|
||||
return csvnOp('start')
|
||||
|
||||
|
||||
def stop():
|
||||
return csvnOp('stop')
|
||||
|
||||
|
||||
def restart():
|
||||
return csvnOp('restart')
|
||||
|
||||
|
||||
def reload():
|
||||
return csvnOp('reload')
|
||||
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_initd_csvn = '/etc/init.d/csvn'
|
||||
_initd_csvn_httpd = '/etc/init.d/csvn-httpd'
|
||||
|
||||
if os.path.exists(_initd_csvn) and os.path.exists(_initd_csvn_httpd):
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_csvn = getServerDir() + '/bin/csvn'
|
||||
_csvn_httpd = getServerDir() + '/bin/csvn-httpd'
|
||||
|
||||
ret_csvn = public.execShell(_csvn + ' install')
|
||||
ret_csvn_httpd = public.execShell(_csvn_httpd + ' install')
|
||||
if ret_csvn[1] == '' and ret_csvn_httpd[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_csvn = getServerDir() + '/bin/csvn'
|
||||
_csvn_httpd = getServerDir() + '/bin/csvn-httpd'
|
||||
|
||||
ret_csvn = public.execShell(_csvn + ' remove')
|
||||
ret_csvn_httpd = public.execShell(_csvn_httpd + ' remove')
|
||||
return 'ok'
|
||||
|
||||
|
||||
def csvnEdit():
|
||||
data = {}
|
||||
data['svn_access_file'] = getServerDir() + '/data/conf/svn_access_file'
|
||||
data['commit_tpl'] = getPluginDir() + '/hook/commit.tpl'
|
||||
data['post_commit_tpl'] = getPluginDir() + '/hook/post-commit.tpl'
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def userAdd():
|
||||
args = getArgs()
|
||||
if not 'username' in args:
|
||||
return 'name missing'
|
||||
|
||||
if not 'password' in args:
|
||||
return 'password missing'
|
||||
|
||||
htpasswd = getServerDir() + "/bin/htpasswd"
|
||||
svn_auth_file = getServerDir() + "/data/conf/svn_auth_file"
|
||||
cmd = htpasswd + ' -b ' + svn_auth_file + ' ' + \
|
||||
args['username'] + ' ' + args['password']
|
||||
data = public.execShell(cmd)
|
||||
# print data
|
||||
if data[0] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def userDel():
|
||||
args = getArgs()
|
||||
if not 'username' in args:
|
||||
return 'name missing'
|
||||
|
||||
htpasswd = getServerDir() + "/bin/htpasswd"
|
||||
svn_auth_file = getServerDir() + "/data/conf/svn_auth_file"
|
||||
cmd = htpasswd + ' -D ' + svn_auth_file + ' ' + args['username']
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def getAllUser(search=''):
|
||||
svn_auth_file = getServerDir() + '/data/conf/svn_auth_file'
|
||||
if not os.path.exists(svn_auth_file):
|
||||
return public.getJson([])
|
||||
auth = public.readFile(svn_auth_file)
|
||||
auth = auth.strip()
|
||||
auth_list = auth.split("\n")
|
||||
|
||||
ulist = []
|
||||
for x in range(len(auth_list)):
|
||||
tmp = auth_list[x].split(':')
|
||||
if search != '':
|
||||
if tmp[0].find(search) != -1:
|
||||
ulist.append(tmp[0])
|
||||
else:
|
||||
ulist.append(tmp[0])
|
||||
return ulist
|
||||
|
||||
|
||||
def userList():
|
||||
import math
|
||||
args = getArgs()
|
||||
|
||||
page = 1
|
||||
page_size = 10
|
||||
search = ''
|
||||
if 'page' in args:
|
||||
page = int(args['page'])
|
||||
|
||||
if 'page_size' in args:
|
||||
page_size = int(args['page_size'])
|
||||
|
||||
if 'search' in args:
|
||||
search = args['search']
|
||||
|
||||
ulist = getAllUser(search)
|
||||
ulist_sum = len(ulist)
|
||||
|
||||
page_info = {'count': ulist_sum, 'p': page,
|
||||
'row': 10, 'tojs': 'csvnUserList'}
|
||||
data = {}
|
||||
data['list'] = public.getPage(page_info)
|
||||
data['page'] = page
|
||||
data['page_size'] = page_size
|
||||
data['page_count'] = int(math.ceil(ulist_sum / page_size))
|
||||
start = (page - 1) * page_size
|
||||
|
||||
data['data'] = ulist[start:start + page_size]
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def projectAdd():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'project name missing'
|
||||
path = getServerDir() + '/bin/svnadmin'
|
||||
dest = getServerDir() + '/data/repositories/' + args['name']
|
||||
cmd = path + ' create ' + dest
|
||||
data = public.execShell(cmd)
|
||||
if data[1] == '':
|
||||
public.execShell('chown -R csvn:csvn ' + dest)
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def projectDel():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'project name missing'
|
||||
|
||||
dest = getServerDir() + '/data/repositories/' + args['name']
|
||||
cmd = 'rm -rf ' + dest
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def getHttpPort():
|
||||
http_main_conf = getServerDir() + '/data/conf/csvn_main_httpd.conf'
|
||||
try:
|
||||
if os.path.exists(http_main_conf):
|
||||
content = public.readFile(http_main_conf)
|
||||
return re.search('Listen\s(\d+)', content).groups()[0]
|
||||
except Exception as e:
|
||||
pass # print e
|
||||
return '80'
|
||||
|
||||
|
||||
def getCsvnPort():
|
||||
http_main_conf = getServerDir() + '/data/conf/csvn-wrapper.conf'
|
||||
try:
|
||||
if os.path.exists(http_main_conf):
|
||||
content = public.readFile(http_main_conf)
|
||||
return re.search('wrapper.java.additional.3=-Djetty.port=(\d+)', content).groups()[0]
|
||||
except Exception as e:
|
||||
pass # print e
|
||||
return '3343'
|
||||
|
||||
|
||||
def getALlProjectList(search=''):
|
||||
path = getServerDir() + '/data/repositories'
|
||||
dlist = []
|
||||
if os.path.exists(path):
|
||||
for filename in os.listdir(path):
|
||||
tmp = {}
|
||||
filePath = path + '/' + filename
|
||||
if os.path.isdir(filePath):
|
||||
if search == '':
|
||||
tmp['name'] = filename
|
||||
dlist.append(tmp)
|
||||
else:
|
||||
if filename.find(search) != -1:
|
||||
tmp['name'] = filename
|
||||
dlist.append(tmp)
|
||||
return dlist
|
||||
|
||||
|
||||
def checkProjectListIsHasScript(data):
|
||||
dlen = len(data)
|
||||
for x in range(dlen):
|
||||
path = getServerDir() + '/data/repositories/' + \
|
||||
data[x]['name'] + '/hooks/post-commit'
|
||||
if os.path.exists(path):
|
||||
data[x]['has_hook'] = True
|
||||
else:
|
||||
data[x]['has_hook'] = False
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def projectList():
|
||||
import math
|
||||
args = getArgs()
|
||||
|
||||
page = 1
|
||||
page_size = 10
|
||||
search = ''
|
||||
if 'page' in args:
|
||||
page = int(args['page'])
|
||||
|
||||
if 'page_size' in args:
|
||||
page_size = int(args['page_size'])
|
||||
|
||||
if 'search' in args:
|
||||
search = args['search']
|
||||
|
||||
dlist = getALlProjectList(search)
|
||||
dlist_sum = len(dlist)
|
||||
|
||||
start = (page - 1) * page_size
|
||||
ret_data = dlist[start:start + page_size]
|
||||
ret_data = checkProjectListIsHasScript(ret_data)
|
||||
|
||||
data = {}
|
||||
data['data'] = ret_data
|
||||
data['list'] = public.getPage(
|
||||
{'count': dlist_sum, 'p': page, 'row': 10, 'tojs': 'csvnProjectList'})
|
||||
data['ip'] = public.getLocalIp()
|
||||
data['port'] = getHttpPort()
|
||||
data['csvn_port'] = getCsvnPort()
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def getAllAclList():
|
||||
svn_access_file = getServerDir() + '/data/conf/svn_access_file'
|
||||
aData = public.readFile(svn_access_file)
|
||||
aData = re.sub('#.*', '', aData)
|
||||
aData = aData.strip().split('[')[1:]
|
||||
allAcl = {}
|
||||
for i in range(len(aData)):
|
||||
oData = aData[i].strip().split(']')
|
||||
name = oData[0].strip('/').strip(':')
|
||||
if oData[1] == '':
|
||||
allAcl[name] = []
|
||||
else:
|
||||
user = oData[1].strip().split('\n')
|
||||
userAll = []
|
||||
for iu in range(len(user)):
|
||||
ulist = user[iu].split('=')
|
||||
utmp = {}
|
||||
utmp['user'] = ulist[0].strip()
|
||||
utmp['acl'] = ulist[1].strip()
|
||||
userAll.append(utmp)
|
||||
allAcl[name] = userAll
|
||||
return allAcl
|
||||
|
||||
|
||||
def makeAclFile(content):
|
||||
# print content
|
||||
svn_access_file = getServerDir() + '/data/conf/svn_access_file'
|
||||
tmp = "\n"
|
||||
for k, v in content.items():
|
||||
if k == '':
|
||||
tmp += "[/]\n"
|
||||
else:
|
||||
tmp += "[" + k + ":/]\n"
|
||||
|
||||
for iv in range(len(v)):
|
||||
tmp += v[iv]['user'] + ' = ' + v[iv]['acl'] + "\n"
|
||||
tmp += "\n"
|
||||
# svn_tmp_path = getServerDir() + '/data/conf/svn_access_file.log'
|
||||
return public.writeFile(svn_access_file, tmp)
|
||||
|
||||
|
||||
def projectAclList():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'name missing!'
|
||||
name = args['name']
|
||||
acl = getAllAclList()
|
||||
|
||||
if name in acl:
|
||||
return public.getJson(acl[name])
|
||||
else:
|
||||
return 'fail'
|
||||
|
||||
|
||||
def projectAclAdd():
|
||||
args = getArgs()
|
||||
if not 'uname' in args:
|
||||
return 'username missing'
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
uname = args['uname']
|
||||
pname = args['pname']
|
||||
|
||||
ulist = getAllUser()
|
||||
if not uname in ulist:
|
||||
return uname + " user not exists!"
|
||||
|
||||
acl = getAllAclList()
|
||||
|
||||
tmp_acl = {'user': uname, 'acl': 'rw'}
|
||||
if not pname in acl:
|
||||
acl[pname] = [tmp_acl]
|
||||
makeAclFile(acl)
|
||||
return 'ok'
|
||||
|
||||
tmp = acl[pname]
|
||||
tmp_len = len(tmp)
|
||||
|
||||
if tmp_len == 0:
|
||||
acl[pname] = [tmp_acl]
|
||||
else:
|
||||
is_have = False
|
||||
for x in range(tmp_len):
|
||||
if tmp[x]['user'] == uname:
|
||||
is_have = True
|
||||
return uname + ' users already exist!'
|
||||
if not is_have:
|
||||
tmp.append(tmp_acl)
|
||||
acl[pname] = tmp
|
||||
|
||||
makeAclFile(acl)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectAclDel():
|
||||
args = getArgs()
|
||||
if not 'uname' in args:
|
||||
return 'username missing'
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
|
||||
uname = args['uname']
|
||||
pname = args['pname']
|
||||
|
||||
ulist = getAllUser()
|
||||
if not uname in ulist:
|
||||
return uname + " user not exists!"
|
||||
|
||||
acl = getAllAclList()
|
||||
|
||||
if not pname in acl:
|
||||
return 'project not exists!'
|
||||
|
||||
tmp = acl[pname]
|
||||
tmp_len = len(tmp)
|
||||
if tmp_len == 0:
|
||||
return 'project no have user:' + uname
|
||||
else:
|
||||
is_have = False
|
||||
rtmp = []
|
||||
for x in range(tmp_len):
|
||||
if tmp[x]['user'] != uname:
|
||||
rtmp.append(tmp[x])
|
||||
acl[pname] = rtmp
|
||||
makeAclFile(acl)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectAclSet():
|
||||
args = getArgs()
|
||||
if not 'uname' in args:
|
||||
return 'username missing'
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
if not 'acl' in args:
|
||||
return 'acl missing'
|
||||
|
||||
uname = args['uname']
|
||||
pname = args['pname']
|
||||
up_acl = args['acl']
|
||||
|
||||
ulist = getAllUser()
|
||||
if not uname in ulist:
|
||||
return uname + " user not exists!"
|
||||
|
||||
acl = getAllAclList()
|
||||
|
||||
if not pname in acl:
|
||||
return 'project not exists!'
|
||||
|
||||
tmp = acl[pname]
|
||||
tmp_len = len(tmp)
|
||||
if tmp_len == 0:
|
||||
return 'project no have user:' + uname
|
||||
else:
|
||||
is_have = False
|
||||
for x in range(tmp_len):
|
||||
if tmp[x]['user'] == uname:
|
||||
tmp[x]['acl'] = up_acl
|
||||
acl[pname] = tmp
|
||||
makeAclFile(acl)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def getCsvnUser():
|
||||
user = 'admin_sync'
|
||||
|
||||
acl = getAllAclList()
|
||||
if '' in acl:
|
||||
tmp = acl['']
|
||||
is_has = False
|
||||
for data in tmp:
|
||||
if data['user'] == user:
|
||||
is_has = True
|
||||
if not is_has:
|
||||
tmp.append({'user': user, 'acl': 'r'})
|
||||
acl[''] = tmp
|
||||
makeAclFile(acl)
|
||||
return user
|
||||
|
||||
|
||||
def getCsvnPwd(user):
|
||||
if app_debug:
|
||||
return user + '123'
|
||||
pwd_file = 'data/csvn_sync.pl'
|
||||
|
||||
if os.path.exists(pwd_file):
|
||||
return public.readFile(pwd_file).strip()
|
||||
|
||||
import time
|
||||
cur_time = time.time()
|
||||
rand_pwd = public.md5(str(cur_time))
|
||||
pwd = user + rand_pwd[:5]
|
||||
|
||||
htpasswd = getServerDir() + "/bin/htpasswd"
|
||||
svn_auth_file = getServerDir() + "/data/conf/svn_auth_file"
|
||||
cmd = htpasswd + ' -b ' + svn_auth_file + ' ' + user + ' ' + pwd
|
||||
data = public.execShell(cmd)
|
||||
|
||||
public.writeFile(pwd_file, pwd)
|
||||
return pwd
|
||||
|
||||
|
||||
def projectScriptLoad():
|
||||
|
||||
args = getArgs()
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
|
||||
post_commit_tpl = getPluginDir() + '/hook/post-commit.tpl'
|
||||
hook_path = getServerDir() + '/data/repositories/' + \
|
||||
args['pname'] + '/hooks'
|
||||
post_commit_file = hook_path + '/post-commit'
|
||||
|
||||
pct_content = public.readFile(post_commit_tpl)
|
||||
public.writeFile(post_commit_file, pct_content)
|
||||
public.execShell('chmod 777 ' + post_commit_file)
|
||||
|
||||
commit_tpl = getPluginDir() + '/hook/commit.tpl'
|
||||
commit_file = hook_path + '/commit'
|
||||
|
||||
ct_content = public.readFile(commit_tpl)
|
||||
ct_content = ct_content.replace('{$PROJECT_DIR}', public.getRootDir())
|
||||
ct_content = ct_content.replace('{$PORT}', getHttpPort())
|
||||
ct_content = ct_content.replace('{$CSVN_USER}', getCsvnUser())
|
||||
ct_content = ct_content.replace('{$CSVN_PWD}', getCsvnPwd(getCsvnUser()))
|
||||
|
||||
public.writeFile(commit_file, ct_content)
|
||||
public.execShell('chmod 777 ' + commit_file)
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectScriptUnload():
|
||||
args = getArgs()
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
|
||||
post_commit_file = getServerDir() + '/data/repositories/' + '/' + \
|
||||
args['pname'] + '/hooks/post-commit'
|
||||
public.execShell('rm -f ' + post_commit_file)
|
||||
|
||||
commit_file = getServerDir() + '/data/repositories/' + '/' + \
|
||||
args['pname'] + '/hooks/commit'
|
||||
public.execShell('rm -f ' + commit_file)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectScriptEdit():
|
||||
args = getArgs()
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
|
||||
data = {}
|
||||
commit_file = getServerDir() + '/data/repositories/' + \
|
||||
args['pname'] + '/hooks/commit'
|
||||
if os.path.exists(commit_file):
|
||||
data['status'] = True
|
||||
data['path'] = commit_file
|
||||
else:
|
||||
data['status'] = False
|
||||
data['msg'] = 'file does not exist'
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def projectScriptDebug():
|
||||
args = getArgs()
|
||||
if not 'pname' in args:
|
||||
return 'project name missing'
|
||||
|
||||
data = {}
|
||||
commit_log = getServerDir() + '/data/repositories/' + \
|
||||
args['pname'] + '/sh.log'
|
||||
if os.path.exists(commit_log):
|
||||
data['status'] = True
|
||||
data['path'] = commit_log
|
||||
else:
|
||||
data['status'] = False
|
||||
data['msg'] = 'file does not exist'
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
elif func == 'start':
|
||||
print start()
|
||||
elif func == 'stop':
|
||||
print stop()
|
||||
elif func == 'restart':
|
||||
print restart()
|
||||
elif func == 'reload':
|
||||
print reload()
|
||||
elif func == 'initd_status':
|
||||
print initdStatus()
|
||||
elif func == 'initd_install':
|
||||
print initdInstall()
|
||||
elif func == 'initd_uninstall':
|
||||
print initdUinstall()
|
||||
elif func == 'csvn_edit':
|
||||
print csvnEdit()
|
||||
elif func == 'user_list':
|
||||
print userList()
|
||||
elif func == 'user_add':
|
||||
print userAdd()
|
||||
elif func == 'user_del':
|
||||
print userDel()
|
||||
elif func == 'project_list':
|
||||
print projectList()
|
||||
elif func == 'project_del':
|
||||
print projectDel()
|
||||
elif func == 'project_add':
|
||||
print projectAdd()
|
||||
elif func == 'project_acl_list':
|
||||
print projectAclList()
|
||||
elif func == 'project_acl_add':
|
||||
print projectAclAdd()
|
||||
elif func == 'project_acl_del':
|
||||
print projectAclDel()
|
||||
elif func == 'project_acl_set':
|
||||
print projectAclSet()
|
||||
elif func == 'project_script_load':
|
||||
print projectScriptLoad()
|
||||
elif func == 'project_script_unload':
|
||||
print projectScriptUnload()
|
||||
elif func == 'project_script_edit':
|
||||
print projectScriptEdit()
|
||||
elif func == 'project_script_debug':
|
||||
print projectScriptDebug()
|
||||
else:
|
||||
print 'fail'
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"sort": 7,
|
||||
"ps": "最流行的SVN代码共享管理软件",
|
||||
"shell": "install.sh",
|
||||
"name": "csvn",
|
||||
"title": "CSVN",
|
||||
"versions": "5.1",
|
||||
"updates":"5.1.4",
|
||||
"tip": "soft",
|
||||
"checks": "server/csvn",
|
||||
"author": "midoks",
|
||||
"date": "2017-04-01",
|
||||
"home": "https://www.collab.net",
|
||||
"type": "SVN代码共享管理软件",
|
||||
"pid": "3"
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/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")
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
|
||||
CSVN_SOURCE='https://github.com/midoks/mdserver-web/releases/download/init/CollabNetSubversionEdge-5.1.4_linux-x86_64.tar.xz'
|
||||
|
||||
Install_csvn()
|
||||
{
|
||||
mkdir -p $serverPath/source
|
||||
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
|
||||
if [ ! -f $serverPath/source/csvn.tar.xz ];then
|
||||
wget -O $serverPath/source/csvn.tar.xz ${CSVN_SOURCE}
|
||||
fi
|
||||
|
||||
cd $serverPath/source && tar -Jxf $serverPath/source/csvn.tar.xz
|
||||
mv $serverPath/source/csvn $serverPath/csvn
|
||||
echo '5.1' > $serverPath/csvn/version.pl
|
||||
|
||||
|
||||
if id -u csvn > /dev/null 2>&1; then
|
||||
echo "csvn user exists"
|
||||
else
|
||||
useradd csvn
|
||||
cp /etc/sudoers{,.`date +"%Y-%m-%d_%H-%M-%S"`}
|
||||
echo "csvn ALL=(ALL) ALL" >> /etc/sudoers
|
||||
fi
|
||||
|
||||
chown -R csvn:csvn $serverPath/csvn
|
||||
|
||||
# $serverPath/csvn/bin/csvn install
|
||||
# $serverPath/csvn/bin/csvn-httpd install
|
||||
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_csvn()
|
||||
{
|
||||
rm -rf $serverPath/csvn
|
||||
}
|
||||
|
||||
|
||||
action=$1
|
||||
host=$2
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_csvn
|
||||
else
|
||||
Uninstall_csvn
|
||||
fi
|
||||
@@ -0,0 +1,504 @@
|
||||
pluginService('csvn');
|
||||
|
||||
function csvnPost(method,args,callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'csvn', func:method, args:JSON.stringify(args)}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
|
||||
function csvnEdit(){
|
||||
|
||||
csvnPost('csvn_edit',{} , function(data){
|
||||
// console.log(data);
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var edit = '<p class="status">通用的手动编辑:</p>';
|
||||
edit +='<div class="sfm-opt">\
|
||||
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['svn_access_file']+'\');">权限编辑</button>\
|
||||
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['post_commit_tpl']+'\');">post_commit_tpl</button>\
|
||||
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['commit_tpl']+'\');">commit_tpl</button>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(edit);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function csvnUserFind(){
|
||||
var search = $('#csvn_find_user').val();
|
||||
if (search==''){
|
||||
layer.msg('搜索字符不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
csvnUserList(1, search);
|
||||
}
|
||||
|
||||
function csvnUserList(page, search) {
|
||||
|
||||
var _data = {};
|
||||
if (typeof(page) =='undefined'){
|
||||
var page = 1;
|
||||
}
|
||||
|
||||
_data['page'] = page;
|
||||
_data['page_size'] = 10;
|
||||
if(typeof(search) != 'undefined'){
|
||||
_data['search'] = search;
|
||||
}
|
||||
|
||||
csvnPost('user_list', _data, function(data){
|
||||
|
||||
var rdata = $.parseJSON(data.data);
|
||||
// console.log(rdata);
|
||||
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找用户名" id="csvn_find_user" style="height: 28px; border-radius: 3px;width: 505px;">';
|
||||
content += '<button class="btn btn-success btn-sm" onclick="csvnUserFind();">查找</button></div>';
|
||||
|
||||
content += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
|
||||
content += '<thead><tr>';
|
||||
content += '<th>用户名</th>';
|
||||
content += '<th>操作(<a class="btlink" onclick="csvnAddUser();">添加</a>)</th>';
|
||||
content += '</tr></thead>';
|
||||
|
||||
content += '<tbody>';
|
||||
|
||||
ulist = rdata.data;
|
||||
for (i in ulist){
|
||||
content += '<tr><td>'+ulist[i]+'</td><td>'+
|
||||
'<a class="btlink" onclick="csvnDelUser(\''+ulist[i]+'\')">删除</a> | ' +
|
||||
'<a class="btlink" onclick="csvnModPwdUser(\''+ulist[i]+'\')">改密</a></td></tr>';
|
||||
}
|
||||
|
||||
content += '</tbody>';
|
||||
content += '</table></div>';
|
||||
|
||||
page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
|
||||
page += rdata.list;
|
||||
page += '</div></ul></div>';
|
||||
|
||||
content += page;
|
||||
|
||||
$(".soft-man-con").html(content);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnDelUser(name){
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '删除用户',
|
||||
area: '350px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>\
|
||||
<div class='version line'>你要确认要删除"+ name + "账户?</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' id='csvn_del_close' class='btn btn-danger btn-sm btn-title'>关闭</button>\
|
||||
<button type='button' id='csvn_del_ok' class='btn btn-success btn-sm btn-title bi-btn'>确认</button>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
|
||||
$('#csvn_del_close').click(function(){
|
||||
layer.close(loadOpen);
|
||||
});
|
||||
|
||||
$('#csvn_del_ok').click(function(){
|
||||
_data = {};
|
||||
_data['username'] = name;
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'csvn', func:'user_del', args:JSON.stringify(_data)}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.data !='ok'){
|
||||
layer.msg(data.data,{icon:2,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
|
||||
layer.close(loadOpen);
|
||||
layer.msg("删除成功!",{icon:1,time:3000,shade: [0.3, '#000']});
|
||||
|
||||
},'json');
|
||||
});
|
||||
}
|
||||
|
||||
function csvnAddUser(username){
|
||||
|
||||
user_input = ''
|
||||
if (typeof(username) == 'undefined'){
|
||||
user_input = "<div><input class='bt-input-text mr5 outline_no' type='text' id='csvn_username' name='username' style='height: 28px; border-radius: 3px;width: 200px;' placeholder='输入用户名'></div>";
|
||||
} else {
|
||||
user_input = "<div><input value='"+ username +"' class='bt-input-text mr5 outline_no' type='text' id='csvn_username' name='username' style='height: 28px; border-radius: 3px;width: 200px;' disabled='true'></div>";
|
||||
}
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '添加用户',
|
||||
area: '240px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>\
|
||||
<div class='version line'>\
|
||||
"+user_input+"\
|
||||
<div style='padding-top:3px;'><input class='bt-input-text mr5 outline_no' type='text' id='csvn_password' name='password' style='height: 28px; border-radius: 3px;width: 200px;' placeholder='输入密码'></div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' id='csvn_add_close' class='btn btn-danger btn-sm btn-title'>关闭</button>\
|
||||
<button type='button' id='csvn_add_ok' class='btn btn-success btn-sm btn-title bi-btn'>确认</button>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
|
||||
$('#csvn_add_close').click(function(){
|
||||
layer.close(loadOpen);
|
||||
});
|
||||
|
||||
$('#csvn_add_ok').click(function(){
|
||||
_data = {};
|
||||
|
||||
_data['username'] = $('#csvn_username').val();
|
||||
_data['password'] = $('#csvn_password').val();
|
||||
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'csvn', func:'user_add', args:JSON.stringify(_data)}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.data !='ok'){
|
||||
layer.msg(data.data,{icon:2,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
|
||||
csvnUserList();
|
||||
layer.close(loadOpen);
|
||||
layer.msg("操作成功!",{icon:1,time:3000,shade: [0.3, '#000']});
|
||||
},'json');
|
||||
});
|
||||
}
|
||||
|
||||
function csvnModPwdUser(name){
|
||||
csvnAddUser(name);
|
||||
}
|
||||
|
||||
function csvnProjectFind(){
|
||||
var search = $('#csvn_project_find').val();
|
||||
if (search == ''){
|
||||
layer.msg('查找字符不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
csvnProjectList(1, search);
|
||||
}
|
||||
|
||||
function csvnProjectList(page, search){
|
||||
var _data = {};
|
||||
_data['page_size'] = 10;
|
||||
if (typeof(search) != 'undefined'){
|
||||
_data['search'] = search;
|
||||
}
|
||||
|
||||
if (typeof(page) != 'undefined'){
|
||||
_data['page'] = page;
|
||||
setCookie('csvnProjectListPage',page);
|
||||
} else {
|
||||
_data['page'] = 1;
|
||||
cookie_page = getCookie('csvnProjectListPage')
|
||||
if (cookie_page >0){
|
||||
_data['page'] = cookie_page;
|
||||
}
|
||||
}
|
||||
|
||||
csvnPost('project_list', _data, function(data){
|
||||
|
||||
var rdata = $.parseJSON($.trim(data.data));
|
||||
var csvn_mg = project_url = 'http://' +rdata['ip'] +(rdata['csvn_port'] == '80' ? '': ':'+rdata['csvn_port']);
|
||||
|
||||
content = '<div><input class="bt-input-text mr5" type="text" placeholder="查找项目" id="csvn_project_find" style="height: 28px; border-radius: 3px;width: 505px;">';
|
||||
content += '<button class="btn btn-success btn-sm" onclick="csvnProjectFind();">查找</button></div>';
|
||||
|
||||
content += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
|
||||
content += '<thead><tr>';
|
||||
content += '<th>项目名</th>';
|
||||
content += '<th>地址</th>';
|
||||
content += '<th>操作(<a class="btlink" onclick="csvnAddProject();">添加</a>) | <a class="btlink" target="_blank" href="'+csvn_mg+'">后台管理</a> </th>';
|
||||
content += '</tr></thead>';
|
||||
content += '<tbody>';
|
||||
|
||||
// console.log(rdata);
|
||||
ulist = rdata.data;
|
||||
for (i in ulist){
|
||||
var project_url = 'http://' +rdata['ip'] +(rdata['port'] == '80' ? '': ':'+rdata['port'])+ '/svn/'+ulist[i]['name'];
|
||||
var code_url = 'http://' +rdata['ip'] +(rdata['port'] == '80' ? '': ':'+rdata['port'])+ '/viewvc/'+ulist[i]['name'];
|
||||
content += '<tr><td>'+ulist[i]['name']+'</td>'+
|
||||
'<td>'+project_url+'</td><td>'+
|
||||
'<a class="btlink" onclick="csvnDelProject(\''+ulist[i]['name']+'\')">删除</a> | ' +
|
||||
'<a class="btlink" onclick="csvnAclProject(\''+ulist[i]['name']+'\')">权限</a> | ' +
|
||||
'<a class="btlink" target="_blank" href="' + code_url +'">源码</a> | ' +
|
||||
'<a class="btlink" onclick="csvnProjectScript(\''+ulist[i]['name']+'\','+ ulist[i]['has_hook']+')">脚本</a>' +
|
||||
'</td></tr>';
|
||||
}
|
||||
|
||||
content += '</tbody>';
|
||||
content += '</table></div>';
|
||||
|
||||
page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
|
||||
page += rdata.list;
|
||||
page += '</div></ul></div>';
|
||||
|
||||
content += page;
|
||||
$(".soft-man-con").html(content);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnDelProject(name){
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '删除用户',
|
||||
area: '350px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>\
|
||||
<div class='version line'>你要确认要删除"+ name + "账户?</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' id='csvn_del_close' class='btn btn-danger btn-sm btn-title'>关闭</button>\
|
||||
<button type='button' id='csvn_del_ok' class='btn btn-success btn-sm btn-title bi-btn'>确认</button>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
|
||||
$('#csvn_del_close').click(function(){
|
||||
layer.close(loadOpen);
|
||||
});
|
||||
|
||||
$('#csvn_del_ok').click(function(){
|
||||
var _data = {};
|
||||
_data['name'] = name;
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'csvn', func:'project_del', args:JSON.stringify(_data)}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.data !='ok'){
|
||||
layer.msg(data.data,{icon:2,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
csvnProjectList();
|
||||
layer.close(loadOpen);
|
||||
layer.msg("删除成功!",{icon:1,time:3000,shade: [0.3, '#000']});
|
||||
},'json');
|
||||
});
|
||||
}
|
||||
|
||||
function csvnAddProject(){
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '添加项目',
|
||||
area: '240px',
|
||||
content:"<div class='bt-form pd20 pb70 c6'>\
|
||||
<div class='version line'>\
|
||||
<div><input class='bt-input-text mr5 outline_no' type='text' id='csvn_name' name='username' style='height: 28px; border-radius: 3px;width: 200px;' placeholder='输入项目名'></div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' id='csvn_project_close' class='btn btn-danger btn-sm btn-title'>关闭</button>\
|
||||
<button type='button' id='csvn_project_ok' class='btn btn-success btn-sm btn-title bi-btn'>确认</button>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
|
||||
$('#csvn_project_close').click(function(){
|
||||
layer.close(loadOpen);
|
||||
});
|
||||
|
||||
$('#csvn_project_ok').click(function(){
|
||||
var _data = {};
|
||||
_data['name'] = $('#csvn_name').val();
|
||||
|
||||
csvnPost('project_add', _data, function(data){
|
||||
|
||||
if (data.data !='ok'){
|
||||
layer.msg(data.data,{icon:2,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
csvnProjectList();
|
||||
layer.close(loadOpen);
|
||||
layer.msg("操作成功!",{icon:1,time:3000,shade: [0.3, '#000']});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function csvnProjectScript(pnanm, has_hook){
|
||||
|
||||
var html = '';
|
||||
if (has_hook){
|
||||
html += '<button onclick="csvnProjectScriptEdit(\''+pnanm+'\')" class="btn btn-default btn-sm">手动编辑</button>';
|
||||
html += '<button onclick="csvnProjectScriptDebug(\''+pnanm+'\')" class="btn btn-default btn-sm">调试日志</button>';
|
||||
html += '<button onclick="csvnProjectScriptLoad(\''+pnanm+'\')" class="btn btn-default btn-sm">重新加载</button>';
|
||||
html += '<button onclick="csvnProjectScriptUnload(\''+pnanm+'\')" class="btn btn-default btn-sm">卸载脚本</button>';
|
||||
} else {
|
||||
html += '<button onclick="csvnProjectScriptLoad(\''+pnanm+'\')" class="btn btn-default btn-sm">加载脚本</button>';
|
||||
}
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '脚本设置',
|
||||
area: '240px',
|
||||
content:'<div class="change-default pd20">'+html+'</div>'
|
||||
});
|
||||
}
|
||||
|
||||
function csvnProjectScriptLoad(pname){
|
||||
csvnPost('project_script_load', {'pname':pname}, function(data){
|
||||
if (data.data != 'ok'){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){
|
||||
$('.layui-layer-close1').click();
|
||||
csvnProjectList();
|
||||
},2000);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnProjectScriptUnload(pname){
|
||||
csvnPost('project_script_unload', {'pname':pname}, function(data){
|
||||
if (data.data != 'ok'){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){
|
||||
$('.layui-layer-close1').click();
|
||||
csvnProjectList();
|
||||
},2000);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnProjectScriptEdit(pname){
|
||||
csvnPost('project_script_edit', {'pname':pname}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (rdata['status']){
|
||||
onlineEditFile(0, rdata['path']);
|
||||
$('.layui-layer-close1').click();
|
||||
csvnProjectList();
|
||||
} else {
|
||||
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function csvnProjectScriptDebug(pname){
|
||||
csvnPost('project_script_debug', {'pname':pname}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (rdata['status']){
|
||||
onlineEditFile(0, rdata['path']);
|
||||
$('.layui-layer-close1').click();
|
||||
csvnProjectList();
|
||||
} else {
|
||||
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function csvnAclAdd(pname){
|
||||
var uname = $('#csvn_username').val();
|
||||
if (uname == ''){
|
||||
layer.msg('添加用户名不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
csvnPost('project_acl_add', {'pname':pname,'uname':uname}, function(data){
|
||||
if (data.data != 'ok'){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
$('.layui-layer-close1').click();
|
||||
csvnAclProject(pname);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnAclDel(pname, uname){
|
||||
csvnPost('project_acl_del', {'pname':pname,'uname':uname}, function(data){
|
||||
if (data.data != 'ok'){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
$('.layui-layer-close1').click();
|
||||
csvnAclProject(pname);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnAclSet(obj, pname, uname, acl, selected){
|
||||
|
||||
if (selected){
|
||||
$(obj).prop('checked',true);
|
||||
layer.msg('权限没有变化!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
csvnPost('project_acl_set', {'pname':pname,'uname':uname, 'acl':acl}, function(data){
|
||||
if (data.data != 'ok'){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
$('.layui-layer-close1').click();
|
||||
csvnAclProject(pname);
|
||||
});
|
||||
}
|
||||
|
||||
function csvnAclProject(pname){
|
||||
csvnPost('project_acl_list', {'name':pname}, function(data){
|
||||
|
||||
var rdata = [];
|
||||
try {
|
||||
rdata = $.parseJSON(data.data);
|
||||
} catch(e){}
|
||||
|
||||
var list = '';
|
||||
for (i in rdata) {
|
||||
var user = rdata[i]['user'];
|
||||
var acl = '';
|
||||
if (rdata[i]['acl'] == 'r'){
|
||||
acl += '<input type="checkbox" onclick="csvnAclSet(this,\''+pname+'\',\''+user+'\',\'r\',true)" checked="true"> 只读 | <input type="checkbox" onclick="csvnAclSet(this,\''+pname+'\',\''+user+'\',\'rw\', false)"> 读写';
|
||||
} else {
|
||||
acl += '<input type="checkbox" onclick="csvnAclSet(this,\''+pname+'\',\''+user+'\',\'r\',false)"> 只读 | <input type="checkbox" onclick="csvnAclSet(this,\''+pname+'\',\''+user+'\',\'rw\',true)" checked="true"> 读写';
|
||||
}
|
||||
|
||||
list += '<tr><td>'+user+'</td><td>' + acl +'</td>'+
|
||||
'<td><a class="btlink" onclick="csvnAclDel(\''+pname+'\',\''+user+'\')">删除</a></td>'+'</tr>';
|
||||
}
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '项目('+pname+')权限设置',
|
||||
area: '300px',
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div>\
|
||||
<div><input class='bt-input-text mr5 outline_no' type='text' id='csvn_username' name='username' style='height: 28px; border-radius: 3px;width: 205px;' placeholder='用户名'>\
|
||||
<button class='btn btn-success btn-sm' onclick='csvnAclAdd(\""+pname+"\");'>添加</button></div>\
|
||||
<div class='divtable' style='margin-top:5px;'><table class='table table-hover'><thead><tr><th>用户</th><th>权限</th><th>操作</th></tr></thead>\
|
||||
<tbody>"+list+"</tbody>\
|
||||
</table></div>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,23 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="readme();">插件说明</p>
|
||||
</div>
|
||||
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
||||
function readme() {
|
||||
$('.bt-w-main .soft-man-con').hide();
|
||||
$('.bt-w-main .v0').show();
|
||||
}
|
||||
|
||||
//../google-cloud-sdk/bin/gcloud app deploy << y
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,20 @@
|
||||
# coding: utf-8
|
||||
|
||||
import time
|
||||
import random
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
def status():
|
||||
return 'start'
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"title":"GAE",
|
||||
"tip":"soft",
|
||||
"name":"gae",
|
||||
"ps":"GAE 英文全称为 Google App Engine。它是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台",
|
||||
"versions": "0.1",
|
||||
"shell":"install.sh",
|
||||
"checks":"server/gae",
|
||||
"path":"server/gae",
|
||||
"author":"mdserver-web",
|
||||
"home":"https://github.com/midoks/mdserver-web",
|
||||
"date":"2018-11-30",
|
||||
"pid":"5"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/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")
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
Install_gae()
|
||||
{
|
||||
mkdir -p ${serverPath}/gae
|
||||
mkdir -p ${serverPath}/source/gae
|
||||
|
||||
os=`uname`
|
||||
if [ "Darwin" == "$os" ];then
|
||||
file=google-cloud-sdk-218.0.0-darwin-x86_64.tar.gz
|
||||
else
|
||||
file=google-cloud-sdk-218.0.0-linux-x86_64.tar.gz
|
||||
fi
|
||||
|
||||
if [ ! -f $serverPath/source/gae/$file ];then
|
||||
wget -O $serverPath/source/gae/$file https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/$file
|
||||
fi
|
||||
|
||||
if [ ! -d $serverPath/source/gae/google-cloud-sdk ];then
|
||||
cd $serverPath/source/gae && tar zxvf $file
|
||||
fi
|
||||
|
||||
cp -r $serverPath/source/gae/google-cloud-sdk ${serverPath}/gae
|
||||
|
||||
|
||||
|
||||
echo "${1}" > ${serverPath}/gae/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_gae()
|
||||
{
|
||||
rm -rf ${serverPath}/gae
|
||||
echo '卸载完成' > $install_tmp
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_gae $2
|
||||
else
|
||||
Uninstall_gae $2
|
||||
fi
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,17 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('gogs');">服务</p>
|
||||
<p onclick="pluginInitD('gogs');">自启动</p>
|
||||
<p onclick="pluginConfig('gogs',null, 'init_conf');">自启动配置</p>
|
||||
<p onclick="pluginConfig('gogs',null, 'conf');">运行配置</p>
|
||||
<p onclick="pluginLogs('gogs',null,'run_log');">运行日志</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
pluginService('gogs');
|
||||
</script>
|
||||
@@ -0,0 +1,192 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append("/usr/local/lib/python2.7/site-packages")
|
||||
import psutil
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
app_debug = False
|
||||
if public.getOs() == 'darwin':
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'gogs'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getInitDFile():
|
||||
if app_debug:
|
||||
return '/tmp/' + getPluginName()
|
||||
return '/etc/init.d/' + getPluginName()
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def getInitdConf():
|
||||
path = getPluginDir() + "/init.d/gogs.tpl"
|
||||
return path
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getServerDir() + "/custom/conf/app.ini"
|
||||
return path
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
file_tpl = getInitdConf()
|
||||
service_path = public.getServerDir()
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
if not os.path.exists(initD_path):
|
||||
os.mkdir(initD_path)
|
||||
file_bin = initD_path + '/' + getPluginName()
|
||||
|
||||
content = public.readFile(file_tpl)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
|
||||
public.writeFile(file_bin, content)
|
||||
public.execShell('chmod +x ' + file_bin)
|
||||
|
||||
log_path = getServerDir() + '/log'
|
||||
if not os.path.exists(log_path):
|
||||
os.mkdir(log_path)
|
||||
|
||||
return file_bin
|
||||
|
||||
|
||||
def start():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' start')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
|
||||
|
||||
def stop():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' stop')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def restart():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def reload():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
if os.path.exists(initd_bin):
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
mem_bin = initDreplace()
|
||||
initd_bin = getInitDFile()
|
||||
shutil.copyfile(mem_bin, initd_bin)
|
||||
public.execShell('chmod +x ' + initd_bin)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
os.remove(initd_bin)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def runLog():
|
||||
log_path = getServerDir() + '/log/gogs.log'
|
||||
return log_path
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
elif func == 'start':
|
||||
print start()
|
||||
elif func == 'stop':
|
||||
print stop()
|
||||
elif func == 'restart':
|
||||
print restart()
|
||||
elif func == 'reload':
|
||||
print reload()
|
||||
elif func == 'initd_status':
|
||||
print initdStatus()
|
||||
elif func == 'initd_install':
|
||||
print initdInstall()
|
||||
elif func == 'initd_uninstall':
|
||||
print initdUinstall()
|
||||
elif func == 'run_log':
|
||||
print runLog()
|
||||
elif func == 'conf':
|
||||
print getConf()
|
||||
elif func == 'init_conf':
|
||||
print getInitdConf()
|
||||
else:
|
||||
print 'fail'
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"ps": "Gogs是一款极易搭建的自助Git服务",
|
||||
"name": "gogs",
|
||||
"title": "Gogs",
|
||||
"versions": ["0.11.79","0.11.66"],
|
||||
"tip": "soft",
|
||||
"checks": "server/gogs",
|
||||
"author": "midoks",
|
||||
"date": "201-04-01",
|
||||
"home": "https://gogs.io",
|
||||
"type": "git服务器",
|
||||
"shell": "install.sh",
|
||||
"pid": "3",
|
||||
"sort": 7
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# /etc/rc.d/init.d/gogs
|
||||
#
|
||||
# Runs the Gogs
|
||||
#
|
||||
#
|
||||
# chkconfig: - 85 15
|
||||
#
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: gogs
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Should-Start: mysql postgresql
|
||||
# Should-Stop: mysql postgresql
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start gogs at boot time.
|
||||
# Description: Control gogs.
|
||||
### END INIT INFO
|
||||
|
||||
# Source function library.
|
||||
if [ -f /etc/init.d/functions ];then
|
||||
. /etc/init.d/functions
|
||||
fi
|
||||
|
||||
# Default values
|
||||
|
||||
NAME=gogs
|
||||
GOGS_HOME={$SERVER_PATH}/gogs
|
||||
GOGS_PATH=${GOGS_HOME}/$NAME
|
||||
GOGS_USER=midoks
|
||||
SERVICENAME="Gogs"
|
||||
LOCKFILE=/tmp/gogs.lock
|
||||
LOGPATH=${GOGS_HOME}/log
|
||||
LOGFILE=${LOGPATH}/gogs.log
|
||||
RETVAL=0
|
||||
|
||||
|
||||
status(){
|
||||
isStart=`ps -ef|grep 'gogs web' |grep -v grep|awk '{print $2}'`
|
||||
if [ "$isStart" == '' ];then
|
||||
echo "${SERVICENAME} not running"
|
||||
else
|
||||
echo "${SERVICENAME}(pid $(echo $isStart)) already running"
|
||||
fi
|
||||
}
|
||||
|
||||
start() {
|
||||
isStart=`ps -ef|grep 'gogs web' |grep -v grep|awk '{print $2}'`
|
||||
if [ "$isStart" != '' ];then
|
||||
echo "${SERVICENAME}(pid $(echo $isStart)) already running"
|
||||
return $RETVAL
|
||||
fi
|
||||
|
||||
cd ${GOGS_HOME}
|
||||
echo "Starting ${SERVICENAME}: \c"
|
||||
${GOGS_PATH} web > ${LOGFILE} 2>&1 &
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && touch ${LOCKFILE} && echo "\033[32mdone\033[0m"
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
stop() {
|
||||
cd ${GOGS_HOME}
|
||||
echo "Shutting down ${SERVICENAME}: \c"
|
||||
pkill ${NAME}
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && rm -f ${LOCKFILE} && echo "\033[32mdone\033[0m"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
reload)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ${NAME} {start|stop|status|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/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")
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
|
||||
GOGS_DOWNLOAD='https://dl.gogs.io'
|
||||
|
||||
getOs(){
|
||||
os=`uname`
|
||||
if [ "Darwin" == "$os" ];then
|
||||
echo 'darwin'
|
||||
else
|
||||
echo 'linux'
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
getBit(){
|
||||
echo `getconf LONG_BIT`
|
||||
}
|
||||
|
||||
|
||||
Install_gogs()
|
||||
{
|
||||
mkdir -p $serverPath/source/gogs
|
||||
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
version=$1
|
||||
os=`getOs`
|
||||
|
||||
if [ "darwin" == "$os" ];then
|
||||
file=gogs_${version}_darwin_amd64.zip
|
||||
else
|
||||
file=gogs_${version}_linux_amd64.zip
|
||||
fi
|
||||
|
||||
if [ ! -f $serverPath/source/gogs/$file ];then
|
||||
wget -O $serverPath/source/gogs/$file ${GOGS_DOWNLOAD}/${version}/${file}
|
||||
fi
|
||||
|
||||
cd $serverPath/source/gogs && unzip -o $file -d gogs_${version}
|
||||
mv $serverPath/source/gogs/gogs_${version}/gogs/ $serverPath/gogs
|
||||
echo $version > $serverPath/gogs/version.pl
|
||||
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_gogs()
|
||||
{
|
||||
rm -rf $serverPath/gogs
|
||||
}
|
||||
|
||||
|
||||
action=$1
|
||||
version=$2
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_gogs $version
|
||||
else
|
||||
Uninstall_gogs $version
|
||||
fi
|
||||
|
After Width: | Height: | Size: 801 B |
@@ -0,0 +1,19 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('memcached');">服务</p>
|
||||
<p onclick="pluginInitD('memcached');">自启动</p>
|
||||
<p onclick="pluginConfig('memcached');">配置修改</p>
|
||||
<p onclick="memcachedStatus();">负载状态</p>
|
||||
<p onclick="memcachedCache();">性能调整</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
pluginService('memcached');
|
||||
$.getScript( "/plugins/file?name=memcached&f=js/mem.js");
|
||||
</script>
|
||||
@@ -0,0 +1,227 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
app_debug = False
|
||||
if public.getOs() == 'darwin':
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'memcached'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getInitDFile():
|
||||
if app_debug:
|
||||
return '/tmp/' + getPluginName()
|
||||
return '/etc/init.d/' + getPluginName()
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getPluginDir() + "/init.d/memcached.tpl"
|
||||
return path
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
return tmp
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
file_tpl = getConf()
|
||||
service_path = public.getServerDir()
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
if not os.path.exists(initD_path):
|
||||
os.mkdir(initD_path)
|
||||
file_bin = initD_path + '/memcached'
|
||||
|
||||
# if os.path.exists(file_bin):
|
||||
# return file_bin
|
||||
|
||||
content = public.readFile(file_tpl)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
|
||||
public.writeFile(file_bin, content)
|
||||
public.execShell('chmod +x ' + file_bin)
|
||||
return file_bin
|
||||
|
||||
|
||||
def start():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' start')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def stop():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' stop')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def restart():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def reload():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def runInfo():
|
||||
# 获取memcached状态
|
||||
import telnetlib
|
||||
import re
|
||||
|
||||
try:
|
||||
tn = telnetlib.Telnet('127.0.0.1', 11211)
|
||||
tn.write(b"stats\n")
|
||||
tn.write(b"quit\n")
|
||||
data = tn.read_all()
|
||||
if type(data) == bytes:
|
||||
data = data.decode('utf-8')
|
||||
data = data.replace('STAT', '').replace('END', '').split("\n")
|
||||
result = {}
|
||||
res = ['cmd_get', 'get_hits', 'get_misses', 'limit_maxbytes', 'curr_items', 'bytes',
|
||||
'evictions', 'limit_maxbytes', 'bytes_written', 'bytes_read', 'curr_connections']
|
||||
for d in data:
|
||||
if len(d) < 3:
|
||||
continue
|
||||
t = d.split()
|
||||
if not t[0] in res:
|
||||
continue
|
||||
result[t[0]] = int(t[1])
|
||||
result['hit'] = 1
|
||||
if result['get_hits'] > 0 and result['cmd_get'] > 0:
|
||||
result['hit'] = float(result['get_hits']) / \
|
||||
float(result['cmd_get']) * 100
|
||||
|
||||
conf = public.readFile(getConf())
|
||||
result['bind'] = re.search('IP=(.+)', conf).groups()[0]
|
||||
result['port'] = int(re.search('PORT=(\d+)', conf).groups()[0])
|
||||
result['maxconn'] = int(re.search('MAXCONN=(\d+)', conf).groups()[0])
|
||||
result['cachesize'] = int(
|
||||
re.search('CACHESIZE=(\d+)', conf).groups()[0])
|
||||
return public.getJson(result)
|
||||
except Exception, e:
|
||||
return public.getJson({})
|
||||
|
||||
|
||||
def saveConf():
|
||||
# 设置memcached缓存大小
|
||||
import re
|
||||
confFile = getConf()
|
||||
try:
|
||||
args = getArgs()
|
||||
content = public.readFile(confFile)
|
||||
content = re.sub('IP=.+', 'IP=' + args['ip'], content)
|
||||
content = re.sub('PORT=\d+', 'PORT=' + args['port'], content)
|
||||
content = re.sub('MAXCONN=\d+', 'MAXCONN=' + args['maxconn'], content)
|
||||
content = re.sub('CACHESIZE=\d+', 'CACHESIZE=' +
|
||||
args['cachesize'], content)
|
||||
public.writeFile(confFile, content)
|
||||
reload()
|
||||
return 'ok'
|
||||
except Exception as e:
|
||||
pass
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
if os.path.exists(initd_bin):
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
|
||||
mem_bin = initDreplace()
|
||||
initd_bin = getInitDFile()
|
||||
shutil.copyfile(mem_bin, initd_bin)
|
||||
public.execShell('chmod +x ' + initd_bin)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
os.remove(initd_bin)
|
||||
return 'ok'
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
elif func == 'start':
|
||||
print start()
|
||||
elif func == 'stop':
|
||||
print stop()
|
||||
elif func == 'restart':
|
||||
print restart()
|
||||
elif func == 'reload':
|
||||
print reload()
|
||||
elif func == 'initd_status':
|
||||
print initdStatus()
|
||||
elif func == 'initd_install':
|
||||
print initdInstall()
|
||||
elif func == 'initd_uninstall':
|
||||
print initdUinstall()
|
||||
elif func == 'run_info':
|
||||
print runInfo()
|
||||
elif func == 'conf':
|
||||
print getConf()
|
||||
elif func == 'save_conf':
|
||||
print saveConf()
|
||||
else:
|
||||
print 'fail'
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"sort": 7,
|
||||
"ps": "Memcached 是一个高性能的分布式内存对象缓存系统",
|
||||
"name": "memcached",
|
||||
"title": "Memcached",
|
||||
"shell": "install.sh",
|
||||
"versions":["1.5"],
|
||||
"updates":["1.5.12"],
|
||||
"tip": "soft",
|
||||
"checks": "server/memcached",
|
||||
"display": 1,
|
||||
"author": "Zend",
|
||||
"date": "2017-04-01",
|
||||
"home": "http://memcached.org/",
|
||||
"type": 0,
|
||||
"pid": "2"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# memcached: MemCached Daemon
|
||||
#
|
||||
# chkconfig: - 90 25
|
||||
# description: MemCached Daemon
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: memcached
|
||||
# Required-Start: $syslog
|
||||
# Required-Stop: $syslog
|
||||
# Should-Start: $local_fs
|
||||
# Should-Stop: $local_fs
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: memcached - Memory caching daemon
|
||||
# Description: memcached - Memory caching daemon
|
||||
### END INIT INFO
|
||||
|
||||
IP=127.0.0.1
|
||||
PORT=11211
|
||||
USER=root
|
||||
MAXCONN=1024
|
||||
CACHESIZE=64
|
||||
OPTIONS=""
|
||||
|
||||
RETVAL=0
|
||||
prog="memcached"
|
||||
|
||||
MEM_PATH={$SERVER_PATH}/memcached
|
||||
|
||||
start () {
|
||||
echo -n $"Starting $prog: "
|
||||
$MEM_PATH/bin/memcached -d -l $IP -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN -P $MEM_PATH/memcached.pid $OPTIONS
|
||||
if [ "$?" != 0 ] ; then
|
||||
echo " failed"
|
||||
exit 1
|
||||
else
|
||||
echo " done"
|
||||
fi
|
||||
}
|
||||
stop () {
|
||||
echo -n $"Stopping $prog: "
|
||||
if [ ! -e $MEM_PATH/$prog.pid ]; then
|
||||
echo -n $"$prog is not running."
|
||||
exit 1
|
||||
fi
|
||||
kill `cat $MEM_PATH/memcached.pid`
|
||||
if [ "$?" != 0 ] ; then
|
||||
echo " failed"
|
||||
exit 1
|
||||
else
|
||||
rm -f ${MEM_PATH}/memcached.pid
|
||||
echo " done"
|
||||
fi
|
||||
}
|
||||
|
||||
restart () {
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
}
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart|reload)
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|reload}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $?
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/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")
|
||||
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
|
||||
Install_mem()
|
||||
{
|
||||
mkdir -p $serverPath/source
|
||||
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
|
||||
if [ ! -f $serverPath/source/memcached.tar.gz ];then
|
||||
wget -O $serverPath/source/memcached.tar.gz http://www.memcached.org/files/memcached-1.5.12.tar.gz
|
||||
if
|
||||
|
||||
cd $serverPath/source && tar -zxvf memcached.tar.gz
|
||||
|
||||
mkdir -p $serverPath/memcached
|
||||
cd memcached* && ./configure --prefix=$serverPath/memcached && make && make install
|
||||
|
||||
echo '1.5' > $serverPath/memcached/version.pl
|
||||
|
||||
echo '安装完成' > $install_tmp
|
||||
|
||||
}
|
||||
|
||||
Uninstall_mem()
|
||||
{
|
||||
$serverPath/memcached/init.d/memcached stop
|
||||
rm -rf mkdir -p $serverPath/memcached
|
||||
}
|
||||
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_mem
|
||||
else
|
||||
Uninstall_mem
|
||||
fi
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
|
||||
//memcached负载状态
|
||||
function memcachedStatus() {
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'memcached', func:'run_info'}, function(data) {
|
||||
layer.close(loadT);
|
||||
|
||||
if (!data.status){
|
||||
showMsg(data.msg, function(){}, null,13000);
|
||||
return;
|
||||
}
|
||||
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if ($.isEmptyObject(rdata)){
|
||||
showMsg('memcached服务没有启动!', function(){}, undefined, 3000);
|
||||
return;
|
||||
}
|
||||
var Con = '<div class="divtable">\
|
||||
<table class="table table-hover table-bordered" style="width: 490px;">\
|
||||
<thead><th>字段</th><th>当前值</th><th>说明</th></thead>\
|
||||
<tbody>\
|
||||
<tr><th>BindIP</th><td>' + rdata.bind + '</td><td>监听IP</td></tr>\
|
||||
<tr><th>PORT</th><td>' + rdata.port + '</td><td>监听端口</td></tr>\
|
||||
<tr><th>CACHESIZE</th><td>' + rdata.cachesize + ' MB</td><td>最大缓存容量</td></tr>\
|
||||
<tr><th>MAXCONN</th><td>' + rdata.maxconn + '</td><td>最大连接数限制</td></tr>\
|
||||
<tr><th>curr_connections</th><td>' + rdata.curr_connections + '</td><td>当前打开的连接数</td></tr>\
|
||||
<tr><th>cmd_get</th><td>' + rdata.cmd_get + '</td><td>GET请求数</td></tr>\
|
||||
<tr><th>get_hits</th><td>' + rdata.get_hits + '</td><td>GET命中次数</td></tr>\
|
||||
<tr><th>get_misses</th><td>' + rdata.get_misses + '</td><td>GET失败次数</td></tr>\
|
||||
<tr><th>hit</th><td>' + rdata.hit.toFixed(2) + '%</td><td>GET命中率</td></tr>\
|
||||
<tr><th>curr_items</th><td>' + rdata.curr_items + '</td><td>当前被缓存的数据行数</td></tr>\
|
||||
<tr><th>evictions</th><td>' + rdata.evictions + '</td><td>因内存不足而被清理的缓存行数</td></tr>\
|
||||
<tr><th>bytes</th><td>' + toSize(rdata.bytes) + '</td><td>当前已使用内存</td></tr>\
|
||||
<tr><th>bytes_read</th><td>' + toSize(rdata.bytes_read) + '</td><td>请求总大小</td></tr>\
|
||||
<tr><th>bytes_written</th><td>' + toSize(rdata.bytes_written) + '</td><td>发送总大小</td></tr>\
|
||||
<tbody>\
|
||||
</table></div>'
|
||||
$(".soft-man-con").html(Con);
|
||||
},'json');
|
||||
}
|
||||
|
||||
//memcached性能调整
|
||||
function memcachedCache() {
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'memcached', func:'run_info'}, function(data) {
|
||||
layer.close(loadT);
|
||||
|
||||
if (!data.status){
|
||||
showMsg(data.msg, function(){}, null,13000);
|
||||
return;
|
||||
}
|
||||
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if ($.isEmptyObject(rdata)){
|
||||
showMsg('memcached服务没有启动!', function(){}, undefined, 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
var memCon = '<div class="conf_p" style="margin-bottom:0">\
|
||||
<p><span>BindIP</span><input style="width: 120px;" class="bt-input-text mr5" name="membind" value="' + rdata.bind + '" type="text" ><font>监听IP,请勿随意修改</font></p>\
|
||||
<p><span>PORT</span><input style="width: 120px;" class="bt-input-text mr5" max="65535" name="memport" value="' + rdata.port + '" type="number" ><font>监听端口,一般无需修改</font></p>\
|
||||
<p><span>CACHESIZE</span><input style="width: 120px;" class="bt-input-text mr5" name="memcachesize" value="' + rdata.cachesize + '" type="number" >MB,<font>缓存大小,建议不要大于512M</font></p>\
|
||||
<p><span>MAXCONN</span><input style="width: 120px;" class="bt-input-text mr5" name="memmaxconn" value="' + rdata.maxconn + '" type="number" ><font>最大连接数,建议不要大于40960</font></p>\
|
||||
<div style="margin-top:10px; padding-right:230px" class="text-right"><button class="btn btn-success btn-sm" onclick="setMemcachedConf()">保存</button></div>\
|
||||
</div>'
|
||||
$(".soft-man-con").html(memCon);
|
||||
},'json');
|
||||
}
|
||||
|
||||
//memcached提交配置
|
||||
function setMemcachedConf() {
|
||||
var data = {
|
||||
ip: $("input[name='membind']").val(),
|
||||
port: $("input[name='memport']").val(),
|
||||
cachesize: $("input[name='memcachesize']").val(),
|
||||
maxconn: $("input[name='memmaxconn']").val()
|
||||
}
|
||||
|
||||
if (data.ip.split('.').length < 4) {
|
||||
layer.msg('IP地址格式不正确!', { icon: 2 });
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.port < 1 || data.port > 65535) {
|
||||
layer.msg('端口范围不正确!', { icon: 2 });
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.cachesize < 8) {
|
||||
layer.msg('缓存值过小', { icon: 2 });
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.maxconn < 4) {
|
||||
layer.msg('最大连接数过小', { icon: 2 });
|
||||
return;
|
||||
}
|
||||
|
||||
var loadT = layer.msg('正在保存...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'memcached', func:'save_conf',args:JSON.stringify(data) }, function(rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
},'json');
|
||||
}
|
||||
|
After Width: | Height: | Size: 515 B |
@@ -0,0 +1,16 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('mysql');">服务</p>
|
||||
<p onclick="indexPy();">自启动</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=mysql&f=js/mysql.js");
|
||||
</script>
|
||||
@@ -0,0 +1,229 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
def checkMyCnf():
|
||||
# 处理MySQL配置文件
|
||||
import os
|
||||
confFile = '/etc/my.cnf'
|
||||
if os.path.exists(confFile):
|
||||
conf = readFile(confFile)
|
||||
if len(conf) > 100:
|
||||
return True
|
||||
versionFile = '/www/server/mysql/version.pl'
|
||||
if not os.path.exists(versionFile):
|
||||
return False
|
||||
|
||||
versions = ['5.1', '5.5', '5.6', '5.7', 'AliSQL']
|
||||
version = readFile(versionFile)
|
||||
for key in versions:
|
||||
if key in version:
|
||||
version = key
|
||||
break
|
||||
|
||||
shellStr = '''
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
CN='125.88.182.172'
|
||||
HK='download.bt.cn'
|
||||
HK2='103.224.251.67'
|
||||
US='174.139.221.74'
|
||||
sleep 0.5;
|
||||
CN_PING=`ping -c 1 -w 1 $CN|grep time=|awk '{print $7}'|sed "s/time=//"`
|
||||
HK_PING=`ping -c 1 -w 1 $HK|grep time=|awk '{print $7}'|sed "s/time=//"`
|
||||
HK2_PING=`ping -c 1 -w 1 $HK2|grep time=|awk '{print $7}'|sed "s/time=//"`
|
||||
US_PING=`ping -c 1 -w 1 $US|grep time=|awk '{print $7}'|sed "s/time=//"`
|
||||
|
||||
echo "$HK_PING $HK" > ping.pl
|
||||
echo "$HK2_PING $HK2" >> ping.pl
|
||||
echo "$US_PING $US" >> ping.pl
|
||||
echo "$CN_PING $CN" >> ping.pl
|
||||
nodeAddr=`sort -V ping.pl|sed -n '1p'|awk '{print $2}'`
|
||||
if [ "$nodeAddr" == "" ];then
|
||||
nodeAddr=$HK
|
||||
fi
|
||||
|
||||
Download_Url=http://$nodeAddr:5880
|
||||
|
||||
|
||||
MySQL_Opt()
|
||||
{
|
||||
MemTotal=`free -m | grep Mem | awk '{print $2}'`
|
||||
if [[ ${MemTotal} -gt 1024 && ${MemTotal} -lt 2048 ]]; then
|
||||
sed -i "s#^key_buffer_size.*#key_buffer_size = 32M#" /etc/my.cnf
|
||||
sed -i "s#^table_open_cache.*#table_open_cache = 128#" /etc/my.cnf
|
||||
sed -i "s#^sort_buffer_size.*#sort_buffer_size = 768K#" /etc/my.cnf
|
||||
sed -i "s#^read_buffer_size.*#read_buffer_size = 768K#" /etc/my.cnf
|
||||
sed -i "s#^myisam_sort_buffer_size.*#myisam_sort_buffer_size = 8M#" /etc/my.cnf
|
||||
sed -i "s#^thread_cache_size.*#thread_cache_size = 16#" /etc/my.cnf
|
||||
sed -i "s#^query_cache_size.*#query_cache_size = 16M#" /etc/my.cnf
|
||||
sed -i "s#^tmp_table_size.*#tmp_table_size = 32M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_buffer_pool_size.*#innodb_buffer_pool_size = 128M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_log_file_size.*#innodb_log_file_size = 32M#" /etc/my.cnf
|
||||
elif [[ ${MemTotal} -ge 2048 && ${MemTotal} -lt 4096 ]]; then
|
||||
sed -i "s#^key_buffer_size.*#key_buffer_size = 64M#" /etc/my.cnf
|
||||
sed -i "s#^table_open_cache.*#table_open_cache = 256#" /etc/my.cnf
|
||||
sed -i "s#^sort_buffer_size.*#sort_buffer_size = 1M#" /etc/my.cnf
|
||||
sed -i "s#^read_buffer_size.*#read_buffer_size = 1M#" /etc/my.cnf
|
||||
sed -i "s#^myisam_sort_buffer_size.*#myisam_sort_buffer_size = 16M#" /etc/my.cnf
|
||||
sed -i "s#^thread_cache_size.*#thread_cache_size = 32#" /etc/my.cnf
|
||||
sed -i "s#^query_cache_size.*#query_cache_size = 32M#" /etc/my.cnf
|
||||
sed -i "s#^tmp_table_size.*#tmp_table_size = 64M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_buffer_pool_size.*#innodb_buffer_pool_size = 256M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_log_file_size.*#innodb_log_file_size = 64M#" /etc/my.cnf
|
||||
elif [[ ${MemTotal} -ge 4096 && ${MemTotal} -lt 8192 ]]; then
|
||||
sed -i "s#^key_buffer_size.*#key_buffer_size = 128M#" /etc/my.cnf
|
||||
sed -i "s#^table_open_cache.*#table_open_cache = 512#" /etc/my.cnf
|
||||
sed -i "s#^sort_buffer_size.*#sort_buffer_size = 2M#" /etc/my.cnf
|
||||
sed -i "s#^read_buffer_size.*#read_buffer_size = 2M#" /etc/my.cnf
|
||||
sed -i "s#^myisam_sort_buffer_size.*#myisam_sort_buffer_size = 32M#" /etc/my.cnf
|
||||
sed -i "s#^thread_cache_size.*#thread_cache_size = 64#" /etc/my.cnf
|
||||
sed -i "s#^query_cache_size.*#query_cache_size = 64M#" /etc/my.cnf
|
||||
sed -i "s#^tmp_table_size.*#tmp_table_size = 64M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_buffer_pool_size.*#innodb_buffer_pool_size = 512M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_log_file_size.*#innodb_log_file_size = 128M#" /etc/my.cnf
|
||||
elif [[ ${MemTotal} -ge 8192 && ${MemTotal} -lt 16384 ]]; then
|
||||
sed -i "s#^key_buffer_size.*#key_buffer_size = 256M#" /etc/my.cnf
|
||||
sed -i "s#^table_open_cache.*#table_open_cache = 1024#" /etc/my.cnf
|
||||
sed -i "s#^sort_buffer_size.*#sort_buffer_size = 4M#" /etc/my.cnf
|
||||
sed -i "s#^read_buffer_size.*#read_buffer_size = 4M#" /etc/my.cnf
|
||||
sed -i "s#^myisam_sort_buffer_size.*#myisam_sort_buffer_size = 64M#" /etc/my.cnf
|
||||
sed -i "s#^thread_cache_size.*#thread_cache_size = 128#" /etc/my.cnf
|
||||
sed -i "s#^query_cache_size.*#query_cache_size = 128M#" /etc/my.cnf
|
||||
sed -i "s#^tmp_table_size.*#tmp_table_size = 128M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_buffer_pool_size.*#innodb_buffer_pool_size = 1024M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_log_file_size.*#innodb_log_file_size = 256M#" /etc/my.cnf
|
||||
elif [[ ${MemTotal} -ge 16384 && ${MemTotal} -lt 32768 ]]; then
|
||||
sed -i "s#^key_buffer_size.*#key_buffer_size = 512M#" /etc/my.cnf
|
||||
sed -i "s#^table_open_cache.*#table_open_cache = 2048#" /etc/my.cnf
|
||||
sed -i "s#^sort_buffer_size.*#sort_buffer_size = 8M#" /etc/my.cnf
|
||||
sed -i "s#^read_buffer_size.*#read_buffer_size = 8M#" /etc/my.cnf
|
||||
sed -i "s#^myisam_sort_buffer_size.*#myisam_sort_buffer_size = 128M#" /etc/my.cnf
|
||||
sed -i "s#^thread_cache_size.*#thread_cache_size = 256#" /etc/my.cnf
|
||||
sed -i "s#^query_cache_size.*#query_cache_size = 256M#" /etc/my.cnf
|
||||
sed -i "s#^tmp_table_size.*#tmp_table_size = 256M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_buffer_pool_size.*#innodb_buffer_pool_size = 2048M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_log_file_size.*#innodb_log_file_size = 512M#" /etc/my.cnf
|
||||
elif [[ ${MemTotal} -ge 32768 ]]; then
|
||||
sed -i "s#^key_buffer_size.*#key_buffer_size = 1024M#" /etc/my.cnf
|
||||
sed -i "s#^table_open_cache.*#table_open_cache = 4096#" /etc/my.cnf
|
||||
sed -i "s#^sort_buffer_size.*#sort_buffer_size = 16M#" /etc/my.cnf
|
||||
sed -i "s#^read_buffer_size.*#read_buffer_size = 16M#" /etc/my.cnf
|
||||
sed -i "s#^myisam_sort_buffer_size.*#myisam_sort_buffer_size = 256M#" /etc/my.cnf
|
||||
sed -i "s#^thread_cache_size.*#thread_cache_size = 512#" /etc/my.cnf
|
||||
sed -i "s#^query_cache_size.*#query_cache_size = 512M#" /etc/my.cnf
|
||||
sed -i "s#^tmp_table_size.*#tmp_table_size = 512M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_buffer_pool_size.*#innodb_buffer_pool_size = 4096M#" /etc/my.cnf
|
||||
sed -i "s#^innodb_log_file_size.*#innodb_log_file_size = 1024M#" /etc/my.cnf
|
||||
fi
|
||||
}
|
||||
|
||||
wget -O /etc/my.cnf $Download_Url/install/conf/mysql-%s.conf -T 5
|
||||
MySQL_Opt
|
||||
''' % (version,)
|
||||
# 判断是否迁移目录
|
||||
if os.path.exists('data/datadir.pl'):
|
||||
newPath = public.readFile('data/datadir.pl')
|
||||
mycnf = public.readFile('/etc/my.cnf')
|
||||
mycnf = mycnf.replace('/www/server/data', newPath)
|
||||
public.writeFile('/etc/my.cnf', mycnf)
|
||||
|
||||
os.system(shellStr)
|
||||
WriteLog('TYPE_SOFE', 'MYSQL_CHECK_ERR')
|
||||
return True
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep mysqld |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def start():
|
||||
path = os.path.dirname(os.getcwd())
|
||||
cmd = path + "/redis/bin/redis-server"
|
||||
cmd = cmd + " " + path + "/redis/redis.conf"
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def stop():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep redis |grep -v grep |grep -v python |awk '{print $2}' | xargs kill -9")
|
||||
if data[0] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def restart():
|
||||
return 'ok'
|
||||
|
||||
|
||||
def reload():
|
||||
return 'ok'
|
||||
|
||||
|
||||
def runInfo():
|
||||
path = os.path.dirname(os.getcwd())
|
||||
cmd = path + "/redis/bin/redis-cli info"
|
||||
data = public.execShell(cmd)[0]
|
||||
res = [
|
||||
'tcp_port',
|
||||
'uptime_in_days', # 已运行天数
|
||||
'connected_clients', # 连接的客户端数量
|
||||
'used_memory', # Redis已分配的内存总量
|
||||
'used_memory_rss', # Redis占用的系统内存总量
|
||||
'used_memory_peak', # Redis所用内存的高峰值
|
||||
'mem_fragmentation_ratio', # 内存碎片比率
|
||||
'total_connections_received', # 运行以来连接过的客户端的总数量
|
||||
'total_commands_processed', # 运行以来执行过的命令的总数量
|
||||
'instantaneous_ops_per_sec', # 服务器每秒钟执行的命令数量
|
||||
'keyspace_hits', # 查找数据库键成功的次数
|
||||
'keyspace_misses', # 查找数据库键失败的次数
|
||||
'latest_fork_usec' # 最近一次 fork() 操作耗费的毫秒数
|
||||
]
|
||||
data = data.split("\n")
|
||||
result = {}
|
||||
for d in data:
|
||||
if len(d) < 3:
|
||||
continue
|
||||
t = d.strip().split(':')
|
||||
if not t[0] in res:
|
||||
continue
|
||||
result[t[0]] = t[1]
|
||||
return public.getJson(result)
|
||||
|
||||
|
||||
def getConf():
|
||||
path = os.path.dirname(os.getcwd()) + "/redis/redis.conf"
|
||||
return path
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'run_info':
|
||||
print runInfo()
|
||||
elif func == 'conf':
|
||||
print getConf()
|
||||
elif func == 'status':
|
||||
print status()
|
||||
elif func == 'start':
|
||||
print start()
|
||||
elif func == 'stop':
|
||||
print stop()
|
||||
elif func == 'restart':
|
||||
print restart()
|
||||
elif func == 'reload':
|
||||
print reload()
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"title":"MySQL",
|
||||
"tip":"soft",
|
||||
"name":"mysql",
|
||||
"type":"运行环境",
|
||||
"ps":"MySQL是一种关系数据库管理系统!",
|
||||
"versions":["5.5","5.6","5.7","8.0"],
|
||||
"updates":["5.5.62"],
|
||||
"shell":"install.sh",
|
||||
"checks":"server/mysql",
|
||||
"author":"midoks",
|
||||
"home":"https://dev.mysql.com/downloads/mysql/5.5.html#downloads",
|
||||
"date":"2017-11-24",
|
||||
"pid": "2"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/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")
|
||||
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
|
||||
action=$1
|
||||
type=$2
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
echo '缺少安装脚本...' > $install_tmp
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -d $curPath/versions/$2 ];then
|
||||
echo '缺少安装脚本2...' > $install_tmp
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
@@ -0,0 +1,692 @@
|
||||
/**
|
||||
* 取回数据库列表
|
||||
* @param {Number} page 页码
|
||||
*/
|
||||
function getData(page,search) {
|
||||
search = $("#SearchValue").prop("value");
|
||||
order = getCookie('order');
|
||||
if(order){
|
||||
order = '&order=' + order;
|
||||
}else{
|
||||
order = '';
|
||||
}
|
||||
var sUrl = '/data?action=getData';
|
||||
var sUrlData='tojs=getData&table=databases&limit=15&p='+page+'&search='+search + order;
|
||||
var loadT = layer.load();
|
||||
$.post(sUrl, sUrlData,function(data) {
|
||||
layer.close(loadT);
|
||||
//构造数据列表
|
||||
var Body = '';
|
||||
if(data.data == ""){
|
||||
Body="<tr><td colspan='7'>"+lan.database.empty+"</td></tr>";
|
||||
$("#DataPage").hide()
|
||||
}
|
||||
else{
|
||||
$("#DataPage").show();
|
||||
for (var i = 0; i < data.data.length; i++) {
|
||||
if(data.data[i].backup_count==0){
|
||||
var isback = "<a href='javascript:;' class='btlink' onclick=\"DataDetails('"+data.data[i].id+"','"+data.data[i].name+"')\">"+lan.database.backup_empty+"</a>"
|
||||
}else{
|
||||
var isback = "<a href='javascript:;' class='btlink' onclick=\"DataDetails('"+data.data[i].id+"','"+data.data[i].name+"')\">"+lan.database.backup_ok+"</a>"
|
||||
}
|
||||
Body += "<tr><td><input type='checkbox' title='"+data.data[i].name+"' onclick='checkSelect();' name='id' value='"+data.data[i].id+"'>\
|
||||
<td>" + data.data[i].name + "</td>\
|
||||
<td>" + data.data[i].username + "</td>\
|
||||
<td class='relative'><span class='password' data-pw='"+data.data[i].password+"'>**********</span><span class='glyphicon glyphicon-eye-open cursor pw-ico' style='margin-left:10px'></span><span class='ico-copy cursor btcopy' style='margin-left:10px' title='"+lan.database.copy_pass+"' data-pw='"+data.data[i].password+"' onclick=\"btcopy('"+data.data[i].password+"')\"></span></td>\
|
||||
<td>"+isback+" | <a class='btlink' href=\"javascript:InputDatabase('"+data.data[i].name+"');\" title='"+lan.database.input_title+"'>"+lan.database.input+"</a></td>\
|
||||
<td><a class='btlinkbed' href='javascript:;' data-id='"+data.data[i].id+"'>" + data.data[i].ps + "</a></td>\
|
||||
<td style='text-align:right;'>\
|
||||
<a href='javascript:;' class='btlink' onclick=\"AdminDatabase('"+data.data[i].name+"','"+data.data[i].username+"','"+data.data[i].password+"')\" title='"+lan.database.admin_title+"'>"+lan.database.admin+"</a> | \
|
||||
<a href='javascript:;' class='btlink' onclick=\"SetDatabaseAccess('"+data.data[i].username+"')\" title='"+lan.database.auth_title+"'>"+lan.database.auth+"</a> | \
|
||||
<a href='javascript:;' class='btlink' onclick=\"DataRespwd(0,'"+data.data[i].id+"','"+data.data[i].username+"')\" title='"+lan.database.edit_pass_title+"'>"+lan.database.edit_pass+"</a> | \
|
||||
<a href='javascript:;' class='btlink' onclick=\"DataDelete("+data.data[i].id+",'"+data.data[i].name+"')\" title='"+lan.database.del_title+"'>"+lan.public.del+"</a>\
|
||||
</td></tr>"
|
||||
}
|
||||
}
|
||||
//输出数据列表
|
||||
$("#DataBody").html(Body);
|
||||
//输出分页
|
||||
$("#DataPage").html(data.page);
|
||||
$("#DataPage .Pcount").css("position","static");
|
||||
//备注
|
||||
$(".btlinkbed").click(function(){
|
||||
var dataid = $(this).attr("data-id");
|
||||
var databak = $(this).text();
|
||||
$(this).hide().after("<input class='baktext' type='text' data-id='"+dataid+"' name='bak' value='" + databak + "' placeholder='"+lan.database.ps+"' onblur='GetBakPost(\"databases\")' />");
|
||||
$(".baktext").focus();
|
||||
});
|
||||
|
||||
showHidePwd();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*添加数据库
|
||||
* @param {Number} sign 操作标识
|
||||
* @param {String} name 数据库名
|
||||
* @param {String} type 数据库类型
|
||||
* @param {Boolean} adduser 是否添加新用户
|
||||
* @param {String} bak 备注
|
||||
*/
|
||||
function DataAdd(sign){
|
||||
if(sign==0){
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '480px',
|
||||
title: lan.database.add_title,
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<form class='bt-form pd20 pb70' id='DataAdd'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.database.add_name+"</span><div class='info-r'>\
|
||||
<input class='bt-input-text mr5' id='db_name' type='text' name='name' placeholder='"+lan.database.add_name_title+"' style='width:70%' />\
|
||||
<select class='bt-input-text' name='codeing' style='width:22%'>\
|
||||
<option value='utf8'>utf-8</option>\
|
||||
<option value='utf8mb4'>utf8mb4</option>\
|
||||
<option value='gbk'>gbk</option>\
|
||||
<option value='big5'>big5</option>\
|
||||
</select>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>用户名</span><div class='info-r'><input class='bt-input-text mr5' type='text' name='db_user' placeholder='数据库用户' style='width:70%;margin-bottom: 10px;' /></div>\
|
||||
<span class='tname'>"+lan.database.add_pass+"</span><div class='info-r'><input class='bt-input-text mr5' type='text' name='password' id='MyPassword' style='width:311px' placeholder='"+lan.database.add_pass_title+"' value='"+(RandomStrPwd(16))+"' /><span title='"+lan.database.add_pass_rep+"' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span></div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.database.add_auth+"</span>\
|
||||
<div class='info-r'>\
|
||||
<select id='dataAccess' class='bt-input-text mr5' style='width:100px;'>\
|
||||
<option value='127.0.0.1'>"+lan.database.add_auth_local+"</option>\
|
||||
<option value='%'>"+lan.database.add_auth_all+"</option>\
|
||||
<option value='ip'>"+lan.database.add_auth_ip+"</option>\
|
||||
</select>\
|
||||
<input class='bt-input-text' type='text' name='address' placeholder='"+lan.database.add_auth_ip_title+"' style='width:203px;display:none;' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='line' style='display:none'>\
|
||||
<span class='tname'>"+lan.database.add_ps+"</span><div class='info-r'><input class='bt-input-text' type='text' name='ps' placeholder='"+lan.database.ps+"' /></div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' class='btn btn-danger btn-sm btn-title' onclick='layer.closeAll()'>"+lan.public.close+"</button>\
|
||||
<button type='button' class='btn btn-success btn-sm btn-title' onclick=\"DataAdd(1)\" >"+lan.public.submit+"</button>\
|
||||
</div>\
|
||||
</form>"
|
||||
});
|
||||
|
||||
$("#dataAccess").change(function(){
|
||||
var access = $(this).val();
|
||||
if(access == 'ip'){
|
||||
$("input[name=address]").show().val('');
|
||||
}else{
|
||||
$("input[name=address]").hide();
|
||||
}
|
||||
});
|
||||
|
||||
$("#db_name").change(function(){
|
||||
$("input[name='db_user']").val($(this).val());
|
||||
});
|
||||
}else{
|
||||
var loadT=layer.load({shade:true,shadeClose:false});
|
||||
var access = $("#dataAccess").val();
|
||||
if(access != 'ip') $("input[name=address]").val(access);
|
||||
var data = $("#DataAdd").serialize();
|
||||
$.post('/database?action=AddDatabase',data,function(rdata){
|
||||
if(rdata.status){
|
||||
getData(1);
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg,{icon:1});
|
||||
}else{
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg,{icon:2});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
*设置数据库密码
|
||||
* @param {Number} sign 操作标识
|
||||
* @param {String} passwd 数据库新密码
|
||||
*/
|
||||
function DataSetuppwd(sign, passwd) {
|
||||
if (sign == 0) {
|
||||
$.post('/data?action=getKey','table=config&key=mysql_root&id=1',function(rdata){
|
||||
var mypasswd=rdata;
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '500px',
|
||||
title: lan.database.edit_pass_title,
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form pd20 pb70' id='DataSetuppwd'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.database.edit_root+":</span><div class='info-r'><input id='MyPassword' class='bt-input-text mr5' type='text' name='password' value='"+mypasswd+"' style='width:320px' /><span title='"+lan.database.add_pass_rep+"' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span>\
|
||||
</div></div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' class='btn btn-danger btn-sm btn-title' onclick='layer.closeAll()'>"+lan.public.close+"</button>\
|
||||
<button type='button' id='PostPwBtn' class='btn btn-success btn-sm btn-title' onclick='DataSetuppwd(1)' >"+lan.public.submit+"</button>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
RandomStrPwd(16);
|
||||
$("#MyPassword").focus().keyup(function(e){
|
||||
if(e.keyCode == 13) $("#PostPwBtn").click();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var loadT=layer.msg(lan.public.the,{icon:16,time:0});
|
||||
var newPassword = $("#MyPassword").val();
|
||||
var data = 'password='+encodeURIComponent(newPassword);
|
||||
$.post('/database?action=SetupPassword',data,function(rdata){
|
||||
if(rdata.status){
|
||||
getData(1);
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg,{icon:1});
|
||||
setTimeout(function(){window.location.reload();},3000);
|
||||
}else{
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg,{icon:2});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 重置数据库密码
|
||||
* @param {Number} sign 操作标识
|
||||
* @param {String} passwd 数据库密码
|
||||
*/
|
||||
function DataRespwd(sign,id,username){
|
||||
if(sign==0){
|
||||
layer.open({
|
||||
type:1,
|
||||
skin:'demo-class',
|
||||
area:'450px',
|
||||
title:lan.database.edit_pass_title,
|
||||
closeBtn:2,
|
||||
shift:5,
|
||||
shadeClose:false,
|
||||
content:"<form class='bt-form pd20 pb70' id='DataRespwd'>\
|
||||
<div class='line'>\
|
||||
<input type='text' name='id' value='"+id+"' hidden />\
|
||||
<span class='tname'>"+lan.database.user+":</span><div class='info-r'><input class='bt-input-text' type='text' name='username' value='"+username+"' readonly='readonly' style='width:100%' />\
|
||||
</div></div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.database.edit_pass_new+":</span><div class='info-r'><input class='bt-input-text' type='text' name='password' placeholder='"+lan.database.edit_pass_new_title+"' style='width:100%' />\
|
||||
</div></div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' class='btn btn-danger btn-sm btn-title' onclick='layer.closeAll()'>"+lan.public.close+"</button>\
|
||||
<button type='button' class='btn btn-success btn-sm btn-title' onclick='DataRespwd(1)' >"+lan.public.submit+"</button>\
|
||||
</div>\
|
||||
</form>"
|
||||
});
|
||||
return;
|
||||
}
|
||||
layer.confirm(lan.database.edit_pass_confirm,{title:lan.database.edit_pass_title,icon:3,closeBtn:2},function(index){
|
||||
if(index>0){
|
||||
var loadT=layer.load({shade:true,shadeClose:false});
|
||||
var data = 'username='+encodeURIComponent($("#DataRespwd input[name='username']").val()) + '&password=' + encodeURIComponent($("#DataRespwd input[name='password']").val()) + '&id=' + $("#DataRespwd input[name='id']").val();
|
||||
$.post('/database?action=ResDatabasePassword',data,function(rdata){
|
||||
getData(1);
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
/**
|
||||
*数据库管理详细信息
|
||||
* @param {Number} id 数据库编号
|
||||
* @param {String} dataname 数据库名称
|
||||
*/
|
||||
function DataDetails(id,dataname,page){
|
||||
if(page == undefined){
|
||||
page = '1';
|
||||
}
|
||||
var loadT = layer.msg(lan.public.the_get,{icon:16,time:0});
|
||||
$.post('/data?action=getFind','table=databases&id='+id,function(rdata){
|
||||
$.post('/data?action=getData','table=backup&search='+id+'&limit=5&p=1&type=1&tojs=DataDetails&p='+page,function(frdata){
|
||||
layer.close(loadT);
|
||||
var ftpdown = '';
|
||||
var body='';
|
||||
var port;
|
||||
|
||||
frdata.page = frdata.page.replace(/'/g,'"').replace(/DataDetails\(/g,"DataDetails(" + id + ",0,");
|
||||
for(var i=0;i<frdata.data.length;i++){
|
||||
if(frdata.data[i].type == '0') continue;
|
||||
if(frdata.data[i].filename.length < 12){
|
||||
var ftpdown = "<a class='btlink' href='/cloud?filename="+frdata.data[i].filename+"&name="+ frdata.data[i].name+"' target='_blank'>"+lan.public.download+"</a>";
|
||||
}else{
|
||||
var ftpdown = "<a class='btlink' herf='javascrpit:;' onclick=\"RecoveryData('"+frdata.data[i].filename+"','"+dataname+"')\">"+lan.database.backup_re+"</a> | <a class='btlink' href='/download?filename="+frdata.data[i].filename+"&name="+ frdata.data[i].name+"' target='_blank'>"+lan.public.download+"</a>";
|
||||
}
|
||||
|
||||
body += "<tr><td><span class='glyphicon glyphicon-file'></span>"+frdata.data[i].name+"</td>\
|
||||
<td>"+(ToSize(frdata.data[i].size))+"</td>\
|
||||
<td>"+frdata.data[i].addtime+"</td>\
|
||||
<td style='color:#bbb;text-align:right'>\
|
||||
"+ftpdown+" | <a class='btlink' herf='javascrpit:;' onclick=\"DataBackupDelete('"+id+"','"+frdata.data[i].id+"')\">"+lan.public.del+"</a>\
|
||||
</td>\
|
||||
</tr>"
|
||||
}
|
||||
|
||||
|
||||
if(dataname == 0){
|
||||
var sBody = "<table width='100%' id='DataBackupList' class='table table-hover'>\
|
||||
<thead><tr><th>"+lan.database.backup_name+"</th><th>"+lan.database.backup_size+"</th><th>"+lan.database.backup_time+"</th><th width='140px' class='text-right'>"+lan.public.action+"</th></tr></thead>\
|
||||
<tbody id='DataBackupBody' class='list-list'>"+body+"</tbody>\
|
||||
</table>"
|
||||
$("#DataBackupList").html(sBody);
|
||||
$(".page").html(frdata.page);
|
||||
return;
|
||||
}
|
||||
layer.closeAll();
|
||||
layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '700px',
|
||||
title: lan.database.backup_title,
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content:"<form class='bt-form pd15' id='DataBackup' style='padding-bottom: 0'>\
|
||||
<button class='btn btn-success btn-sm' style='margin-right:10px' type='button' onclick=\"DataBackup(" + rdata.id + ",'" + dataname + "')\">"+lan.database.backup+"</button>\
|
||||
</form>\
|
||||
<div class='divtable pd15'><table width='100%' id='DataBackupList' class='table table-hover' style='margin-bottom:0'>\
|
||||
<thead><tr><th>"+lan.database.backup_name+"</th><th>"+lan.database.backup_size+"</th><th>"+lan.database.backup_time+"</th><th class='text-right'>"+lan.public.action+"</th></tr></thead>\
|
||||
<tbody id='DataBackupBody' class='list-list'>"+body+"</tbody>\
|
||||
</table><div class='page'>"+frdata.page+"</div></div>"
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
//恢复数据库备份
|
||||
function RecoveryData(fileName,dataName){
|
||||
layer.confirm(lan.database.input_confirm,{title:lan.database.input_title,icon:3,closeBtn:2},function(index){
|
||||
var loadT =layer.msg(lan.database.input_the, {icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/database?action=InputSql','file='+fileName+'&name='+dataName,function(rdata){
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
*设置数据库备份
|
||||
* @param {Number} id 数据库编号
|
||||
* @param {String} dataname 数据库名称
|
||||
*/
|
||||
function DataBackup(id,dataname){
|
||||
var loadT =layer.msg(lan.database.backup_the, {icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/database?action=ToBackup', "id="+id, function(rdata) {
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
DataDetails(id,dataname);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*删除数据库备份
|
||||
* @param {Number} id 数据库编号
|
||||
* @param {String} dataname 数据库名称
|
||||
*/
|
||||
function DataBackupDelete(typeid,id,dataname){
|
||||
layer.confirm(lan.database.backup_del_confirm,{title:lan.database.backup_del_title,icon:3,closeBtn:2},function(index){
|
||||
var loadT=layer.load({shade:true,shadeClose:false});
|
||||
$.post('/database?action=DelBackup','id='+id,function(frdata){
|
||||
layer.closeAll();
|
||||
layer.msg(frdata.msg,{icon:frdata.status?1:2});
|
||||
DataDetails(typeid,dataname);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*删除数据库
|
||||
* @param {Number} id 数据编号
|
||||
*/
|
||||
|
||||
function DataDelete(id,name){
|
||||
SafeMessage(lan.get('del',[name]),lan.get('confirm_del',[name]),function(){
|
||||
deleteDatabase(id,name);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//删除操作
|
||||
function deleteDatabase(id,name){
|
||||
var loadT = layer.msg(lan.get('del_all_task_the',[name]),{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/database?action=DeleteDatabase','id='+id+'&name='+name,function(frdata){
|
||||
getData(1);
|
||||
layer.close(loadT);
|
||||
layer.msg(frdata.msg,{icon:frdata.status?1:2});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//批量删除
|
||||
function allDeleteDatabase(){
|
||||
var checkList = $("input[name=id]");
|
||||
var dataList = new Array();
|
||||
for(var i=0;i<checkList.length;i++){
|
||||
if(!checkList[i].checked) continue;
|
||||
var tmp = new Object();
|
||||
tmp.name = checkList[i].title;
|
||||
tmp.id = checkList[i].value;
|
||||
dataList.push(tmp);
|
||||
}
|
||||
SafeMessage(lan.database.del_all_title,"<a style='color:red;'>"+lan.get('del_all_database',[dataList.length])+"</a>",function(){
|
||||
layer.closeAll();
|
||||
syncDelete(dataList,0,'');
|
||||
});
|
||||
}
|
||||
|
||||
//模拟同步开始批量删除数据库
|
||||
function syncDelete(dataList,successCount,errorMsg){
|
||||
if(dataList.length < 1) {
|
||||
layer.msg(lan.get('del_all_database_ok',[successCount]),{icon:1});
|
||||
return;
|
||||
}
|
||||
var loadT = layer.msg(lan.get('del_all_task_the',[dataList[0].name]),{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'/database?action=DeleteDatabase',
|
||||
data:'id='+dataList[0].id+'&name='+dataList[0].name,
|
||||
async: true,
|
||||
success:function(frdata){
|
||||
layer.close(loadT);
|
||||
if(frdata.status){
|
||||
successCount++;
|
||||
$("input[title='"+dataList[0].name+"']").parents("tr").remove();
|
||||
}else{
|
||||
if(!errorMsg){
|
||||
errorMsg = '<br><p>'+lan.database.del_all_err+'</p>';
|
||||
}
|
||||
errorMsg += '<li>'+dataList[0].name+' -> '+frdata.msg+'</li>'
|
||||
}
|
||||
|
||||
dataList.splice(0,1);
|
||||
syncDelete(dataList,successCount,errorMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 选中项操作
|
||||
*/
|
||||
function goSet(num){
|
||||
//取选中对象
|
||||
var el = document.getElementsByTagName('input');
|
||||
var len = el.length;
|
||||
var data='';
|
||||
var a = '';
|
||||
var count = 0;
|
||||
//构造POST数据
|
||||
for(var i=0;i<len;i++){
|
||||
if(el[i].checked == true && el[i].value != 'on'){
|
||||
data += a+count+'='+el[i].value;
|
||||
a = '&';
|
||||
count++;
|
||||
}
|
||||
}
|
||||
//判断操作类别
|
||||
if(num==1){
|
||||
reAdd(data);
|
||||
}
|
||||
else if(num==2){
|
||||
shift(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Date.prototype.format = function(format)
|
||||
{
|
||||
var o = {
|
||||
"M+" : this.getMonth()+1, //month
|
||||
"d+" : this.getDate(), //day
|
||||
"h+" : this.getHours(), //hour
|
||||
"m+" : this.getMinutes(), //minute
|
||||
"s+" : this.getSeconds(), //second
|
||||
"q+" : Math.floor((this.getMonth()+3)/3), //quarter
|
||||
"S" : this.getMilliseconds() //millisecond
|
||||
}
|
||||
if(/(y+)/.test(format)) format=format.replace(RegExp.$1,
|
||||
(this.getFullYear()+"").substr(4 - RegExp.$1.length));
|
||||
for(var k in o)if(new RegExp("("+ k +")").test(format))
|
||||
format = format.replace(RegExp.$1,
|
||||
RegExp.$1.length==1 ? o[k] :
|
||||
("00"+ o[k]).substr((""+ o[k]).length));
|
||||
return format;
|
||||
}
|
||||
//时间戳到格式日期
|
||||
function getLocalTime(tm) {
|
||||
return new Date(parseInt(tm) * 1000).format("yyyy/MM/dd hh:mm:ss");
|
||||
}
|
||||
|
||||
|
||||
//取扩展名
|
||||
function GetExtName(fileName,oext){
|
||||
var extArr = fileName.split(".");
|
||||
var exts = ['conf','sh','cnf','pl','so','passwd','cshrc','deny','cache','init','po','ext2','ext3','ext4','i686','img','gz','efi','old','pid','lock','frm','opt','err','MYI','MYD','CSM'];
|
||||
var extLastName = extArr[extArr.length - 1];
|
||||
if(oext) return extLastName;
|
||||
if(extArr.length<2 || extLastName.length>5 || extLastName.length < 2){
|
||||
return "file";
|
||||
}
|
||||
for(var i=0; i<exts.length; i++){
|
||||
if(exts[i]==extLastName){
|
||||
return "file";
|
||||
}
|
||||
}
|
||||
return extLastName;
|
||||
}
|
||||
|
||||
//导入数据库
|
||||
function InputDatabase(name){
|
||||
var path = getCookie('backup_path') + "/database";
|
||||
$.post('/files?action=GetDir','path='+path,function(rdata){
|
||||
var Body = '';
|
||||
for (var i = 0; i < rdata.FILES.length; i++) {
|
||||
if(rdata.FILES[i] == null) continue;
|
||||
var fmp = rdata.FILES[i].split(";");
|
||||
var ext = GetExtName(fmp[0],true);
|
||||
|
||||
if(ext != 'sql' && ext != 'zip' && ext != 'gz' && ext != 'tgz') continue;
|
||||
Body += "<tr>\
|
||||
<td class='column-name'><span class='ico ico-"+ext+"'></span><a class='text'>" + fmp[0] + "</a></td>\
|
||||
<td>" + ((fmp[2].length > 11)?fmp[2]:getLocalTime(fmp[2])) + "</td>\
|
||||
<td>" + (ToSize(fmp[1])) + "</td>\
|
||||
<td class='editmenu'>\
|
||||
<a class='btlink' href='javascript:;' onclick=\"RecoveryData('" + rdata.PATH +"/"+ fmp[0] + "','"+name+"')\">"+lan.database.input+"</a>\
|
||||
</span></td>\
|
||||
</tr>";
|
||||
}
|
||||
layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '600px',
|
||||
title: lan.database.input_title_file,
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15">'
|
||||
+'<button class="btn btn-default btn-sm" onclick="UploadFiles1(\''+name+'\')">'+lan.database.input_local_up+'</button>'
|
||||
+'<div class="divtable mtb15" style="max-height:300px; overflow:auto">'
|
||||
+'<table class="table table-hover">'
|
||||
+'<thead>'
|
||||
+'<tr>'
|
||||
+'<th>'+lan.files.file_name+'</th>'
|
||||
+'<th>'+lan.files.file_etime+'</th>'
|
||||
+'<th>'+lan.files.file_size+'</th>'
|
||||
+'<th>'+lan.public.action+'</th>'
|
||||
+'</tr>'
|
||||
+'</thead>'
|
||||
+'<tbody>'+Body+'</tbody>'
|
||||
+'</table>'
|
||||
+'</div>'
|
||||
+'<ul class="help-info-text c7">'
|
||||
+'<li>'+lan.database.input_ps1+'</li>'
|
||||
+'<li>'+lan.database.input_ps2+'</li>'
|
||||
+'<li>'+lan.database.input_ps3+'</li>'
|
||||
+'</ul>'
|
||||
+'</div>'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//上传文件
|
||||
function UploadFiles1(name){
|
||||
var path = getCookie('backup_path') + "/database/";
|
||||
var index = layer.open({
|
||||
type:1,
|
||||
closeBtn: 2,
|
||||
title:lan.files.up_title+' --- <span style="color:red;">'+lan.database.input_up_type+'</span>',
|
||||
area: ['500px','500px'],
|
||||
shadeClose:false,
|
||||
content:'<div class="fileUploadDiv"><input type="hidden" id="input-val" value="'+path+'" />\
|
||||
<input type="file" id="file_input" multiple="true" autocomplete="off" />\
|
||||
<button type="button" id="opt" autocomplete="off">'+lan.files.up_add+'</button>\
|
||||
<button type="button" id="up" autocomplete="off" >'+lan.files.up_start+'</button>\
|
||||
<span id="totalProgress" style="position: absolute;top: 7px;right: 147px;"></span>\
|
||||
<span style="float:right;margin-top: 9px;">\
|
||||
<font>'+lan.files.up_coding+':</font>\
|
||||
<select id="fileCodeing" >\
|
||||
<option value="byte">'+lan.files.up_bin+'</option>\
|
||||
<option value="utf-8">UTF-8</option>\
|
||||
<option value="gb18030">GB2312</option>\
|
||||
</select>\
|
||||
</span>\
|
||||
<button type="button" id="filesClose" autocomplete="off">'+lan.public.close+'</button>\
|
||||
<ul id="up_box"></ul></div>'
|
||||
});
|
||||
$("#filesClose").click(function(){
|
||||
layer.close(index);
|
||||
InputDatabase(name);
|
||||
});
|
||||
UploadStart(true);
|
||||
}
|
||||
|
||||
|
||||
//设置访问权限
|
||||
function SetDatabaseAccess(dataName,action){
|
||||
if(action == 1){
|
||||
var access = $("#dataAccess").val();
|
||||
if(access == 'ip') access = $("input[name=address]").val();
|
||||
layer.msg(lan.public.the,{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/database?action=SetDatabaseAccess','name='+dataName+'&access='+access,function(rdata){
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$.post('/database?action=GetDatabaseAccess','name='+dataName,function(rdata){
|
||||
if(rdata == null){
|
||||
layer.msg(lan.database.auth_err,{icon:2});
|
||||
return;
|
||||
}
|
||||
layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '480px',
|
||||
title: lan.database.auth_title+'['+dataName+']',
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<form class='bt-form pd20 pb70' id='DatabaseAccess'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.database.auth_name+"</span>\
|
||||
<div class='info-r'>\
|
||||
<select id='dataAccess' class='bt-input-text mr5' style='width:88px;'>\
|
||||
<option value='127.0.0.1' "+(rdata.msg == '127.0.0.1'?'selected':'')+">"+lan.database.add_auth_local+"</option>\
|
||||
<option value='%' "+(rdata.msg == '%'?'selected':'')+">"+lan.database.add_auth_all+"</option>\
|
||||
<option value='ip' "+((rdata.msg != '127.0.0.1' && rdata.msg != '%')?'selected':'')+">"+lan.database.add_auth_ip+"</option>\
|
||||
</select>\
|
||||
<input class='bt-input-text' type='text' name='address' placeholder='允可IP,多个请用逗号隔开' value='"+rdata.msg+"' style='width:218px;"+((rdata.msg != '127.0.0.1' && rdata.msg != '%')?'':'display:none;')+"' />\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button type='button' class='btn btn-danger btn-sm btn-title' onclick='layer.closeAll()'>"+lan.public.close+"</button>\
|
||||
<button type='button' class='btn btn-success btn-sm btn-title' onclick=\"SetDatabaseAccess('"+dataName+"',1)\" >"+lan.public.ok+"</button>\
|
||||
</div>\
|
||||
</form>"
|
||||
});
|
||||
|
||||
$("#dataAccess").change(function(){
|
||||
var access = $(this).val();
|
||||
if(access == 'ip'){
|
||||
$("input[name=address]").show().val('');
|
||||
}else{
|
||||
$("input[name=address]").hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//同步到数据库
|
||||
function SyncToDatabases(type){
|
||||
//取选中对象
|
||||
var el = document.getElementsByTagName('input');
|
||||
var len = el.length;
|
||||
var data=[];
|
||||
//构造POST数据
|
||||
for(var i=0;i<len;i++){
|
||||
if(el[i].checked == true && el[i].value != 'on'){
|
||||
data.push(el[i].value)
|
||||
}
|
||||
}
|
||||
|
||||
var loadT = layer.msg(lan.database.sync_the,{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/database?action=SyncToDatabases&type='+type,{ids:JSON.stringify(data)},function(rdata){
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
});
|
||||
}
|
||||
|
||||
//从数据库中获取
|
||||
function SyncGetDatabases(){
|
||||
var loadT = layer.msg(lan.database.sync_the,{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/database?action=SyncGetDatabases',function(rdata){
|
||||
layer.close(loadT);
|
||||
getData(1);
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//管理数据库
|
||||
function AdminDatabase(name,username,password){
|
||||
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
|
||||
layer.msg(lan.database.phpmyadmin_err,{icon:2,shade: [0.3, '#000']})
|
||||
setTimeout(function(){ window.location.href = '/soft'; },3000);
|
||||
return;
|
||||
}
|
||||
var murl = $("#toPHPMyAdmin").attr('action');
|
||||
$("#pma_username").val(username);
|
||||
$("#pma_password").val(password);
|
||||
$("#db").val(name);
|
||||
layer.msg(lan.database.phpmyadmin,{icon:16,shade: [0.3, '#000'],time:1000});
|
||||
setTimeout(function(){
|
||||
$("#toPHPMyAdmin").submit();
|
||||
},200);
|
||||
}
|
||||
|
||||
$(".safe .tipstitle").mouseover(function(){
|
||||
var title = $(this).attr("data-title");
|
||||
layer.tips(title, this, {
|
||||
tips: [1, '#3c8dbc'],
|
||||
time:0
|
||||
})
|
||||
}).mouseout(function(){
|
||||
$(".layui-layer-tips").remove();
|
||||
})
|
||||
$(".btn-more").hover(function(){
|
||||
$(this).addClass("open");
|
||||
},function(){
|
||||
$(this).removeClass("open");
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
{% extends "default/layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="main-content pb55">
|
||||
<div class="container-fluid">
|
||||
<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="search pull-right">
|
||||
<form target="hid" onsubmit='getData(1,$$("#SearchValue").prop("value"))'>
|
||||
<input type="text" id="SearchValue" class="ser-text pull-left" placeholder="搜索数据库" />
|
||||
<button type="button" class="ser-sub pull-left" onclick='getData(1,$$("#SearchValue").prop("value"))'></button>
|
||||
</form>
|
||||
<iframe name='hid' id="hid" style="display:none"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="safe bgw mtb15 pd15">
|
||||
<button onclick="DataAdd(0)" title="添加数据库" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加数据库</button>
|
||||
<button onclick="DataSetuppwd(0)" title="$tData['lan']['BTNT2']" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">root密码</button>
|
||||
<button onclick="AdminDatabase('','root','$tData['mysql_root']')" title="$tData['lan']['BTNT3']" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">phpMyAdmin</button>
|
||||
<span style="float:right">
|
||||
<button id="allDelete" style="float: right;display: none;margin-left:10px;" onclick="allDeleteDatabase();" title="$tData['lan']['BTNT4']" class="btn btn-default btn-sm">$tData['lan']['BTN4']</button>
|
||||
<button onclick="Recycle_bin('open');" id="dataRecycle" title="$tData['lan']['BTNT4']" class="btn btn-default btn-sm" style="margin-left: 5px;"><span class="glyphicon glyphicon-trash" style="margin-right: 5px;"></span>回收站</button>
|
||||
</span>
|
||||
<div class="divtable mtb10">
|
||||
<div class="tablescroll">
|
||||
<table class="table table-hover" style="min-width: 900px;border: 0 none;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width='30px'><input onclick="checkSelect();" type="checkbox" id="setBox"></th>
|
||||
<th onclick="listOrder('name','database',this)" style="cursor: pointer;">数据库名<span class="glyphicon glyphicon-triangle-top" style="margin-left:5px;color:#bbb"></span></th>
|
||||
<th onclick="listOrder('name','database',this)" style="cursor: pointer;">用户名<span class="glyphicon glyphicon-triangle-top" style="margin-left:5px;color:#bbb"></span></th>
|
||||
<th>密码</th>
|
||||
<th width="140">备份</th>
|
||||
<th>备注</th>
|
||||
<th width="260" class="text-right">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="DataBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="dataTables_paginate paging_bootstrap pagination">
|
||||
<span class="sync btn btn-default btn-sm" style="margin-right:5px" onclick="SyncToDatabases(1)" title="$tData['lan']['TP1']">同步选中</span>
|
||||
<span class="sync btn btn-default btn-sm" style="margin-right:5px" onclick="SyncToDatabases(0)" title="$tData['lan']['TP2']">同步所有</span>
|
||||
<span class="sync btn btn-default btn-sm" onclick="SyncGetDatabases()" title="$tData['lan']['TP3']">从服务器获取</span>
|
||||
<ul id="DataPage" class="page pull-right"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form id="toPHPMyAdmin" action="$web.ctx.session.phpmyadminDir/index.php" method="post" style="display: none;" target="_blank">
|
||||
<input type="text" name="pma_username" id="pma_username" value="" />
|
||||
<input type="password" name="pma_password" id="pma_password" value="" />
|
||||
<input type="text" name="server" value="1" />
|
||||
<input type="text" name="target" value="index.php" />
|
||||
<input type="text" name="db" id="db" value="" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/static/app/data.js?v={{config.version}}"></script>
|
||||
<script type="text/javascript" src="/static/app/files.js?v={{config.version}}></script>
|
||||
<script type="text/javascript">
|
||||
// $if not tData['isSetup']:
|
||||
// layer.msg('$tData["lan"]["JS1"]<a href="/soft#i" style="color:#20a53a;float: right;">$tData["lan"]["JS2"]</a>',{icon:7,shade: [0.3, '#000'],time:0});
|
||||
// $(".layui-layer-shade").css("margin-left","180px");
|
||||
setTimeout(function(){
|
||||
getData(1);
|
||||
},300);
|
||||
|
||||
$("#dataRecycle").click(function(){
|
||||
setTimeout(function(){
|
||||
Recycle_bin(6);
|
||||
},1000);
|
||||
// });
|
||||
</script>
|
||||
<script src="/static/app/upload.js?v={{config.version}}"></script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,441 @@
|
||||
function selectChange() {
|
||||
$("#SelectVersion,#selectVer").change(function() {
|
||||
var info = $(this).val();
|
||||
var name = info.split(" ")[0];
|
||||
var version = info.split(" ")[1];
|
||||
max = 64
|
||||
msg = "64M"
|
||||
if (name == 'mysql') {
|
||||
memSize = getCookie('memSize');
|
||||
switch (version) {
|
||||
case '5.1':
|
||||
max = 256;
|
||||
msg = '256M';
|
||||
break;
|
||||
case '8.0':
|
||||
max = 5200;
|
||||
msg = '6GB';
|
||||
break;
|
||||
case '5.7':
|
||||
max = 1500;
|
||||
msg = '2GB';
|
||||
break;
|
||||
case '5.6':
|
||||
max = 800;
|
||||
msg = '1GB';
|
||||
break;
|
||||
case 'AliSQL':
|
||||
max = 800;
|
||||
msg = '1GB';
|
||||
break;
|
||||
case 'mariadb_10.0':
|
||||
max = 800;
|
||||
msg = '1GB';
|
||||
break;
|
||||
case 'mariadb_10.1':
|
||||
max = 1500;
|
||||
msg = '2GB';
|
||||
break;
|
||||
}
|
||||
if (memSize < max) {
|
||||
layer.msg(lan.bt.insatll_mem.replace('{1}', msg).replace('{2}', version), { icon: 5 });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
//设置二进制日志
|
||||
function SetBinLog() {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/database?action=BinLog', "", function(rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
mysqlLog();
|
||||
});
|
||||
}
|
||||
|
||||
//清空日志
|
||||
function closeMySqlLog() {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/database?action=GetErrorLog', "close=1", function(rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
mysqlLog();
|
||||
});
|
||||
}
|
||||
|
||||
//数据库端口
|
||||
function changeMySQLPort(act) {
|
||||
if (act != undefined) {
|
||||
layer.confirm(lan.soft.mysql_port_title, { closeBtn: 2, icon: 3 }, function() {
|
||||
var port = $("#dataport").val();
|
||||
var data = 'port=' + port;
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/database?action=SetMySQLPort', data, function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$.post('/database?action=GetMySQLInfo', '', function(rdata) {
|
||||
var LimitCon = '<p class="conf_p">\
|
||||
<input id="dataport" class="phpUploadLimit bt-input-text mr20" type="number" value="' + rdata.port + '" name="dataport">\
|
||||
<button style="margin-top: -1px;" class="btn btn-success btn-sm" onclick="changeMySQLPort(1)">' + lan.public.edit + '</button>\
|
||||
</p>';
|
||||
|
||||
$(".soft-man-con").html(LimitCon);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//软件切换版本
|
||||
function softChangeVer(name, version) {
|
||||
if (name == "mysqld") name = "mysql";
|
||||
var veropt = version.split("|");
|
||||
var SelectVersion = '';
|
||||
for (var i = 0; i < veropt.length; i++) {
|
||||
SelectVersion += '<option>' + name + ' ' + veropt[i] + '</option>';
|
||||
}
|
||||
|
||||
var body = "<div class='ver line'><span class='tname'>" + lan.soft.select_version + "</span><select id='selectVer' class='bt-input-text mr20' name='phpVersion' style='width:160px'>";
|
||||
body += SelectVersion + '</select><button class="btn btn-success btn-sm">' + lan.soft.version_to + '</button></div>';
|
||||
|
||||
if (name == 'mysql') {
|
||||
body += "<ul class='help-info-text c7 ptb15'><li style='color:red;'>" + lan.soft.mysql_f + "</li></ul>"
|
||||
}
|
||||
|
||||
$(".soft-man-con").html(body);
|
||||
$(".btn-success").click(function() {
|
||||
var ver = $("#selectVer").val();
|
||||
oneInstall(name, ver.split(" ")[1]);
|
||||
});
|
||||
selectChange();
|
||||
}
|
||||
|
||||
|
||||
//设置MySQL配置参数
|
||||
function SetMySQLConf() {
|
||||
$.post('/system?action=GetMemInfo', '', function(memInfo) {
|
||||
//var memSize = memInfo['memTotal'];
|
||||
//var setSize = parseInt($("input[name='memSize']").val());
|
||||
//if(memSize < setSize){
|
||||
// var msg = lan.soft.mysql_set_err.replace('{1}',memSize).replace('{2}',setSize);
|
||||
// layer.msg(msg,{icon:2,time:5000});
|
||||
// return;
|
||||
//}
|
||||
var query_cache_size = parseInt($("input[name='query_cache_size']").val());
|
||||
var query_cache_type = 0;
|
||||
if (query_cache_size > 0) {
|
||||
query_cache_type = 1;
|
||||
}
|
||||
var data = {
|
||||
key_buffer_size: parseInt($("input[name='key_buffer_size']").val()),
|
||||
query_cache_size: query_cache_size,
|
||||
query_cache_type: query_cache_type,
|
||||
tmp_table_size: parseInt($("input[name='tmp_table_size']").val()),
|
||||
max_heap_table_size: parseInt($("input[name='tmp_table_size']").val()),
|
||||
innodb_buffer_pool_size: parseInt($("input[name='innodb_buffer_pool_size']").val()),
|
||||
innodb_log_buffer_size: parseInt($("input[name='innodb_log_buffer_size']").val()),
|
||||
sort_buffer_size: parseInt($("input[name='sort_buffer_size']").val()),
|
||||
read_buffer_size: parseInt($("input[name='read_buffer_size']").val()),
|
||||
read_rnd_buffer_size: parseInt($("input[name='read_rnd_buffer_size']").val()),
|
||||
join_buffer_size: parseInt($("input[name='join_buffer_size']").val()),
|
||||
thread_stack: parseInt($("input[name='thread_stack']").val()),
|
||||
binlog_cache_size: parseInt($("input[name='binlog_cache_size']").val()),
|
||||
thread_cache_size: parseInt($("input[name='thread_cache_size']").val()),
|
||||
table_open_cache: parseInt($("input[name='table_open_cache']").val()),
|
||||
max_connections: parseInt($("input[name='max_connections']").val())
|
||||
};
|
||||
|
||||
$.post('/database?action=SetDbConf', data, function(rdata) {
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//MySQL内存优化方案
|
||||
function MySQLMemOpt(opt) {
|
||||
var query_size = parseInt($("input[name='query_cache_size']").val());
|
||||
switch (opt) {
|
||||
case '1':
|
||||
$("input[name='key_buffer_size']").val(128);
|
||||
if (query_size) $("input[name='query_cache_size']").val(64);
|
||||
$("input[name='tmp_table_size']").val(64);
|
||||
$("input[name='innodb_buffer_pool_size']").val(256);
|
||||
$("input[name='sort_buffer_size']").val(768);
|
||||
$("input[name='read_buffer_size']").val(768);
|
||||
$("input[name='read_rnd_buffer_size']").val(512);
|
||||
$("input[name='join_buffer_size']").val(1024);
|
||||
$("input[name='thread_stack']").val(256);
|
||||
$("input[name='binlog_cache_size']").val(64);
|
||||
$("input[name='thread_cache_size']").val(64);
|
||||
$("input[name='table_open_cache']").val(128);
|
||||
$("input[name='max_connections']").val(100);
|
||||
break;
|
||||
case '2':
|
||||
$("input[name='key_buffer_size']").val(256);
|
||||
if (query_size) $("input[name='query_cache_size']").val(128);
|
||||
$("input[name='tmp_table_size']").val(384);
|
||||
$("input[name='innodb_buffer_pool_size']").val(384);
|
||||
$("input[name='sort_buffer_size']").val(768);
|
||||
$("input[name='read_buffer_size']").val(768);
|
||||
$("input[name='read_rnd_buffer_size']").val(512);
|
||||
$("input[name='join_buffer_size']").val(2048);
|
||||
$("input[name='thread_stack']").val(256);
|
||||
$("input[name='binlog_cache_size']").val(64);
|
||||
$("input[name='thread_cache_size']").val(96);
|
||||
$("input[name='table_open_cache']").val(192);
|
||||
$("input[name='max_connections']").val(200);
|
||||
break;
|
||||
case '3':
|
||||
$("input[name='key_buffer_size']").val(384);
|
||||
if (query_size) $("input[name='query_cache_size']").val(192);
|
||||
$("input[name='tmp_table_size']").val(512);
|
||||
$("input[name='innodb_buffer_pool_size']").val(512);
|
||||
$("input[name='sort_buffer_size']").val(1024);
|
||||
$("input[name='read_buffer_size']").val(1024);
|
||||
$("input[name='read_rnd_buffer_size']").val(768);
|
||||
$("input[name='join_buffer_size']").val(2048);
|
||||
$("input[name='thread_stack']").val(256);
|
||||
$("input[name='binlog_cache_size']").val(128);
|
||||
$("input[name='thread_cache_size']").val(128);
|
||||
$("input[name='table_open_cache']").val(384);
|
||||
$("input[name='max_connections']").val(300);
|
||||
break;
|
||||
case '4':
|
||||
$("input[name='key_buffer_size']").val(512);
|
||||
if (query_size) $("input[name='query_cache_size']").val(256);
|
||||
$("input[name='tmp_table_size']").val(1024);
|
||||
$("input[name='innodb_buffer_pool_size']").val(1024);
|
||||
$("input[name='sort_buffer_size']").val(2048);
|
||||
$("input[name='read_buffer_size']").val(2048);
|
||||
$("input[name='read_rnd_buffer_size']").val(1024);
|
||||
$("input[name='join_buffer_size']").val(4096);
|
||||
$("input[name='thread_stack']").val(384);
|
||||
$("input[name='binlog_cache_size']").val(192);
|
||||
$("input[name='thread_cache_size']").val(192);
|
||||
$("input[name='table_open_cache']").val(1024);
|
||||
$("input[name='max_connections']").val(400);
|
||||
break;
|
||||
case '5':
|
||||
$("input[name='key_buffer_size']").val(1024);
|
||||
if (query_size) $("input[name='query_cache_size']").val(384);
|
||||
$("input[name='tmp_table_size']").val(2048);
|
||||
$("input[name='innodb_buffer_pool_size']").val(4096);
|
||||
$("input[name='sort_buffer_size']").val(4096);
|
||||
$("input[name='read_buffer_size']").val(4096);
|
||||
$("input[name='read_rnd_buffer_size']").val(2048);
|
||||
$("input[name='join_buffer_size']").val(8192);
|
||||
$("input[name='thread_stack']").val(512);
|
||||
$("input[name='binlog_cache_size']").val(256);
|
||||
$("input[name='thread_cache_size']").val(256);
|
||||
$("input[name='table_open_cache']").val(2048);
|
||||
$("input[name='max_connections']").val(500);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//重启MySQL
|
||||
function ReBootMySqld() {
|
||||
var loadT = layer.msg(lan.get('service_the', [lan.bt.restart, 'MySQLd']), { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/system?action=ServiceAdmin', 'name=mysqld&type=restart', function(rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
|
||||
//计算MySQL内存开销
|
||||
function ComMySqlMem() {
|
||||
var key_buffer_size = parseInt($("input[name='key_buffer_size']").val());
|
||||
var query_cache_size = parseInt($("input[name='query_cache_size']").val());
|
||||
var tmp_table_size = parseInt($("input[name='tmp_table_size']").val());
|
||||
var innodb_buffer_pool_size = parseInt($("input[name='innodb_buffer_pool_size']").val());
|
||||
var innodb_additional_mem_pool_size = parseInt($("input[name='innodb_additional_mem_pool_size']").val());
|
||||
var innodb_log_buffer_size = parseInt($("input[name='innodb_log_buffer_size']").val());
|
||||
|
||||
var sort_buffer_size = $("input[name='sort_buffer_size']").val() / 1024;
|
||||
var read_buffer_size = $("input[name='read_buffer_size']").val() / 1024;
|
||||
var read_rnd_buffer_size = $("input[name='read_rnd_buffer_size']").val() / 1024;
|
||||
var join_buffer_size = $("input[name='join_buffer_size']").val() / 1024;
|
||||
var thread_stack = $("input[name='thread_stack']").val() / 1024;
|
||||
var binlog_cache_size = $("input[name='binlog_cache_size']").val() / 1024;
|
||||
var max_connections = $("input[name='max_connections']").val();
|
||||
|
||||
var a = key_buffer_size + query_cache_size + tmp_table_size + innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size
|
||||
var b = sort_buffer_size + read_buffer_size + read_rnd_buffer_size + join_buffer_size + thread_stack + binlog_cache_size
|
||||
var memSize = a + max_connections * b
|
||||
$("input[name='memSize']").val(memSize.toFixed(2));
|
||||
}
|
||||
|
||||
//数据库存储信置
|
||||
function changeMySQLDataPath(act) {
|
||||
if (act != undefined) {
|
||||
layer.confirm(lan.soft.mysql_to_msg, { closeBtn: 2, icon: 3 }, function() {
|
||||
var datadir = $("#datadir").val();
|
||||
var data = 'datadir=' + datadir;
|
||||
var loadT = layer.msg(lan.soft.mysql_to_msg1, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/database?action=SetDataDir', data, function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$.post('/database?action=GetMySQLInfo', '', function(rdata) {
|
||||
var LimitCon = '<p class="conf_p">\
|
||||
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
|
||||
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
|
||||
</p>';
|
||||
$(".soft-man-con").html(LimitCon);
|
||||
});
|
||||
}
|
||||
|
||||
//MySQL-Slow日志
|
||||
function mysqlSlowLog() {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/database?action=GetSlowLogs', {}, function(logs) {
|
||||
layer.close(loadT);
|
||||
if (logs.status !== true) {
|
||||
logs.msg = '';
|
||||
}
|
||||
if (logs.msg == '') logs.msg = '当前没有慢日志.';
|
||||
var phpCon = '<textarea readonly="" style="margin: 0px;width: 500px;height: 520px;background-color: #333;color:#fff; padding:0 5px" id="error_log">' + logs.msg + '</textarea>';
|
||||
$(".soft-man-con").html(phpCon);
|
||||
var ob = document.getElementById('error_log');
|
||||
ob.scrollTop = ob.scrollHeight;
|
||||
});
|
||||
}
|
||||
|
||||
//数据库日志
|
||||
function mysqlLog(act) {
|
||||
//获取二进制日志相关信息
|
||||
$.post('/database?action=BinLog', "status=1", function(rdata) {
|
||||
var limitCon = '<p class="conf_p">\
|
||||
<span class="f14 c6 mr20">' + lan.soft.mysql_log_bin + ' </span><span class="f14 c6 mr20">' + ToSize(rdata.msg) + '</span>\
|
||||
<button class="btn btn-success btn-xs va0" onclick="SetBinLog();">' + (rdata.status ? lan.soft.off : lan.soft.on) + '</button>\
|
||||
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">' + lan.soft.mysql_log_err + '<button class="btn btn-default btn-xs" style="float:right;" onclick="closeMySqlLog();">' + lan.soft.mysql_log_close + '</button></p>\
|
||||
<textarea readonly style="margin: 0px;width: 515px;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
|
||||
</p>'
|
||||
|
||||
$(".soft-man-con").html(limitCon);
|
||||
|
||||
//获取错误日志
|
||||
$.post('/database?action=GetErrorLog', "", function(error_body) {
|
||||
if (error_body.status === false) {
|
||||
layer.msg(error_body.msg, { icon: 5 });
|
||||
error_body = lan.soft.mysql_log_ps1;
|
||||
}
|
||||
if (error_body == "") error_body = lan.soft.mysql_log_ps1;
|
||||
$("#error_log").text(error_body);
|
||||
var ob = document.getElementById('error_log');
|
||||
ob.scrollTop = ob.scrollHeight;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//取数据库运行状态
|
||||
function mysqlRunStatus() {
|
||||
$.post('/database?action=GetRunStatus', "", function(rdata) {
|
||||
var cache_size = ((parseInt(rdata.Qcache_hits) / (parseInt(rdata.Qcache_hits) + parseInt(rdata.Qcache_inserts))) * 100).toFixed(2) + '%';
|
||||
if (cache_size == 'NaN%') cache_size = 'OFF';
|
||||
var Con = '<div class="divtable"><table class="table table-hover table-bordered" style="width: 490px;margin-bottom:10px;background-color:#fafafa">\
|
||||
<tbody>\
|
||||
<tr><th>' + lan.soft.mysql_status_title1 + '</th><td>' + getLocalTime(rdata.Run) + '</td><th>' + lan.soft.mysql_status_title5 + '</th><td>' + parseInt(rdata.Questions / rdata.Uptime) + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title2 + '</th><td>' + rdata.Connections + '</td><th>' + lan.soft.mysql_status_title6 + '</th><td>' + parseInt((parseInt(rdata.Com_commit) + parseInt(rdata.Com_rollback)) / rdata.Uptime) + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title3 + '</th><td>' + ToSize(rdata.Bytes_sent) + '</td><th>' + lan.soft.mysql_status_title7 + '</th><td>' + rdata.File + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title4 + '</th><td>' + ToSize(rdata.Bytes_received) + '</td><th>' + lan.soft.mysql_status_title8 + '</th><td>' + rdata.Position + '</td></tr>\
|
||||
</tbody>\
|
||||
</table>\
|
||||
<table class="table table-hover table-bordered" style="width: 490px;">\
|
||||
<thead style="display:none;"><th></th><th></th><th></th><th></th></thead>\
|
||||
<tbody>\
|
||||
<tr><th>' + lan.soft.mysql_status_title9 + '</th><td>' + rdata.Threads_running + '/' + rdata.Max_used_connections + '</td><td colspan="2">' + lan.soft.mysql_status_ps1 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title10 + '</th><td>' + ((1 - rdata.Threads_created / rdata.Connections) * 100).toFixed(2) + '%</td><td colspan="2">' + lan.soft.mysql_status_ps2 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title11 + '</th><td>' + ((1 - rdata.Key_reads / rdata.Key_read_requests) * 100).toFixed(2) + '%</td><td colspan="2">' + lan.soft.mysql_status_ps3 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title12 + '</th><td>' + ((1 - rdata.Innodb_buffer_pool_reads / rdata.Innodb_buffer_pool_read_requests) * 100).toFixed(2) + '%</td><td colspan="2">' + lan.soft.mysql_status_ps4 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title13 + '</th><td>' + cache_size + '</td><td colspan="2">' + lan.soft.mysql_status_ps5 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title14 + '</th><td>' + ((rdata.Created_tmp_disk_tables / rdata.Created_tmp_tables) * 100).toFixed(2) + '%</td><td colspan="2">' + lan.soft.mysql_status_ps6 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title15 + '</th><td>' + rdata.Open_tables + '</td><td colspan="2">' + lan.soft.mysql_status_ps7 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title16 + '</th><td>' + rdata.Select_full_join + '</td><td colspan="2">' + lan.soft.mysql_status_ps8 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title17 + '</th><td>' + rdata.Select_range_check + '</td><td colspan="2">' + lan.soft.mysql_status_ps9 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title18 + '</th><td>' + rdata.Sort_merge_passes + '</td><td colspan="2">' + lan.soft.mysql_status_ps10 + '</td></tr>\
|
||||
<tr><th>' + lan.soft.mysql_status_title19 + '</th><td>' + rdata.Table_locks_waited + '</td><td colspan="2">' + lan.soft.mysql_status_ps11 + '</td></tr>\
|
||||
<tbody>\
|
||||
</table></div>'
|
||||
$(".soft-man-con").html(Con);
|
||||
});
|
||||
}
|
||||
|
||||
//数据库配置状态
|
||||
function mysqlStatus() {
|
||||
//获取MySQL配置
|
||||
$.post('/database?action=GetDbStatus', "", function(rdata) {
|
||||
var key_buffer_size = ToSizeM(rdata.mem.key_buffer_size)
|
||||
var query_cache_size = ToSizeM(rdata.mem.query_cache_size)
|
||||
var tmp_table_size = ToSizeM(rdata.mem.tmp_table_size)
|
||||
var innodb_buffer_pool_size = ToSizeM(rdata.mem.innodb_buffer_pool_size)
|
||||
var innodb_additional_mem_pool_size = ToSizeM(rdata.mem.innodb_additional_mem_pool_size)
|
||||
var innodb_log_buffer_size = ToSizeM(rdata.mem.innodb_log_buffer_size)
|
||||
|
||||
var sort_buffer_size = ToSizeM(rdata.mem.sort_buffer_size)
|
||||
var read_buffer_size = ToSizeM(rdata.mem.read_buffer_size)
|
||||
var read_rnd_buffer_size = ToSizeM(rdata.mem.read_rnd_buffer_size)
|
||||
var join_buffer_size = ToSizeM(rdata.mem.join_buffer_size)
|
||||
var thread_stack = ToSizeM(rdata.mem.thread_stack)
|
||||
var binlog_cache_size = ToSizeM(rdata.mem.binlog_cache_size)
|
||||
|
||||
var a = key_buffer_size + query_cache_size + tmp_table_size + innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size
|
||||
var b = sort_buffer_size + read_buffer_size + read_rnd_buffer_size + join_buffer_size + thread_stack + binlog_cache_size
|
||||
var memSize = a + rdata.mem.max_connections * b
|
||||
|
||||
|
||||
var memCon = '<div class="conf_p" style="margin-bottom:0">\
|
||||
<div style="border-bottom:#ccc 1px solid;padding-bottom:10px;margin-bottom:10px"><span><b>' + lan.soft.mysql_set_msg + '</b></span>\
|
||||
<select class="bt-input-text" name="mysql_set" style="margin-left:-4px">\
|
||||
<option value="0">' + lan.soft.mysql_set_select + '</option>\
|
||||
<option value="1">1-2GB</option>\
|
||||
<option value="2">2-4GB</option>\
|
||||
<option value="3">4-8GB</option>\
|
||||
<option value="4">8-16GB</option>\
|
||||
<option value="5">16-32GB</option>\
|
||||
</select>\
|
||||
<span>' + lan.soft.mysql_set_maxmem + ': </span><input style="width:70px;background-color:#eee;" class="bt-input-text mr5" name="memSize" type="text" value="' + memSize.toFixed(2) + '" readonly>MB\
|
||||
</div>\
|
||||
<p><span>key_buffer_size</span><input style="width: 70px;" class="bt-input-text mr5" name="key_buffer_size" value="' + key_buffer_size + '" type="number" >MB, <font>' + lan.soft.mysql_set_key_buffer_size + '</font></p>\
|
||||
<p><span>query_cache_size</span><input style="width: 70px;" class="bt-input-text mr5" name="query_cache_size" value="' + query_cache_size + '" type="number" >MB, <font>' + lan.soft.mysql_set_query_cache_size + '</font></p>\
|
||||
<p><span>tmp_table_size</span><input style="width: 70px;" class="bt-input-text mr5" name="tmp_table_size" value="' + tmp_table_size + '" type="number" >MB, <font>' + lan.soft.mysql_set_tmp_table_size + '</font></p>\
|
||||
<p><span>innodb_buffer_pool_size</span><input style="width: 70px;" class="bt-input-text mr5" name="innodb_buffer_pool_size" value="' + innodb_buffer_pool_size + '" type="number" >MB, <font>' + lan.soft.mysql_set_innodb_buffer_pool_size + '</font></p>\
|
||||
<p><span>innodb_log_buffer_size</span><input style="width: 70px;" class="bt-input-text mr5" name="innodb_log_buffer_size" value="' + innodb_log_buffer_size + '" type="number">MB, <font>' + lan.soft.mysql_set_innodb_log_buffer_size + '</font></p>\
|
||||
<p style="display:none;"><span>innodb_additional_mem_pool_size</span><input style="width: 70px;" class="bt-input-text mr5" name="innodb_additional_mem_pool_size" value="' + innodb_additional_mem_pool_size + '" type="number" >MB</p>\
|
||||
<p><span>sort_buffer_size</span><input style="width: 70px;" class="bt-input-text mr5" name="sort_buffer_size" value="' + (sort_buffer_size * 1024) + '" type="number" >KB * ' + lan.soft.mysql_set_conn + ', <font>' + lan.soft.mysql_set_sort_buffer_size + '</font></p>\
|
||||
<p><span>read_buffer_size</span><input style="width: 70px;" class="bt-input-text mr5" name="read_buffer_size" value="' + (read_buffer_size * 1024) + '" type="number" >KB * ' + lan.soft.mysql_set_conn + ', <font>' + lan.soft.mysql_set_read_buffer_size + ' </font></p>\
|
||||
<p><span>read_rnd_buffer_size</span><input style="width: 70px;" class="bt-input-text mr5" name="read_rnd_buffer_size" value="' + (read_rnd_buffer_size * 1024) + '" type="number" >KB * ' + lan.soft.mysql_set_conn + ', <font>' + lan.soft.mysql_set_read_rnd_buffer_size + ' </font></p>\
|
||||
<p><span>join_buffer_size</span><input style="width: 70px;" class="bt-input-text mr5" name="join_buffer_size" value="' + (join_buffer_size * 1024) + '" type="number" >KB * ' + lan.soft.mysql_set_conn + ', <font>' + lan.soft.mysql_set_join_buffer_size + '</font></p>\
|
||||
<p><span>thread_stack</span><input style="width: 70px;" class="bt-input-text mr5" name="thread_stack" value="' + (thread_stack * 1024) + '" type="number" >KB * ' + lan.soft.mysql_set_conn + ', <font>' + lan.soft.mysql_set_thread_stack + '</font></p>\
|
||||
<p><span>binlog_cache_size</span><input style="width: 70px;" class="bt-input-text mr5" name="binlog_cache_size" value="' + (binlog_cache_size * 1024) + '" type="number" >KB * ' + lan.soft.mysql_set_conn + ', <font>' + lan.soft.mysql_set_binlog_cache_size + '</font></p>\
|
||||
<p><span>thread_cache_size</span><input style="width: 70px;" class="bt-input-text mr5" name="thread_cache_size" value="' + rdata.mem.thread_cache_size + '" type="number" ><font> ' + lan.soft.mysql_set_thread_cache_size + '</font></p>\
|
||||
<p><span>table_open_cache</span><input style="width: 70px;" class="bt-input-text mr5" name="table_open_cache" value="' + rdata.mem.table_open_cache + '" type="number" > <font>' + lan.soft.mysql_set_table_open_cache + '</font></p>\
|
||||
<p><span>max_connections</span><input style="width: 70px;" class="bt-input-text mr5" name="max_connections" value="' + rdata.mem.max_connections + '" type="number" ><font> ' + lan.soft.mysql_set_max_connections + '</font></p>\
|
||||
<div style="margin-top:10px; padding-right:15px" class="text-right"><button class="btn btn-success btn-sm mr5" onclick="ReBootMySqld()">' + lan.soft.mysql_set_restart + '</button><button class="btn btn-success btn-sm" onclick="SetMySQLConf()">' + lan.public.save + '</button></div>\
|
||||
</div>'
|
||||
|
||||
$(".soft-man-con").html(memCon);
|
||||
|
||||
$(".conf_p input[name*='size'],.conf_p input[name='max_connections'],.conf_p input[name='thread_stack']").change(function() {
|
||||
ComMySqlMem();
|
||||
});
|
||||
|
||||
$(".conf_p select[name='mysql_set']").change(function() {
|
||||
MySQLMemOpt($(this).val());
|
||||
ComMySqlMem();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
|
||||
#https://dev.mysql.com/downloads/file/?id=480541
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
mysqlDir=${serverPath}/source/mysql
|
||||
|
||||
Install_mysql()
|
||||
{
|
||||
mkdir -p ${mysqlDir}
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
|
||||
if [ ! -f ${mysqlDir}/mysql-5.5.62.tar.gz ];then
|
||||
wget -O ${mysqlDir}/mysql-5.5.62.tar.gz https://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.62.tar.gz
|
||||
fi
|
||||
|
||||
if [ ! -f ${mysqlDir}/mysql-5.5.62 ];then
|
||||
cd ${mysqlDir} && tar -zxvf ${mysqlDir}/mysql-5.5.62.tar.gz
|
||||
fi
|
||||
|
||||
|
||||
cd ${mysqlDir}/mysql-5.5.62 && cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$serverPath/mysql \
|
||||
&& make && make install \
|
||||
&& echo '5.5' > $serverPath/mysql/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_mysql()
|
||||
{
|
||||
rm -rf $serverPath/mysql
|
||||
echo '卸载完成' > $install_tmp
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_mysql
|
||||
else
|
||||
Uninstall_mysql
|
||||
fi
|
||||
@@ -0,0 +1,73 @@
|
||||
user {$OS_USER} {$OS_USER_GROUP};
|
||||
worker_processes auto;
|
||||
error_log {$SERVER_PATH}/openresty/nginx/logs/error.log crit;
|
||||
pid {$SERVER_PATH}/openresty/nginx/logs/nginx.pid;
|
||||
|
||||
worker_rlimit_nofile 51200;
|
||||
|
||||
events
|
||||
{
|
||||
use {$EVENT_MODEL};
|
||||
worker_connections 51200;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http
|
||||
{
|
||||
include mime.types;
|
||||
#include luawaf.conf;
|
||||
|
||||
#include proxy.conf;
|
||||
|
||||
default_type application/octet-stream;
|
||||
|
||||
server_names_hash_bucket_size 512;
|
||||
client_header_buffer_size 32k;
|
||||
large_client_header_buffers 4 32k;
|
||||
client_max_body_size 50m;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
|
||||
keepalive_timeout 60;
|
||||
|
||||
tcp_nodelay on;
|
||||
|
||||
fastcgi_connect_timeout 300;
|
||||
fastcgi_send_timeout 300;
|
||||
fastcgi_read_timeout 300;
|
||||
fastcgi_buffer_size 64k;
|
||||
fastcgi_buffers 4 64k;
|
||||
fastcgi_busy_buffers_size 128k;
|
||||
fastcgi_temp_file_write_size 256k;
|
||||
fastcgi_intercept_errors on;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1k;
|
||||
gzip_buffers 4 16k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_comp_level 2;
|
||||
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
|
||||
gzip_vary on;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
limit_conn_zone $binary_remote_addr zone=perip:10m;
|
||||
limit_conn_zone $server_name zone=perserver:10m;
|
||||
|
||||
server_tokens off;
|
||||
access_log off;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name 127.0.0.1;
|
||||
allow 127.0.0.1;
|
||||
location /nginx_status {
|
||||
stub_status on;
|
||||
access_log off;
|
||||
}
|
||||
include {$SERVER_PATH}/openresty/nginx/conf/php_status/*.conf;
|
||||
}
|
||||
include {$SERVER_PATH}/openresty/nginx/conf/vhost/*.conf;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 501 B |
@@ -0,0 +1,18 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="orPluginService('openresty');">服务</p>
|
||||
<p onclick="pluginInitD('openresty');">自启动</p>
|
||||
<p onclick="pluginConfig('openresty');">配置修改</p>
|
||||
<p onclick="getOpenrestyStatus();">负载状态</p>
|
||||
<p onclick="pluginLogs('openresty');">错误日志</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=openresty&f=js/openresty.js");
|
||||
</script>
|
||||
@@ -0,0 +1,293 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
app_debug = False
|
||||
|
||||
if public.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'openresty'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getInitDFile():
|
||||
if app_debug:
|
||||
return '/tmp/' + getPluginName()
|
||||
return '/etc/init.d/' + getPluginName()
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def clearTemp():
|
||||
path_bin = getServerDir() + "/nginx"
|
||||
public.execShell('rm -rf ' + path_bin + '/client_body_temp')
|
||||
public.execShell('rm -rf ' + path_bin + '/fastcgi_temp')
|
||||
public.execShell('rm -rf ' + path_bin + '/proxy_temp')
|
||||
public.execShell('rm -rf ' + path_bin + '/scgi_temp')
|
||||
public.execShell('rm -rf ' + path_bin + '/uwsgi_temp')
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getPluginDir() + "/conf/nginx.conf"
|
||||
return path
|
||||
|
||||
|
||||
def getOs():
|
||||
data = {}
|
||||
data['os'] = public.getOs()
|
||||
ng_exe_bin = getServerDir() + "/nginx/sbin/nginx"
|
||||
if checkAuthEq(ng_exe_bin, 'root'):
|
||||
data['auth'] = True
|
||||
else:
|
||||
data['auth'] = False
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def getInitDTpl():
|
||||
path = getPluginDir() + "/init.d/nginx.tpl"
|
||||
return path
|
||||
|
||||
|
||||
def makeConf():
|
||||
vhost = getServerDir() + '/nginx/conf/vhost'
|
||||
if not os.path.exists(vhost):
|
||||
os.mkdir(vhost)
|
||||
php_status = getServerDir() + '/nginx/conf/php_status'
|
||||
if not os.path.exists(php_status):
|
||||
os.mkdir(php_status)
|
||||
|
||||
|
||||
def getFileOwner(filename):
|
||||
import pwd
|
||||
stat = os.lstat(filename)
|
||||
uid = stat.st_uid
|
||||
pw = pwd.getpwuid(uid)
|
||||
return pw.pw_name
|
||||
|
||||
|
||||
def checkAuthEq(file, owner='root'):
|
||||
fowner = getFileOwner(file)
|
||||
if (fowner == owner):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def confReplace():
|
||||
service_path = os.path.dirname(os.getcwd())
|
||||
content = public.readFile(getConf())
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
|
||||
user = 'www'
|
||||
user_group = 'www'
|
||||
|
||||
if public.getOs() == 'darwin':
|
||||
# macosx do
|
||||
user = public.execShell(
|
||||
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
|
||||
# user = 'root'
|
||||
user_group = 'staff'
|
||||
content = content.replace('{$EVENT_MODEL}', 'kqueue')
|
||||
else:
|
||||
user = 'www'
|
||||
user_group = 'www'
|
||||
content = content.replace('{$EVENT_MODEL}', 'epoll')
|
||||
|
||||
content = content.replace('{$OS_USER}', user)
|
||||
content = content.replace('{$OS_USER_GROUP}', user_group)
|
||||
|
||||
public.writeFile(getServerDir() + '/nginx/conf/nginx.conf', content)
|
||||
|
||||
# give nginx root permission
|
||||
ng_exe_bin = getServerDir() + "/nginx/sbin/nginx"
|
||||
if not checkAuthEq(ng_exe_bin, 'root'):
|
||||
args = getArgs()
|
||||
sudoPwd = args['pwd']
|
||||
cmd_own = 'chown -R ' + 'root:' + user_group + ' ' + ng_exe_bin
|
||||
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_own))
|
||||
cmd_mod = 'chmod 755 ' + ng_exe_bin
|
||||
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_mod))
|
||||
cmd_s = 'chmod u+s ' + ng_exe_bin
|
||||
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_s))
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
file_tpl = getInitDTpl()
|
||||
service_path = os.path.dirname(os.getcwd())
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
if not os.path.exists(initD_path):
|
||||
os.mkdir(initD_path)
|
||||
file_bin = initD_path + '/' + getPluginName()
|
||||
|
||||
# initd replace
|
||||
content = public.readFile(file_tpl)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
public.writeFile(file_bin, content)
|
||||
public.execShell('chmod +x ' + file_bin)
|
||||
|
||||
# config replace
|
||||
confReplace()
|
||||
|
||||
# make nginx vhost or other
|
||||
makeConf()
|
||||
|
||||
return file_bin
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep nginx |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def start():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' start')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
|
||||
|
||||
def stop():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' stop')
|
||||
clearTemp()
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
|
||||
|
||||
def restart():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' restart')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
|
||||
|
||||
def reload():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
if os.path.exists(initd_bin):
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
source_bin = initDreplace()
|
||||
initd_bin = getInitDFile()
|
||||
shutil.copyfile(source_bin, initd_bin)
|
||||
public.execShell('chmod +x ' + initd_bin)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
os.remove(initd_bin)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def runInfo():
|
||||
# 取Openresty负载状态
|
||||
try:
|
||||
result = public.httpGet('http://127.0.0.1/nginx_status')
|
||||
tmp = result.split()
|
||||
data = {}
|
||||
data['active'] = tmp[2]
|
||||
data['accepts'] = tmp[9]
|
||||
data['handled'] = tmp[7]
|
||||
data['requests'] = tmp[8]
|
||||
data['Reading'] = tmp[11]
|
||||
data['Writing'] = tmp[13]
|
||||
data['Waiting'] = tmp[15]
|
||||
return public.getJson(data)
|
||||
except Exception as e:
|
||||
return 'oprenresty not started'
|
||||
|
||||
|
||||
def errorLogPath():
|
||||
return getServerDir() + '/nginx/logs/error.log'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
elif func == 'start':
|
||||
print start()
|
||||
elif func == 'stop':
|
||||
print stop()
|
||||
elif func == 'restart':
|
||||
print restart()
|
||||
elif func == 'reload':
|
||||
print reload()
|
||||
elif func == 'initd_status':
|
||||
print initdStatus()
|
||||
elif func == 'initd_install':
|
||||
print initdInstall()
|
||||
elif func == 'initd_uninstall':
|
||||
print initdUinstall()
|
||||
elif func == 'conf':
|
||||
print getConf()
|
||||
elif func == 'get_os':
|
||||
print getOs()
|
||||
elif func == 'run_info':
|
||||
print runInfo()
|
||||
elif func == 'error_log':
|
||||
print errorLogPath()
|
||||
else:
|
||||
print 'error'
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"title":"OpenResty",
|
||||
"tip":"soft",
|
||||
"name":"openresty",
|
||||
"type":"其他插件",
|
||||
"ps":"轻量级,占有内存少,并发能力强",
|
||||
"shell":"install.sh",
|
||||
"checks":"server/openresty",
|
||||
"path":"server/openresty",
|
||||
"author":"agentzh",
|
||||
"home":"http://openresty.org",
|
||||
"date":"2017-11-24",
|
||||
"pid": "1",
|
||||
"versions": ["1.11.2", "1.13.6"],
|
||||
"updates": ["1.11.2.5", "1.13.6.2"]
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#! /bin/sh
|
||||
# chkconfig: 2345 55 25
|
||||
# Description: Startup script for nginx webserver on Debian. Place in /etc/init.d and
|
||||
# run 'update-rc.d -f nginx defaults', or use the appropriate command on your
|
||||
# distro. For CentOS/Redhat run: 'chkconfig --add nginx'
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: nginx
|
||||
# Required-Start: $all
|
||||
# Required-Stop: $all
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: starts the nginx web server
|
||||
# Description: starts nginx using start-stop-daemon
|
||||
### END INIT INFO
|
||||
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
NAME=nginx
|
||||
NGINX_BIN={$SERVER_PATH}/openresty/bin/openresty
|
||||
CONFIGFILE={$SERVER_PATH}/openresty/nginx/conf/$NAME.conf
|
||||
PIDFILE={$SERVER_PATH}/openresty/nginx/logs/$NAME.pid
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting $NAME... "
|
||||
if [ -f $PIDFILE ];then
|
||||
mPID=`cat $PIDFILE`
|
||||
isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
|
||||
if [ "$isStart" != '' ];then
|
||||
echo "$NAME (pid `pidof $NAME`) already running."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
$NGINX_BIN -c $CONFIGFILE
|
||||
|
||||
if [ "$?" != 0 ] ; then
|
||||
echo " failed"
|
||||
exit 1
|
||||
else
|
||||
echo " done"
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
echo -n "Stoping $NAME... "
|
||||
if [ -f $PIDFILE ];then
|
||||
mPID=`cat $PIDFILE`
|
||||
isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
|
||||
if [ "$isStart" = '' ];then
|
||||
echo "$NAME is not running."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "$NAME is not running."
|
||||
exit 1
|
||||
fi
|
||||
$NGINX_BIN -s stop
|
||||
|
||||
if [ "$?" != 0 ] ; then
|
||||
echo " failed. Use force-quit"
|
||||
exit 1
|
||||
else
|
||||
echo " done"
|
||||
fi
|
||||
;;
|
||||
|
||||
status)
|
||||
if [ -f $PIDFILE ];then
|
||||
mPID=`cat $PIDFILE`
|
||||
isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
|
||||
if [ "$isStart" != '' ];then
|
||||
echo "$NAME (pid `pidof $NAME`) already running."
|
||||
exit 1
|
||||
else
|
||||
echo "$NAME is stopped"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
echo "$NAME is stopped"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
|
||||
reload)
|
||||
echo -n "Reload service $NAME... "
|
||||
if [ -f $PIDFILE ];then
|
||||
mPID=`cat $PIDFILE`
|
||||
isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
|
||||
if [ "$isStart" != '' ];then
|
||||
$NGINX_BIN -s reload
|
||||
echo " done"
|
||||
else
|
||||
echo "$NAME is not running, can't reload."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "$NAME is not running, can't reload."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
configtest)
|
||||
echo -n "Test $NAME configure files... "
|
||||
$NGINX_BIN -t
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|reload|status|configtest}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/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")
|
||||
|
||||
|
||||
action=$1
|
||||
type=$2
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
echo '缺少安装脚本...' > $install_tmp
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -d $curPath/versions/$2 ];then
|
||||
echo '缺少安装脚本2...' > $install_tmp
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sh -x $curPath/versions/$2/install.sh $1
|
||||
@@ -0,0 +1,375 @@
|
||||
orPluginService('openresty');
|
||||
|
||||
|
||||
function orPost(method, args, callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'openresty', func:method, args:JSON.stringify(args)}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
function orPluginService(_name, version){
|
||||
var data = {name:_name, func:'status'}
|
||||
if ( typeof(version) != 'undefined' ){
|
||||
data['version'] = version;
|
||||
} else {
|
||||
version = '';
|
||||
}
|
||||
|
||||
orPost('status', data, function(data){
|
||||
if (data.data == 'start'){
|
||||
orPluginSetService(_name, true, version);
|
||||
} else {
|
||||
orPluginSetService(_name, false, version);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function orPluginSetService(_name ,status, version){
|
||||
var serviceCon ='<p class="status">当前状态:<span>'+(status ? '开启' : '关闭' )+
|
||||
'</span><span style="color: '+
|
||||
(status?'#20a53a;':'red;')+
|
||||
' margin-left: 3px;" class="glyphicon ' + (status?'glyphicon glyphicon-play':'glyphicon-pause')+'"></span></p><div class="sfm-opt">\
|
||||
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\''+(status?'stop':'start')+'\',\''+version+'\')">'+(status?'停止':'启动')+'</button>\
|
||||
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'restart\',\''+version+'\')">重启</button>\
|
||||
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'reload\',\''+version+'\')">重载配置</button>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(serviceCon);
|
||||
}
|
||||
|
||||
|
||||
function orPluginOpService(a, b, v) {
|
||||
|
||||
var c = "name=" + a + "&func=" + b;
|
||||
if(v != ''){
|
||||
c = c + '&version='+v;
|
||||
}
|
||||
|
||||
var d = "";
|
||||
|
||||
switch(b) {
|
||||
case "stop":d = '停止';break;
|
||||
case "start":d = '启动';break;
|
||||
case "restart":d = '重启';break;
|
||||
case "reload":d = '重载';break;
|
||||
}
|
||||
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 2}, function() {
|
||||
orPost('get_os',{},function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (!rdata['auth']){
|
||||
layer.prompt({title: '检查到权限不足,需要输入密码!', formType: 1},function(pwd, index){
|
||||
|
||||
layer.close(index);
|
||||
var data = {'pwd':pwd};
|
||||
c += '&args='+JSON.stringify(data);
|
||||
orPluginOpServiceOp(a,b,c,d,a,v);
|
||||
});
|
||||
} else {
|
||||
orPluginOpServiceOp(a,b,c,d,a,v);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function orPluginOpServiceOp(a,b,c,d,a,v){
|
||||
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0});
|
||||
$.post("/plugins/run", c, function(g) {
|
||||
layer.close(e);
|
||||
|
||||
var f = g.data == 'ok' ? msgTpl('{1}{2}服务已{3}',[a,v,d]) : msgTpl('{1}{2}服务{3}失败!',[a,v,d]);
|
||||
layer.msg(f, {icon: g.data == 'ok' ? 1 : 2});
|
||||
|
||||
if( b != "reload" && g.data == 'ok' ) {
|
||||
if ( b == 'start' ) {
|
||||
orPluginSetService(a, true, v);
|
||||
} else if ( b == 'stop' ){
|
||||
orPluginSetService(a, false, v);
|
||||
}
|
||||
}
|
||||
|
||||
if( g.status && g.data != 'ok' ) {
|
||||
layer.msg(g.data, {icon: 2,time: 3000,shade: 0.3,shadeClose: true});
|
||||
}
|
||||
},'json').error(function() {
|
||||
layer.close(e);
|
||||
layer.msg('操作异常!', {icon: 2});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//查看Nginx负载状态
|
||||
function getOpenrestyStatus() {
|
||||
$.post('/plugins/run', {name:'openresty', func:'run_info'}, function(data) {
|
||||
if (!data.status){
|
||||
showMsg(data.msg, function(){}, null,3000);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var con = "<div><table class='table table-hover table-bordered'>\
|
||||
<tr><th>活动连接(Active connections)</th><td>" + rdata.active + "</td></tr>\
|
||||
<tr><th>总连接次数(accepts)</th><td>" + rdata.accepts + "</td></tr>\
|
||||
<tr><th>总握手次数(handled)</th><td>" + rdata.handled + "</td></tr>\
|
||||
<tr><th>总请求数(requests)</th><td>" + rdata.requests + "</td></tr>\
|
||||
<tr><th>请求数(Reading)</th><td>" + rdata.Reading + "</td></tr>\
|
||||
<tr><th>响应数(Writing)</th><td>" + rdata.Writing + "</td></tr>\
|
||||
<tr><th>驻留进程(Waiting)</th><td>" + rdata.Waiting + "</td></tr>\
|
||||
</table></div>";
|
||||
$(".soft-man-con").html(con);
|
||||
}catch(err){
|
||||
showMsg(data.data, function(){}, null,3000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
//nginx
|
||||
function nginxSoftMain(name, version) {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.get('/system?action=GetConcifInfo', function(rdata) {
|
||||
layer.close(loadT);
|
||||
nameA = rdata['web'];
|
||||
var status = name == 'nginx' ? '<p onclick="GetNginxStatus()">' + lan.soft.nginx_status + '</p>' : '';
|
||||
var menu = '';
|
||||
if (version != undefined || version != '') {
|
||||
var menu = '<p onclick="softChangeVer(\'' + name + '\',\'' + version + '\')">' + lan.soft.nginx_version + '</p>';
|
||||
}
|
||||
|
||||
var waf = ''
|
||||
if (name == 'nginx') {
|
||||
waf = '<p onclick="waf()">' + lan.soft.waf_title + '</p>'
|
||||
}
|
||||
|
||||
var logsPath = (name == 'nginx') ? '/www/wwwlogs/nginx_error.log' : '/www/wwwlogs/error_log';
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: '640px',
|
||||
title: name + lan.soft.admin,
|
||||
closeBtn: 2,
|
||||
shift: 0,
|
||||
content: '<div class="bt-w-main" style="width:640px;">\
|
||||
<div class="bt-w-menu">\
|
||||
<p class="bgw" onclick="service(\'' + name + '\',' + nameA.status + ')">' + lan.soft.web_service + '</p>\
|
||||
<p onclick="configChange(\'' + name + '\')">' + lan.soft.config_edit + '</p>\
|
||||
' + waf + '\
|
||||
' + menu + '\
|
||||
' + status + '\
|
||||
<p onclick="showLogs(\'' + logsPath + '\')">错误日志</p>\
|
||||
</div>\
|
||||
<div id="webEdit-con" class="bt-w-con pd15" style="height:555px;overflow:auto">\
|
||||
<div class="soft-man-con"></div>\
|
||||
</div>\
|
||||
</div>'
|
||||
});
|
||||
service(name, nameA.status);
|
||||
$(".bt-w-menu p").click(function() {
|
||||
//var i = $(this).index();
|
||||
$(this).addClass("bgw").siblings().removeClass("bgw");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//显示指定日志
|
||||
function showLogs(logPath) {
|
||||
var loadT = layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/ajax?action=GetOpeLogs', { path: logPath }, function(rdata) {
|
||||
layer.close(loadT);
|
||||
if (rdata.msg == '') rdata.msg = '当前没有日志!';
|
||||
var ebody = '<div class="soft-man-con"><textarea readonly="" style="margin: 0px;width: 500px;height: 520px;background-color: #333;color:#fff; padding:0 5px" id="error_log">' + rdata.msg + '</textarea></div>';
|
||||
$(".soft-man-con").html(ebody);
|
||||
var ob = document.getElementById('error_log');
|
||||
ob.scrollTop = ob.scrollHeight;
|
||||
});
|
||||
}
|
||||
|
||||
//WAF防火墙
|
||||
function waf() {
|
||||
var loadT = layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.get("/waf?action=GetConfig", function(rdata) {
|
||||
layer.close(loadT);
|
||||
if (rdata.status == -1) {
|
||||
layer.msg(lan.soft.waf_not, { icon: 5, time: 5000 });
|
||||
return;
|
||||
}
|
||||
|
||||
var whiteList = ""
|
||||
for (var i = 0; i < rdata.ipWhitelist.length; i++) {
|
||||
if (rdata.ipWhitelist[i] == "") continue;
|
||||
whiteList += "<tr><td>" + rdata.ipWhitelist[i] + "</td><td><a href=\"javascript:deleteWafKey('ipWhitelist','" + rdata.ipWhitelist[i] + "');\">" + lan.public.del + "</a></td></tr>";
|
||||
}
|
||||
|
||||
var blackList = ""
|
||||
for (var i = 0; i < rdata.ipBlocklist.length; i++) {
|
||||
if (rdata.ipBlocklist[i] == "") continue;
|
||||
blackList += "<tr><td>" + rdata.ipBlocklist[i] + "</td><td><a href=\"javascript:deleteWafKey('ipBlocklist','" + rdata.ipBlocklist[i] + "');\">" + lan.public.del + "</a></td></tr>";
|
||||
}
|
||||
|
||||
var cc = rdata.CCrate.split('/')
|
||||
|
||||
var con = "<div class='wafConf'>\
|
||||
<div class='wafConf-btn'>\
|
||||
<span>" + lan.soft.waf_title + "</span><div class='ssh-item'>\
|
||||
<input class='btswitch btswitch-ios' id='closeWaf' type='checkbox' " + (rdata.status == 1 ? 'checked' : '') + ">\
|
||||
<label class='btswitch-btn' for='closeWaf' onclick='CloseWaf()'></label>\
|
||||
</div>\
|
||||
<div class='pull-right'>\
|
||||
<button class='btn btn-default btn-sm' onclick='gzEdit()'>" + lan.soft.waf_edit + "</button>\
|
||||
<button class='btn btn-default btn-sm' onclick='upLimit()'>" + lan.soft.waf_up_title + "</button>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class='wafConf_checkbox label-input-group ptb10 relative'>\
|
||||
<input type='checkbox' id='waf_UrlDeny' " + (rdata['UrlDeny'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('UrlDeny','" + (rdata['UrlDeny'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_UrlDeny'>" + lan.soft.waf_input1 + "</label>\
|
||||
<input type='checkbox' id='waf_CookieMatch' " + (rdata['CookieMatch'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('CookieMatch','" + (rdata['CookieMatch'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_CookieMatch'>" + lan.soft.waf_input2 + "</label>\
|
||||
<input type='checkbox' id='waf_postMatch' " + (rdata['postMatch'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('postMatch','" + (rdata['postMatch'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_postMatch'>" + lan.soft.waf_input3 + "</label>\
|
||||
<input type='checkbox' id='waf_CCDeny' " + (rdata['CCDeny'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('CCDeny','" + (rdata['CCDeny'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_CCDeny'>" + lan.soft.waf_input4 + "</label>\
|
||||
<input type='checkbox' id='waf_attacklog' " + (rdata['attacklog'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('attacklog','" + (rdata['attacklog'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_attacklog'>" + lan.soft.waf_input5 + "</label>\
|
||||
<span class='glyphicon glyphicon-folder-open' style='position: absolute; right: 10px; top: 12px; color: orange;cursor: pointer' onclick='openPath(\"/www/wwwlogs/waf\")'></span>\
|
||||
</div>\
|
||||
<div class='wafConf_cc'>\
|
||||
<span>" + lan.soft.waf_input6 + "</span><input id='CCrate_1' class='bt-input-text' type='number' value='" + cc[0] + "' style='width:80px;margin-right:30px'/>\
|
||||
<span>" + lan.soft.waf_input7 + "(" + lan.bt.s + ")</span><input id='CCrate_2' class='bt-input-text' type='number' value='" + cc[1] + "' style='width:80px;'/>\
|
||||
<button onclick=\"SetWafConfig('CCrate','')\" class='btn btn-default btn-sm'>" + lan.public.ok + "</button>\
|
||||
</div>\
|
||||
<div class='wafConf_ip'>\
|
||||
<fieldset>\
|
||||
<legend>" + lan.soft.waf_input8 + "</legend>\
|
||||
<input type='text' id='ipWhitelist_val' class='bt-input-text mr5' placeholder='" + lan.soft.waf_ip + "' style='width:175px;' /><button onclick=\"addWafKey('ipWhitelist')\" class='btn btn-default btn-sm'>" + lan.public.add + "</button>\
|
||||
<div class='table-overflow'><table class='table table-hover'>" + whiteList + "</table></div>\
|
||||
</fieldset>\
|
||||
<fieldset>\
|
||||
<legend>" + lan.soft.waf_input9 + "</legend>\
|
||||
<input type='text' id='ipBlocklist_val' class='bt-input-text mr5' placeholder='" + lan.soft.waf_ip + "' style='width:175px;' /><button onclick=\"addWafKey('ipBlocklist')\" class='btn btn-default btn-sm'>" + lan.public.add + "</button>\
|
||||
<div class='table-overflow'><table class='table table-hover'>" + blackList + "</table></div>\
|
||||
</fieldset>\
|
||||
</div>\
|
||||
</div>"
|
||||
$(".soft-man-con").html(con);
|
||||
});
|
||||
}
|
||||
|
||||
//上传限制
|
||||
function upLimit() {
|
||||
var loadT = layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.get("/waf?action=GetConfig", function(rdata) {
|
||||
layer.close(loadT);
|
||||
var black_fileExt = ''
|
||||
for (var i = 0; i < rdata.black_fileExt.length; i++) {
|
||||
black_fileExt += "<tr><td>" + rdata.black_fileExt[i] + "</td><td><a style='float:right;' href=\"javascript:deleteWafKey('black_fileExt','" + rdata.black_fileExt[i] + "');\">" + lan.public.del + "</a></td></tr>";
|
||||
}
|
||||
|
||||
if ($("#blacktable").html() != undefined) {
|
||||
$("#blacktable").html(black_fileExt);
|
||||
$("#black_fileExt_val").val('');
|
||||
return;
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: '300px',
|
||||
title: lan.soft.waf_up_title,
|
||||
closeBtn: 2,
|
||||
shift: 0,
|
||||
content: "<div class='dirBinding mlr15'>" +
|
||||
"<input class='bt-input-text mr5' type='text' placeholder='" + lan.soft.waf_up_from1 + "' id='black_fileExt_val' style='height: 28px; border-radius: 3px;width: 219px;margin-top:15px' />" +
|
||||
"<button class='btn btn-success btn-sm' onclick=\"addWafKey('black_fileExt')\">" + lan.public.add + "</button>" +
|
||||
"</div>" +
|
||||
"<div class='divtable' style='margin:15px'><table class='table table-hover' width='100%' style='margin-bottom:0'>" +
|
||||
"<thead><tr><th>" + lan.soft.waf_up_from2 + "</th><th width='100' class='text-right'>" + lan.public.action + "</th></tr></thead>" +
|
||||
"<tbody id='blacktable'>" + black_fileExt + "</tbody>" +
|
||||
"</table></div>"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//设置waf状态
|
||||
function closeWaf() {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/waf?action=SetStatus', '', function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
if (rdata.status) waf();
|
||||
});
|
||||
}
|
||||
|
||||
//取规则文件
|
||||
function getWafFile(name) {
|
||||
onlineEditFile(0, '/www/server/panel/vhost/wafconf/' + name);
|
||||
}
|
||||
//规则编辑
|
||||
function gzEdit() {
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: '360px',
|
||||
title: lan.soft.waf_edit,
|
||||
closeBtn: 2,
|
||||
shift: 0,
|
||||
content: "<div class='gzEdit'><button class='btn btn-default btn-sm' onclick=\"GetWafFile('cookie')\">Cookie</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('post')\">POST</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('url')\">URL</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('user-agent')\">User-Agent</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('args')\">Args</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('whiteurl')\">" + lan.soft.waf_url_white + "</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('returnhtml')\">" + lan.soft.waf_index + "</button>\
|
||||
<button class='btn btn-default btn-sm' onclick=\"updateWaf('returnhtml')\">" + lan.soft.waf_cloud + "</button></div>"
|
||||
});
|
||||
}
|
||||
|
||||
//更新WAF规则
|
||||
function updateWaf() {
|
||||
var loadT = layer.msg(lan.soft.waf_update, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/waf?action=updateWaf', '', function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
});
|
||||
}
|
||||
|
||||
//设置WAF配置值
|
||||
function setWafConfig(name, value) {
|
||||
if (name == 'CCrate') {
|
||||
var CCrate_1 = $("#CCrate_1").val();
|
||||
var CCrate_2 = $("#CCrate_2").val();
|
||||
if (CCrate_1 < 1 || CCrate_1 > 3000 || CCrate_2 < 1 || CCrate_2 > 1800) {
|
||||
layer.msg(lan.soft.waf_cc_err, { icon: 5 });
|
||||
return;
|
||||
}
|
||||
value = CCrate_1 + '/' + CCrate_2;
|
||||
}
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/waf?action=SetConfigString', 'name=' + name + '&value=' + value, function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
if (rdata.status) waf();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//删除WAF指定值
|
||||
function deleteWafKey(name, value) {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/waf?action=SetConfigList&act=del', 'name=' + name + '&value=' + value, function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
if (rdata.status) waf();
|
||||
if (name == 'black_fileExt') upLimit();
|
||||
});
|
||||
}
|
||||
|
||||
//删除WAF指定值
|
||||
function addWafKey(name) {
|
||||
var value = $('#' + name + '_val').val();
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/waf?action=SetConfigList&act=add', 'name=' + name + '&value=' + value, function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
|
||||
if (rdata.status) waf();
|
||||
if (name == 'black_fileExt') upLimit();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
openrestyDir=${serverPath}/source/openresty
|
||||
|
||||
Install_openresty()
|
||||
{
|
||||
mkdir -p ${openrestyDir}
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
|
||||
if [ ! -f ${openrestyDir}/openresty-1.11.2.5.tar.gz ];then
|
||||
wget -O ${openrestyDir}/openresty-1.11.2.5.tar.gz https://openresty.org/download/openresty-1.11.2.5.tar.gz
|
||||
fi
|
||||
|
||||
|
||||
cd ${openrestyDir} && tar -zxvf openresty-1.11.2.5.tar.gz
|
||||
|
||||
cd ${openrestyDir}/openresty-1.11.2.5 && ./configure --prefix=$serverPath/openresty \
|
||||
--with-openssl=$serverPath/source/lib/openssl-1.0.2q \
|
||||
--with-http_stub_status_module && make && make install && \
|
||||
echo '1.11.2' > $serverPath/openresty/version.pl
|
||||
|
||||
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_openresty()
|
||||
{
|
||||
rm -rf $serverPath/openresty
|
||||
echo '卸载完成' > $install_tmp
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_openresty
|
||||
else
|
||||
Uninstall_openresty
|
||||
fi
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/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")
|
||||
|
||||
install_tmp=${rootPath}/tmp/bt_install.pl
|
||||
|
||||
openrestyDir=${serverPath}/source/openresty
|
||||
|
||||
Install_openresty()
|
||||
{
|
||||
mkdir -p ${openrestyDir}
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
|
||||
if [ ! -f ${openrestyDir}/openresty-1.13.6.2.tar.gz ];then
|
||||
wget -O ${openrestyDir}/openresty-1.13.6.2.tar.gz https://openresty.org/download/openresty-1.13.6.2.tar.gz
|
||||
fi
|
||||
|
||||
cd ${openrestyDir} && tar -zxvf openresty-1.13.6.2.tar.gz
|
||||
|
||||
cd ${openrestyDir}/openresty-1.13.6.2 && ./configure --prefix=$serverPath/openresty \
|
||||
--with-openssl=$serverPath/source/lib/openssl-1.0.2q \
|
||||
--with-http_stub_status_module \
|
||||
&& make && make install && \
|
||||
echo '1.13.6' > $serverPath/openresty/version.pl
|
||||
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_openresty()
|
||||
{
|
||||
rm -rf $serverPath/openresty
|
||||
echo '卸载完成' > $install_tmp
|
||||
}
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_openresty
|
||||
else
|
||||
Uninstall_openresty
|
||||
fi
|
||||
@@ -0,0 +1,8 @@
|
||||
location ~ [^/]\.php(/|$)
|
||||
{
|
||||
try_files $uri =404;
|
||||
fastcgi_pass unix:/tmp/php-cgi-{$PHP_VERSION}.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi.conf;
|
||||
include pathinfo.conf;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
set $real_script_name $fastcgi_script_name;
|
||||
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
|
||||
set $real_script_name $1;
|
||||
set $path_info $2;
|
||||
}
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
|
||||
fastcgi_param SCRIPT_NAME $real_script_name;
|
||||
fastcgi_param PATH_INFO $path_info;
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
[global]
|
||||
include={$SERVER_PATH}/php/{$PHP_VERSION}/etc/php-fpm.d/*.conf
|
||||
;php_value[auto_prepend_file]={$SERVER_PATH}/md_start.php
|
||||
;php_value[auto_append_file]={$SERVER_PATH}/md_end.php
|
||||
@@ -0,0 +1,237 @@
|
||||
[PHP]
|
||||
engine = On
|
||||
short_open_tag = On
|
||||
asp_tags = Off
|
||||
precision = 14
|
||||
output_buffering = 4096
|
||||
zlib.output_compression = Off
|
||||
implicit_flush = Off
|
||||
unserialize_callback_func =
|
||||
serialize_precision = 17
|
||||
zend.enable_gc = On
|
||||
expose_php = On
|
||||
max_execution_time = 30
|
||||
max_input_time = 60
|
||||
memory_limit = 128M
|
||||
error_reporting = E_ALL
|
||||
display_errors = On
|
||||
display_startup_errors = On
|
||||
log_errors = On
|
||||
log_errors_max_len = 1024
|
||||
ignore_repeated_errors = Off
|
||||
ignore_repeated_source = Off
|
||||
report_memleaks = On
|
||||
track_errors = On
|
||||
html_errors = On
|
||||
variables_order = "GPCS"
|
||||
request_order = "GP"
|
||||
register_argc_argv = Off
|
||||
auto_globals_jit = On
|
||||
post_max_size = 8M
|
||||
auto_prepend_file =
|
||||
auto_append_file =
|
||||
default_mimetype = "text/html"
|
||||
doc_root =
|
||||
user_dir =
|
||||
enable_dl = Off
|
||||
|
||||
|
||||
file_uploads = On
|
||||
upload_tmp_dir = "/tmp"
|
||||
upload_max_filesize = 2M
|
||||
max_file_uploads = 20
|
||||
|
||||
allow_url_fopen = On
|
||||
allow_url_include = Off
|
||||
default_socket_timeout = 60
|
||||
|
||||
disable_functions = phpinfo,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
|
||||
|
||||
[CLI Server]
|
||||
cli_server.color = On
|
||||
|
||||
[Date]
|
||||
date.timezone = PRC
|
||||
|
||||
[filter]
|
||||
[iconv]
|
||||
iconv.input_encoding = ISO-8859-1
|
||||
iconv.internal_encoding = ISO-8859-1
|
||||
iconv.output_encoding = ISO-8859-1
|
||||
|
||||
[intl]
|
||||
[sqlite]
|
||||
[sqlite3]
|
||||
[Pcre]
|
||||
[Pdo]
|
||||
|
||||
|
||||
[Pdo_mysql]
|
||||
pdo_mysql.cache_size = 2000
|
||||
pdo_mysql.default_socket=
|
||||
|
||||
[Phar]
|
||||
|
||||
[mail function]
|
||||
SMTP = localhost
|
||||
smtp_port = 25
|
||||
mail.add_x_header = On
|
||||
|
||||
|
||||
[SQL]
|
||||
sql.safe_mode = Off
|
||||
|
||||
[ODBC]
|
||||
odbc.allow_persistent = On
|
||||
odbc.check_persistent = On
|
||||
odbc.max_persistent = -1
|
||||
odbc.max_links = -1
|
||||
odbc.defaultlrl = 4096
|
||||
odbc.defaultbinmode = 1
|
||||
|
||||
|
||||
[Interbase]
|
||||
ibase.allow_persistent = 1
|
||||
ibase.max_persistent = -1
|
||||
ibase.max_links = -1
|
||||
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
|
||||
ibase.dateformat = "%Y-%m-%d"
|
||||
ibase.timeformat = "%H:%M:%S"
|
||||
|
||||
[MySQL]
|
||||
mysql.allow_local_infile = On
|
||||
mysql.allow_persistent = On
|
||||
mysql.cache_size = 2000
|
||||
mysql.max_persistent = -1
|
||||
mysql.max_links = -1
|
||||
mysql.default_port =
|
||||
mysql.default_socket =
|
||||
mysql.default_host =
|
||||
mysql.default_user =
|
||||
mysql.default_password =
|
||||
mysql.connect_timeout = 60
|
||||
mysql.trace_mode = Off
|
||||
|
||||
[MySQLi]
|
||||
mysqli.max_persistent = -1
|
||||
mysqli.allow_persistent = On
|
||||
mysqli.max_links = -1
|
||||
mysqli.cache_size = 2000
|
||||
mysqli.default_port = 3306
|
||||
mysqli.default_socket =
|
||||
mysqli.default_host =
|
||||
mysqli.default_user =
|
||||
mysqli.default_pw =
|
||||
mysqli.reconnect = Off
|
||||
|
||||
[mysqlnd]
|
||||
mysqlnd.collect_statistics = On
|
||||
mysqlnd.collect_memory_statistics = On
|
||||
|
||||
[OCI8]
|
||||
|
||||
|
||||
[PostgreSQL]
|
||||
pgsql.allow_persistent = On
|
||||
pgsql.auto_reset_persistent = Off
|
||||
pgsql.max_persistent = -1
|
||||
pgsql.max_links = -1
|
||||
pgsql.ignore_notice = 0
|
||||
pgsql.log_notice = 0
|
||||
|
||||
[Sybase-CT]
|
||||
sybct.allow_persistent = On
|
||||
sybct.max_persistent = -1
|
||||
sybct.max_links = -1
|
||||
sybct.min_server_severity = 10
|
||||
sybct.min_client_severity = 10
|
||||
|
||||
|
||||
[bcmath]
|
||||
bcmath.scale = 0
|
||||
|
||||
[browscap]
|
||||
|
||||
[Session]
|
||||
session.save_handler = files
|
||||
session.save_path = "MD:/bin/tmp/session"
|
||||
session.use_strict_mode = 0
|
||||
session.use_cookies = 1
|
||||
session.use_only_cookies = 1
|
||||
session.name = PHPSESSID
|
||||
session.auto_start = 0
|
||||
session.cookie_lifetime = 0
|
||||
session.cookie_path = /
|
||||
session.cookie_domain =
|
||||
session.cookie_httponly =
|
||||
session.serialize_handler = php
|
||||
session.gc_probability = 1
|
||||
session.gc_divisor = 1000
|
||||
session.gc_maxlifetime = 1440
|
||||
session.referer_check =
|
||||
session.cache_limiter = nocache
|
||||
session.cache_expire = 180
|
||||
session.use_trans_sid = 0
|
||||
session.hash_function = 0
|
||||
session.hash_bits_per_character = 5
|
||||
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
|
||||
|
||||
|
||||
[MSSQL]
|
||||
mssql.allow_persistent = On
|
||||
mssql.max_persistent = -1
|
||||
mssql.max_links = -1
|
||||
mssql.min_error_severity = 10
|
||||
mssql.min_message_severity = 10
|
||||
mssql.compatibility_mode = Off
|
||||
mssql.secure_connection = Off
|
||||
|
||||
[Assertion]
|
||||
[COM]
|
||||
[mbstring]
|
||||
[gd]
|
||||
[exif]
|
||||
[Tidy]
|
||||
|
||||
tidy.clean_output = Off
|
||||
|
||||
[soap]
|
||||
soap.wsdl_cache_enabled=1
|
||||
soap.wsdl_cache_dir="/tmp"
|
||||
soap.wsdl_cache_ttl=86400
|
||||
soap.wsdl_cache_limit = 5
|
||||
|
||||
[sysvshm]
|
||||
|
||||
[ldap]
|
||||
ldap.max_links = -1
|
||||
|
||||
[mcrypt]
|
||||
|
||||
|
||||
[dba]
|
||||
[curl]
|
||||
[Zend Opcache]
|
||||
|
||||
;[xhprof]
|
||||
;extension=md_xhprof.so
|
||||
;xhprof.output_dir="MD:/bin/tmp/xhprof"
|
||||
|
||||
|
||||
;extension=igbinary.so
|
||||
;extension=iconv.so
|
||||
;extension=yaf.so
|
||||
;extension=swoole.so
|
||||
;extension=curl.so
|
||||
;extension=bcmath.so
|
||||
;extension=mcrypt.so
|
||||
;extension=gd.so
|
||||
;extension=openssl.so
|
||||
;extension=intl.so
|
||||
;extension=gettext.so
|
||||
;extension=imagick.so
|
||||
;extension=redis.so
|
||||
;extension=mongodb.so
|
||||
;extension=memcached.so
|
||||
;extension=phalcon.so
|
||||
;extension=opencv.so
|
||||