Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6451d1caa1 | ||
|
|
ca8d2ac405 | ||
|
|
9f9922abdd | ||
|
|
9ec0987cfa | ||
|
|
c21ad861af | ||
|
|
eac65528c7 | ||
|
|
291071a3a3 | ||
|
|
c454f7ddbe | ||
|
|
9e6a95460b | ||
|
|
5a4b06f12e | ||
|
|
9def3d0854 | ||
|
|
2183c74aa2 | ||
|
|
3ffe6102e8 | ||
|
|
cb21fc08e4 | ||
|
|
ccd819d18a | ||
|
|
532f458993 | ||
|
|
abc74b3e3b | ||
|
|
1d6664f01a | ||
|
|
c5f11d6819 | ||
|
|
495a46deec | ||
|
|
7863a7b50d | ||
|
|
cb4a4d0568 | ||
|
|
639ee1c0ba | ||
|
|
1a380c2745 | ||
|
|
4b4164f146 | ||
|
|
728add52d1 | ||
|
|
2b694bee35 | ||
|
|
9f4e4b8541 | ||
|
|
736ceeb730 | ||
|
|
b95804587c | ||
|
|
77af5fcf7f | ||
|
|
2c2aed7d18 | ||
|
|
ff543284cc | ||
|
|
835fea0ad6 | ||
|
|
8bbdcdb095 | ||
|
|
1e8c6ea498 | ||
|
|
da17e7782e | ||
|
|
11c9a9d736 | ||
|
|
b77c5ce39a | ||
|
|
795322d77a | ||
|
|
78168a1df0 | ||
|
|
12b99b7c87 | ||
|
|
7976c16965 | ||
|
|
31de75f3ff | ||
|
|
45d14c4ad4 | ||
|
|
fc6ce6c614 | ||
|
|
b2b0716a48 | ||
|
|
0ce33bb170 | ||
|
|
e8fb2a231a | ||
|
|
9bafcaef7c | ||
|
|
6cf91549be | ||
|
|
80c9cafae1 | ||
|
|
6487cbae09 | ||
|
|
2f1b080870 | ||
|
|
cef24d3084 | ||
|
|
ca03199583 | ||
|
|
4170b790bf | ||
|
|
97f9391c41 | ||
|
|
5f704ec742 | ||
|
|
1ea7632b38 | ||
|
|
61853ee530 | ||
|
|
3d82092e1a | ||
|
|
0ba8620966 | ||
|
|
d657d7a322 | ||
|
|
95a9bc8d5f | ||
|
|
1bfc2e9c1c | ||
|
|
a81b16a27a | ||
|
|
3d67694786 | ||
|
|
22b65e3bba | ||
|
|
3874cbee86 | ||
|
|
990f52dd81 | ||
|
|
9f0be85a9f | ||
|
|
4ae442ae4c | ||
|
|
d0514fdca1 | ||
|
|
093ceae9d4 | ||
|
|
cfb6fb07ac | ||
|
|
ea3ece1639 | ||
|
|
ef4d35cee7 | ||
|
|
d6e79d057a | ||
|
|
17022f2fcb | ||
|
|
b4a371f1a1 | ||
|
|
831bb240d1 | ||
|
|
b3ea4a8307 | ||
|
|
5f607ded95 | ||
|
|
cc01156b8c | ||
|
|
b208a5d751 | ||
|
|
72c31b8aaf | ||
|
|
5bd6f43b2a | ||
|
|
e8f0cc5003 | ||
|
|
34d17289cc | ||
|
|
30bc6f27ec | ||
|
|
77a36e6cfd | ||
|
|
2ff70a2c32 | ||
|
|
782389972b | ||
|
|
60fd8d306b | ||
|
|
e341272547 | ||
|
|
a28e9e2dbf | ||
|
|
1041f64c93 | ||
|
|
7c6d13473f | ||
|
|
cd38c261b7 | ||
|
|
091f5f3fbb | ||
|
|
212798426b | ||
|
|
29fa997ad2 | ||
|
|
c36cf7d83e | ||
|
|
8b6bdd25d9 | ||
|
|
f7b3fbc249 | ||
|
|
baf091d8c3 | ||
|
|
6831c00c2a | ||
|
|
4050d9697b | ||
|
|
9872bf5e61 | ||
|
|
24f8a551d8 | ||
|
|
7dcc584c87 | ||
|
|
7a94dd9ad9 | ||
|
|
643f4f177c | ||
|
|
b2a1530b01 | ||
|
|
7753e7a7c1 | ||
|
|
19a9bf6554 | ||
|
|
477c48080b | ||
|
|
332324d218 | ||
|
|
f6928c1784 | ||
|
|
dd7b2c30a2 | ||
|
|
763744b4a5 | ||
|
|
8e3202b354 | ||
|
|
2a148c9309 | ||
|
|
159c4d57b3 | ||
|
|
aee172170e | ||
|
|
845fc8104a | ||
|
|
ef91abab77 | ||
|
|
ea295d1e0a | ||
|
|
ed83c1da60 | ||
|
|
752b400c6c | ||
|
|
6fb2e94e05 | ||
|
|
8cf1cfad59 | ||
|
|
8eb7e20654 | ||
|
|
a62fe19491 | ||
|
|
77ebd5bc36 | ||
|
|
49873a5249 | ||
|
|
6c90f2a7c3 | ||
|
|
13061a3808 | ||
|
|
e3aab8c8da | ||
|
|
dab3920618 | ||
|
|
5ff24872b9 | ||
|
|
e7e0295446 | ||
|
|
97752b690e | ||
|
|
8894280ad7 | ||
|
|
4a3ac08498 | ||
|
|
497981b4fc | ||
|
|
ac6d714c01 | ||
|
|
858540a440 | ||
|
|
a9300b0e43 | ||
|
|
abc04b7995 | ||
|
|
208d892675 | ||
|
|
3b83c0538f | ||
|
|
35bd7d4cc1 | ||
|
|
6effc0ed8f | ||
|
|
d50011d1e2 | ||
|
|
3e9cbf89da | ||
|
|
f7df26a118 | ||
|
|
f5fe6ad747 | ||
|
|
c45b2d8d5f | ||
|
|
48729c39df | ||
|
|
8946d8a12f | ||
|
|
3783ab407b | ||
|
|
14f59c7ae7 | ||
|
|
a080a4f5f6 | ||
|
|
e43b66618c | ||
|
|
f2362bd7a2 | ||
|
|
e7513c7ed7 | ||
|
|
0cdc743b4f | ||
|
|
16e964ccbe | ||
|
|
d3d6feae0a | ||
|
|
31fa78c31c | ||
|
|
9cce88755e | ||
|
|
973e2fa1ac | ||
|
|
5645431d90 | ||
|
|
4c660e307a | ||
|
|
c76ed0ae97 | ||
|
|
8144de6ced | ||
|
|
328c84e78a | ||
|
|
679a10104f | ||
|
|
c9e307382d | ||
|
|
bc4d25871d | ||
|
|
d11a10e607 | ||
|
|
01cfa5a8d0 | ||
|
|
c880e935d7 | ||
|
|
4b67f348f6 | ||
|
|
2a9bfe15c0 | ||
|
|
bb8a6a3a2c | ||
|
|
d6b5a019cf | ||
|
|
d623cab022 | ||
|
|
26748bbeaa | ||
|
|
e211cc075f | ||
|
|
f52d8c0fbb | ||
|
|
22f6f04c8a | ||
|
|
bd4972e55d | ||
|
|
3318218764 | ||
|
|
fe468421f2 | ||
|
|
fee05f6af3 | ||
|
|
04c09ed101 | ||
|
|
142437ea7e | ||
|
|
bf3ddbf4a5 | ||
|
|
602ef37d88 | ||
|
|
9c860a5941 | ||
|
|
242ffd4517 | ||
|
|
6821f7a895 | ||
|
|
2bb03a71c6 | ||
|
|
433cf508e5 | ||
|
|
bdb852c8cf | ||
|
|
cf008c7ccd | ||
|
|
1f1870c5e2 | ||
|
|
aecabf7dd2 | ||
|
|
342652abe8 | ||
|
|
0bbe4f6ffc | ||
|
|
4411b4e70f | ||
|
|
b4757dfadd | ||
|
|
ed465ad8cf | ||
|
|
2896e2d9fb | ||
|
|
f6ff5c8e26 | ||
|
|
d6dfccb5bc | ||
|
|
d6007b273c | ||
|
|
b7da5f7db3 | ||
|
|
58258afe6e | ||
|
|
139b1cf03b | ||
|
|
8e3e170c6e | ||
|
|
51c50c8fc6 | ||
|
|
3513230de1 | ||
|
|
4b72cd448d | ||
|
|
7096a65591 | ||
|
|
7b36b808bd | ||
|
|
3a4467619e | ||
|
|
f928ef95f6 | ||
|
|
9cf984ed65 | ||
|
|
1f14e271c4 | ||
|
|
dddf0edb26 | ||
|
|
8ac906f11e | ||
|
|
243c1d2291 | ||
|
|
072bd93ac0 | ||
|
|
a3d2183eef | ||
|
|
71ffa35702 | ||
|
|
c28e48557d | ||
|
|
c6c88c0841 | ||
|
|
9dbc4baa25 | ||
|
|
0f7a493777 | ||
|
|
cd4c21697d | ||
|
|
e45832ea22 | ||
|
|
603323f576 | ||
|
|
421e1d5623 | ||
|
|
2492d38a1d | ||
|
|
22a023b877 | ||
|
|
b1f95fb5f2 | ||
|
|
7641d03f34 | ||
|
|
d2b9fbed4a | ||
|
|
67abcc17c5 | ||
|
|
dfdeef8f4c | ||
|
|
92e23cb018 | ||
|
|
8e9aa1489e | ||
|
|
47fc9576dc | ||
|
|
ab1ad909ad | ||
|
|
1da2a454ad | ||
|
|
33a418017a | ||
|
|
c0161572f7 | ||
|
|
ba2a061eb1 | ||
|
|
7535598be6 | ||
|
|
f98e69ede7 | ||
|
|
9d88675756 | ||
|
|
8c07db3b57 | ||
|
|
a226c3c019 | ||
|
|
8533d667cd | ||
|
|
4b1f483565 | ||
|
|
ede5bab112 | ||
|
|
be5fc96998 | ||
|
|
ffbe43b589 | ||
|
|
e2ae038fa2 | ||
|
|
f9482c43c7 | ||
|
|
b4898e32a5 | ||
|
|
0094d4e573 | ||
|
|
ffd1258d26 | ||
|
|
f46139e1f9 | ||
|
|
4eb68cbdbb | ||
|
|
5b164ee478 | ||
|
|
619bbca29d | ||
|
|
32dfc0a1ab | ||
|
|
7124f314ac | ||
|
|
526ba2cd65 | ||
|
|
9fce92c7d5 | ||
|
|
7102f809c2 | ||
|
|
cb8d396b98 | ||
|
|
7c22685f49 | ||
|
|
0ae83fe2b2 | ||
|
|
6ec4c72219 | ||
|
|
d6321dbbb7 | ||
|
|
3706c64b8f | ||
|
|
28e5787dc9 | ||
|
|
a8afc4fe88 | ||
|
|
86326de64f | ||
|
|
96d441fe5f | ||
|
|
b610e8f997 | ||
|
|
824d58e07f | ||
|
|
7d0a5713ba | ||
|
|
e59cd0d15d | ||
|
|
5975d712f8 | ||
|
|
42b25fb503 | ||
|
|
a50cf91428 | ||
|
|
db55a16503 | ||
|
|
100ac12bba | ||
|
|
682c155ada | ||
|
|
3cbb91409d | ||
|
|
a1508357ee | ||
|
|
d4742f061b | ||
|
|
669259634a | ||
|
|
0050d85b8e | ||
|
|
17b810436e | ||
|
|
7249ec56c0 | ||
|
|
537346dace | ||
|
|
d83a4fe27f | ||
|
|
56168b76fb | ||
|
|
6bcf3c5d35 | ||
|
|
edf44d09e1 | ||
|
|
31e48ffc53 | ||
|
|
030aa7b46c | ||
|
|
ea6be0b69a | ||
|
|
e172aa3a6e | ||
|
|
6d8048af2f | ||
|
|
ec3f8c0249 | ||
|
|
ddd8a32abf | ||
|
|
3b842620a0 | ||
|
|
553b2b10d9 | ||
|
|
177369585c | ||
|
|
1977fa025a | ||
|
|
13fd61f0cf | ||
|
|
7ef6cdd76c | ||
|
|
b1b1878637 | ||
|
|
17f8b47625 | ||
|
|
d7e7f5ea2d | ||
|
|
6efa3e6a35 | ||
|
|
e3e1545c9b | ||
|
|
b26737eb3c | ||
|
|
4eb430a88b | ||
|
|
bfa0add999 | ||
|
|
7f20090e8c | ||
|
|
e151f0dee1 | ||
|
|
a5184e933e | ||
|
|
819e74333e | ||
|
|
4a09c3fd95 | ||
|
|
c214c19a89 | ||
|
|
889de6769a | ||
|
|
7dfe6eb681 | ||
|
|
ef21d5f47f | ||
|
|
2d8e62417f | ||
|
|
d2750f41aa | ||
|
|
0ab7af4748 | ||
|
|
56cc3b75c3 | ||
|
|
127caf661c | ||
|
|
9bc857b000 | ||
|
|
233fa4cf60 | ||
|
|
d5b8f7f800 | ||
|
|
b595557f2c | ||
|
|
d90509e479 | ||
|
|
e1e84741f5 | ||
|
|
9169ce58de | ||
|
|
0b55595ce6 | ||
|
|
b5aeaacc69 | ||
|
|
1ed469b5f6 | ||
|
|
d900298a7b | ||
|
|
5ac1642927 | ||
|
|
d1f26a59ce | ||
|
|
7be7de2bce | ||
|
|
91c9250f74 | ||
|
|
91bd3abb74 | ||
|
|
04d6166deb | ||
|
|
c66fd7abe0 | ||
|
|
ac71de01bd | ||
|
|
d0430e7b3c | ||
|
|
0264e2edda | ||
|
|
631776c0ce | ||
|
|
008ff29e13 | ||
|
|
c66105ae96 | ||
|
|
6c2fe6c9de | ||
|
|
970cc56ea1 | ||
|
|
4a582d75df | ||
|
|
9438388877 | ||
|
|
cc39d7cb25 | ||
|
|
b7394e2f79 | ||
|
|
ab52563f3f | ||
|
|
c5c49f2ec0 | ||
|
|
a76c6af147 | ||
|
|
e71b00669e | ||
|
|
02df20fc57 | ||
|
|
cc0e4d1064 | ||
|
|
bff6b17839 | ||
|
|
9c397fff8a | ||
|
|
255f4b95a0 | ||
|
|
a9ed883407 | ||
|
|
2b446087fc | ||
|
|
6e9dc8e9e6 | ||
|
|
a08e48c139 | ||
|
|
557aabfaf8 | ||
|
|
97c02f00a0 | ||
|
|
2280d41ddd | ||
|
|
72fb2d1ecc | ||
|
|
85c88dcde0 | ||
|
|
bd9f7510d3 | ||
|
|
e39b06cf83 | ||
|
|
ed992ff1a3 | ||
|
|
f470ae037f | ||
|
|
b9f9b7c49d | ||
|
|
29b525cbee | ||
|
|
5fd8873068 | ||
|
|
7627ba6f4b | ||
|
|
e0b5956ad5 | ||
|
|
d7b09afd02 | ||
|
|
a5e146e918 | ||
|
|
666738eb56 | ||
|
|
75c3701e21 | ||
|
|
733de4a0ff | ||
|
|
aedb8bba05 | ||
|
|
003e11eda3 | ||
|
|
f44de8ec5c | ||
|
|
dea8263e98 | ||
|
|
40456846a8 | ||
|
|
99ac5f34f0 | ||
|
|
bef1c16cb5 | ||
|
|
d1282b667d | ||
|
|
222b878c79 | ||
|
|
9bd6ec598d | ||
|
|
8bff295837 | ||
|
|
f28b0c3878 | ||
|
|
58fa31352e | ||
|
|
afa2e2e773 | ||
|
|
0b7548d10f | ||
|
|
f53b4f4139 | ||
|
|
f338814f97 | ||
|
|
28f2b28a53 | ||
|
|
e0861a2a9e | ||
|
|
72e23f11a4 | ||
|
|
256be27d3a | ||
|
|
482759a0e9 | ||
|
|
0faf8036da | ||
|
|
c8289a732c | ||
|
|
a579e5b1d6 | ||
|
|
5aa714876f | ||
|
|
b75c1c1049 | ||
|
|
9c03f9d8b7 | ||
|
|
f255eb1fda | ||
|
|
f7d17302a5 | ||
|
|
161d9656a8 | ||
|
|
d76f0b22f8 | ||
|
|
96f3e36183 | ||
|
|
f13b4c73b2 | ||
|
|
aa0f53f2fb | ||
|
|
fcd3088bee | ||
|
|
889757d42e | ||
|
|
4204310442 | ||
|
|
3209837e99 | ||
|
|
7ad3aa3b21 | ||
|
|
e9ddd3bfa2 | ||
|
|
7a0042ff65 | ||
|
|
e5662b4ae7 | ||
|
|
1ac3b3ae9d | ||
|
|
29e81cfdfe | ||
|
|
a1cf9fc980 | ||
|
|
2072955c37 | ||
|
|
8cc15d0c00 | ||
|
|
aaca84e1bc | ||
|
|
906cf1a8dc | ||
|
|
b4c22268b1 | ||
|
|
157280c508 | ||
|
|
266ec5fde3 | ||
|
|
17a873b775 | ||
|
|
27294b5c35 | ||
|
|
28fcdd303f | ||
|
|
329adc2f6f | ||
|
|
5e076aee60 | ||
|
|
c95ea69f16 | ||
|
|
5a52354541 | ||
|
|
4ebf6af532 | ||
|
|
5a8e903695 | ||
|
|
667956a6b9 | ||
|
|
3834eda363 | ||
|
|
58bd54ee67 | ||
|
|
e7c228cd35 | ||
|
|
8d948ca74b | ||
|
|
16c9103549 | ||
|
|
a461c143ee | ||
|
|
a3ca576667 | ||
|
|
f2bdce2ec1 | ||
|
|
ba560eb468 | ||
|
|
dc2c87999a | ||
|
|
174cf75755 | ||
|
|
0f4a16ace6 | ||
|
|
32a2acf61b | ||
|
|
328b67bd88 | ||
|
|
0d6f9b5c5f | ||
|
|
b359a594cd | ||
|
|
8e31452c19 | ||
|
|
54ded3ae58 | ||
|
|
7a8ab1acf1 | ||
|
|
e4179b4ae5 | ||
|
|
80fb58cefe | ||
|
|
87c8b585f8 | ||
|
|
90bc1750c7 | ||
|
|
5b2839515b | ||
|
|
392ab0e8cd | ||
|
|
e1f9aeb065 | ||
|
|
7bb412a0bd | ||
|
|
f67d9e088e | ||
|
|
ee7c42481f | ||
|
|
f7a764d6a4 | ||
|
|
d8ab3c2511 | ||
|
|
a36c619f23 | ||
|
|
1280c993fd | ||
|
|
b433042a87 | ||
|
|
62cb495ee0 | ||
|
|
feb91ce0b9 | ||
|
|
48b123ae17 | ||
|
|
45374c8e65 | ||
|
|
3e9c884d83 | ||
|
|
501c35f1f6 | ||
|
|
895bf541e2 | ||
|
|
58b7cd5193 | ||
|
|
05184e5608 | ||
|
|
da05ef9b15 | ||
|
|
5ef627e490 | ||
|
|
d0e5ff7461 | ||
|
|
8b8533e820 | ||
|
|
c6d591100f | ||
|
|
cfe5463d87 | ||
|
|
8825d01455 | ||
|
|
57f2174764 | ||
|
|
cc430c30ef | ||
|
|
3d150074fb | ||
|
|
5263efbbac | ||
|
|
d26c529a3a | ||
|
|
897f3ddfe6 | ||
|
|
606fc44641 | ||
|
|
c49bed0474 | ||
|
|
c92f110893 | ||
|
|
be526ccd4e | ||
|
|
31d4fef0ee | ||
|
|
f28784db54 | ||
|
|
6ca67961fb | ||
|
|
b367c45dd6 | ||
|
|
10661e4f14 | ||
|
|
684f80bec9 | ||
|
|
5523488b4c | ||
|
|
c793e73d5d | ||
|
|
6f8bc6d012 | ||
|
|
db9fcd952c | ||
|
|
fdfd90a7e5 | ||
|
|
2c2a50f301 | ||
|
|
a96d0b7401 | ||
|
|
d8362d1341 | ||
|
|
b97a14638f | ||
|
|
3e705b02cf | ||
|
|
4df0859734 | ||
|
|
4c8022d47b | ||
|
|
21d7ab3406 | ||
|
|
9dd1c46521 | ||
|
|
438cfb6256 | ||
|
|
a2bda07cc6 |
@@ -8,7 +8,6 @@ __pycache__/
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
@@ -115,3 +114,8 @@ 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
|
||||
ssl/input.pl
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import config
|
||||
|
||||
app = config.config().makeApp(__name__)
|
||||
from route import app, socketio
|
||||
|
||||
try:
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
PORT = 7200
|
||||
HOST = '0.0.0.0'
|
||||
socketio.run(app, host=HOST, port=PORT)
|
||||
except Exception as ex:
|
||||
print ex
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# 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
|
||||
from random import Random
|
||||
|
||||
import public
|
||||
import db
|
||||
|
||||
from flask import redirect
|
||||
|
||||
|
||||
def init():
|
||||
|
||||
initDB()
|
||||
initInitD()
|
||||
initUserInfo()
|
||||
|
||||
|
||||
def local():
|
||||
result = checkClose()
|
||||
if result:
|
||||
return result
|
||||
|
||||
|
||||
# 检查面板是否关闭
|
||||
def checkClose():
|
||||
if os.path.exists('data/close.pl'):
|
||||
return redirect('/close')
|
||||
|
||||
|
||||
def initDB():
|
||||
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 initInitD():
|
||||
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 not public.isAppleSystem():
|
||||
initd_bin = '/etc/init.d/mw'
|
||||
if not os.path.exists(initd_bin):
|
||||
import shutil
|
||||
shutil.copyfile(script_bin, initd_bin)
|
||||
public.execShell('chmod +x ' + initd_bin)
|
||||
|
||||
|
||||
def initUserInfo():
|
||||
|
||||
data = public.M('users').where('id=?', (1,)).getField('password')
|
||||
if data == '21232f297a57a5a743894a0e4a801fc3':
|
||||
pwd = public.getRandomString(8).lower()
|
||||
file_pw = public.getRunDir() + '/data/default.pl'
|
||||
public.writeFile(file_pw, pwd)
|
||||
public.M('users').where('id=?', (1,)).setField(
|
||||
'password', public.md5(pwd))
|
||||
@@ -1,114 +0,0 @@
|
||||
# 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,320 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
from flask import session
|
||||
from flask import request
|
||||
|
||||
|
||||
class config_api:
|
||||
|
||||
__version = '0.0.5'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
##### ----- start ----- ###
|
||||
|
||||
# 取面板列表
|
||||
def getPanelListApi(self):
|
||||
data = public.M('panel').field(
|
||||
'id,title,url,username,password,click,addtime').order('click desc').select()
|
||||
return public.getJson(data)
|
||||
|
||||
def addPanelInfoApi(self):
|
||||
title = request.form.get('title', '')
|
||||
url = request.form.get('url', '')
|
||||
username = request.form.get('username', '')
|
||||
password = request.form.get('password', '')
|
||||
# 校验是还是重复
|
||||
isAdd = public.M('panel').where(
|
||||
'title=? OR url=?', (title, url)).count()
|
||||
if isAdd:
|
||||
return public.returnJson(False, '备注或面板地址重复!')
|
||||
isRe = public.M('panel').add('title,url,username,password,click,addtime',
|
||||
(title, url, username, password, 0, int(time.time())))
|
||||
if isRe:
|
||||
return public.returnJson(True, '添加成功!')
|
||||
return public.returnJson(False, '添加失败!')
|
||||
|
||||
# 删除面板资料
|
||||
def delPanelInfoApi(self):
|
||||
mid = request.form.get('id', '')
|
||||
isExists = public.M('panel').where('id=?', (mid,)).count()
|
||||
if not isExists:
|
||||
return public.returnJson(False, '指定面板资料不存在!')
|
||||
public.M('panel').where('id=?', (mid,)).delete()
|
||||
return public.returnJson(True, '删除成功!')
|
||||
|
||||
# 修改面板资料
|
||||
def setPanelInfoApi(self):
|
||||
title = request.form.get('title', '')
|
||||
url = request.form.get('url', '')
|
||||
username = request.form.get('username', '')
|
||||
password = request.form.get('password', '')
|
||||
mid = request.form.get('id', '')
|
||||
# 校验是还是重复
|
||||
isSave = public.M('panel').where(
|
||||
'(title=? OR url=?) AND id!=?', (title, url, mid)).count()
|
||||
if isSave:
|
||||
return public.returnMsg(False, '备注或面板地址重复!')
|
||||
|
||||
# 更新到数据库
|
||||
isRe = public.M('panel').where('id=?', (mid,)).save(
|
||||
'title,url,username,password', (title, url, username, password))
|
||||
if isRe:
|
||||
return public.returnMsg(True, '修改成功!')
|
||||
return public.returnMsg(False, '修改失败!')
|
||||
|
||||
def syncDateApi(self):
|
||||
if public.isAppleSystem():
|
||||
return public.returnJson(True, '开发系统不必同步时间!')
|
||||
|
||||
data = public.execShell('ntpdate -s time.nist.gov')
|
||||
if data[0] == '':
|
||||
return public.returnJson(True, '同步成功!')
|
||||
return public.returnJson(False, '同步失败:' + data[0])
|
||||
|
||||
def setPasswordApi(self):
|
||||
password1 = request.form.get('password1', '')
|
||||
password2 = request.form.get('password2', '')
|
||||
if password1 != password2:
|
||||
return public.returnJson(False, '两次输入的密码不一致,请重新输入!')
|
||||
if len(password1) < 5:
|
||||
return public.returnJson(False, '用户密码不能小于5位!')
|
||||
public.M('users').where("username=?", (session['username'],)).setField(
|
||||
'password', public.md5(password1.strip()))
|
||||
return public.returnJson(True, '密码修改成功!')
|
||||
|
||||
def setNameApi(self):
|
||||
name1 = request.form.get('name1', '')
|
||||
name2 = request.form.get('name2', '')
|
||||
if name1 != name2:
|
||||
return public.returnJson(False, '两次输入的用户名不一致,请重新输入!')
|
||||
if len(name1) < 3:
|
||||
return public.returnJson(False, '用户名长度不能少于3位')
|
||||
|
||||
public.M('users').where("username=?", (session['username'],)).setField(
|
||||
'username', name1.strip())
|
||||
|
||||
session['username'] = name1
|
||||
return public.returnJson(True, '用户修改成功!')
|
||||
|
||||
def setApi(self):
|
||||
webname = request.form.get('webname', '')
|
||||
port = request.form.get('port', '')
|
||||
host_ip = request.form.get('host_ip', '')
|
||||
domain = request.form.get('domain', '')
|
||||
sites_path = request.form.get('sites_path', '')
|
||||
backup_path = request.form.get('backup_path', '')
|
||||
|
||||
if domain != '':
|
||||
reg = "^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
|
||||
if not re.match(reg, domain):
|
||||
return public.returnJson(False, '主域名格式不正确')
|
||||
|
||||
if int(port) >= 65535 or int(port) < 100:
|
||||
return public.returnJson(False, '端口范围不正确!')
|
||||
|
||||
if webname != public.getConfig('title'):
|
||||
public.setConfig('title', webname)
|
||||
|
||||
if sites_path != public.getWwwDir():
|
||||
public.setWwwDir(sites_path)
|
||||
|
||||
if backup_path != public.getWwwDir():
|
||||
public.setBackupDir(backup_path)
|
||||
|
||||
if port != public.getHostPort():
|
||||
import system_api
|
||||
public.setHostPort(port)
|
||||
system_api.system_api().restartMw()
|
||||
|
||||
if host_ip != public.getHostAddr():
|
||||
public.setHostAddr(host_ip)
|
||||
|
||||
mhost = public.getHostAddr()
|
||||
info = {
|
||||
'uri': '/config',
|
||||
'host': mhost + ':' + port
|
||||
}
|
||||
return public.returnJson(True, '保存成功!', info)
|
||||
|
||||
def setAdminPathApi(self):
|
||||
admin_path = request.form.get('admin_path', '').strip()
|
||||
admin_path_checks = ['/', '/close', '/login', '/do_login', '/site',
|
||||
'/sites', '/download_file', '/control', '/crontab',
|
||||
'/firewall', '/files', 'config', '/soft', '/system',
|
||||
'/code', '/ssl', '/plugins']
|
||||
if admin_path == '':
|
||||
admin_path = '/'
|
||||
if admin_path != '/':
|
||||
if len(admin_path) < 6:
|
||||
return public.returnJson(False, '安全入口地址长度不能小于6位!')
|
||||
if admin_path in admin_path_checks:
|
||||
return public.returnJson(False, '该入口已被面板占用,请使用其它入口!')
|
||||
if not re.match("^/[\w\./-_]+$", admin_path):
|
||||
return public.returnJson(False, '入口地址格式不正确,示例: /my_panel')
|
||||
else:
|
||||
domain = public.readFile('data/domain.conf')
|
||||
if not domain:
|
||||
domain = ''
|
||||
limitip = public.readFile('data/limitip.conf')
|
||||
if not limitip:
|
||||
limitip = ''
|
||||
if not domain.strip() and not limitip.strip():
|
||||
return public.returnJson(False, '警告,关闭安全入口等于直接暴露你的后台地址在外网,十分危险,至少开启以下一种安全方式才能关闭:<a style="color:red;"><br>1、绑定访问域名<br>2、绑定授权IP</a>')
|
||||
|
||||
admin_path_file = 'data/admin_path.pl'
|
||||
admin_path_old = '/'
|
||||
if os.path.exists(admin_path_file):
|
||||
admin_path_old = public.readFile(admin_path_file).strip()
|
||||
|
||||
if admin_path_old != admin_path:
|
||||
public.writeFile(admin_path_file, admin_path)
|
||||
public.restartMw()
|
||||
return public.returnJson(True, '修改成功!')
|
||||
|
||||
def closePanelApi(self):
|
||||
filename = 'data/close.pl'
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
return public.returnJson(True, '开启成功')
|
||||
public.writeFile(filename, 'True')
|
||||
public.execShell("chmod 600 " + filename)
|
||||
public.execShell("chown root.root " + filename)
|
||||
return public.returnJson(True, '面板已关闭!')
|
||||
|
||||
def setIpv6StatusApi(self):
|
||||
ipv6_file = 'data/ipv6.pl'
|
||||
if os.path.exists('data/ipv6.pl'):
|
||||
os.remove(ipv6_file)
|
||||
public.writeLog('面板设置', '关闭面板IPv6兼容!')
|
||||
else:
|
||||
public.writeFile(ipv6_file, 'True')
|
||||
public.writeLog('面板设置', '开启面板IPv6兼容!')
|
||||
public.restartMw()
|
||||
return public.returnJson(True, '设置成功!')
|
||||
|
||||
# 获取面板证书
|
||||
def getPanelSslApi(self):
|
||||
cert = {}
|
||||
cert['privateKey'] = public.readFile('ssl/privateKey.pem')
|
||||
cert['certPem'] = public.readFile('ssl/certificate.pem')
|
||||
cert['rep'] = os.path.exists('ssl/input.pl')
|
||||
return public.getJson(cert)
|
||||
|
||||
# 保存面板证书
|
||||
def savePanelSslApi(self):
|
||||
keyPath = 'ssl/privateKey.pem'
|
||||
certPath = 'ssl/certificate.pem'
|
||||
checkCert = '/tmp/cert.pl'
|
||||
|
||||
certPem = request.form.get('certPem', '').strip()
|
||||
privateKey = request.form.get('privateKey', '').strip()
|
||||
|
||||
public.writeFile(checkCert, certPem)
|
||||
if privateKey:
|
||||
public.writeFile(keyPath, privateKey)
|
||||
if certPem:
|
||||
public.writeFile(certPath, certPem)
|
||||
if not public.checkCert(checkCert):
|
||||
return public.returnJson(False, '证书错误,请检查!')
|
||||
public.writeFile('ssl/input.pl', 'True')
|
||||
return public.returnJson(True, '证书已保存!')
|
||||
|
||||
# 设置面板SSL
|
||||
def setPanelSslApi(self):
|
||||
sslConf = public.getRunDir() + '/data/ssl.pl'
|
||||
if os.path.exists(sslConf):
|
||||
os.system('rm -f ' + sslConf)
|
||||
return public.returnJson(True, 'SSL已关闭,请使用http协议访问面板!')
|
||||
else:
|
||||
os.system('pip install cffi==1.10')
|
||||
os.system('pip install cryptography==2.1')
|
||||
os.system('pip install pyOpenSSL==16.2')
|
||||
try:
|
||||
if not self.createSSL():
|
||||
return public.returnJson(False, '开启失败,无法自动安装pyOpenSSL组件!<p>请尝试手动安装: pip install pyOpenSSL</p>')
|
||||
public.writeFile(sslConf, 'True')
|
||||
except Exception as ex:
|
||||
return public.returnJson(False, '开启失败,无法自动安装pyOpenSSL组件!<p>请尝试手动安装: pip install pyOpenSSL</p>')
|
||||
return public.returnJson(True, '开启成功,请使用https协议访问面板!')
|
||||
|
||||
def getApi(self):
|
||||
data = {}
|
||||
return public.getJson(data)
|
||||
##### ----- end ----- ###
|
||||
|
||||
# 自签证书
|
||||
def createSSL(self):
|
||||
if os.path.exists('ssl/input.pl'):
|
||||
return True
|
||||
import OpenSSL
|
||||
key = OpenSSL.crypto.PKey()
|
||||
key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
|
||||
cert = OpenSSL.crypto.X509()
|
||||
cert.set_serial_number(0)
|
||||
cert.get_subject().CN = '120.27.27.98'
|
||||
cert.set_issuer(cert.get_subject())
|
||||
cert.gmtime_adj_notBefore(0)
|
||||
cert.gmtime_adj_notAfter(86400 * 3650)
|
||||
cert.set_pubkey(key)
|
||||
cert.sign(key, 'md5')
|
||||
cert_ca = OpenSSL.crypto.dump_certificate(
|
||||
OpenSSL.crypto.FILETYPE_PEM, cert)
|
||||
private_key = OpenSSL.crypto.dump_privatekey(
|
||||
OpenSSL.crypto.FILETYPE_PEM, key)
|
||||
if len(cert_ca) > 100 and len(private_key) > 100:
|
||||
public.writeFile('ssl/certificate.pem', cert_ca)
|
||||
public.writeFile('ssl/privateKey.pem', private_key)
|
||||
print cert_ca, private_key
|
||||
return True
|
||||
return False
|
||||
|
||||
def getVersion(self):
|
||||
return self.__version
|
||||
|
||||
def get(self):
|
||||
|
||||
data = {}
|
||||
data['title'] = public.getConfig('title')
|
||||
data['site_path'] = public.getWwwDir()
|
||||
data['backup_path'] = public.getBackupDir()
|
||||
sformat = 'date +"%Y-%m-%d %H:%M:%S %Z %z"'
|
||||
data['systemdate'] = public.execShell(sformat)[0].strip()
|
||||
|
||||
data['port'] = public.getHostPort()
|
||||
data['ip'] = public.getHostAddr()
|
||||
|
||||
admin_path_file = 'data/admin_path.pl'
|
||||
if not os.path.exists(admin_path_file):
|
||||
data['admin_path'] = '/'
|
||||
else:
|
||||
data['admin_path'] = public.readFile(admin_path_file)
|
||||
|
||||
ipv6_file = 'data/ipv6.pl'
|
||||
if os.path.exists('data/ipv6.pl'):
|
||||
data['ipv6'] = 'checked'
|
||||
else:
|
||||
data['ipv6'] = ''
|
||||
|
||||
ssl_file = 'data/ssl.pl'
|
||||
if os.path.exists('data/ssl.pl'):
|
||||
data['ssl'] = 'checked'
|
||||
else:
|
||||
data['ssl'] = ''
|
||||
|
||||
data['site_count'] = public.M('sites').count()
|
||||
|
||||
data['username'] = public.M('users').where(
|
||||
"id=?", (1,)).getField('username')
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,514 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
from flask import request
|
||||
|
||||
|
||||
class crontab_api:
|
||||
|
||||
field = 'id,name,type,where1,where_hour,where_minute,echo,addtime,status,save,backup_to,stype,sname,sbody,urladdress'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
##### ----- start ----- ###
|
||||
def listApi(self):
|
||||
_list = public.M('crontab').where('', ()).field(self.field).limit(
|
||||
'0,5').order('id desc').select()
|
||||
|
||||
data = []
|
||||
for i in range(len(_list)):
|
||||
tmp = _list[i]
|
||||
if _list[i]['type'] == "day":
|
||||
tmp['type'] = '每天'
|
||||
tmp['cycle'] = public.getInfo('每天, {1}点{2}分 执行', (str(
|
||||
_list[i]['where_hour']), str(_list[i]['where_minute'])))
|
||||
elif _list[i]['type'] == "day-n":
|
||||
tmp['type'] = public.getInfo(
|
||||
'每{1}天', (str(_list[i]['where1']),))
|
||||
tmp['cycle'] = public.getInfo('每隔{1}天, {2}点{3}分 执行', (str(
|
||||
_list[i]['where1']), str(_list[i]['where_hour']), str(_list[i]['where_minute'])))
|
||||
elif _list[i]['type'] == "hour":
|
||||
tmp['type'] = '每小时'
|
||||
tmp['cycle'] = public.getInfo(
|
||||
'每小时, 第{1}分钟 执行', (str(_list[i]['where_minute']),))
|
||||
elif _list[i]['type'] == "hour-n":
|
||||
tmp['type'] = public.getInfo(
|
||||
'每{1}小时', (str(_list[i]['where1']),))
|
||||
tmp['cycle'] = public.getInfo('每{1}小时, 第{2}分钟 执行', (str(
|
||||
_list[i]['where1']), str(_list[i]['where_minute'])))
|
||||
elif _list[i]['type'] == "minute-n":
|
||||
tmp['type'] = public.getInfo(
|
||||
'每{1}分钟', (str(_list[i]['where1']),))
|
||||
tmp['cycle'] = public.getInfo(
|
||||
'每隔{1}分钟执行', (str(_list[i]['where1']),))
|
||||
elif _list[i]['type'] == "week":
|
||||
tmp['type'] = '每周'
|
||||
if not _list[i]['where1']:
|
||||
_list[i]['where1'] = '0'
|
||||
tmp['cycle'] = public.getInfo('每周{1}, {2}点{3}分执行', (self.toWeek(int(
|
||||
_list[i]['where1'])), str(_list[i]['where_hour']), str(_list[i]['where_minute'])))
|
||||
elif _list[i]['type'] == "month":
|
||||
tmp['type'] = '每月'
|
||||
tmp['cycle'] = public.getInfo('每月, {1}日 {2}点{3}分执行', (str(_list[i]['where1']), str(
|
||||
_list[i]['where_hour']), str(_list[i]['where_minute'])))
|
||||
data.append(tmp)
|
||||
|
||||
_ret = {}
|
||||
_ret['data'] = data
|
||||
|
||||
count = public.M('crontab').where('', ()).count()
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['tojs'] = 'remind'
|
||||
|
||||
_ret['page'] = public.getPage(_page)
|
||||
return public.getJson(_ret)
|
||||
|
||||
# 设置计划任务状态
|
||||
def setCronStatusApi(self):
|
||||
mid = request.form.get('id', '')
|
||||
cronInfo = public.M('crontab').where(
|
||||
'id=?', (mid,)).field(self.field).find()
|
||||
status = 1
|
||||
if cronInfo['status'] == status:
|
||||
status = 0
|
||||
self.removeForCrond(cronInfo['echo'])
|
||||
else:
|
||||
cronInfo['status'] = 1
|
||||
self.syncToCrond(cronInfo)
|
||||
|
||||
public.M('crontab').where('id=?', (mid,)).setField('status', status)
|
||||
public.writeLog(
|
||||
'计划任务', '修改计划任务[' + cronInfo['name'] + ']状态为[' + str(status) + ']')
|
||||
return public.returnJson(True, '设置成功')
|
||||
|
||||
# 获取指定任务数据
|
||||
def getCrondFindApi(self):
|
||||
sid = request.form.get('id', '')
|
||||
data = public.M('crontab').where(
|
||||
'id=?', (sid,)).field(self.field).find()
|
||||
return public.getJson(data)
|
||||
|
||||
def modifyCrondApi(self):
|
||||
sid = request.form.get('id', '')
|
||||
iname = request.form.get('name', '')
|
||||
field_type = request.form.get('type', '')
|
||||
week = request.form.get('week', '')
|
||||
where1 = request.form.get('where1', '')
|
||||
hour = request.form.get('hour', '')
|
||||
minute = request.form.get('minute', '')
|
||||
save = request.form.get('save', '')
|
||||
backup_to = request.form.get('backup_to', '')
|
||||
stype = request.form.get('stype', '')
|
||||
sname = request.form.get('sname', '')
|
||||
sbody = request.form.get('sbody', '')
|
||||
urladdress = request.form.get('urladdress', '')
|
||||
|
||||
if len(iname) < 1:
|
||||
return public.returnJson(False, '任务名称不能为空!')
|
||||
|
||||
params = {
|
||||
'name': iname,
|
||||
'type': field_type,
|
||||
'week': week,
|
||||
'where1': where1,
|
||||
'hour': hour,
|
||||
'minute': minute,
|
||||
'save': save,
|
||||
'backup_to': backup_to,
|
||||
'stype': stype,
|
||||
'sname': sname,
|
||||
'sbody': sbody,
|
||||
'urladdress': urladdress,
|
||||
}
|
||||
cuonConfig, get, name = self.getCrondCycle(params)
|
||||
cronInfo = public.M('crontab').where(
|
||||
'id=?', (sid,)).field(self.field).find()
|
||||
del(cronInfo['id'])
|
||||
del(cronInfo['addtime'])
|
||||
cronInfo['name'] = get['name']
|
||||
cronInfo['type'] = get['type']
|
||||
cronInfo['where1'] = get['where1']
|
||||
cronInfo['where_hour'] = get['hour']
|
||||
cronInfo['where_minute'] = get['minute']
|
||||
cronInfo['save'] = get['save']
|
||||
cronInfo['backup_to'] = get['backup_to']
|
||||
cronInfo['sbody'] = get['sbody']
|
||||
cronInfo['urladdress'] = get['urladdress']
|
||||
|
||||
addData = public.M('crontab').where('id=?', (sid,)).save('name,type,where1,where_hour,where_minute,save,backup_to,sbody,urladdress', (get[
|
||||
'name'], field_type, get['where1'], get['hour'], get['minute'], get['save'], get['backup_to'], get['sbody'], get['urladdress']))
|
||||
self.removeForCrond(cronInfo['echo'])
|
||||
self.syncToCrond(cronInfo)
|
||||
public.writeLog('计划任务', '修改计划任务[' + cronInfo['name'] + ']成功')
|
||||
return public.returnJson(True, '修改成功')
|
||||
|
||||
def logsApi(self):
|
||||
sid = request.form.get('id', '')
|
||||
echo = public.M('crontab').where("id=?", (sid,)).field('echo').find()
|
||||
logFile = public.getServerDir() + '/cron/' + echo['echo'] + '.log'
|
||||
if not os.path.exists(logFile):
|
||||
return public.returnJson(False, '当前日志为空!')
|
||||
log = public.getNumLines(logFile, 2000)
|
||||
return public.returnJson(True, log)
|
||||
|
||||
def addApi(self):
|
||||
iname = request.form.get('name', '')
|
||||
field_type = request.form.get('type', '')
|
||||
week = request.form.get('week', '')
|
||||
where1 = request.form.get('where1', '')
|
||||
hour = request.form.get('hour', '')
|
||||
minute = request.form.get('minute', '')
|
||||
save = request.form.get('save', '')
|
||||
backup_to = request.form.get('backupTo', '')
|
||||
stype = request.form.get('sType', '')
|
||||
sname = request.form.get('sName', '')
|
||||
sbody = request.form.get('sBody', '')
|
||||
urladdress = request.form.get('urladdress', '')
|
||||
|
||||
if len(iname) < 1:
|
||||
return public.returnJson(False, '任务名称不能为空!')
|
||||
|
||||
params = {
|
||||
'name': iname,
|
||||
'type': field_type,
|
||||
'week': week,
|
||||
'where1': where1,
|
||||
'hour': hour,
|
||||
'minute': minute,
|
||||
'save': save,
|
||||
'backup_to': backup_to,
|
||||
'stype': stype,
|
||||
'sname': sname,
|
||||
'sbody': sbody,
|
||||
'urladdress': urladdress,
|
||||
}
|
||||
|
||||
# print params
|
||||
cuonConfig, get, name = self.getCrondCycle(params)
|
||||
cronPath = public.getServerDir() + '/cron'
|
||||
|
||||
cronName = self.getShell(params)
|
||||
# print cuonConfig, _params, name
|
||||
# print cronPath, cronName
|
||||
# print stype
|
||||
|
||||
if type(cronName) == dict:
|
||||
return cronName
|
||||
|
||||
cuonConfig += ' ' + cronPath + '/' + cronName + \
|
||||
' >> ' + cronPath + '/' + cronName + '.log 2>&1'
|
||||
wRes = self.writeShell(cuonConfig)
|
||||
|
||||
if type(wRes) != bool:
|
||||
return wRes
|
||||
|
||||
self.crondReload()
|
||||
addData = public.M('crontab').add('name,type,where1,where_hour,where_minute,echo,addtime,status,save,backup_to,stype,sname,sbody,urladdress', (iname, field_type, where1, hour, minute, cronName, time.strftime(
|
||||
'%Y-%m-%d %X', time.localtime()), 1, save, backup_to, stype, sname, sbody, urladdress))
|
||||
|
||||
if addData > 0:
|
||||
return public.returnJson(True, '添加成功')
|
||||
return public.returnJson(False, '添加失败')
|
||||
|
||||
def startTaskApi(self):
|
||||
sid = request.form.get('id', '')
|
||||
echo = public.M('crontab').where('id=?', (sid,)).getField('echo')
|
||||
execstr = public.getServerDir() + '/cron/' + echo
|
||||
os.system('chmod +x ' + execstr)
|
||||
os.system('nohup ' + execstr + ' >> ' + execstr + '.log 2>&1 &')
|
||||
return public.returnJson(True, '任务已执行!')
|
||||
|
||||
def delApi(self):
|
||||
sid = request.form.get('id', '')
|
||||
try:
|
||||
find = public.M('crontab').where(
|
||||
"id=?", (sid,)).field('name,echo').find()
|
||||
if not self.removeForCrond(find['echo']):
|
||||
return public.returnJson(False, '无法写入文件,请检查是否开启了系统加固功能!')
|
||||
|
||||
cronPath = public.getServerDir() + '/cron'
|
||||
sfile = cronPath + '/' + find['echo']
|
||||
|
||||
if os.path.exists(sfile):
|
||||
os.remove(sfile)
|
||||
sfile = cronPath + '/' + find['echo'] + '.log'
|
||||
if os.path.exists(sfile):
|
||||
os.remove(sfile)
|
||||
|
||||
public.M('crontab').where("id=?", (sid,)).delete()
|
||||
public.writeLog('计划任务', public.getInfo(
|
||||
'删除计划任务[{1}]成功!', (find['name'],)))
|
||||
return public.returnJson(True, '删除成功')
|
||||
except Exception as e:
|
||||
return public.returnJson(False, '删除失败:' + str(e))
|
||||
|
||||
def delLogsApi(self):
|
||||
sid = request.form.get('id', '')
|
||||
try:
|
||||
echo = public.M('crontab').where("id=?", (sid,)).getField('echo')
|
||||
logFile = public.getServerDir() + '/cron/' + echo + '.log'
|
||||
os.remove(logFile)
|
||||
return public.returnJson(True, '任务日志已清空!')
|
||||
except:
|
||||
return public.returnJson(False, '任务日志清空失败!')
|
||||
|
||||
# 取数据列表
|
||||
def getDataListApi(self):
|
||||
stype = request.form.get('type', '').encode('utf-8')
|
||||
if stype == 'databases':
|
||||
db_list = {}
|
||||
db_list['orderOpt'] = []
|
||||
path = public.getServerDir() + '/mysql'
|
||||
if not os.path.exists(path + '/mysql.db'):
|
||||
db_list['data'] = []
|
||||
else:
|
||||
db_list['data'] = public.M('databases').dbPos(
|
||||
path, 'mysql').field('name,ps').select()
|
||||
return public.getJson(db_list)
|
||||
|
||||
data = {}
|
||||
data['data'] = public.M(stype).field('name,ps').select()
|
||||
data['orderOpt'] = []
|
||||
# try:
|
||||
# tmp = public.readFile('data/libList.conf')
|
||||
# libs = json.loads(tmp)
|
||||
# import imp
|
||||
# for lib in libs:
|
||||
# imp.find_module(lib['module'])
|
||||
# tmp = {}
|
||||
# tmp['name'] = lib['name']
|
||||
# tmp['value'] = lib['opt']
|
||||
# data['orderOpt'].append(tmp)
|
||||
# except Exception as e:
|
||||
# print e
|
||||
return public.getJson(data)
|
||||
##### ----- start ----- ###
|
||||
|
||||
# 转换大写星期
|
||||
def toWeek(self, num):
|
||||
wheres = {
|
||||
0: '日',
|
||||
1: '一',
|
||||
2: '二',
|
||||
3: '三',
|
||||
4: '四',
|
||||
5: '五',
|
||||
6: '六'
|
||||
}
|
||||
try:
|
||||
return wheres[num]
|
||||
except:
|
||||
return ''
|
||||
|
||||
def getCrondCycle(self, params):
|
||||
cuonConfig = ''
|
||||
name = ''
|
||||
if params['type'] == "day":
|
||||
cuonConfig = self.getDay(params)
|
||||
name = '每天'
|
||||
elif params['type'] == "day-n":
|
||||
cuonConfig = self.getDay_N(params)
|
||||
name = public.getInfo('每{1}天', (params['where1'],))
|
||||
elif params['type'] == "hour":
|
||||
cuonConfig = self.getHour(params)
|
||||
name = '每小时'
|
||||
elif params['type'] == "hour-n":
|
||||
cuonConfig = self.getHour_N(params)
|
||||
name = '每小时'
|
||||
elif params['type'] == "minute-n":
|
||||
cuonConfig = self.minute_N(params)
|
||||
elif params['type'] == "week":
|
||||
params['where1'] = params['week']
|
||||
cuonConfig = self.week(params)
|
||||
elif params['type'] == "month":
|
||||
cuonConfig = self.month(params)
|
||||
return cuonConfig, params, name
|
||||
|
||||
# 取任务构造Day
|
||||
def getDay(self, param):
|
||||
cuonConfig = "{0} {1} * * * ".format(param['minute'], param['hour'])
|
||||
return cuonConfig
|
||||
# 取任务构造Day_n
|
||||
|
||||
def getDay_N(self, param):
|
||||
cuonConfig = "{0} {1} */{2} * * ".format(
|
||||
param['minute'], param['hour'], param['where1'])
|
||||
return cuonConfig
|
||||
|
||||
# 取任务构造Hour
|
||||
def getHour(self, param):
|
||||
cuonConfig = "{0} * * * * ".format(param['minute'])
|
||||
return cuonConfig
|
||||
|
||||
# 取任务构造Hour-N
|
||||
def getHour_N(self, param):
|
||||
cuonConfig = "{0} */{1} * * * ".format(
|
||||
param['minute'], param['where1'])
|
||||
return cuonConfig
|
||||
|
||||
# 取任务构造Minute-N
|
||||
def minute_N(self, param):
|
||||
cuonConfig = "*/{0} * * * * ".format(param['where1'])
|
||||
return cuonConfig
|
||||
|
||||
# 取任务构造week
|
||||
def week(self, param):
|
||||
cuonConfig = "{0} {1} * * {2}".format(
|
||||
param['minute'], param['hour'], param['week'])
|
||||
return cuonConfig
|
||||
|
||||
# 取任务构造Month
|
||||
def month(self, param):
|
||||
cuonConfig = "{0} {1} {2} * * ".format(
|
||||
param['minute'], param['hour'], param['where1'])
|
||||
return cuonConfig
|
||||
|
||||
# 取执行脚本
|
||||
def getShell(self, param):
|
||||
# try:
|
||||
stype = param['stype']
|
||||
if stype == 'toFile':
|
||||
shell = param.sFile
|
||||
else:
|
||||
head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n"
|
||||
log = '.log'
|
||||
|
||||
wheres = {
|
||||
'path': head + "python " + public.getServerDir() + "/mdserver-web/scripts/backup.py path " + param['sname'] + " " + str(param['save']),
|
||||
'site': head + "python " + public.getServerDir() + "/mdserver-web/scripts/backup.py site " + param['sname'] + " " + str(param['save']),
|
||||
'database': head + "python " + public.getServerDir() + "/mdserver-web/scripts/backup.py database " + param['sname'] + " " + str(param['save']),
|
||||
'logs': head + "python " + public.getServerDir() + "/mdserver-web/scripts/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
|
||||
'rememory': head + "/bin/bash " + public.getServerDir() + '/mdserver-web/scripts/rememory.sh'
|
||||
}
|
||||
if param['backup_to'] != 'localhost':
|
||||
cfile = public.getServerDir() + "/mdserver-web/plugin/" + param[
|
||||
'backup_to'] + "/" + param['backup_to'] + "_main.py"
|
||||
if not os.path.exists(cfile):
|
||||
cfile = public.getServerDir() + "/mdserver-web/script/backup_" + \
|
||||
param['backup_to'] + ".py"
|
||||
wheres = {
|
||||
'path': head + "python " + cfile + " path " + param['sname'] + " " + str(param['save']),
|
||||
'site': head + "python " + cfile + " site " + param['sname'] + " " + str(param['save']),
|
||||
'database': head + "python " + cfile + " database " + param['sname'] + " " + str(param['save']),
|
||||
'logs': head + "python " + public.getServerDir() + "/mdserver-web/scripts/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
|
||||
'rememory': head + "/bin/bash " + public.getServerDir() + '/mdserver-web/scripts/rememory.sh'
|
||||
}
|
||||
try:
|
||||
shell = wheres[stype]
|
||||
except:
|
||||
if stype == 'toUrl':
|
||||
shell = head + "curl -sS --connect-timeout 10 -m 60 '" + \
|
||||
param['urladdress'] + "'"
|
||||
else:
|
||||
shell = head + param['sbody'].replace("\r\n", "\n")
|
||||
|
||||
shell += '''
|
||||
echo "----------------------------------------------------------------------------"
|
||||
endDate=`date +"%Y-%m-%d %H:%M:%S"`
|
||||
echo "★[$endDate] Successful"
|
||||
echo "----------------------------------------------------------------------------"
|
||||
'''
|
||||
cronPath = public.getServerDir() + '/cron'
|
||||
if not os.path.exists(cronPath):
|
||||
public.execShell('mkdir -p ' + cronPath)
|
||||
if not 'echo' in param:
|
||||
cronName = public.md5(public.md5(str(time.time()) + '_mw'))
|
||||
else:
|
||||
cronName = param['echo']
|
||||
file = cronPath + '/' + cronName
|
||||
public.writeFile(file, self.checkScript(shell))
|
||||
public.execShell('chmod 750 ' + file)
|
||||
return cronName
|
||||
|
||||
# 检查脚本
|
||||
def checkScript(self, shell):
|
||||
keys = ['shutdown', 'init 0', 'mkfs', 'passwd',
|
||||
'chpasswd', '--stdin', 'mkfs.ext', 'mke2fs']
|
||||
for key in keys:
|
||||
shell = shell.replace(key, '[***]')
|
||||
return shell
|
||||
|
||||
# 将Shell脚本写到文件
|
||||
def writeShell(self, config):
|
||||
u_file = '/var/spool/cron/crontabs/root'
|
||||
if not os.path.exists(u_file):
|
||||
file = '/var/spool/cron/root'
|
||||
if public.isAppleSystem():
|
||||
file = '/etc/crontab'
|
||||
else:
|
||||
file = u_file
|
||||
|
||||
if not os.path.exists(file):
|
||||
public.writeFile(file, '')
|
||||
conf = public.readFile(file)
|
||||
conf += config + "\n"
|
||||
if public.writeFile(file, conf):
|
||||
if not os.path.exists(u_file):
|
||||
public.execShell("chmod 600 '" + file +
|
||||
"' && chown root.root " + file)
|
||||
else:
|
||||
public.execShell("chmod 600 '" + file +
|
||||
"' && chown root.crontab " + file)
|
||||
return True
|
||||
return public.returnJson(False, '文件写入失败,请检查是否开启系统加固功能!')
|
||||
|
||||
# 重载配置
|
||||
def crondReload(self):
|
||||
if public.isAppleSystem():
|
||||
if os.path.exists('/etc/crontab'):
|
||||
pass
|
||||
# public.execShell('/usr/sbin/cron restart')
|
||||
else:
|
||||
if os.path.exists('/etc/init.d/crond'):
|
||||
public.execShell('/etc/init.d/crond reload')
|
||||
elif os.path.exists('/etc/init.d/cron'):
|
||||
public.execShell('service cron restart')
|
||||
else:
|
||||
public.execShell("systemctl reload crond")
|
||||
|
||||
# 从crond删除
|
||||
def removeForCrond(self, echo):
|
||||
u_file = '/var/spool/cron/crontabs/root'
|
||||
if not os.path.exists(u_file):
|
||||
file = '/var/spool/cron/root'
|
||||
if public.isAppleSystem():
|
||||
file = '/etc/crontab'
|
||||
else:
|
||||
file = u_file
|
||||
conf = public.readFile(file)
|
||||
rep = ".+" + str(echo) + ".+\n"
|
||||
conf = re.sub(rep, "", conf)
|
||||
if not public.writeFile(file, conf):
|
||||
return False
|
||||
self.crondReload()
|
||||
return True
|
||||
|
||||
def syncToCrond(self, cronInfo):
|
||||
if 'status' in cronInfo:
|
||||
if cronInfo['status'] == 0:
|
||||
return False
|
||||
if 'where_hour' in cronInfo:
|
||||
cronInfo['hour'] = cronInfo['where_hour']
|
||||
cronInfo['minute'] = cronInfo['where_minute']
|
||||
cronInfo['week'] = cronInfo['where1']
|
||||
cuonConfig, cronInfo, name = self.getCrondCycle(cronInfo)
|
||||
cronPath = public.getServerDir() + '/cron'
|
||||
cronName = self.getShell(cronInfo)
|
||||
if type(cronName) == dict:
|
||||
return cronName
|
||||
cuonConfig += ' ' + cronPath + '/' + cronName + \
|
||||
' >> ' + cronPath + '/' + cronName + '.log 2>&1'
|
||||
wRes = self.writeShell(cuonConfig)
|
||||
if type(wRes) != bool:
|
||||
return False
|
||||
self.crondReload()
|
||||
@@ -33,6 +33,10 @@ class Sql():
|
||||
self.__DB_FILE = 'data/' + name + '.db'
|
||||
return self
|
||||
|
||||
def dbPos(self, path, name):
|
||||
self.__DB_FILE = path + '/' + name + '.db'
|
||||
return self
|
||||
|
||||
def table(self, table):
|
||||
# 设置表名
|
||||
self.__DB_TABLE = table
|
||||
@@ -223,6 +227,7 @@ class Sql():
|
||||
def execute(self, sql, param):
|
||||
# 执行SQL语句返回受影响行
|
||||
self.__GetConn()
|
||||
# print sql, param
|
||||
try:
|
||||
result = self.__DB_CONN.execute(sql, param)
|
||||
self.__DB_CONN.commit()
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
# 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,610 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
import shutil
|
||||
|
||||
from flask import request
|
||||
from flask import send_file, send_from_directory
|
||||
from flask import make_response
|
||||
|
||||
|
||||
class files_api:
|
||||
|
||||
rPath = None
|
||||
|
||||
def __init__(self):
|
||||
self.rPath = public.getRootDir() + '/recycle_bin/'
|
||||
|
||||
##### ----- start ----- ###
|
||||
def getBodyApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
return self.getBody(path)
|
||||
|
||||
def getLastBodyApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
line = request.form.get('line', '100')
|
||||
|
||||
if not os.path.exists(path):
|
||||
return public.returnJson(False, '文件不存在', (path,))
|
||||
|
||||
try:
|
||||
data = public.getNumLines(path, int(line))
|
||||
return public.returnJson(True, 'OK', data)
|
||||
except Exception as ex:
|
||||
return public.returnJson(False, u'无法正确读取文件!' + str(ex))
|
||||
|
||||
def saveBodyApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
data = request.form.get('data', '').encode('utf-8')
|
||||
encoding = request.form.get('encoding', '').encode('utf-8')
|
||||
return self.saveBody(path, data, encoding)
|
||||
|
||||
def downloadApi(self):
|
||||
filename = request.args.get('filename', '').encode('utf-8')
|
||||
if not os.path.exists(filename):
|
||||
return ''
|
||||
response = make_response(send_from_directory(
|
||||
os.path.dirname(filename), os.path.basename(filename), as_attachment=True))
|
||||
return response
|
||||
|
||||
def zipApi(self):
|
||||
sfile = request.form.get('sfile', '').encode('utf-8')
|
||||
dfile = request.form.get('dfile', '').encode('utf-8')
|
||||
stype = request.form.get('type', '').encode('utf-8')
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
return self.zip(sfile, dfile, stype, path)
|
||||
|
||||
def deleteApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
return self.delete(path)
|
||||
|
||||
def fileAccessApi(self):
|
||||
filename = request.form.get('filename', '').encode('utf-8')
|
||||
data = self.getAccess(filename)
|
||||
return public.getJson(data)
|
||||
|
||||
def getDirSizeApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
tmp = self.getDirSize(path)
|
||||
return public.returnJson(True, tmp[0].split()[0])
|
||||
|
||||
def getDirApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
if not os.path.exists(path):
|
||||
path = public.getRootDir() + "/wwwroot"
|
||||
search = request.args.get('search', '').strip().lower()
|
||||
page = request.args.get('p', '1').strip().lower()
|
||||
row = request.args.get('showRow', '10')
|
||||
return self.getDir(path, int(page), int(row), search)
|
||||
|
||||
def createFileApi(self):
|
||||
file = request.form.get('path', '').encode('utf-8')
|
||||
try:
|
||||
if not self.checkFileName(file):
|
||||
return public.returnJson(False, '文件名中不能包含特殊字符!')
|
||||
if os.path.exists(file):
|
||||
return public.returnJson(False, '指定文件已存在!')
|
||||
_path = os.path.dirname(file)
|
||||
if not os.path.exists(_path):
|
||||
os.makedirs(_path)
|
||||
open(file, 'w+').close()
|
||||
self.setFileAccept(file)
|
||||
msg = public.getInfo('创建文件[{1}]成功!', (file,))
|
||||
public.writeLog('文件管理', msg)
|
||||
return public.returnJson(True, '文件创建成功!')
|
||||
except Exception as e:
|
||||
# print str(e)
|
||||
return public.returnJson(True, '文件创建失败!')
|
||||
|
||||
def createDirApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
try:
|
||||
if not self.checkFileName(path):
|
||||
return public.returnJson(False, '目录名中不能包含特殊字符!')
|
||||
if os.path.exists(path):
|
||||
return public.returnJson(False, '指定目录已存在!')
|
||||
os.makedirs(path)
|
||||
self.setFileAccept(path)
|
||||
msg = public.getInfo('创建目录[{1}]成功!', (path,))
|
||||
public.writeLog('文件管理', msg)
|
||||
return public.returnJson(True, '目录创建成功!')
|
||||
except Exception as e:
|
||||
return public.returnJson(False, '目录创建失败!')
|
||||
|
||||
def downloadFileApi(self):
|
||||
import db
|
||||
import time
|
||||
url = request.form.get('url', '').encode('utf-8')
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
filename = request.form.get('filename', '').encode('utf-8')
|
||||
|
||||
isTask = public.getRootDir() + '/tmp/panelTask.pl'
|
||||
execstr = url + '|mw|' + path + '/' + filename
|
||||
public.M('tasks').add('name,type,status,addtime,execstr',
|
||||
('下载文件[' + filename + ']', 'download', '0', time.strftime('%Y-%m-%d %H:%M:%S'), execstr))
|
||||
public.writeFile(isTask, 'True')
|
||||
# self.setFileAccept(path + '/' + filename)
|
||||
return public.returnJson(True, '已将下载任务添加到队列!')
|
||||
|
||||
def removeTaskApi(self):
|
||||
mid = request.form.get('id', '').encode('utf-8')
|
||||
try:
|
||||
name = public.M('tasks').where('id=?', (mid,)).getField('name')
|
||||
status = public.M('tasks').where('id=?', (mid,)).getField('status')
|
||||
public.M('tasks').delete(mid)
|
||||
if status == '-1':
|
||||
os.system(
|
||||
"kill `ps -ef |grep 'python panelSafe.pyc'|grep -v grep|grep -v panelExec|awk '{print $2}'`")
|
||||
os.system(
|
||||
"kill `ps aux | grep 'python task.pyc$'|awk '{print $2}'`")
|
||||
os.system('''
|
||||
pids=`ps aux | grep 'sh'|grep -v grep|grep install|awk '{print $2}'`
|
||||
arr=($pids)
|
||||
|
||||
for p in ${arr[@]}
|
||||
do
|
||||
kill -9 $p
|
||||
done
|
||||
''')
|
||||
|
||||
os.system(
|
||||
'rm -f ' + name.replace('扫描目录[', '').replace(']', '') + '/scan.pl')
|
||||
isTask = public.getRootDir() + '/tmp/panelTask.pl'
|
||||
public.writeFile(isTask, 'True')
|
||||
os.system('/etc/init.d/mw start')
|
||||
except:
|
||||
os.system('/etc/init.d/mw start')
|
||||
return public.returnJson(True, '任务已删除!')
|
||||
|
||||
# 上传文件
|
||||
def uploadFileApi(self):
|
||||
from werkzeug.utils import secure_filename
|
||||
from flask import request
|
||||
|
||||
path = request.args.get('path', '').encode('utf-8')
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
f = request.files['zunfile']
|
||||
filename = os.path.join(path, f.filename)
|
||||
if sys.version_info[0] == 2:
|
||||
filename = filename.encode('utf-8')
|
||||
s_path = path
|
||||
if os.path.exists(filename):
|
||||
s_path = filename
|
||||
p_stat = os.stat(s_path)
|
||||
f.save(filename)
|
||||
os.chown(filename, p_stat.st_uid, p_stat.st_gid)
|
||||
os.chmod(filename, p_stat.st_mode)
|
||||
|
||||
msg = public.getInfo('上传文件[{1}] 到 [{2}]成功!', (filename, path))
|
||||
public.writeLog('文件管理', msg)
|
||||
return public.returnMsg(True, '上传成功!')
|
||||
|
||||
def getRecycleBinApi(self):
|
||||
rPath = self.rPath
|
||||
if not os.path.exists(rPath):
|
||||
os.system('mkdir -p ' + rPath)
|
||||
data = {}
|
||||
data['dirs'] = []
|
||||
data['files'] = []
|
||||
data['status'] = os.path.exists('data/recycle_bin.pl')
|
||||
data['status_db'] = os.path.exists('data/recycle_bin_db.pl')
|
||||
for file in os.listdir(rPath):
|
||||
try:
|
||||
tmp = {}
|
||||
fname = rPath + file
|
||||
tmp1 = file.split('_mw_')
|
||||
tmp2 = tmp1[len(tmp1) - 1].split('_t_')
|
||||
tmp['rname'] = file
|
||||
tmp['dname'] = file.replace('_mw_', '/').split('_t_')[0]
|
||||
tmp['name'] = tmp2[0]
|
||||
tmp['time'] = int(float(tmp2[1]))
|
||||
if os.path.islink(fname):
|
||||
filePath = os.readlink(fname)
|
||||
link = ' -> ' + filePath
|
||||
if os.path.exists(filePath):
|
||||
tmp['size'] = os.path.getsize(filePath)
|
||||
else:
|
||||
tmp['size'] = 0
|
||||
else:
|
||||
tmp['size'] = os.path.getsize(fname)
|
||||
if os.path.isdir(fname):
|
||||
data['dirs'].append(tmp)
|
||||
else:
|
||||
data['files'].append(tmp)
|
||||
except:
|
||||
continue
|
||||
return public.returnJson(True, 'OK', data)
|
||||
|
||||
# 回收站开关
|
||||
def recycleBinApi(self):
|
||||
c = 'data/recycle_bin.pl'
|
||||
db = request.form.get('db', '').encode('utf-8')
|
||||
if db != '':
|
||||
c = 'data/recycle_bin_db.pl'
|
||||
if os.path.exists(c):
|
||||
os.remove(c)
|
||||
public.writeLog('文件管理', '已关闭回收站功能!')
|
||||
return public.returnJson(True, '已关闭回收站功能!')
|
||||
else:
|
||||
public.writeFile(c, 'True')
|
||||
public.writeLog('文件管理', '已开启回收站功能!')
|
||||
return public.returnJson(True, '已开启回收站功能!')
|
||||
|
||||
def reRecycleBinApi(self):
|
||||
rPath = self.rPath
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
dFile = path.replace('_mw_', '/').split('_t_')[0]
|
||||
try:
|
||||
import shutil
|
||||
shutil.move(rPath + path, dFile)
|
||||
msg = public.getInfo('移动文件[{1}]到回收站成功!', (dFile,))
|
||||
public.writeLog('文件管理', msg)
|
||||
return public.returnJson(True, '恢复成功!')
|
||||
except Exception as e:
|
||||
msg = public.getInfo('从回收站恢复[{1}]失败!', (dFile,))
|
||||
public.writeLog('文件管理', msg)
|
||||
return public.returnJson(False, '恢复失败!')
|
||||
|
||||
def delRecycleBinApi(self):
|
||||
rPath = self.rPath
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
empty = request.form.get('empty', '').encode('utf-8')
|
||||
dFile = path.split('_t_')[0]
|
||||
|
||||
if not self.checkDir(path):
|
||||
return public.returnJson(False, '敏感目录,请不要花样作死!')
|
||||
|
||||
os.system('which chattr && chattr -R -i ' + rPath + path)
|
||||
if os.path.isdir(rPath + path):
|
||||
import shutil
|
||||
shutil.rmtree(rPath + path)
|
||||
else:
|
||||
os.remove(rPath + path)
|
||||
|
||||
tfile = path.replace('_mw_', '/').split('_t_')[0]
|
||||
msg = public.getInfo('已彻底从回收站删除{1}!', (tfile,))
|
||||
public.writeLog('文件管理', msg)
|
||||
return public.returnJson(True, msg)
|
||||
|
||||
# 获取进度
|
||||
def getSpeedApi(self):
|
||||
data = public.getSpeed()
|
||||
return public.returnJson(True, '已清空回收站!', data)
|
||||
|
||||
def closeRecycleBinApi(self):
|
||||
rPath = self.rPath
|
||||
os.system('which chattr && chattr -R -i ' + rPath)
|
||||
rlist = os.listdir(rPath)
|
||||
i = 0
|
||||
l = len(rlist)
|
||||
for name in rlist:
|
||||
i += 1
|
||||
path = rPath + name
|
||||
public.writeSpeed(name, i, l)
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
else:
|
||||
os.remove(path)
|
||||
public.writeSpeed(None, 0, 0)
|
||||
public.writeLog('文件管理', '已清空回收站!')
|
||||
return public.returnJson(True, '已清空回收站!')
|
||||
|
||||
def deleteDirApi(self):
|
||||
path = request.form.get('path', '').encode('utf-8')
|
||||
if not os.path.exists(path):
|
||||
return public.returnJson(False, '指定文件不存在!')
|
||||
|
||||
# 检查是否为.user.ini
|
||||
if path.find('.user.ini'):
|
||||
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('文件管理', '删除文件成功!', (path,))
|
||||
return public.returnJson(True, '删除文件成功!')
|
||||
except:
|
||||
return public.returnJson(False, '删除文件失败!')
|
||||
|
||||
def closeLogsApi(self):
|
||||
logPath = public.getLogsDir()
|
||||
os.system('rm -f ' + logPath + '/*')
|
||||
os.system('kill -USR1 `cat ' + public.getServerDir() +
|
||||
'openresty/nginx/logs/nginx.pid`')
|
||||
public.writeLog('文件管理', '网站日志已被清空!')
|
||||
tmp = self.getDirSize(logPath)
|
||||
return public.returnJson(True, tmp[0].split()[0])
|
||||
|
||||
##### ----- end ----- ###
|
||||
|
||||
# 检查敏感目录
|
||||
def checkDir(self, path):
|
||||
path = path.replace('//', '/')
|
||||
if path[-1:] == '/':
|
||||
path = path[:-1]
|
||||
|
||||
nDirs = ('',
|
||||
'/',
|
||||
'/*',
|
||||
'/www',
|
||||
'/root',
|
||||
'/boot',
|
||||
'/bin',
|
||||
'/etc',
|
||||
'/home',
|
||||
'/dev',
|
||||
'/sbin',
|
||||
'/var',
|
||||
'/usr',
|
||||
'/tmp',
|
||||
'/sys',
|
||||
'/proc',
|
||||
'/media',
|
||||
'/mnt',
|
||||
'/opt',
|
||||
'/lib',
|
||||
'/srv',
|
||||
'/selinux',
|
||||
'/www/server',
|
||||
'/www/server/data',
|
||||
public.getRootDir())
|
||||
|
||||
return not path in nDirs
|
||||
|
||||
def getDirSize(self, path):
|
||||
if public.getOs() == 'darwin':
|
||||
tmp = public.execShell('du -sh ' + path)
|
||||
else:
|
||||
tmp = public.execShell('du -sbh ' + path)
|
||||
return tmp
|
||||
|
||||
def checkFileName(self, filename):
|
||||
# 检测文件名
|
||||
nots = ['\\', '&', '*', '|', ';']
|
||||
if filename.find('/') != -1:
|
||||
filename = filename.split('/')[-1]
|
||||
for n in nots:
|
||||
if n in filename:
|
||||
return False
|
||||
return True
|
||||
|
||||
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 = self.rPath
|
||||
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)
|
||||
data['PATH'] = path.replace('//', '/')
|
||||
return public.getJson(data)
|
||||
@@ -9,11 +9,311 @@ import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
from flask import request
|
||||
|
||||
|
||||
class firewall_api:
|
||||
|
||||
__isFirewalld = False
|
||||
__isUfw = False
|
||||
__isMac = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
if os.path.exists('/usr/sbin/firewalld'):
|
||||
self.__isFirewalld = True
|
||||
if os.path.exists('/usr/sbin/ufw'):
|
||||
self.__isUfw = True
|
||||
if public.isAppleSystem():
|
||||
self.__isMac = True
|
||||
|
||||
##### ----- start ----- ###
|
||||
# 添加屏蔽IP
|
||||
def addDropAddressApi(self):
|
||||
import re
|
||||
port = request.form.get('port', '').strip()
|
||||
ps = request.form.get('ps', '').strip()
|
||||
|
||||
rep = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
|
||||
if not re.search(rep, port):
|
||||
return public.returnJson(False, '您输入的IP地址不合法!')
|
||||
address = port
|
||||
if public.M('firewall').where("port=?", (address,)).count() > 0:
|
||||
return public.returnJson(False, '您要放屏蔽的IP已存在屏蔽列表,无需重复处理!')
|
||||
if self.__isUfw:
|
||||
public.execShell('ufw deny from ' + address + ' to any')
|
||||
else:
|
||||
if self.__isFirewalld:
|
||||
cmd = 'firewall-cmd --permanent --add-rich-rule=\'rule family=ipv4 source address="' + \
|
||||
address + '" drop\''
|
||||
public.execShell(cmd)
|
||||
else:
|
||||
cmd = 'iptables -I INPUT -s ' + address + ' -j DROP'
|
||||
public.execShell(cmd)
|
||||
|
||||
msg = public.getInfo('屏蔽IP[{1}]成功!', (address,))
|
||||
public.writeLog("防火墙管理", msg)
|
||||
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
public.M('firewall').add('port,ps,addtime', (address, ps, addtime))
|
||||
self.firewallReload()
|
||||
return public.returnJson(True, '添加成功!')
|
||||
|
||||
# 添加放行端口
|
||||
def addAcceptPortApi(self):
|
||||
import re
|
||||
import time
|
||||
port = request.form.get('port', '').strip()
|
||||
ps = request.form.get('ps', '').strip()
|
||||
stype = request.form.get('type', '').strip()
|
||||
|
||||
rep = "^\d{1,5}(:\d{1,5})?$"
|
||||
if not re.search(rep, port):
|
||||
return public.returnJson(False, '端口范围不正确!')
|
||||
|
||||
if public.M('firewall').where("port=?", (port,)).count() > 0:
|
||||
return public.returnJson(False, '您要放行的端口已存在,无需重复放行!')
|
||||
|
||||
msg = public.getInfo('放行端口[{1}]成功', (port,))
|
||||
public.writeLog("防火墙管理", msg)
|
||||
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
public.M('firewall').add('port,ps,addtime', (port, ps, addtime))
|
||||
|
||||
self.addAcceptPort(port)
|
||||
self.firewallReload()
|
||||
return public.returnJson(True, '添加放行(' + port + ')端口成功!')
|
||||
|
||||
# 删除IP屏蔽
|
||||
def delDropAddressApi(self):
|
||||
port = request.form.get('port', '').strip()
|
||||
ps = request.form.get('ps', '').strip()
|
||||
sid = request.form.get('id', '').strip()
|
||||
address = port
|
||||
if self.__isUfw:
|
||||
public.execShell('ufw delete deny from ' + address + ' to any')
|
||||
else:
|
||||
if self.__isFirewalld:
|
||||
public.execShell(
|
||||
'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'')
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
|
||||
public.execShell(cmd)
|
||||
|
||||
msg = public.getInfo('解除IP[{1}]的屏蔽!', (address,))
|
||||
public.writeLog("防火墙管理", msg)
|
||||
public.M('firewall').where("id=?", (sid,)).delete()
|
||||
|
||||
self.firewallReload()
|
||||
return public.returnJson(True, '删除成功!')
|
||||
|
||||
# 删除放行端口
|
||||
def delAcceptPortApi(self):
|
||||
port = request.form.get('port', '').strip()
|
||||
sid = request.form.get('id', '').strip()
|
||||
mw_port = public.readFile('data/port.pl')
|
||||
try:
|
||||
if(port == mw_port):
|
||||
return public.returnJson(False, '失败,不能删除当前面板端口!')
|
||||
if self.__isUfw:
|
||||
public.execShell('ufw delete allow ' + port + '/tcp')
|
||||
else:
|
||||
if self.__isFirewalld:
|
||||
public.execShell(
|
||||
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
|
||||
public.execShell(
|
||||
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
|
||||
else:
|
||||
public.execShell(
|
||||
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
|
||||
msg = public.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
|
||||
public.writeLog("防火墙管理", msg)
|
||||
public.M('firewall').where("id=?", (sid,)).delete()
|
||||
|
||||
self.firewallReload()
|
||||
return public.returnJson(True, '删除成功!')
|
||||
except Exception as e:
|
||||
return public.returnJson(False, '删除失败!:' + str(e))
|
||||
|
||||
def getWwwPathApi(self):
|
||||
path = public.getLogsDir()
|
||||
return public.getJson({'path': path})
|
||||
|
||||
def getListApi(self):
|
||||
p = request.form.get('p', '1').strip()
|
||||
limit = request.form.get('limit', '10').strip()
|
||||
return self.getList(int(p), int(limit))
|
||||
|
||||
def getLogListApi(self):
|
||||
p = request.form.get('p', '1').strip()
|
||||
limit = request.form.get('limit', '10').strip()
|
||||
search = request.form.get('search', '').strip()
|
||||
return self.getLogList(int(p), int(limit), search)
|
||||
|
||||
def getSshInfoApi(self):
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = public.readFile(file)
|
||||
rep = "#*Port\s+([0-9]+)\s*\n"
|
||||
port = re.search(rep, conf).groups(0)[0]
|
||||
|
||||
isPing = True
|
||||
try:
|
||||
if public.isAppleSystem():
|
||||
isPing = True
|
||||
else:
|
||||
file = '/etc/sysctl.conf'
|
||||
conf = public.readFile(file)
|
||||
rep = "#*net\.ipv4\.icmp_echo_ignore_all\s*=\s*([0-9]+)"
|
||||
tmp = re.search(rep, conf).groups(0)[0]
|
||||
if tmp == '1':
|
||||
isPing = False
|
||||
except:
|
||||
isPing = True
|
||||
|
||||
import system_api
|
||||
panelsys = system_api.system_api()
|
||||
version = panelsys.getSystemVersion()
|
||||
if os.path.exists('/usr/bin/apt-get'):
|
||||
if os.path.exists('/etc/init.d/sshd'):
|
||||
cmd = "service sshd status | grep -P '(dead|stop)'|grep -v grep"
|
||||
status = public.execShell(cmd)
|
||||
else:
|
||||
cmd = "service ssh status | grep -P '(dead|stop)'|grep -v grep"
|
||||
status = public.execShell(cmd)
|
||||
else:
|
||||
if version.find(' 7.') != -1:
|
||||
cmd = "systemctl status sshd.service | grep 'dead'|grep -v grep"
|
||||
status = public.execShell(cmd)
|
||||
else:
|
||||
cmd = "/etc/init.d/sshd status | grep -e 'stopped' -e '已停'|grep -v grep"
|
||||
status = public.execShell(cmd)
|
||||
if len(status[0]) > 3:
|
||||
status = False
|
||||
else:
|
||||
status = True
|
||||
|
||||
data = {}
|
||||
data['port'] = port
|
||||
|
||||
data['status'] = status
|
||||
data['ping'] = isPing
|
||||
if public.isAppleSystem():
|
||||
data['firewall_status'] = False
|
||||
else:
|
||||
data['firewall_status'] = self.getFwStatus()
|
||||
return public.getJson(data)
|
||||
|
||||
def setSshPortApi(self):
|
||||
port = request.form.get('port', '1').strip()
|
||||
if int(port) < 22 or int(port) > 65535:
|
||||
return public.returnJson(False, '端口范围必需在22-65535之间!')
|
||||
|
||||
ports = ['21', '25', '80', '443', '7200', '8080', '888', '8888']
|
||||
if port in ports:
|
||||
return public.returnJson(False, '(' + port + ')' + '特殊端口不可设置!')
|
||||
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = public.readFile(file)
|
||||
|
||||
rep = "#*Port\s+([0-9]+)\s*\n"
|
||||
conf = re.sub(rep, "Port " + port + "\n", conf)
|
||||
public.writeFile(file, conf)
|
||||
|
||||
if self.__isFirewalld:
|
||||
public.execShell('setenforce 0')
|
||||
public.execShell(
|
||||
'sed -i "s#SELINUX=enforcing#SELINUX=disabled#" /etc/selinux/config')
|
||||
public.execShell("systemctl restart sshd.service")
|
||||
elif self.__isUfw:
|
||||
public.execShell('ufw allow ' + port + '/tcp')
|
||||
public.execShell("service ssh restart")
|
||||
else:
|
||||
public.execShell(
|
||||
'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
|
||||
public.execShell("/etc/init.d/sshd restart")
|
||||
|
||||
self.firewallReload()
|
||||
# public.M('firewall').where(
|
||||
# "ps=?", ('SSH远程管理服务',)).setField('port', port)
|
||||
msg = public.getInfo('改SSH端口为[{1}]成功!', port)
|
||||
public.writeLog("防火墙管理", msg)
|
||||
return public.returnJson(True, '修改成功!')
|
||||
|
||||
def setSshStatusApi(self):
|
||||
if public.isAppleSystem():
|
||||
return public.returnJson(True, '开发机不能操作!')
|
||||
|
||||
status = request.form.get('status', '1').strip()
|
||||
version = public.readFile('/etc/redhat-release')
|
||||
if int(status) == 1:
|
||||
msg = 'SSH服务已停用'
|
||||
act = 'stop'
|
||||
else:
|
||||
msg = 'SSH服务已启用'
|
||||
act = 'start'
|
||||
|
||||
if not os.path.exists('/etc/redhat-release'):
|
||||
public.execShell('service ssh ' + act)
|
||||
elif version.find(' 7.') != -1:
|
||||
public.execShell("systemctl " + act + " sshd.service")
|
||||
else:
|
||||
public.execShell("/etc/init.d/sshd " + act)
|
||||
|
||||
public.writeLog("防火墙管理", msg)
|
||||
return public.returnJson(True, '操作成功!')
|
||||
|
||||
def setPingApi(self):
|
||||
if public.isAppleSystem():
|
||||
return public.returnJson(True, '开发机不能操作!')
|
||||
|
||||
status = request.form.get('status')
|
||||
filename = '/etc/sysctl.conf'
|
||||
conf = public.readFile(filename)
|
||||
if conf.find('net.ipv4.icmp_echo') != -1:
|
||||
rep = u"net\.ipv4\.icmp_echo.*"
|
||||
conf = re.sub(rep, 'net.ipv4.icmp_echo_ignore_all=' + status, conf)
|
||||
else:
|
||||
conf += "\nnet.ipv4.icmp_echo_ignore_all=" + status
|
||||
|
||||
public.writeFile(filename, conf)
|
||||
public.execShell('sysctl -p')
|
||||
return public.returnJson(True, '设置成功!')
|
||||
|
||||
def setFwApi(self):
|
||||
if public.isAppleSystem():
|
||||
return public.returnJson(True, '开发机不能设置!')
|
||||
|
||||
status = request.form.get('status', '1')
|
||||
if status == '1':
|
||||
if self.__isUfw:
|
||||
public.execShell('/usr/sbin/ufw stop')
|
||||
return
|
||||
if self.__isFirewalld:
|
||||
public.execShell('systemctl stop firewalld.service')
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
public.execShell('/etc/init.d/iptables save')
|
||||
public.execShell('/etc/init.d/iptables stop')
|
||||
else:
|
||||
if self.__isUfw:
|
||||
public.execShell('/usr/sbin/ufw start')
|
||||
return
|
||||
if self.__isFirewalld:
|
||||
public.execShell('systemctl start firewalld.service')
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
public.execShell('/etc/init.d/iptables save')
|
||||
public.execShell('/etc/init.d/iptables restart')
|
||||
|
||||
return public.returnJson(True, '设置成功!')
|
||||
|
||||
def delPanelLogsApi(self):
|
||||
public.M('logs').where('id>?', (0,)).delete()
|
||||
public.writeLog('面板设置', '面板操作日志已清空!')
|
||||
return public.returnJson(True, '面板操作日志已清空!')
|
||||
|
||||
##### ----- start ----- ###
|
||||
|
||||
def getList(self, page, limit):
|
||||
|
||||
@@ -54,3 +354,51 @@ class firewall_api:
|
||||
|
||||
data['page'] = public.getPage(_page)
|
||||
return public.getJson(data)
|
||||
|
||||
def addAcceptPort(self, port):
|
||||
if self.__isUfw:
|
||||
public.execShell('ufw allow ' + port + '/tcp')
|
||||
else:
|
||||
if self.__isFirewalld:
|
||||
port = port.replace(':', '-')
|
||||
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
|
||||
public.execShell(cmd)
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
|
||||
public.execShell(cmd)
|
||||
|
||||
def firewallReload(self):
|
||||
if self.__isUfw:
|
||||
public.execShell('/usr/sbin/ufw reload')
|
||||
return
|
||||
if self.__isFirewalld:
|
||||
public.execShell('firewall-cmd --reload')
|
||||
elif self.__isMac:
|
||||
pass
|
||||
else:
|
||||
public.execShell('/etc/init.d/iptables save')
|
||||
public.execShell('/etc/init.d/iptables restart')
|
||||
|
||||
def getFwStatus(self):
|
||||
if self.__isUfw:
|
||||
cmd = "ps -ef|grep ufw |grep -v grep | awk '{print $2}'"
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return False
|
||||
return True
|
||||
if self.__isFirewalld:
|
||||
cmd = "ps -ef|grep firewalld |grep -v grep | awk '{print $2}'"
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return False
|
||||
return True
|
||||
elif self.__isMac:
|
||||
return False
|
||||
else:
|
||||
cmd = "ps -ef|grep iptables |grep -v grep | awk '{print $2}'"
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -29,8 +29,8 @@ class Page():
|
||||
__END_NUM = None # 结束行
|
||||
|
||||
def __init__(self):
|
||||
tmp = public.getMsg('PAGE')
|
||||
if tmp:
|
||||
# tmp = public.getMsg('PAGE')
|
||||
if False:
|
||||
self.__PREV = tmp['PREV']
|
||||
self.__NEXT = tmp['NEXT']
|
||||
self.__START = tmp['START']
|
||||
|
||||
@@ -7,10 +7,17 @@ import public
|
||||
import re
|
||||
import json
|
||||
|
||||
import sys
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf8')
|
||||
|
||||
import threading
|
||||
import multiprocessing
|
||||
|
||||
|
||||
from flask import request
|
||||
|
||||
|
||||
class pa_thread(threading.Thread):
|
||||
|
||||
def __init__(self, func, args, name=''):
|
||||
@@ -27,7 +34,7 @@ class pa_thread(threading.Thread):
|
||||
return None
|
||||
|
||||
|
||||
class plugin_api:
|
||||
class plugins_api:
|
||||
__tasks = None
|
||||
__plugin_dir = 'plugins'
|
||||
__type = 'data/json/type.json'
|
||||
@@ -36,7 +43,212 @@ class plugin_api:
|
||||
|
||||
def __init__(self):
|
||||
self.setupPath = 'server'
|
||||
# self.__plugin_dir = public.getRunDir() + '/plugins'
|
||||
|
||||
##### ----- start ----- ###
|
||||
def listApi(self):
|
||||
sType = request.args.get('type', '0')
|
||||
sPage = request.args.get('p', '1')
|
||||
# print sPage
|
||||
data = self.getPluginList(sType, int(sPage))
|
||||
return public.getJson(data)
|
||||
|
||||
def fileApi(self):
|
||||
name = request.args.get('name', '')
|
||||
if name.strip() == '':
|
||||
return ''
|
||||
|
||||
f = request.args.get('f', '')
|
||||
if f.strip() == '':
|
||||
return ''
|
||||
|
||||
file = self.__plugin_dir + '/' + name + '/' + f
|
||||
if not os.path.exists(file):
|
||||
return ''
|
||||
|
||||
c = public.readFile(file)
|
||||
return c
|
||||
|
||||
def indexListApi(self):
|
||||
data = self.getIndexList()
|
||||
return public.getJson(data)
|
||||
|
||||
def indexSortApi(self):
|
||||
sort = request.form.get('ssort', '')
|
||||
if sort.strip() == '':
|
||||
return public.returnJson(False, '排序数据不能为空!')
|
||||
data = self.setIndexSort(sort)
|
||||
if data:
|
||||
return public.returnJson(True, '成功!')
|
||||
return public.returnJson(False, '失败!')
|
||||
|
||||
def installApi(self):
|
||||
rundir = public.getRunDir()
|
||||
name = request.form.get('name', '')
|
||||
version = request.form.get('version', '')
|
||||
|
||||
mmsg = '安装'
|
||||
if hasattr(request.form, 'upgrade'):
|
||||
mtype = 'update'
|
||||
mmsg = 'upgrade'
|
||||
|
||||
if name.strip() == '':
|
||||
return public.returnJson(False, '缺少插件名称!', ())
|
||||
|
||||
if version.strip() == '':
|
||||
return public.returnJson(False, '缺少版本信息!', ())
|
||||
|
||||
infoJsonPos = self.__plugin_dir + '/' + name + '/' + 'info.json'
|
||||
print infoJsonPos
|
||||
|
||||
if not os.path.exists(infoJsonPos):
|
||||
return public.retJson(False, '配置文件不存在!', ())
|
||||
|
||||
pluginInfo = json.loads(public.readFile(infoJsonPos))
|
||||
|
||||
execstr = "cd " + os.getcwd() + "/plugins/" + \
|
||||
name + " && /bin/bash " + pluginInfo["shell"] \
|
||||
+ " install " + version
|
||||
|
||||
taskAdd = (None, mmsg + '[' + name + '-' + version + ']',
|
||||
'execshell', '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, '已将安装任务添加到队列!')
|
||||
|
||||
def uninstallApi(self):
|
||||
rundir = public.getRunDir()
|
||||
name = request.form.get('name', '')
|
||||
version = request.form.get('version', '')
|
||||
if name.strip() == '':
|
||||
return public.returnJson(False, "缺少插件名称!", ())
|
||||
|
||||
if version.strip() == '':
|
||||
return public.returnJson(False, "缺少版本信息!", ())
|
||||
|
||||
infoJsonPos = self.__plugin_dir + '/' + name + '/' + 'info.json'
|
||||
|
||||
if not os.path.exists(infoJsonPos):
|
||||
return public.retJson(False, "配置文件不存在!", ())
|
||||
|
||||
pluginInfo = json.loads(public.readFile(infoJsonPos))
|
||||
|
||||
execstr = "cd " + os.getcwd() + "/plugins/" + \
|
||||
name + " && /bin/bash " + pluginInfo["shell"] \
|
||||
+ " uninstall " + version
|
||||
|
||||
taskAdd = (None, '卸载[' + name + '-' + version + ']',
|
||||
'execshell', '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, '已将卸载任务添加到队列!')
|
||||
|
||||
def checkApi(self):
|
||||
name = request.form.get('name', '')
|
||||
if name.strip() == '':
|
||||
return public.returnJson(False, "缺少插件名称!", ())
|
||||
|
||||
infoJsonPos = self.__plugin_dir + '/' + name + '/' + 'info.json'
|
||||
if not os.path.exists(infoJsonPos):
|
||||
return public.returnJson(False, "配置文件不存在!", ())
|
||||
return public.returnJson(True, "插件存在!", ())
|
||||
|
||||
def setIndexApi(self):
|
||||
name = request.form.get('name', '')
|
||||
status = request.form.get('status', '0')
|
||||
version = request.form.get('version', '')
|
||||
if status == '1':
|
||||
return self.addIndex(name, version)
|
||||
return self.removeIndex(name, version)
|
||||
|
||||
def settingApi(self):
|
||||
name = request.args.get('name', '')
|
||||
html = self.__plugin_dir + '/' + name + '/index.html'
|
||||
return public.readFile(html)
|
||||
|
||||
def runApi(self):
|
||||
name = request.form.get('name', '')
|
||||
func = request.form.get('func', '')
|
||||
version = request.form.get('version', '')
|
||||
args = request.form.get('args', '')
|
||||
script = request.form.get('script', 'index')
|
||||
|
||||
data = self.run(name, func, version, args, script)
|
||||
if data[1] == '':
|
||||
return public.returnJson(True, "OK", data[0].strip())
|
||||
return public.returnJson(False, data[1].strip())
|
||||
|
||||
def updateZipApi(self):
|
||||
tmp_path = public.getRootDir() + '/temp'
|
||||
if not os.path.exists(tmp_path):
|
||||
os.makedirs(tmp_path)
|
||||
public.execShell("rm -rf " + tmp_path + '/*')
|
||||
|
||||
tmp_file = tmp_path + '/plugin_tmp.zip'
|
||||
from werkzeug.utils import secure_filename
|
||||
from flask import request
|
||||
f = request.files['plugin_zip']
|
||||
if f.filename[-4:] != '.zip':
|
||||
return public.returnJson(False, '仅支持zip文件!')
|
||||
f.save(tmp_file)
|
||||
public.execShell('cd ' + tmp_path + ' && unzip ' + tmp_file)
|
||||
os.remove(tmp_file)
|
||||
|
||||
p_info = tmp_path + '/info.json'
|
||||
if not os.path.exists(p_info):
|
||||
d_path = None
|
||||
for df in os.walk(tmp_path):
|
||||
if len(df[2]) < 3:
|
||||
continue
|
||||
if not 'info.json' in df[2]:
|
||||
continue
|
||||
if not 'install.sh' in df[2]:
|
||||
continue
|
||||
if not os.path.exists(df[0] + '/info.json'):
|
||||
continue
|
||||
d_path = df[0]
|
||||
if d_path:
|
||||
tmp_path = d_path
|
||||
p_info = tmp_path + '/info.json'
|
||||
try:
|
||||
data = json.loads(public.readFile(p_info))
|
||||
data['size'] = public.getPathSize(tmp_path)
|
||||
if not 'author' in data:
|
||||
data['author'] = '未知'
|
||||
if not 'home' in data:
|
||||
data['home'] = 'https://www.bt.cn/bbs/forum-40-1.html'
|
||||
plugin_path = public.getPluginDir() + data['name'] + '/info.json'
|
||||
data['old_version'] = '0'
|
||||
data['tmp_path'] = tmp_path
|
||||
if os.path.exists(plugin_path):
|
||||
try:
|
||||
old_info = json.loads(public.ReadFile(plugin_path))
|
||||
data['old_version'] = old_info['versions']
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
public.execShell("rm -rf " + tmp_path)
|
||||
return public.returnJson(False, '在压缩包中没有找到插件信息,请检查插件包!')
|
||||
return public.getJson(data)
|
||||
|
||||
def inputZipApi(self):
|
||||
plugin_name = request.form.get('plugin_name', '')
|
||||
tmp_path = request.form.get('tmp_path', '')
|
||||
|
||||
if not os.path.exists(tmp_path):
|
||||
return public.returnJson(False, '临时文件不存在,请重新上传!')
|
||||
plugin_path = public.getPluginDir() + '/' + plugin_name
|
||||
if not os.path.exists(plugin_path):
|
||||
print public.execShell('mkdir -p ' + plugin_path)
|
||||
public.execShell("\cp -rf " + tmp_path + '/* ' + plugin_path + '/')
|
||||
public.execShell('chmod -R 755 ' + plugin_path)
|
||||
p_info = public.readFile(plugin_path + '/info.json')
|
||||
if p_info:
|
||||
public.writeLog('软件管理', '安装第三方插件[%s]' %
|
||||
json.loads(p_info)['title'])
|
||||
return public.returnJson(True, '安装成功!')
|
||||
public.execShell("rm -rf " + plugin_path)
|
||||
return public.returnJson(False, '安装失败!')
|
||||
##### ----- end ----- ###
|
||||
|
||||
# 进程是否存在
|
||||
def processExists(self, pname, exe=None):
|
||||
@@ -60,6 +272,8 @@ class plugin_api:
|
||||
|
||||
# 检查是否正在安装
|
||||
def checkSetupTask(self, sName):
|
||||
sName = ''
|
||||
version = ''
|
||||
if not self.__tasks:
|
||||
self.__tasks = public.M('tasks').where(
|
||||
"status!=?", ('1',)).field('status,name').select()
|
||||
@@ -86,7 +300,6 @@ class plugin_api:
|
||||
return isTask
|
||||
|
||||
def checkStatus(self, info):
|
||||
|
||||
if not info['setup']:
|
||||
return False
|
||||
|
||||
@@ -96,7 +309,6 @@ class plugin_api:
|
||||
return False
|
||||
|
||||
def checkStatusProcess(self, info, i, return_dict):
|
||||
|
||||
if not info['setup']:
|
||||
return_dict[i] = False
|
||||
return
|
||||
@@ -107,12 +319,41 @@ class plugin_api:
|
||||
else:
|
||||
return_dict[i] = False
|
||||
|
||||
def checkStatusThreads(self, info, i):
|
||||
if not info['setup']:
|
||||
return False
|
||||
data = self.run(info['name'], 'status', info['setup_version'])
|
||||
if data[0] == 'start':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def checkStatusMThreads(self, plugins_info):
|
||||
try:
|
||||
threads = []
|
||||
ntmp_list = range(len(plugins_info))
|
||||
for i in ntmp_list:
|
||||
t = pa_thread(self.checkStatusThreads, (plugins_info[i], i))
|
||||
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()
|
||||
plugins_info[i]['status'] = t
|
||||
except Exception as e:
|
||||
print 'checkStatusMThreads:', str(e)
|
||||
|
||||
return plugins_info
|
||||
|
||||
def checkStatusMProcess(self, plugins_info):
|
||||
manager = multiprocessing.Manager()
|
||||
return_dict = manager.dict()
|
||||
jobs = []
|
||||
ntmp_list = range(len(plugins_info))
|
||||
for i in ntmp_list:
|
||||
for i in range(len(plugins_info)):
|
||||
p = multiprocessing.Process(
|
||||
target=self.checkStatusProcess, args=(plugins_info[i], i, return_dict))
|
||||
jobs.append(p)
|
||||
@@ -211,6 +452,7 @@ class plugin_api:
|
||||
pluginInfo['setup_version'] = self.getVersion(
|
||||
pluginInfo['install_checks'])
|
||||
# pluginInfo['status'] = self.checkStatus(pluginInfo)
|
||||
pluginInfo['status'] = False
|
||||
return pluginInfo
|
||||
|
||||
def makeCoexist(self, data):
|
||||
@@ -289,7 +531,7 @@ class plugin_api:
|
||||
end = start + pageSize
|
||||
_plugins_info = plugins_info[start:end]
|
||||
|
||||
_plugins_info = self.checkStatusMProcess(_plugins_info)
|
||||
_plugins_info = self.checkStatusMThreads(_plugins_info)
|
||||
return (_plugins_info, len(plugins_info))
|
||||
|
||||
def makeListThread(self, data, sType='0'):
|
||||
@@ -414,6 +656,7 @@ class plugin_api:
|
||||
return plugins_info
|
||||
|
||||
def getPluginList(self, sType, sPage=1, sPageSize=10):
|
||||
# print sType, sPage, sPageSize
|
||||
|
||||
ret = {}
|
||||
ret['type'] = json.loads(public.readFile(self.__type))
|
||||
@@ -436,7 +679,6 @@ class plugin_api:
|
||||
public.writeFile(self.__index, '[]')
|
||||
|
||||
indexList = json.loads(public.readFile(self.__index))
|
||||
|
||||
plist = []
|
||||
app = []
|
||||
for i in indexList:
|
||||
@@ -456,9 +698,11 @@ class plugin_api:
|
||||
plist.append(tmp_data[index])
|
||||
continue
|
||||
except Exception, e:
|
||||
print e
|
||||
print 'getIndexList:', e
|
||||
|
||||
plist = self.checkStatusMProcess(plist)
|
||||
# 使用gevent模式时,无法使用多进程
|
||||
# plist = self.checkStatusMProcess(plist)
|
||||
plist = self.checkStatusMThreads(plist)
|
||||
return plist
|
||||
|
||||
def setIndexSort(self, sort):
|
||||
@@ -498,6 +742,7 @@ class plugin_api:
|
||||
path = public.getRunDir() + '/' + self.__plugin_dir + \
|
||||
'/' + name + '/' + script + '.py'
|
||||
py = 'python ' + path
|
||||
|
||||
if args == '':
|
||||
py_cmd = py + ' ' + func + ' ' + version
|
||||
else:
|
||||
@@ -506,7 +751,9 @@ class plugin_api:
|
||||
if not os.path.exists(path):
|
||||
return ('', '')
|
||||
data = public.execShell(py_cmd)
|
||||
# data = os.popen(py_cmd).read()
|
||||
|
||||
print py_cmd
|
||||
if public.isAppleSystem():
|
||||
print py_cmd
|
||||
# print os.path.exists(py_cmd)
|
||||
return (data[0].strip(), data[1].strip())
|
||||
@@ -55,16 +55,32 @@ def getServerDir():
|
||||
|
||||
|
||||
def getWwwDir():
|
||||
file = getRunDir() + '/data/site.pl'
|
||||
if os.path.exists(file):
|
||||
return readFile(file).strip()
|
||||
return getRootDir() + '/wwwroot'
|
||||
|
||||
|
||||
def setWwwDir(wdir):
|
||||
file = getRunDir() + '/data/site.pl'
|
||||
return writeFile(file, wdir)
|
||||
|
||||
|
||||
def getLogsDir():
|
||||
return getRootDir() + '/wwwlogs'
|
||||
|
||||
|
||||
def getBackupDir():
|
||||
return getRootDir() + '/backup'
|
||||
|
||||
|
||||
def setBackupDir(bdir):
|
||||
file = getRunDir() + '/data/backup.pl'
|
||||
return writeFile(file, bdir)
|
||||
|
||||
|
||||
def getOs():
|
||||
os = execShell('uname')
|
||||
return os[0].lower().strip()
|
||||
return sys.platform
|
||||
|
||||
|
||||
def isAppleSystem():
|
||||
@@ -73,6 +89,11 @@ def isAppleSystem():
|
||||
return False
|
||||
|
||||
|
||||
def deleteFile(file):
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
|
||||
|
||||
def isInstalledWeb():
|
||||
path = getServerDir() + '/openresty/nginx/sbin/nginx'
|
||||
if os.path.exists(path):
|
||||
@@ -86,6 +107,24 @@ def restartWeb():
|
||||
execShell(initd + ' ' + 'reload')
|
||||
|
||||
|
||||
def restartMw():
|
||||
import system_api
|
||||
system_api.system_api().restartMw()
|
||||
|
||||
|
||||
def checkWebConfig():
|
||||
op_dir = getServerDir() + '/openresty'
|
||||
cmd = "ulimit -n 10240 && " + op_dir + \
|
||||
"/nginx/sbin/nginx -t -c " + op_dir + "/nginx/conf/nginx.conf"
|
||||
result = execShell(cmd)
|
||||
searchStr = 'successful'
|
||||
if result[1].find(searchStr) == -1:
|
||||
msg = getInfo('配置文件错误: {1}', (result[1],))
|
||||
writeLog("软件管理", msg)
|
||||
return result[1]
|
||||
return True
|
||||
|
||||
|
||||
def M(table):
|
||||
sql = db.Sql()
|
||||
return sql.table(table)
|
||||
@@ -164,9 +203,17 @@ def getJson(data):
|
||||
return json.dumps(data)
|
||||
|
||||
|
||||
def returnJson(status, msg, args=()):
|
||||
# 取通用Json返回
|
||||
return getJson(returnMsg(status, msg, args))
|
||||
def returnData(status, msg, data=None):
|
||||
return {'status': status, 'msg': msg, 'data': data}
|
||||
|
||||
|
||||
def returnJson(status, msg, data=None):
|
||||
# if data == None:
|
||||
# return {'status': status, 'msg': msg}
|
||||
# return {'status': status, 'msg': msg, 'data': data}
|
||||
if data == None:
|
||||
return getJson({'status': status, 'msg': msg})
|
||||
return getJson({'status': status, 'msg': msg, 'data': data})
|
||||
|
||||
|
||||
def returnMsg(status, msg, args=()):
|
||||
@@ -249,22 +296,12 @@ def writeLog(type, logMsg, args=()):
|
||||
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
|
||||
except Exception as e:
|
||||
print e
|
||||
|
||||
|
||||
def writeFile(filename, str):
|
||||
@@ -278,39 +315,100 @@ def writeFile(filename, str):
|
||||
return False
|
||||
|
||||
|
||||
def httpGet(url, timeout=30):
|
||||
# 发送GET请求
|
||||
try:
|
||||
import urllib2
|
||||
import ssl
|
||||
def HttpGet(url, timeout=10):
|
||||
"""
|
||||
发送GET请求
|
||||
@url 被请求的URL地址(必需)
|
||||
@timeout 超时时间默认60秒
|
||||
return string
|
||||
"""
|
||||
if sys.version_info[0] == 2:
|
||||
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)
|
||||
import urllib2
|
||||
import ssl
|
||||
if sys.version_info[0] == 2:
|
||||
reload(urllib2)
|
||||
reload(ssl)
|
||||
try:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except:
|
||||
pass
|
||||
response = urllib2.urlopen(url, timeout=timeout)
|
||||
return response.read()
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
else:
|
||||
try:
|
||||
import urllib.request
|
||||
import ssl
|
||||
try:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except:
|
||||
pass
|
||||
response = urllib.request.urlopen(url, timeout=timeout)
|
||||
result = response.read()
|
||||
if type(result) == bytes:
|
||||
result = result.decode('utf-8')
|
||||
return result
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
|
||||
|
||||
def httpPost(url, data, timeout=30):
|
||||
# 发送POST请求
|
||||
try:
|
||||
import urllib
|
||||
import urllib2
|
||||
import ssl
|
||||
def HttpGet2(url, timeout):
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
req = urllib2.Request(url)
|
||||
res = urllib2.urlopen(req, timeout=timeout)
|
||||
result = res.read()
|
||||
return result
|
||||
|
||||
|
||||
def httpGet(url, timeout=10):
|
||||
return HttpGet2(url, timeout)
|
||||
|
||||
|
||||
def HttpPost(url, data, timeout=10):
|
||||
"""
|
||||
发送POST请求
|
||||
@url 被请求的URL地址(必需)
|
||||
@data POST参数,可以是字符串或字典(必需)
|
||||
@timeout 超时时间默认60秒
|
||||
return string
|
||||
"""
|
||||
if sys.version_info[0] == 2:
|
||||
try:
|
||||
import urllib
|
||||
import urllib2
|
||||
import ssl
|
||||
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)
|
||||
data = urllib.urlencode(data)
|
||||
req = urllib2.Request(url, data)
|
||||
response = urllib2.urlopen(req, timeout=timeout)
|
||||
return response.read()
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
else:
|
||||
try:
|
||||
import urllib.request
|
||||
import ssl
|
||||
try:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except:
|
||||
pass
|
||||
data = urllib.parse.urlencode(data).encode('utf-8')
|
||||
req = urllib.request.Request(url, data)
|
||||
response = urllib.request.urlopen(req, timeout=timeout)
|
||||
result = response.read()
|
||||
if type(result) == bytes:
|
||||
result = result.decode('utf-8')
|
||||
return result
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
|
||||
|
||||
def httpPost(url, data, timeout=10):
|
||||
return HttpPost(url, data, timeout)
|
||||
|
||||
|
||||
def writeSpeed(title, used, total, speed=0):
|
||||
@@ -328,11 +426,12 @@ def writeSpeed(title, used, total, speed=0):
|
||||
|
||||
def getSpeed():
|
||||
# 取进度
|
||||
data = readFile('/tmp/panelSpeed.pl')
|
||||
path = public.getRootDir()
|
||||
data = readFile(path + '/tmp/panelSpeed.pl')
|
||||
if not data:
|
||||
data = json.dumps({'title': None, 'progress': 0,
|
||||
'total': 0, 'used': 0, 'speed': 0})
|
||||
writeFile('/tmp/panelSpeed.pl', data)
|
||||
writeFile(path + '/tmp/panelSpeed.pl', data)
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
@@ -367,6 +466,59 @@ def getLastLine(inputfile, lineNum):
|
||||
return getMsg('TASK_SLEEP')
|
||||
|
||||
|
||||
def getNumLines(path, num, p=1):
|
||||
pyVersion = sys.version_info[0]
|
||||
try:
|
||||
import cgi
|
||||
if not os.path.exists(path):
|
||||
return ""
|
||||
start_line = (p - 1) * num
|
||||
count = start_line + num
|
||||
fp = open(path, 'rb')
|
||||
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 = str.rfind(str(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)
|
||||
t_buf = fp.read(to_read)
|
||||
if pyVersion == 3:
|
||||
if type(t_buf) == bytes:
|
||||
t_buf = t_buf.decode('utf-8')
|
||||
buf = t_buf + buf
|
||||
fp.seek(-to_read, 1)
|
||||
if pos - to_read == 0:
|
||||
buf = "\n" + buf
|
||||
if not b:
|
||||
break
|
||||
fp.close()
|
||||
except Exception as e:
|
||||
return ''
|
||||
|
||||
return "\n".join(data)
|
||||
|
||||
|
||||
def downloadFile(url, filename):
|
||||
import urllib
|
||||
urllib.urlretrieve(url, filename=filename, reporthook=downloadHook)
|
||||
@@ -420,7 +572,7 @@ def checkIp(ip):
|
||||
|
||||
def checkPort(port):
|
||||
# 检查端口是否合法
|
||||
ports = ['21', '25', '443', '8080', '888', '8888', '8443']
|
||||
ports = ['21', '25', '443', '7200', '8080', '888', '8888', '8443']
|
||||
if port in ports:
|
||||
return False
|
||||
intport = int(port)
|
||||
@@ -488,6 +640,54 @@ def getTimeout(url):
|
||||
return int((time.time() - start) * 1000)
|
||||
|
||||
|
||||
def makeConf():
|
||||
file = getRunDir() + '/data/json/config.json'
|
||||
if not os.path.exists(file):
|
||||
c = {}
|
||||
c['title'] = 'Linux面板'
|
||||
c['home'] = 'http://github/midoks/mdserver-web'
|
||||
c['recycle_bin'] = True
|
||||
c['template'] = 'default'
|
||||
writeFile(file, json.dumps(c))
|
||||
return c
|
||||
c = readFile(file)
|
||||
return json.loads(c)
|
||||
|
||||
|
||||
def getConfig(k):
|
||||
c = makeConf()
|
||||
return c[k]
|
||||
|
||||
|
||||
def setConfig(k, v):
|
||||
c = makeConf()
|
||||
c[k] = v
|
||||
file = getRunDir() + '/data/json/config.json'
|
||||
return writeFile(file, json.dumps(c))
|
||||
|
||||
|
||||
def getHostAddr():
|
||||
if os.path.exists('data/iplist.txt'):
|
||||
return readFile('data/iplist.txt').strip()
|
||||
return '127.0.0.1'
|
||||
|
||||
|
||||
def setHostAddr(addr):
|
||||
file = getRunDir() + '/data/iplist.txt'
|
||||
return writeFile(file, addr)
|
||||
|
||||
|
||||
def getHostPort():
|
||||
if os.path.exists('data/port.pl'):
|
||||
return readFile('data/port.pl').strip()
|
||||
return '7200'
|
||||
|
||||
|
||||
def setHostPort(port):
|
||||
file = getRunDir() + '/data/port.pl'
|
||||
return writeFile(file, port)
|
||||
|
||||
|
||||
def auth_decode(data):
|
||||
# 解密数据
|
||||
token = GetToken()
|
||||
@@ -581,54 +781,6 @@ def checkInput(data):
|
||||
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'
|
||||
@@ -651,18 +803,19 @@ def checkCert(certPath='ssl/certificate.pem'):
|
||||
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 getPathSize(path):
|
||||
# 取文件或目录大小
|
||||
if not os.path.exists(path):
|
||||
return 0
|
||||
if not os.path.isdir(path):
|
||||
return os.path.getsize(path)
|
||||
size_total = 0
|
||||
for nf in os.walk(path):
|
||||
for f in nf[2]:
|
||||
filename = nf[0] + '/' + f
|
||||
size_total += os.path.getsize(filename)
|
||||
return size_total
|
||||
|
||||
|
||||
def toSize(size):
|
||||
@@ -671,10 +824,10 @@ def toSize(size):
|
||||
s = d[0]
|
||||
for b in d:
|
||||
if size < 1024:
|
||||
return str(size) + ' ' + b
|
||||
size = size / 1024
|
||||
return str(round(size, 2)) + ' ' + b
|
||||
size = float(size) / 1024.0
|
||||
s = b
|
||||
return str(size) + ' ' + b
|
||||
return str(round(size, 2)) + ' ' + b
|
||||
|
||||
|
||||
def getMacAddress():
|
||||
@@ -721,3 +874,34 @@ def get_string_arr(t):
|
||||
if s1 == s_arr[i][j]:
|
||||
t_arr.append(str(i) + str(j))
|
||||
return t_arr
|
||||
|
||||
|
||||
def getSSHPort():
|
||||
try:
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = ReadFile(file)
|
||||
rep = "#*Port\s+([0-9]+)\s*\n"
|
||||
port = re.search(rep, conf).groups(0)[0]
|
||||
return int(port)
|
||||
except:
|
||||
return 22
|
||||
|
||||
|
||||
def getSSHStatus():
|
||||
if os.path.exists('/usr/bin/apt-get'):
|
||||
status = execShell("service ssh status | grep -P '(dead|stop)'")
|
||||
else:
|
||||
import system_api
|
||||
version = system_api.system_api().getSystemVersion()
|
||||
if version.find(' Mac ') != -1:
|
||||
return True
|
||||
if version.find(' 7.') != -1:
|
||||
status = execShell("systemctl status sshd.service | grep 'dead'")
|
||||
else:
|
||||
status = execShell(
|
||||
"/etc/init.d/sshd status | grep -e 'stopped' -e '已停'")
|
||||
if len(status[0]) > 3:
|
||||
status = False
|
||||
else:
|
||||
status = True
|
||||
return status
|
||||
|
||||
@@ -8,10 +8,22 @@ import math
|
||||
import json
|
||||
|
||||
from flask import Flask, session
|
||||
from flask import request
|
||||
|
||||
import db
|
||||
import public
|
||||
import config
|
||||
import config_api
|
||||
|
||||
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
|
||||
|
||||
def async(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
thr = Thread(target=f, args=args, kwargs=kwargs)
|
||||
thr.start()
|
||||
return wrapper
|
||||
|
||||
|
||||
class system_api:
|
||||
@@ -21,7 +33,87 @@ class system_api:
|
||||
def __init__(self):
|
||||
self.setupPath = public.getServerDir()
|
||||
|
||||
# 名取PID
|
||||
##### ----- start ----- ###
|
||||
def networkApi(self):
|
||||
data = self.getNetWork()
|
||||
return public.getJson(data)
|
||||
|
||||
def updateServerApi(self):
|
||||
stype = request.args.get('type', 'check')
|
||||
version = request.args.get('version', '')
|
||||
return self.updateServer(stype, version)
|
||||
|
||||
def systemTotalApi(self):
|
||||
data = self.getSystemTotal()
|
||||
return public.getJson(data)
|
||||
|
||||
def diskInfoApi(self):
|
||||
diskInfo = self.getDiskInfo()
|
||||
return public.getJson(diskInfo)
|
||||
|
||||
def setControlApi(self):
|
||||
stype = request.form.get('type', '')
|
||||
day = request.form.get('day', '')
|
||||
data = self.setControl(stype, day)
|
||||
return data
|
||||
|
||||
def getLoadAverageApi(self):
|
||||
start = request.args.get('start', '')
|
||||
end = request.args.get('end', '')
|
||||
data = self.getLoadAverageData(start, end)
|
||||
return public.getJson(data)
|
||||
|
||||
def getCpuIoApi(self):
|
||||
start = request.args.get('start', '')
|
||||
end = request.args.get('end', '')
|
||||
data = self.getCpuIoData(start, end)
|
||||
return public.getJson(data)
|
||||
|
||||
def getDiskIoApi(self):
|
||||
start = request.args.get('start', '')
|
||||
end = request.args.get('end', '')
|
||||
data = self.getDiskIoData(start, end)
|
||||
return public.getJson(data)
|
||||
|
||||
def getNetworkIoApi(self):
|
||||
start = request.args.get('start', '')
|
||||
end = request.args.get('end', '')
|
||||
data = self.getNetWorkIoData(start, end)
|
||||
return public.getJson(data)
|
||||
|
||||
def rememoryApi(self):
|
||||
os.system('sync')
|
||||
scriptFile = public.getRunDir() + '/script/rememory.sh'
|
||||
public.execShell("/bin/bash " + scriptFile)
|
||||
data = self.getMemInfo()
|
||||
return public.getJson(data)
|
||||
|
||||
# 重启面板
|
||||
def restartApi(self):
|
||||
self.restartMw()
|
||||
return public.returnJson(True, '面板已重启!')
|
||||
|
||||
def restartServerApi(self):
|
||||
if public.isAppleSystem():
|
||||
return public.returnJson(False, "开发环境不可重起")
|
||||
self.restartServer()
|
||||
return public.returnJson(True, '正在重启服务器!')
|
||||
##### ----- end ----- ###
|
||||
|
||||
@async
|
||||
def restartMw(self):
|
||||
sleep(1)
|
||||
cmd = public.getRunDir() + '/scripts/init.d/mw reload'
|
||||
public.execShell(cmd)
|
||||
|
||||
@async
|
||||
def restartServer(self):
|
||||
if not public.isRestart():
|
||||
return public.returnJson(False, '请等待所有安装任务完成再执行!')
|
||||
public.execShell("sync && init 6 &")
|
||||
return public.returnJson(True, '命令发送成功!')
|
||||
|
||||
# 名取PID
|
||||
def getPid(self, pname):
|
||||
try:
|
||||
if not self.pids:
|
||||
@@ -100,7 +192,7 @@ class system_api:
|
||||
data['version'] = '0.0.1'
|
||||
return data
|
||||
|
||||
def getLoadAverage(self, get=None):
|
||||
def getLoadAverage(self):
|
||||
c = os.getloadavg()
|
||||
data = {}
|
||||
data['one'] = float(c[0])
|
||||
@@ -117,7 +209,7 @@ class system_api:
|
||||
data['title'] = self.GetTitle()
|
||||
data['network'] = self.GetNetWorkApi(get)
|
||||
data['panel_status'] = not os.path.exists(
|
||||
'/www/server/panel/data/close.pl')
|
||||
'/www/server/mdserver-web/data/close.pl')
|
||||
import firewalls
|
||||
ssh_info = firewalls.firewalls().GetSshInfo(None)
|
||||
data['enable_ssh_status'] = ssh_info['status']
|
||||
@@ -130,15 +222,14 @@ class system_api:
|
||||
|
||||
def getTitle(self):
|
||||
titlePl = 'data/title.pl'
|
||||
title = '宝塔Linux面板'
|
||||
title = 'Linux面板'
|
||||
if os.path.exists(titlePl):
|
||||
title = public.readFile(titlePl).strip()
|
||||
return title
|
||||
|
||||
def getSystemVersion(self):
|
||||
# 取操作系统版本
|
||||
os = public.getOs()
|
||||
if os == 'darwin':
|
||||
if public.getOs() == 'darwin':
|
||||
data = public.execShell('sw_vers')[0]
|
||||
data_list = data.strip().split("\n")
|
||||
mac_version = ''
|
||||
@@ -173,7 +264,7 @@ class system_api:
|
||||
used = psutil.cpu_percent(interval=interval)
|
||||
return used, cpuCount
|
||||
|
||||
def getMemInfo(self, get=None):
|
||||
def getMemInfo(self):
|
||||
# 取内存信息
|
||||
mem = psutil.virtual_memory()
|
||||
if public.getOs() == 'darwin':
|
||||
@@ -312,10 +403,10 @@ class system_api:
|
||||
# 清理其它
|
||||
def clearOther(self):
|
||||
clearPath = [
|
||||
{'path': '/www/server/panel', 'find': 'testDisk_'},
|
||||
{'path': '/www/server/mdserver-web', 'find': 'testDisk_'},
|
||||
{'path': '/www/wwwlogs', 'find': 'log'},
|
||||
{'path': '/tmp', 'find': 'panelBoot.pl'},
|
||||
{'path': '/www/server/panel/install', 'find': '.rpm'}
|
||||
{'path': '/www/server/mdserver-web/install', 'find': '.rpm'}
|
||||
]
|
||||
|
||||
total = count = 0
|
||||
@@ -335,7 +426,7 @@ class system_api:
|
||||
os.system('echo > /tmp/panelBoot.pl')
|
||||
return total, count
|
||||
|
||||
def getNetWork(self, get=None):
|
||||
def getNetWork(self):
|
||||
# return self.GetNetWorkApi(get);
|
||||
# 取网络流量信息
|
||||
try:
|
||||
@@ -363,15 +454,15 @@ class system_api:
|
||||
session['otime'] = time.time()
|
||||
|
||||
networkInfo['cpu'] = self.getCpuInfo()
|
||||
networkInfo['load'] = self.getLoadAverage(get)
|
||||
networkInfo['mem'] = self.getMemInfo(get)
|
||||
networkInfo['load'] = self.getLoadAverage()
|
||||
networkInfo['mem'] = self.getMemInfo()
|
||||
|
||||
return networkInfo
|
||||
except Exception, e:
|
||||
print e
|
||||
return None
|
||||
|
||||
def getNetWorkApi(self, get=None):
|
||||
def getNetWorkApi(self):
|
||||
# 取网络流量信息
|
||||
try:
|
||||
tmpfile = 'data/network.temp'
|
||||
@@ -402,23 +493,6 @@ class system_api:
|
||||
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(
|
||||
@@ -537,40 +611,24 @@ class system_api:
|
||||
return ret
|
||||
|
||||
def getServerInfo(self):
|
||||
|
||||
upAddr = 'https://raw.githubusercontent.com/midoks/mdserver-web/master/version'
|
||||
upAddr = 'https://raw.githubusercontent.com/midoks/mdserver-web/master/version/info.json'
|
||||
try:
|
||||
version = public.httpGet(
|
||||
upAddr + '/info.json')
|
||||
version = public.httpGet(upAddr)
|
||||
print version
|
||||
version = json.loads(version)
|
||||
return version[0]
|
||||
except Exception as e:
|
||||
print e
|
||||
print 'getServerInfo', 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_now = config_api.config_api().getVersion()
|
||||
version_new_info = self.getServerInfo()
|
||||
if not 'version' in version_new_info:
|
||||
return public.returnJson(False, '服务器数据有问题!')
|
||||
@@ -586,7 +644,7 @@ class system_api:
|
||||
|
||||
if stype == 'info':
|
||||
version_new_info = self.getServerInfo()
|
||||
version_now = config.config().getVersion()
|
||||
version_now = config_api.config_api().getVersion()
|
||||
|
||||
if not 'version' in version_new_info:
|
||||
return public.returnJson(False, '服务器数据有问题!')
|
||||
@@ -605,36 +663,28 @@ class system_api:
|
||||
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)
|
||||
newUrl = v_new_info['path']
|
||||
toPath = public.getRootDir() + '/temp'
|
||||
if not os.path.exists(toPath):
|
||||
public.execShell('mkdir -p ' + toPath)
|
||||
|
||||
public.M('tasks').add(
|
||||
'id,name,type,status,addtime, execstr', taskAdd)
|
||||
return public.returnJson(True, '下载中...')
|
||||
if not os.path.exists(toPath + '/mw.zip'):
|
||||
public.execShell('wget -O ' + toPath + '/mw.zip ' + newUrl)
|
||||
|
||||
if stype == 'update_install':
|
||||
public.execShell('unzip -o ' + toPath + '/mw.zip' + ' -d ./')
|
||||
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
|
||||
print 'updateServer', 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:
|
||||
if public.readFile('/www/server/mdserver-web/class/common.py').find('checkSafe') != -1:
|
||||
vp = '_pro'
|
||||
public.ExecShell("wget -O update.sh " + public.get_url() +
|
||||
"/install/update" + vp + ".sh && bash update.sh")
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# coding: utf-8
|
||||
|
||||
import psutil
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import public
|
||||
import re
|
||||
import json
|
||||
import pwd
|
||||
|
||||
|
||||
from flask import request
|
||||
|
||||
|
||||
class task_api:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def countApi(self):
|
||||
c = public.M('tasks').where("status!=?", ('1',)).count()
|
||||
return str(c)
|
||||
|
||||
def listApi(self):
|
||||
|
||||
p = request.form.get('p', '1').encode('utf-8')
|
||||
limit = request.form.get('limit', '10').strip()
|
||||
search = request.form.get('search', '').strip()
|
||||
|
||||
start = (int(p) - 1) * int(limit)
|
||||
limit_str = str(start) + ',' + str(limit)
|
||||
|
||||
_list = public.M('tasks').where('', ()).field(
|
||||
'id,name,type,status,addtime,start,end').limit(limit_str).order('id desc').select()
|
||||
_ret = {}
|
||||
_ret['data'] = _list
|
||||
|
||||
count = public.M('tasks').where('', ()).count()
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['tojs'] = 'remind'
|
||||
_page['p'] = p
|
||||
|
||||
_ret['page'] = public.getPage(_page)
|
||||
return public.getJson(_ret)
|
||||
|
||||
def getExecLogApi(self):
|
||||
file = os.getcwd() + "/tmp/panelExec.log"
|
||||
v = public.getLastLine(file, 100)
|
||||
return v
|
||||
|
||||
def getTaskSpeedApi(self):
|
||||
tempFile = os.getcwd() + '/tmp/panelExec.log'
|
||||
freshFile = os.getcwd() + '/tmp/panelFresh'
|
||||
|
||||
find = public.M('tasks').where('status=? OR status=?',
|
||||
('-1', '0')).field('id,type,name,execstr').find()
|
||||
if not len(find):
|
||||
return public.returnJson(False, '当前没有任务队列在执行-2!')
|
||||
|
||||
isTask = os.getcwd() + '/tmp/panelTask.pl'
|
||||
public.writeFile(isTask, 'True')
|
||||
|
||||
echoMsg = {}
|
||||
echoMsg['name'] = find['name']
|
||||
echoMsg['execstr'] = find['execstr']
|
||||
if find['type'] == 'download':
|
||||
import json
|
||||
try:
|
||||
tmp = public.readFile(tempFile)
|
||||
if len(tmp) < 10:
|
||||
return public.returnJson(False, '当前没有任务队列在执行-3!')
|
||||
echoMsg['msg'] = json.loads(tmp)
|
||||
echoMsg['isDownload'] = True
|
||||
except:
|
||||
public.M('tasks').where(
|
||||
"id=?", (find['id'],)).save('status', ('0',))
|
||||
return public.returnJson(False, '当前没有任务队列在执行-4!')
|
||||
else:
|
||||
echoMsg['msg'] = public.getLastLine(tempFile, 10)
|
||||
echoMsg['isDownload'] = False
|
||||
|
||||
echoMsg['task'] = public.M('tasks').where("status!=?", ('1',)).field(
|
||||
'id,status,name,type').order("id asc").select()
|
||||
return public.getJson(echoMsg)
|
||||
@@ -1,18 +1,19 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/usr/local/lib/python2.7/bin
|
||||
|
||||
|
||||
|
||||
mw_start(){
|
||||
gunicorn -c setting.py app:app &
|
||||
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 -b :7200 -k gevent -w 1 app:app
|
||||
# gunicorn -b :7200 -k eventlet -w 1 app:app
|
||||
# gunicorn -c setting.py app:app
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
qpzw99oc
|
||||
@@ -19,19 +19,6 @@ CREATE TABLE IF NOT EXISTS `binding` (
|
||||
);
|
||||
|
||||
|
||||
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,
|
||||
@@ -40,18 +27,14 @@ CREATE TABLE IF NOT EXISTS `crontab` (
|
||||
`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
|
||||
`addtime` TEXT,
|
||||
`status` INTEGER DEFAULT '1',
|
||||
`save` INTEGER DEFAULT '3',
|
||||
`backup_to` TEXT DEFAULT 'off',
|
||||
`sname` TEXT,
|
||||
`sbody` TEXT,
|
||||
'stype' TEXT,
|
||||
`urladdress` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `firewall` (
|
||||
@@ -62,23 +45,12 @@ CREATE TABLE IF NOT EXISTS `firewall` (
|
||||
);
|
||||
|
||||
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');
|
||||
(1, '80', '网站默认端口', '0000-00-00 00:00:00'),
|
||||
(2, '7200', 'WEB面板', '0000-00-00 00:00:00'),
|
||||
(3, '22', 'SSH远程管理服务', '0000-00-00 00:00:00')
|
||||
(3, '888', 'phpMyAdmin默认端口', '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,
|
||||
@@ -130,3 +102,13 @@ CREATE TABLE IF NOT EXISTS `tasks` (
|
||||
`end` INTEGER,
|
||||
`execstr` TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `panel` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`title` TEXT,
|
||||
`url` TEXT,
|
||||
`username` TEXT,
|
||||
`password` TEXT,
|
||||
`click` INTEGER,
|
||||
`addtime` INTEGER
|
||||
);
|
||||
|
||||
@@ -5,20 +5,20 @@ server
|
||||
index index.php index.html index.htm default.php default.htm default.html;
|
||||
root {$ROOT_DIR};
|
||||
|
||||
#SSL-START %s
|
||||
#SSL-START
|
||||
#error_page 404/404.html;
|
||||
#SSL-END
|
||||
|
||||
#ERROR-PAGE-START %s
|
||||
#ERROR-PAGE-START
|
||||
error_page 404 /404.html;
|
||||
error_page 502 /502.html;
|
||||
#ERROR-PAGE-END
|
||||
|
||||
#PHP-INFO-START %s
|
||||
#PHP-INFO-START
|
||||
include enable-php-{$PHPVER}.conf;
|
||||
#PHP-INFO-END
|
||||
|
||||
#REWRITE-START %s
|
||||
#REWRITE-START
|
||||
include {$OR_REWRITE}/{$SERVER_NAME}.conf;
|
||||
#REWRITE-END
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
#BINDING-{$DIRBIND}-START
|
||||
server
|
||||
{
|
||||
listen {$PORT};
|
||||
server_name {$DIRBIND};
|
||||
index index.php index.html index.htm default.php default.htm default.html;
|
||||
root {$ROOT_DIR};
|
||||
|
||||
#SSL-START
|
||||
#error_page 404/404.html;
|
||||
#SSL-END
|
||||
|
||||
#ERROR-PAGE-START
|
||||
error_page 404 /404.html;
|
||||
error_page 502 /502.html;
|
||||
#ERROR-PAGE-END
|
||||
|
||||
#PHP-INFO-START
|
||||
include enable-php-{$PHPVER}.conf;
|
||||
#PHP-INFO-END
|
||||
|
||||
#REWRITE-START
|
||||
include {$OR_REWRITE}/{$SERVER_MAIN}.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_MAIN}_{$DIRBIND}.log;
|
||||
error_log {$LOGPATH}/{$SERVER_MAIN}_{$DIRBIND}.error.log;
|
||||
}
|
||||
#BINDING-{$DIRBIND}-END
|
||||
@@ -9,15 +9,26 @@ REV="$2"
|
||||
TXN_NAME="$3"
|
||||
|
||||
|
||||
WEB_PATH={$PROJECT_DIR}/wwwroot/$REPOS
|
||||
if [ ! -d {$PROJECT_DIR}/csvn ]; then
|
||||
sudo mkdir -p {$PROJECT_DIR}/csvn
|
||||
sudo chown -R csvn:csvn {$PROJECT_DIR}/csvn
|
||||
fi
|
||||
|
||||
SAVE_PATH={$PROJECT_DIR}/csvn/$REPOS
|
||||
SVN_PATH=http://127.0.0.1:{$PORT}/svn/$REPOS
|
||||
|
||||
if [ ! -d $WEB_PATH ]; then
|
||||
svn co $SVN_PATH $WEB_PATH \
|
||||
if [ ! -d $SAVE_PATH ]; then
|
||||
svn co $SVN_PATH $SAVE_PATH \
|
||||
--username={$CSVN_USER} \
|
||||
--password={$CSVN_PWD} \
|
||||
--no-auth-cache \
|
||||
--non-interactive
|
||||
fi
|
||||
|
||||
cd $WEB_PATH && svn update --username={$CSVN_USER} --password={$CSVN_PWD}
|
||||
cd $SAVE_PATH && svn update --username={$CSVN_USER} --password={$CSVN_PWD} --no-auth-cache --non-interactive
|
||||
|
||||
WEB_PATH={$PROJECT_DIR}/wwwroot/$REPOS
|
||||
sudo mkdir -p $WEB_PATH
|
||||
|
||||
sudo rsync -vauP --delete --exclude=".*" $SAVE_PATH/ $WEB_PATH
|
||||
sudo chown -R www:www $WEB_PATH
|
||||
@@ -31,6 +31,7 @@ function csvnReadme(){
|
||||
html += '<p>* 注意:牢记admin的密码,在后csvn的管理后台和这里不同步</p>';
|
||||
html += '<p>* 注意:在这里添加用户和csvn后台并不同步</p>';
|
||||
html += '<p>* 注意:项目管理的地址一般是正确的,但在特殊环境下,地址可能不一致</p>';
|
||||
html += '<p>* 注意:脚本内使用sudo名,需要注释(vi /etc/sudoers)[#Default requiretty]</p>';
|
||||
|
||||
$('.bt-w-main .soft-man-con').html(html);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import public
|
||||
|
||||
|
||||
app_debug = False
|
||||
if public.getOs() == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ def reload():
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_initd_csvn = '/etc/init.d/csvn'
|
||||
@@ -124,7 +124,7 @@ def initdStatus():
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_csvn = getServerDir() + '/bin/csvn'
|
||||
@@ -139,7 +139,7 @@ def initdInstall():
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
if public.getOs() == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
_csvn = getServerDir() + '/bin/csvn'
|
||||
@@ -640,6 +640,21 @@ def projectScriptDebug():
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def getTotalStatistics():
|
||||
st = status()
|
||||
data = {}
|
||||
if st == 'start':
|
||||
svn_path = getServerDir() + '/data/repositories'
|
||||
data['status'] = True
|
||||
data['count'] = len(os.listdir(svn_path))
|
||||
data['ver'] = public.readFile(getServerDir() + '/version.pl').strip()
|
||||
return public.returnJson(True, 'ok', data)
|
||||
else:
|
||||
data['status'] = False
|
||||
data['count'] = 0
|
||||
return public.returnJson(False, 'fail', data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
@@ -688,5 +703,7 @@ if __name__ == "__main__":
|
||||
print projectScriptEdit()
|
||||
elif func == 'project_script_debug':
|
||||
print projectScriptDebug()
|
||||
elif func == 'get_total_statistics':
|
||||
print getTotalStatistics()
|
||||
else:
|
||||
print 'fail'
|
||||
|
||||
@@ -12,8 +12,22 @@ 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'
|
||||
|
||||
CheckJAVA()
|
||||
{
|
||||
which "java" > /dev/null
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo 'java is exist'
|
||||
else
|
||||
echo 'java install...'
|
||||
yum install -y java
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
Install_csvn()
|
||||
{
|
||||
CheckJAVA
|
||||
mkdir -p $serverPath/source
|
||||
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
@@ -32,7 +46,7 @@ Install_csvn()
|
||||
else
|
||||
useradd csvn
|
||||
cp /etc/sudoers{,.`date +"%Y-%m-%d_%H-%M-%S"`}
|
||||
echo "csvn ALL=(ALL) ALL" >> /etc/sudoers
|
||||
echo "csvn ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
fi
|
||||
|
||||
chown -R csvn:csvn $serverPath/csvn
|
||||
|
||||
@@ -340,16 +340,16 @@ function csvnAddProject(){
|
||||
}
|
||||
|
||||
|
||||
function csvnProjectScript(pnanm, has_hook){
|
||||
function csvnProjectScript(pname, 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>';
|
||||
html += '<button onclick="csvnProjectScriptEdit(\''+pname+'\')" class="btn btn-default btn-sm">手动编辑</button>';
|
||||
html += '<button onclick="csvnProjectScriptDebug(\''+pname+'\')" class="btn btn-default btn-sm">调试日志</button>';
|
||||
html += '<button onclick="csvnProjectScriptLoad(\''+pname+'\')" class="btn btn-default btn-sm">重新加载</button>';
|
||||
html += '<button onclick="csvnProjectScriptUnload(\''+pname+'\')" class="btn btn-default btn-sm">卸载脚本</button>';
|
||||
} else {
|
||||
html += '<button onclick="csvnProjectScriptLoad(\''+pnanm+'\')" class="btn btn-default btn-sm">加载脚本</button>';
|
||||
html += '<button onclick="csvnProjectScriptLoad(\''+pname+'\')" class="btn btn-default btn-sm">加载脚本</button>';
|
||||
}
|
||||
|
||||
var loadOpen = layer.open({
|
||||
@@ -369,7 +369,6 @@ function csvnProjectScriptLoad(pname){
|
||||
|
||||
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){
|
||||
$('.layui-layer-close1').click();
|
||||
csvnProjectList();
|
||||
},2000);
|
||||
});
|
||||
@@ -384,7 +383,6 @@ function csvnProjectScriptUnload(pname){
|
||||
|
||||
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
setTimeout(function(){
|
||||
$('.layui-layer-close1').click();
|
||||
csvnProjectList();
|
||||
},2000);
|
||||
});
|
||||
@@ -395,7 +393,6 @@ function csvnProjectScriptEdit(pname){
|
||||
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']});
|
||||
@@ -408,7 +405,6 @@ function csvnProjectScriptDebug(pname){
|
||||
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']});
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
runtime: php55
|
||||
api_version: 1
|
||||
threadsafe: true
|
||||
|
||||
handlers:
|
||||
- url: /.*
|
||||
script: helloworld.php
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'Hello, GAE!';
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -1,7 +1,8 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="readme();">插件说明</p>
|
||||
<p class="bgw" onclick="readme();">插件说明</p>
|
||||
<p onclick="projectList();">项目列表</p>
|
||||
</div>
|
||||
|
||||
<div class="bt-w-con pd15">
|
||||
@@ -12,12 +13,15 @@
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
||||
function readme() {
|
||||
$('.bt-w-main .soft-man-con').hide();
|
||||
$('.bt-w-main .v0').show();
|
||||
$.getScript( "/plugins/file?name=gae&f=js/gae.js");
|
||||
resetPluginWinWidth(720);
|
||||
readme();
|
||||
function readme(){
|
||||
var html = '<p>开发文档:https://cloud.google.com/sdk/docs/</p>';
|
||||
html += '<p>* 注意:本插件通过Google <a class="btlink" target="_blank" href="https://cloud.google.com/sdk/docs/scripting-gcloud">JSON 格式</a>赋权免交互式</p>';
|
||||
html += '<p>* 注意:添加:gcloud auth activate-service-account --key-file [KEY_FILE]</p>';
|
||||
html += '<p>* 注意:设置后,一般同步项目命令:gcloud app deploy << y</p>';
|
||||
html += '<p>* 注意:可以查看命令,把命令加入到脚本中...自动更新。</p>';
|
||||
$('.bt-w-main .soft-man-con').html(html);
|
||||
}
|
||||
|
||||
//../google-cloud-sdk/bin/gcloud app deploy << y
|
||||
|
||||
</script>
|
||||
@@ -11,10 +11,230 @@ sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'gae'
|
||||
|
||||
|
||||
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 status():
|
||||
return 'start'
|
||||
|
||||
|
||||
def getAllProjectList(search):
|
||||
path = public.getWwwDir()
|
||||
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
|
||||
tmp['dir'] = filePath
|
||||
dlist.append(tmp)
|
||||
else:
|
||||
if filename.find(search) != -1:
|
||||
tmp['name'] = filename
|
||||
tmp['dir'] = filePath
|
||||
dlist.append(tmp)
|
||||
return dlist
|
||||
|
||||
|
||||
def checkProjectListIsSet(data):
|
||||
dlen = len(data)
|
||||
for x in range(dlen):
|
||||
path = getServerDir() + '/' + data[x]['name'] + '.json'
|
||||
if os.path.exists(path):
|
||||
if os.path.getsize(path) == 0:
|
||||
data[x]['isset'] = False
|
||||
else:
|
||||
data[x]['isset'] = True
|
||||
else:
|
||||
data[x]['isset'] = False
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def projectListEdit():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'missing name!'
|
||||
|
||||
file = getServerDir() + '/' + args['name'] + '.json'
|
||||
if not os.path.exists(file):
|
||||
public.execShell('touch ' + file)
|
||||
return file
|
||||
|
||||
|
||||
def projectListDel():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'missing name!'
|
||||
|
||||
file = getServerDir() + '/' + args['name'] + '.json'
|
||||
if os.path.exists(file):
|
||||
content = public.readFile(file)
|
||||
contentObj = json.loads(content)
|
||||
asyncUser = contentObj['client_email']
|
||||
cmd = getServerDir() + '/google-cloud-sdk/bin/'
|
||||
public.execShell(cmd + 'gcloud auth revoke ' + asyncUser)
|
||||
public.execShell('rm -rf ' + file)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def checkUserExist(cmd, user):
|
||||
data = public.execShell(cmd + 'gcloud auth list | grep ' + user)
|
||||
if data[0] == '':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def projectListAsync():
|
||||
import subprocess
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'missing name!'
|
||||
|
||||
file = getServerDir() + '/' + args['name'] + '.json'
|
||||
if not os.path.exists(file):
|
||||
return 'not configured file!'
|
||||
|
||||
content = public.readFile(file)
|
||||
contentObj = json.loads(content)
|
||||
asyncUser = contentObj['client_email']
|
||||
cmd = getServerDir() + '/google-cloud-sdk/bin/'
|
||||
projectDir = public.getWwwDir() + '/' + args['name']
|
||||
|
||||
if not checkUserExist(cmd, asyncUser):
|
||||
public.execShell(
|
||||
cmd + 'gcloud auth activate-service-account --key-file ' + file)
|
||||
|
||||
pName = contentObj['project_id']
|
||||
setUserCmd = cmd + 'gcloud config set account ' + asyncUser
|
||||
setUserCmd += ' && ' + cmd + 'gcloud config set project ' + pName
|
||||
asyncCmd = setUserCmd + ' && cd ' + projectDir + \
|
||||
' && ' + cmd + 'gcloud app deploy << y'
|
||||
|
||||
taskAdd = (None, 'gae[async]',
|
||||
'execshell', '0', time.strftime('%Y-%m-%d %H:%M:%S'), asyncCmd)
|
||||
public.M('tasks').add('id,name,type,status,addtime, execstr', taskAdd)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectListCmd():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'missing name!'
|
||||
|
||||
file = getServerDir() + '/' + args['name'] + '.json'
|
||||
if not os.path.exists(file):
|
||||
return 'not configured file!'
|
||||
|
||||
content = public.readFile(file)
|
||||
contentObj = json.loads(content)
|
||||
asyncUser = contentObj['client_email']
|
||||
cmd = getServerDir() + '/google-cloud-sdk/bin/'
|
||||
pName = contentObj['project_id']
|
||||
projectDir = public.getWwwDir() + '/' + args['name']
|
||||
|
||||
setUserCmd = 'sudo ' + cmd + 'gcloud config set account ' + asyncUser
|
||||
setUserCmd += ' && sudo ' + cmd + 'gcloud config set project ' + pName
|
||||
asyncCmd = setUserCmd + ' && sudo cd ' + projectDir + \
|
||||
' && sudo ' + cmd + 'gcloud app deploy <<y'
|
||||
return asyncCmd
|
||||
|
||||
|
||||
def projectListUrl():
|
||||
args = getArgs()
|
||||
if not 'name' in args:
|
||||
return 'missing name!'
|
||||
|
||||
file = getServerDir() + '/' + args['name'] + '.json'
|
||||
if not os.path.exists(file):
|
||||
return 'not configured file!'
|
||||
|
||||
content = public.readFile(file)
|
||||
contentObj = json.loads(content)
|
||||
asyncUser = contentObj['client_email']
|
||||
plist = asyncUser.split('@')
|
||||
|
||||
url = 'https://' + plist[0] + '.appspot.com'
|
||||
return url
|
||||
|
||||
|
||||
def projectList():
|
||||
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 = checkProjectListIsSet(ret_data)
|
||||
|
||||
data = {}
|
||||
data['data'] = ret_data
|
||||
data['list'] = public.getPage(
|
||||
{'count': dlist_sum, 'p': page, 'row': 10, 'tojs': 'projectList'})
|
||||
return public.getJson(data)
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
print status()
|
||||
elif func == 'project_list':
|
||||
print projectList()
|
||||
elif func == 'project_list_edit':
|
||||
print projectListEdit()
|
||||
elif func == 'project_list_del':
|
||||
print projectListDel()
|
||||
elif func == 'project_list_async':
|
||||
print projectListAsync()
|
||||
elif func == 'project_list_cmd':
|
||||
print projectListCmd()
|
||||
elif func == 'project_list_url':
|
||||
print projectListUrl()
|
||||
else:
|
||||
print 'error'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"title":"GAE",
|
||||
"tip":"soft",
|
||||
"name":"gae",
|
||||
"ps":"GAE 英文全称为 Google App Engine。它是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台",
|
||||
"ps":"GAE(Google App Engine)。它是Google管理的数据中心中用于WEB应用程序的开发和托管的平台",
|
||||
"versions": "0.1",
|
||||
"shell":"install.sh",
|
||||
"checks":"server/gae",
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
function gaePost(method,args,callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'gae', 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 projectList(page, search){
|
||||
var _data = {};
|
||||
_data['page_size'] = 10;
|
||||
if (typeof(search) != 'undefined'){
|
||||
_data['search'] = search;
|
||||
}
|
||||
|
||||
if (typeof(page) != 'undefined'){
|
||||
_data['page'] = page;
|
||||
setCookie('gaeProjectListPage',page);
|
||||
} else {
|
||||
_data['page'] = 1;
|
||||
cookie_page = getCookie('gaeProjectListPage')
|
||||
if (cookie_page >0){
|
||||
_data['page'] = cookie_page;
|
||||
}
|
||||
}
|
||||
|
||||
gaePost('project_list', _data, function(data){
|
||||
|
||||
var rdata = $.parseJSON($.trim(data.data));
|
||||
// console.log(rdata);
|
||||
|
||||
content = '<div><input class="bt-input-text mr5" type="text" placeholder="查找项目" id="project_find" style="height: 28px; border-radius: 3px;width: 435px;">';
|
||||
content += '<button class="btn btn-success btn-sm" onclick="projectListFind();">查找</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" target="_blank" href="https://console.cloud.google.com/">官方地址</a>)</th>';
|
||||
content += '</tr></thead>';
|
||||
content += '<tbody>';
|
||||
|
||||
|
||||
ulist = rdata.data;
|
||||
for (i in ulist){
|
||||
setName = ulist[i]['isset'] ? '已设置' : '设置';
|
||||
content += '<tr><td>'+ulist[i]['name']+'</td>'+
|
||||
'<td>'+ulist[i]['dir']+'</td><td>'+
|
||||
'<a class="btlink" onclick="gaeSetProject(\''+ulist[i]['name']+'\','+ulist[i]['isset']+')">'+setName+'</a> | ' +
|
||||
'<a class="btlink" onclick="gaeAsyncProject(\''+ulist[i]['name']+'\')">同步</a> | ' +
|
||||
'<a class="btlink" target="_blank" onclick="gaeProjectCmd(\''+ulist[i]['name']+'\')">命令</a> | ' +
|
||||
'<a class="btlink" target="_blank" onclick="gaeProjectUrl(\''+ulist[i]['name']+'\')">访问</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 projectListFind(){
|
||||
var search = $('#project_find').val();
|
||||
if (search == ''){
|
||||
layer.msg('查找字符不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
projectList(1, search);
|
||||
}
|
||||
|
||||
function gaeSetProject(pname,isset){
|
||||
var html = '';
|
||||
if (isset){
|
||||
html += '<button onclick="gaeProjectDel(\''+pname+'\')" class="btn btn-default btn-sm">删除</button>';
|
||||
}
|
||||
html += '<button onclick="gaeProjectEdit(\''+pname+'\')" class="btn btn-default btn-sm">编辑</button>';
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '['+ pname +']密钥设置',
|
||||
area: '240px',
|
||||
content:'<div class="change-default pd20">'+html+'</div>'
|
||||
});
|
||||
}
|
||||
|
||||
function gaeProjectEdit(pname){
|
||||
gaePost('project_list_edit', {'name':pname}, function(data){
|
||||
onlineEditFile(0,data.data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function gaeProjectDel(pname){
|
||||
gaePost('project_list_del', {'name':pname}, function(data){
|
||||
showMsg('删除成功!',function(){
|
||||
$('.layui-layer-close1').click();
|
||||
projectList();
|
||||
},{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
});
|
||||
}
|
||||
|
||||
function gaeAsyncProject(pname){
|
||||
gaePost('project_list_async', {'name':pname}, function(data){
|
||||
if (data.data !='ok'){
|
||||
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
} else {
|
||||
layer.msg('加入任务,请自行观察!',{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
$('.layui-layer-close1').click();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function stringToEntity(str,radix){
|
||||
let arr=[]
|
||||
//返回的字符实体默认10进制,也可以选择16进制
|
||||
radix=radix||0
|
||||
for(let i=0;i<str.length;i++){
|
||||
arr.push((!radix?'&#'+str.charCodeAt(i):'&#x'+str.charCodeAt(i).toString(16))+';')
|
||||
}
|
||||
let tmp=arr.join('')
|
||||
// console.log(`'${str}' 转实体为 '${tmp}'`)
|
||||
return tmp
|
||||
}
|
||||
|
||||
function gaeProjectCmd(pname){
|
||||
gaePost('project_list_cmd', {'name':pname}, function(data){
|
||||
var data_str = data.data;
|
||||
if (data_str.indexOf('gcloud') !== -1){
|
||||
layer.msg(stringToEntity(data.data),{icon:1,time:5000,shade: [0.3, '#000']});
|
||||
} else {
|
||||
layer.msg(data.data,{icon:0,time:5000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function gaeProjectUrl(pname){
|
||||
gaePost('project_list_url', {'name':pname}, function(data){
|
||||
var data_str = data.data;
|
||||
if (data_str.indexOf('appspot.com') !== -1){
|
||||
window.open(data.data);
|
||||
} else {
|
||||
layer.msg(data.data,{icon:0,time:5000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# coding: utf-8
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append("/usr/local/lib/python2.7/site-packages")
|
||||
|
||||
|
||||
class mysql:
|
||||
__DB_PASS = None
|
||||
__DB_USER = 'root'
|
||||
__DB_PORT = 3306
|
||||
__DB_HOST = 'localhost'
|
||||
__DB_NAME = 'test'
|
||||
__DB_CONN = None
|
||||
__DB_CUR = None
|
||||
__DB_ERR = None
|
||||
__DB_CNF = '/etc/my.cnf'
|
||||
|
||||
def __Conn(self):
|
||||
'''连接MYSQL数据库'''
|
||||
try:
|
||||
socket = '/tmp/mysql.sock'
|
||||
try:
|
||||
import MySQLdb
|
||||
except Exception, ex:
|
||||
self.__DB_ERR = ex
|
||||
return False
|
||||
try:
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, db=self.__DB_NAME, charset="utf8", connect_timeout=10, unix_socket=socket)
|
||||
except MySQLdb.Error, e:
|
||||
self.__DB_HOST = '127.0.0.1'
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, db=self.__DB_NAME, charset="utf8", connect_timeout=10, unix_socket=socket)
|
||||
self.__DB_CUR = self.__DB_CONN.cursor()
|
||||
return True
|
||||
|
||||
except MySQLdb.Error, e:
|
||||
self.__DB_ERR = e
|
||||
return False
|
||||
|
||||
def setHost(self, host):
|
||||
self.__DB_HOST = host
|
||||
|
||||
def setPwd(self, pwd):
|
||||
self.__DB_PASS = pwd
|
||||
|
||||
def setUser(self, user):
|
||||
self.__DB_USER = user
|
||||
|
||||
def setPort(self, port):
|
||||
self.__DB_PORT = port
|
||||
|
||||
def setDb(self, name):
|
||||
self.__DB_NAME = name
|
||||
|
||||
def getPwd(self):
|
||||
return self.__DB_PASS
|
||||
|
||||
def execute(self, sql):
|
||||
# 执行SQL语句返回受影响行
|
||||
if not self.__Conn():
|
||||
return self.__DB_ERR
|
||||
try:
|
||||
result = self.__DB_CUR.execute(sql)
|
||||
self.__DB_CONN.commit()
|
||||
self.__Close()
|
||||
return result
|
||||
except Exception, ex:
|
||||
return ex
|
||||
|
||||
def query(self, sql):
|
||||
# 执行SQL语句返回数据集
|
||||
if not self.__Conn():
|
||||
return self.__DB_ERR
|
||||
try:
|
||||
self.__DB_CUR.execute(sql)
|
||||
result = self.__DB_CUR.fetchall()
|
||||
# 将元组转换成列表
|
||||
data = map(list, result)
|
||||
self.__Close()
|
||||
return data
|
||||
except Exception, ex:
|
||||
return ex
|
||||
|
||||
# 关闭连接
|
||||
def __Close(self):
|
||||
self.__DB_CUR.close()
|
||||
self.__DB_CONN.close()
|
||||
@@ -0,0 +1,63 @@
|
||||
APP_NAME = Gogs
|
||||
RUN_USER = {$RUN_USER}
|
||||
RUN_MODE = prod
|
||||
|
||||
[database]
|
||||
DB_TYPE = mysql
|
||||
HOST = 127.0.0.1:3306
|
||||
NAME = gogs
|
||||
USER = gogs
|
||||
PASSWD = gogs
|
||||
SSL_MODE = disable
|
||||
PATH = data/gogs.db
|
||||
|
||||
[repository]
|
||||
ROOT = {$ROOT_PATH}/gogs-repositories
|
||||
FORCE_PRIVATE = false
|
||||
|
||||
[server]
|
||||
DOMAIN = 127.0.0.1
|
||||
HTTP_PORT = 3000
|
||||
ROOT_URL = http://127.0.0.1:3000/
|
||||
DISABLE_SSH = false
|
||||
SSH_PORT = 2000
|
||||
START_SSH_SERVER = false
|
||||
OFFLINE_MODE = false
|
||||
LANDING_PAGE = home
|
||||
|
||||
[mailer]
|
||||
ENABLED = false
|
||||
HOST = smtp.163.com:465
|
||||
USER = midoks@163.com
|
||||
PASSWD = ***
|
||||
USE_PLAIN_TEXT = true
|
||||
|
||||
[service]
|
||||
REGISTER_EMAIL_CONFIRM = false
|
||||
ENABLE_NOTIFY_MAIL = false
|
||||
DISABLE_REGISTRATION = false
|
||||
ENABLE_CAPTCHA = true
|
||||
REQUIRE_SIGNIN_VIEW = false
|
||||
|
||||
[picture]
|
||||
DISABLE_GRAVATAR = false
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[session]
|
||||
PROVIDER = file
|
||||
|
||||
[log]
|
||||
MODE = console, file
|
||||
LEVEL = Info
|
||||
ROOT_PATH = {$SERVER_PATH}/gogs/log
|
||||
|
||||
[security]
|
||||
INSTALL_LOCK = true
|
||||
SECRET_KEY = jmGSJXDBH5Ng4wt
|
||||
|
||||
|
||||
[other]
|
||||
SHOW_FOOTER_BRANDING = false
|
||||
SHOW_FOOTER_VERSION = false
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
GITADDR="{$GITROOTURL}{$USERNAME}/{$PROJECT}"
|
||||
GIT_SDIR="{$CODE_DIR}"
|
||||
|
||||
GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}"
|
||||
GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
|
||||
|
||||
# echo $GIT_PROJECT_DIR
|
||||
if [ ! -d $GIT_PROJECT_DIR ];then
|
||||
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
|
||||
git clone $GITADDR
|
||||
fi
|
||||
|
||||
unset GIT_DIR
|
||||
cd $GIT_PROJECT_DIR && git pull
|
||||
|
||||
# func 2
|
||||
# cd $GIT_PROJECT_DIR && env -i git pull origin master
|
||||
|
||||
|
||||
|
||||
WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT}
|
||||
mkdir -p $WEB_PATH
|
||||
|
||||
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
|
||||
|
||||
sysName=`uname`
|
||||
if [ $sysName == 'Darwin' ]; then
|
||||
USER=$(who | sed -n "2,1p" |awk '{print $1}')
|
||||
chown -R $USER:staff $WEB_PATH
|
||||
else
|
||||
chown -R www:www $WEB_PATH
|
||||
fi
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
sh -x {$PATH}/commit 2>{$PATH}/sh.log
|
||||
@@ -3,9 +3,14 @@
|
||||
<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="pluginConfig('gogs',null, 'init_conf');">启动配置</p>
|
||||
<p onclick="gogsEdit();">手动编辑</p>
|
||||
<p onclick="pluginConfig('gogs',null, 'conf');">配置文件</p>
|
||||
<p onclick="gogsSetConfig();">配置修改</p>
|
||||
<p onclick="gogsUserList();">用户列表</p>
|
||||
<p onclick="pluginLogs('gogs',null,'run_log');">运行日志</p>
|
||||
<p onclick="pluginLogs('gogs',null,'post_receive_log');" title="提交post-receive日志">提交日志</p>
|
||||
<p onclick="gogsRead();">使用说明</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
@@ -13,5 +18,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=gogs&f=js/gogs.js");
|
||||
pluginService('gogs');
|
||||
</script>
|
||||
@@ -4,6 +4,7 @@
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
sys.path.append("/usr/local/lib/python2.7/site-packages")
|
||||
import psutil
|
||||
@@ -24,6 +25,9 @@ def getPluginName():
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
sys.path.append(getPluginDir() + "/class")
|
||||
import mysql
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
@@ -52,16 +56,26 @@ def getArgs():
|
||||
return tmp
|
||||
|
||||
|
||||
def getInitdConf():
|
||||
def getInitdConfTpl():
|
||||
path = getPluginDir() + "/init.d/gogs.tpl"
|
||||
return path
|
||||
|
||||
|
||||
def getInitdConf():
|
||||
path = getServerDir() + "/init.d/gogs"
|
||||
return path
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getServerDir() + "/custom/conf/app.ini"
|
||||
return path
|
||||
|
||||
|
||||
def getConfTpl():
|
||||
path = getPluginDir() + "/conf/app.ini"
|
||||
return path
|
||||
|
||||
|
||||
def status():
|
||||
data = public.execShell(
|
||||
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
|
||||
@@ -70,9 +84,26 @@ def status():
|
||||
return 'start'
|
||||
|
||||
|
||||
def contentReplace(content):
|
||||
user = 'root'
|
||||
if public.isAppleSystem():
|
||||
user = public.execShell(
|
||||
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
|
||||
content = content.replace('{$HOME_DIR}', '/Users/' + user)
|
||||
else:
|
||||
content = content.replace('{$HOME_DIR}', '/root')
|
||||
|
||||
service_path = public.getServerDir()
|
||||
content = content.replace('{$ROOT_PATH}', public.getRootDir())
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
content = content.replace('{$RUN_USER}', user)
|
||||
|
||||
return content
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
file_tpl = getInitdConf()
|
||||
file_tpl = getInitdConfTpl()
|
||||
service_path = public.getServerDir()
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
@@ -80,11 +111,19 @@ def initDreplace():
|
||||
os.mkdir(initD_path)
|
||||
file_bin = initD_path + '/' + getPluginName()
|
||||
|
||||
content = public.readFile(file_tpl)
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
if not os.path.exists(file_bin):
|
||||
content = public.readFile(file_tpl)
|
||||
content = contentReplace(content)
|
||||
public.writeFile(file_bin, content)
|
||||
public.execShell('chmod +x ' + file_bin)
|
||||
|
||||
public.writeFile(file_bin, content)
|
||||
public.execShell('chmod +x ' + file_bin)
|
||||
conf_bin = getConf()
|
||||
if not os.path.exists(conf_bin):
|
||||
public.execShell('mkdir -p ' + getServerDir() + '/custom/conf')
|
||||
conf_tpl = getConfTpl()
|
||||
content = public.readFile(conf_tpl)
|
||||
content = contentReplace(content)
|
||||
public.writeFile(conf_bin, content)
|
||||
|
||||
log_path = getServerDir() + '/log'
|
||||
if not os.path.exists(log_path):
|
||||
@@ -93,12 +132,99 @@ def initDreplace():
|
||||
return file_bin
|
||||
|
||||
|
||||
def getRootUrl():
|
||||
content = public.readFile(getConf())
|
||||
rep = 'ROOT_URL\s*=\s*(.*)'
|
||||
tmp = re.search(rep, content)
|
||||
if not tmp:
|
||||
return ''
|
||||
return tmp.groups()[0]
|
||||
|
||||
|
||||
def getRootPath():
|
||||
content = public.readFile(getConf())
|
||||
rep = 'ROOT\s*=\s*(.*)'
|
||||
tmp = re.search(rep, content)
|
||||
if not tmp:
|
||||
return ''
|
||||
return tmp.groups()[0]
|
||||
|
||||
|
||||
def getDbConfValue():
|
||||
content = public.readFile(getConf())
|
||||
|
||||
rep_scope = "\[database\](.*?)\["
|
||||
tmp = re.findall(rep_scope, content, re.S)
|
||||
|
||||
rep = '(\w*)\s*=\s*(.*)'
|
||||
tmp = re.findall(rep, tmp[0])
|
||||
r = {}
|
||||
for x in range(len(tmp)):
|
||||
k = tmp[x][0]
|
||||
v = tmp[x][1]
|
||||
r[k] = v
|
||||
return r
|
||||
|
||||
|
||||
def pMysqlDb():
|
||||
conf = getDbConfValue()
|
||||
|
||||
host = conf['HOST'].split(':')
|
||||
conn = mysql.mysql()
|
||||
|
||||
conn.setHost(host[0])
|
||||
conn.setUser(conf['USER'])
|
||||
conn.setPwd(conf['PASSWD'])
|
||||
conn.setPort(int(host[1]))
|
||||
conn.setDb(conf['NAME'])
|
||||
return conn
|
||||
|
||||
|
||||
def isSqlError(mysqlMsg):
|
||||
# 检测数据库执行错误
|
||||
_mysqlMsg = str(mysqlMsg)
|
||||
# print _mysqlMsg
|
||||
if "MySQLdb" in _mysqlMsg:
|
||||
return public.returnData(False, 'MySQLdb组件缺失! <br>进入SSH命令行输入: pip install mysql-python')
|
||||
if "2002," in _mysqlMsg:
|
||||
return public.returnData(False, '数据库连接失败,请检查数据库服务是否启动!')
|
||||
if "using password:" in _mysqlMsg:
|
||||
return public.returnData(False, '数据库管理密码错误!')
|
||||
if "Connection refused" in _mysqlMsg:
|
||||
return public.returnData(False, '数据库连接失败,请检查数据库服务是否启动!')
|
||||
if "1133," in _mysqlMsg:
|
||||
return public.returnData(False, '数据库用户不存在!')
|
||||
if "1007," in _mysqlMsg:
|
||||
return public.returnData(False, '数据库已经存在!')
|
||||
if "1044," in _mysqlMsg:
|
||||
return public.returnData(False, mysqlMsg[1])
|
||||
if "2003," in _mysqlMsg:
|
||||
return public.returnData(False, mysqlMsg[1])
|
||||
return public.returnData(True, 'OK')
|
||||
|
||||
|
||||
def start():
|
||||
|
||||
is_frist = True
|
||||
conf_bin = getConf()
|
||||
if os.path.exists(conf_bin):
|
||||
is_frist = False
|
||||
|
||||
file = initDreplace()
|
||||
|
||||
if is_frist:
|
||||
return "第一次启动Gogs,默认使用MySQL连接!<br>可以在配置文件中重新设置,再启动!"
|
||||
|
||||
conn = pMysqlDb()
|
||||
list_table = conn.query('show tables')
|
||||
data = isSqlError(list_table)
|
||||
if not data['status']:
|
||||
return data['msg']
|
||||
|
||||
data = public.execShell(file + ' start')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
return data[0]
|
||||
|
||||
|
||||
def stop():
|
||||
@@ -106,7 +232,7 @@ def stop():
|
||||
data = public.execShell(file + ' stop')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return data[1]
|
||||
|
||||
|
||||
def restart():
|
||||
@@ -114,7 +240,7 @@ def restart():
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return data[1]
|
||||
|
||||
|
||||
def reload():
|
||||
@@ -122,7 +248,7 @@ def reload():
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return data[1]
|
||||
|
||||
|
||||
def initdStatus():
|
||||
@@ -164,6 +290,307 @@ def runLog():
|
||||
log_path = getServerDir() + '/log/gogs.log'
|
||||
return log_path
|
||||
|
||||
|
||||
def postReceiveLog():
|
||||
log_path = getServerDir() + '/log/hooks/post-receive.log'
|
||||
return log_path
|
||||
|
||||
|
||||
def getGogsConf():
|
||||
gets = [
|
||||
{'name': 'DOMAIN', 'type': -1, 'ps': '服务器域名'},
|
||||
{'name': 'ROOT_URL', 'type': -1, 'ps': '公开的完整URL路径'},
|
||||
{'name': 'HTTP_ADDR', 'type': -1, 'ps': '应用HTTP监听地址'},
|
||||
{'name': 'HTTP_PORT', 'type': -1, 'ps': '应用 HTTP 监听端口号'},
|
||||
|
||||
{'name': 'START_SSH_SERVER', 'type': 2, 'ps': '启动内置SSH服务器'},
|
||||
{'name': 'SSH_PORT', 'type': -1, 'ps': 'SSH 端口号'},
|
||||
|
||||
{'name': 'REQUIRE_SIGNIN_VIEW', 'type': 2, 'ps': '强制登录浏览'},
|
||||
{'name': 'ENABLE_CAPTCHA', 'type': 2, 'ps': '启用验证码服务'},
|
||||
{'name': 'DISABLE_REGISTRATION', 'type': 2, 'ps': '禁止注册,只能由管理员创建帐号'},
|
||||
{'name': 'ENABLE_NOTIFY_MAIL', 'type': 2, 'ps': '是否开启邮件通知'},
|
||||
|
||||
{'name': 'FORCE_PRIVATE', 'type': 2, 'ps': '强制要求所有新建的仓库都是私有'},
|
||||
|
||||
{'name': 'SHOW_FOOTER_BRANDING', 'type': 2, 'ps': 'Gogs推广信息'},
|
||||
{'name': 'SHOW_FOOTER_VERSION', 'type': 2, 'ps': 'Gogs版本信息'},
|
||||
{'name': 'SHOW_FOOTER_TEMPLATE_LOAD_TIME', 'type': 2, 'ps': 'Gogs模板加载时间'},
|
||||
]
|
||||
conf = public.readFile(getConf())
|
||||
result = []
|
||||
|
||||
for g in gets:
|
||||
rep = g['name'] + '\s*=\s*(.*)'
|
||||
tmp = re.search(rep, conf)
|
||||
if not tmp:
|
||||
continue
|
||||
g['value'] = tmp.groups()[0]
|
||||
result.append(g)
|
||||
return public.getJson(result)
|
||||
|
||||
|
||||
def submitGogsConf():
|
||||
gets = ['DOMAIN',
|
||||
'ROOT_URL',
|
||||
'HTTP_ADDR',
|
||||
'HTTP_PORT',
|
||||
'START_SSH_SERVER',
|
||||
'SSH_PORT',
|
||||
'REQUIRE_SIGNIN_VIEW',
|
||||
'FORCE_PRIVATE',
|
||||
'ENABLE_CAPTCHA',
|
||||
'DISABLE_REGISTRATION',
|
||||
'ENABLE_NOTIFY_MAIL',
|
||||
'SHOW_FOOTER_BRANDING',
|
||||
'SHOW_FOOTER_VERSION',
|
||||
'SHOW_FOOTER_TEMPLATE_LOAD_TIME']
|
||||
args = getArgs()
|
||||
filename = getConf()
|
||||
conf = public.readFile(filename)
|
||||
for g in gets:
|
||||
if g in args:
|
||||
rep = g + '\s*=\s*(.*)'
|
||||
val = g + ' = ' + args[g]
|
||||
conf = re.sub(rep, val, conf)
|
||||
public.writeFile(filename, conf)
|
||||
reload()
|
||||
return public.returnJson(True, '设置成功')
|
||||
|
||||
|
||||
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']
|
||||
|
||||
data = {}
|
||||
|
||||
data['root_url'] = getRootUrl()
|
||||
|
||||
pm = pMysqlDb()
|
||||
start = (page - 1) * page_size
|
||||
list_count = pm.query('select count(id) as num from user')
|
||||
count = list_count[0][0]
|
||||
|
||||
list_data = pm.query(
|
||||
'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size))
|
||||
|
||||
page_info = {'count': count, 'p': page,
|
||||
'row': page_size, 'tojs': 'gogsUserList'}
|
||||
data['list'] = public.getPage(page_info)
|
||||
data['page'] = page
|
||||
data['page_size'] = page_size
|
||||
data['page_count'] = int(math.ceil(count / page_size))
|
||||
data['data'] = list_data
|
||||
return public.returnJson(True, 'OK', data)
|
||||
|
||||
|
||||
def getAllUserProject(user, search=''):
|
||||
path = getRootPath() + '/' + user
|
||||
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.replace('.git', '')
|
||||
dlist.append(tmp)
|
||||
else:
|
||||
if filename.find(search) != -1:
|
||||
tmp['name'] = filename.replace('.git', '')
|
||||
dlist.append(tmp)
|
||||
return dlist
|
||||
|
||||
|
||||
def checkProjectListIsHasScript(user, data):
|
||||
path = getRootPath() + '/' + user
|
||||
for x in range(len(data)):
|
||||
name = data[x]['name'] + '.git'
|
||||
path_tmp = path + '/' + name + '/custom_hooks/post-receive'
|
||||
if os.path.exists(path_tmp):
|
||||
data[x]['has_hook'] = True
|
||||
else:
|
||||
data[x]['has_hook'] = False
|
||||
return data
|
||||
|
||||
|
||||
def userProjectList():
|
||||
import math
|
||||
args = getArgs()
|
||||
# print args
|
||||
|
||||
page = 1
|
||||
page_size = 5
|
||||
search = ''
|
||||
|
||||
if not 'name' in args:
|
||||
return public.returnJson(False, '缺少参数name')
|
||||
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']
|
||||
|
||||
data = {}
|
||||
|
||||
ulist = getAllUserProject(args['name'])
|
||||
dlist_sum = len(ulist)
|
||||
|
||||
start = (page - 1) * page_size
|
||||
ret_data = ulist[start:start + page_size]
|
||||
ret_data = checkProjectListIsHasScript(args['name'], ret_data)
|
||||
|
||||
data['root_url'] = getRootUrl()
|
||||
data['data'] = ret_data
|
||||
data['args'] = args
|
||||
data['list'] = public.getPage(
|
||||
{'count': dlist_sum, 'p': page, 'row': page_size, 'tojs': 'userProjectList'})
|
||||
|
||||
return public.returnJson(True, 'OK', data)
|
||||
|
||||
|
||||
def projectScriptEdit():
|
||||
args = getArgs()
|
||||
|
||||
if not 'user' in args:
|
||||
return public.returnJson(True, 'username missing')
|
||||
|
||||
if not 'name' in args:
|
||||
return public.returnJson(True, 'project name missing')
|
||||
|
||||
user = args['user']
|
||||
name = args['name'] + '.git'
|
||||
post_receive = getRootPath() + '/' + user + '/' + name + \
|
||||
'/custom_hooks/post-receive'
|
||||
if os.path.exists(post_receive):
|
||||
return public.returnJson(True, 'OK', {'path': post_receive})
|
||||
else:
|
||||
return public.returnJson(False, 'file does not exist')
|
||||
|
||||
|
||||
def projectScriptLoad():
|
||||
args = getArgs()
|
||||
if not 'user' in args:
|
||||
return public.returnJson(True, 'username missing')
|
||||
|
||||
if not 'name' in args:
|
||||
return public.returnJson(True, 'project name missing')
|
||||
|
||||
user = args['user']
|
||||
name = args['name'] + '.git'
|
||||
|
||||
path = getRootPath() + '/' + user + '/' + name
|
||||
post_receive_tpl = getPluginDir() + '/hook/post-receive.tpl'
|
||||
post_receive = path + '/custom_hooks/post-receive'
|
||||
|
||||
if not os.path.exists(path + '/custom_hooks'):
|
||||
public.execShell('mkdir -p ' + path + '/custom_hooks')
|
||||
|
||||
pct_content = public.readFile(post_receive_tpl)
|
||||
pct_content = pct_content.replace('{$PATH}', path + '/custom_hooks')
|
||||
public.writeFile(post_receive, pct_content)
|
||||
public.execShell('chmod 777 ' + post_receive)
|
||||
|
||||
commit_tpl = getPluginDir() + '/hook/commit.tpl'
|
||||
commit = path + '/custom_hooks/commit'
|
||||
|
||||
codeDir = public.getRootDir() + '/git'
|
||||
|
||||
cc_content = public.readFile(commit_tpl)
|
||||
cc_content = cc_content.replace('{$GITROOTURL}', getRootUrl())
|
||||
cc_content = cc_content.replace('{$CODE_DIR}', codeDir)
|
||||
cc_content = cc_content.replace('{$USERNAME}', user)
|
||||
cc_content = cc_content.replace('{$PROJECT}', args['name'])
|
||||
cc_content = cc_content.replace('{$WEB_ROOT}', public.getWwwDir())
|
||||
public.writeFile(commit, cc_content)
|
||||
public.execShell('chmod 777 ' + commit)
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectScriptUnload():
|
||||
args = getArgs()
|
||||
if not 'user' in args:
|
||||
return public.returnJson(True, 'username missing')
|
||||
|
||||
if not 'name' in args:
|
||||
return public.returnJson(True, 'project name missing')
|
||||
|
||||
user = args['user']
|
||||
name = args['name'] + '.git'
|
||||
|
||||
post_receive = getRootPath() + '/' + user + '/' + name + \
|
||||
'/custom_hooks/post-receive'
|
||||
public.execShell('rm -f ' + post_receive)
|
||||
|
||||
commit = getRootPath() + '/' + user + '/' + name + \
|
||||
'/custom_hooks/commit'
|
||||
public.execShell('rm -f ' + commit)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def projectScriptDebug():
|
||||
args = getArgs()
|
||||
if not 'user' in args:
|
||||
return public.returnJson(True, 'username missing')
|
||||
|
||||
if not 'name' in args:
|
||||
return public.returnJson(True, 'project name missing')
|
||||
user = args['user']
|
||||
name = args['name'] + '.git'
|
||||
commit_log = getRootPath() + '/' + user + '/' + name + \
|
||||
'/custom_hooks/sh.log'
|
||||
|
||||
data = {}
|
||||
if os.path.exists(commit_log):
|
||||
data['status'] = True
|
||||
data['path'] = commit_log
|
||||
else:
|
||||
data['status'] = False
|
||||
data['msg'] = '没有日志文件'
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def gogsEdit():
|
||||
data = {}
|
||||
data['post_receive'] = getPluginDir() + '/hook/post-receive.tpl'
|
||||
data['commit'] = getPluginDir() + '/hook/commit.tpl'
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def getTotalStatistics():
|
||||
st = status()
|
||||
data = {}
|
||||
if st == 'start':
|
||||
pm = pMysqlDb()
|
||||
list_count = pm.query('select count(id) as num from repository')
|
||||
count = list_count[0][0]
|
||||
|
||||
data['status'] = True
|
||||
data['count'] = count
|
||||
data['ver'] = public.readFile(getServerDir() + '/version.pl').strip()
|
||||
return public.returnJson(True, 'ok', data)
|
||||
else:
|
||||
data['status'] = False
|
||||
data['count'] = 0
|
||||
return public.returnJson(False, 'fail', data)
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
@@ -184,9 +611,31 @@ if __name__ == "__main__":
|
||||
print initdUinstall()
|
||||
elif func == 'run_log':
|
||||
print runLog()
|
||||
elif func == 'post_receive_log':
|
||||
print postReceiveLog()
|
||||
elif func == 'conf':
|
||||
print getConf()
|
||||
elif func == 'init_conf':
|
||||
print getInitdConf()
|
||||
elif func == 'get_gogs_conf':
|
||||
print getGogsConf()
|
||||
elif func == 'submit_gogs_conf':
|
||||
print submitGogsConf()
|
||||
elif func == 'user_list':
|
||||
print userList()
|
||||
elif func == 'user_project_list':
|
||||
print userProjectList()
|
||||
elif func == 'project_script_edit':
|
||||
print projectScriptEdit()
|
||||
elif func == 'project_script_load':
|
||||
print projectScriptLoad()
|
||||
elif func == 'project_script_unload':
|
||||
print projectScriptUnload()
|
||||
elif func == 'project_script_debug':
|
||||
print projectScriptDebug()
|
||||
elif func == 'gogs_edit':
|
||||
print gogsEdit()
|
||||
elif func == 'get_total_statistics':
|
||||
print getTotalStatistics()
|
||||
else:
|
||||
print 'fail'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"ps": "Gogs是一款极易搭建的自助Git服务",
|
||||
"name": "gogs",
|
||||
"title": "Gogs",
|
||||
"versions": ["0.11.79","0.11.66"],
|
||||
"versions": ["0.11.86","0.11.79"],
|
||||
"tip": "soft",
|
||||
"checks": "server/gogs",
|
||||
"author": "midoks",
|
||||
|
||||
@@ -26,7 +26,7 @@ if [ -f /etc/init.d/functions ];then
|
||||
fi
|
||||
|
||||
# Default values
|
||||
|
||||
HOME={$HOME_DIR}
|
||||
NAME=gogs
|
||||
GOGS_HOME={$SERVER_PATH}/gogs
|
||||
GOGS_PATH=${GOGS_HOME}/$NAME
|
||||
@@ -65,7 +65,12 @@ start() {
|
||||
stop() {
|
||||
cd ${GOGS_HOME}
|
||||
echo "Shutting down ${SERVICENAME}: \c"
|
||||
pkill ${NAME}
|
||||
which "killproc" > /dev/null
|
||||
if [ $? -eq 0 ];then
|
||||
killproc ${NAME}
|
||||
else
|
||||
pkill ${NAME}
|
||||
fi
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && rm -f ${LOCKFILE} && echo "\033[32mdone\033[0m"
|
||||
}
|
||||
|
||||
@@ -49,12 +49,13 @@ Install_gogs()
|
||||
mv $serverPath/source/gogs/gogs_${version}/gogs/ $serverPath/gogs
|
||||
echo $version > $serverPath/gogs/version.pl
|
||||
|
||||
echo '安装完成' > $install_tmp
|
||||
echo 'install success' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_gogs()
|
||||
{
|
||||
rm -rf $serverPath/gogs
|
||||
echo 'uninstall success' > $install_tmp
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
|
||||
function str2Obj(str){
|
||||
var data = {};
|
||||
kv = str.split('&');
|
||||
for(i in kv){
|
||||
v = kv[i].split('=');
|
||||
data[v[0]] = v[1];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function gogsPost(method,args,callback, title){
|
||||
|
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){
|
||||
_args = JSON.stringify(str2Obj(args));
|
||||
} else {
|
||||
_args = JSON.stringify(args);
|
||||
}
|
||||
|
||||
var _title = '正在获取...';
|
||||
if (typeof(title) != 'undefined'){
|
||||
_title = title;
|
||||
}
|
||||
|
||||
var loadT = layer.msg(_title, { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'gogs', func:method, args:_args}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
function gogsSetConfig(){
|
||||
gogsPost('get_gogs_conf', '', function(data){
|
||||
// console.log(data);
|
||||
var rdata = $.parseJSON(data.data);
|
||||
// console.log(rdata);
|
||||
var mlist = '';
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
var w = '140';
|
||||
if (rdata[i].name == 'error_reporting') w = '250';
|
||||
var ibody = '<input style="width: ' + w + 'px;" class="bt-input-text mr5" name="' + rdata[i].name + '" value="' + rdata[i].value + '" type="text" >';
|
||||
switch (rdata[i].type) {
|
||||
case 0:
|
||||
var selected_1 = (rdata[i].value == 1) ? 'selected' : '';
|
||||
var selected_0 = (rdata[i].value == 0) ? 'selected' : '';
|
||||
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
|
||||
<option value="1" ' + selected_1 + '>开启</option>\
|
||||
<option value="0" ' + selected_0 + '>关闭</option>\
|
||||
</select>';
|
||||
break;
|
||||
case 1:
|
||||
var selected_1 = (rdata[i].value == 'On') ? 'selected' : '';
|
||||
var selected_0 = (rdata[i].value == 'Off') ? 'selected' : '';
|
||||
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
|
||||
<option value="On" ' + selected_1 + '>开启</option>\
|
||||
<option value="Off" ' + selected_0 + '>关闭</option></select>'
|
||||
break;
|
||||
case 2:
|
||||
var selected_1 = (rdata[i].value == 'true') ? 'selected' : '';
|
||||
var selected_0 = (rdata[i].value == 'false') ? 'selected' : '';
|
||||
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
|
||||
<option value="true" ' + selected_1 + '>开启</option>\
|
||||
<option value="false" ' + selected_0 + '>关闭</option></select>'
|
||||
break;
|
||||
}
|
||||
mlist += '<p><span>' + rdata[i].name + '</span>' + ibody + ', <font>' + rdata[i].ps + '</font></p>'
|
||||
}
|
||||
var html = '<style>.conf_p p{margin-bottom: 2px}</style><div class="conf_p" style="margin-bottom:0">\
|
||||
' + mlist + '\
|
||||
<div style="margin-top:10px; padding-right:15px" class="text-right">\
|
||||
<button class="btn btn-success btn-sm mr5" onclick="gogsSetConfig()">刷新</button>\
|
||||
<button class="btn btn-success btn-sm" onclick="submitGogsConf()">保存</button></div>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(html);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//提交PHP配置
|
||||
function submitGogsConf() {
|
||||
var data = {
|
||||
DOMAIN: $("select[name='DOMAIN']").val(),
|
||||
ROOT_URL: $("select[name='ROOT_URL']").val(),
|
||||
HTTP_ADDR: $("select[name='HTTP_ADDR']").val(),
|
||||
HTTP_PORT: $("select[name='HTTP_PORT']").val(),
|
||||
START_SSH_SERVER: $("select[name='START_SSH_SERVER']").val() || 'false',
|
||||
SSH_PORT: $("select[name='SSH_PORT']").val(),
|
||||
ROOT_URL: $("select[name='ROOT_URL']").val(),
|
||||
REQUIRE_SIGNIN_VIEW: $("select[name='REQUIRE_SIGNIN_VIEW']").val() || 'false',
|
||||
ENABLE_CAPTCHA: $("select[name='ENABLE_CAPTCHA']").val() || 'true',
|
||||
DISABLE_REGISTRATION: $("select[name='DISABLE_REGISTRATION']").val() || 'false',
|
||||
ENABLE_NOTIFY_MAIL: $("select[name='ENABLE_NOTIFY_MAIL']").val() || 'false',
|
||||
FORCE_PRIVATE: $("select[name='FORCE_PRIVATE']").val() || 'false',
|
||||
SHOW_FOOTER_BRANDING: $("select[name='SHOW_FOOTER_BRANDING']").val() || 'false',
|
||||
SHOW_FOOTER_VERSION: $("select[name='SHOW_FOOTER_VERSION']").val() || 'false',
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME: $("select[name='SHOW_FOOTER_TEMPLATE_LOAD_TIME']").val() || 'false',
|
||||
};
|
||||
|
||||
gogsPost('submit_gogs_conf', data, function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
gogsSetConfig();
|
||||
});
|
||||
}
|
||||
|
||||
function gogsEdit(){
|
||||
|
||||
gogsPost('gogs_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['post_receive']+'\');">post-receive.tpl</button>\
|
||||
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['commit']+'\');">commit.tpl</button>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(edit);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function gogsUserList(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;
|
||||
}
|
||||
|
||||
gogsPost('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="find_user" style="height: 28px; border-radius: 3px;width: 435px;">';
|
||||
content += '<button class="btn btn-success btn-sm" onclick="userFind();">查找</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>邮件地址</th>';
|
||||
content += '<th>操作(<a href="'+rdata['data']['root_url']+'" class="btlink" target="_blank">WEB管理</a>)</th>';
|
||||
content += '</tr></thead>';
|
||||
|
||||
content += '<tbody>';
|
||||
|
||||
ulist = rdata['data']['data'];
|
||||
for (i in ulist){
|
||||
email = ulist[i][2] == '' ? '无' : ulist[i][2];
|
||||
content += '<tr><td>'+ulist[i][0]+'</td>'+
|
||||
'<td>'+ulist[i][1]+'</td>'+
|
||||
'<td>'+email+'</td>'+
|
||||
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i][1]+'\')">项目管理</a></td>'+
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
content += '</tbody>';
|
||||
content += '</table></div>';
|
||||
|
||||
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
|
||||
page += rdata['data']['list'];
|
||||
page += '</div></ul></div>';
|
||||
|
||||
content += page;
|
||||
|
||||
$(".soft-man-con").html(content);
|
||||
});
|
||||
}
|
||||
|
||||
function userProjectList(user, search){
|
||||
var req = {};
|
||||
if (!isNaN(user)){
|
||||
req['page'] = user;
|
||||
req['name'] = user = getCookie('gogsUserSelected');
|
||||
} else {
|
||||
req['page'] = 1;
|
||||
req['name'] = user;
|
||||
setCookie('gogsUserSelected', user);
|
||||
}
|
||||
|
||||
req['page_size'] = 5;
|
||||
req['search'] = '';
|
||||
if(typeof(search) != 'undefined'){
|
||||
req['search'] = search;
|
||||
}
|
||||
|
||||
$('.layui-layer-close1').click();
|
||||
gogsPost('user_project_list', req, function(data){
|
||||
var rdata = [];
|
||||
try {
|
||||
rdata = $.parseJSON(data.data);
|
||||
} catch(e){}
|
||||
|
||||
if (!rdata['status']){
|
||||
layer.msg(rdata['msg'], { icon: 2 });
|
||||
return;
|
||||
}
|
||||
|
||||
var list = '';
|
||||
// console.log(rdata);
|
||||
var project_list = rdata['data']['data'];
|
||||
for (i in project_list) {
|
||||
var name = project_list[i]['name'];
|
||||
list += '<tr><td>'+name+'</td>\
|
||||
<td>\
|
||||
<a class="btlink" target="_blank" href="'+rdata['data']['root_url']+user+'/'+name+'">源码</a> | \
|
||||
<a class="btlink" onclick="projectScript(\''+user+'\',\''+name+'\','+project_list[i]['has_hook']+');">脚本</a>\
|
||||
</td>\
|
||||
</tr>';
|
||||
}
|
||||
|
||||
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
|
||||
page += rdata['data']['list'];
|
||||
page += '</div></ul></div>';
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '用户('+user+')项目列表',
|
||||
area: '300px',
|
||||
content:"<div class='bt-form pd20 c6'>\
|
||||
<div>\
|
||||
<div class='divtable' style='margin-top:5px;'>\
|
||||
<table class='table table-hover'>\
|
||||
<thead><tr><th>项目</th><th>操作</th></tr></thead>\
|
||||
<tbody>" + list + "</tbody>\
|
||||
</table>" +
|
||||
page +
|
||||
"</div></div></div>"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function projectScript(user, name,has_hook){
|
||||
// console.log(user,name,has_hook);
|
||||
var html = '';
|
||||
if (has_hook){
|
||||
html += '<button onclick="projectScriptEdit(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">手动编辑</button>';
|
||||
html += '<button onclick="projectScriptDebug(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">调试日志</button>';
|
||||
html += '<button onclick="projectScriptLoad(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">重新加载</button>';
|
||||
html += '<button onclick="projectScriptUnload(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">卸载脚本</button>';
|
||||
} else {
|
||||
html += '<button onclick="projectScriptLoad(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">加载脚本</button>';
|
||||
}
|
||||
|
||||
var loadOpen = layer.open({
|
||||
type: 1,
|
||||
title: '['+user+']['+name+']脚本设置',
|
||||
area: '240px',
|
||||
content:'<div class="change-default pd20">'+html+'</div>'
|
||||
});
|
||||
}
|
||||
|
||||
function projectScriptEdit(user,name){
|
||||
gogsPost('project_script_edit', {'user':user,'name':name}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (rdata['status']){
|
||||
onlineEditFile(0, rdata['data']['path']);
|
||||
} else {
|
||||
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function projectScriptLoad(user,name){
|
||||
gogsPost('project_script_load', {'user':user,'name':name}, 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(){
|
||||
userProjectList(1);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
function projectScriptUnload(user,name){
|
||||
gogsPost('project_script_unload', {'user':user,'name':name}, 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(){
|
||||
userProjectList(1);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
function projectScriptDebug(user,name){
|
||||
gogsPost('project_script_debug', {'user':user,'name':name}, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (rdata['status']){
|
||||
onlineEditFile(0, rdata['path']);
|
||||
} else {
|
||||
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function gogsRead(){
|
||||
var readme = '<p>* 默认使用MySQL,第一个启动加载各种配置,并修改成正确的数据库配置</p>';
|
||||
readme += '<p>* 邮件端口使用456,gogs仅支持使用STARTTLS的SMTP协议</p>';
|
||||
$('.soft-man-con').html(readme);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 801 B After Width: | Height: | Size: 653 B |
@@ -3,7 +3,8 @@
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('memcached');">服务</p>
|
||||
<p onclick="pluginInitD('memcached');">自启动</p>
|
||||
<p onclick="pluginConfig('memcached');">配置修改</p>
|
||||
<p onclick="pluginConfig('memcached', null, 'conf_tpl');">配置模板</p>
|
||||
<p onclick="pluginConfig('memcached');">配置文件</p>
|
||||
<p onclick="memcachedStatus();">负载状态</p>
|
||||
<p onclick="memcachedCache();">性能调整</p>
|
||||
</div>
|
||||
|
||||
@@ -4,12 +4,13 @@ import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
app_debug = False
|
||||
if public.getOs() == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
@@ -32,16 +33,37 @@ def getInitDFile():
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getServerDir() + "/init.d/memcached"
|
||||
return path
|
||||
|
||||
|
||||
def getConfTpl():
|
||||
path = getPluginDir() + "/init.d/memcached.tpl"
|
||||
return path
|
||||
|
||||
|
||||
def getMemPort():
|
||||
path = getConf()
|
||||
content = public.readFile(path)
|
||||
rep = 'PORT\s*=\s*(\d*)'
|
||||
tmp = re.search(rep, content)
|
||||
return tmp.groups()[0]
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
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
|
||||
|
||||
|
||||
@@ -55,7 +77,7 @@ def status():
|
||||
|
||||
def initDreplace():
|
||||
|
||||
file_tpl = getConf()
|
||||
file_tpl = getConfTpl()
|
||||
service_path = public.getServerDir()
|
||||
|
||||
initD_path = getServerDir() + '/init.d'
|
||||
@@ -63,56 +85,46 @@ def initDreplace():
|
||||
os.mkdir(initD_path)
|
||||
file_bin = initD_path + '/memcached'
|
||||
|
||||
# if os.path.exists(file_bin):
|
||||
# return file_bin
|
||||
if not os.path.exists(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)
|
||||
|
||||
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():
|
||||
def memOp(method):
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' start')
|
||||
data = public.execShell(file + ' ' + method)
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return data[1]
|
||||
|
||||
|
||||
def start():
|
||||
return memOp('start')
|
||||
|
||||
|
||||
def stop():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' stop')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return memOp('stop')
|
||||
|
||||
|
||||
def restart():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return memOp('restart')
|
||||
|
||||
|
||||
def reload():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return memOp('reload')
|
||||
|
||||
|
||||
def runInfo():
|
||||
# 获取memcached状态
|
||||
import telnetlib
|
||||
import re
|
||||
|
||||
port = getMemPort()
|
||||
try:
|
||||
tn = telnetlib.Telnet('127.0.0.1', 11211)
|
||||
tn = telnetlib.Telnet('127.0.0.1', int(port))
|
||||
tn.write(b"stats\n")
|
||||
tn.write(b"quit\n")
|
||||
data = tn.read_all()
|
||||
@@ -149,6 +161,7 @@ def saveConf():
|
||||
# 设置memcached缓存大小
|
||||
import re
|
||||
confFile = getConf()
|
||||
print confFile
|
||||
try:
|
||||
args = getArgs()
|
||||
content = public.readFile(confFile)
|
||||
@@ -158,8 +171,8 @@ def saveConf():
|
||||
content = re.sub('CACHESIZE=\d+', 'CACHESIZE=' +
|
||||
args['cachesize'], content)
|
||||
public.writeFile(confFile, content)
|
||||
reload()
|
||||
return 'ok'
|
||||
restart()
|
||||
return 'save ok'
|
||||
except Exception as e:
|
||||
pass
|
||||
return 'fail'
|
||||
@@ -167,8 +180,7 @@ def saveConf():
|
||||
|
||||
def initdStatus():
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
if os.path.exists(initd_bin):
|
||||
@@ -179,8 +191,7 @@ def initdStatus():
|
||||
def initdInstall():
|
||||
import shutil
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
|
||||
mem_bin = initDreplace()
|
||||
@@ -192,8 +203,7 @@ def initdInstall():
|
||||
|
||||
def initdUinstall():
|
||||
if not app_debug:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
if public.isAppleSystem():
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
os.remove(initd_bin)
|
||||
@@ -221,6 +231,8 @@ if __name__ == "__main__":
|
||||
print runInfo()
|
||||
elif func == 'conf':
|
||||
print getConf()
|
||||
elif func == 'conf_tpl':
|
||||
print getConfTpl()
|
||||
elif func == 'save_conf':
|
||||
print saveConf()
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# coding: utf-8
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append("/usr/local/lib/python2.7/site-packages")
|
||||
|
||||
|
||||
class mysql:
|
||||
__DB_PASS = None
|
||||
__DB_USER = 'root'
|
||||
__DB_PORT = 3306
|
||||
__DB_HOST = 'localhost'
|
||||
__DB_CONN = None
|
||||
__DB_CUR = None
|
||||
__DB_ERR = None
|
||||
__DB_CNF = '/etc/my.cnf'
|
||||
|
||||
def __Conn(self):
|
||||
'''连接MYSQL数据库'''
|
||||
try:
|
||||
import public
|
||||
socket = '/tmp/mysql.sock'
|
||||
try:
|
||||
import MySQLdb
|
||||
except Exception, ex:
|
||||
self.__DB_ERR = ex
|
||||
return False
|
||||
try:
|
||||
myconf = public.readFile(self.__DB_CNF)
|
||||
rep = "port\s*=\s*([0-9]+)"
|
||||
self.__DB_PORT = int(re.search(rep, myconf).groups()[0])
|
||||
except:
|
||||
self.__DB_PORT = 3306
|
||||
# print self.__DB_PASS
|
||||
#self.__DB_PASS = public.M('config').where('id=?', (1,)).getField('mysql_root')
|
||||
try:
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, charset="utf8", connect_timeout=1, unix_socket=socket)
|
||||
except MySQLdb.Error, e:
|
||||
self.__DB_HOST = '127.0.0.1'
|
||||
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
|
||||
port=self.__DB_PORT, charset="utf8", connect_timeout=1, unix_socket=socket)
|
||||
self.__DB_CUR = self.__DB_CONN.cursor()
|
||||
return True
|
||||
except MySQLdb.Error, e:
|
||||
self.__DB_ERR = e
|
||||
return False
|
||||
|
||||
def setPwd(self, pwd):
|
||||
self.__DB_PASS = pwd
|
||||
|
||||
def getPwd(self):
|
||||
return self.__DB_PASS
|
||||
|
||||
def execute(self, sql):
|
||||
# 执行SQL语句返回受影响行
|
||||
if not self.__Conn():
|
||||
return self.__DB_ERR
|
||||
try:
|
||||
result = self.__DB_CUR.execute(sql)
|
||||
self.__DB_CONN.commit()
|
||||
self.__Close()
|
||||
return result
|
||||
except Exception, ex:
|
||||
return ex
|
||||
|
||||
def query(self, sql):
|
||||
# 执行SQL语句返回数据集
|
||||
if not self.__Conn():
|
||||
return self.__DB_ERR
|
||||
try:
|
||||
self.__DB_CUR.execute(sql)
|
||||
result = self.__DB_CUR.fetchall()
|
||||
# 将元组转换成列表
|
||||
data = map(list, result)
|
||||
self.__Close()
|
||||
return data
|
||||
except Exception, ex:
|
||||
return ex
|
||||
|
||||
# 关闭连接
|
||||
def __Close(self):
|
||||
self.__DB_CUR.close()
|
||||
self.__DB_CONN.close()
|
||||
@@ -0,0 +1,70 @@
|
||||
[client]
|
||||
#password = your_password
|
||||
port = 3306
|
||||
socket = /tmp/mysql.sock
|
||||
|
||||
[mysqld]
|
||||
port = 3306
|
||||
socket = /tmp/mysql.sock
|
||||
datadir = {$SERVER_APP_PATH}/data
|
||||
log-error = {$SERVER_APP_PATH}/data/error.log
|
||||
default_storage_engine = MyISAM
|
||||
#skip-external-locking
|
||||
#loose-skip-innodb
|
||||
key_buffer_size = 8M
|
||||
max_allowed_packet = 100G
|
||||
table_open_cache = 32
|
||||
sort_buffer_size = 256K
|
||||
net_buffer_length = 4K
|
||||
read_buffer_size = 128K
|
||||
read_rnd_buffer_size = 256K
|
||||
myisam_sort_buffer_size = 4M
|
||||
thread_cache_size = 4
|
||||
query_cache_size = 4M
|
||||
tmp_table_size = 8M
|
||||
|
||||
#skip-networking
|
||||
#skip-name-resolve
|
||||
max_connections = 500
|
||||
max_connect_errors = 100
|
||||
open_files_limit = 65535
|
||||
|
||||
log-bin=mysql-bin
|
||||
binlog_format=mixed
|
||||
server-id = 1
|
||||
expire_logs_days = 10
|
||||
slow_query_log=1
|
||||
slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log
|
||||
long_query_time=3
|
||||
#log_queries_not_using_indexes=on
|
||||
|
||||
default_storage_engine = InnoDB
|
||||
innodb_data_home_dir = {$SERVER_APP_PATH}/data
|
||||
innodb_data_file_path = ibdata1:10M:autoextend
|
||||
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
|
||||
innodb_buffer_pool_size = 16M
|
||||
innodb_additional_mem_pool_size = 2M
|
||||
innodb_log_file_size = 5M
|
||||
innodb_log_buffer_size = 8M
|
||||
innodb_flush_log_at_trx_commit = 1
|
||||
innodb_lock_wait_timeout = 120
|
||||
innodb_max_dirty_pages_pct = 90
|
||||
innodb_read_io_threads = 1
|
||||
innodb_write_io_threads = 1
|
||||
innodb_file_per_table=1
|
||||
|
||||
[mysqldump]
|
||||
quick
|
||||
max_allowed_packet = 16M
|
||||
|
||||
[mysql]
|
||||
no-auto-rehash
|
||||
|
||||
[myisamchk]
|
||||
key_buffer_size = 20M
|
||||
sort_buffer_size = 20M
|
||||
read_buffer = 2M
|
||||
write_buffer = 2M
|
||||
|
||||
[mysqlhotcopy]
|
||||
interactive-timeout
|
||||
@@ -0,0 +1,17 @@
|
||||
CREATE TABLE IF NOT EXISTS `config` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`mysql_root` TEXT
|
||||
);
|
||||
|
||||
INSERT INTO `config` (`id`, `mysql_root`) VALUES (1, 'admin');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `databases` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`pid` INTEGER,
|
||||
`name` TEXT,
|
||||
`username` TEXT,
|
||||
`password` TEXT,
|
||||
`accept` TEXT,
|
||||
`ps` TEXT,
|
||||
`addtime` TEXT
|
||||
);
|
||||
@@ -1,16 +1,52 @@
|
||||
<style type="text/css">
|
||||
.db_list{
|
||||
padding: 0px 0 10px 0;
|
||||
font-size: 13px;
|
||||
line-height: 35px;
|
||||
height: 45px;
|
||||
}
|
||||
.db_list a{
|
||||
margin-right: 15px;
|
||||
color: #555;
|
||||
font-weight: 600;
|
||||
}
|
||||
.db_list span:nth-child(1){
|
||||
display: block;
|
||||
float: left;
|
||||
padding-left: 15px;
|
||||
background: #ececec;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#db_tools button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
#db_tools button:last-child{
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('mysql');">服务</p>
|
||||
<p onclick="indexPy();">自启动</p>
|
||||
<p onclick="pluginInitD('mysql');">自启动</p>
|
||||
<p onclick="pluginConfig('mysql');">配置文件</p>
|
||||
<p onclick="myPort();">端口</p>
|
||||
<p onclick="runInfo();">当前状态</p>
|
||||
<p onclick="myPerfOpt();">性能优化</p>
|
||||
<p onclick="myLogs();">日志</p>
|
||||
<p onclick="pluginLogs('mysql','','show_log');">慢日志</p>
|
||||
<p onclick="dbList()">管理列表</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con">
|
||||
</div>
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=mysql&f=js/mysql.js");
|
||||
resetPluginWinWidth(800);
|
||||
pluginService('mysql');
|
||||
$.getScript( "/plugins/file?name=mysql&f=js/mysql.js");
|
||||
</script>
|
||||
@@ -8,8 +8,8 @@
|
||||
"updates":["5.5.62"],
|
||||
"shell":"install.sh",
|
||||
"checks":"server/mysql",
|
||||
"author":"midoks",
|
||||
"home":"https://dev.mysql.com/downloads/mysql/5.5.html#downloads",
|
||||
"author":"mysql",
|
||||
"home":"https://dev.mysql.com/downloads/mysql",
|
||||
"date":"2017-11-24",
|
||||
"pid": "2"
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
#!/bin/sh
|
||||
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
|
||||
# This file is public domain and comes with NO WARRANTY of any kind
|
||||
|
||||
# MySQL daemon start/stop script.
|
||||
|
||||
# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
|
||||
# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
|
||||
# When this is done the mysql server will be started when the machine is
|
||||
# started and shut down when the systems goes down.
|
||||
|
||||
# Comments to support chkconfig on RedHat Linux
|
||||
# chkconfig: 2345 64 36
|
||||
# description: A very fast and reliable SQL database engine.
|
||||
|
||||
# Comments to support LSB init script conventions
|
||||
### BEGIN INIT INFO
|
||||
# Provides: mysql
|
||||
# Required-Start: $local_fs $network $remote_fs
|
||||
# Should-Start: ypbind nscd ldap ntpd xntpd
|
||||
# Required-Stop: $local_fs $network $remote_fs
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: start and stop MySQL
|
||||
# Description: MySQL is a very fast and reliable SQL database engine.
|
||||
### END INIT INFO
|
||||
|
||||
# If you install MySQL on some other places than /www/server/mysql, then you
|
||||
# have to do one of the following things for this script to work:
|
||||
#
|
||||
# - Run this script from within the MySQL installation directory
|
||||
# - Create a /etc/my.cnf file with the following information:
|
||||
# [mysqld]
|
||||
# basedir=<path-to-mysql-installation-directory>
|
||||
# - Add the above to any other configuration file (for example ~/.my.ini)
|
||||
# and copy my_print_defaults to /usr/bin
|
||||
# - Add the path to the mysql-installation-directory to the basedir variable
|
||||
# below.
|
||||
#
|
||||
# If you want to affect other MySQL variables, you should make your changes
|
||||
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.
|
||||
|
||||
# If you change base dir, you must also change datadir. These may get
|
||||
# overwritten by settings in the MySQL configuration files.
|
||||
|
||||
basedir=
|
||||
datadir=
|
||||
|
||||
# Default value, in seconds, afterwhich the script should timeout waiting
|
||||
# for server start.
|
||||
# Value here is overriden by value in my.cnf.
|
||||
# 0 means don't wait at all
|
||||
# Negative numbers mean to wait indefinitely
|
||||
service_startup_timeout=900
|
||||
|
||||
# Lock directory for RedHat / SuSE.
|
||||
lockdir='/var/lock/subsys'
|
||||
lock_file_path="$lockdir/mysql"
|
||||
|
||||
# The following variables are only set for letting mysql.server find things.
|
||||
|
||||
# Set some defaults
|
||||
mysqld_pid_file_path=
|
||||
if test -z "$basedir"
|
||||
then
|
||||
basedir={$SERVER_APP_PATH}
|
||||
bindir={$SERVER_APP_PATH}/bin
|
||||
if test -z "$datadir"
|
||||
then
|
||||
datadir={$SERVER_APP_PATH}/data
|
||||
fi
|
||||
sbindir={$SERVER_APP_PATH}/bin
|
||||
libexecdir={$SERVER_APP_PATH}/bin
|
||||
else
|
||||
bindir="$basedir/bin"
|
||||
if test -z "$datadir"
|
||||
then
|
||||
datadir="$basedir/data"
|
||||
fi
|
||||
sbindir="$basedir/sbin"
|
||||
libexecdir="$basedir/libexec"
|
||||
fi
|
||||
|
||||
# datadir_set is used to determine if datadir was set (and so should be
|
||||
# *not* set inside of the --basedir= handler.)
|
||||
datadir_set=
|
||||
|
||||
#
|
||||
# Use LSB init script functions for printing messages, if possible
|
||||
#
|
||||
lsb_functions="/lib/lsb/init-functions"
|
||||
if test -f $lsb_functions ; then
|
||||
. $lsb_functions
|
||||
else
|
||||
log_success_msg()
|
||||
{
|
||||
echo " SUCCESS! $@"
|
||||
}
|
||||
log_failure_msg()
|
||||
{
|
||||
echo " ERROR! $@"
|
||||
}
|
||||
fi
|
||||
|
||||
PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
|
||||
export PATH
|
||||
|
||||
mode=$1 # start or stop
|
||||
|
||||
[ $# -ge 1 ] && shift
|
||||
|
||||
|
||||
other_args=--sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" # uncommon, but needed when called from an RPM upgrade action
|
||||
# Expected: "--skip-networking --skip-grant-tables"
|
||||
# They are not checked here, intentionally, as it is the resposibility
|
||||
# of the "spec" file author to give correct arguments only.
|
||||
|
||||
case `echo "testing\c"`,`echo -n testing` in
|
||||
*c*,-n*) echo_n= echo_c= ;;
|
||||
*c*,*) echo_n=-n echo_c= ;;
|
||||
*) echo_n= echo_c='\c' ;;
|
||||
esac
|
||||
|
||||
parse_server_arguments() {
|
||||
for arg do
|
||||
case "$arg" in
|
||||
--basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
|
||||
bindir="$basedir/bin"
|
||||
if test -z "$datadir_set"; then
|
||||
datadir="$basedir/data"
|
||||
fi
|
||||
sbindir="$basedir/sbin"
|
||||
libexecdir="$basedir/libexec"
|
||||
;;
|
||||
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
|
||||
datadir_set=1
|
||||
;;
|
||||
--pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
|
||||
--service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_pid () {
|
||||
verb="$1" # created | removed
|
||||
pid="$2" # process ID of the program operating on the pid-file
|
||||
pid_file_path="$3" # path to the PID file.
|
||||
|
||||
i=0
|
||||
avoid_race_condition="by checking again"
|
||||
|
||||
while test $i -ne $service_startup_timeout ; do
|
||||
|
||||
case "$verb" in
|
||||
'created')
|
||||
# wait for a PID-file to pop into existence.
|
||||
test -s "$pid_file_path" && i='' && break
|
||||
;;
|
||||
'removed')
|
||||
# wait for this PID-file to disappear
|
||||
test ! -s "$pid_file_path" && i='' && break
|
||||
;;
|
||||
*)
|
||||
echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# if server isn't running, then pid-file will never be updated
|
||||
if test -n "$pid"; then
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
: # the server still runs
|
||||
else
|
||||
# The server may have exited between the last pid-file check and now.
|
||||
if test -n "$avoid_race_condition"; then
|
||||
avoid_race_condition=""
|
||||
continue # Check again.
|
||||
fi
|
||||
|
||||
# there's nothing that will affect the file.
|
||||
log_failure_msg "The server quit without updating PID file ($pid_file_path)."
|
||||
return 1 # not waiting any more.
|
||||
fi
|
||||
fi
|
||||
|
||||
echo $echo_n ".$echo_c"
|
||||
i=`expr $i + 1`
|
||||
sleep 1
|
||||
|
||||
done
|
||||
|
||||
if test -z "$i" ; then
|
||||
log_success_msg
|
||||
return 0
|
||||
else
|
||||
log_failure_msg
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get arguments from the my.cnf file,
|
||||
# the only group, which is read from now on is [mysqld]
|
||||
if test -x "$bindir/my_print_defaults"; then
|
||||
print_defaults="$bindir/my_print_defaults"
|
||||
else
|
||||
# Try to find basedir in /etc/my.cnf
|
||||
conf=/etc/my.cnf
|
||||
print_defaults=
|
||||
if test -r $conf
|
||||
then
|
||||
subpat='^[^=]*basedir[^=]*=\(.*\)$'
|
||||
dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf`
|
||||
for d in $dirs
|
||||
do
|
||||
d=`echo $d | sed -e 's/[ ]//g'`
|
||||
if test -x "$d/bin/my_print_defaults"
|
||||
then
|
||||
print_defaults="$d/bin/my_print_defaults"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Hope it's in the PATH ... but I doubt it
|
||||
test -z "$print_defaults" && print_defaults="my_print_defaults"
|
||||
fi
|
||||
|
||||
#
|
||||
# Read defaults file from 'basedir'. If there is no defaults file there
|
||||
# check if it's in the old (depricated) place (datadir) and read it from there
|
||||
#
|
||||
|
||||
extra_args=""
|
||||
if test -r "$basedir/my.cnf"
|
||||
then
|
||||
extra_args="-e $basedir/my.cnf"
|
||||
else
|
||||
if test -r "$datadir/my.cnf"
|
||||
then
|
||||
extra_args="-e $datadir/my.cnf"
|
||||
fi
|
||||
fi
|
||||
|
||||
parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
|
||||
|
||||
#
|
||||
# Set pid file if not given
|
||||
#
|
||||
if test -z "$mysqld_pid_file_path"
|
||||
then
|
||||
mysqld_pid_file_path=$datadir/`hostname`.pid
|
||||
else
|
||||
case "$mysqld_pid_file_path" in
|
||||
/* ) ;;
|
||||
* ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#ulimit -s unlimited
|
||||
case "$mode" in
|
||||
'start')
|
||||
# Start daemon
|
||||
|
||||
# Safeguard (relative paths, core dumps..)
|
||||
cd $basedir
|
||||
|
||||
echo $echo_n "Starting MySQL"
|
||||
if test -x $bindir/mysqld_safe
|
||||
then
|
||||
# Give extra arguments to mysqld with the my.cnf file. This script
|
||||
# may be overwritten at next upgrade.
|
||||
$bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
|
||||
wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
|
||||
|
||||
# Make lock for RedHat / SuSE
|
||||
if test -w "$lockdir"
|
||||
then
|
||||
touch "$lock_file_path"
|
||||
fi
|
||||
|
||||
exit $return_value
|
||||
else
|
||||
log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"
|
||||
fi
|
||||
;;
|
||||
|
||||
'stop')
|
||||
# Stop daemon. We use a signal here to avoid having to know the
|
||||
# root password.
|
||||
|
||||
if test -s "$mysqld_pid_file_path"
|
||||
then
|
||||
mysqld_pid=`cat "$mysqld_pid_file_path"`
|
||||
|
||||
if (kill -0 $mysqld_pid 2>/dev/null)
|
||||
then
|
||||
echo $echo_n "Shutting down MySQL"
|
||||
kill $mysqld_pid
|
||||
# mysqld should remove the pid file when it exits, so wait for it.
|
||||
wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
|
||||
else
|
||||
log_failure_msg "MySQL server process #$mysqld_pid is not running!"
|
||||
rm "$mysqld_pid_file_path"
|
||||
fi
|
||||
|
||||
# Delete lock for RedHat / SuSE
|
||||
if test -f "$lock_file_path"
|
||||
then
|
||||
rm -f "$lock_file_path"
|
||||
fi
|
||||
exit $return_value
|
||||
else
|
||||
log_failure_msg "MySQL server PID file could not be found!"
|
||||
fi
|
||||
;;
|
||||
|
||||
'restart')
|
||||
# Stop the service and regardless of whether it was
|
||||
# running or not, start it again.
|
||||
if $0 stop $other_args; then
|
||||
$0 start $other_args
|
||||
else
|
||||
log_failure_msg "Failed to stop running server, so refusing to try to start."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
'reload'|'force-reload')
|
||||
if test -s "$mysqld_pid_file_path" ; then
|
||||
read mysqld_pid < "$mysqld_pid_file_path"
|
||||
kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
|
||||
touch "$mysqld_pid_file_path"
|
||||
else
|
||||
log_failure_msg "MySQL PID file could not be found!"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
'status')
|
||||
# First, check to see if pid file exists
|
||||
if test -s "$mysqld_pid_file_path" ; then
|
||||
read mysqld_pid < "$mysqld_pid_file_path"
|
||||
if kill -0 $mysqld_pid 2>/dev/null ; then
|
||||
log_success_msg "MySQL running ($mysqld_pid)"
|
||||
exit 0
|
||||
else
|
||||
log_failure_msg "MySQL is not running, but PID file exists"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Try to find appropriate mysqld process
|
||||
mysqld_pid=`pidof $libexecdir/mysqld`
|
||||
|
||||
# test if multiple pids exist
|
||||
pid_count=`echo $mysqld_pid | wc -w`
|
||||
if test $pid_count -gt 1 ; then
|
||||
log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)"
|
||||
exit 5
|
||||
elif test -z $mysqld_pid ; then
|
||||
if test -f "$lock_file_path" ; then
|
||||
log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
|
||||
exit 2
|
||||
fi
|
||||
log_failure_msg "MySQL is not running"
|
||||
exit 3
|
||||
else
|
||||
log_failure_msg "MySQL is running but PID file could not be found"
|
||||
exit 4
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# usage
|
||||
basename=`basename "$0"`
|
||||
echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -1,692 +0,0 @@
|
||||
/**
|
||||
* 取回数据库列表
|
||||
* @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");
|
||||
});
|
||||
@@ -1,80 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -19,6 +19,12 @@ Install_mysql()
|
||||
mkdir -p ${mysqlDir}
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
|
||||
mkdir -p /var/log/mariadb
|
||||
touch /var/log/mariadb/mariadb.log
|
||||
|
||||
groupadd mysql
|
||||
useradd -g mysql mysql
|
||||
|
||||
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
|
||||
@@ -30,14 +36,25 @@ Install_mysql()
|
||||
|
||||
cd ${mysqlDir}/mysql-5.5.62 && cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$serverPath/mysql \
|
||||
&& make && make install \
|
||||
-DMYSQL_USER=mysql \
|
||||
-DMYSQL_TCP_PORT=3306 \
|
||||
-DMYSQL_UNIX_ADDR=/var/tmp/mysql.sock \
|
||||
-DWITH_MYISAM_STORAGE_ENGINE=1 \
|
||||
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
|
||||
-DWITH_MEMORY_STORAGE_ENGINE=1 \
|
||||
-DENABLED_LOCAL_INFILE=1 \
|
||||
-DWITH_PARTITION_STORAGE_ENGINE=1 \
|
||||
-DEXTRA_CHARSETS=all \
|
||||
-DDEFAULT_CHARSET=utf8 \
|
||||
-DDEFAULT_COLLATION=utf8_general_ci \
|
||||
&& make && make install && make clean \
|
||||
&& echo '5.5' > $serverPath/mysql/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
}
|
||||
|
||||
Uninstall_mysql()
|
||||
{
|
||||
rm -rf $serverPath/mysql
|
||||
#rm -rf $serverPath/mysql
|
||||
echo '卸载完成' > $install_tmp
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,16 @@ events
|
||||
http
|
||||
{
|
||||
include mime.types;
|
||||
|
||||
#include luawaf.conf;
|
||||
|
||||
#include proxy.conf;
|
||||
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for" "$request_time"';
|
||||
|
||||
server_names_hash_bucket_size 512;
|
||||
client_header_buffer_size 32k;
|
||||
large_client_header_buffers 4 32k;
|
||||
@@ -68,6 +72,6 @@ http
|
||||
}
|
||||
include {$SERVER_PATH}/openresty/nginx/conf/php_status/*.conf;
|
||||
}
|
||||
include {$SERVER_PATH}/openresty/nginx/conf/vhost/*.conf;
|
||||
include {$SERVER_PATH}/web_conf/nginx/vhost/*.conf;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,12 @@ def clearTemp():
|
||||
|
||||
|
||||
def getConf():
|
||||
path = getPluginDir() + "/conf/nginx.conf"
|
||||
path = getServerDir() + "/nginx/conf/nginx.conf"
|
||||
return path
|
||||
|
||||
|
||||
def getConfTpl():
|
||||
path = getPluginDir() + '/conf/nginx.conf'
|
||||
return path
|
||||
|
||||
|
||||
@@ -107,7 +112,7 @@ def checkAuthEq(file, owner='root'):
|
||||
|
||||
def confReplace():
|
||||
service_path = os.path.dirname(os.getcwd())
|
||||
content = public.readFile(getConf())
|
||||
content = public.readFile(getConfTpl())
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
|
||||
user = 'www'
|
||||
@@ -121,8 +126,6 @@ def confReplace():
|
||||
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)
|
||||
|
||||
@@ -11,6 +11,14 @@ serverPath=$(dirname "$rootPath")
|
||||
action=$1
|
||||
type=$2
|
||||
|
||||
if id www &> /dev/null ;then
|
||||
echo "www UID is `id -u www`"
|
||||
echo "www Shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
|
||||
else
|
||||
groupadd www
|
||||
useradd -g www -s /sbin/nologin www
|
||||
fi
|
||||
|
||||
if [ "${2}" == "" ];then
|
||||
echo '缺少安装脚本...' > $install_tmp
|
||||
exit 0
|
||||
|
||||
@@ -24,6 +24,7 @@ Install_openresty()
|
||||
cd ${openrestyDir} && tar -zxvf openresty-1.11.2.5.tar.gz
|
||||
|
||||
cd ${openrestyDir}/openresty-1.11.2.5 && ./configure --prefix=$serverPath/openresty \
|
||||
--with-http_v2_module \
|
||||
--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
|
||||
|
||||
@@ -23,6 +23,7 @@ Install_openresty()
|
||||
cd ${openrestyDir} && tar -zxvf openresty-1.13.6.2.tar.gz
|
||||
|
||||
cd ${openrestyDir}/openresty-1.13.6.2 && ./configure --prefix=$serverPath/openresty \
|
||||
--with-http_v2_module \
|
||||
--with-openssl=$serverPath/source/lib/openssl-1.0.2q \
|
||||
--with-http_stub_status_module \
|
||||
&& make && make install && \
|
||||
|
||||
@@ -154,7 +154,7 @@ bcmath.scale = 0
|
||||
|
||||
[Session]
|
||||
session.save_handler = files
|
||||
session.save_path = "MD:/bin/tmp/session"
|
||||
session.save_path = "/tmp/session"
|
||||
session.use_strict_mode = 0
|
||||
session.use_cookies = 1
|
||||
session.use_only_cookies = 1
|
||||
@@ -217,21 +217,3 @@ ldap.max_links = -1
|
||||
;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
|
||||
|
||||
@@ -36,7 +36,7 @@ enable_dl = Off
|
||||
|
||||
|
||||
file_uploads = On
|
||||
upload_tmp_dir = "MD:/bin/tmp/upload"
|
||||
upload_tmp_dir = "/tmp/upload"
|
||||
upload_max_filesize = 2M
|
||||
max_file_uploads = 20
|
||||
|
||||
@@ -153,7 +153,7 @@ bcmath.scale = 0
|
||||
|
||||
[Session]
|
||||
session.save_handler = files
|
||||
session.save_path = "MD:/bin/tmp/session"
|
||||
session.save_path = "/tmp/session"
|
||||
session.use_strict_mode = 0
|
||||
session.use_cookies = 1
|
||||
session.use_only_cookies = 1
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
user = {$PHP_USER}
|
||||
group = {$PHP_GROUP}
|
||||
listen = /tmp/php-cgi-{$PHP_VERSION}.sock
|
||||
listen.owner = {$PHP_USER}
|
||||
listen.group = {$PHP_GROUP}
|
||||
pm = dynamic
|
||||
pm.max_children = 5
|
||||
pm.start_servers = 2
|
||||
|
||||
@@ -54,6 +54,13 @@ def getArgs():
|
||||
return tmp
|
||||
|
||||
|
||||
def checkArgs(data, ck=[]):
|
||||
for i in range(len(ck)):
|
||||
if not ck[i] in data:
|
||||
return (False, public.returnJson(False, '参数:(' + ck[i] + ')没有!'))
|
||||
return (True, public.returnJson(True, 'ok'))
|
||||
|
||||
|
||||
def getConf(version):
|
||||
path = getServerDir() + '/' + version + '/etc/php.ini'
|
||||
return path
|
||||
@@ -80,13 +87,22 @@ def contentReplace(content, version):
|
||||
content = content.replace('{$PHP_USER}', 'nobody')
|
||||
content = content.replace('{$PHP_GROUP}', 'nobody')
|
||||
|
||||
rep = 'listen.owner\s*=\s*(.+)\r?\n'
|
||||
val = ';listen.owner = nobody\n'
|
||||
content = re.sub(rep, val, content)
|
||||
|
||||
rep = 'listen.group\s*=\s*(.+)\r?\n'
|
||||
val = ';listen.group = nobody\n'
|
||||
content = re.sub(rep, val, content)
|
||||
|
||||
rep = 'user\s*=\s*(.+)\r?\n'
|
||||
val = ';user = nobody\n'
|
||||
content = re.sub(rep, val, content)
|
||||
|
||||
rep = 'group\s*=\s*(.+)\r?\n'
|
||||
rep = r'[^\.]group\s*=\s*(.+)\r?\n'
|
||||
val = ';group = nobody\n'
|
||||
content = re.sub(rep, val, content)
|
||||
|
||||
else:
|
||||
content = content.replace('{$PHP_USER}', 'www')
|
||||
content = content.replace('{$PHP_GROUP}', 'www')
|
||||
@@ -165,6 +181,12 @@ def initReplace(version):
|
||||
phpFpmWwwReplace(version)
|
||||
phpFpmReplace(version)
|
||||
|
||||
session_path = '/tmp/session'
|
||||
if not os.path.exists(session_path):
|
||||
os.mkdir(session_path)
|
||||
if not public.isAppleSystem():
|
||||
public.execShell('chmod -R www:www' + session_path)
|
||||
|
||||
return file_bin
|
||||
|
||||
|
||||
@@ -285,8 +307,10 @@ def getLimitConf(version):
|
||||
|
||||
def setMaxTime(version):
|
||||
args = getArgs()
|
||||
if not 'time' in args:
|
||||
return 'missing time args!'
|
||||
data = checkArgs(args, ['time'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
time = args['time']
|
||||
if int(time) < 30 or int(time) > 86400:
|
||||
return public.returnJson(False, '请填写30-86400间的值!')
|
||||
@@ -471,35 +495,79 @@ def checkPhpinfoFile(version):
|
||||
def getPhpinfo(version):
|
||||
checkPhpinfoFile(version)
|
||||
sPath = public.getRootDir() + '/phpinfo/' + version
|
||||
public.execShell("rm -rf " + public.getRootDir() + '/phpinfo')
|
||||
# public.execShell("rm -rf " + public.getRootDir() + '/phpinfo')
|
||||
public.execShell("mkdir -p " + sPath)
|
||||
public.writeFile(sPath + '/phpinfo.php', '<?php phpinfo(); ?>')
|
||||
phpinfo = public.httpGet('http://127.0.0.1/' + version + '/phpinfo.php')
|
||||
os.system("rm -rf " + public.getRootDir() + '/phpinfo')
|
||||
# print 'http://127.0.0.1/' + version + '/phpinfo.php'
|
||||
phpinfo = public.httpGet('http://127.0.0.1/' + version + '/phpinfo.php', 3)
|
||||
# os.system("rm -rf " + public.getRootDir() + '/phpinfo')
|
||||
return phpinfo
|
||||
|
||||
|
||||
def getLibConf(version):
|
||||
fname = public.getServerDir() + '/php/' + version + '/etc/php.ini'
|
||||
if not os.path.exists(filename):
|
||||
if not os.path.exists(fname):
|
||||
return public.returnJson(False, '指定PHP版本不存在!')
|
||||
|
||||
data = {}
|
||||
rep = "disable_functions\s*=\s{0,1}(.*)\n"
|
||||
tmp = re.search(rep, phpini).groups()
|
||||
data['disable_functions'] = tmp[0]
|
||||
phpini = public.readFile(fname)
|
||||
|
||||
rep = "upload_max_filesize\s*=\s*([0-9]+)(M|m|K|k)"
|
||||
tmp = re.search(rep, phpini).groups()
|
||||
data['max'] = tmp[0]
|
||||
libpath = getPluginDir() + '/versions/phplib.conf'
|
||||
phplib = json.loads(public.readFile(libpath))
|
||||
|
||||
rep = ur"\n;*\s*cgi\.fix_pathinfo\s*=\s*([0-9]+)\s*\n"
|
||||
tmp = re.search(rep, phpini).groups()
|
||||
if tmp[0] == '0':
|
||||
data['pathinfo'] = False
|
||||
else:
|
||||
data['pathinfo'] = True
|
||||
return public.getJson(data)
|
||||
libs = []
|
||||
tasks = public.M('tasks').where(
|
||||
"status!=?", ('1',)).field('status,name').select()
|
||||
for lib in phplib:
|
||||
lib['task'] = '1'
|
||||
for task in tasks:
|
||||
tmp = public.getStrBetween('[', ']', task['name'])
|
||||
if not tmp:
|
||||
continue
|
||||
tmp1 = tmp.split('-')
|
||||
if tmp1[0].lower() == lib['name'].lower():
|
||||
lib['task'] = task['status']
|
||||
lib['phpversions'] = []
|
||||
lib['phpversions'].append(tmp1[1])
|
||||
if phpini.find(lib['check']) == -1:
|
||||
lib['status'] = False
|
||||
else:
|
||||
lib['status'] = True
|
||||
libs.append(lib)
|
||||
return public.returnJson(True, 'OK!', libs)
|
||||
|
||||
|
||||
def installLib(version):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
name = args['name']
|
||||
execstr = "cd " + getPluginDir() + '/versions/' + version + " && /bin/bash " + \
|
||||
name + '.sh' + ' install ' + version
|
||||
|
||||
rettime = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
insert_info = (None, '安装[' + name + '-' + version + ']',
|
||||
'execshell', '0', rettime, execstr)
|
||||
public.M('tasks').add('id,name,type,status,addtime,execstr', insert_info)
|
||||
return public.returnJson(True, '已将下载任务添加到队列!')
|
||||
|
||||
|
||||
def uninstallLib(version):
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['name'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
name = args['name']
|
||||
execstr = "cd " + getPluginDir() + '/versions/' + version + " && /bin/bash " + \
|
||||
name + '.sh' + ' uninstall ' + version
|
||||
|
||||
rettime = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
insert_info = (None, '安装[' + name + '-' + version + ']',
|
||||
'execshell', '0', rettime, execstr)
|
||||
public.M('tasks').add('id,name,type,status,addtime,execstr', insert_info)
|
||||
return public.returnJson(True, '已将卸载载任务添加到队列!')
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -550,5 +618,9 @@ if __name__ == "__main__":
|
||||
print getPhpinfo(version)
|
||||
elif func == 'get_lib_conf':
|
||||
print getLibConf(version)
|
||||
elif func == 'install_lib':
|
||||
print installLib(version)
|
||||
elif func == 'uninstall_lib':
|
||||
print uninstallLib(version)
|
||||
else:
|
||||
print "fail"
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
function phpPost(method,version, args,callback){
|
||||
|
||||
function str2Obj(str){
|
||||
var data = {};
|
||||
kv = str.split('&');
|
||||
for(i in kv){
|
||||
v = kv[i].split('=');
|
||||
data[v[0]] = v[1];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function phpPost(method, version, args,callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
|
||||
var req_data = {};
|
||||
@@ -6,7 +17,9 @@ function phpPost(method,version, args,callback){
|
||||
req_data['func'] = method;
|
||||
req_data['version'] = version;
|
||||
|
||||
if (typeof(args) != 'undefined' && args!=''){
|
||||
if (typeof(args) == 'string'){
|
||||
req_data['args'] = JSON.stringify(str2Obj(args));
|
||||
} else {
|
||||
req_data['args'] = JSON.stringify(args);
|
||||
}
|
||||
|
||||
@@ -312,11 +325,10 @@ function disableFunc(version) {
|
||||
"<tbody id='blacktable'>" + dbody + "</tbody>" +
|
||||
"</table></div>";
|
||||
|
||||
con += '\
|
||||
<ul class="help-info-text">\
|
||||
<li>在此处可以禁用指定函数的调用,以增强环境安全性!</li>\
|
||||
<li>强烈建议禁用如exec,system等危险函数!</li>\
|
||||
</ul>';
|
||||
con += '<ul class="help-info-text">\
|
||||
<li>在此处可以禁用指定函数的调用,以增强环境安全性!</li>\
|
||||
<li>强烈建议禁用如exec,system等危险函数!</li>\
|
||||
</ul>';
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
});
|
||||
@@ -382,122 +394,86 @@ function getPHPInfo(version) {
|
||||
|
||||
function phpLibConfig(version){
|
||||
|
||||
}
|
||||
phpPost('get_lib_conf', version, '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var libs = rdata.data;
|
||||
|
||||
var body = '';
|
||||
var opt = '';
|
||||
for (var i = 0; i < libs.length; i++) {
|
||||
if (libs[i].versions.indexOf(version) == -1){
|
||||
continue;
|
||||
}
|
||||
|
||||
//设置PATHINFO
|
||||
function setPathInfo(version, type) {
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/config?action=setPathInfo', 'version=' + version + '&type=' + type, function(rdata) {
|
||||
var pathinfo = (type == 'on') ? true : false;
|
||||
var pathinfoOpt = '<a style="color:red;" href="javascript:SetPathInfo(\'' + version + '\',\'off\');">' + lan.public.off + '</a>'
|
||||
if (!pathinfo) {
|
||||
pathinfoOpt = '<a class="link" href="javascript:SetPathInfo(\'' + version + '\',\'on\');">' + lan.public.on + '</a>'
|
||||
}
|
||||
var pathinfo1 = '<td>PATH_INFO</td><td>' + lan.soft.php_menu_ext + '</td><td>' + lan.soft.mvc_ps + '</td><td><span class="ico-' + (pathinfo ? 'start' : 'stop') + ' glyphicon glyphicon-' + (pathinfo ? 'ok' : 'remove') + '"></span></td><td style="text-align: right;" width="50">' + pathinfoOpt + '</td>';
|
||||
$("#pathInfo").html(pathinfo1);
|
||||
$(".bt-w-menu .bgw").attr('onclick', "SetPHPConfig('" + version + "'," + pathinfo + ",1)");
|
||||
$(".bt-w-menu .bgw a").attr('href', "javascript:SetPHPConfig('" + version + "'," + pathinfo + ",1);");
|
||||
layer.msg(rdata.msg, { icon: 1 });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//PHP扩展配置
|
||||
function setPHPConfig(version, pathinfo, go) {
|
||||
$.get('/ajax?action=GetPHPConfig&version=' + version, function(rdata) {
|
||||
var body = ""
|
||||
var opt = ""
|
||||
for (var i = 0; i < rdata.libs.length; i++) {
|
||||
if (rdata.libs[i].versions.indexOf(version) == -1) continue;
|
||||
if (rdata.libs[i]['task'] == '-1' && rdata.libs[i].phpversions.indexOf(version) != -1) {
|
||||
opt = '<a style="color:green;" href="javascript:messagebox();">' + lan.soft.the_install + '</a>'
|
||||
} else if (rdata.libs[i]['task'] == '0' && rdata.libs[i].phpversions.indexOf(version) != -1) {
|
||||
opt = '<a style="color:#C0C0C0;" href="javascript:messagebox();">' + lan.soft.sleep_install + '</a>'
|
||||
} else if (rdata.libs[i].status) {
|
||||
opt = '<a style="color:red;" href="javascript:UninstallPHPLib(\'' + version + '\',\'' + rdata.libs[i].name + '\',\'' + rdata.libs[i].title + '\',' + pathinfo + ');">' + lan.soft.uninstall + '</a>'
|
||||
if (libs[i]['task'] == '-1' && libs[i].phpversions.indexOf(version) != -1) {
|
||||
opt = '<a style="color:green;" href="javascript:messageBox();">安装</a>'
|
||||
} else if (libs[i]['task'] == '0' && libs[i].phpversions.indexOf(version) != -1) {
|
||||
opt = '<a style="color:#C0C0C0;" href="javascript:messageBox();">等待安装...</a>'
|
||||
} else if (libs[i].status) {
|
||||
opt = '<a style="color:red;" href="javascript:uninstallPHPLib(\'' + version + '\',\'' + libs[i].name + '\',\'' + libs[i].title + '\',' + '' + ');">卸载</a>'
|
||||
} else {
|
||||
opt = '<a class="btlink" href="javascript:InstallPHPLib(\'' + version + '\',\'' + rdata.libs[i].name + '\',\'' + rdata.libs[i].title + '\',' + pathinfo + ');">' + lan.soft.install + '</a>'
|
||||
opt = '<a class="btlink" href="javascript:installPHPLib(\'' + version + '\',\'' + libs[i].name + '\',\'' + libs[i].title + '\',' + '' + ');">安装</a>'
|
||||
}
|
||||
|
||||
body += '<tr>' +
|
||||
'<td>' + rdata.libs[i].name + '</td>' +
|
||||
'<td>' + rdata.libs[i].type + '</td>' +
|
||||
'<td>' + rdata.libs[i].msg + '</td>' +
|
||||
'<td><span class="ico-' + (rdata.libs[i].status ? 'start' : 'stop') + ' glyphicon glyphicon-' + (rdata.libs[i].status ? 'ok' : 'remove') + '"></span></td>' +
|
||||
'<td>' + libs[i].name + '</td>' +
|
||||
'<td>' + libs[i].type + '</td>' +
|
||||
'<td>' + libs[i].msg + '</td>' +
|
||||
'<td><span class="ico-' + (libs[i].status ? 'start' : 'stop') + ' glyphicon glyphicon-' + (libs[i].status ? 'ok' : 'remove') + '"></span></td>' +
|
||||
'<td style="text-align: right;">' + opt + '</td>' +
|
||||
'</tr>'
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
var pathinfoOpt = '<a style="color:red;" href="javascript:SetPathInfo(\'' + version + '\',\'off\');">' + lan.soft.off + '</a>'
|
||||
if (!rdata.pathinfo) {
|
||||
pathinfoOpt = '<a class="btlink" href="javascript:SetPathInfo(\'' + version + '\',\'on\');">' + lan.soft.on + '</a>'
|
||||
}
|
||||
var pathinfo1 = '<tr id="pathInfo"><td>PATH_INFO</td><td>' + lan.soft.php_menu_ext + '</td><td>' + lan.soft.mvc_ps + '</td><td><span class="ico-' + (rdata.pathinfo ? 'start' : 'stop') + ' glyphicon glyphicon-' + (rdata.pathinfo ? 'ok' : 'remove') + '"></span></td><td style="text-align: right;" width="50">' + pathinfoOpt + '</td></tr>';
|
||||
|
||||
var con = '<div class="divtable" id="phpextdiv" style="margin-right:10px;height: 420px; overflow: auto; margin-right: 0px;">' +
|
||||
'<table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">' +
|
||||
'<thead>' +
|
||||
'<tr>' +
|
||||
'<th>' + lan.soft.php_ext_name + '</th>' +
|
||||
'<th width="64">' + lan.soft.php_ext_type + '</th>' +
|
||||
'<th>' + lan.soft.php_ext_ps + '</th>' +
|
||||
'<th width="40">' + lan.soft.php_ext_status + '</th>' +
|
||||
'<th style="text-align: right;" width="50">' + lan.public.action + '</th>' +
|
||||
'<th>名称</th>' +
|
||||
'<th width="64">类型</th>' +
|
||||
'<th>说明</th>' +
|
||||
'<th width="40">状态</th>' +
|
||||
'<th style="text-align: right;" width="50">操作</th>' +
|
||||
'</tr>' +
|
||||
'</thead>' +
|
||||
'<tbody>' + pathinfo1 + body + '</tbody>' +
|
||||
'<tbody>' + body + '</tbody>' +
|
||||
'</table>' +
|
||||
'</div>' +
|
||||
'<ul class="help-info-text c7 pull-left"><li>请按实际需求安装扩展,不要安装不必要的PHP扩展,这会影响PHP执行效率,甚至出现异常</li><li>Redis扩展只允许在1个PHP版本中使用,安装到其它PHP版本请在[软件管理]重装Redis</li><li>opcache/xcache/apc等脚本缓存扩展,请只安装其中1个,否则可能导致您的站点程序异常</li></ul>';
|
||||
var divObj = document.getElementById('phpextdiv');
|
||||
var scrollTopNum = 0;
|
||||
if (divObj) scrollTopNum = divObj.scrollTop;
|
||||
$(".soft-man-con").html(con);
|
||||
document.getElementById('phpextdiv').scrollTop = scrollTopNum;
|
||||
'<ul class="help-info-text c7 pull-left">\
|
||||
<li>请按实际需求安装扩展,不要安装不必要的PHP扩展,这会影响PHP执行效率,甚至出现异常</li>\
|
||||
<li>Redis扩展只允许在1个PHP版本中使用,安装到其它PHP版本请在[软件管理]重装Redis</li>\
|
||||
<li>opcache/xcache/apc等脚本缓存扩展,请只安装其中1个,否则可能导致您的站点程序异常</li>\
|
||||
</ul>';
|
||||
$('.soft-man-con').html(con);
|
||||
});
|
||||
|
||||
if (go == undefined) {
|
||||
setTimeout(function() {
|
||||
if ($(".bgw #phpext").html() != '安装扩展') {
|
||||
return;
|
||||
}
|
||||
SetPHPConfig(version, pathinfo);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
//安装扩展
|
||||
function InstallPHPLib(version, name, title, pathinfo) {
|
||||
layer.confirm(lan.soft.php_ext_install_confirm.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
|
||||
function installPHPLib(version, name, title, pathinfo) {
|
||||
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
|
||||
name = name.toLowerCase();
|
||||
var data = "name=" + name + "&version=" + version + "&type=1";
|
||||
var loadT = layer.msg(lan.soft.add_install, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/files?action=InstallSoft', data, function(rdata) {
|
||||
setTimeout(function() {
|
||||
layer.close(loadT);
|
||||
SetPHPConfig(version, pathinfo, true);
|
||||
setTimeout(function() {
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
fly("bi-btn");
|
||||
InstallTips();
|
||||
GetTaskCount();
|
||||
phpPost('install_lib', version, data, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
getTaskCount();
|
||||
phpLibConfig(version);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//卸载扩展
|
||||
function UninstallPHPLib(version, name, title, pathinfo) {
|
||||
layer.confirm(lan.soft.php_ext_uninstall_confirm.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
|
||||
function uninstallPHPLib(version, name, title, pathinfo) {
|
||||
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
|
||||
name = name.toLowerCase();
|
||||
var data = 'name=' + name + '&version=' + version;
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/files?action=UninstallSoft', data, function(rdata) {
|
||||
layer.close(loadT);
|
||||
phpPost('uninstall_lib', version, data, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
SetPHPConfig(version, pathinfo, true);
|
||||
getTaskCount();
|
||||
phpLibConfig(version);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -37,15 +37,25 @@ cd $sourcePath/php/php-5.6.36 && ./configure \
|
||||
--exec-prefix=$serverPath/php/56 \
|
||||
--with-config-file-path=$serverPath/php/56/etc \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--with-mysql=mysqlnd \
|
||||
--with-pdo-mysql=mysqlnd \
|
||||
--with-mysqli=mysqlnd \
|
||||
--without-iconv \
|
||||
--enable-zip \
|
||||
--enable-mbstring \
|
||||
--enable-ftp \
|
||||
--enable-pcntl \
|
||||
--enable-shmop \
|
||||
--enable-sysvmsg \
|
||||
--enable-sysvsem \
|
||||
--enable-sysvshm \
|
||||
--enable-sockets \
|
||||
--enable-intl \
|
||||
--enable-wddx \
|
||||
--enable-soap \
|
||||
--enable-posix \
|
||||
--enable-fpm \
|
||||
&& make && make install
|
||||
&& make clean && make && make install && make clean
|
||||
|
||||
#------------------------ install end ------------------------------------#
|
||||
}
|
||||
@@ -54,6 +64,7 @@ cd $sourcePath/php/php-5.6.36 && ./configure \
|
||||
|
||||
Uninstall_php()
|
||||
{
|
||||
rm -rf $serverPath/php/56
|
||||
echo "卸载php-5.6.36 ..." > $install_tmp
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
LIBNAME=memcache
|
||||
|
||||
sysName=`uname`
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
|
||||
wget -O $php_lib/memcache-2.2.7.tgz http://pecl.php.net/get/memcache-2.2.7.tgz
|
||||
|
||||
cd $php_lib && tar xvf memcache-2.2.7.tgz
|
||||
cd memcache-2.2.7
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config --enable-memcache --with-zlib-dir
|
||||
make && make install
|
||||
|
||||
cd $php_lib
|
||||
rm -rf memcache-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return
|
||||
fi
|
||||
echo "extension=memcache.so" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装${LIBNAME},请选择其它版本!"
|
||||
echo "php-$vphp not install memcache, Plese select other version!"
|
||||
return
|
||||
fi
|
||||
|
||||
sed -i '_bak' '/memcache.so/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
LIBNAME=mongo
|
||||
|
||||
sysName=`uname`
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
|
||||
wget -O $php_lib/mongo-1.6.16.tgz http://pecl.php.net/get/mongo-1.6.16.tgz
|
||||
|
||||
cd $php_lib && tar xvf mongo-1.6.16.tgz
|
||||
cd mongo-1.6.16
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
make && make install
|
||||
|
||||
cd $php_lib
|
||||
rm -rf mongo-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return
|
||||
fi
|
||||
echo "extension=mongo.so" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装${LIBNAME},请选择其它版本!"
|
||||
echo "php-$vphp not install memcache, Plese select other version!"
|
||||
return
|
||||
fi
|
||||
|
||||
sed -i '_bak' '/mongo.so/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
LIBNAME=redis
|
||||
|
||||
sysName=`uname`
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
|
||||
wget -O $php_lib/redis-4.2.0.tgz http://pecl.php.net/get/redis-4.2.0.tgz
|
||||
|
||||
cd $php_lib && tar xvf redis-4.2.0.tgz
|
||||
cd redis-4.2.0
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
make && make install
|
||||
|
||||
cd $php_lib
|
||||
rm -rf redis-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return
|
||||
fi
|
||||
echo "extension=redis.so" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装${LIBNAME},请选择其它版本!"
|
||||
echo "php-$vphp not install memcache, Plese select other version!"
|
||||
return
|
||||
fi
|
||||
|
||||
sed -i '_bak' '/redis.so/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/swoole.so
|
||||
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep 'swoole.so'`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php-$version 已安装yaf,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
wafV='1.10.1';
|
||||
if [ "$version" = '70' ] || [ "$version" = '71' ] || [ "$version" = '72' ];then
|
||||
wafV='2.2.0';
|
||||
fi
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
wget -O $php_lib/swoole-$wafV.tgz http://pecl.php.net/get/swoole-$wafV.tgz
|
||||
cd $php_lib
|
||||
tar xvf swoole-$wafV.tgz
|
||||
cd swoole-$wafV
|
||||
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config \
|
||||
--enable-openssl --with-openssl-dir=$serverPath/lib/openssl --enable-sockets
|
||||
make && make install
|
||||
cd ..
|
||||
rm -rf swoole-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return;
|
||||
fi
|
||||
echo "extension=$extFile"
|
||||
echo "extension=$extFile" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/swoole.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装swoole,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
echo $serverPath/php/$version/etc/php.ini
|
||||
sed -i '_bak' '/swoole.so/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/yaf.so
|
||||
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep 'yaf.so'`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php-$version 已安装yaf,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
wafV='2.3.5';
|
||||
if [ "$version" = '70' ] || [ "$version" = '71' ] || [ "$version" = '72' ];then
|
||||
wafV='3.0.7';
|
||||
fi
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
wget -O $php_lib/yaf-$wafV.tgz http://pecl.php.net/get/yaf-$wafV.tgz
|
||||
cd $php_lib
|
||||
tar xvf yaf-$wafV.tgz
|
||||
cd yaf-$wafV
|
||||
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
make && make install
|
||||
cd ..
|
||||
rm -rf yaf-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return;
|
||||
fi
|
||||
|
||||
echo -e "[yaf]\nextension=yaf.so\nyaf.use_namespace=1" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/yaf.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装yaf,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
echo $serverPath/php/$version/etc/php.ini
|
||||
sed -i '_bak' '/yaf.so/d' $serverPath/php/$version/etc/php.ini
|
||||
sed -i '_bak' '/yaf.use_namespace/d' $serverPath/php/$version/etc/php.ini
|
||||
sed -i '_bak' '/\[yaf\]/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
LIBNAME=ZendGuardLoader
|
||||
|
||||
sysName=`uname`
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
|
||||
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
|
||||
if [ $sysName == 'Darwin' ]; then
|
||||
wget -O $php_lib/zend-loader-php5.6.tar.gz http://downloads.zend.com/guard/7.0.0/zend-loader-php5.6-darwin10.7-x86_64_update1.tar.gz
|
||||
else
|
||||
wget -O $php_lib/zend-loader-php5.6.tar.gz http://downloads.zend.com/guard/7.0.0/zend-loader-php5.6-linux-x86_64_update1.tar.gz
|
||||
fi
|
||||
|
||||
|
||||
cd $php_lib && tar xvf zend-loader-php5.6.tar.gz
|
||||
cd zend-loader-php5.6*
|
||||
cp ZendGuardLoader.so $serverPath/php/$version/lib/php/extensions/no-debug-non-zts-20131226/
|
||||
|
||||
rm -rf $php_lib/zend-loader-php5.6*
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "[Zend ZendGuard Loader]\nzend_extension=ZendGuardLoader.so\nzend_loader.enable=1\nzend_loader.disable_licensing=0\nzend_loader.obfuscation_level_support=3\nzend_loader.license_path=" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20131226/${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
sed -i '_bak' '/ZendGuardLoader.so/d' $serverPath/php/$version/etc/php.ini
|
||||
sed -i '_bak' '/zend_loader/d' $serverPath/php/$version/etc/php.ini
|
||||
sed -i '_bak' '/\[Zend ZendGuard Loader\]/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -37,6 +37,7 @@ cd $sourcePath/php/php-7.2.5 && ./configure \
|
||||
--exec-prefix=$serverPath/php/72 \
|
||||
--with-config-file-path=$serverPath/php/72/etc \
|
||||
--with-zlib-dir=$serverPath/lib/zlib \
|
||||
--enable-mysqlnd \
|
||||
--without-iconv \
|
||||
--enable-zip \
|
||||
--enable-mbstring \
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
sourcePath=${serverPath}/source/php
|
||||
|
||||
LIBNAME=redis
|
||||
sysName=`uname`
|
||||
actionType=$1
|
||||
version=$2
|
||||
|
||||
extDir=$serverPath/php/${version}/lib/php/extensions/no-debug-non-zts-20170718/
|
||||
|
||||
Install_lib()
|
||||
{
|
||||
isInstall=`cat $serverPath/php/$version/etc/php.ini|grep "${LIBNAME}.so"`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php$version 已安装${LIBNAME},请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$extDir${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
|
||||
php_lib=$sourcePath/php_${version}_lib
|
||||
mkdir -p $php_lib
|
||||
|
||||
if [ ! -f $php_lib/redis-4.2.0.tgz ];then
|
||||
wget -O $php_lib/redis-4.2.0.tgz http://pecl.php.net/get/redis-4.2.0.tgz
|
||||
fi
|
||||
|
||||
cd $php_lib && tar xvf redis-4.2.0.tgz
|
||||
cd redis-4.2.0
|
||||
$serverPath/php/$version/bin/phpize
|
||||
./configure --with-php-config=$serverPath/php/$version/bin/php-config
|
||||
make && make install
|
||||
|
||||
cd $php_lib
|
||||
rm -rf redis-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
sleep 1
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return
|
||||
fi
|
||||
echo "extension=redis.so" >> $serverPath/php/$version/etc/php.ini
|
||||
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_lib()
|
||||
{
|
||||
if [ ! -f "$serverPath/php/$version/bin/php-config" ];then
|
||||
echo "php$version 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
extFile=$extDir${LIBNAME}.so
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php$version 未安装${LIBNAME},请选择其它版本!"
|
||||
echo "php-$vphp not install memcache, Plese select other version!"
|
||||
return
|
||||
fi
|
||||
|
||||
sed -i '_bak' '/redis.so/d' $serverPath/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
$serverPath/php/init.d/php$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_lib
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_lib
|
||||
fi
|
||||
@@ -0,0 +1,473 @@
|
||||
[
|
||||
{
|
||||
"name": "ZendGuardLoader",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56"
|
||||
],
|
||||
"type": "脚本解密",
|
||||
"msg": "用于解密ZendGuard加密脚本!",
|
||||
"shell": "zend_guard_loader.sh",
|
||||
"check": "ZendGuardLoader.so"
|
||||
},
|
||||
{
|
||||
"name": "ZendOptimizer",
|
||||
"versions": [
|
||||
"52"
|
||||
],
|
||||
"type": "脚本解密",
|
||||
"msg": "用于解密ZendOptimizer加密脚本!",
|
||||
"shell": "zend_optimizer.sh",
|
||||
"check": "ZendOptimizer.so"
|
||||
},
|
||||
{
|
||||
"name": "ionCube",
|
||||
"versions": [],
|
||||
"type": "脚本解密",
|
||||
"msg": "用于解密ionCube Encoder加密脚本!",
|
||||
"shell": "ioncube.sh",
|
||||
"check": "ioncube_loader_lin"
|
||||
},
|
||||
{
|
||||
"name": "fileinfo",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "用于获取文件MIME,编码等信息!",
|
||||
"shell": "fileinfo.sh",
|
||||
"check": "fileinfo.so"
|
||||
},
|
||||
{
|
||||
"name": "opcache",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "用于加速PHP脚本!",
|
||||
"shell": "opcache.sh",
|
||||
"check": "opcache.so"
|
||||
},
|
||||
{
|
||||
"name": "xcache",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "支持脚本缓存和变量缓存!",
|
||||
"shell": "xcache.sh",
|
||||
"check": "xcache.so"
|
||||
},
|
||||
{
|
||||
"name": "memcache",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "强大的内容缓存器,不支持集群",
|
||||
"shell": "memcache.sh",
|
||||
"check": "memcache.so"
|
||||
},
|
||||
{
|
||||
"name": "memcached",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "强大的内容缓存器,支持集群",
|
||||
"shell": "memcached.sh",
|
||||
"check": "memcached.so"
|
||||
},
|
||||
{
|
||||
"name": "redis",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71",
|
||||
"72"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "更强大的内容缓存器,支持集群",
|
||||
"shell": "redis.sh",
|
||||
"check": "redis.so"
|
||||
},
|
||||
{
|
||||
"name": "apc",
|
||||
"versions": [
|
||||
"53",
|
||||
"54"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "脚本缓存器",
|
||||
"shell": "apc.sh",
|
||||
"check": "apc.so"
|
||||
},
|
||||
{
|
||||
"name": "imagemagick",
|
||||
"versions": [
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "比GD更强大的图形库",
|
||||
"shell": "imagemagick.sh",
|
||||
"check": "imagick.so"
|
||||
},
|
||||
{
|
||||
"name": "xdebug",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "调试器",
|
||||
"msg": "不多说,不了解的不要安装",
|
||||
"shell": "xdebug.sh",
|
||||
"check": "xdebug.so"
|
||||
},
|
||||
{
|
||||
"name": "imap",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "邮件服务",
|
||||
"msg": "邮件服务器必备",
|
||||
"shell": "imap.sh",
|
||||
"check": "imap.so"
|
||||
},
|
||||
{
|
||||
"name": "exif",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "用于读取图片EXIF信息",
|
||||
"shell": "exif.sh",
|
||||
"check": "exif.so"
|
||||
},
|
||||
{
|
||||
"name": "intl",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "提供国际化支持",
|
||||
"shell": "intl.sh",
|
||||
"check": "intl.so"
|
||||
},
|
||||
{
|
||||
"name": "xsl",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "xsl解析扩展",
|
||||
"shell": "xsl.sh",
|
||||
"check": "xsl.so"
|
||||
},
|
||||
{
|
||||
"name": "Swoole",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "异步、并行、高性能网络通信引擎",
|
||||
"shell": "swoole.sh",
|
||||
"check": "swoole.so"
|
||||
},
|
||||
{
|
||||
"name": "eAccelerator",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "内容缓存器",
|
||||
"shell": "eaccelerator.sh",
|
||||
"check": "eaccelerator.so"
|
||||
},
|
||||
{
|
||||
"name": "yaf",
|
||||
"versions": [
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "框架",
|
||||
"msg": "Yaf是一个C语言编写的PHP框架",
|
||||
"shell": "yaf.sh",
|
||||
"check": "yaf.so"
|
||||
},
|
||||
{
|
||||
"name": "mongo",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "Mongodb数据库连接驱动",
|
||||
"shell": "mongo.sh",
|
||||
"check": "mongo.so"
|
||||
},
|
||||
{
|
||||
"name": "yac",
|
||||
"versions": [
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "缓存器",
|
||||
"msg": "高性能无锁共享内存Cache",
|
||||
"shell": "yac.sh",
|
||||
"check": "yac.so"
|
||||
},
|
||||
{
|
||||
"name": "sg11",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "脚本加密",
|
||||
"msg": "php代码混淆加密",
|
||||
"shell": "sg11.sh",
|
||||
"check": "ixed.lin"
|
||||
},
|
||||
{
|
||||
"name": "readline",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "readline.sh",
|
||||
"check": "readline.so"
|
||||
},
|
||||
{
|
||||
"name": "snmp",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "snmp.sh",
|
||||
"check": "snmp.so"
|
||||
},
|
||||
{
|
||||
"name": "recode",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "recode.sh",
|
||||
"check": "recode.so"
|
||||
},
|
||||
{
|
||||
"name": "enchant",
|
||||
"versions": [
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "enchant.sh",
|
||||
"check": "enchant.so"
|
||||
},
|
||||
{
|
||||
"name": "pspell",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "pspell.sh",
|
||||
"check": "pspell.so"
|
||||
},
|
||||
{
|
||||
"name": "bz2",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "bz2.sh",
|
||||
"check": "bz2.so"
|
||||
},
|
||||
{
|
||||
"name": "sysvshm",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "sysvshm.sh",
|
||||
"check": "sysvshm.so"
|
||||
},
|
||||
{
|
||||
"name": "calendar",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "calendar.sh",
|
||||
"check": "calendar.so"
|
||||
},
|
||||
{
|
||||
"name": "gmp",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"56",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "gmp.sh",
|
||||
"check": "gmp.so"
|
||||
},
|
||||
{
|
||||
"name": "wddx",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "wddx.sh",
|
||||
"check": "wddx.so"
|
||||
},
|
||||
{
|
||||
"name": "sysvmsg",
|
||||
"versions": [
|
||||
"52",
|
||||
"53",
|
||||
"54",
|
||||
"55",
|
||||
"70",
|
||||
"71"
|
||||
],
|
||||
"type": "通用扩展",
|
||||
"msg": "php官方扩展",
|
||||
"shell": "sysvmsg.sh",
|
||||
"check": "sysvmsg.so"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
curPath=`pwd`
|
||||
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
echo $serverPath
|
||||
Install_yaf()
|
||||
{
|
||||
case "${version}" in
|
||||
'54')
|
||||
extFile='/www/server/php/54/lib/php/extensions/no-debug-non-zts-20100525/yaf.so'
|
||||
;;
|
||||
'55')
|
||||
extFile='/www/server/php/55/lib/php/extensions/no-debug-non-zts-20121212/yaf.so'
|
||||
;;
|
||||
'56')
|
||||
extFile='/www/server/php/56/lib/php/extensions/no-debug-non-zts-20131226/yaf.so'
|
||||
;;
|
||||
'70')
|
||||
extFile='/www/server/php/70/lib/php/extensions/no-debug-non-zts-20151012/yaf.so'
|
||||
;;
|
||||
'71')
|
||||
extFile='/www/server/php/71/lib/php/extensions/no-debug-non-zts-20160303/yaf.so'
|
||||
;;
|
||||
'71')
|
||||
extFile='/www/server/php/71/lib/php/extensions/no-debug-non-zts-20160303/yaf.so'
|
||||
;;
|
||||
'72')
|
||||
extFile='/www/server/php/72/lib/php/extensions/no-debug-non-zts-20170718/yaf.so'
|
||||
;;
|
||||
esac
|
||||
|
||||
isInstall=`cat /www/server/php/$version/etc/php.ini|grep 'yaf.so'`
|
||||
if [ "${isInstall}" != "" ];then
|
||||
echo "php-$vphp 已安装yaf,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
public_file=/www/server/panel/install/public.sh
|
||||
if [ ! -f $public_file ];then
|
||||
wget -O $public_file http://download.bt.cn/install/public.sh -T 5;
|
||||
fi
|
||||
. $public_file
|
||||
|
||||
download_Url=$NODE_URL
|
||||
|
||||
wafV='2.3.5';
|
||||
if [ "$version" = '70' ] || [ "$version" = '71' ] || [ "$version" = '72' ];then
|
||||
wafV='3.0.7';
|
||||
fi
|
||||
wget -O yaf-$wafV.tgz $download_Url/src/yaf-$wafV.tgz
|
||||
tar xvf yaf-$wafV.tgz
|
||||
cd yaf-$wafV
|
||||
|
||||
/www/server/php/$version/bin/phpize
|
||||
./configure --with-php-config=/www/server/php/$version/bin/php-config
|
||||
make && make install
|
||||
cd ..
|
||||
rm -rf yaf-*
|
||||
rm -f package.xml
|
||||
fi
|
||||
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "ERROR!"
|
||||
return;
|
||||
fi
|
||||
echo "extension=$extFile" >> /www/server/php/$version/etc/php.ini
|
||||
|
||||
service php-fpm-$version reload
|
||||
echo '==========================================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
Uninstall_yaf()
|
||||
{
|
||||
if [ ! -f "/www/server/php/$version/bin/php-config" ];then
|
||||
echo "php-$vphp 未安装,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
case "${version}" in
|
||||
'54')
|
||||
extFile='/www/server/php/54/lib/php/extensions/no-debug-non-zts-20100525/yaf.so'
|
||||
;;
|
||||
'55')
|
||||
extFile='/www/server/php/55/lib/php/extensions/no-debug-non-zts-20121212/yaf.so'
|
||||
;;
|
||||
'56')
|
||||
extFile='/www/server/php/56/lib/php/extensions/no-debug-non-zts-20131226/yaf.so'
|
||||
;;
|
||||
'70')
|
||||
extFile='/www/server/php/70/lib/php/extensions/no-debug-non-zts-20151012/yaf.so'
|
||||
;;
|
||||
'71')
|
||||
extFile='/www/server/php/71/lib/php/extensions/no-debug-non-zts-20160303/yaf.so'
|
||||
;;
|
||||
'72')
|
||||
extFile='/www/server/php/72/lib/php/extensions/no-debug-non-zts-20170718/yaf.so'
|
||||
esac
|
||||
if [ ! -f "$extFile" ];then
|
||||
echo "php-$vphp 未安装yaf,请选择其它版本!"
|
||||
return
|
||||
fi
|
||||
|
||||
sed -i '/yaf.so/d' /www/server/php/$version/etc/php.ini
|
||||
|
||||
rm -f $extFile
|
||||
/etc/init.d/php-fpm-$version reload
|
||||
echo '==============================================='
|
||||
echo 'successful!'
|
||||
}
|
||||
|
||||
|
||||
actionType=$1
|
||||
version=$2
|
||||
if [ "$actionType" == 'install' ];then
|
||||
Install_yaf
|
||||
elif [ "$actionType" == 'uninstall' ];then
|
||||
Uninstall_yaf
|
||||
fi
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
$cfg['blowfish_secret'] = 'd41d8cd98f00b204e9800998ecf8427e';
|
||||
$i = 0;
|
||||
$i++;
|
||||
$cfg['Servers'][$i]['auth_type'] = 'cookie';
|
||||
$cfg['Servers'][$i]['host'] = 'localhost';
|
||||
$cfg['Servers'][$i]['connect_type'] = 'tcp';
|
||||
$cfg['Servers'][$i]['compress'] = false;
|
||||
$cfg['Servers'][$i]['AllowNoPassword'] = false;
|
||||
$cfg['UploadDir'] = '';
|
||||
$cfg['SaveDir'] = '';
|
||||
?>
|
||||
@@ -0,0 +1,27 @@
|
||||
server
|
||||
{
|
||||
listen 888;
|
||||
server_name www.bt.cn;
|
||||
index index.html index.htm index.php;
|
||||
root {$SERVER_PATH}/phpmyadmin;
|
||||
|
||||
#error_page 404 /404.html;
|
||||
include enable-php-{$PHP_VER}.conf;
|
||||
|
||||
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
|
||||
{
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
location ~ .*\.(js|css)?$
|
||||
{
|
||||
expires 12h;
|
||||
}
|
||||
|
||||
location ~ /\.
|
||||
{
|
||||
deny all;
|
||||
}
|
||||
|
||||
access_log {$SERVER_PATH}/phpmyadmin/access.log;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,19 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('phpmyadmin');">服务</p>
|
||||
<p onclick="pluginConfig('phpmyadmin');">重写模版</p>
|
||||
<p onclick="homePage()">主页</p>
|
||||
<p onclick="phpVer(56)">PHP版本</p>
|
||||
<p onclick="safeConf();">安全设置</p>
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
pluginService('phpmyadmin');
|
||||
$.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js");
|
||||
</script>
|
||||
@@ -0,0 +1,220 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
import site_api
|
||||
|
||||
app_debug = False
|
||||
if public.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'phpmyadmin'
|
||||
|
||||
|
||||
def getPluginDir():
|
||||
return public.getPluginDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getServerDir():
|
||||
return public.getServerDir() + '/' + getPluginName()
|
||||
|
||||
|
||||
def getArgs():
|
||||
args = sys.argv[2:]
|
||||
tmp = {}
|
||||
args_len = len(args)
|
||||
|
||||
if args_len == 1:
|
||||
t = args[0].strip('{').strip('}')
|
||||
t = t.split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
elif args_len > 1:
|
||||
for i in range(len(args)):
|
||||
t = args[i].split(':')
|
||||
tmp[t[0]] = t[1]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def getConf():
|
||||
return public.getServerDir() + '/openresty/nginx/conf/vhost/phpmyadmin.conf'
|
||||
|
||||
|
||||
def getPort():
|
||||
file = getConf()
|
||||
content = public.readFile(file)
|
||||
rep = 'listen\s*(.*);'
|
||||
tmp = re.search(rep, content)
|
||||
return tmp.groups()[0].strip()
|
||||
|
||||
|
||||
def getHomePage():
|
||||
try:
|
||||
port = getPort()
|
||||
ip = '127.0.0.1'
|
||||
if not public.isAppleSystem():
|
||||
ip = public.getLocalIp()
|
||||
url = 'http://' + ip + ':' + port + '/phpmyadmin/index.php'
|
||||
return public.returnJson(True, 'OK', url)
|
||||
except Exception as e:
|
||||
return public.returnJson(False, '插件未启动!')
|
||||
|
||||
|
||||
def getPhpVer(expect=55):
|
||||
import json
|
||||
v = site_api.site_api().getPhpVersion()
|
||||
v = json.loads(v)
|
||||
for i in range(len(v)):
|
||||
t = int(v[i]['version'])
|
||||
if (t >= expect):
|
||||
return str(t)
|
||||
return str(expect)
|
||||
|
||||
|
||||
def getCachePhpVer():
|
||||
cacheFile = getServerDir() + '/php.pl'
|
||||
v = ''
|
||||
if os.path.exists(cacheFile):
|
||||
v = public.readFile(cacheFile)
|
||||
else:
|
||||
v = getPhpVer()
|
||||
public.writeFile(cacheFile, v)
|
||||
return v
|
||||
|
||||
|
||||
def contentReplace(content):
|
||||
service_path = public.getServerDir()
|
||||
php_ver = getCachePhpVer()
|
||||
# print php_ver
|
||||
content = content.replace('{$ROOT_PATH}', public.getRootDir())
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
content = content.replace('{$PHP_VER}', php_ver)
|
||||
return content
|
||||
|
||||
|
||||
def status():
|
||||
conf = getConf()
|
||||
if os.path.exists(conf):
|
||||
return 'start'
|
||||
return 'stop'
|
||||
|
||||
|
||||
def start():
|
||||
file_tpl = getPluginDir() + '/conf/phpmyadmin.conf'
|
||||
file_run = getConf()
|
||||
|
||||
if not os.path.exists(file_run):
|
||||
centent = public.readFile(file_tpl)
|
||||
centent = contentReplace(centent)
|
||||
public.writeFile(file_run, centent)
|
||||
|
||||
conf_run = getServerDir() + '/phpmyadmin/config.inc.php'
|
||||
if not os.path.exists(conf_run):
|
||||
conf_tpl = getPluginDir() + '/conf/config.inc.php'
|
||||
centent = public.readFile(conf_tpl)
|
||||
# centent = contentReplace(centent)
|
||||
print public.writeFile(conf_run, centent)
|
||||
|
||||
public.restartWeb()
|
||||
return 'ok'
|
||||
|
||||
|
||||
def stop():
|
||||
conf = getConf()
|
||||
if os.path.exists(conf):
|
||||
os.remove(conf)
|
||||
public.restartWeb()
|
||||
return 'ok'
|
||||
|
||||
|
||||
def restart():
|
||||
return start()
|
||||
|
||||
|
||||
def reload():
|
||||
return start()
|
||||
|
||||
|
||||
def setPhpVer():
|
||||
args = getArgs()
|
||||
|
||||
if not 'phpver' in args:
|
||||
return 'phpver missing'
|
||||
|
||||
cacheFile = getServerDir() + '/php.pl'
|
||||
public.writeFile(cacheFile, args['phpver'])
|
||||
restart()
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
def getSetPhpVer():
|
||||
cacheFile = getServerDir() + '/php.pl'
|
||||
if os.path.exists(cacheFile):
|
||||
return public.readFile(cacheFile).strip()
|
||||
return ''
|
||||
|
||||
|
||||
def getPmaPort():
|
||||
try:
|
||||
port = getPort()
|
||||
return public.returnJson(True, 'OK', port)
|
||||
except Exception as e:
|
||||
print e
|
||||
return public.returnJson(False, '插件未启动!')
|
||||
|
||||
|
||||
def setPmaPort():
|
||||
args = getArgs()
|
||||
if not 'port' in args:
|
||||
return public.returnJson(False, 'port missing!')
|
||||
|
||||
port = args['port']
|
||||
if port == '80':
|
||||
return public.returnJson(False, '80端不能使用!')
|
||||
|
||||
file = getConf()
|
||||
if not os.path.exists(file):
|
||||
return public.returnJson(False, '插件未启动!')
|
||||
content = public.readFile(file)
|
||||
rep = 'listen\s*(.*);'
|
||||
content = re.sub(rep, "listen " + port + ';', content)
|
||||
public.writeFile(file, content)
|
||||
public.restartWeb()
|
||||
return public.returnJson(True, '修改成功!')
|
||||
|
||||
|
||||
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 == 'conf':
|
||||
print getConf()
|
||||
elif func == 'get_home_page':
|
||||
print getHomePage()
|
||||
elif func == 'set_php_ver':
|
||||
print setPhpVer()
|
||||
elif func == 'get_set_php_ver':
|
||||
print getSetPhpVer()
|
||||
elif func == 'get_pma_port':
|
||||
print getPmaPort()
|
||||
elif func == 'set_pma_port':
|
||||
print setPmaPort()
|
||||
else:
|
||||
print 'error'
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"title":"phpMyAdmin",
|
||||
"tip":"soft",
|
||||
"name":"phpmyadmin",
|
||||
"type":"运行环境",
|
||||
"ps":"著名Web端MySQL管理工具",
|
||||
"versions":["4.4.15","4.8.4"],
|
||||
"updates":["4.4.15","4.8.4"],
|
||||
"shell":"install.sh",
|
||||
"checks":"server/phpmyadmin",
|
||||
"author":"phpMyAdmin",
|
||||
"home":"https://www.phpmyadmin.net/",
|
||||
"date":"2017-11-24",
|
||||
"pid": "2"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/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_phpmyadmin()
|
||||
{
|
||||
mkdir -p ${serverPath}/phpmyadmin
|
||||
mkdir -p ${serverPath}/source/phpmyadmin
|
||||
|
||||
VER=$1
|
||||
FILE=phpMyAdmin-${VER}-all-languages.tar.gz
|
||||
FDIR=phpMyAdmin-${VER}-all-languages
|
||||
DOWNLOAD=https://files.phpmyadmin.net/phpMyAdmin/${VER}/$FILE
|
||||
|
||||
|
||||
if [ ! -f $serverPath/source/phpmyadmin/$FILE ];then
|
||||
wget -O $serverPath/source/phpmyadmin/$FILE $DOWNLOAD
|
||||
fi
|
||||
|
||||
if [ ! -d $serverPath/source/phpmyadmin/$FDIR ];then
|
||||
cd $serverPath/source/phpmyadmin && tar zxvf $FILE
|
||||
fi
|
||||
|
||||
cp -r $serverPath/source/phpmyadmin/$FDIR $serverPath/phpmyadmin/
|
||||
cd $serverPath/phpmyadmin/ && mv $FDIR phpmyadmin
|
||||
|
||||
echo "${1}" > ${serverPath}/phpmyadmin/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
|
||||
}
|
||||
|
||||
Uninstall_phpmyadmin()
|
||||
{
|
||||
rm -rf ${serverPath}/phpmyadmin
|
||||
echo '卸载完成' > $install_tmp
|
||||
}
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_phpmyadmin $2
|
||||
else
|
||||
Uninstall_phpmyadmin $2
|
||||
fi
|
||||
@@ -1,118 +1,122 @@
|
||||
//phpmyadmin安全设置
|
||||
function safeConf(name, port, auth) {
|
||||
var con = '<div class="ver line">\
|
||||
<span style="margin-right:10px">' + lan.soft.pma_port + '</span>\
|
||||
<input class="bt-input-text phpmyadmindk mr20" name="Name" id="pmport" value="' + port + '" placeholder="' + lan.soft.pma_port_title + '" maxlength="5" type="number">\
|
||||
<button class="btn btn-success btn-sm" onclick="phpmyadminport()">' + lan.public.save + '</button>\
|
||||
</div>\
|
||||
<div class="user_pw_tit">\
|
||||
<span class="tit">' + lan.soft.pma_pass + '</span>\
|
||||
<span class="btswitch-p"><input class="btswitch btswitch-ios" id="phpmyadminsafe" type="checkbox" ' + (auth ? 'checked' : '') + '>\
|
||||
<label class="btswitch-btn phpmyadmin-btn" for="phpmyadminsafe" onclick="phpmyadminSafe()"></label>\
|
||||
</span>\
|
||||
</div>\
|
||||
<div class="user_pw">\
|
||||
<p><span>' + lan.soft.pma_user + '</span><input id="username_get" class="bt-input-text" name="username_get" value="" type="text" placeholder="' + lan.soft.edit_empty + '"></p>\
|
||||
<p><span>' + lan.soft.pma_pass1 + '</span><input id="password_get_1" class="bt-input-text" name="password_get_1" value="" type="password" placeholder="' + lan.soft.edit_empty + '"></p>\
|
||||
<p><span>' + lan.soft.pma_pass2 + '</span><input id="password_get_2" class="bt-input-text" name="password_get_1" value="" type="password" placeholder="' + lan.soft.edit_empty + '"></p>\
|
||||
<p><button class="btn btn-success btn-sm" onclick="phpmyadmin(\'get\')">' + lan.public.save + '</button></p>\
|
||||
</div>\
|
||||
<ul class="help-info-text c7"><li>' + lan.soft.pma_ps + '</li></ul>';
|
||||
$(".soft-man-con").html(con);
|
||||
if (auth) {
|
||||
$(".user_pw").show();
|
||||
function str2Obj(str){
|
||||
var data = {};
|
||||
kv = str.split('&');
|
||||
for(i in kv){
|
||||
v = kv[i].split('=');
|
||||
data[v[0]] = v[1];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function pmaPost(method,args,callback){
|
||||
|
||||
function phpVerChange(type, msg) {
|
||||
var data = type + '=' + $("#" + msg).val();
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/ajax?action=setPHPMyAdmin', data, function(rdata) {
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
if (rdata.status) {
|
||||
setTimeout(function() {
|
||||
window.location.reload();
|
||||
}, 3000);
|
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){
|
||||
_args = JSON.stringify(str2Obj(args));
|
||||
} else {
|
||||
_args = JSON.stringify(args);
|
||||
}
|
||||
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'phpmyadmin', func:method, args:_args}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
})
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function pmaAsyncPost(method,args){
|
||||
|
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){
|
||||
_args = JSON.stringify(str2Obj(args));
|
||||
} else {
|
||||
_args = JSON.stringify(args);
|
||||
}
|
||||
return syncPost('/plugins/run', {name:'phpmyadmin', func:method, args:_args});
|
||||
}
|
||||
|
||||
function homePage(){
|
||||
pmaPost('get_home_page', '', function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (!rdata.status){
|
||||
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
var con = '<button class="btn btn-default btn-sm" onclick="window.open(\'' + rdata.data + '\')">主页</button>';
|
||||
$(".soft-man-con").html(con);
|
||||
});
|
||||
}
|
||||
|
||||
//phpmyadmin切换php版本
|
||||
function phpVer(name, version) {
|
||||
$.post('/site?action=GetPHPVersion', function(rdata) {
|
||||
var body = "<div class='ver line'><span class='tname'>" + lan.soft.php_version + "</span><select id='get' class='bt-input-text mr20' name='phpVersion' style='width:110px'>";
|
||||
function phpVer(version) {
|
||||
|
||||
var _version = pmaAsyncPost('get_set_php_ver','')
|
||||
if (_version['data'] != ''){
|
||||
version = _version['data'];
|
||||
}
|
||||
|
||||
$.post('/site/get_php_version', function(rdata) {
|
||||
// console.log(rdata);
|
||||
var body = "<div class='ver line'><span class='tname'>PHP版本</span><select id='phpver' class='bt-input-text mr20' name='phpVersion' style='width:110px'>";
|
||||
var optionSelect = '';
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
optionSelect = rdata[i].version == version ? 'selected' : '';
|
||||
body += "<option value='" + rdata[i].version + "' " + optionSelect + ">" + rdata[i].name + "</option>"
|
||||
}
|
||||
body += '</select><button class="btn btn-success btn-sm" onclick="phpVerChange(\'phpversion\',\'get\')">' + lan.public.save + '</button></div>';
|
||||
body += '</select><button class="btn btn-success btn-sm" onclick="phpVerChange(\'phpversion\',\'get\')">保存</button></div>';
|
||||
$(".soft-man-con").html(body);
|
||||
})
|
||||
},'json');
|
||||
}
|
||||
|
||||
function phpVerChange(type, msg) {
|
||||
var phpver = $("#phpver").val();
|
||||
pmaPost('set_php_ver', 'phpver='+phpver, function(data){
|
||||
if ( data.data == 'ok' ){
|
||||
layer.msg('设置成功!',{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
} else {
|
||||
layer.msg('设置失败!',{icon:2,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//phpmyadmin安全设置
|
||||
function safeConf() {
|
||||
var data = pmaAsyncPost('get_pma_port');
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (!rdata.status){
|
||||
layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
var con = '<div class="ver line">\
|
||||
<span style="margin-right:10px">访问端口</span>\
|
||||
<input class="bt-input-text phpmyadmindk mr20" name="Name" id="pmport" value="' + rdata['data'] + '" placeholder="phpmyadmin访问端口" maxlength="5" type="number">\
|
||||
<button class="btn btn-success btn-sm" onclick="phpmyadminPort()">保存</button>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(con);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//修改phpmyadmin端口
|
||||
function phpmyadminport() {
|
||||
function phpmyadminPort() {
|
||||
var pmport = $("#pmport").val();
|
||||
if (pmport < 80 || pmport > 65535) {
|
||||
layer.msg(lan.firewall.port_err, { icon: 2 });
|
||||
layer.msg('端口范围不合法!', { icon: 2 });
|
||||
return;
|
||||
}
|
||||
var data = 'port=' + pmport;
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/ajax?action=setPHPMyAdmin', data, function(rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
|
||||
//phpmyadmin二级密码
|
||||
function phpmyadminSafe() {
|
||||
var stat = $("#phpmyadminsafe").prop("checked");
|
||||
if (stat) {
|
||||
$(".user_pw").hide();
|
||||
phpmyadmin('close');
|
||||
} else {
|
||||
$(".user_pw").show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//设置phpmyadmin二级密码
|
||||
function phpmyadmin(msg) {
|
||||
type = 'password';
|
||||
if (msg == 'close') {
|
||||
password_1 = msg;
|
||||
username = msg;
|
||||
layer.confirm(lan.soft.pma_pass_close, { closeBtn: 2, icon: 3 }, function() {
|
||||
var data = type + '=' + msg + '&siteName=phpmyadmin';
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/ajax?action=setPHPMyAdmin', data, function(rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
username = $("#username_get").val()
|
||||
password_1 = $("#password_get_1").val()
|
||||
password_2 = $("#password_get_2").val()
|
||||
if (username.length < 1 || password_1.length < 1) {
|
||||
layer.msg(lan.soft.pma_pass_empty, { icon: 2 });
|
||||
return;
|
||||
}
|
||||
if (password_1 != password_2) {
|
||||
layer.msg(lan.bt.pass_err_re, { icon: 2 });
|
||||
return;
|
||||
}
|
||||
}
|
||||
msg = password_1 + '&username=' + username + '&siteName=phpmyadmin';
|
||||
var data = type + '=' + msg;
|
||||
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.post('/ajax?action=setPHPMyAdmin', data, function(rdata) {
|
||||
layer.close(loadT);
|
||||
|
||||
pmaPost('set_pma_port',data, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
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
|
||||
);
|
||||
@@ -0,0 +1,29 @@
|
||||
ChrootEveryone yes
|
||||
BrokenClientsCompatibility no
|
||||
MaxClientsNumber 50
|
||||
Daemonize yes
|
||||
MaxClientsPerIP 8
|
||||
VerboseLog no
|
||||
DisplayDotFiles yes
|
||||
AnonymousOnly no
|
||||
NoAnonymous no
|
||||
SyslogFacility ftp
|
||||
DontResolve yes
|
||||
MaxIdleTime 15
|
||||
LimitRecursion 10000 8
|
||||
AnonymousCanCreateDirs no
|
||||
MaxLoad 4
|
||||
AntiWarez yes
|
||||
Bind 0.0.0.0,21
|
||||
Umask 133:022
|
||||
MinUID 100
|
||||
AllowUserFXP no
|
||||
AllowAnonymousFXP no
|
||||
ProhibitDotFilesWrite no
|
||||
ProhibitDotFilesRead no
|
||||
AutoRename no
|
||||
AnonymousCantUpload no
|
||||
MaxDiskUsage 99
|
||||
CustomerProof yes
|
||||
PIDFile /var/run/pure-ftpd.pid
|
||||
PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb
|
||||
@@ -1,57 +0,0 @@
|
||||
$def with (tData)
|
||||
<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="/">$tData['lan']['H1']</a>/<span class="plr10 c4">$tData['lan']['H2']</span>
|
||||
</div>
|
||||
<div class="search pull-right">
|
||||
<form target="hid" onsubmit='getFtp(1,$$("#SearchValue").prop("value"))'>
|
||||
<input type="text" id="SearchValue" class="ser-text pull-left" placeholder="$tData['lan']['SEARCH']" />
|
||||
<button type="button" class="ser-sub pull-left" onclick='getFtp(1,$$("#SearchValue").prop("value"))'></button>
|
||||
</form>
|
||||
<iframe name='hid' id="hid" style="display:none"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="safe bgw mtb15 pd15">
|
||||
<div class="important-title">
|
||||
<p><span class="glyphicon glyphicon-alert" style="color: #f39c12; margin-right: 10px;"></span> $tData['lan']['PS'] ftp://$web.ctx.session.address:$web.ctx.session.port</p>
|
||||
</div>
|
||||
<button onclick="ftpAdd()" class="btn btn-success btn-sm" type="button">$tData['lan']['BTN1']</button>
|
||||
<button onclick="ftpPortEdit($web.ctx.session.port)" class="btn btn-default btn-sm" type="button" style="margin-left:5px">$tData['lan']['BTN2']</button>
|
||||
<span id="allDelete" style="float: right;display: none;">
|
||||
<button onclick="allDeleteFtp();" class="btn btn-default btn-sm">$tData['lan']['BTN3']</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='30'><input type="checkbox" onclick="checkSelect();" id="setBox"></th>
|
||||
<th onclick="listOrder('name','ftp',this)" style="cursor: pointer;">$tData['lan']['TH1']<span class="glyphicon glyphicon-triangle-top" style="margin-left:5px;color:#bbb"></span></th>
|
||||
<th width="15%">$tData['lan']['TH2']</th>
|
||||
<th onclick="listOrder('status','ftp',this)" style="cursor: pointer;" width="100">$tData['lan']['TH3']<span class="glyphicon glyphicon-triangle-top" style="margin-left:5px;color:#bbb"></span></th>
|
||||
<th width="26%">$tData['lan']['TH4']</th>
|
||||
<th width="15%">$tData['lan']['TH5']</th>
|
||||
<th width="130" class="text-right">$tData['lan']['TH6']</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ftpBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="dataTables_paginate paging_bootstrap pagination">
|
||||
<ul id="ftpPage" class="page"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/ftp.js?date=20180725"></script>
|
||||
<script type="text/javascript">
|
||||
$if not tData['isSetup']:
|
||||
layer.msg('$tData["lan"]["JS1"]<a href="/soft" style="color:#20a53a; float: right;">$tData["lan"]["JS1"]</a>',{icon:7,time:0,shade: [0.3, '#000']});
|
||||
$$(".layui-layer-shade").css("margin-left","180px");
|
||||
setTimeout(function(){
|
||||
getFtp(1);
|
||||
},300);
|
||||
</script>
|
||||
@@ -0,0 +1,21 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('pureftp');">服务</p>
|
||||
<p onclick="pluginInitD('pureftp');">自启动</p>
|
||||
<p onclick="pluginConfig('pureftp');">配置修改</p>
|
||||
<p onclick="ftpList();">管理列表</p>
|
||||
</div>
|
||||
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
resetPluginWinWidth(800);
|
||||
$.getScript( "/plugins/file?name=pureftp&f=js/ftp.js", function(){
|
||||
pluginService('pureftp');
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,474 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import public
|
||||
|
||||
app_debug = False
|
||||
if public.isAppleSystem():
|
||||
app_debug = True
|
||||
|
||||
|
||||
def getPluginName():
|
||||
return 'pureftp'
|
||||
|
||||
|
||||
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 = getServerDir() + "/etc/pure-ftpd.conf"
|
||||
return path
|
||||
|
||||
|
||||
def getInitDTpl():
|
||||
path = getPluginDir() + "/init.d/pure-ftpd.tpl"
|
||||
return path
|
||||
|
||||
|
||||
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 status():
|
||||
cmd = "ps -ef|grep pure-ftpd |grep -v grep | grep -v python | awk '{print $2}'"
|
||||
data = public.execShell(cmd)
|
||||
if data[0] == '':
|
||||
return 'stop'
|
||||
return 'start'
|
||||
|
||||
|
||||
def contentReplace(content):
|
||||
service_path = public.getServerDir()
|
||||
content = content.replace('{$ROOT_PATH}', public.getRootDir())
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
return content
|
||||
|
||||
|
||||
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
|
||||
if not os.path.exists(file_bin):
|
||||
content = public.readFile(file_tpl)
|
||||
content = contentReplace(content)
|
||||
public.writeFile(file_bin, content)
|
||||
public.execShell('chmod +x ' + file_bin)
|
||||
|
||||
pureSbinConfig = getServerDir() + "/sbin/pure-config.pl"
|
||||
if not os.path.exists(pureSbinConfig):
|
||||
pureTplConfig = getPluginDir() + "/init.d/pure-config.pl"
|
||||
content = public.readFile(pureTplConfig)
|
||||
content = contentReplace(content)
|
||||
public.writeFile(pureSbinConfig, content)
|
||||
public.execShell('chmod +x ' + pureSbinConfig)
|
||||
|
||||
pureFtpdConfig = getServerDir() + "/etc/pure-ftpd.conf"
|
||||
pureFtpdConfigBak = getServerDir() + "/etc/pure-ftpd.bak.conf"
|
||||
pureFtpdConfigTpl = getPluginDir() + "/conf/pure-ftpd.conf"
|
||||
|
||||
if not os.path.exists(pureFtpdConfigBak):
|
||||
shutil.copyfile(pureFtpdConfig, pureFtpdConfigBak)
|
||||
content = public.readFile(pureFtpdConfigTpl)
|
||||
content = contentReplace(content)
|
||||
public.writeFile(pureFtpdConfig, content)
|
||||
|
||||
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 data[1]
|
||||
|
||||
|
||||
def restart():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' restart')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
|
||||
def reload():
|
||||
file = initDreplace()
|
||||
data = public.execShell(file + ' reload')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[1]
|
||||
|
||||
|
||||
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"
|
||||
|
||||
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:
|
||||
os_name = public.getOs()
|
||||
if os_name == 'darwin':
|
||||
return "Apple Computer does not support"
|
||||
initd_bin = getInitDFile()
|
||||
os.remove(initd_bin)
|
||||
return 'ok'
|
||||
|
||||
|
||||
def pftpDB():
|
||||
file = getServerDir() + '/ftps.db'
|
||||
if not os.path.exists(file):
|
||||
conn = public.M('ftps').dbPos(getServerDir(), 'ftps')
|
||||
csql = public.readFile(getPluginDir() + '/conf/ftps.sql')
|
||||
csql_list = csql.split(';')
|
||||
for index in range(len(csql_list)):
|
||||
conn.execute(csql_list[index], ())
|
||||
else:
|
||||
conn = public.M('ftps').dbPos(getServerDir(), 'ftps')
|
||||
return conn
|
||||
|
||||
|
||||
def pftpUser():
|
||||
if public.isAppleSystem():
|
||||
user = public.execShell(
|
||||
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
|
||||
return user
|
||||
return 'www'
|
||||
|
||||
|
||||
def pftpAdd(username, password, path):
|
||||
user = pftpUser()
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
if public.isAppleSystem():
|
||||
os.system('chown ' + user + '.staff ' + path)
|
||||
else:
|
||||
os.system('chown www.www ' + path)
|
||||
|
||||
cmd = getServerDir() + '/bin/pure-pw useradd ' + username + ' -u ' + user + ' -d ' + \
|
||||
path + '<<EOF \n' + password + '\n' + password + '\nEOF'
|
||||
return public.execShell(cmd)
|
||||
|
||||
|
||||
def pftpMod(username, password):
|
||||
user = pftpUser()
|
||||
cmd = getServerDir() + '/bin/pure-pw passwd ' + username + \
|
||||
'<<EOF \n' + password + '\n' + password + '\nEOF'
|
||||
return public.execShell(cmd)
|
||||
|
||||
|
||||
def pftpStop(username):
|
||||
cmd = getServerDir() + '/bin/pure-pw usermod ' + username + ' -r 1'
|
||||
return public.execShell(cmd)
|
||||
|
||||
|
||||
def pftpStart(username):
|
||||
cmd = getServerDir() + '/bin/pure-pw usermod ' + username + " -r ''"
|
||||
return public.execShell(cmd)
|
||||
|
||||
|
||||
def pftpReload():
|
||||
public.execShell(getServerDir() + '/bin/pure-pw mkdb ' +
|
||||
getServerDir() + '/etc/pureftpd.pdb')
|
||||
|
||||
|
||||
def getWwwDir():
|
||||
path = public.getWwwDir()
|
||||
return path
|
||||
|
||||
|
||||
def getFtpPort():
|
||||
import re
|
||||
try:
|
||||
file = getServerDir() + '/etc/pure-ftpd.conf'
|
||||
conf = public.readFile(file)
|
||||
rep = "\n#?\s*Bind\s+[0-9]+\.[0-9]+\.[0-9]+\.+[0-9]+,([0-9]+)"
|
||||
port = re.search(rep, conf).groups()[0]
|
||||
except:
|
||||
port = '21'
|
||||
return port
|
||||
|
||||
|
||||
def getFtpList():
|
||||
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']
|
||||
|
||||
data = {}
|
||||
conn = pftpDB()
|
||||
limit = str((page - 1) * page_size) + ',' + str(page_size)
|
||||
# print limit, search
|
||||
condition = ''
|
||||
if not search == '':
|
||||
condition = "name like '%" + search + "%'"
|
||||
field = 'id,pid,name,password,path,status,ps,addtime'
|
||||
clist = conn.where(condition, ()).field(
|
||||
field).limit(limit).order('id desc').select()
|
||||
|
||||
count = conn.where(condition, ()).count()
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['p'] = page
|
||||
_page['row'] = page_size
|
||||
_page['tojs'] = 'ftpList'
|
||||
data['page'] = public.getPage(_page)
|
||||
|
||||
info = {}
|
||||
info['ip'] = public.getLocalIp()
|
||||
info['port'] = getFtpPort()
|
||||
data['info'] = info
|
||||
data['data'] = clist
|
||||
|
||||
return public.getJson(data)
|
||||
|
||||
|
||||
def addFtp():
|
||||
import urllib
|
||||
args = getArgs()
|
||||
if not 'ftp_username' in args:
|
||||
return 'ftp_username missing'
|
||||
|
||||
if not 'ftp_password' in args:
|
||||
return 'ftp_password missing'
|
||||
|
||||
if not 'path' in args:
|
||||
return 'path missing'
|
||||
|
||||
if not 'ps' in args:
|
||||
return 'ps missing'
|
||||
|
||||
path = urllib.unquote(args['path'])
|
||||
user = args['ftp_username']
|
||||
pwd = args['ftp_password']
|
||||
ps = args['ps']
|
||||
|
||||
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
|
||||
data = pftpAdd(user, pwd, path)
|
||||
conn = pftpDB()
|
||||
conn.add('pid,name,password,path,status,ps,addtime',
|
||||
(0, user, pwd, path, 1, ps, addtime))
|
||||
pftpReload()
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[0]
|
||||
|
||||
|
||||
def delFtp():
|
||||
args = getArgs()
|
||||
if not 'id' in args:
|
||||
return 'ftp_username missing'
|
||||
|
||||
if not 'username' in args:
|
||||
return 'username missing'
|
||||
|
||||
public.execShell(getServerDir() +
|
||||
'/bin/pure-pw userdel ' + args['username'])
|
||||
pftpReload()
|
||||
conn = pftpDB()
|
||||
conn.where("id=?", (args['id'],)).delete()
|
||||
public.writeLog('TYPE_FTP', 'FTP_DEL_SUCCESS', (args['username'],))
|
||||
return 'ok'
|
||||
|
||||
|
||||
def modFtp():
|
||||
args = getArgs()
|
||||
if not 'id' in args:
|
||||
return 'id missing'
|
||||
|
||||
if not 'name' in args:
|
||||
return 'name missing'
|
||||
|
||||
if not 'password' in args:
|
||||
return 'password missing'
|
||||
|
||||
conn = pftpDB()
|
||||
data = pftpMod(args['name'], args['password'])
|
||||
pftpReload()
|
||||
|
||||
conn.where('id=?', (int(args['id']),)).save(
|
||||
'password', (args['password'],))
|
||||
# print data
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[0]
|
||||
|
||||
|
||||
def modFtpPort():
|
||||
import re
|
||||
args = getArgs()
|
||||
if not 'port' in args:
|
||||
return 'port missing'
|
||||
try:
|
||||
port = args['port']
|
||||
if int(port) < 1 or int(port) > 65535:
|
||||
return '端口范围不正确!'
|
||||
file = file = getServerDir() + '/etc/pure-ftpd.conf'
|
||||
conf = public.readFile(file)
|
||||
rep = u"\n#?\s*Bind\s+[0-9]+\.[0-9]+\.[0-9]+\.+[0-9]+,([0-9]+)"
|
||||
# preg_match(rep,conf,tmp)
|
||||
conf = re.sub(
|
||||
rep, "\nBind 0.0.0.0," + port, conf)
|
||||
public.writeFile(file, conf)
|
||||
restart()
|
||||
return 'ok'
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
|
||||
|
||||
def stopPort():
|
||||
args = getArgs()
|
||||
if not 'id' in args:
|
||||
return 'id missing'
|
||||
|
||||
if not 'username' in args:
|
||||
return 'username missing'
|
||||
|
||||
if not 'status' in args:
|
||||
return 'status missing'
|
||||
|
||||
data = pftpStop(args['username'])
|
||||
pftpReload()
|
||||
conn = pftpDB()
|
||||
conn.where('id=?', (int(args['id']),)).save(
|
||||
'status', (args['status'],))
|
||||
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[0]
|
||||
|
||||
|
||||
def startPort():
|
||||
args = getArgs()
|
||||
if not 'id' in args:
|
||||
return 'id missing'
|
||||
|
||||
if not 'username' in args:
|
||||
return 'username missing'
|
||||
|
||||
if not 'status' in args:
|
||||
return 'status missing'
|
||||
|
||||
data = pftpStart(args['username'])
|
||||
pftpReload()
|
||||
conn = pftpDB()
|
||||
conn.where('id=?', (int(args['id']),)).save(
|
||||
'status', (args['status'],))
|
||||
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return data[0]
|
||||
|
||||
|
||||
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_www_dir':
|
||||
print getWwwDir()
|
||||
elif func == 'get_ftp_list':
|
||||
print getFtpList()
|
||||
elif func == 'add_ftp':
|
||||
print addFtp()
|
||||
elif func == 'del_ftp':
|
||||
print delFtp()
|
||||
elif func == 'mod_ftp':
|
||||
print modFtp()
|
||||
elif func == 'mod_ftp_port':
|
||||
print modFtpPort()
|
||||
elif func == 'stop_ftp':
|
||||
print stopPort()
|
||||
elif func == 'start_ftp':
|
||||
print startPort()
|
||||
else:
|
||||
print 'error'
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title":"pureftp",
|
||||
"title":"PureFtpd",
|
||||
"tip":"soft",
|
||||
"name":"pureftp",
|
||||
"ps":"PureFTPd是一款专注于程序健壮和软件安全的免费FTP服务器软件",
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
# (C) 2001-2013 Aristotle Pagaltzis
|
||||
# derived from code (C) 2001-2002 Frank Denis and Matthias Andree
|
||||
|
||||
use strict;
|
||||
|
||||
my ($conffile, @flg) = @ARGV;
|
||||
|
||||
my $PUREFTPD;
|
||||
-x && ($PUREFTPD=$_, last) for qw(
|
||||
{$SERVER_PATH}/pureftp/sbin/pure-ftpd
|
||||
/www/server/pure-ftpd/sbin/pure-ftpd
|
||||
/www/server/pureftpd/sbin/pure-ftpd
|
||||
/www/server/sbin/pure-ftpd
|
||||
/usr/sbin/pure-ftpd
|
||||
);
|
||||
|
||||
my %simple_switch_for = (
|
||||
IPV4Only => "-4",
|
||||
IPV6Only => "-6",
|
||||
ChrootEveryone => "-A",
|
||||
BrokenClientsCompatibility => "-b",
|
||||
Daemonize => "-B",
|
||||
VerboseLog => "-d",
|
||||
DisplayDotFiles => "-D",
|
||||
AnonymousOnly => "-e",
|
||||
NoAnonymous => "-E",
|
||||
DontResolve => "-H",
|
||||
AnonymousCanCreateDirs => "-M",
|
||||
NATmode => "-N",
|
||||
CallUploadScript => "-o",
|
||||
AntiWarez => "-s",
|
||||
AllowUserFXP => "-w",
|
||||
AllowAnonymousFXP => "-W",
|
||||
ProhibitDotFilesWrite => "-x",
|
||||
ProhibitDotFilesRead => "-X",
|
||||
AllowDotFiles => "-z",
|
||||
AutoRename => "-r",
|
||||
AnonymousCantUpload => "-i",
|
||||
LogPID => "-1",
|
||||
NoChmod => "-R",
|
||||
KeepAllFiles => "-K",
|
||||
CreateHomeDir => "-j",
|
||||
NoRename => "-G",
|
||||
CustomerProof => "-Z",
|
||||
NoTruncate => "-0",
|
||||
);
|
||||
|
||||
my %string_switch_for = (
|
||||
FileSystemCharset => "-8",
|
||||
ClientCharset => "-9",
|
||||
SyslogFacility => "-f",
|
||||
FortunesFile => "-F",
|
||||
ForcePassiveIP => "-P",
|
||||
Bind => "-S",
|
||||
AnonymousBandwidth => "-t",
|
||||
UserBandwidth => "-T",
|
||||
TrustedIP => "-V",
|
||||
AltLog => "-O",
|
||||
PIDFile => "-g",
|
||||
TLSCipherSuite => "-J",
|
||||
CertFile => "-2",
|
||||
);
|
||||
|
||||
my %numeric_switch_for = (
|
||||
MaxIdleTime => "-I",
|
||||
MaxDiskUsage => "-k",
|
||||
TrustedGID => "-a",
|
||||
MaxClientsNumber => "-c",
|
||||
MaxClientsPerIP => "-C",
|
||||
MaxLoad => "-m",
|
||||
MinUID => "-u",
|
||||
TLS => "-Y",
|
||||
);
|
||||
|
||||
my %numpairb_switch_for = (
|
||||
LimitRecursion => "-L",
|
||||
PassivePortRange => "-p",
|
||||
AnonymousRatio => "-q",
|
||||
UserRatio => "-Q",
|
||||
);
|
||||
|
||||
my %numpairc_switch_for = (
|
||||
Umask => "-U",
|
||||
Quota => "-n",
|
||||
PerUserLimits => "-y",
|
||||
);
|
||||
|
||||
my %auth_method_for = (
|
||||
LDAPConfigFile => "ldap",
|
||||
MySQLConfigFile => "mysql",
|
||||
PGSQLConfigFile => "pgsql",
|
||||
PureDB => "puredb",
|
||||
ExtAuth => "extauth",
|
||||
);
|
||||
|
||||
my $simple_switch = qr/(@{[join "|", keys %simple_switch_for ]})\s+yes/i;
|
||||
my $string_switch = qr/(@{[join "|", keys %string_switch_for ]})\s+(\S+)/i;
|
||||
my $numeric_switch = qr/(@{[join "|", keys %numeric_switch_for ]})\s+(\d+)/i;
|
||||
my $numpairb_switch = qr/(@{[join "|", keys %numpairb_switch_for ]})\s+(\d+)\s+(\d+)/i;
|
||||
my $numpairc_switch = qr/(@{[join "|", keys %numpairc_switch_for ]})\s+(\d+):(\d+)/i;
|
||||
my $auth_method = qr/(@{[join "|", keys %auth_method_for ]})\s+(\S+)/i;
|
||||
|
||||
die "Usage: pure-config.pl <configuration file> [extra options]\n"
|
||||
unless defined $conffile;
|
||||
|
||||
open CONF, "< $conffile" or die "Can't open $conffile: $!\n";
|
||||
|
||||
!/^\s*(?:$|#)/ and (chomp, push @flg,
|
||||
/$simple_switch/i ? ($simple_switch_for{$1}) :
|
||||
/$string_switch/i ? ($string_switch_for{$1} . $2) :
|
||||
/$numeric_switch/i ? ($numeric_switch_for{$1} . $2) :
|
||||
/$numpairb_switch/i ? ($numpairb_switch_for{$1} . "$2:$3") :
|
||||
/$numpairc_switch/i ? ($numpairc_switch_for{$1} . "$2:$3") :
|
||||
/$auth_method/i ? ("-l" . "$auth_method_for{$1}:$2") :
|
||||
/UnixAuthentication\s+yes/i ? ("-l" . "unix") :
|
||||
/PAMAuthentication\s+yes/i ? ("-l" . "pam") :
|
||||
()
|
||||
) while <CONF>;
|
||||
|
||||
close CONF;
|
||||
|
||||
if (-t STDOUT) {
|
||||
print "Running: $PUREFTPD ", join(" ", @flg), "\n";
|
||||
}
|
||||
exec { $PUREFTPD } ($PUREFTPD, @flg) or die "cannot exec $PUREFTPD: $!";
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# chkconfig: 2345 85 15
|
||||
# description: Pure-FTPd is an FTP server daemon based upon Troll-FTPd
|
||||
# processname: pure-ftpd
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: pureftpd
|
||||
# Required-Start: $all
|
||||
# Required-Stop: $all
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: starts pureftpd server
|
||||
# Description: starts pureftpd server
|
||||
### END INIT INFO
|
||||
|
||||
# Pure-FTPd Settings
|
||||
PURE_PERL="{$SERVER_PATH}/pureftp/sbin/pure-config.pl"
|
||||
PURE_CONF="{$SERVER_PATH}/pureftp/etc/pure-ftpd.conf"
|
||||
PURE_PID="/var/run/pure-ftpd.pid"
|
||||
RETVAL=0
|
||||
prog="Pure-FTPd"
|
||||
|
||||
start() {
|
||||
echo -n $"Starting $prog... "
|
||||
$PURE_PERL $PURE_CONF --daemonize
|
||||
if [ "$?" = 0 ] ; then
|
||||
echo " done"
|
||||
else
|
||||
echo " failed"
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog... "
|
||||
if [ ! -e $PURE_PID ]; then
|
||||
echo -n $"$prog is not running."
|
||||
exit 1
|
||||
fi
|
||||
kill `cat $PURE_PID`
|
||||
if [ "$?" = 0 ] ; then
|
||||
echo " done"
|
||||
else
|
||||
echo " failed"
|
||||
fi
|
||||
}
|
||||
|
||||
restart(){
|
||||
echo $"Restarting $prog..."
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
}
|
||||
|
||||
status(){
|
||||
if [ -e $PURE_PID ]; then
|
||||
echo $"$prog is running."
|
||||
else
|
||||
echo $"$prog is not running."
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart}"
|
||||
esac
|
||||
@@ -16,6 +16,7 @@ Install_pureftp()
|
||||
|
||||
VER=$1
|
||||
FILE=pure-ftpd-${VER}.tar.gz
|
||||
FDIR=pure-ftpd-${VER}
|
||||
DOWNLOAD=https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-${VER}.tar.gz
|
||||
|
||||
|
||||
@@ -23,22 +24,18 @@ Install_pureftp()
|
||||
wget -O $serverPath/source/pureftp/$FILE $DOWNLOAD
|
||||
fi
|
||||
|
||||
if [ ! -d $serverPath/source/pureftp/$FILE ];then
|
||||
cd $serverPath/source/pureftp && tar zxvf $FILE
|
||||
if [ ! -d $serverPath/source/pureftp/$FDIR ];then
|
||||
cd $serverPath/source/pureftp && tar zxvf $FILE
|
||||
fi
|
||||
|
||||
cd pure-ftpd-${1} && ./configure --prefix=${serverPath}/pureftp \
|
||||
--without-inetd \
|
||||
--with-altlog \
|
||||
--with-puredb \
|
||||
--with-throttling \
|
||||
--with-peruserlimits \
|
||||
--with-tls && make && make install
|
||||
|
||||
|
||||
|
||||
cd $serverPath/source/pureftp/$FDIR && ./configure --prefix=${serverPath}/pureftp \
|
||||
--with-everything && make && make install && make clean
|
||||
|
||||
echo "${1}" > ${serverPath}/pureftp/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Uninstall_pureftp()
|
||||
|
||||
@@ -1,131 +1,173 @@
|
||||
/**
|
||||
* 取回FTP数据列表
|
||||
* @param {Number} page 当前页
|
||||
*/
|
||||
function getFtp(page,search) {
|
||||
if(page == undefined) page = 1
|
||||
search = search == undefined ? '':search;
|
||||
search = $("#SearchValue").prop("value");
|
||||
order = getCookie('order');
|
||||
if(order){
|
||||
order = '&order=' + order;
|
||||
}else{
|
||||
order = '';
|
||||
function str2Obj(str){
|
||||
var data = {};
|
||||
kv = str.split('&');
|
||||
for(i in kv){
|
||||
v = kv[i].split('=');
|
||||
data[v[0]] = v[1];
|
||||
}
|
||||
var sUrl = '/data?action=getData'
|
||||
var data = 'tojs=getFtp&table=ftps&limit=15&p='+page+'&search='+search + order;
|
||||
var loadT = layer.load();
|
||||
$.post(sUrl,data, function(data){
|
||||
layer.close(loadT);
|
||||
//构造数据列表
|
||||
var Body = '';
|
||||
if(data.data == ""){
|
||||
Body="<tr><td colspan='7'>"+lan.ftp.empty+"</td></tr>";
|
||||
$(".dataTables_paginate").hide()
|
||||
}
|
||||
for (var i = 0; i < data.data.length; i++) {
|
||||
if(data.data[i].status == '1'){
|
||||
var ftp_status = "<a href='javascript:;' title='"+lan.ftp.stop_title+"' onclick=\"ftpStop("+data.data[i].id+",'"+data.data[i].name+"')\"><span style='color:#5CB85C'>"+lan.ftp.start+" </span> <span style='color:#5CB85C' class='glyphicon glyphicon-play'></span></a>";
|
||||
}else{
|
||||
var ftp_status = "<a href='javascript:;' title='"+lan.ftp.start_title+"' onclick=\"ftpStart("+data.data[i].id+",'"+data.data[i].name+"')\"><span style='color:red'>"+lan.ftp.stop+" </span> <span style='color:red;' class='glyphicon glyphicon-pause'></span></a>";;
|
||||
}
|
||||
Body +="<tr><td><input type='checkbox' onclick='checkSelect();' title='"+data.data[i].name+"' name='id' value='"+data.data[i].id+"'></td>\
|
||||
<td>"+data.data[i].name+"</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.ftp.copy+"' data-pw='"+data.data[i].password+"' onclick=\"btcopy('"+data.data[i].password+"')\"></span></td>\
|
||||
<td>"+ftp_status+"</td>\
|
||||
<td><a class='btlink' title='"+lan.ftp.open_path+"' href=\"javascript:openPath('"+data.data[i].path+"');\">"+data.data[i].path+"</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; color:#bbb'>\
|
||||
<a href='javascript:;' class='btlink' onClick=\"ftpEditSet("+data.data[i].id+",'"+data.data[i].name+"','"+data.data[i].password+"')\">"+lan.ftp.edit_pass+" </a>\
|
||||
| <a href='javascript:;' class='btlink' onclick=\"ftpDelete('"+data.data[i].id+"','"+data.data[i].name+"')\" >"+lan.public.del+"</a>\
|
||||
</td></tr>"
|
||||
}
|
||||
//输出数据列表
|
||||
$("#ftpBody").html(Body);
|
||||
//输出分页
|
||||
$("#ftpPage").html(data.page);
|
||||
//备注
|
||||
$(".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.ftp.ps+"' onblur='GetBakPost(\"ftps\")' />");
|
||||
$(".baktext").focus();
|
||||
});
|
||||
//复制密码
|
||||
showHidePwd();
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
function ftpPost(method,args,callback){
|
||||
|
||||
var _args = null;
|
||||
if (typeof(args) == 'string'){
|
||||
_args = JSON.stringify(str2Obj(args));
|
||||
} else {
|
||||
_args = JSON.stringify(args);
|
||||
}
|
||||
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
$.post('/plugins/run', {name:'pureftp', func:method, args:_args}, function(data) {
|
||||
layer.close(loadT);
|
||||
if (!data.status){
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(callback) == 'function'){
|
||||
callback(data);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
|
||||
function ftpAsyncPost(method,args){
|
||||
return syncPost('/plugins/run',
|
||||
{name:'pureftp', func:method, args:JSON.stringify(args)}
|
||||
);
|
||||
}
|
||||
|
||||
function ftpListFind(){
|
||||
var search = $('#ftp_find_user').val();
|
||||
if (search==''){
|
||||
layer.msg('搜索字符不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
ftpList(1, search);
|
||||
}
|
||||
|
||||
function ftpList(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;
|
||||
}
|
||||
|
||||
ftpPost('get_ftp_list', _data, function(data){
|
||||
|
||||
var rdata = $.parseJSON(data.data);
|
||||
// console.log(rdata);
|
||||
content = '<div class="info-title-tips"><p><span class="glyphicon glyphicon-alert" style="color: #f39c12; margin-right: 10px;"></span>当前FTP地址为:ftp://'+rdata['info']['ip']+':'+rdata['info']['port']+'</p></div>';
|
||||
content += '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找用户名" id="ftp_find_user" style="height: 28px; border-radius: 3px;width: 605px;">';
|
||||
content += '<button class="btn btn-success btn-sm" onclick="ftpListFind();">查找</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 style="width:10%;overflow:hidden;">用户名</th>';
|
||||
content += '<th style="width:10%;overflow:hidden;">密码</th>';
|
||||
content += '<th style="width:10%;">状态</th>';
|
||||
content += '<th>根目录</th>';
|
||||
content += '<th>备注</th>';
|
||||
content += '<th>操作(<a class="btlink" onclick="addFtp(0);">添加</a>|<a class="btlink" onclick="modFtpPort(0,\''+rdata['info']['port']+'\')">端口</a>)</th>';
|
||||
content += '</tr></thead>';
|
||||
|
||||
content += '<tbody>';
|
||||
|
||||
ulist = rdata.data;
|
||||
for (i in ulist){
|
||||
// console.log(ulist[i]);
|
||||
status = '<a href="javascript:;" onclick="ftpStart(\''+ulist[i]['id']+'\',\''+ulist[i]['name']+'\')" <span="" style="color:red">已停用<span style="color:red" class="glyphicon glyphicon-pause"></span></a>';
|
||||
if (ulist[i]['status'] == '1'){
|
||||
status = '<a href="javascript:;" title="FTP帐户" onclick="ftpStop(\''+ulist[i]['id']+'\',\''+ulist[i]['name']+'\')"><span style="color:#5CB85C">已启用</span><span style="color:#5CB85C" class="glyphicon glyphicon-play"></span></a>';
|
||||
}
|
||||
content += '<tr><td>'+ulist[i]['name']+'</td>'+
|
||||
'<td>'+ulist[i]['password']+'</td>'+
|
||||
'<td>'+status+'</td>' +
|
||||
'<td>'+ulist[i]['path']+'</td>' +
|
||||
'<td>'+ulist[i]['ps']+'</td>' +
|
||||
'<td><a class="btlink" onclick="ftpModPwd(\''+ulist[i]['id']+'\',\''+ulist[i]['name']+'\',\''+ulist[i]['password']+'\')">改密</a> | ' +
|
||||
'<a class="btlink" onclick="ftpDelete(\''+ulist[i]['id']+'\',\''+ulist[i]['name']+'\')">删除</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.page;
|
||||
page += '</div></ul></div>';
|
||||
|
||||
content += page;
|
||||
|
||||
$(".soft-man-con").html(content);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*添加FTP帐户
|
||||
* @param {Number} type 添加类型
|
||||
*/
|
||||
function ftpAdd(type) {
|
||||
function addFtp(type) {
|
||||
if (type == 1) {
|
||||
var loadT = layer.load({
|
||||
shade: true,
|
||||
shadeClose: false
|
||||
});
|
||||
var loadT = layer.load({shade: true,shadeClose: false});
|
||||
var data = $("#ftpAdd").serialize();
|
||||
$.post('/ftp?action=AddUser', data, function(rdata) {
|
||||
if (rdata.status) {
|
||||
getFtp(1);
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg, {
|
||||
icon: 1
|
||||
});
|
||||
ftpPost('add_ftp', data, function(data){
|
||||
if (data.data == 'ok'){
|
||||
layer.msg('添加成功!', {icon: 1});
|
||||
} else {
|
||||
getFtp(1);
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg, {
|
||||
icon: 5
|
||||
});
|
||||
layer.msg(rdata.data, {icon: 5});
|
||||
}
|
||||
ftpList();
|
||||
layer.close(loadT);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
var defaultPath = $("#defaultPath").html();
|
||||
|
||||
var data = ftpAsyncPost('get_www_dir');
|
||||
var defaultPath = data.data;
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '500px',
|
||||
title: lan.ftp.add_title,
|
||||
title: '添加FTP帐户',
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<form class='bt-form pd20 pb70' id='ftpAdd'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.ftp.add_user+"</span>\
|
||||
<span class='tname'>用户名</span>\
|
||||
<div class='info-r'><input class='bt-input-text' type='text' id='ftpUser' name='ftp_username' style='width:330px' /></div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.ftp.add_pass+"</span>\
|
||||
<div class='info-r'><input class='bt-input-text mr5' type='text' name='ftp_password' id='MyPassword' style='width:330px' value='"+(RandomStrPwd(10))+"' /><span title='"+lan.ftp.add_pass_rep+"' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(10)'></span></div>\
|
||||
<span class='tname'>密码</span>\
|
||||
<div class='info-r'><input class='bt-input-text mr5' type='text' name='ftp_password' id='MyPassword' style='width:330px' value='"+(randomStrPwd(16))+"' /><span title='随机密码' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span></div>\
|
||||
</div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.ftp.add_path+"</span>\
|
||||
<div class='info-r'><input id='inputPath' class='bt-input-text mr5' type='text' name='path' value='"+defaultPath+"/' placeholder='"+lan.ftp.add_path_title+"' style='width:330px' /><span class='glyphicon glyphicon-folder-open cursor' onclick='ChangePath(\"inputPath\")'></span><p class='c9 mt10'>"+lan.ftp.add_path_ps+"</p></div>\
|
||||
<span class='tname'>根目录</span>\
|
||||
<div class='info-r'><input id='inputPath' class='bt-input-text mr5' type='text' name='path' value='"+defaultPath+"/' placeholder='"+lan.ftp.add_path_title+"' style='width:330px' /><span class='glyphicon glyphicon-folder-open cursor' onclick='changePath(\"inputPath\")'></span><p class='c9 mt10'>"+lan.ftp.add_path_ps+"</p></div>\
|
||||
</div>\
|
||||
<div class='line' style='display:none'>\
|
||||
<span class='tname'>"+lan.ftp.add_ps+"</span>\
|
||||
<span class='tname'>备注</span>\
|
||||
<div class='info-r'>\
|
||||
<input class='bt-input-text' type='text' name='ps' value='' placeholder='"+lan.ftp.add_ps_title+"' />\
|
||||
<input id='ftp_ps' class='bt-input-text' type='text' name='ps' value='' placeholder='备注' />\
|
||||
</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=\"ftpAdd(1)\" >"+lan.public.submit+"</button>\
|
||||
<button type='button' class='btn btn-danger btn-sm btn-title' onclick='layer.closeAll()'>关闭</button>\
|
||||
<button type='button' class='btn btn-success btn-sm btn-title' onclick=\"addFtp(1)\" >提交</button>\
|
||||
</div>\
|
||||
</form>"
|
||||
</form>",
|
||||
});
|
||||
|
||||
|
||||
$("#ftpUser").keyup(function()
|
||||
{
|
||||
$("#ftpUser").keyup(function(){
|
||||
var ftpName = $(this).val();
|
||||
if($("#inputPath").val().substr(0,11) == '/www/wwwroo' )
|
||||
{
|
||||
$("#inputPath").val('/www/wwwroot/'+ftpName);
|
||||
}
|
||||
$("#inputPath").val(defaultPath+'/'+ftpName);
|
||||
$("#ftp_ps").val(ftpName);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -137,122 +179,123 @@ function ftpAdd(type) {
|
||||
* @return {bool}
|
||||
*/
|
||||
function ftpDelete(id,ftp_username){
|
||||
SafeMessage(lan.public.del+"["+ftp_username+"]",lan.get('confirm_del',[ftp_username]),function(){
|
||||
safeMessage(lan.public.del+"["+ftp_username+"]",lan.get('confirm_del',[ftp_username]),function(){
|
||||
layer.msg(lan.public.the_del,{icon:16,time:0,shade: [0.3, '#000']});
|
||||
var data='&id='+id+'&username='+ftp_username;
|
||||
$.post('/ftp?action=DeleteUser',data,function(rdata){
|
||||
layer.closeAll();
|
||||
if(rdata['status'] == true){
|
||||
getFtp(1);
|
||||
layer.msg(rdata.msg,{icon:1});
|
||||
}else{
|
||||
layer.msg(rdata.msg,{icon:2});
|
||||
|
||||
ftpPost('del_ftp', data, function(data){
|
||||
layer.msg('删除成功!', {icon: 1});
|
||||
ftpList();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function modFtpPort(type, port){
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '500px',
|
||||
title: '修改FTP帐户端口',
|
||||
content: "<form class='bt-form pd20 pb70'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>默认端口</span>\
|
||||
<div class='info-r'><input class='bt-input-text mr5' type='text' id='ftpPort' name='ftp_port' style='width:330px' value='"+port+"'/></div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button id='ftp_port_close' type='button' class='btn btn-danger btn-sm btn-title'>关闭</button>\
|
||||
<button id='ftp_port_submit' type='button' class='btn btn-success btn-sm btn-title'>提交</button>\
|
||||
</div>\
|
||||
</form>",
|
||||
});
|
||||
|
||||
$('#ftp_port_close').click(function(){
|
||||
$('.layui-layer-close1').click();
|
||||
});
|
||||
|
||||
$('#ftp_port_submit').click(function(){
|
||||
var port = $('#ftpPort').val();
|
||||
data = 'port='+port
|
||||
ftpPost('mod_ftp_port', data,function(data){
|
||||
ftpList();
|
||||
if (data.data == 'ok'){
|
||||
layer.msg('修改成功!', {icon: 1});
|
||||
} else {
|
||||
layer.msg(data.data, {icon: 2});
|
||||
}
|
||||
$('.layui-layer-close1').click();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
//批量删除
|
||||
function allDeleteFtp(){
|
||||
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.ftp.del_all,"<a style='color:red;'>"+lan.get('del_all_ftp',[dataList.length])+"</a>",function(){
|
||||
layer.closeAll();
|
||||
syncDeleteFtp(dataList,0,'');
|
||||
function ftpModPwd(id,name,password){
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '500px',
|
||||
title: '修改FTP帐户密码',
|
||||
content: "<form class='bt-form pd20 pb70'>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>用户名</span>\
|
||||
<div class='info-r'><input disabled class='bt-input-text mr5' type='text' id='ftpUser' name='ftp_username' style='width:330px' value='"+name+"'/></div>\
|
||||
</div>\
|
||||
\
|
||||
<div class='line'>\
|
||||
<span class='tname'>密码</span>\
|
||||
<div class='info-r'><input class='bt-input-text mr5' type='text' name='ftp_password' id='MyPassword' style='width:330px' value='"+password+"' /><span title='随机密码' class='glyphicon glyphicon-repeat cursor' onclick='repeatPwd(16)'></span></div>\
|
||||
</div>\
|
||||
<div class='bt-form-submit-btn'>\
|
||||
<button id='ftp_mod_close' type='button' class='btn btn-danger btn-sm btn-title'>关闭</button>\
|
||||
<button id='ftp_mod_submit' type='button' class='btn btn-success btn-sm btn-title'>提交</button>\
|
||||
</div>\
|
||||
</form>",
|
||||
});
|
||||
}
|
||||
|
||||
//模拟同步开始批量删除
|
||||
function syncDeleteFtp(dataList,successCount,errorMsg){
|
||||
if(dataList.length < 1) {
|
||||
layer.msg(lan.get('del_all_ftp_ok',[successCount]),{icon:1});
|
||||
return;
|
||||
}
|
||||
var loadT = layer.msg(lan.get('del_all_task_del',[dataList[0].name]),{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'/ftp?action=DeleteUser',
|
||||
data:'id='+dataList[0].id+'&username='+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.ftp.del_all_err+'</p>';
|
||||
}
|
||||
errorMsg += '<li>'+dataList[0].name+' -> '+frdata.msg+'</li>'
|
||||
|
||||
$('#ftp_mod_close').click(function(){
|
||||
$('.layui-layer-close1').click();
|
||||
});
|
||||
|
||||
$('#ftp_mod_submit').click(function(){
|
||||
pwd = $('#MyPassword').val();
|
||||
data='id='+id+'&name='+name+'&password='+pwd
|
||||
ftpPost('mod_ftp', data,function(data){
|
||||
ftpList();
|
||||
if (data.data == 'ok'){
|
||||
layer.msg('修改成功!', {icon: 1});
|
||||
}
|
||||
dataList.splice(0,1);
|
||||
syncDeleteFtp(dataList,successCount,errorMsg);
|
||||
}
|
||||
$('.layui-layer-close1').click();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 选中项操作
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止FTP帐号
|
||||
* @param {Number} id FTP的ID
|
||||
* @param {String} username FTP用户名
|
||||
*/
|
||||
function ftpStop(id, username) {
|
||||
layer.confirm(lan.ftp.stop_confirm.replace('{1}',username), {
|
||||
title: lan.ftp.stop_title,icon:3,
|
||||
layer.confirm('您真的要停止{1}的FTP吗?'.replace('{1}',username), {
|
||||
title: 'FTP帐户',icon:3,
|
||||
closeBtn:2
|
||||
}, function(index) {
|
||||
if (index > 0) {
|
||||
var loadT = layer.load({shade: true,shadeClose: false});
|
||||
var data='id=' + id + '&username=' + username + '&status=0';
|
||||
$.post('/ftp?action=SetStatus',data, function(rdata) {
|
||||
ftpPost('stop_ftp', data, function(data){
|
||||
layer.close(loadT);
|
||||
if (rdata.status == true) {
|
||||
layer.msg(rdata.msg, {icon: 1});
|
||||
getFtp(1);
|
||||
if (data.data == 'ok'){
|
||||
showMsg('启动成功!', function(){
|
||||
ftpList();
|
||||
},{icon: 1});
|
||||
} else {
|
||||
layer.msg(rdata.msg, {icon: 5});
|
||||
layer.msg(data.data, {icon: 2});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
layer.closeAll();
|
||||
}
|
||||
$('.layui-layer-close1').click();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -264,110 +307,16 @@ function ftpStop(id, username) {
|
||||
function ftpStart(id, username) {
|
||||
var loadT = layer.load({shade: true,shadeClose: false});
|
||||
var data='id=' + id + '&username=' + username + '&status=1';
|
||||
$.post('/ftp?action=SetStatus',data, function(rdata) {
|
||||
ftpPost('start_ftp', data, function(data){
|
||||
layer.close(loadT);
|
||||
if (rdata.status == true) {
|
||||
layer.msg(rdata.msg, {icon: 1});
|
||||
getFtp(1);
|
||||
if (data.data == 'ok'){
|
||||
showMsg('启动成功!', function(){
|
||||
ftpList();
|
||||
},{icon: 1});
|
||||
} else {
|
||||
layer.msg(rdata.msg, {icon: 5});
|
||||
layer.msg(data.data, {icon: 2});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改FTP帐户信息
|
||||
* @param {Number} type 修改类型
|
||||
* @param {Number} id FTP编号
|
||||
* @param {String} username FTP用户名
|
||||
* @param {String} statu FTP状态
|
||||
* @param {String} group FTP权限
|
||||
* @param {String} passwd FTP密码
|
||||
*/
|
||||
function ftpEditSet(id, username, passwd) {
|
||||
if (id != undefined) {
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '300px',
|
||||
title: lan.ftp.pass_title,
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<form class='bt-form pd20 pb70' id='ftpEditSet'>\
|
||||
<div class='line'>\
|
||||
<input type='hidden' name='id' value='" + id + "'/>\
|
||||
<input type='hidden' name='ftp_username' value='" + username + "'/>\
|
||||
<span class='tname'>"+lan.ftp.pass_user+":</span><div class='info-r'><input class='bt-input-text' type='text' name='myusername' value='" + username + "' disabled style='width:100%'/></div></div>\
|
||||
<div class='line'>\
|
||||
<span class='tname'>"+lan.ftp.pass_new+":</span><div class='info-r'><input class='bt-input-text' type='text' name='new_password' value='" + passwd + "' 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='ftpEditSet()' >"+lan.public.ok+"</button>\
|
||||
</div>\
|
||||
</form>"
|
||||
});
|
||||
} else {
|
||||
layer.confirm(lan.ftp.pass_confirm, {
|
||||
title: lan.ftp.stop_title,icon:3,
|
||||
closeBtn:2
|
||||
}, function(index) {
|
||||
if (index > 0) {
|
||||
var loadT = layer.load({
|
||||
shade: true,
|
||||
shadeClose: false
|
||||
});
|
||||
var data = $("#ftpEditSet").serialize();
|
||||
$.post('/ftp?action=SetUserPassword', data, function(rdata) {
|
||||
layer.closeAll();
|
||||
layer.msg(rdata.msg, { icon: rdata.status?1:5});
|
||||
getFtp(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*修改FTP服务端口
|
||||
*/
|
||||
function ftpPortEdit(port) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
skin: 'demo-class',
|
||||
area: '300px',
|
||||
title: lan.ftp.port_title,
|
||||
closeBtn: 2,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form pd20 pb70' id='ftpEditSet'>\
|
||||
<div class='line'><input id='ftp_port' class='bt-input-text' type='text' name='ftp_port' value='" + port + "' style='width:100%' /></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 id='poseFtpPort' type='button' class='btn btn-success btn-sm btn-title'>"+lan.public.submit+"</button>\
|
||||
</div>\
|
||||
</div>"
|
||||
});
|
||||
$("#poseFtpPort").click(function(){
|
||||
var NewPort = $("#ftp_port").val();
|
||||
ftpPortPost(NewPort);
|
||||
})
|
||||
$("#ftp_port").focus().keyup(function(e){
|
||||
if(e.keyCode == 13) $("#poseFtpPort").click();
|
||||
});
|
||||
}
|
||||
//修改FTP服务端口
|
||||
function ftpPortPost(port){
|
||||
layer.closeAll();
|
||||
var loadT = layer.msg(lan.public.the,{icon:16,time:0,shade: [0.3, '#000']});
|
||||
var data='port=' + port;
|
||||
$.post('/ftp?action=setPort',data, function(rdata) {
|
||||
layer.close(loadT)
|
||||
layer.msg(rdata.msg,{icon:rdata.status?1:2})
|
||||
setTimeout(function(){
|
||||
window.location.reload()
|
||||
},3000)
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
[db]
|
||||
DB_HOST = 127.0.0.1
|
||||
DB_PORT = 3306
|
||||
DB_USER = qbittorrent
|
||||
DB_PASS = qbittorrent
|
||||
DB_NAME = qbittorrent
|
||||
|
||||
[qb]
|
||||
QB_HOST = 127.0.0.1
|
||||
QB_PORT = 8080
|
||||
QB_USER = admin
|
||||
QB_PWD = adminadmin
|
||||
|
||||
|
||||
[file]
|
||||
FILE_TO={$SERVER_PATH}/tmp
|
||||
FILE_TRANSFER_TO={$SERVER_PATH}/tmp
|
||||
FILE_OWN=www
|
||||
FILE_GROUP=www
|
||||
|
||||
[task]
|
||||
TASK_RATE=4
|
||||
TASK_COMPLETED_RATE=10
|
||||
@@ -0,0 +1,29 @@
|
||||
CREATE TABLE `pl_hash_list` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` text NOT NULL,
|
||||
`info_hash` varchar(40) NOT NULL,
|
||||
`length` bigint(20) NOT NULL,
|
||||
`create_time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `info_hash` (`info_hash`),
|
||||
KEY `create_time` (`create_time`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `pl_hash_file` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`pid` bigint(20) NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`m3u8` varchar(40) NOT NULL,
|
||||
`length` bigint(20) NOT NULL,
|
||||
`create_time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `create_time` (`create_time`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `pl_hash_queue` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`info_hash` varchar(40) NOT NULL,
|
||||
`create_time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `create_time` (`create_time`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,22 @@
|
||||
<div class="bt-form">
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('qbittorrent');">服务</p>
|
||||
<p onclick="pluginInitD('qbittorrent');">自启动</p>
|
||||
<p onclick="pluginConfig('qbittorrent', '','get_sql');" title="手动导入SQL">导入SQL</p>
|
||||
<p onclick="pluginConfig('qbittorrent');">配置</p>
|
||||
<p onclick="pluginLogs('qbittorrent','','get_run_Log', 25);">日志</p>
|
||||
<p onclick="qbList();">列表</p>
|
||||
|
||||
</div>
|
||||
<div class="bt-w-con pd15">
|
||||
<div class="soft-man-con">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
pluginService('qbittorrent');
|
||||
$.getScript( "/plugins/file?name=qbittorrent&f=js/qbittorrent.js");
|
||||
</script>
|
||||