Compare commits

...

2909 Commits
0.18.0 ... dev

Author SHA1 Message Date
6f365e122a Create install.sh 2026-11-05 20:31:10 +08:00
e3229efe1b Update install.sh 2026-11-05 20:27:25 +08:00
710acecff7 update 2026-11-05 20:21:13 +08:00
9c7a155be0 update 2026-11-05 20:18:44 +08:00
157a5da6f1 Update index.py 2026-11-05 19:19:31 +08:00
7ee5ed5808 up 2026-11-05 19:02:31 +08:00
e8a96959a5 Update install.sh 2026-11-05 18:56:26 +08:00
a4845acbb6 Update index.py 2026-11-05 18:44:11 +08:00
fec638007c Update setting.py 2026-11-05 16:49:15 +08:00
80f7a0de38 Update setting.py 2026-11-05 16:42:39 +08:00
a3bb9ac80a Update setting.py 2026-11-05 16:30:21 +08:00
3dcc6e3349 Update setting.py 2026-11-05 16:28:18 +08:00
60870a4e5d Update setting.py 2026-11-05 16:18:39 +08:00
ea635bc960 Update setting.py 2026-11-05 16:08:12 +08:00
749c8443ee Update setting.py 2026-11-05 16:06:46 +08:00
052120c25e Update setting.py 2026-11-05 16:05:48 +08:00
a2b3b86c43 Update setting.py 2026-11-05 16:05:37 +08:00
6d57e3dd40 Update mw.tpl 2026-11-05 15:45:41 +08:00
a67689d890 Update mw.tpl 2026-11-05 15:36:24 +08:00
b6bffedf06 Update mw.tpl 2026-11-05 15:34:52 +08:00
e07eaf4226 Update mw.tpl 2026-11-05 15:32:05 +08:00
dd9e9d4899 Update mw.tpl 2026-11-05 15:17:19 +08:00
cd1d80915a Update mw.tpl 2026-11-05 15:14:19 +08:00
40f64ab3e8 Update install.sh 2026-11-05 14:55:31 +08:00
69ba921ec4 Update index.py 2026-11-05 14:54:39 +08:00
255fbcd688 Update index.py 2026-11-05 14:35:35 +08:00
24e12b70c8 Update index.py 2026-11-05 14:35:02 +08:00
0feee48ea8 Update install.sh 2026-11-05 14:31:22 +08:00
5cd8c5ae2c Update index.py 2026-11-05 14:28:11 +08:00
28a75eaedc Update index.py 2026-11-05 14:26:12 +08:00
50d0794f4a Update index.py 2026-11-05 14:23:24 +08:00
755e53f4d7 Update index.py 2026-11-05 14:20:13 +08:00
1876027bd2 update 2026-11-05 14:14:23 +08:00
26b06f9bb2 Update index.py 2026-11-05 14:10:37 +08:00
8f67d35260 update 2026-11-05 13:40:46 +08:00
7fa78c78e2 更加优化匹配 2026-11-05 13:37:37 +08:00
ae7276300f Update install.sh 2026-11-05 11:57:54 +08:00
420816ff4e Update requirements.txt 2026-11-05 09:58:54 +08:00
df34a7ef9b Update plugin.py 2026-11-05 00:12:28 +08:00
e1b199c8d5 Update plugin.py 2026-11-05 00:07:29 +08:00
Mr Chen
e6060847ef Merge pull request #965 from midoks/dev
常规更新
2026-11-04 15:52:18 +08:00
7ff1530684 update 2026-11-04 15:35:08 +08:00
cd0ad7488e update 2026-11-04 15:33:18 +08:00
6a0f81154a Update index.py 2026-11-04 15:31:09 +08:00
Mr Chen
096c736c28 Merge pull request #964 from midoks/dev
常规优化
2026-11-04 14:51:09 +08:00
7d01a487dc Merge branch 'master' into dev 2026-11-04 14:47:28 +08:00
ba95ef1537 Update install.sh 2026-11-04 14:43:26 +08:00
01035018c4 Update install.sh 2026-11-04 14:43:07 +08:00
8aa12b979a Update install.sh 2026-11-04 14:40:26 +08:00
98dc9e5bd8 Update tool_cron.py 2026-11-04 14:34:10 +08:00
4ebadc28c9 Update tool_cron.py 2026-11-04 14:32:34 +08:00
02115226fa Update tool_cron.py 2026-11-04 14:31:51 +08:00
f661aea83c Update manticore.conf 2026-11-04 14:17:36 +08:00
cfd3abf97b Update manticore.conf 2026-11-04 14:15:16 +08:00
b5d1c8cfcf Update manticore.conf 2026-11-04 14:12:11 +08:00
98156cc1cb Update sql_mysql.py 2026-11-04 14:01:56 +08:00
33a0dc6014 Update my.cnf 2026-11-04 13:57:38 +08:00
95a6f86e5d Update sql_mysql.py 2026-11-04 13:52:16 +08:00
74ac55b01d Update info.json 2026-11-04 13:50:19 +08:00
518cc78670 Update none.conf 2026-11-04 13:45:04 +08:00
43727decf0 update 2026-11-04 13:12:33 +08:00
599b3a7f4a Update install.sh 2026-11-04 13:05:29 +08:00
bf6c18c57a Update install.sh 2026-11-04 13:04:06 +08:00
34838bb238 update 2026-11-04 12:58:55 +08:00
1a356e516c Update index.py 2026-11-04 12:45:23 +08:00
15e273aa6f Update index.py 2026-11-04 12:44:21 +08:00
Mr Chen
4c3d3bf41d Merge pull request #963 from midoks/dev
常规优化
2026-11-04 12:43:49 +08:00
f782bacc64 update 2026-11-04 12:41:48 +08:00
7e62ab62f9 Update index.py 2026-11-04 11:45:38 +08:00
aaa8644348 Update mariadb.js 2026-11-04 11:43:26 +08:00
53797c7f56 Update index.py 2026-11-04 11:42:18 +08:00
c9302f406e Update my.cnf 2026-11-04 11:10:00 +08:00
7ad881c8ad mysql 同时过滤系统表
replicate-wild-ignore-table = mysql.%
replicate-wild-ignore-table = information_schema.%
replicate-wild-ignore-table = performance_schema.%
replicate-wild-ignore-table = sys.%
2026-11-04 11:06:28 +08:00
015e57f96d update 2026-11-04 10:21:48 +08:00
84b94a172e Update index.py 2026-11-04 10:11:25 +08:00
c1380945ef Update index.py 2026-11-04 10:11:02 +08:00
2d80df003e Update my5.7.cnf 2026-11-04 01:16:28 +08:00
568cdaa0ad Update my5.7.cnf 2026-11-04 01:13:19 +08:00
d11e4807df Update my5.7.cnf 2026-11-04 01:12:00 +08:00
Mr Chen
f6bc08cec1 Merge pull request #962 from midoks/dev
update
2026-11-04 00:47:06 +08:00
d723afb96e update 2026-11-04 00:26:05 +08:00
Mr Chen
6c2aa089f3 Merge pull request #961 from midoks/dev
常规优化
2026-11-04 00:06:02 +08:00
35e1ff2e96 update 2026-11-04 00:04:52 +08:00
bee9e89ed5 Update index.py 2026-11-03 22:46:33 +08:00
d0b622906f Update index.py 2026-11-03 22:37:34 +08:00
56f7edcb55 update 2026-11-03 22:36:17 +08:00
4acbc0363f Merge branch 'master' into dev 2026-11-03 22:26:50 +08:00
79013db685 Merge branch 'master' into dev 2026-11-03 22:19:05 +08:00
Mr Chen
eb5b5e5ce8 Merge pull request #960 from midoks/dev
常规更新
2026-11-03 22:16:20 +08:00
b9e6469635 update 2026-11-03 22:04:11 +08:00
56ab927f8c update 2026-11-03 21:56:19 +08:00
3d74320e76 update 2026-11-03 21:25:14 +08:00
0371eaa37a Update index.py 2026-11-03 17:01:41 +08:00
713dbfcda5 Update index.py 2026-11-03 16:47:50 +08:00
93ef2848ed Update mariadb.js 2026-11-03 16:38:47 +08:00
8750cf0f74 Update mariadb.js 2026-11-03 16:38:38 +08:00
af32a1e54d Update index.py 2026-11-03 16:23:42 +08:00
2a7c63029a Update index.py 2026-11-03 15:56:48 +08:00
f8fe7bea19 Update index.py 2026-11-03 15:55:08 +08:00
ef2814bafe Update index.py 2026-11-03 14:14:09 +08:00
220fef5f4d Update index.py 2026-11-03 14:13:36 +08:00
2835c111d0 update 2026-11-03 14:10:41 +08:00
6d0dcf3112 Update index.py 2026-11-03 14:06:44 +08:00
28307ce8e8 Update index.py 2026-11-03 14:01:04 +08:00
282fbed37d Update index.py 2026-11-03 13:53:13 +08:00
101b6d06bc Update mysql-community.js 2026-11-03 13:46:27 +08:00
8de4c74696 update 2026-11-03 13:45:35 +08:00
ba62972820 update 2026-11-03 13:34:34 +08:00
ec512f50af update 2026-11-03 13:08:43 +08:00
3261f54649 update 2026-11-03 12:28:50 +08:00
ec38ba9e21 update 2026-11-03 12:22:57 +08:00
9e1dc94a08 Update install.sh 2026-11-03 12:19:41 +08:00
40a76ac81e 主从同步模式 切换功能 2026-11-03 12:12:16 +08:00
721245b9ad Update my26.10.cnf 2026-11-03 12:02:37 +08:00
cb4ae9b74f Update my26.7.cnf 2026-11-03 12:01:15 +08:00
Mr Chen
5524ecf4e0 Merge pull request #959 from midoks/dev
常规更新
2026-11-03 12:00:47 +08:00
dbb2718892 update 2026-11-03 11:59:39 +08:00
88fc903d80 update 2026-11-03 11:56:07 +08:00
Mr Chen
242c30f7cb Merge pull request #958 from midoks/dev
常规更新
2026-11-03 11:29:36 +08:00
c944b7c585 update 2026-11-03 11:17:45 +08:00
dc2e2695be update 2026-11-03 11:05:28 +08:00
f5b86ea189 update 2026-11-03 11:04:36 +08:00
b6c2f7f3a1 Update index.py 2026-11-03 10:57:31 +08:00
81003f75b7 Update backup.py 2026-11-03 10:55:25 +08:00
d6dc330083 Update postgresql.js 2026-11-03 10:53:49 +08:00
fd0cbe10fc update 2026-11-03 10:51:15 +08:00
4ed77e82be update 2026-11-03 10:29:58 +08:00
Mr Chen
de0e89f056 Merge pull request #957 from midoks/dev
常规优化
2026-11-03 10:22:32 +08:00
29da5146f6 数据类开启卸载检查 2026-11-03 10:19:24 +08:00
e951089b45 Update index.py 2026-11-03 10:14:05 +08:00
909d65ad83 update 2026-11-03 10:13:20 +08:00
27cac55b8f Update index.py 2026-11-03 10:06:26 +08:00
0ee6ae3713 Update index.py 2026-11-03 09:58:32 +08:00
fb97160cfb Update index.py 2026-11-03 09:58:04 +08:00
96b00526fe Update install.sh 2026-11-03 09:55:18 +08:00
909fe6d0f1 Update sql_postgresql.py 2026-11-03 09:54:01 +08:00
f2e9f4c5e8 update 2026-11-03 09:52:15 +08:00
3b629b1296 Merge branch 'master' into dev 2026-11-02 23:51:58 +08:00
5cee415030 Merge branch 'master' into dev 2026-11-02 23:49:49 +08:00
Mr Chen
141e52d42a Merge pull request #956 from midoks/dev
常规更新
2026-11-02 23:48:47 +08:00
1b21f3c814 Update app.js 2026-11-02 23:46:15 +08:00
4ddc2fef8e update 2026-11-02 23:42:40 +08:00
18b259a5a5 Update app.js 2026-11-02 23:35:06 +08:00
2e2288a691 update 2026-11-02 23:32:29 +08:00
d03ae1db7b Update app.js 2026-11-02 23:15:15 +08:00
418355a571 update 2026-11-02 23:12:34 +08:00
340b53aa62 update 2026-11-02 23:01:21 +08:00
dd0628a7fb Update install.sh 2026-11-02 22:50:47 +08:00
3e5b48d2ad Update index.py 2026-11-02 22:28:54 +08:00
Mr Chen
815148a722 Merge pull request #955 from midoks/dev
常规优化
2026-11-02 22:21:33 +08:00
47aadfd877 Merge branch 'master' into dev 2026-11-02 22:19:31 +08:00
42bfd9a934 update 2026-11-02 22:01:40 +08:00
55df1b7613 Update backup.py 2026-11-02 21:50:01 +08:00
6bc3fc5707 Update index.py 2026-11-02 21:42:33 +08:00
19771181dd update 2026-11-02 21:42:27 +08:00
f0b65332bd Update index.py 2026-11-02 21:28:35 +08:00
7dd8a1eb4f Update index.py 2026-11-02 21:24:39 +08:00
f584c18d7e Update index.py 2026-11-02 21:16:53 +08:00
b023044473 Update index.py 2026-11-02 21:13:07 +08:00
dfa7ffdb53 Update index.py 2026-11-02 21:08:45 +08:00
a5a6eb7e5f update 2026-11-02 21:07:24 +08:00
eac88f1d26 update 2026-11-02 21:03:09 +08:00
518f693948 Update index.py 2026-11-02 20:56:05 +08:00
43684e9b20 update 2026-11-02 20:53:54 +08:00
59a7bb5584 update 2026-11-02 20:49:31 +08:00
f623fd9dcf Update postgresql.js 2026-11-02 20:41:50 +08:00
9db36d45af update 2026-11-02 20:33:57 +08:00
ff5670797a Update backup.py 2026-11-02 20:31:56 +08:00
54ad7e5fd0 update 2026-11-02 20:10:08 +08:00
2970aa4b8c Update index.py 2026-11-02 20:08:36 +08:00
d2e5751542 Update index.py 2026-11-02 20:07:59 +08:00
ba5f6f4958 Update index.py 2026-11-02 20:07:11 +08:00
b220552f92 update 2026-11-02 20:04:47 +08:00
d02981cee5 Update backup.py 2026-11-02 19:46:25 +08:00
96d5246415 Update index.py 2026-11-02 19:35:17 +08:00
ea284049c0 update 2026-11-02 19:02:40 +08:00
5c44bb10d1 Update index.py 2026-11-02 18:55:21 +08:00
c7c834fb75 Update postgresql.js 2026-11-02 18:55:16 +08:00
2ade5e490c update 2026-11-02 18:40:38 +08:00
6c61d3f3c0 Update postgresql.js 2026-11-02 18:30:25 +08:00
ab19878a80 Update mw.tpl 2026-11-02 18:11:02 +08:00
c27abfde3c Update install_mac.sh 2026-11-02 17:54:06 +08:00
411b21cdec Update install_mac.sh 2026-11-02 17:48:46 +08:00
26e21e631d update 2026-11-02 17:46:47 +08:00
Mr Chen
653068f2c2 Merge pull request #954 from midoks/dev
常规优化
2026-11-02 17:42:54 +08:00
188c63826f mysql-community mac 2026-11-02 17:41:02 +08:00
1820fc724f Update install.sh 2026-11-02 17:32:37 +08:00
645519b983 update 2026-11-02 17:27:57 +08:00
f97e015bbc update 2026-11-02 17:22:03 +08:00
9d47a385f5 update 2026-11-02 16:56:59 +08:00
ca06c68d24 update 2026-11-02 16:53:59 +08:00
841873418c update 2026-11-02 16:32:58 +08:00
05a6f093ab update 2026-11-02 16:31:45 +08:00
a916104d33 update 2026-11-02 16:30:09 +08:00
4609c360ac mongodb命令导入 2026-11-02 16:18:22 +08:00
b3acf3647f Update mysql.js 2026-11-02 16:10:51 +08:00
400c9d1276 Update mysql.js 2026-11-02 15:09:57 +08:00
Mr Chen
59bd655bb1 Merge pull request #953 from midoks/dev
常规优化
2026-11-02 07:52:20 +08:00
8227253b74 update 2026-11-02 07:42:26 +08:00
4e5604dc27 Update mariadb.js 2026-11-02 07:36:44 +08:00
2e238e6982 Update index.py 2026-11-02 07:33:01 +08:00
c5df0f256c Update index.py 2026-11-02 07:32:03 +08:00
6bd73131ce Update index.py 2026-11-02 07:29:19 +08:00
309422a41c update 2026-11-02 07:26:34 +08:00
6aa7d9dc20 update 2026-11-02 07:24:45 +08:00
565e1cc882 Update index.py 2026-11-02 07:24:33 +08:00
Mr Chen
5c1e292da9 Merge pull request #952 from midoks/dev
常规优化
2026-11-01 19:44:53 +08:00
6db1ee133d update 2026-11-01 19:35:10 +08:00
Mr Chen
383cec2ee5 Merge pull request #951 from midoks/dev
兼容更新+mysql备份可指定到表备份
2026-11-01 15:45:08 +08:00
dfa2163407 Update plugin.py 2026-11-01 15:32:23 +08:00
ed9a9b7860 Update plugin.py 2026-11-01 15:26:22 +08:00
5af49dc081 Merge branch 'master' into dev 2026-11-01 14:51:45 +08:00
d4f425abf8 备份不走sqlite了 2026-11-01 14:49:39 +08:00
1867ee01f1 update 2026-11-01 14:45:00 +08:00
81fe83e0a1 update 2026-11-01 14:31:42 +08:00
f266ec86c0 Create backup.py 2026-11-01 14:22:44 +08:00
e5d6357fae update 2026-11-01 14:20:52 +08:00
7967b36088 Update backup.py 2026-11-01 14:03:52 +08:00
d7471fe882 Update index.py 2026-11-01 13:56:19 +08:00
b4b67c8f48 update 2026-11-01 13:56:02 +08:00
63ae895f12 Update index.py 2026-11-01 13:53:27 +08:00
5dd77ee747 Update backup.py 2026-11-01 13:50:33 +08:00
6071dfa5f1 Update index.py 2026-11-01 13:46:01 +08:00
11d8d813d2 update 2026-11-01 13:40:40 +08:00
f337a60dc1 Update index.py 2026-11-01 13:16:07 +08:00
33f66ab3b1 Update index.py 2026-11-01 13:14:27 +08:00
eb71732d20 Update index.py 2026-11-01 13:07:09 +08:00
fbc9340960 Update index.py 2026-11-01 13:01:15 +08:00
a2f14f4121 Update index.py 2026-11-01 12:26:38 +08:00
ce8c7474ce Update backup.py 2026-11-01 12:24:13 +08:00
85d9f1409a Update index.py 2026-11-01 12:19:10 +08:00
c29dfee004 Update backup.py 2026-11-01 12:12:04 +08:00
618f938462 update 2026-11-01 12:08:34 +08:00
4e7927f9bc Update crontab.py 2026-11-01 03:24:26 +08:00
212f29438d Update crontab.py 2026-11-01 03:16:28 +08:00
3b6d9c3310 Update crontab.py 2026-11-01 03:15:13 +08:00
c01cb01d71 Update crontab.py 2026-11-01 03:14:31 +08:00
712863b766 Update crontab.py 2026-11-01 03:11:14 +08:00
601a80950f Update crontab.py 2026-11-01 03:10:21 +08:00
9f46ceac33 Update crontab.js 2026-11-01 03:08:58 +08:00
ad9b9be7fe Update crontab.py 2026-11-01 03:05:36 +08:00
2be6ac36ef Update crontab.py 2026-11-01 03:04:11 +08:00
fdb8ca205f Update crontab.py 2026-11-01 03:01:49 +08:00
f1024c165a Update crontab.py 2026-11-01 02:58:01 +08:00
9efc85f10d Update crontab.py 2026-11-01 02:52:33 +08:00
dd592b40ee Update crontab.py 2026-11-01 02:52:02 +08:00
9103646150 Update crontab.py 2026-11-01 02:50:05 +08:00
cae2680862 Update crontab.py 2026-11-01 02:48:41 +08:00
e3099a946b Update crontab.py 2026-11-01 02:44:49 +08:00
3f1da50025 Update crontab.py 2026-11-01 02:41:36 +08:00
fbd70eb4f9 Update crontab.py 2026-11-01 02:40:11 +08:00
ef0d6d5265 Update crontab.py 2026-11-01 02:36:43 +08:00
1e6932cd01 Update crontab.py 2026-11-01 02:36:08 +08:00
d173586d49 Update crontab.py 2026-11-01 02:28:51 +08:00
717269dadc Update crontab.py 2026-11-01 02:25:23 +08:00
21c4f93e02 Update crontab.py 2026-11-01 02:18:09 +08:00
c36a03bfb3 Update index.py 2026-11-01 02:12:49 +08:00
a71927917c Update index.py 2026-11-01 02:06:55 +08:00
2f5d5835c5 Update config.inc.php 2026-11-01 01:46:11 +08:00
e95b42df77 Update __init__.py 2026-11-01 01:41:09 +08:00
5c6dbbbb0c Update index.py 2026-11-01 01:27:59 +08:00
a151516eab Update index.py 2026-11-01 01:16:10 +08:00
3a590c7feb Update index.py 2026-11-01 01:12:08 +08:00
e9f0e1962e update 2026-11-01 01:10:39 +08:00
c4fda1362d Update mw.py 2026-11-01 01:05:35 +08:00
f31343b2a5 Update index.py 2026-11-01 01:00:10 +08:00
90b414d373 Update index.py 2026-11-01 00:55:03 +08:00
3eab70db4c Update index.py 2026-11-01 00:46:11 +08:00
e0810bb8d6 Update index.py 2026-11-01 00:45:15 +08:00
96a32d5c8f 更加公用 2026-11-01 00:44:10 +08:00
d45cfb5fe8 Update crontab.js 2026-11-01 00:29:32 +08:00
08753ae96d mysql支持表备份 2026-11-01 00:27:45 +08:00
465e55848f Update crontab.py 2026-10-31 23:51:28 +08:00
4492a97155 Update crontab.js 2026-10-31 23:41:38 +08:00
ba46d568bf Update crontab.js 2026-10-31 22:55:35 +08:00
d87d5d5349 Update crontab.js 2026-10-31 18:54:29 +08:00
76ea3e3375 update 2026-10-31 18:54:26 +08:00
ef47145135 Update crontab.js 2026-10-31 18:12:30 +08:00
43a9ee7368 Update crontab.py 2026-10-31 18:12:24 +08:00
6646e0c46c Update crontab.py 2026-10-31 18:01:10 +08:00
535dbb2e37 Update __init__.py 2026-10-31 18:01:03 +08:00
035953c7f5 Update install.sh 2026-10-31 18:00:28 +08:00
6a9ce81d46 update 2026-10-31 17:16:19 +08:00
f2a6824632 Update ssh_terminal.py 2026-10-31 11:57:54 +08:00
594976373e Update requirements.txt 2026-10-31 11:54:09 +08:00
45704f1c31 update 2026-10-30 17:07:22 +08:00
ce57885343 Create rapira85.toml 2026-10-30 16:55:33 +08:00
4d143ef959 Update crontab.js 2026-10-30 10:47:18 +08:00
9a0f9a759c Update install.sh 2026-10-30 10:10:34 +08:00
6341f00f46 update 2026-10-30 10:09:58 +08:00
f517568251 Update crontab.js 2026-10-29 21:02:44 +08:00
1ff6d0c2cb Update crontab.js 2026-10-29 19:17:44 +08:00
5e28039573 update 2026-10-29 18:36:48 +08:00
Mr Chen
d7757bee0d Merge pull request #949 from midoks/dev
update
2026-10-29 12:01:57 +08:00
6b18511708 Update install.sh 2026-10-29 12:00:41 +08:00
4a3e0791d3 update 2026-10-29 11:52:00 +08:00
7c25d3f6c3 Update install.sh 2026-10-29 11:41:54 +08:00
8ef38674d7 Update install.sh 2026-10-29 11:24:40 +08:00
e84cbf1d76 Update install.sh 2026-10-29 11:24:24 +08:00
14f622d252 Update install.sh 2026-10-29 11:16:08 +08:00
8bb2bfacdc Update install.sh 2026-10-29 11:13:52 +08:00
191c4b1331 Update install.sh 2026-10-29 11:11:41 +08:00
7bed2b977e update 2026-10-29 11:11:28 +08:00
b6c09b2b37 update 2026-10-29 11:03:15 +08:00
Mr Chen
1bd5251dc0 Merge pull request #948 from midoks/dev
更新优化
2026-10-28 10:40:32 +08:00
ecf1b6b600 Update install.sh 2026-10-27 23:03:09 +08:00
22cca82967 Update install.sh 2026-10-27 23:02:43 +08:00
cd66e42b1a Update install.sh 2026-10-27 23:00:26 +08:00
d887fa1b50 Update install.sh 2026-10-27 22:59:57 +08:00
55870ca08a Update my9.7.cnf 2026-10-27 22:51:21 +08:00
2ce1d49386 Update install_generic.sh 2026-10-27 22:47:35 +08:00
a0226ccbcd Update install_generic.sh 2026-10-27 22:47:02 +08:00
de7c14ec62 Update index.py 2026-10-27 22:42:03 +08:00
0c2cfd6d9a Update index.py 2026-10-27 22:41:21 +08:00
4ca78b9a91 Update my26.10.cnf 2026-10-27 22:37:56 +08:00
8219c2d2ed Update install_generic.sh 2026-10-27 22:31:47 +08:00
9f22ce949c Update install_generic.sh 2026-10-27 22:28:29 +08:00
d76c21c54b Update install_generic.sh 2026-10-27 22:28:12 +08:00
30c5cee81a update 2026-10-27 22:24:42 +08:00
e2d0ac6d89 update 2026-10-27 22:11:37 +08:00
3578a65d6e Update my9.7.cnf 2026-10-27 22:04:14 +08:00
c8331b800b update 2026-10-27 21:58:20 +08:00
1e7dc18c21 update 2026-10-27 21:46:06 +08:00
046da1868e Update install_generic.sh 2026-10-27 21:38:37 +08:00
ef7068ebd2 Update install_generic.sh 2026-10-27 21:37:47 +08:00
0525667032 Update install_generic.sh 2026-10-27 21:34:15 +08:00
6198ca02da Update install_generic.sh 2026-10-27 21:32:05 +08:00
4d4fd90fc6 Update install.sh 2026-10-27 21:29:58 +08:00
acfc4d710b Update install.sh 2026-10-27 21:29:43 +08:00
4fd12f4d73 update 2026-10-27 21:23:42 +08:00
9a8bb9f94b update 2026-10-27 21:22:30 +08:00
170f758bc9 Update install.sh 2026-10-27 21:19:34 +08:00
8b7d563fac update 2026-10-27 21:18:03 +08:00
6f9e0cdd8f update 2026-10-27 21:16:58 +08:00
0a3af7a0c0 Create install_generic.sh 2026-10-27 21:16:25 +08:00
c90a2facac update 2026-10-27 21:15:35 +08:00
92d56bddab update 2026-10-27 21:07:39 +08:00
a3bab2da47 Update install.sh 2026-10-27 21:02:19 +08:00
d51a3ac1f7 Update info.json 2026-10-27 20:45:25 +08:00
04774bddc3 update 2026-10-27 20:45:00 +08:00
770f1532da update 2026-10-27 17:47:37 +08:00
d09872c2f3 update 2026-10-27 17:30:36 +08:00
e77369cd25 Update install.sh 2026-10-27 17:12:00 +08:00
69897a208c update 2026-10-27 17:10:57 +08:00
1f5c5ac66e update 2026-10-27 17:08:36 +08:00
3a7f8f09cb Update opcache.sh 2026-10-26 13:13:39 +08:00
77d2b9e323 update 2026-10-26 13:11:27 +08:00
d56c271cc4 update 2026-10-26 04:16:03 +08:00
b4aecf5d0c update 2026-10-26 04:15:29 +08:00
e55e23c845 Update rapira.js 2026-10-26 04:05:37 +08:00
e2977dbbc4 Update mcrypt.sh 2026-10-26 04:04:34 +08:00
8ad94ffeff Update install.sh 2026-10-26 04:02:58 +08:00
c94ff04dcf update 2026-10-26 04:00:20 +08:00
65f10ca22f Update sodium.sh 2026-10-26 03:53:59 +08:00
a1127b3bc0 Update sodium.sh 2026-10-26 03:52:48 +08:00
81c16d1a3d update 2026-10-26 03:47:17 +08:00
b1b4c82457 Update rapira.toml 2026-10-26 03:46:09 +08:00
515b22b103 update 2026-10-26 03:45:19 +08:00
c200165057 update 2026-10-26 03:24:02 +08:00
64c30893d5 update 2026-10-26 03:09:50 +08:00
98b8dce5fd up 2026-10-26 03:06:09 +08:00
0d9b7b6edf Update gd_old.sh 2026-10-26 02:59:15 +08:00
b72bb1fa87 update 2026-10-26 02:58:58 +08:00
d85131266c update 2026-10-26 02:56:59 +08:00
22da275f5b up 2026-10-26 02:51:34 +08:00
f6d65b9e33 update 2026-10-26 02:49:41 +08:00
ebc07becd0 update 2026-10-26 02:48:03 +08:00
024f2c2369 update 2026-10-26 02:45:33 +08:00
2b93fb684b update 2026-10-26 02:43:27 +08:00
b2daf6bf65 update 2026-10-26 02:37:33 +08:00
3ee0f553e9 update 2026-10-26 02:26:03 +08:00
f206da8278 Update apcu.sh 2026-10-26 02:07:49 +08:00
edbaeb37f5 update 2026-10-26 02:07:42 +08:00
46847833d0 update 2026-10-26 01:57:13 +08:00
4303a62b1b update 2026-10-26 01:12:09 +08:00
d6d5babf81 Update dispatcher.toml 2026-10-26 00:46:27 +08:00
8e5b10bda3 Update worker.toml 2026-10-26 00:45:45 +08:00
8e54ee987c Update index.py 2026-10-26 00:42:09 +08:00
929b30ce73 update 2026-10-26 00:38:38 +08:00
c085fa7066 update 2026-10-26 00:30:21 +08:00
783e71f189 update 2026-10-26 00:18:37 +08:00
ae1ffd313c Update doh.conf 2026-10-25 22:46:56 +08:00
122c0b5f64 Update doh.conf 2026-10-25 12:53:13 +08:00
21e496f22e Update doh.conf 2026-10-25 12:52:25 +08:00
d92b3039e2 Update doh.conf 2026-10-25 12:49:37 +08:00
ea57812191 Update info.json 2026-10-25 12:46:02 +08:00
d72238df45 update 2026-10-25 12:45:22 +08:00
55aab8d86d Update install.sh 2026-10-25 12:34:49 +08:00
f8d4d9e4cf update 2026-10-25 12:32:30 +08:00
90afa6446c Update install.sh 2026-10-25 09:58:41 +08:00
5e468c548a Update install.sh 2026-10-25 09:58:16 +08:00
48f4521ef6 Update install.sh 2026-10-25 09:55:12 +08:00
ccd48cecfb update 2026-10-25 09:52:31 +08:00
0757638b2e Update install.sh 2026-10-25 09:46:55 +08:00
68cb547d5f update 2026-10-25 08:13:29 +08:00
1f7c494d82 Update install.sh 2026-10-24 14:58:04 +08:00
Mr Chen
8e58783964 Merge pull request #947 from midoks/dev
redis在线更新支持
2026-10-24 14:14:35 +08:00
bfdc0639b6 update 2026-10-24 14:12:33 +08:00
337a7d87e4 Update install.sh 2026-10-24 14:08:47 +08:00
38c062220c redis 在线升级支持 2026-10-24 14:01:26 +08:00
f639acec86 Merge branch 'master' into dev 2026-10-24 12:54:12 +08:00
02ba38a01a Update install.sh 2026-10-24 12:30:18 +08:00
ea8487b14c up 2026-10-24 12:27:40 +08:00
Mr Chen
f0b613865b Merge pull request #946 from midoks/dev
0.19.0
2026-10-24 10:37:42 +08:00
b142f37045 Update install.sh 2026-10-24 02:04:36 +08:00
45eeb3c045 update 2026-10-24 02:03:38 +08:00
ab99d972cd update 2026-10-24 01:44:03 +08:00
08562a12a2 Update install.sh 2026-10-24 01:37:52 +08:00
d7e62bbfa1 update 2026-10-24 01:36:21 +08:00
5829c48995 update 2026-10-24 01:33:12 +08:00
cd133fc278 update 2026-10-24 01:24:21 +08:00
8a2a4d1a84 update 2026-10-24 01:03:12 +08:00
Mr Chen
a225b98432 Merge pull request #945 from midoks/dev
优化
2026-10-24 01:01:25 +08:00
1acd50b3f3 Update install.sh 2026-10-24 00:59:41 +08:00
5279fe0ba7 Update soft.js 2026-10-24 00:56:26 +08:00
a73f7d86a9 Update version.py 2026-10-24 00:47:15 +08:00
5fe7e4b43d update 2026-10-24 00:43:18 +08:00
d50d666fb2 Update install.sh 2026-10-24 00:42:30 +08:00
86229586f1 update 2026-10-24 00:42:06 +08:00
2947dea3dd Merge branch 'master' into dev 2026-10-24 00:38:28 +08:00
264534ff2c update 2026-10-24 00:38:16 +08:00
82655592d7 Update index.py 2026-10-24 00:35:57 +08:00
Mr Chen
85f90e8ce6 Merge pull request #944 from midoks/dev
优化
2026-10-24 00:29:19 +08:00
450ae37f05 Update index.py 2026-10-24 00:22:55 +08:00
07d0eff75b update 2026-10-24 00:16:33 +08:00
8697bea0d3 Update info.json 2026-10-23 23:59:14 +08:00
a06839fe20 Update info.json 2026-10-23 23:55:31 +08:00
6542113a21 Merge branch 'master' into dev 2026-10-23 23:53:11 +08:00
63d04b8c75 update 2026-10-23 23:50:05 +08:00
71b409a970 update 2026-10-23 23:48:31 +08:00
e0bcc720cc Update soft.html 2026-10-23 23:44:27 +08:00
8bcabd055b update 2026-10-23 23:38:02 +08:00
94597476ac update 2026-10-23 23:33:27 +08:00
a5172d4b5a update 2026-10-23 23:10:50 +08:00
ee79ea55db update 2026-10-23 23:04:31 +08:00
2230c2b632 update 2026-10-23 22:48:12 +08:00
9b231554ef update 2026-10-23 22:43:49 +08:00
ccc499359b Update fcgi_client.py 2026-10-23 22:38:02 +08:00
c5ba0dd8a2 openresty 支持在线升级 2026-10-23 22:31:44 +08:00
3811979f7e update 2026-10-23 22:14:26 +08:00
fb17b7e3a1 update 2026-10-23 22:08:10 +08:00
6ea79b8b28 支持插件更新功能 2026-10-23 22:03:48 +08:00
037e360e3d Update install.sh 2026-10-23 21:49:47 +08:00
3e4a995d5a Update info.json 2026-10-23 21:42:51 +08:00
9d7056184a Update public.js 2026-10-23 21:40:37 +08:00
8aad54b2eb Update index.py 2026-10-23 21:37:41 +08:00
9639dc0e19 Merge branch 'master' into dev 2026-10-23 19:45:14 +08:00
Mr Chen
1f816c4c09 Merge pull request #943 from midoks/dev
简单优化
2026-10-23 19:44:27 +08:00
d88c3d812e Create e.cfg 2026-10-23 19:40:00 +08:00
de3f060e8b Update requirements.txt 2026-10-23 19:32:50 +08:00
2c740726e2 Update lib.sh 2026-10-23 19:31:53 +08:00
01fcadf7c9 update 2026-10-23 19:30:25 +08:00
21378014c4 Update lib.sh 2026-10-23 19:29:50 +08:00
765e3d7d1a Update lib.sh 2026-10-23 19:29:11 +08:00
2bd77e5830 update 2026-10-23 19:20:46 +08:00
b5c61af33c Update plugin.py 2026-10-23 18:13:14 +08:00
ac7df862c1 Update info.json 2026-10-23 14:12:40 +08:00
ae30e8c740 update 2026-10-23 13:29:04 +08:00
db4cd40e35 Update sql_mysql.py 2026-10-23 13:19:34 +08:00
592cdc3e17 Update soft.html 2026-10-23 12:09:24 +08:00
Mr Chen
9a84276abf Merge pull request #942 from midoks/dev
优化
2026-10-22 16:52:22 +08:00
1c70d6381b Merge branch 'master' into dev 2026-10-22 16:51:48 +08:00
556da39be8 Update install.sh 2026-10-22 15:53:22 +08:00
59c8d02c7d Update install.sh 2026-10-22 15:52:03 +08:00
3b0b53d1b5 update 2026-10-22 15:44:47 +08:00
996cbfb279 Update install.sh 2026-10-22 15:37:43 +08:00
e47ad14cb1 Update install.sh 2026-10-22 15:36:50 +08:00
8921647180 update 2026-10-22 15:35:12 +08:00
Mr Chen
2d7933e715 Merge pull request #941 from midoks/dev
局部优化
2026-10-22 14:15:00 +08:00
cffe463779 update 2026-10-22 14:00:45 +08:00
2a0e7c090d Update install.sh 2026-10-22 13:47:58 +08:00
eab8ed9551 Update install.sh 2026-10-22 13:46:50 +08:00
Mr Chen
e9c3b5d135 Merge pull request #940 from midoks/dev
php 支持手动升级
2026-10-22 12:38:02 +08:00
59076d4750 update 2026-10-22 12:36:43 +08:00
8aa84d22a8 Update install.sh 2026-10-22 12:28:35 +08:00
cfb26034b1 Update install.sh 2026-10-22 12:27:30 +08:00
953980ee47 Update install.sh 2026-10-22 12:26:27 +08:00
994198517a Update install.sh 2026-10-22 12:26:07 +08:00
98728b2eb8 Update install.sh 2026-10-22 12:23:49 +08:00
6498606e69 update 2026-10-22 12:23:29 +08:00
Mr Chen
d17ba4d785 Merge pull request #939 from midoks/dev
php升级
2026-10-22 12:00:07 +08:00
e4eeed3559 update 2026-10-22 11:59:23 +08:00
b100204b37 Update rapira.toml 2026-10-18 11:01:26 +08:00
82ff3e3d0a Update rapira.js 2026-10-17 14:38:47 +08:00
0b2223bce0 Update rapira.js 2026-10-17 14:35:50 +08:00
a43b723b09 Update rapira.js 2026-10-17 14:34:17 +08:00
96551f49ca Update rapira.js 2026-10-17 14:32:51 +08:00
8e32d37985 Update rapira.toml 2026-10-17 14:21:49 +08:00
d1da238ddc update 2026-10-17 14:07:59 +08:00
7260a2be21 Create rapira.conf 2026-10-17 14:02:10 +08:00
7562d50e58 Update phpinfo.conf 2026-10-17 13:29:05 +08:00
e77ae8763b Update index.py 2026-10-17 13:28:22 +08:00
a0e51c75fe Update index.py 2026-10-17 13:22:00 +08:00
6021a5e6e2 Update enable-rapira.conf 2026-10-17 13:12:48 +08:00
e50e222955 Update index.py 2026-10-17 13:07:00 +08:00
531dd665c9 update 2026-10-17 13:02:17 +08:00
a79c0a1a9b update 2026-10-17 11:41:47 +08:00
9ef144c304 Update rapira.toml 2026-10-16 12:58:36 +08:00
5402af8df7 Update index.py 2026-10-16 12:38:11 +08:00
99802125dc Update index.py 2026-10-16 12:37:51 +08:00
705647cd3b Update rapira.toml 2026-10-16 11:54:05 +08:00
0ea2eeab7f Update rapira.toml 2026-10-16 11:53:31 +08:00
727cde1352 Update rapira.toml 2026-10-16 11:53:11 +08:00
6ef6358cbb update 2026-10-16 11:44:30 +08:00
6acb303ac9 update 2026-10-16 11:32:27 +08:00
a80e5492b8 Update index.html 2026-10-16 11:24:05 +08:00
4358b1a520 update 2026-10-16 11:11:00 +08:00
ad1a7c22a6 Update index.py 2026-10-16 11:01:33 +08:00
2f3af23e6d Update index.html 2026-10-15 16:23:17 +08:00
89a26d294d Update public.js 2026-10-15 15:43:36 +08:00
f83faeacac update 2026-10-15 15:42:08 +08:00
fb7c27c205 Update index.py 2026-10-15 15:37:08 +08:00
3f958c7083 Update index.html 2026-10-15 15:33:09 +08:00
60b6689318 Update index.py 2026-10-15 15:32:29 +08:00
ba94e81367 update 2026-10-15 15:05:36 +08:00
89c8c68b88 Update requirements.txt 2026-10-15 15:00:58 +08:00
e78ae7e4de Update requirements.txt 2026-10-15 15:00:32 +08:00
f87cadd3ce Update index.html 2026-10-15 14:59:44 +08:00
1631e149ea Update index.py 2026-10-15 14:58:02 +08:00
d84f585bff Update index.py 2026-10-15 14:52:00 +08:00
7e9091b341 update 2026-10-15 14:51:02 +08:00
7020d3e198 Update install.sh 2026-10-15 14:39:55 +08:00
9d8e0ded8f Update install.sh 2026-10-15 14:25:05 +08:00
090e8fa160 Create rapira.source.toml 2026-10-15 14:20:21 +08:00
83746675e7 Update install.sh 2026-10-15 14:19:57 +08:00
74d73d76cd Update index_php.py 2026-10-13 13:03:48 +08:00
6bfedde66d Update install.sh 2026-10-13 13:02:00 +08:00
554bee4040 Update install.sh 2026-10-13 13:01:27 +08:00
a1005adf04 Update install.sh 2026-10-13 11:43:52 +08:00
cbed47d825 update 2026-10-13 10:55:20 +08:00
abb7da896b Update index.py 2026-10-11 15:39:00 +08:00
e62a69ac45 update 2026-10-11 15:31:57 +08:00
769285736b update 2026-10-11 15:29:04 +08:00
8d2eaa94bd Update index.html 2026-10-11 15:07:48 +08:00
a31143e0e8 Update install.sh 2026-10-11 15:05:22 +08:00
584551f764 update 2026-10-11 15:04:11 +08:00
8b60a65bbd Update index.py 2026-10-11 14:52:34 +08:00
c13df7c25b Update index.py 2026-10-11 14:52:08 +08:00
ad30ba776c Update index.py 2026-10-11 14:51:43 +08:00
de3451993f Update install.sh 2026-10-11 14:45:56 +08:00
fde9b49f39 Update rapira.service.tpl 2026-10-11 14:39:51 +08:00
cff0e9442c Update install.sh 2026-10-11 14:34:11 +08:00
5cb57d89de Update install.sh 2026-10-11 14:29:32 +08:00
fadcbaa1bb Update install.sh 2026-10-11 14:29:01 +08:00
911554f6df Update install.sh 2026-10-11 14:27:46 +08:00
77b525d955 Update install.sh 2026-10-11 14:19:44 +08:00
b872a2bb53 Update install.sh 2026-10-11 14:19:29 +08:00
818444d4f4 Update install.sh 2026-10-11 14:17:47 +08:00
63e16e05aa Update install.sh 2026-10-11 13:56:53 +08:00
06743894a3 Update install.sh 2026-10-11 12:48:56 +08:00
2d665235c8 update 2026-10-11 12:43:17 +08:00
72311a2801 update 2026-10-09 12:42:45 +08:00
d7ba290ed3 up 2026-10-09 11:08:59 +08:00
e0d2984bae Update install.sh 2026-10-09 10:51:30 +08:00
ecdbe8d014 Update install.sh 2026-10-09 10:40:39 +08:00
7d57e320b8 Update install.sh 2026-10-09 10:40:27 +08:00
cf16b729f6 Create install.sh 2026-10-09 10:01:12 +08:00
366c5c91aa Update install.sh 2026-10-09 09:37:39 +08:00
173cf2985e Update install.sh 2026-10-09 09:17:39 +08:00
0bdba73f25 Update install.sh 2026-10-09 09:14:55 +08:00
24d25e69ad Update install.sh 2026-10-09 09:09:41 +08:00
d3e6297503 Update site.css 2026-10-08 21:30:53 +08:00
76b5f15115 update 2026-10-08 19:17:46 +08:00
cfa92b637a update 2026-10-08 18:52:56 +08:00
f07e75e508 init rapira 2026-10-08 18:42:21 +08:00
4220300731 Update site.css 2026-09-22 19:11:55 +08:00
Mr Chen
43b464866f Merge pull request #938 from midoks/dev
HDD和SSD磁盘识别
2026-09-22 16:31:43 +08:00
7bf5dbb4f3 Update site.css 2026-09-22 16:13:41 +08:00
9fe8453898 Update index.js 2026-09-22 16:05:43 +08:00
b421cf261f Update index.js 2026-09-22 16:02:45 +08:00
75d28763ee Update index.js 2026-09-22 15:58:28 +08:00
25533fa8bc Update main.py 2026-09-22 15:34:24 +08:00
04294e6cbe Update main.py 2026-09-22 15:28:38 +08:00
f0550ba6b3 Update main.py 2026-09-22 15:21:43 +08:00
88d0733d95 Update install.sh 2026-09-13 13:17:11 +08:00
74633e155a update 2026-09-13 12:59:14 +08:00
7d8d7a8c6f Create openssl_40.sh 2026-09-13 10:32:35 +08:00
Mr Chen
32956578b2 Merge pull request #937 from midoks/dev
bash符合标准
2026-09-11 22:52:09 +08:00
4efdf7606c update 2026-09-11 22:48:34 +08:00
a61644861b update 2026-09-11 22:39:42 +08:00
e60570e380 update 2026-09-11 22:25:42 +08:00
ad160cb23e update 2026-09-11 22:10:30 +08:00
73f58ced9a update 2026-09-11 21:57:55 +08:00
36ca82c1b4 update 2026-09-11 21:52:24 +08:00
acd46f4724 update 2026-09-11 21:28:59 +08:00
370ff99134 update 2026-09-11 21:10:03 +08:00
aa317ee2f5 update 2026-09-11 20:47:27 +08:00
44600b5657 update 2026-09-11 20:42:39 +08:00
ea45316a32 update 2026-09-11 20:32:22 +08:00
6cd13022f1 Update install.sh 2026-09-11 20:31:05 +08:00
91ff2f7550 update 2026-09-11 20:30:55 +08:00
483b5b090d Update install.sh 2026-09-11 20:18:46 +08:00
6087931c58 Update install.sh 2026-09-11 20:18:28 +08:00
9014fd8911 Update install.sh 2026-09-11 20:18:07 +08:00
76f7f51d80 Update install.sh 2026-09-11 20:15:43 +08:00
0c4902e01e Update install.sh 2026-09-11 20:13:34 +08:00
175fb089cd Update install.sh 2026-09-11 20:13:11 +08:00
7b8a4a38b3 Update install.sh 2026-09-11 20:12:33 +08:00
ebf920ed12 Update install.sh 2026-09-11 20:08:55 +08:00
bb8591f5e5 update 2026-09-11 20:06:25 +08:00
b8573e1f1f Update plugin.py 2026-09-11 20:04:59 +08:00
dacc1e5ad8 update 2026-09-11 20:00:47 +08:00
8cc64e32dd update 2026-09-11 19:55:44 +08:00
1d294cc3b1 Update index.py 2026-09-11 19:51:42 +08:00
f9da2e4391 update 2026-09-11 19:46:15 +08:00
3b78079cd2 Update install.sh 2026-09-11 19:35:40 +08:00
07a0a1be48 Update install.sh 2026-09-11 19:31:44 +08:00
837f95e571 Merge branch 'master' into dev 2026-09-09 01:45:29 +08:00
Mr Chen
909d818caa Merge pull request #936 from ramondelee/patch-2
Update freetype_new.sh
2026-09-09 01:44:12 +08:00
ramondelee
355ceebbd7 Update freetype_new.sh
修复freetype下载失败问题
2026-09-08 21:12:36 +08:00
6ae1370709 Merge branch 'master' into dev 2026-09-08 12:02:31 +08:00
Mr Chen
93b5d8b8b4 Merge pull request #935 from ramondelee/patch-1
Update freetype_old.sh
2026-09-08 12:02:10 +08:00
ramondelee
be461a15a9 Update freetype_old.sh
修复freetype下载失败问题
2026-09-07 22:23:11 +08:00
c239f35382 Update firewall.py 2026-09-02 08:25:34 +08:00
49d57af719 Update linux.conf 2026-08-27 13:36:19 +08:00
Mr Chen
19fc0fdc51 Merge pull request #934 from midoks/dev
常规更新
2026-08-26 18:16:57 +08:00
c1fd4fa24c Update __init__.py 2026-08-26 18:15:43 +08:00
7239b22759 update 2026-08-16 00:14:39 +08:00
f5fa94ae95 Update update.sh 2026-08-08 10:09:28 +08:00
Mr Chen
b679ea035d Merge pull request #933 from midoks/dev
常规优化
2026-07-22 13:05:42 +08:00
49bbca8faa Update index.py 2026-07-22 13:03:46 +08:00
8b86cd5e63 up 2026-07-22 13:00:43 +08:00
698e3ffd81 update 2026-07-22 12:55:33 +08:00
Mr Chen
c2284dcee5 Merge pull request #932 from midoks/dev
兼容Ubuntu 26.04 LTS
2026-07-21 20:43:06 +08:00
b68c9edc3e Update index.py 2026-07-21 20:37:12 +08:00
650365997a Update index.py 2026-07-21 20:36:34 +08:00
3279404595 Update info.json 2026-07-21 20:35:41 +08:00
d32a94dccf Update install.sh 2026-07-21 20:34:44 +08:00
80d846f247 Update install.sh 2026-07-21 20:31:08 +08:00
eadcbe336d Update install.sh 2026-07-21 20:26:57 +08:00
474d0f075f Update install.sh 2026-07-21 20:26:33 +08:00
2d6a41e19f Update install.sh 2026-07-21 12:03:36 +08:00
1f24944417 Update caddy.service.tpl 2026-07-21 11:51:42 +08:00
4ab3409e54 Update index.py 2026-07-21 11:43:14 +08:00
c3ad146303 update 2026-07-21 11:38:30 +08:00
745cd304fb Update install.sh 2026-07-21 00:33:05 +08:00
e6efefd1fd Update install.sh 2026-07-21 00:11:57 +08:00
1350404c58 Update install.sh 2026-07-21 00:10:03 +08:00
9cdd2274fa Update install.sh 2026-07-21 00:08:53 +08:00
cc204ad721 Update install.sh 2026-07-21 00:00:26 +08:00
8eb1614b31 Update install.sh 2026-07-20 23:50:41 +08:00
9c2e9627ec update 2026-07-20 23:48:18 +08:00
87123c526a update 2026-07-20 23:45:15 +08:00
7c3ebc6e35 Update ubuntu.sh 2026-07-20 23:42:08 +08:00
6c5bf63424 Update ubuntu.sh 2026-07-20 23:38:00 +08:00
13fd47e7d4 Update ubuntu.sh 2026-07-20 23:36:38 +08:00
fc1321584a Update ubuntu.sh 2026-07-20 23:36:25 +08:00
bab3ae16d3 Update ubuntu.sh 2026-07-20 23:33:35 +08:00
ab8498e519 Update ubuntu.sh 2026-07-20 23:33:13 +08:00
0e480c7ad8 update 2026-07-20 23:29:01 +08:00
7ed8558ff0 Update ubuntu.sh 2026-07-20 23:22:35 +08:00
4ed2f0caa9 update 2026-07-20 23:19:31 +08:00
f275eabe1b Update file.py 2026-07-20 23:08:01 +08:00
fe13ab1e5f Update file.py 2026-07-20 23:07:46 +08:00
6ed045cf94 update 2026-07-20 22:41:10 +08:00
ef333ff142 update 2026-07-20 22:23:37 +08:00
dac2f5240f Update install.sh 2026-07-20 22:18:45 +08:00
cebfc2fc91 update 2026-07-20 22:17:22 +08:00
1da865c1b2 Update install.sh 2026-07-20 16:46:29 +08:00
2abdaaa7ce Update install.sh 2026-07-20 16:45:08 +08:00
c62142cf6b Update requirements.txt 2026-07-20 16:04:57 +08:00
7c1820b6cd update 2026-07-20 15:59:27 +08:00
a24af95d24 Update install.sh 2026-07-20 15:39:32 +08:00
1326c282c8 Update requirements.txt 2026-07-20 15:33:13 +08:00
b7e84749f1 Update debian.sh 2026-07-20 15:26:10 +08:00
8a65158540 Update db.py 2026-07-20 15:21:46 +08:00
a576c521a2 Update ubuntu.sh 2026-07-20 15:17:24 +08:00
736a387a71 Update ubuntu.sh 2026-07-20 15:15:23 +08:00
090205c372 update 2026-07-20 13:41:03 +08:00
fda0bddc8f Update db.py 2026-07-20 13:26:23 +08:00
292b18468d Update db.py 2026-07-20 13:24:57 +08:00
47aab245fc Update panel_task.py 2026-07-20 12:42:24 +08:00
39bd601825 Update mw.py 2026-07-20 12:32:39 +08:00
b744adeb13 Update monitor.py 2026-07-20 11:46:30 +08:00
7b70f9fc99 Merge branch 'master' into dev 2026-07-19 22:06:00 +08:00
Mr Chen
0723f751b3 Merge pull request #930 from midoks/dependabot/pip/python-engineio-4.13.2
Bump python-engineio from 4.3.2 to 4.13.2
2026-07-19 22:05:47 +08:00
1fd8617a12 Update push_notice_msg.py 2026-07-17 23:21:19 +08:00
dependabot[bot]
2fec8fcef4 Bump python-engineio from 4.3.2 to 4.13.2
Bumps [python-engineio](https://github.com/miguelgrinberg/python-engineio) from 4.3.2 to 4.13.2.
- [Release notes](https://github.com/miguelgrinberg/python-engineio/releases)
- [Changelog](https://github.com/miguelgrinberg/python-engineio/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/python-engineio/compare/v4.3.2...v4.13.2)

---
updated-dependencies:
- dependency-name: python-engineio
  dependency-version: 4.13.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-14 21:18:01 +00:00
Mr Chen
51a48afa71 Merge pull request #929 from ccbkkb/patch-1
Fix return statement for unban IP function
2026-07-13 13:12:38 +08:00
ccbkkb
76919faca7 Fix return statement for unban IP function 2026-07-13 10:50:19 +08:00
Mr Chen
9bcbeaf1a5 Merge pull request #928 from midoks/dev
常规更新
2026-07-09 17:11:23 +08:00
d0de121721 Update update.sh 2026-07-09 15:14:16 +08:00
957e2db3d0 Update update.sh 2026-07-09 15:06:33 +08:00
fb0be5549d Update update.sh 2026-07-09 15:04:40 +08:00
8a9132d557 Update update.sh 2026-07-09 14:52:08 +08:00
04d10435c2 Update update.sh 2026-07-09 14:51:29 +08:00
92543e10fa Update update.sh 2026-07-09 14:46:38 +08:00
cd427dcbf3 Update update.sh 2026-07-09 14:46:26 +08:00
Mr Chen
ddb5e0285b Merge pull request #927 from midoks/dev
常规更新
2026-07-09 14:24:08 +08:00
75610a4559 Update crontab.js 2026-07-09 14:22:26 +08:00
b8f7a45f61 Update push_notice_msg.py 2026-07-09 12:58:16 +08:00
Mr Chen
37d5ce719e Merge pull request #926 from midoks/dev
常规更新
2026-07-08 16:47:46 +08:00
ef9053aa7e Update webstats_index.py 2026-07-08 16:47:05 +08:00
018fcb7afb Update index.py 2026-07-08 16:46:45 +08:00
5cc9a67152 Update mw.py 2026-07-07 23:54:17 +08:00
54895f1d0a Update mw.py 2026-07-07 23:38:29 +08:00
91dfecf882 up 2026-07-07 23:36:34 +08:00
2f09e227d1 Update tool_migrate.py 2026-07-07 23:12:23 +08:00
5d0463836e Update mw.py 2026-07-07 23:11:02 +08:00
Mr Chen
fb6499cb35 Merge pull request #925 from midoks/dev
常规更新
2026-07-07 02:35:02 +08:00
0bbfb58e67 Update index.py 2026-07-07 02:32:34 +08:00
Mr Chen
fcd780a7d3 Merge pull request #924 from midoks/dev
常规更新
2026-07-07 02:19:41 +08:00
4f4d1e7580 Update webstats_common.lua 2026-07-07 02:15:57 +08:00
6e2a8e0a12 up 2026-07-07 02:12:09 +08:00
817b4b36c7 Update webstats.conf 2026-07-07 02:06:03 +08:00
Mr Chen
0ba89cbb9e Merge pull request #923 from midoks/dev
常规更新
2026-07-06 21:13:07 +08:00
4e3e7864be Update tool_migrate.py 2026-07-06 21:02:13 +08:00
6f51eaa298 update 2026-07-06 20:59:32 +08:00
39bd87e868 Update tool_migrate.py 2026-07-06 20:54:00 +08:00
18443aab60 Update tool_migrate.py 2026-07-06 20:49:20 +08:00
b88ea7aa3c update 2026-07-06 20:32:36 +08:00
6a6f6e6062 Update tool_migrate.py 2026-07-06 20:27:17 +08:00
5839dbcd6b Update tool_migrate.py 2026-07-06 20:05:10 +08:00
b46f45569e Update tool_migrate.py 2026-07-06 20:01:23 +08:00
5cdc5af8cd Update tool_migrate.py 2026-07-06 19:50:13 +08:00
4f38a9f3ff Update tool_migrate.py 2026-07-06 19:49:58 +08:00
9c83695187 Create tool_migrate.py 2026-07-06 19:44:14 +08:00
f9be534101 update 2026-07-06 19:24:36 +08:00
58ab48ac15 Update webstats_common.lua 2026-07-06 19:11:48 +08:00
f34e93192d Update webstats_common.lua 2026-07-06 19:10:17 +08:00
31106f2b13 Update webstats_common.lua 2026-07-06 19:03:27 +08:00
468cc54cf5 Update webstats_common.lua 2026-07-06 18:55:25 +08:00
728a38c55c Update webstats_log.lua 2026-07-06 18:35:05 +08:00
Mr Chen
b2b23b0e3b Merge pull request #922 from midoks/dev
常规更新
2026-07-05 15:51:08 +08:00
167dd11548 Update webstats_log.lua 2026-07-05 15:47:23 +08:00
03fdbf2604 Merge branch 'master' into dev 2026-07-05 15:43:18 +08:00
edbdec8370 Update init.sql 2026-07-05 15:42:44 +08:00
8f1c9f9471 up 2026-07-05 15:38:54 +08:00
d35d16943d up 2026-07-05 15:34:56 +08:00
3ac4270dee Update stats.js 2026-07-05 15:30:16 +08:00
90777e08ff update 2026-07-05 15:28:56 +08:00
b47d1262ac Update push_notice_msg.py 2026-07-05 15:11:57 +08:00
e28081a7c5 Update stats.js 2026-07-05 15:04:05 +08:00
5f7d6c1488 Create webstats_common.lua.bk1.txt 2026-07-05 14:46:32 +08:00
59385e11be Merge branch 'master' into dev 2026-07-05 14:21:28 +08:00
Mr Chen
a668d88791 Merge pull request #921 from midoks/dev
常规更新
2026-07-05 14:13:11 +08:00
e62bd7c5a6 Update webstats_log.lua 2026-07-05 14:07:31 +08:00
1ad3d2f187 Update webstats_log.lua 2026-07-05 13:41:19 +08:00
bf06af14ed Update webstats_log.lua 2026-07-05 13:24:37 +08:00
Mr Chen
805c96f260 Merge pull request #920 from midoks/dev
常规更新
2026-07-05 12:33:28 +08:00
8ccba2f6d5 Update webstats_log.lua 2026-07-05 04:08:00 +08:00
2e9f01d3ee Update webstats_log.lua 2026-07-05 04:05:19 +08:00
d1dcdd4f25 Update webstats_common.lua 2026-07-05 03:58:34 +08:00
60958d1403 Update webstats_common.lua 2026-07-05 03:56:13 +08:00
5530b14f36 Update webstats_common.lua 2026-07-05 03:36:39 +08:00
64c9942ee1 Update webstats_common.lua 2026-07-05 03:36:26 +08:00
bc1437dac4 Update webstats_init_worker.lua 2026-07-05 03:27:35 +08:00
1d9576e838 Update webstats_log.lua 2026-07-05 03:27:11 +08:00
8b275a5df4 Update webstats_log.lua 2026-07-05 03:18:14 +08:00
40d9334dcf Update index.py 2026-07-05 02:45:28 +08:00
98c0242819 Update index.py 2026-07-05 02:39:23 +08:00
a2fb03f9b8 Update index.py 2026-07-05 02:31:20 +08:00
98815ac5c3 update 2026-07-05 02:29:29 +08:00
073dd20c96 update 2026-07-05 01:16:02 +08:00
23af9085a9 update 2026-07-05 00:51:14 +08:00
bcaec6b6ee Update install.sh 2026-07-04 23:42:10 +08:00
4063bea922 Update webstats_common.lua 2026-07-04 23:02:54 +08:00
9f864b3407 Update webstats_common.lua 2026-07-04 22:56:49 +08:00
01ac598e39 Update webstats_common.lua 2026-07-04 22:43:20 +08:00
77a0d3af36 Update webstats_common.lua 2026-07-04 22:35:03 +08:00
8d34bbea47 Update webstats_common.lua 2026-07-04 22:33:43 +08:00
be18e98001 Update webstats_common.lua 2026-07-04 22:23:56 +08:00
754e0f98f9 Update webstats_common.lua 2026-07-04 22:23:43 +08:00
07f893b6a1 Update webstats_common.lua 2026-07-04 22:21:17 +08:00
Mr Chen
c1497ec44e Merge pull request #919 from midoks/dev
常规更新
2026-07-03 12:05:30 +08:00
55d4784fe2 Update webstats_common.lua 2026-07-02 14:30:04 +08:00
f26e8bc520 update 2026-07-02 14:22:10 +08:00
7b5f1a4253 up 2026-07-02 14:12:32 +08:00
1058fb7e1f Update webstats_log.lua 2026-07-02 14:01:50 +08:00
0f1b95cdfc up 2026-07-02 13:54:31 +08:00
8ea16fcd85 Update webstats_common.lua 2026-07-02 13:32:22 +08:00
b4b9496980 Update webstats_common.lua 2026-07-02 13:15:12 +08:00
8dfd26361f Update webstats_common.lua 2026-07-02 13:06:32 +08:00
cb5bd32b86 Update webstats_common.lua 2026-07-02 13:02:31 +08:00
2584330d40 update 2026-07-02 12:52:05 +08:00
ebe6333ac9 up 2026-07-02 12:50:35 +08:00
534892280e up 2026-07-02 12:45:28 +08:00
df05cf69cf Update tool_migrate.py 2026-07-02 12:27:43 +08:00
2f782cf6a2 Update db.py 2026-07-02 12:26:19 +08:00
6f483c17e6 Create tool_migrate_bak.py 2026-07-02 11:42:13 +08:00
e64610a2dc Update mw.py 2026-06-30 20:18:46 +08:00
Mr Chen
7673a16779 Merge pull request #918 from midoks/dev
常规更新
2026-06-29 00:51:56 +08:00
d73fe4b29c Update __init__.py 2026-06-29 00:51:14 +08:00
2c61be084b Update __init__.py 2026-06-29 00:38:56 +08:00
fe5f8d1997 Update __init__.py 2026-06-29 00:38:08 +08:00
2653291ded Update __init__.py 2026-06-29 00:37:42 +08:00
417f91a2e8 Update init_cron.py 2026-06-29 00:19:10 +08:00
Mr Chen
08625e85bb Merge pull request #917 from midoks/dev
常规更新
2026-06-28 23:23:15 +08:00
c554c19a12 Update site.py 2026-06-28 23:10:34 +08:00
d7d08f2f12 Update site.py 2026-06-28 23:09:46 +08:00
Mr Chen
bafe45a2f9 Merge pull request #916 from midoks/dev
常规优化
2026-06-28 22:44:26 +08:00
a11d24723d Update README.md 2026-06-28 22:43:37 +08:00
3b858476f1 Update version.py 2026-06-28 22:41:13 +08:00
5560b68ac1 Update site.js 2026-06-28 22:40:26 +08:00
8bfd381363 Update site.py 2026-06-28 22:38:29 +08:00
c6cfe2a22c Update mw.py 2026-06-28 22:34:51 +08:00
4ed274dedc Update gd_old.sh 2026-06-28 22:26:28 +08:00
Mr Chen
283c815de7 Merge pull request #915 from midoks/dev
哪吒监控更新,同步官方
2026-06-22 18:00:56 +08:00
c72c1bc889 Update update.sh 2026-06-22 17:59:31 +08:00
6e61a535ca Update update.sh 2026-06-22 17:54:37 +08:00
c1f69ea1c7 Update update.sh 2026-06-22 17:51:11 +08:00
984599c56f Update update.sh 2026-06-22 17:50:22 +08:00
038bb31ec3 Update update.sh 2026-06-22 17:48:58 +08:00
1ac541d16e Update update.sh 2026-06-22 17:48:47 +08:00
ecaa0e99c5 Update update.sh 2026-06-22 17:45:38 +08:00
666ebeef0d Update update.sh 2026-06-22 17:43:53 +08:00
b39a936fa4 Update update.sh 2026-06-22 17:41:12 +08:00
d434dce568 Update update.sh 2026-06-22 17:40:21 +08:00
6acb390133 Update update.sh 2026-06-22 17:30:59 +08:00
3c6f3c50c4 Update update.sh 2026-06-22 17:28:40 +08:00
c52e707421 Update update.sh 2026-06-22 17:21:11 +08:00
5fb998c221 update 2026-06-22 17:15:18 +08:00
a0989ea833 Update nezha.js 2026-06-22 17:12:09 +08:00
5e565c06a0 Update nezha.js 2026-06-22 17:09:22 +08:00
69b96aa5fa Create update.sh 2026-06-22 17:08:16 +08:00
bce9de1494 Update nezha.js 2026-06-22 17:05:57 +08:00
3de7928be7 Update nezha.js 2026-06-22 17:05:30 +08:00
41630ef01a Update install.sh 2026-06-22 17:03:46 +08:00
bf29cb1a4d Update index.py 2026-06-22 16:59:49 +08:00
8f79a4ab86 update 2026-06-22 16:59:23 +08:00
0ad933c5ad Update nezha.js 2026-06-22 16:55:33 +08:00
5ed9470d83 update 2026-06-22 16:53:26 +08:00
cac468f454 Update plugin.py 2026-06-22 16:33:54 +08:00
f0f9dcf4de Update index.py 2026-06-22 16:32:59 +08:00
3e0e84a4f6 Update index.py 2026-06-22 16:09:53 +08:00
ef8080b420 Update index.py 2026-06-22 16:05:57 +08:00
b5fab1fb10 Update plugin.py 2026-06-22 16:03:41 +08:00
c3f019d4ff Update plugin.py 2026-06-22 16:00:40 +08:00
701f172276 Update plugin.py 2026-06-22 15:56:05 +08:00
9e8c736cb4 Update install.sh 2026-06-22 15:31:31 +08:00
c8589d750c Update info.json 2026-06-22 15:30:42 +08:00
5bb20a01de update 2026-06-22 15:16:01 +08:00
6e4bf9da3e Update nezha.js 2026-06-22 15:02:39 +08:00
c21ddb5c63 Update install.sh 2026-06-22 14:43:12 +08:00
431295cec9 update 2026-06-22 14:42:54 +08:00
180cb84b2c Update index.py 2026-06-22 14:42:14 +08:00
66b5f322d9 Update index.py 2026-06-22 14:41:00 +08:00
f00dc248bd Update install.sh 2026-06-22 14:40:16 +08:00
dbba5db9f7 Update info.json 2026-06-22 14:40:06 +08:00
3a8b799df6 Update index.py 2026-06-22 14:39:29 +08:00
0b99a4ae74 update 2026-06-22 14:35:51 +08:00
99b77d347a update 2026-06-22 14:30:08 +08:00
8235a88ecc Update nezha.js 2026-06-22 14:27:32 +08:00
564ba30f91 Update install.sh 2026-06-22 14:23:48 +08:00
aa8535d513 update 2026-06-22 14:22:40 +08:00
a02ef2575b Update install.sh 2026-06-22 14:21:10 +08:00
a0be16c0fa Update install.sh 2026-06-22 14:12:24 +08:00
548d87e339 Update install.sh 2026-06-22 14:12:14 +08:00
c704aa0817 Update install.sh 2026-06-22 14:10:03 +08:00
c6a060fde5 Update install.sh 2026-06-22 14:09:51 +08:00
762e88cc44 Update index.py 2026-06-22 14:05:03 +08:00
b7f671d1d5 update 2026-06-22 14:04:45 +08:00
48706d01f9 Update index.py 2026-06-22 14:04:21 +08:00
fb53354956 Update index.py 2026-06-22 14:03:54 +08:00
5995147054 Update index.py 2026-06-22 13:59:22 +08:00
fed9f458d1 Update install.sh 2026-06-22 13:49:41 +08:00
7987564401 Update install.sh 2026-06-22 13:45:08 +08:00
90ae21fb8b Update nezha.service.tpl 2026-06-22 13:43:14 +08:00
56a78d174d Update install.sh 2026-06-22 13:31:25 +08:00
37da947b90 Update install.sh 2026-06-22 13:31:09 +08:00
f23e272027 Update install.sh 2026-06-22 13:27:25 +08:00
10afc0a2d5 Update install.sh 2026-06-22 13:19:13 +08:00
f59c8ea533 Update install.sh 2026-06-22 13:17:26 +08:00
4153ea7431 update 2026-06-22 13:16:32 +08:00
2c73577798 Update nezha.js 2026-06-22 13:08:33 +08:00
0b5c53ef7e Update index.html 2026-06-22 12:55:34 +08:00
0fca0d54f8 Update info.json 2026-06-22 12:53:08 +08:00
3da0c5b2b6 Update install.sh 2026-06-22 12:52:55 +08:00
d8519bc1c3 update 2026-06-22 12:49:08 +08:00
33a4a799c5 Update index.py 2026-06-22 12:48:46 +08:00
358a021ba6 Update install.sh 2026-06-22 12:47:54 +08:00
6dba9c25b6 update 2026-06-22 12:47:23 +08:00
Mr Chen
1f724c802b Merge pull request #914 from midoks/dependabot/pip/gevent-23.9.0
Bump gevent from 22.10.2 to 23.9.0
2026-06-21 10:36:12 +08:00
dependabot[bot]
67e3dd0035 Bump gevent from 22.10.2 to 23.9.0
Bumps [gevent](https://github.com/gevent/gevent) from 22.10.2 to 23.9.0.
- [Release notes](https://github.com/gevent/gevent/releases)
- [Changelog](https://github.com/gevent/gevent/blob/master/docs/changelog_pre.rst)
- [Commits](https://github.com/gevent/gevent/compare/22.10.2...23.9.0)

---
updated-dependencies:
- dependency-name: gevent
  dependency-version: 23.9.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-21 02:35:26 +00:00
Mr Chen
de657829fd Merge pull request #913 from midoks/dev
常规更新
2026-06-21 10:33:03 +08:00
a2c27134a8 update 2026-06-21 10:30:30 +08:00
66c60ec10e Update r3.9.txt 2026-06-21 10:25:42 +08:00
867b39d8e1 Update r3.9.txt 2026-06-21 10:25:12 +08:00
1c8997d44a Update requirements.txt 2026-06-21 10:23:14 +08:00
88b5112e30 Update requirements.txt 2026-06-21 10:20:39 +08:00
3874b6a25a Update mw.py 2026-06-21 10:18:48 +08:00
Mr Chen
8ba6587c57 Merge pull request #912 from midoks/dev
常规更新
2026-06-21 10:17:02 +08:00
3ebe36f785 Update mw.py 2026-06-21 10:13:07 +08:00
Mr Chen
34ed0b96d3 Merge pull request #910 from midoks/dev
常规更新
2026-06-20 19:38:45 +08:00
ab353d2268 Update mw.py 2026-06-20 19:36:23 +08:00
Mr Chen
fd6f013480 Merge pull request #909 from midoks/dev
证书读取兼容
2026-06-20 19:31:31 +08:00
4d0b7bc127 Update mw.py 2026-06-20 19:27:39 +08:00
ce917b227f Merge branch 'master' into dev 2026-06-20 18:58:41 +08:00
dec1bb04e8 Merge branch 'master' into dev 2026-06-20 18:57:49 +08:00
Mr Chen
a1093c17bc Merge pull request #908 from midoks/dev
常规更新
2026-06-20 18:56:05 +08:00
8110fbf701 Update openresty.js 2026-06-20 18:44:03 +08:00
cf502ebf05 Update openresty.js 2026-06-20 18:37:41 +08:00
7c7837b967 up 2026-06-20 18:25:40 +08:00
3bfc1cacb0 Update openresty.js 2026-06-20 18:20:52 +08:00
cd2ea26608 Update openresty.js 2026-06-20 18:15:52 +08:00
dcf8159d1c update 2026-06-20 18:11:57 +08:00
Mr Chen
1bdab80b5d Merge pull request #907 from midoks/dev
常规更新
2026-06-20 15:33:43 +08:00
241c4dc600 Update install.sh 2026-06-20 15:24:32 +08:00
18e93d2b24 Update info.json 2026-06-20 15:13:08 +08:00
084cf6b761 Update info.json 2026-06-20 14:42:54 +08:00
47ddf5f4e6 Update install.sh 2026-06-20 14:40:58 +08:00
325321f5d4 Update install.sh 2026-06-20 14:32:38 +08:00
ecbeca3d35 Update install.sh 2026-06-20 14:29:40 +08:00
862b434c72 Update install.sh 2026-06-20 14:29:10 +08:00
6376ed3b7b update 2026-06-20 14:28:23 +08:00
42e40d1718 Update push_notice_msg.py 2026-06-18 14:33:55 +08:00
1c1cc12058 Update install.sh 2026-06-18 02:23:01 +08:00
e648b88a74 Update install.sh 2026-06-18 02:05:24 +08:00
Mr Chen
6fea46f7c8 Merge pull request #905 from midoks/dev
常规更新
2026-06-17 18:21:27 +08:00
a06e5a6e55 Update gd_old.sh 2026-06-17 18:21:15 +08:00
85bf429a08 Update freetype_old.sh 2026-06-17 18:14:30 +08:00
dd6ba45cdd Update gd_old.sh 2026-06-17 17:39:36 +08:00
ab967efa64 Update gd_old.sh 2026-06-17 17:16:14 +08:00
369505e1a0 Update r3.9.txt 2026-06-12 18:18:08 +08:00
86d858a0fb Update r3.9.txt 2026-06-12 18:15:50 +08:00
d1f5158276 Update r3.9.txt 2026-06-12 18:13:48 +08:00
Mr Chen
db83b0f78c Merge pull request #904 from midoks/dev
常规更新
2026-06-12 18:07:52 +08:00
24fcc5a0c6 Update requirements.txt 2026-06-12 17:51:47 +08:00
Mr Chen
9cb3d474aa Merge pull request #900 from midoks/dev
常规更新
2026-06-12 16:29:24 +08:00
0adfebfad6 Update install.sh 2026-06-12 16:25:58 +08:00
66c4225aa3 update 2026-06-09 11:11:15 +08:00
6ddef9ffda Update setting.py 2026-06-08 17:56:08 +08:00
27a1b22e6f Update setting.py 2026-06-08 17:54:45 +08:00
f9c18cb225 update 2026-06-07 00:10:11 +08:00
b97733328a Update plugin.py 2026-06-05 11:47:25 +08:00
Mr Chen
2fe17aefd9 Merge pull request #899 from midoks/dev
常规更新
2026-06-01 19:10:03 +08:00
acddca54cd update 2026-06-01 19:06:13 +08:00
7d80fb31ce Update install.sh 2026-06-01 18:52:36 +08:00
Mr Chen
8ac1d78053 Merge pull request #898 from midoks/dev
常规优化
2026-06-01 11:53:03 +08:00
468d6d7752 Update op_waf_index.py 2026-06-01 11:50:38 +08:00
f49d789411 update 2026-06-01 11:49:51 +08:00
1f56115fbb update 2026-05-21 17:35:19 +08:00
20d277102e Update install.sh 2026-05-21 11:08:06 +08:00
47b4036f09 Update install.sh 2026-05-21 10:32:07 +08:00
Mr Chen
ee9e154fec Merge pull request #897 from midoks/dev
openresty 1.29.2.4
2026-05-21 10:26:24 +08:00
85256b4fb6 Update install.sh 2026-05-21 10:24:37 +08:00
Mr Chen
16be671f1d Merge pull request #896 from midoks/dev
常规更新
2026-05-20 16:08:41 +08:00
af880115ab update 2026-05-17 18:06:54 +08:00
e64ac8f616 Update info.json 2026-05-17 18:01:47 +08:00
a7d4206b77 update 2026-05-17 17:58:29 +08:00
5a80690404 update 2026-05-17 17:55:47 +08:00
9b0d71d4ac Update phplib.conf 2026-05-17 17:54:01 +08:00
729f77d8db Update opcache.sh 2026-05-17 17:53:53 +08:00
e89f96aa2d Update phplib.conf 2026-05-17 17:50:16 +08:00
Mr Chen
f05f81cace Merge pull request #893 from midoks/dev
常规优化
2026-05-09 20:20:59 +08:00
f4883ee708 Update webstats_index.py 2026-05-09 20:18:45 +08:00
043fb739d9 Update index.py 2026-05-09 20:04:41 +08:00
b19aa8702b Update index.py 2026-05-09 20:01:39 +08:00
f4e0744879 update 2026-05-09 19:59:09 +08:00
Mr Chen
d7c822f86d Merge pull request #892 from midoks/dev
常规更新
2026-05-09 14:31:10 +08:00
c8f8e217e5 update 2026-05-09 14:26:41 +08:00
Mr Chen
bfec7f1fe8 Merge pull request #891 from midoks/dev
常规更新
2026-05-07 19:07:02 +08:00
21fce1f618 Update index.py 2026-05-07 19:05:07 +08:00
b5987b57ad Update task.py 2026-05-07 18:48:04 +08:00
e8c1cb08a7 update 2026-05-07 18:47:45 +08:00
0de3a16898 Update index.py 2026-05-07 18:42:07 +08:00
278bd7f38e Update debian.sh 2026-05-07 17:50:16 +08:00
4a3b9db324 Update debian.sh 2026-05-07 17:47:48 +08:00
b3e8e96875 Update index.py 2026-05-07 17:06:56 +08:00
f5e50c6d76 Update index.py 2026-05-07 16:59:27 +08:00
c551c2ee1a Update index.py 2026-05-07 16:55:58 +08:00
3fb8406e7b Update index.py 2026-05-07 16:53:30 +08:00
50d12407c9 Update install.sh 2026-05-07 16:48:13 +08:00
17931bb0ea Update install.sh 2026-05-07 16:48:03 +08:00
6d30940920 Update index.py 2026-05-07 16:46:31 +08:00
3a4c985baf Update index.py 2026-05-07 16:45:59 +08:00
Mr Chen
960d8b6cb8 Merge pull request #890 from midoks/dev
mongodb 兼容低版本
2026-05-07 16:34:36 +08:00
9b7e9d4ffa update 2026-05-07 16:29:03 +08:00
c1a646c0d7 Merge branch 'master' into dev 2026-05-07 16:25:26 +08:00
48ef0e7a65 Update index.py 2026-05-07 16:22:03 +08:00
8dff306a91 Update index.py 2026-05-07 16:20:03 +08:00
a935acbc95 update 2026-05-07 16:12:16 +08:00
b1f9c99eb1 Update mw.tpl 2026-05-07 16:04:53 +08:00
0851f749c3 Update mw.tpl 2026-05-07 15:57:20 +08:00
3a7d9f84c7 Update install.sh 2026-05-07 15:22:12 +08:00
b43b35ccab Update install.sh 2026-05-07 15:21:29 +08:00
5fc6eacc53 update 2026-05-07 15:11:09 +08:00
bd782362e8 update 2026-05-07 15:06:37 +08:00
32151a176f update 2026-05-07 15:04:27 +08:00
f7c88d2086 update 2026-05-07 14:01:26 +08:00
1eb76f2b90 update 2026-05-07 13:56:40 +08:00
226b3e049d Merge branch 'master' into dev 2026-05-07 12:58:58 +08:00
Mr Chen
7f0e9851cd Merge pull request #889 from midoks/dev
常规优化
2026-05-07 12:58:41 +08:00
15df77940e Update index.py 2026-05-07 12:09:57 +08:00
9781516552 Update plugin.py 2026-05-07 12:05:18 +08:00
a23264a542 update 2026-05-07 12:03:23 +08:00
0e7845985a Update install.sh 2026-05-07 11:51:06 +08:00
93efe45347 Update install.sh 2026-05-07 11:40:52 +08:00
a46f824e1e Update install.sh 2026-05-07 11:40:09 +08:00
Mr Chen
0de9f036bc Merge pull request #888 from midoks/dev
常规优化
2026-05-01 19:19:07 +08:00
275f2515d6 优化 2026-05-01 19:17:05 +08:00
b4604928ec Update panel_task.py 2026-05-01 18:53:42 +08:00
5a79b4021a update 2026-04-23 23:09:01 +08:00
280fd38039 Create r3.9.txt 2026-04-23 15:29:05 +08:00
Mr Chen
b032364616 Merge pull request #887 from midoks/dev
常规更新
2026-04-23 00:24:22 +08:00
a430aaee97 Update index.py 2026-04-23 00:19:46 +08:00
f4ee2ca3b9 Update install.sh 2026-04-23 00:12:59 +08:00
92b9212b31 update 2026-04-23 00:12:57 +08:00
73656e60ff Update nginx.conf 2026-04-22 23:02:44 +08:00
401329d80c update 2026-04-22 22:32:25 +08:00
Mr Chen
6131970724 Merge pull request #886 from midoks/dev
常规优化
2026-04-21 20:51:12 +08:00
85dcc4b78a update 2026-04-21 20:27:46 +08:00
34a1bf7e28 Update mw.tpl 2026-04-15 20:33:51 +08:00
Mr Chen
afdccefa98 Merge pull request #885 from midoks/dev
0.18.6
2026-04-15 20:00:09 +08:00
e1fd0a5535 Delete r3.9.txt 2026-04-15 19:54:42 +08:00
15d2cd7342 update 2026-04-15 19:53:22 +08:00
Mr Chen
f5fda8b71f Merge pull request #884 from midoks/dev
紧急‼️更新。计划任务修改未鉴权
2026-04-15 19:33:41 +08:00
8586dbbe8b Update site_default.py 2026-04-15 19:32:07 +08:00
c508c71f60 Update __init__.py 2026-04-15 19:28:57 +08:00
Mr Chen
33cabc8e2d Merge pull request #883 from midoks/dev
简单优化
2026-04-15 17:33:09 +08:00
e244d477e2 Update mw.tpl 2026-04-15 17:08:47 +08:00
c2f81e182a update 2026-04-15 17:02:25 +08:00
d7c68cfaa9 Update mw.tpl 2026-04-15 16:42:15 +08:00
b1aa5b8183 Update install.sh 2026-04-15 16:34:01 +08:00
877b1dacf8 Update mw.tpl 2026-04-15 16:28:58 +08:00
8eef664e50 Update mw.tpl 2026-04-15 16:28:16 +08:00
f0581f5038 Update mw.tpl 2026-04-15 16:27:42 +08:00
0b584d48b8 up 2026-04-15 16:06:58 +08:00
9199875c51 Update mw.tpl 2026-04-15 15:41:19 +08:00
e062cc4870 Update __init__.py 2026-04-15 15:10:36 +08:00
2ba4d87b75 Update mw.tpl 2026-04-15 15:08:37 +08:00
4b4c0df77d update 2026-04-15 14:03:21 +08:00
b5e4f32fa5 Update __init__.py 2026-04-15 13:56:05 +08:00
27ca45b088 Update http.tpl 2026-04-15 13:45:02 +08:00
345e38a560 Create http.tpl 2026-04-15 13:26:43 +08:00
176e4c8b3e update 2026-04-15 13:22:15 +08:00
81083dd30c Delete test_apache_install.sh 2026-04-14 18:31:17 +08:00
9a5a09438e Update mw.tpl 2026-04-14 18:26:12 +08:00
f17447b2f1 Update mw.tpl 2026-04-14 18:11:18 +08:00
930eb14a8a Update mw.tpl 2026-04-14 18:04:35 +08:00
08951f8c2e Update mw.tpl 2026-04-14 18:00:02 +08:00
c74bb01c3c Update mw.tpl 2026-04-14 17:53:14 +08:00
34b9b189d4 Update mw.tpl 2026-04-14 17:43:22 +08:00
960aca266e Update mw.tpl 2026-04-14 17:32:55 +08:00
840e04dc55 Update index.py 2026-04-12 12:01:09 +08:00
defaf3f970 Update index.py 2026-04-12 12:01:02 +08:00
b8b2349b6c update 2026-04-12 11:49:35 +08:00
c3c4671f76 update 2026-04-12 11:23:54 +08:00
d9811d9d50 Update index.py 2026-04-12 11:10:47 +08:00
da515f8595 Update install.sh 2026-04-11 23:57:37 +08:00
467a8af504 Update httpd.conf 2026-04-11 23:55:46 +08:00
ed16571d44 Update install.sh 2026-04-11 23:53:49 +08:00
6d06f1fbce update 2026-04-11 23:53:31 +08:00
9a59b2ad3f Update install.sh 2026-04-11 23:51:33 +08:00
1dc03ca5ae Update httpd.service.tpl 2026-04-11 22:13:45 +08:00
260de6eae5 Update index.py 2026-04-11 22:05:27 +08:00
2458377010 Update index.py 2026-04-11 22:03:17 +08:00
d4a7f2bbc8 Update httpd.conf 2026-04-11 21:59:01 +08:00
1b8b009b58 Update httpd.conf 2026-04-11 21:55:10 +08:00
a6623058b5 Update httpd.conf 2026-04-11 21:52:11 +08:00
aa385a5e30 Update httpd.conf 2026-04-11 21:51:03 +08:00
67e9113b48 Update index.py 2026-04-11 21:45:10 +08:00
9667279bf6 Update index.py 2026-04-11 21:44:45 +08:00
84e94c1122 update 2026-04-11 21:43:44 +08:00
12fd04b296 Update index.py 2026-04-11 21:34:11 +08:00
2e5ab39fee Update install.sh 2026-04-11 21:32:54 +08:00
b975fedfee update 2026-04-11 21:24:15 +08:00
0670bca67d Update index.py 2026-04-11 21:00:23 +08:00
9a976fdd3c update 2026-04-11 20:56:29 +08:00
91d189cf00 Update index.py 2026-04-11 20:45:19 +08:00
b97e0df6c5 Update index.py 2026-04-11 20:44:54 +08:00
e966df976f Update index.py 2026-04-11 20:42:40 +08:00
530347c847 Update index.py 2026-04-11 20:41:55 +08:00
fc5acaf0be Update index.py 2026-04-11 20:40:07 +08:00
affea597bf Update index.py 2026-04-11 20:38:39 +08:00
732ad976bf Update index.py 2026-04-11 20:37:11 +08:00
b0133162f0 Update index.py 2026-04-11 20:36:30 +08:00
0fa462c385 Update index.py 2026-04-11 20:36:17 +08:00
f7d7ee6b43 update 2026-04-11 20:30:00 +08:00
b769b79b9a update 2026-04-11 20:23:44 +08:00
320001b3a3 Update httpd.service.tpl 2026-04-11 20:14:46 +08:00
5c53bb3853 up 2026-04-11 19:10:59 +08:00
584ac773b3 Update install.sh 2026-04-11 17:01:44 +08:00
be6e034153 Update install.sh 2026-04-11 16:57:04 +08:00
b85bb698d0 up 2026-04-11 16:56:03 +08:00
ecab1a45b9 up 2026-04-11 16:46:12 +08:00
d3a7f7a732 Update install.sh 2026-04-11 16:34:01 +08:00
30b106c5c2 Update install.sh 2026-04-11 16:32:44 +08:00
5b8148b83d Update install.sh 2026-04-11 16:32:04 +08:00
a973696501 Update install.sh 2026-04-11 16:30:49 +08:00
5bb5ad7ba8 Update install.sh 2026-04-11 16:22:08 +08:00
72188223ae Update install.sh 2026-04-11 16:19:02 +08:00
4fbd037af1 update 2026-04-11 16:18:12 +08:00
9789ab6e37 Update index.py 2026-04-11 15:04:56 +08:00
f766039139 caddy 2026-04-11 15:01:26 +08:00
9aad09be9a Update install.sh 2026-04-11 13:02:33 +08:00
Mr Chen
ea07a3e3ce Merge pull request #879 from midoks/dev
php pgsql扩展
2026-04-10 17:44:02 +08:00
4e9ea630d7 Update phplib.conf 2026-04-10 17:39:25 +08:00
c4aeecdf3a Update phplib.conf 2026-04-10 17:38:55 +08:00
ab36c69729 Update phplib.conf 2026-04-10 17:35:32 +08:00
ade7d1f735 Update phplib.conf 2026-04-10 17:33:13 +08:00
5c7d62c59b update 2026-04-10 17:31:20 +08:00
772de4e67b update 2026-04-10 17:29:14 +08:00
Mr Chen
2505f3904d Merge pull request #878 from midoks/dev
软件更新
2026-04-10 17:25:35 +08:00
ea06ede236 update 2026-04-10 16:40:29 +08:00
d9132fad5a update 2026-04-10 16:34:32 +08:00
b20148b93f update 2026-04-10 16:21:58 +08:00
41dde8a164 Update info.json 2026-04-10 16:14:31 +08:00
c83c4b052b update 2026-04-10 16:12:34 +08:00
3dad8258df Update setting.py 2026-04-08 22:58:17 +08:00
60f358510c Update nginx.conf 2026-04-08 19:03:54 +08:00
Mr Chen
46e5e5fbdc Merge pull request #876 from midoks/dev
常规优化
2026-04-08 00:24:22 +08:00
6561a63956 Update nginx.conf 2026-04-08 00:03:10 +08:00
9a390616ad Update nginx.conf 2026-04-08 00:02:27 +08:00
815ede7e1a Update nginx.conf 2026-04-08 00:01:20 +08:00
4960657be7 Update nginx.conf 2026-04-08 00:00:26 +08:00
Mr Chen
0b18aa4906 Merge pull request #875 from midoks/dev
Update __init__.py
2026-04-07 23:34:44 +08:00
f040827bc8 Update __init__.py 2026-04-07 23:27:43 +08:00
Mr Chen
876c3b2ecd Merge pull request #874 from midoks/dev
openresty配置优化
2026-04-07 15:30:38 +08:00
52c30a1e0e Update index.py 2026-04-07 15:27:00 +08:00
f2d93564a5 Update index.py 2026-04-07 15:24:46 +08:00
f19213d6f7 Update index.py 2026-04-07 15:23:08 +08:00
0e378ea982 Update openresty.js 2026-04-07 15:21:10 +08:00
51d8d48218 Update index.py 2026-04-07 15:18:28 +08:00
0f560a3594 update 2026-04-07 15:16:08 +08:00
Mr Chen
07ea3e39b9 Merge pull request #873 from midoks/dev
常规更新
2026-04-06 10:10:17 +08:00
50851ad62a Update mw.tpl 2026-04-06 10:04:31 +08:00
d45a956520 Update mw.tpl 2026-04-06 09:57:47 +08:00
7e9e95b7d2 Update mw.tpl 2026-04-06 09:56:49 +08:00
c02255dd08 Update mw.tpl 2026-04-06 09:55:18 +08:00
c465e15e96 Update __init__.py 2026-04-06 09:48:31 +08:00
Mr Chen
1da99434b3 Merge pull request #872 from midoks/dev
更新
2026-04-05 15:28:24 +08:00
368db8d94c up 2026-04-05 15:19:19 +08:00
a05c8cc3ea Update __init__.py 2026-04-05 15:12:45 +08:00
7d7ef2788e Update install.sh 2026-04-05 14:52:17 +08:00
93844b0e20 Update install.sh 2026-04-05 14:44:22 +08:00
Mr Chen
45b8e7cc28 Merge pull request #871 from midoks/dev
反代优化
2026-04-05 11:53:30 +08:00
59aea26e72 Update site.py 2026-04-05 11:51:16 +08:00
Mr Chen
a3a3a737ed Merge pull request #870 from midoks/dev
常规更新
2026-04-04 23:43:59 +08:00
69c048cfa6 Update index.py 2026-04-04 23:41:58 +08:00
045543f27a Update index.py 2026-04-04 23:41:05 +08:00
Mr Chen
3369821875 Merge pull request #869 from midoks/dev
面板优化
2026-04-04 23:09:53 +08:00
e880edd680 Update __init__.py 2026-04-04 22:59:04 +08:00
c5d516949d Update mw.tpl 2026-04-04 22:41:13 +08:00
cd695e5024 Update __init__.py 2026-04-04 22:37:01 +08:00
f97dd9747f Update __init__.py 2026-04-04 22:25:03 +08:00
67ed60731b Update __init__.py 2026-04-04 22:13:31 +08:00
d2c756a08a Update __init__.py 2026-04-04 22:13:22 +08:00
976d8a16e4 Update __init__.py 2026-04-04 22:08:54 +08:00
55f7a181cd 去掉 whitenoise , 使用flask static原生的功能 2026-04-04 21:28:51 +08:00
55d0ebad03 支持br和zstd 2026-04-04 21:04:47 +08:00
Mr Chen
5db9a064ca Merge pull request #868 from midoks/dev
常规更新
2026-04-04 19:26:23 +08:00
2a5fe72a34 Update mw.tpl 2026-04-04 19:24:57 +08:00
fd6d36b6d9 Update install.sh 2026-04-04 13:31:44 +08:00
Mr Chen
2aafc85fae Merge pull request #867 from midoks/dev
Update mw.py
2026-04-04 10:50:25 +08:00
3905f4ed28 Update mw.py 2026-04-04 10:38:24 +08:00
Mr Chen
c6570ac499 Merge pull request #866 from midoks/dev
openresty http3 较为完美实现
2026-04-04 01:08:23 +08:00
9241be1f5f Update mw.py 2026-04-04 01:01:22 +08:00
4fbd695f4e Update site.py 2026-04-04 00:42:07 +08:00
05b72a0c7e update 2026-04-04 00:29:52 +08:00
09ab982a4a Update site.js 2026-04-04 00:26:07 +08:00
70b2f20ca8 Update nginx.conf 2026-04-04 00:18:19 +08:00
4f12a096e7 up 2026-04-04 00:09:46 +08:00
ea5df706a8 Update site.py 2026-04-03 21:47:02 +08:00
d92dae066d Update install.sh 2026-04-03 21:13:22 +08:00
Mr Chen
40345f6cb9 Merge pull request #865 from midoks/dev
openresty优化
2026-04-03 14:18:42 +08:00
8aaf0eb99e Update site.py 2026-04-03 14:11:28 +08:00
cd1885477d Update site.py 2026-04-03 14:08:08 +08:00
28bb578170 Update site.py 2026-04-03 14:07:25 +08:00
2965df19cb Update site.py 2026-04-03 13:57:58 +08:00
36929f3ab4 Update nginx.conf 2026-04-03 13:54:14 +08:00
e1f7ea8f18 Update nginx.conf 2026-04-03 13:53:53 +08:00
7e4b603582 Update nginx.conf 2026-04-03 13:47:53 +08:00
f82eaee49e Update alpine.sh 2026-04-03 13:19:13 +08:00
e1fe3d959a update 2026-04-03 13:17:45 +08:00
86d3dd2c88 bash zstd 2026-04-03 13:13:59 +08:00
127e3ae325 openresty 2026-04-03 12:31:24 +08:00
16c8c3c873 Update nginx.conf 2026-04-03 12:30:09 +08:00
58fbd9c581 Update install.sh 2026-04-03 11:52:44 +08:00
91f75c60c6 Update install.sh 2026-04-03 11:52:02 +08:00
dee60a5a34 Update install.sh 2026-04-03 11:37:38 +08:00
013d53c346 Update install.sh 2026-04-03 11:33:11 +08:00
d42e28f713 Update site.py 2026-04-03 11:09:37 +08:00
dc69407d76 Update push_notice_msg.py 2026-04-03 10:51:29 +08:00
ab228bb8d4 Update push_ad.py 2026-04-03 10:33:27 +08:00
772ba40108 Update site.py 2026-04-03 03:44:44 +08:00
f143e2ea49 Update site.py 2026-04-03 03:44:36 +08:00
dd32fc58eb Update site.py 2026-04-03 03:35:43 +08:00
30f499f3cd update 2026-04-03 03:22:17 +08:00
c7325645be Update install.sh 2026-04-03 03:16:53 +08:00
dfca75f19a Update install.sh 2026-04-03 03:16:07 +08:00
70005b3b82 Update install.sh 2026-04-03 03:14:47 +08:00
e51e2dfe27 Update install.sh 2026-04-03 03:12:58 +08:00
57ddcb47f2 update 2026-04-03 03:09:19 +08:00
0ec2764369 update 2026-04-03 02:59:24 +08:00
2215a7895e update 2026-04-03 02:57:18 +08:00
bac86bd8e0 Update install.sh 2026-04-03 02:55:55 +08:00
3f9540a415 Update site.py 2026-04-03 02:38:07 +08:00
e5be78e832 Update site.py 2026-04-03 02:37:52 +08:00
8a03d1c704 Update site.py 2026-04-03 02:36:55 +08:00
1655fd33eb Update site.py 2026-04-03 02:36:23 +08:00
af93e5d00e Update site.py 2026-04-03 02:35:43 +08:00
f2f1f1c879 Update site.py 2026-04-03 02:23:45 +08:00
fd7179c3f5 Update site.py 2026-04-03 02:21:16 +08:00
bbf4200b42 Update site.py 2026-04-03 02:20:25 +08:00
e50877ba5d Update site.py 2026-04-03 02:20:15 +08:00
61cf4eb964 Update site.py 2026-04-03 02:20:05 +08:00
87ca7fdc8d Update site.py 2026-04-03 02:17:27 +08:00
7745bbe60c Update site.py 2026-04-03 02:01:47 +08:00
949ebf83e3 Update site.py 2026-04-03 02:01:13 +08:00
6744282bf1 Update site.py 2026-04-03 01:58:18 +08:00
5b374b0410 Update site.py 2026-04-03 01:56:58 +08:00
efaa97b9bd Update site.py 2026-04-03 01:50:13 +08:00
87c5dd5fa7 Update site.py 2026-04-03 01:48:15 +08:00
023a5b75b4 Update site.py 2026-04-03 01:46:54 +08:00
7e6a5de0f1 Update site.py 2026-04-03 01:43:21 +08:00
348500a288 Update site.py 2026-04-03 01:42:42 +08:00
27be26d12d Update site.py 2026-04-03 01:39:09 +08:00
4932eab08a Update site.py 2026-04-03 01:34:08 +08:00
341e2ed7ff Update site.py 2026-04-03 01:28:38 +08:00
7af6dac964 Update site.py 2026-04-03 01:19:43 +08:00
f94d23723c Update site.py 2026-04-03 01:14:40 +08:00
170005fb79 Update site.py 2026-04-03 01:07:59 +08:00
5ebe3fd95c Update site.py 2026-04-03 01:06:01 +08:00
d49d2247c9 Update site.py 2026-04-03 01:04:27 +08:00
593c90f605 Update site.py 2026-04-03 01:02:40 +08:00
fa41140aed Update site.py 2026-04-03 01:01:33 +08:00
e246509ebf Update site.py 2026-04-03 00:59:29 +08:00
81db94ac8a Update site.py 2026-04-03 00:58:19 +08:00
de29c766b3 Update site.py 2026-04-03 00:45:37 +08:00
3e96586c8e Update site.py 2026-04-03 00:39:50 +08:00
7eac6cadb0 Update nginx.conf 2026-04-03 00:33:25 +08:00
414ba32541 Update nginx.conf 2026-04-03 00:33:11 +08:00
8d4db5b574 Update site.py 2026-04-03 00:33:01 +08:00
422b904e00 Update site.py 2026-04-03 00:32:41 +08:00
5ce627ee0b Update site.py 2026-04-03 00:32:03 +08:00
3ddb6f9abc Update site.py 2026-04-03 00:31:53 +08:00
583f2a17b5 Update site.py 2026-04-03 00:31:33 +08:00
e628f1f6d5 update 2026-04-03 00:29:12 +08:00
89f21867a5 Update nginx.conf 2026-04-03 00:13:41 +08:00
4dd557feee Update nginx.conf 2026-04-03 00:12:18 +08:00
cc315db34b Update nginx.conf 2026-04-03 00:10:35 +08:00
086692e668 Update nginx.conf 2026-04-03 00:05:59 +08:00
e7528205f6 Update nginx.conf 2026-04-03 00:05:27 +08:00
af735e196e Update site.py 2026-04-02 23:37:24 +08:00
7dd59c3346 Update install.sh 2026-04-02 20:29:06 +08:00
1c6ade5b77 Update install.sh 2026-04-02 20:26:25 +08:00
f714da7662 Update install.sh 2026-04-02 11:25:02 +08:00
907ae1db04 update 2026-04-02 11:16:32 +08:00
691dd4a7bd Update install.sh 2026-04-02 11:12:33 +08:00
b1f531446a Update install.sh 2026-04-02 11:02:47 +08:00
c5aeaf1452 update 2026-04-02 10:48:59 +08:00
c27914c957 Update install.sh 2026-04-02 10:48:35 +08:00
6424e1e416 Update install.sh 2026-04-02 10:44:41 +08:00
0fc0e12c08 update 2026-04-02 10:39:45 +08:00
dfc3e79709 Update install.sh 2026-04-02 10:39:20 +08:00
f0b515ff5c Update install.sh 2026-04-02 10:38:53 +08:00
2f39e3277f Update install.sh 2026-04-02 10:38:25 +08:00
6576794456 Update install.sh 2026-04-02 10:34:20 +08:00
bdc8223c6c Update install.sh 2026-04-02 10:24:57 +08:00
d68cf3b557 Update install.sh 2026-04-02 10:22:40 +08:00
11787d290b Update install.sh 2026-04-02 10:16:00 +08:00
047a14dcbc up 2026-04-02 10:11:11 +08:00
f9d441a97f Update install.sh 2026-04-01 15:11:46 +08:00
Mr Chen
9cee124afd Merge pull request #864 from midoks/dev
openresty 加入br功能
2026-04-01 01:44:11 +08:00
43cf348b72 Update mw.py 2026-04-01 01:16:49 +08:00
86eb344492 Update mw.py 2026-04-01 00:56:32 +08:00
9030628090 Update mw.py 2026-04-01 00:52:26 +08:00
f6d39c7be3 Update install.sh 2026-04-01 00:46:49 +08:00
a9931b114e Update mw.py 2026-04-01 00:44:32 +08:00
87d9ce4486 Update install.sh 2026-04-01 00:32:21 +08:00
b61256221a Update install.sh 2026-04-01 00:24:09 +08:00
e9f43cb6f4 openresty 所有版本加入br的扩展 2026-04-01 00:17:53 +08:00
be79a9b4f9 Update install.sh 2026-04-01 00:13:38 +08:00
a3ff2fbefe Update install.sh 2026-04-01 00:12:31 +08:00
8d032cd867 Update nginx.conf 2026-04-01 00:05:10 +08:00
71392cd54f Update install.sh 2026-03-31 23:54:37 +08:00
92f14b1c12 Update install.sh 2026-03-31 23:41:37 +08:00
7e9674c7a7 Update install.sh 2026-03-31 23:41:06 +08:00
ccf0b070b0 Update install.sh 2026-03-31 23:17:08 +08:00
a9536cccd1 Update install.sh 2026-03-31 23:15:28 +08:00
5f26bdcefb Update install.sh 2026-03-31 23:13:55 +08:00
015c901047 Update install.sh 2026-03-31 23:08:23 +08:00
201ac15aea Update install.sh 2026-03-31 23:01:40 +08:00
04725db699 Update install.sh 2026-03-31 22:50:08 +08:00
9b72c785b5 Update install.sh 2026-03-31 22:49:46 +08:00
ca20d585da Update install.sh 2026-03-31 22:27:58 +08:00
48bcb80dd7 Update install.sh 2026-03-31 22:25:26 +08:00
e4bf1f0d53 Update install.sh 2026-03-31 22:18:23 +08:00
769764ad17 Update install.sh 2026-03-31 20:49:26 +08:00
Mr Chen
cbf732d072 Merge pull request #863 from midoks/dev
opcache优化
2026-03-21 23:50:54 +08:00
9a60ded31c Update opcache.sh 2026-03-21 23:47:55 +08:00
f7fa4a6dc5 Update opcache.sh 2026-03-21 23:41:33 +08:00
Mr Chen
d2f653decb Merge pull request #862 from midoks/dev
Update r3.6.txt
2026-03-21 15:04:06 +08:00
7471265010 Update r3.6.txt 2026-03-21 15:00:26 +08:00
Mr Chen
60e5dc0e57 Merge pull request #861 from midoks/dev
AI插件+swoole优化
2026-03-21 14:58:31 +08:00
9aacf8ca41 update 2026-03-21 14:52:16 +08:00
b91b4cd5b2 Update swoole.sh 2026-03-21 14:50:13 +08:00
e5843a4f40 Merge branch 'master' into dev 2026-03-21 11:17:28 +08:00
97259b5a14 Update phplib.conf 2026-03-21 11:17:17 +08:00
e0e56faa5d Update swoole.sh 2026-03-18 15:26:47 +08:00
f837fb31fc Update push_notice_msg.py 2026-03-17 18:41:35 +08:00
d1eef0a8c5 update 2026-03-17 18:15:40 +08:00
4a657451ed update 2026-03-17 18:08:50 +08:00
Mr Chen
68a5af4bef Merge pull request #859 from ccbkkb/master 2026-03-16 08:35:12 +08:00
ccbkkb
d0018d4de8 Update mw.py 2026-03-15 23:20:27 +08:00
ccbkkb
38dd92754a Fix: 修复安装时公网IP获取失败的问题(使用cloudflare接口替换v6r.ipip.net接口)
v6r.ipip.net return 502
2026-03-15 23:18:03 +08:00
1f2d68ffd2 Update ollama.js 2026-03-12 16:31:31 +08:00
f18d0c998f Update install.sh 2026-03-12 16:26:06 +08:00
374e2e6b91 Update install.sh 2026-03-12 16:23:42 +08:00
b2e439c94e Update install.sh 2026-03-12 16:21:57 +08:00
875d616cbf Update install.sh 2026-03-12 16:21:07 +08:00
837e229d11 Update ollama.js 2026-03-12 16:19:04 +08:00
8fd038cd11 Update install.sh 2026-03-12 16:18:42 +08:00
ca8b44dd8d update 2026-03-12 16:16:07 +08:00
e8f767a56b Update index.py 2026-03-12 16:07:46 +08:00
b531c48083 update 2026-03-12 16:00:51 +08:00
bbab1c13a2 Update info.json 2026-03-12 13:04:27 +08:00
4334b48ab1 Update info.json 2026-03-07 17:50:30 +08:00
ab1ca7af80 Update install.sh 2026-03-03 15:09:01 +08:00
ac54b65c87 update 2026-03-03 15:08:45 +08:00
35db1ff6b2 Update init_cron.py 2026-02-25 12:35:44 +08:00
Mr Chen
126bdcca73 Merge pull request #858 from midoks/dev
简单ui优化
2026-02-23 01:31:19 +08:00
5cfcb71759 up 2026-02-23 01:21:44 +08:00
e6a54b08f1 Update info.json 2026-02-13 13:29:48 +08:00
Mr Chen
434ac7b577 Merge pull request #857 from midoks/dev
常规更新
2026-02-05 11:58:03 +08:00
7e3b3fae1c Update install.sh 2026-02-05 11:57:00 +08:00
4c52629ba7 update 2026-02-05 10:37:31 +08:00
135b9b6e09 Update php.js 2026-02-05 10:32:43 +08:00
1647065b04 Update php.js 2026-02-05 10:30:01 +08:00
bf6b39707a Update php.js 2026-02-05 10:29:39 +08:00
4a4450260f Update php.js 2026-02-05 10:26:28 +08:00
Mr Chen
4701234c94 Merge pull request #856 from midoks/dev
可迁移ssh终端配置
2026-02-01 18:15:42 +08:00
8c4c4a25cb Update index.py 2026-02-01 17:43:09 +08:00
7be14d2d8c Update index.py 2026-02-01 17:40:58 +08:00
d8b387fbad Update index.py 2026-02-01 17:38:32 +08:00
6087377e8e Update index.py 2026-02-01 17:37:25 +08:00
e5797ef6a8 Update index.py 2026-02-01 17:37:09 +08:00
6817cafbfa update 2026-02-01 14:08:19 +08:00
bcdfeb03a8 Update index.py 2026-02-01 13:56:28 +08:00
Mr Chen
8854328697 Merge pull request #855 from midoks/dev
快捷连接ssh
2026-02-01 03:49:25 +08:00
0d83b2a59f Update cmd.md 2026-02-01 03:48:43 +08:00
691b4b5e59 Update mw.tpl 2026-02-01 03:47:15 +08:00
c4bffbda11 Update mw.tpl 2026-02-01 03:45:08 +08:00
ef7da60ec0 Update mw.tpl 2026-02-01 03:40:41 +08:00
95275c1b39 Update mw.tpl 2026-02-01 03:39:53 +08:00
944714e4ba update 2026-02-01 03:34:07 +08:00
aa7962c959 update 2026-02-01 03:07:48 +08:00
97c13d5f44 Update panel_tools.py 2026-01-31 17:56:36 +08:00
004faffc4c Update mw.tpl 2026-01-31 17:55:07 +08:00
eeef2abaf3 update 2026-01-31 17:54:34 +08:00
3a70c388cc update 2026-01-31 17:41:18 +08:00
Mr Chen
b81044106e Merge pull request #853 from midoks/dev
常规更新
2026-01-24 20:56:24 +08:00
a5230d1da4 Update swoole.sh 2026-01-24 20:38:53 +08:00
c1223aaee4 Update swoole.sh 2026-01-24 20:38:37 +08:00
7175315abc Update swoole.sh 2026-01-24 20:37:47 +08:00
00f4a722e1 Merge branch 'master' into dev 2026-01-24 20:35:53 +08:00
664d847a71 Update swoole.sh 2026-01-24 20:35:28 +08:00
21dedb7748 Update swoole.sh 2026-01-24 20:34:14 +08:00
88a0c5dc57 update 2026-01-24 20:29:30 +08:00
4677c39b97 Update phplib.conf 2026-01-24 20:28:17 +08:00
00b145d673 Update lib.sh 2026-01-24 20:27:43 +08:00
f04fff354a Update lib.sh 2026-01-24 20:27:18 +08:00
ca4264b838 Update brotli.sh 2026-01-24 20:22:21 +08:00
0e4047c36f Update phplib.conf 2026-01-24 20:16:38 +08:00
1f3bb11a5d Merge branch 'master' into dev 2026-01-20 12:13:15 +08:00
Mr Chen
f7a103ff89 Merge pull request #852 from midoks/dev
常规优化
2026-01-20 12:13:08 +08:00
555c326b0c Update lib.sh 2026-01-20 12:12:27 +08:00
4f74a770af Update lib.sh 2026-01-20 12:03:31 +08:00
b26b14a0f2 Update lib.sh 2026-01-20 11:55:14 +08:00
Mr Chen
7d0e8c96ee Merge pull request #851 from midoks/dev
Update my9.3.cnf
2026-01-15 18:41:15 +08:00
a14439f128 Update my9.3.cnf 2026-01-15 18:40:38 +08:00
Mr Chen
4de8aba54a Merge pull request #850 from midoks/dev
常规更新
2026-01-15 14:49:19 +08:00
3814dda46e Update ubuntu.sh 2026-01-15 14:45:39 +08:00
923716dd08 Update debian.sh 2026-01-15 14:33:16 +08:00
fa0f86c8a0 Update debian.sh 2026-01-15 14:31:53 +08:00
efb8d29f78 Update debian.sh 2026-01-15 14:30:10 +08:00
22c71009df Update debian.sh 2026-01-15 14:29:10 +08:00
4e48bae0ad Update debian.sh 2026-01-15 13:46:14 +08:00
Mr Chen
ce55c5c011 Merge pull request #849 from midoks/dev
常规更新
2026-01-14 22:01:16 +08:00
7daf02e94c Update index.py 2026-01-14 21:59:05 +08:00
e4fdf60b8a Update index.py 2026-01-14 21:56:59 +08:00
b9ae73d865 Update index.py 2026-01-14 21:47:59 +08:00
Mr Chen
e9583db6a7 Merge pull request #848 from midoks/dev
Update my9.3.cnf
2026-01-14 21:43:48 +08:00
89eda3c702 Update my9.3.cnf 2026-01-14 21:38:03 +08:00
Mr Chen
245e0e038b Merge pull request #847 from midoks/dev
版本更新
2026-01-14 21:22:30 +08:00
010579aa1b Create mysql9.3.service.tpl 2026-01-14 21:17:13 +08:00
24e8337b41 update 2026-01-14 21:10:58 +08:00
d5f6224236 update 2026-01-14 13:13:42 +08:00
9ec8fe921d Update push_notice_msg.py 2026-01-12 11:23:13 +08:00
6fd1d294e5 update 2025-12-21 14:53:26 +08:00
d48c7271c0 up 2025-12-21 14:26:27 +08:00
d155c675f2 up 2025-12-21 14:25:48 +08:00
3a56faf123 update 2025-12-21 10:56:35 +08:00
Mr Chen
bc74608271 Merge pull request #845 from midoks/dev
ca证书可选择
2025-12-20 21:02:18 +08:00
484a615981 Update ssl_acme.py 2025-12-20 20:56:40 +08:00
efe92ba356 Update site.py 2025-12-20 20:49:25 +08:00
25f4a815fd acme证书选择 2025-12-20 20:46:58 +08:00
74f774bc3b Update push_notice_msg.py 2025-12-19 15:42:20 +08:00
Mr Chen
e871beda8e Merge pull request #844 from midoks/dev
PHP85 openssl bug解决
2025-12-11 15:43:54 +08:00
ddc3011dd9 update 2025-12-11 14:46:13 +08:00
9bf9322994 Update redis.sh 2025-12-11 14:41:54 +08:00
325d1567a7 Update redis.sh 2025-12-11 14:41:26 +08:00
e3ed7fde45 update 2025-12-11 14:39:58 +08:00
e8810cc2a7 update 2025-12-11 14:30:16 +08:00
bf101519d8 Update install.sh 2025-12-11 12:48:10 +08:00
58e1302b75 Update install.sh 2025-12-10 20:35:15 +08:00
750a070fbb Update obf_proxy.conf 2025-12-09 18:16:12 +08:00
e8b3131d2e Update obf_proxy.conf 2025-12-09 18:15:58 +08:00
c00cc887e4 Delete obf.conf 2025-12-09 17:24:12 +08:00
6fb8a5bbe5 update 2025-12-09 17:24:09 +08:00
952fcc2a1e delete 2025-12-09 17:23:07 +08:00
d070592491 Update install.sh 2025-12-08 14:50:12 +08:00
4fe64ddcb1 update 2025-12-07 00:37:52 +08:00
a10f10aa61 Update obf.lua 2025-12-07 00:22:53 +08:00
db2ad358cf Update util.lua 2025-12-07 00:14:03 +08:00
124b19525f Update nginx.conf 2025-12-07 00:01:36 +08:00
a64b9e1ab2 Update nginx.conf 2025-12-06 23:59:07 +08:00
a936daf95b update 2025-12-06 23:45:53 +08:00
dba64f9ea7 Update obf.lua 2025-12-06 23:42:21 +08:00
2e6555a8cb Update tpl.lua 2025-12-06 23:41:32 +08:00
52003c2d58 Update obf.conf 2025-12-06 20:07:31 +08:00
da028d6665 update 2025-12-06 20:05:34 +08:00
01a7746ae9 Update obf.lua 2025-12-06 19:57:10 +08:00
827fe3578f update 2025-12-06 19:45:44 +08:00
d4cf1d9aca Update tpl.lua 2025-12-06 19:36:30 +08:00
c2a4be71c4 Create tpl_v5.lua 2025-12-06 19:35:32 +08:00
404fd0dfdd update 2025-12-06 17:14:40 +08:00
9ffd7c91b7 Update util.lua 2025-12-06 16:27:00 +08:00
fc20046aaf Update tpl.lua 2025-12-06 16:25:59 +08:00
934ccba81f update 2025-12-06 16:23:54 +08:00
4db502e0f1 up 2025-12-06 15:54:47 +08:00
dd9dbd8321 Create obf_v4.lua 2025-12-06 14:06:04 +08:00
47102edfef update 2025-12-06 14:04:12 +08:00
9b86a6ee33 Create obf_v3.lua 2025-12-06 13:58:31 +08:00
9cb4dbc79d Update obf.lua 2025-12-05 15:51:00 +08:00
4789e40574 up 2025-12-05 15:42:20 +08:00
39109ae40b Update obf.lua 2025-12-05 15:26:37 +08:00
b6ffe579e0 update 2025-12-05 15:11:40 +08:00
d2b94a9a0e Update obf.conf 2025-12-05 14:49:20 +08:00
809022b388 update 2025-12-05 14:30:44 +08:00
5c2c614a65 混淆配置 2025-12-05 05:48:48 +08:00
a0934d9aaf Update site.js 2025-12-05 04:49:40 +08:00
19ac2d9a0a Update obf.lua 2025-12-05 04:29:46 +08:00
ae5870556a update 2025-12-05 04:27:19 +08:00
87c42c810e Update index.py 2025-12-05 04:15:42 +08:00
d7d36b44b2 Update index.py 2025-12-05 04:13:51 +08:00
9bb44d3ae5 Update index.py 2025-12-05 04:13:29 +08:00
f216c03a7b Update index.py 2025-12-05 04:13:23 +08:00
d091fc48f6 Update index.py 2025-12-05 04:11:16 +08:00
0eeae3a7ff html混淆代码 2025-12-05 04:06:40 +08:00
22c26c97f7 Merge branch 'master' into dev 2025-12-04 16:46:48 +08:00
Mr Chen
86c6416090 Merge pull request #843 from clutter0584/clutter0584-patch-1
Update index.py
2025-12-04 16:46:12 +08:00
clutter0584
123c07efe0 Update index.py
修复supervisor多进程任务重启失败的bug
2025-12-01 10:34:07 +08:00
d64f01bc54 update 2025-11-30 19:20:05 +08:00
415d7988b9 Create t.md 2025-11-29 16:43:28 +08:00
f846a1ac83 Create doh.conf 2025-11-29 16:07:23 +08:00
e95269d539 Update install.sh 2025-11-29 15:52:51 +08:00
4161a3afc1 Update doh.service.tpl 2025-11-29 15:50:22 +08:00
f842ed7b3d Update doh.js 2025-11-29 15:40:36 +08:00
66c8bb7c78 update 2025-11-29 15:35:49 +08:00
cd499edd6c update 2025-11-29 15:34:38 +08:00
51d4e187b6 update 2025-11-29 15:24:12 +08:00
a75f648b71 Update index.py 2025-11-29 15:18:26 +08:00
66a253b4e9 Update index.py 2025-11-29 15:16:50 +08:00
076f8e0365 Update index.py 2025-11-29 15:16:44 +08:00
37c850cf6c Update index.py 2025-11-29 15:15:14 +08:00
dc93213811 Update index.py 2025-11-29 15:11:18 +08:00
56d8c6c236 Update index.py 2025-11-29 15:08:30 +08:00
0a0b114baf Update index.py 2025-11-29 15:07:51 +08:00
7c444b3c53 update 2025-11-29 14:57:11 +08:00
f4c72266ea update 2025-11-29 14:50:24 +08:00
f45e6c885e Update install.sh 2025-11-29 14:29:17 +08:00
c4646a7de6 Update install.sh 2025-11-29 14:27:52 +08:00
37be254f25 Update install.sh 2025-11-29 14:21:54 +08:00
21d6244c3c Update install.sh 2025-11-29 14:11:06 +08:00
d141e67f52 Update install.sh 2025-11-29 14:09:16 +08:00
d2c4a79791 Update install.sh 2025-11-29 14:06:22 +08:00
240058005f Update install.sh 2025-11-29 14:05:10 +08:00
6d31f3791b update 2025-11-29 13:59:51 +08:00
7fba05d0d5 Update .gitignore 2025-11-23 22:27:30 +08:00
Mr Chen
44ead9f469 Merge pull request #842 from midoks/dev
常规更新
2025-11-23 17:43:33 +08:00
7ef3971fe1 Update file.py 2025-11-23 17:41:30 +08:00
216a3d5d60 Update file.py 2025-11-23 12:03:38 +08:00
ffb6844a41 Update file.py 2025-11-23 12:02:37 +08:00
575723b860 update 2025-11-23 11:57:54 +08:00
50a000f1c7 Update files.js 2025-11-23 11:48:25 +08:00
476c73fed3 update 2025-11-22 23:56:35 +08:00
471e655eb3 Update install.sh 2025-11-22 18:33:50 +08:00
934a436065 Update install.sh 2025-11-22 18:27:57 +08:00
ba1508a82a Update info.json 2025-11-22 18:27:03 +08:00
0f67d14153 Update install.sh 2025-11-22 18:25:50 +08:00
832d8f44f1 update 2025-11-22 18:20:24 +08:00
33343e1b1c Update index.py 2025-11-22 18:15:34 +08:00
Mr Chen
28694cd2b7 Merge pull request #841 from midoks/dev
PHP8.5正式版
2025-11-22 13:37:01 +08:00
c65f66decc Update install.sh 2025-11-22 13:07:28 +08:00
73a4743e88 update 2025-11-22 13:05:22 +08:00
2bcbf6365e Update info.json 2025-11-13 12:07:28 +08:00
Mr Chen
43301108ba Merge pull request #838 from midoks/dev
ACME强制更新修改
2025-11-13 02:28:04 +08:00
7898d26461 Update init_cron.py 2025-11-13 02:26:40 +08:00
13b3158bd6 Update init_cron.py 2025-11-13 02:18:14 +08:00
f4f327f25d Update index.py 2025-11-13 01:30:04 +08:00
45ff09dadb Update index.py 2025-11-13 01:25:42 +08:00
Mr Chen
bec78bc44c Merge pull request #837 from midoks/dev
ad修改
2025-11-06 16:22:09 +08:00
16e35935f9 update 2025-11-06 16:11:22 +08:00
d6603488b6 Update valkey.conf 2025-11-06 15:56:39 +08:00
717c2d2ece Update redis.conf 2025-11-04 17:42:33 +08:00
Mr Chen
e704af5494 Merge pull request #836 from midoks/dev
暂时关闭面板检查
2025-11-03 18:22:16 +08:00
5399d26c94 Update __init__.py 2025-11-03 18:17:37 +08:00
a32e29a378 Update mw.py 2025-11-03 17:57:15 +08:00
a62c474f99 Create window.tpl 2025-11-01 00:21:15 +08:00
Mr Chen
c507bb0238 Merge pull request #833 from midoks/dev
简单优化
2025-10-23 17:08:45 +08:00
30902eeac8 Update crontab.py 2025-10-23 17:05:34 +08:00
9442d58f4c Update crontab.py 2025-10-23 17:00:08 +08:00
Mr Chen
55a14cfedc Merge pull request #832 from midoks/dev
mariadb 12.0 版本修正
2025-10-18 13:40:35 +08:00
3d0ea980c8 Update install.sh 2025-10-18 11:33:11 +08:00
c9f7696519 Update info.json 2025-10-17 13:01:22 +08:00
Mr Chen
623d435758 Merge pull request #830 from midoks/dev
面板自动更新-加入计划任务(可删除)
2025-10-14 18:37:45 +08:00
05f06f09d4 Update init_cron.py 2025-10-14 18:35:36 +08:00
e19402c80c Update init_cron.py 2025-10-14 18:33:59 +08:00
cb87c5ba71 Update __init__.py 2025-10-14 18:32:41 +08:00
657eca08bf Update init_cron.py 2025-10-14 18:32:17 +08:00
4c58c86f84 Update check.sh 2025-10-02 12:25:14 +08:00
9b73a057fa Update check.sh 2025-10-02 12:14:49 +08:00
3c9bf95728 Update check.sh 2025-10-02 12:14:16 +08:00
2f48af5afe Update check.sh 2025-10-02 12:12:34 +08:00
Mr Chen
f7f5ba15ff Merge pull request #829 from midoks/dev
php85版本配置
2025-10-01 22:47:54 +08:00
5fd014f023 Update index.py 2025-10-01 22:46:50 +08:00
Mr Chen
caf3f4a783 Merge pull request #828 from midoks/dev
修复pgadmin4安装
2025-09-26 17:04:12 +08:00
b264bf6f58 Update install.sh 2025-09-26 17:00:19 +08:00
06b07cf9a0 Update install.sh 2025-09-26 16:27:27 +08:00
e5804b22cd Update requirements.txt 2025-09-26 16:24:55 +08:00
Mr Chen
85f292e1d2 Merge pull request #826 from midoks/dev
mongodb维护功能及DNS配置更改推荐方式
2025-09-17 12:52:58 +08:00
057f05a88a Update check.sh 2025-09-17 12:49:30 +08:00
a700267ee6 Update mongodb.js 2025-09-17 12:47:44 +08:00
331e33ec70 update 2025-09-17 12:46:19 +08:00
c9dc118af6 mongodb维护功能 2025-09-17 12:44:37 +08:00
e1e24a3350 Update index.html 2025-09-17 12:38:14 +08:00
Mr Chen
339dfd1c0b Merge pull request #825 from ramondelee/patch-3
Update site.py
2025-09-17 02:26:22 +08:00
Mr Chen
5bcc81c00a Merge branch 'dev' into patch-3 2025-09-17 02:26:08 +08:00
e7212ed506 Update site.py 2025-09-17 02:22:17 +08:00
ramondelee
c705c282d1 Update site.py
按ACME官方推荐配置更新huaweicloud和cloudflare的DNS-API配置,cloudflare更改为账户ID和可配置权限token。
2025-09-16 22:23:49 +08:00
Mr Chen
20ea1f8209 Merge pull request #821 from midoks/dev
openresty 添加检查任务功能
2025-09-16 01:25:15 +08:00
fa73171d7d openresty 检查重启任务 2025-09-16 01:21:17 +08:00
a27675a783 Update tool_cron.py 2025-09-16 00:26:11 +08:00
2ddae1f0b9 Update tool_task.py 2025-09-16 00:18:07 +08:00
415acc7780 Update site.py 2025-09-14 22:01:30 +08:00
Mr Chen
7590cf824f Merge pull request #819 from midoks/dev
兼容及优化
2025-09-14 16:29:20 +08:00
3ee88ddfb4 Update install.sh 2025-09-14 16:01:47 +08:00
4d5f90e0ec Update install.sh 2025-09-14 15:51:47 +08:00
694a65e9de Update install.sh 2025-09-14 15:51:19 +08:00
7e33103758 update 2025-09-14 15:49:37 +08:00
e04f26223e Update file.py 2025-09-14 15:40:45 +08:00
cd76b72d3c Update file.py 2025-09-14 15:39:05 +08:00
57372fe922 Update file.py 2025-09-14 15:34:09 +08:00
82ca7fdcdc Update file.py 2025-09-14 15:18:21 +08:00
c6d9fb89ba Update file.py 2025-09-14 15:16:05 +08:00
2ecd88586b Update file.py 2025-09-14 15:10:55 +08:00
d8779bed14 Update files.js 2025-09-14 15:06:37 +08:00
7ad988bceb Update file.py 2025-09-14 15:04:26 +08:00
04fc897a60 Update file.py 2025-09-14 15:03:04 +08:00
7922ba15ce Update file.py 2025-09-14 15:02:43 +08:00
fae27f7e19 Update file.py 2025-09-14 15:01:57 +08:00
7ba2f29efc Update file.py 2025-09-14 15:01:13 +08:00
0e8439d52b Update file.py 2025-09-14 15:01:04 +08:00
17c60b6b4e Update file.py 2025-09-14 14:52:09 +08:00
4ec54b2dbc Update file.py 2025-09-14 14:49:52 +08:00
409b1fa00d Update file.py 2025-09-14 14:49:02 +08:00
ad5fc52d66 Update file.py 2025-09-14 14:46:45 +08:00
4b4d21a0de Update files.js 2025-09-14 14:42:07 +08:00
3642a3fec5 Update files.js 2025-09-14 14:37:40 +08:00
cac097ea66 Update www.conf 2025-09-14 14:25:14 +08:00
4a2b0d9d9f Update index.py 2025-09-14 14:24:24 +08:00
Mr Chen
6e53e7a23b Merge pull request #818 from midoks/dev
兼容细节优化
2025-09-12 14:27:52 +08:00
1e1e86dc16 Update rhel.sh 2025-09-12 14:09:13 +08:00
e7777877fa update 2025-09-12 14:00:27 +08:00
3a685eb316 Update install_generic.sh 2025-09-11 20:16:19 +08:00
344509ec28 up 2025-09-11 20:14:01 +08:00
b70a2951bd Update info.json 2025-09-11 20:08:52 +08:00
63282f42b2 Create install.sh 2025-09-11 20:08:30 +08:00
Mr Chen
03786817ed Merge pull request #817 from midoks/dev
兼容debain13
2025-09-11 18:21:24 +08:00
680bffa9e8 Update crontab.py 2025-09-11 18:10:11 +08:00
6f07ec52ad Update crontab.py 2025-09-11 18:09:59 +08:00
daecb76f8e Update crontab.py 2025-09-11 18:00:01 +08:00
7f653d900d Update crontab.py 2025-09-11 17:27:46 +08:00
4cd3e682b9 Update crontab.py 2025-09-11 17:27:37 +08:00
143cceeade Update crontab.py 2025-09-11 17:26:12 +08:00
fb8ca67ac1 Update crontab.py 2025-09-11 17:25:36 +08:00
80fc1c4112 Update tool_cron.py 2025-09-11 17:23:48 +08:00
eecdeb0af4 update 2025-09-11 17:22:58 +08:00
5e9e11694d Update crontab.py 2025-09-11 17:11:14 +08:00
bb41f89d44 update 2025-09-11 17:10:08 +08:00
4158f25b35 Update crontab.py 2025-09-11 17:06:51 +08:00
3694cd0694 Update mw.py 2025-09-11 16:52:47 +08:00
a5a06fbaab Update mw.py 2025-09-11 16:49:01 +08:00
a5ee38d4fd Update mw.py 2025-09-11 16:45:30 +08:00
eca95c36dd Update mw.py 2025-09-11 16:41:09 +08:00
554b4047b9 update 2025-09-11 16:38:30 +08:00
b1e8b4eb11 Update mw.py 2025-09-11 16:36:23 +08:00
b3f693556c Update mw.py 2025-09-11 16:36:05 +08:00
e2fd50d152 Update mw.py 2025-09-11 16:31:43 +08:00
f1cb9a824d Update install.sh 2025-09-11 16:07:00 +08:00
da0e718276 up 2025-09-11 15:07:55 +08:00
4519a4175b Update install.sh 2025-09-11 15:03:17 +08:00
4fa375f4f4 Update install.sh 2025-09-11 15:02:42 +08:00
3ca5fdb082 Update openssl.sh 2025-09-11 15:00:41 +08:00
32ae726050 update 2025-09-11 15:00:28 +08:00
83950cbecb Update install.sh 2025-09-11 14:59:08 +08:00
5b9f63bc91 Update install.sh 2025-09-11 14:57:48 +08:00
7b93072093 Update install.sh 2025-09-11 14:56:08 +08:00
90c312ea5c Update install.sh 2025-09-11 14:54:54 +08:00
2bec38d85f Update install.sh 2025-09-11 14:52:49 +08:00
b8ab1780d3 Update install.sh 2025-09-11 14:51:57 +08:00
997ad34151 Update install.sh 2025-09-11 14:50:06 +08:00
e960d4f00b update 2025-09-11 14:40:36 +08:00
52fe9e2c13 Update openssl_30.sh 2025-09-11 14:35:43 +08:00
e6b386dabf Update mw.py 2025-09-11 12:38:47 +08:00
f558095a0e Update index.py 2025-09-10 23:52:55 +08:00
014a604c86 Update index.py 2025-09-10 23:49:47 +08:00
5e7f2f0d5a Update index.py 2025-09-10 23:49:33 +08:00
11b52cb212 Update install.sh 2025-09-10 23:28:01 +08:00
aa7abab742 Update install.sh 2025-09-10 23:20:08 +08:00
f5ce6e47e2 Update install.sh 2025-09-10 23:06:29 +08:00
05258e6fce Update install.sh 2025-09-10 23:05:02 +08:00
7675ead837 Update install.sh 2025-09-10 23:04:36 +08:00
6e80a19933 Update install.sh 2025-09-10 23:04:15 +08:00
3a6cf05647 Update install.sh 2025-09-10 23:01:21 +08:00
147cd32129 Update crontab.py 2025-09-10 22:54:23 +08:00
9789117759 Update install.sh 2025-09-10 22:31:31 +08:00
aeee5658d3 Update install.sh 2025-09-10 22:29:00 +08:00
949ac2de98 Update install.sh 2025-09-10 22:17:25 +08:00
5b4333dacf Update install.sh 2025-09-10 22:16:46 +08:00
561cd7111e Update install.sh 2025-09-10 22:14:21 +08:00
784ee84fb3 Update install.sh 2025-09-10 22:12:20 +08:00
b0cf548775 Update install.sh 2025-09-10 22:08:35 +08:00
Mr Chen
55c315eb98 Merge pull request #815 from midoks/dev
禁止root登陆 功能添加
2025-09-10 22:05:00 +08:00
9bcb41ab5d Update firewall.py 2025-09-10 22:02:57 +08:00
007b1bd21b Update firewall.py 2025-09-10 22:02:50 +08:00
9dae7988fd Update firewall.py 2025-09-10 22:00:51 +08:00
8877d7ea55 Update firewall.py 2025-09-10 21:58:08 +08:00
f35a23a53d Update firewall.py 2025-09-10 21:56:10 +08:00
64484ef18b Update firewall.py 2025-09-10 21:53:39 +08:00
0d9381b528 Update firewall.py 2025-09-10 21:52:12 +08:00
d57465d067 Update firewall.py 2025-09-10 21:50:33 +08:00
5039dac045 Update firewall.py 2025-09-10 21:45:43 +08:00
6073357bb6 Update firewall.js 2025-09-10 21:44:15 +08:00
a00343d444 Update firewall.py 2025-09-10 21:38:57 +08:00
a0b4681369 Update firewall.py 2025-09-10 21:38:04 +08:00
ea340f3fc2 Update firewall.py 2025-09-10 21:36:52 +08:00
db39483f97 Update firewall.py 2025-09-10 21:36:05 +08:00
e575511849 Update firewall.js 2025-09-10 21:33:36 +08:00
9dc3030c18 Update firewall.js 2025-09-10 21:30:21 +08:00
f990d7584e Update firewall.js 2025-09-10 21:29:39 +08:00
133d560e64 update 2025-09-10 21:29:03 +08:00
b3ba764d89 update 2025-09-10 21:25:41 +08:00
Mr Chen
3ff1124c30 Merge pull request #814 from midoks/dev
回收站-永久删除修复
2025-09-07 12:04:43 +08:00
da927c8f7b Update file.py 2025-09-07 12:04:13 +08:00
cb211d8ba1 回收站-永久删除修复 2025-09-07 12:02:37 +08:00
Mr Chen
9cbebbdd6a Merge pull request #813 from midoks/dev
Update crontab.py
2025-09-03 22:27:33 +08:00
8684e21da3 Update crontab.py 2025-09-03 22:24:46 +08:00
Mr Chen
3f9a90f758 Merge pull request #812 from ramondelee/patch-2
Update crontab.py
2025-09-03 22:22:19 +08:00
ramondelee
661a58b549 Update crontab.py
修复计划任务停止后重新启用不生效问题。
2025-09-03 22:09:31 +08:00
Mr Chen
a47b049dfd Merge pull request #810 from midoks/dev
Update config.json
2025-08-30 14:19:59 +08:00
58b2918ea4 Update config.json 2025-08-30 14:19:18 +08:00
Mr Chen
484b4cb280 Merge pull request #809 from midoks/dev
Update tool_migrate.py
2025-08-30 01:00:24 +08:00
a77d512bac Update tool_migrate.py 2025-08-30 00:58:57 +08:00
Mr Chen
e295354aa1 Merge pull request #808 from midoks/dev
网站统计优化
2025-08-23 01:04:03 +08:00
7aeae1e998 Update webstats_common.lua 2025-08-23 00:53:58 +08:00
9b98afd6cf Update webstats_common.lua 2025-08-23 00:53:47 +08:00
bad97971db Update webstats_common.lua 2025-08-23 00:50:28 +08:00
6f8c122503 Update webstats_common.lua 2025-08-23 00:44:21 +08:00
8b25aecb3a Update webstats_common.lua 2025-08-23 00:40:08 +08:00
400846cab4 Update webstats_common.lua 2025-08-23 00:39:52 +08:00
72708bdef0 Update index.py 2025-08-23 00:36:48 +08:00
Mr Chen
23d817d1f3 Merge pull request #807 from midoks/dev
OP防火墙修复
2025-08-22 21:38:45 +08:00
daf4086bc9 Update tool_task.py 2025-08-22 20:03:36 +08:00
ab2e9ca43e Update tool_task.py 2025-08-22 20:02:06 +08:00
222d69218a Update tool_task.py 2025-08-22 20:00:15 +08:00
ae03da927e Update init.sql 2025-08-22 19:54:49 +08:00
9cb311a6c9 Update install.sh 2025-08-22 19:07:41 +08:00
dfd665088e update 2025-08-22 18:58:01 +08:00
51afd70fff Update install.sh 2025-08-22 18:48:19 +08:00
203abc1ff9 Update files.js 2025-08-22 18:09:19 +08:00
a0487671d2 Update tool_task.py 2025-08-22 17:24:27 +08:00
88e605fc5a Update tool_task.py 2025-08-22 17:24:07 +08:00
130c390916 Update install.sh 2025-08-22 17:19:05 +08:00
93389633ba Update tool_task.py 2025-08-22 17:15:55 +08:00
53897cf779 update 2025-08-22 17:15:32 +08:00
9192ac2c81 Update tool_task.py 2025-08-22 17:14:27 +08:00
d54b8ab756 Update install.sh 2025-08-22 17:06:43 +08:00
67210ce23b Update tool_task.py 2025-08-22 17:05:01 +08:00
a89f27abb9 Update install.sh 2025-08-22 17:02:20 +08:00
37eccd8a58 Update tool_task.py 2025-08-22 17:00:16 +08:00
452fd810ac Update tool_task.py 2025-08-22 16:35:15 +08:00
Mr Chen
cd91a79578 Merge pull request #806 from midoks/dev
修复批量压缩
2025-08-22 14:17:18 +08:00
4c70fb9cfa update 2025-08-22 14:16:09 +08:00
62dcd672fe Update stats.js 2025-08-21 17:03:01 +08:00
fde40577ee Update stats.js 2025-08-21 17:02:44 +08:00
Mr Chen
963633328c Merge pull request #805 from midoks/dev
网站统计/修复下载文件
2025-08-21 16:55:51 +08:00
bddf214f91 Update install.sh 2025-08-21 16:54:51 +08:00
c7ef2eeec7 Update install.sh 2025-08-21 16:10:30 +08:00
Mr Chen
8b988a3f02 Merge pull request #804 from midoks/dev
网站统计/索引优化
2025-08-21 15:41:32 +08:00
792337ed73 update 2025-08-21 15:27:58 +08:00
d1e5f9d0a4 update 2025-08-21 15:04:39 +08:00
d202746829 Update index.py 2025-08-21 14:53:18 +08:00
72724c6014 Update db.py 2025-08-21 14:38:50 +08:00
8cdbe8a491 Update index.py 2025-08-20 12:56:50 +08:00
Mr Chen
4617161f3d Merge pull request #803 from midoks/dev
0.18.4
2025-08-19 19:48:15 +08:00
ffed4f56bf 0.18.4 2025-08-19 19:47:20 +08:00
Mr Chen
19f9390020 Merge pull request #802 from midoks/dev
Update install_dev.sh
2025-08-19 19:17:58 +08:00
10a4401259 Update install_dev.sh 2025-08-19 19:17:21 +08:00
Mr Chen
ed7ab76cd6 Merge pull request #801 from midoks/dev
update
2025-08-19 19:13:59 +08:00
ccfe1bac74 update 2025-08-19 19:13:36 +08:00
Mr Chen
0c2071bc5d Merge pull request #800 from midoks/dev
修正acme安装
2025-08-19 19:11:14 +08:00
2d503ab05a Update install.sh 2025-08-19 19:10:12 +08:00
0f204b48dd Update README.md 2025-08-19 13:59:58 +08:00
ac586267c5 update 2025-08-19 01:03:40 +08:00
897619f126 Update install.sh 2025-08-19 00:57:06 +08:00
5fef08797d Update info.json 2025-08-19 00:56:31 +08:00
b43c3a7294 Update info.json 2025-08-19 00:55:28 +08:00
423b145b7f Update install.sh 2025-08-19 00:54:47 +08:00
Mr Chen
93333a4915 Merge pull request #799 from midoks/dev
Update site.html
2025-08-19 00:28:04 +08:00
b3708abcb6 Update site.html 2025-08-19 00:27:38 +08:00
Mr Chen
f8c2580773 Merge pull request #798 from midoks/dev
站点搜索,排序优化
2025-08-19 00:22:40 +08:00
4609d5588d 站点排序优化 2025-08-19 00:21:52 +08:00
cbeb44779f Update public.js 2025-08-19 00:10:45 +08:00
7c848aa372 Update sites.py 2025-08-19 00:10:40 +08:00
015fca8145 update 2025-08-19 00:02:33 +08:00
54cc5fbad5 Update sites.py 2025-08-18 23:41:06 +08:00
66f66dd408 Update install.sh 2025-08-18 23:34:08 +08:00
Mr Chen
24de9d5988 Merge pull request #797 from midoks/dev
为国内安装优化发一个版本号
2025-08-18 23:26:38 +08:00
7dc5fdc88e 为国内安装优化发一个版本号
可以选择代理
2025-08-18 23:26:07 +08:00
Mr Chen
2f912b4ddd Merge pull request #796 from midoks/dev
update
2025-08-18 22:41:37 +08:00
0931cb9f9c update 2025-08-18 22:41:08 +08:00
bc98a80de6 Update mw.tpl 2025-08-18 22:40:32 +08:00
9e3ad237b5 Update mw.tpl 2025-08-18 22:07:38 +08:00
Mr Chen
40a6ce7aa7 Merge pull request #795 from midoks/dev
国内安装支持多个代理选择
2025-08-18 21:59:21 +08:00
85bedbf56b update 2025-08-18 21:48:27 +08:00
5575710d7e Update update_dev.sh 2025-08-18 21:25:31 +08:00
df442f7fff update 2025-08-18 21:24:45 +08:00
89e665b369 Update mw.tpl 2025-08-18 21:22:43 +08:00
42f845a7e2 Update mw.tpl 2025-08-18 21:21:17 +08:00
a226bc9fbb update 2025-08-18 21:10:20 +08:00
b2f9935abb Update mw.tpl 2025-08-18 20:57:56 +08:00
d8a22ba5ee update 2025-08-18 20:36:17 +08:00
be09821778 Update mw.tpl 2025-08-18 20:35:33 +08:00
4f0f440f2c update 2025-08-18 20:26:06 +08:00
9cd46a7f9f Update update_dev.sh 2025-08-18 20:22:49 +08:00
66c875584f Update update_dev.sh 2025-08-18 20:13:35 +08:00
f14d2fddc7 Update mw.tpl 2025-08-18 20:10:19 +08:00
fa2dda6ee4 Update README.md 2025-08-18 20:08:43 +08:00
73c8117a67 Update README.md 2025-08-18 20:07:31 +08:00
5f42e94da7 Update README.md 2025-08-18 20:05:56 +08:00
c31a95dd4b Update README.md 2025-08-18 20:03:30 +08:00
19ec0ddcb9 Update mw.tpl 2025-08-18 20:00:41 +08:00
5e24086476 Delete t.sh 2025-08-18 19:58:04 +08:00
72934000b0 Update mw.tpl 2025-08-18 19:56:48 +08:00
8a240e2c9c Update mw.tpl 2025-08-18 19:55:45 +08:00
9f081359b0 Update mw.tpl 2025-08-18 19:54:17 +08:00
679a1f0d05 Update mw.tpl 2025-08-18 19:53:43 +08:00
4533e87bef Update mw.tpl 2025-08-18 19:50:29 +08:00
47a60b41a8 up 2025-08-18 19:30:17 +08:00
b06100d0dc Update README.md 2025-08-18 19:07:07 +08:00
e5591cc59e Update install_dev.sh 2025-08-18 18:08:17 +08:00
9831216ca4 Update install_dev.sh 2025-08-18 18:03:43 +08:00
57e36c5fdb Update mw.tpl 2025-08-18 17:45:02 +08:00
35904bd79d Update install_dev.sh 2025-08-18 17:41:12 +08:00
f16a2a7fec update 2025-08-18 17:37:33 +08:00
0b4b8a62aa Update install_dev.sh 2025-08-18 17:16:29 +08:00
ca4fa30cdb Update install_dev.sh 2025-08-18 17:11:40 +08:00
90c024dfe5 Update install_dev.sh 2025-08-18 17:05:35 +08:00
e634c44797 Update install_dev.sh 2025-08-18 17:04:58 +08:00
8eea4072f6 Update install_dev.sh 2025-08-18 17:03:19 +08:00
a0886e1a3d Update install_dev.sh 2025-08-18 17:01:11 +08:00
b93d77c907 Update install_dev.sh 2025-08-18 16:35:00 +08:00
a148e27211 Update install_dev.sh 2025-08-18 16:33:57 +08:00
3cd9b52d2a Update install_dev.sh 2025-08-18 16:30:13 +08:00
37206916e4 Update install_dev.sh 2025-08-18 16:29:49 +08:00
d36d2fa4b4 Update install_dev.sh 2025-08-18 16:29:07 +08:00
4591c9006b Update install_dev.sh 2025-08-18 16:28:23 +08:00
5b4ceb49df Update install_dev.sh 2025-08-18 16:27:54 +08:00
ba937c1e77 update 2025-08-18 16:25:54 +08:00
2b77254322 Update install_dev.sh 2025-08-18 16:22:57 +08:00
b27cb78f62 Update install_dev.sh 2025-08-18 16:21:26 +08:00
106af5b177 Update install_dev.sh 2025-08-18 16:21:14 +08:00
4b31160670 Update install_dev.sh 2025-08-18 16:19:48 +08:00
0593be9928 Update install_dev.sh 2025-08-18 16:18:18 +08:00
6602119ee7 Update install_dev.sh 2025-08-18 16:15:57 +08:00
2943d1f1b7 Update install_dev.sh 2025-08-18 16:14:53 +08:00
485ab6793c Update install_dev.sh 2025-08-18 16:13:35 +08:00
164a450784 update 2025-08-18 16:10:14 +08:00
f12db7e55f Update install_dev.sh 2025-08-18 16:03:31 +08:00
23e000afb3 Update install_dev.sh 2025-08-18 15:57:38 +08:00
5c77dd91e7 Update nosql_mongodb.py 2025-08-17 17:25:34 +08:00
1c4140daec Update nginx.conf 2025-08-11 17:48:18 +08:00
ad1035547d Update nginx.conf 2025-08-11 17:48:01 +08:00
e61be60f71 Update linux.conf 2025-08-11 17:11:38 +08:00
9d6db1e847 Update nginx.conf 2025-08-11 17:06:29 +08:00
Mr Chen
76a417fee7 Merge pull request #794 from midoks/dev
数据展示插件及修复计划任务列表
2025-08-03 11:48:32 +08:00
9e836148bb Update crontab.js 2025-08-03 11:44:35 +08:00
8d32e404e7 Update crontab.js 2025-08-03 11:28:46 +08:00
fb3b0f0ae6 Update crontab.js 2025-08-03 11:21:50 +08:00
6ad415fa5a Update index.py 2025-08-02 19:48:28 +08:00
79d2cc26b0 Update index.py 2025-08-02 19:47:36 +08:00
df0ad48348 Update prometheus.js 2025-08-02 19:45:50 +08:00
b1024d1da1 Update index.html 2025-08-02 19:45:15 +08:00
5db1ad1535 Update index.py 2025-08-02 19:44:26 +08:00
b45fef8b0b Update prometheus.service.tpl 2025-08-02 19:42:44 +08:00
22d4a9a809 update 2025-08-02 19:37:00 +08:00
0478356ea5 pdate 2025-08-02 19:34:25 +08:00
45e35c4396 Update linux.sh 2025-08-02 19:27:59 +08:00
eb5079a5ef Update linux.sh 2025-08-02 19:26:38 +08:00
a62e01e02e Update install.sh 2025-08-02 19:24:35 +08:00
c58db08e5f update 2025-08-02 19:23:00 +08:00
6476fe1d2c Update linux.sh 2025-08-02 19:22:30 +08:00
8ea34d5736 prometheus 2025-08-02 19:22:14 +08:00
4d4f43fa93 Update info.json 2025-08-02 19:07:39 +08:00
3e7b2ee6c1 Update promtail-config.yaml 2025-08-02 17:02:52 +08:00
0d16d3abf1 Update loki-config.yaml 2025-08-02 16:35:42 +08:00
3923ea9dd6 Update promtail-config.yaml 2025-08-02 15:19:37 +08:00
e1292620c7 update 2025-08-02 15:08:50 +08:00
4e2b2e1f54 Update promtail-config.yaml 2025-08-02 15:02:00 +08:00
fcf75b652c update 2025-08-02 14:57:53 +08:00
9765b51969 Update linux.sh 2025-08-02 14:52:48 +08:00
0769183f61 Update linux.sh 2025-08-02 14:52:39 +08:00
845cc1a2ef Update linux.sh 2025-08-02 14:49:03 +08:00
16a95c12b4 Update linux.sh 2025-08-02 14:45:04 +08:00
0516aeb94f Update linux.sh 2025-08-02 14:43:19 +08:00
6b92ecebf9 Update linux.sh 2025-08-02 14:37:48 +08:00
9010c71051 Update linux.sh 2025-08-02 14:35:53 +08:00
fcca331224 Update index.py 2025-08-02 14:32:26 +08:00
e3a2f76f78 Update promtail.service.tpl 2025-08-02 14:25:27 +08:00
7e221454a3 update 2025-08-02 14:24:40 +08:00
ebecffca03 Update linux.sh 2025-08-02 14:14:07 +08:00
42f99fd7a2 update 2025-08-02 14:05:46 +08:00
b31ab0ae16 update 2025-08-02 13:56:29 +08:00
bec041aa01 Update linux.sh 2025-08-02 13:53:37 +08:00
8ded811295 Update linux.sh 2025-08-02 13:51:17 +08:00
f1c0b9f1ed update 2025-08-02 13:49:07 +08:00
d32a371b3a Create loki-config.bak.yaml 2025-08-02 13:45:15 +08:00
c0860cd275 update 2025-08-02 13:34:50 +08:00
bfd125fc4f Update loki.service.tpl 2025-08-02 13:30:02 +08:00
a115ab28ba Update loki-config.yaml 2025-08-02 13:29:42 +08:00
d21b126401 update 2025-08-02 13:24:10 +08:00
410bf03682 Update loki.service.tpl 2025-08-02 13:21:35 +08:00
0a9f3de5c3 Update index.py 2025-08-02 13:18:47 +08:00
0ecadb918b Update index.py 2025-08-02 13:16:43 +08:00
e90b055f12 Update loki.service.tpl 2025-08-02 13:14:13 +08:00
02877dc23c Update index.py 2025-08-02 12:40:08 +08:00
e22439af4c update 2025-08-02 12:33:11 +08:00
298c777971 update 2025-08-02 12:31:35 +08:00
39cf12f51a Update linux.sh 2025-08-02 11:30:40 +08:00
276bc480cf Update install.sh 2025-08-02 11:10:43 +08:00
f0b2820034 Update linux.sh 2025-08-02 11:08:32 +08:00
ba65103df4 Update index.py 2025-08-02 11:07:08 +08:00
ae64b70f10 Update linux.sh 2025-08-02 11:04:01 +08:00
56ea2dd6f4 Update linux.sh 2025-08-02 11:02:31 +08:00
1633b9fca7 Update install.sh 2025-08-02 00:04:26 +08:00
cb7a79953f update 2025-08-01 23:33:43 +08:00
5c12d9d6a6 Update install.sh 2025-08-01 19:30:28 +08:00
244ae40969 update 2025-08-01 19:27:48 +08:00
e2b7fec286 Update install.sh 2025-08-01 19:20:39 +08:00
4cc2bc16c0 Update grafana.js 2025-08-01 19:19:29 +08:00
24a4872058 Update index.py 2025-08-01 19:18:20 +08:00
91a9788706 update 2025-08-01 19:17:14 +08:00
2a6ef8853d update 2025-08-01 19:10:26 +08:00
56358508c8 Update index.py 2025-08-01 18:57:27 +08:00
976b94464e Update index.py 2025-08-01 18:57:05 +08:00
d166a0ccfb Update index.html 2025-08-01 18:55:32 +08:00
7c5c389629 update 2025-08-01 18:54:20 +08:00
f447b527eb update 2025-08-01 18:52:52 +08:00
a251714989 Update install.sh 2025-08-01 18:50:28 +08:00
ea27f817e3 Update grafana.service.tpl 2025-08-01 18:48:58 +08:00
b6fb47fc16 update 2025-08-01 18:44:34 +08:00
fa540d516d Update install.sh 2025-08-01 18:37:17 +08:00
4b068d2a52 Update grafana.service.tpl 2025-08-01 18:34:35 +08:00
50f5289e2e Update grafana.service.tpl 2025-08-01 18:26:02 +08:00
1ba20a4ea7 Update grafana.service.tpl 2025-08-01 18:20:55 +08:00
e18067b2f0 Update index.py 2025-08-01 18:18:04 +08:00
025f19728f up 2025-08-01 18:14:54 +08:00
248496021a up 2025-08-01 18:12:07 +08:00
d56a73f0f7 Update linux.sh 2025-08-01 17:50:09 +08:00
a2b68ebce1 Update grafana.js 2025-08-01 17:27:00 +08:00
93b92f2b17 Update index.py 2025-08-01 17:26:02 +08:00
f5219bf79b Update index.py 2025-08-01 17:21:51 +08:00
cc1d99d9c9 Update index.py 2025-08-01 17:20:33 +08:00
f7101db942 Update linux.sh 2025-08-01 17:10:14 +08:00
97ae9d17bf Update linux.sh 2025-08-01 17:08:06 +08:00
a5624e7e3c Update linux.sh 2025-08-01 17:04:34 +08:00
0be42900c1 Update install.sh 2025-08-01 17:02:51 +08:00
9722e1ca64 update 2025-08-01 17:02:31 +08:00
63a20506a0 Update info.json 2025-08-01 16:58:28 +08:00
9b334e416f update 2025-08-01 16:55:54 +08:00
7805956cdf update 2025-07-30 15:33:03 +08:00
04ffd0ad45 Update install.sh 2025-07-30 15:30:51 +08:00
f6e7055c2b Update info.json 2025-07-30 13:23:05 +08:00
77167655e8 update 2025-07-30 13:22:42 +08:00
Mr Chen
24e2d0a3db Merge pull request #791 from midoks/dev
mysql强制修改密码
2025-07-27 17:20:18 +08:00
29795074fe Update index.py 2025-07-27 17:17:17 +08:00
e017675b4d Update index.py 2025-07-27 17:14:19 +08:00
74a9897deb Update index.py 2025-07-27 17:03:02 +08:00
f593e77d35 Update mysql.js 2025-07-27 17:01:36 +08:00
8b9ab7f0b8 Update mysql.js 2025-07-27 17:00:45 +08:00
02951833cc Update mysql.js 2025-07-27 16:58:53 +08:00
08e300d065 Update index.py 2025-07-27 16:56:56 +08:00
776e4c2418 Update index.py 2025-07-27 16:53:42 +08:00
cbe439815d Update index.py 2025-07-27 16:50:42 +08:00
5c43222e4f Update index.py 2025-07-27 16:49:54 +08:00
a6fe7e2fe3 Update index.py 2025-07-27 16:49:17 +08:00
6f6523836d Update index.py 2025-07-27 16:48:44 +08:00
650a57350c Update index.py 2025-07-27 16:48:25 +08:00
736b34e834 Update index.py 2025-07-27 16:45:55 +08:00
d29682fd19 Update index.py 2025-07-27 16:44:09 +08:00
59c9058426 Update index.py 2025-07-27 16:43:26 +08:00
dbd32201c5 Update index.py 2025-07-27 16:40:56 +08:00
55158a67fc Update index.py 2025-07-27 16:40:27 +08:00
49dfe99a14 Update index.py 2025-07-27 16:23:53 +08:00
165672f9fd Update index.py 2025-07-27 16:22:51 +08:00
3bf03aa0b2 Update index.py 2025-07-27 16:20:49 +08:00
8ccbe8e7a6 Update index.py 2025-07-27 16:17:02 +08:00
1d54f90c95 Update index.py 2025-07-27 16:11:56 +08:00
000de62093 Update index.py 2025-07-27 16:09:05 +08:00
7ed82a796a Update install.sh 2025-07-27 16:07:50 +08:00
4ad7e4c3f3 Update index.py 2025-07-27 16:07:41 +08:00
e1c17d8926 update 2025-07-27 15:58:59 +08:00
47cc40d0dd Update index.py 2025-07-27 15:56:34 +08:00
1a66d91885 Update mysql.js 2025-07-27 15:56:27 +08:00
01fbe11831 Update orm.py 2025-07-27 15:41:28 +08:00
d834965d79 Update orm.py 2025-07-27 15:37:30 +08:00
b6eeb79500 Update README.md 2025-07-25 11:56:51 +08:00
460d6c4e02 Update manticore.conf 2025-07-23 12:47:27 +08:00
c6089bd480 Update sphinx_make.py 2025-07-23 12:44:12 +08:00
3d18d4bc6f Update manticore.conf 2025-07-23 12:41:07 +08:00
61954b820f Update manticore.conf 2025-07-23 12:40:18 +08:00
dee67c6ea2 Update index.py 2025-07-23 12:31:19 +08:00
2fdaf1d482 update 2025-07-23 12:30:24 +08:00
8af986a4c5 Update sphinx_make.py 2025-07-23 12:18:29 +08:00
c3a13b66e6 Update index.py 2025-07-23 12:13:20 +08:00
Mr Chen
78111fd408 Merge pull request #788 from midoks/dev
manticoresearch插件配置优化
2025-07-23 12:05:04 +08:00
efeaa3f0b5 Update sphinx_make.py 2025-07-23 12:04:29 +08:00
aed5e1aa63 Update index.py 2025-07-23 11:58:35 +08:00
44211065a0 Update index.py 2025-07-23 11:55:05 +08:00
364d38cc05 Update install_dev.sh 2025-07-23 11:47:53 +08:00
b38bfd7ada Update index.py 2025-07-23 11:32:48 +08:00
f05efd1693 Update mw.tpl 2025-07-22 18:06:15 +08:00
c64b03135c Update alpine.sh 2025-07-22 17:56:07 +08:00
860a50f025 Update update.sh 2025-07-22 17:54:47 +08:00
5e9706ca23 Update install.sh 2025-07-22 17:54:35 +08:00
d3d23fe7b9 Update alpine.sh 2025-07-22 17:54:10 +08:00
af2aa2e083 Update alpine.sh 2025-07-22 17:44:34 +08:00
bb52b17a12 Update alpine.sh 2025-07-22 17:37:01 +08:00
17c68cb9b7 Update alpine.sh 2025-07-22 17:36:31 +08:00
5c3fe16e9c Update install_dev.sh 2025-07-22 17:30:21 +08:00
81ce4e3445 Update alpine.sh 2025-07-22 17:27:45 +08:00
9aaa5174bb Update update_dev.sh 2025-07-22 17:23:55 +08:00
8d9c89d281 update 2025-07-22 17:20:56 +08:00
Mr Chen
62fa42f1ba Merge pull request #787 from midoks/dev
manticoresearch状态修复
2025-07-22 00:35:59 +08:00
502cb1595f Update index.py 2025-07-22 00:33:13 +08:00
c1e358e9fd Update index.py 2025-07-22 00:33:01 +08:00
7600ef1b30 Update index.html 2025-07-22 00:14:54 +08:00
b9057da526 Update index.py 2025-07-22 00:14:05 +08:00
99e143b686 up 2025-07-22 00:10:10 +08:00
Mr Chen
0414f1f4de Merge pull request #786 from midoks/dev
增加插件manticoresearch
2025-07-21 21:28:24 +08:00
80f651d17a Update index.py 2025-07-21 21:03:19 +08:00
1a373eb876 Update install.sh 2025-07-21 21:01:09 +08:00
5882b6b58e Update index.py 2025-07-21 20:49:12 +08:00
f876e56a2d Update install.sh 2025-07-21 20:34:21 +08:00
ac98ec92e4 Update tool_cron.py 2025-07-21 20:32:25 +08:00
6cf6445c01 Update index.py 2025-07-21 20:31:00 +08:00
062a6def14 Update tool_cron.py 2025-07-21 20:30:42 +08:00
282a5451f8 Update index.py 2025-07-21 20:02:08 +08:00
b410f782e6 Update sphinx_make.py 2025-07-21 19:50:36 +08:00
f4d997957c Update index.py 2025-07-21 19:46:02 +08:00
5551c7d341 Update discuz.conf 2025-07-21 19:43:28 +08:00
642e028fca Update discuz.conf 2025-07-21 19:42:54 +08:00
ffe5cd21e5 Update index.py 2025-07-21 19:41:02 +08:00
93679924f4 up 2025-07-21 19:25:59 +08:00
212e3c1066 Update sphinx_make.py 2025-07-21 19:23:18 +08:00
ebd4baa6ff Update sphinx_make.py 2025-07-21 19:23:05 +08:00
6d846144dc Update sphinx_make.py 2025-07-21 19:20:52 +08:00
e9767ee6c7 Update sphinx_make.py 2025-07-21 19:19:09 +08:00
b4a77f25f9 Update sphinx_make.py 2025-07-21 19:18:03 +08:00
08098f48a0 Update sphinx_make.py 2025-07-21 19:17:11 +08:00
478ebe95f0 Update discuz.conf 2025-07-21 19:14:27 +08:00
bc48b85478 up 2025-07-21 19:09:44 +08:00
a5f7610230 Update index.py 2025-07-21 19:06:31 +08:00
98157bbc8b Update index.py 2025-07-21 19:05:34 +08:00
4e0792b139 Update discuz.conf 2025-07-21 18:51:19 +08:00
a171970c96 Update index.py 2025-07-21 18:46:39 +08:00
38490fd462 Create discuz.conf 2025-07-21 18:45:23 +08:00
b9726cc23f Update install.sh 2025-07-21 18:16:38 +08:00
e047696fba Update info.json 2025-07-21 18:13:24 +08:00
bea5a0896a Update install.sh 2025-07-21 18:12:18 +08:00
c15ddb64e8 Update install.sh 2025-07-21 18:07:18 +08:00
e4e3cbd68e update 2025-07-21 18:04:27 +08:00
fd8b27d3f1 Update install.sh 2025-07-21 17:58:53 +08:00
497a1632c0 Update install.sh 2025-07-21 17:58:43 +08:00
5e991a9708 Update manticore.conf 2025-07-21 17:55:46 +08:00
0e49874d38 update 2025-07-21 17:55:36 +08:00
a93b99bca7 Update install.sh 2025-07-21 17:38:33 +08:00
4d541c175c Update install.sh 2025-07-21 17:37:56 +08:00
588de95004 Update install.sh 2025-07-21 17:34:06 +08:00
8850d73ea3 Update install.sh 2025-07-21 17:33:38 +08:00
feca7c7d7c Update manticore.conf 2025-07-21 17:32:22 +08:00
1507368ea7 Update index.py 2025-07-21 17:20:34 +08:00
ce74ec97fb Update index.py 2025-07-21 17:20:12 +08:00
1fd5e2c3f6 update 2025-07-21 17:19:20 +08:00
79e23fe0c7 Update index.py 2025-07-21 17:12:44 +08:00
ab0c62c73a Update index.py 2025-07-21 17:07:27 +08:00
e72de994ad up 2025-07-21 17:01:16 +08:00
364a84cc6d Update manticoresearch.js 2025-07-21 16:58:56 +08:00
40072c6423 Update index.py 2025-07-21 16:55:51 +08:00
2d56f71588 Update index.py 2025-07-21 16:55:03 +08:00
d7a8b87473 Update index.py 2025-07-21 16:51:53 +08:00
7c8c2c655c Update index.py 2025-07-21 16:50:31 +08:00
8ea870b2a7 Update index.py 2025-07-21 16:49:59 +08:00
7e1317a400 Update index.py 2025-07-21 16:49:26 +08:00
6569a4af3b Update index.py 2025-07-21 16:47:40 +08:00
31ee85a523 Update index.py 2025-07-21 16:44:48 +08:00
acf6384318 Update index.py 2025-07-21 16:44:29 +08:00
539426d585 update 2025-07-21 16:43:51 +08:00
f8401414d3 update 2025-07-21 16:41:00 +08:00
e3cbdb9420 Update index.py 2025-07-21 16:35:23 +08:00
823126dad6 update 2025-07-21 16:34:29 +08:00
6d3c8d6679 Update install.sh 2025-07-21 16:33:13 +08:00
da2ee9c6f4 update 2025-07-21 16:32:02 +08:00
0b4299d6c3 Update install.sh 2025-07-21 16:29:19 +08:00
0830419658 Update install.sh 2025-07-21 16:28:51 +08:00
85bfcd7447 manticoresearch初始化 2025-07-21 16:13:34 +08:00
729b7e0bcc Update index.py 2025-07-21 16:08:23 +08:00
4dbaf5d0f8 Update site.py 2025-07-20 23:19:38 +08:00
Mr Chen
cbad208be6 Merge pull request #785 from midoks/dev
更友好的顶级域名识别
2025-07-20 22:16:11 +08:00
f7992d8eae Update site.py 2025-07-20 22:04:02 +08:00
8c7c344ea9 update 2025-07-20 21:52:24 +08:00
Mr Chen
2a52aa61c1 Merge pull request #783 from midoks/dev
php版本更新
2025-07-20 17:05:30 +08:00
8d06bd94b8 Update xdebug.sh 2025-07-20 17:02:27 +08:00
8f53747515 Update swoole.sh 2025-07-20 17:02:16 +08:00
d7a997052d Update xhprof.sh 2025-07-20 16:30:42 +08:00
324e98b639 Update xdebug.sh 2025-07-20 16:15:20 +08:00
7aebb728f8 Update xdebug.sh 2025-07-20 16:13:04 +08:00
c386a2a57a Update xdebug.sh 2025-07-20 16:12:19 +08:00
6e5c4917d9 Update event.sh 2025-07-20 16:07:37 +08:00
d5d9ae51c5 Update all_test.sh 2025-07-20 16:04:38 +08:00
ca39f0da3a Update all_test.sh 2025-07-20 15:59:53 +08:00
41cdbb43fc Update swoole.sh 2025-07-20 15:53:41 +08:00
6f3897886e Update swoole.sh 2025-07-20 15:50:55 +08:00
6b1bfdfeca Update solr.sh 2025-07-20 15:48:49 +08:00
a07a37f256 Update solr.sh 2025-07-20 15:30:07 +08:00
896512cf3e Update imagemagick.sh 2025-07-20 15:25:30 +08:00
60602e68f5 Update mcrypt.sh 2025-07-20 15:19:47 +08:00
7066eb2632 Update memcached.sh 2025-07-20 14:35:29 +08:00
ddfdebced2 up 2025-07-20 13:52:29 +08:00
4913cc9ed6 update 2025-07-20 13:31:18 +08:00
6427bb794d Update swoole.sh 2025-07-20 12:51:15 +08:00
77bc7c85f8 Update swoole.sh 2025-07-20 12:50:46 +08:00
54a90a2e99 Update swoole.sh 2025-07-20 12:46:17 +08:00
e4a9c32caa Update all_mac.sh 2025-07-20 12:28:37 +08:00
13b9711d4a Update phplib.conf 2025-07-20 12:25:38 +08:00
af15d6a592 Update all_test.sh 2025-07-20 12:23:19 +08:00
132580ea6c Update phplib.conf 2025-07-20 12:18:45 +08:00
262ab0ab73 Update phplib.conf 2025-07-20 12:15:56 +08:00
1e19d70fa1 Update phplib.conf 2025-07-20 12:13:07 +08:00
48b8d530ca Update all_test.sh 2025-07-20 11:35:41 +08:00
1f35c5b8fa Update install.sh 2025-07-20 11:26:12 +08:00
574b87f5b5 update 2025-07-20 11:20:11 +08:00
88be69ffc7 update 2025-07-20 11:19:14 +08:00
Mr Chen
87e49e3244 Merge pull request #782 from midoks/dev
mysql 配置回退
2025-07-20 11:06:02 +08:00
4a392126cd update 2025-07-20 11:05:24 +08:00
c0489ebb44 Update info.json 2025-07-19 19:02:29 +08:00
ed65f63a37 Update index.py 2025-07-17 20:12:16 +08:00
Mr Chen
2b4ff60de0 Merge pull request #781 from midoks/dev
版本更新及细节优化
2025-07-17 18:04:06 +08:00
8069bf51ab update 2025-07-17 17:37:57 +08:00
369b53e2fd update 2025-07-17 11:19:33 +08:00
1cf0c1636b update 2025-07-17 11:15:34 +08:00
060fe39331 update 2025-07-17 11:13:19 +08:00
8bec4058e2 Update info.json 2025-07-17 11:11:13 +08:00
Mr Chen
61d30d6f77 Merge pull request #780 from midoks/dev
Update index.py
2025-07-16 15:48:56 +08:00
7daae8a129 Update index.py 2025-07-16 15:47:01 +08:00
Mr Chen
ab2c9e450e Merge pull request #779 from midoks/dev
Dev
2025-07-16 15:34:06 +08:00
24c269bf4c Update install.sh 2025-07-16 15:29:54 +08:00
8f0c8fd800 Update install.sh 2025-07-16 15:29:21 +08:00
Mr Chen
a0e29a2bc2 Merge pull request #778 from midoks/dev
0.18.2
2025-07-16 15:22:03 +08:00
94cab2e71a update 2025-07-16 15:20:50 +08:00
266b9fa5c2 up 2025-07-16 11:47:23 +08:00
Mr Chen
31de8edc4a Merge pull request #777 from midoks/dev
Update site_reflect.py
2025-07-15 18:30:26 +08:00
1e59eda9a9 Update site_reflect.py 2025-07-15 18:23:40 +08:00
Mr Chen
36c3fcb395 Merge pull request #776 from midoks/dev
计划任务兼容性问题
2025-07-13 22:06:52 +08:00
ea8f0523d5 Update crontab.py 2025-07-13 21:34:46 +08:00
71625b7c0e Update init_cron.py 2025-07-13 21:19:30 +08:00
408a62c755 update 2025-07-13 10:58:05 +08:00
Mr Chen
da4a61b716 Merge pull request #775 from midoks/dev
0.18.1
2025-07-12 20:57:46 +08:00
996c4474ec Update version.py 2025-07-12 20:55:05 +08:00
cdc05d8d98 update 2025-07-12 20:44:37 +08:00
52892ef5df Update crontab.js 2025-07-12 20:34:50 +08:00
ce0340689b Update crontab.py 2025-07-12 20:34:06 +08:00
58cdb0db95 Update crontab.py 2025-07-12 20:28:40 +08:00
c2c49d09e9 Update crontab.py 2025-07-12 20:25:14 +08:00
c9a2997cea Update backup.py 2025-07-12 20:23:43 +08:00
94aba71ae4 Update backup.py 2025-07-12 20:17:16 +08:00
b80c7bdc23 Update backup.py 2025-07-12 20:12:31 +08:00
279231c08c update 2025-07-12 20:12:17 +08:00
ef47b839ad Update crontab.py 2025-07-12 19:54:24 +08:00
ffc8ae7d04 update 2025-07-12 17:43:45 +08:00
7d8269832f up 2025-07-12 16:42:10 +08:00
6ba516f66e Update default.sql 2025-07-12 14:26:09 +08:00
53d4fcbd6d update 2025-07-12 14:21:04 +08:00
237ef10545 update 2025-07-12 14:19:01 +08:00
23650aa800 update 2025-07-12 14:13:47 +08:00
9998691524 update 2025-07-12 13:59:05 +08:00
bd61a953ad Update public.js 2025-07-12 12:45:59 +08:00
f53379829c Update public.js 2025-07-12 01:35:49 +08:00
Mr Chen
04a4faba22 Merge pull request #774 from midoks/dev
编辑细节优化
2025-07-12 01:14:08 +08:00
65d4369306 Update public.js 2025-07-12 01:10:42 +08:00
6ab650d498 Update public.js 2025-07-12 00:20:17 +08:00
Mr Chen
2a06c108ac Merge pull request #773 from midoks/dev
Update public.js
2025-07-12 00:15:29 +08:00
3bd31c55fd Update public.js 2025-07-12 00:14:03 +08:00
Mr Chen
ea2fb6d4cd Merge pull request #772 from midoks/dev
编辑文件优化
2025-07-11 23:57:12 +08:00
d4dccc8016 Update public.js 2025-07-11 23:52:50 +08:00
3cdc78af1f Update push_ad.py 2025-07-11 15:37:26 +08:00
7784f0c929 Update push_notice_msg.py 2025-07-11 15:34:42 +08:00
a399d3d04a Update push_notice_msg.py 2025-07-11 15:33:39 +08:00
d261dd8fb4 Update push_notice_msg.py 2025-07-11 15:28:57 +08:00
273f475732 up 2025-07-04 08:40:56 +08:00
Mr Chen
35cce62b9b Merge pull request #769 from midoks/dev
修复mysql8+正确关闭二进制日志
2025-07-02 23:12:34 +08:00
7b5d2820ca up 2025-07-02 23:05:45 +08:00
46374cfb2d update 2025-07-02 23:00:48 +08:00
020bfb2abc Update index.py 2025-07-02 22:58:07 +08:00
d3ab317b34 Update index.py 2025-07-02 22:57:15 +08:00
da3dd52484 Update index.py 2025-07-02 22:54:38 +08:00
9514cd9cce Update my9.0.cnf 2025-07-02 22:52:34 +08:00
654a66062a Update my9.0.cnf 2025-07-02 22:52:18 +08:00
5ac5b13f9d update 2025-06-30 12:13:21 +08:00
Mr Chen
7f39bf5c6e Merge pull request #767 from midoks/dev
Update crontab.py
2025-06-26 17:30:00 +08:00
0e07a10dcf Update crontab.py 2025-06-26 15:45:03 +08:00
Mr Chen
8cbedd00b8 Merge pull request #766 from midoks/dev
acme.sh 定时每7天强制更新
2025-06-25 23:07:56 +08:00
d9d3d3fdb4 Update init_cron.py 2025-06-25 23:06:09 +08:00
364c142f0a Update init_cron.py 2025-06-25 23:04:07 +08:00
92c0177c44 Update init_cron.py 2025-06-25 22:59:42 +08:00
6bdca8c37e Update init_cron.py 2025-06-25 22:58:43 +08:00
fcb51e727a Update __init__.py 2025-06-25 22:57:34 +08:00
4523a10898 Update __init__.py 2025-06-25 22:56:39 +08:00
4e155c8039 Update init_cron.py 2025-06-25 22:55:40 +08:00
8b9f861f30 Update init_cron.py 2025-06-25 22:54:45 +08:00
Mr Chen
3595ae6066 Merge pull request #765 from midoks/dev
mysql 9.0 兼容优化
2025-06-25 18:55:27 +08:00
351d4a0ad6 Update index.py 2025-06-25 17:26:17 +08:00
c6e6771839 Update index.py 2025-06-25 17:21:18 +08:00
fb51e0fcd1 Update index.py 2025-06-25 17:05:09 +08:00
4fbf9c345d update 2025-06-25 17:03:45 +08:00
f3557e9acf update 2025-06-25 17:01:24 +08:00
cb7367264b Update index.py 2025-06-25 16:53:15 +08:00
2fb722edbf Update index.py 2025-06-25 16:50:22 +08:00
fce1608403 Update index.py 2025-06-25 16:46:38 +08:00
c6117cb599 update 2025-06-25 16:46:21 +08:00
c68e056267 Update index.py 2025-06-25 16:44:55 +08:00
4c9924580a Update index.py 2025-06-25 16:38:37 +08:00
058b3b8d62 Update index.py 2025-06-25 16:36:27 +08:00
1eb29acf7c Update index.py 2025-06-25 16:35:16 +08:00
48ac052de8 Update index.py 2025-06-25 16:35:03 +08:00
4863ff2a19 update 2025-06-25 16:32:59 +08:00
0b0fd8ea67 Update index.py 2025-06-25 16:25:48 +08:00
Mr Chen
b8f4ed2767 Merge pull request #759 from midoks/dev
Update file.py
2025-06-16 18:44:21 +08:00
732eba7d7d Update file.py 2025-06-16 18:43:19 +08:00
Mr Chen
8b676f3c1b Merge pull request #758 from midoks/dev
Update file.py
2025-06-12 15:40:50 +08:00
960ca4deca Update file.py 2025-06-12 15:37:14 +08:00
Mr Chen
63ecec4edb Merge pull request #757 from midoks/dev
bug! 根目录解压引起所有目录权限发生变化-限制
2025-06-12 15:18:40 +08:00
c6f04aa26f Update file.py 2025-06-12 15:18:22 +08:00
8f29df66d5 Update file.py 2025-06-12 15:11:12 +08:00
2d9e62aedb Update file.py 2025-06-12 15:10:25 +08:00
eba511add2 Update file.py 2025-06-12 15:09:42 +08:00
Mr Chen
e9e38d5224 Merge pull request #756 from midoks/dev
Update setting.py
2025-06-12 13:18:59 +08:00
b131ba8b93 Update setting.py 2025-06-12 13:17:44 +08:00
Mr Chen
a12046fe93 Merge pull request #755 from midoks/dev
简单优化
2025-06-12 08:11:46 +08:00
769f065bdf update 2025-06-12 08:10:42 +08:00
81f9ee5eca Update git.tpl 2025-06-09 23:03:14 +08:00
42fb44dd15 Update backup.py 2025-06-09 19:09:50 +08:00
600bb8b516 Update site.py 2025-06-04 15:58:34 +08:00
Mr Chen
8831d91cbe Merge pull request #753 from midoks/dev
PHP GD优化
2025-06-04 15:48:29 +08:00
d7d734565c Update gd_old.sh 2025-06-04 15:45:06 +08:00
791e9bf156 Update gd_old.sh 2025-06-04 15:43:20 +08:00
284812b4e3 Update gd_old.sh 2025-06-04 15:43:05 +08:00
505d59bc77 Update install.sh 2025-06-04 12:47:52 +08:00
Mr Chen
02eda25aaf Merge pull request #751 from midoks/dev
优化
2025-05-29 19:11:46 +08:00
d19521810e Update __init__.py 2025-05-29 19:10:41 +08:00
f8d17724f9 update 2025-05-29 19:07:51 +08:00
Mr Chen
6548125747 Merge pull request #750 from midoks/dev
常规优化
2025-05-29 18:51:51 +08:00
ef375619b6 php 默认的 mysql 连接配置,可支持localhost连接 2025-05-29 18:49:17 +08:00
fe89ae1846 Update index.py 2025-05-29 18:45:55 +08:00
4ccf142917 Update push_ad.py 2025-05-27 16:38:50 +08:00
Mr Chen
89fbeb85a2 Merge pull request #749 from midoks/dev
debian ufw 规则识别有优化
2025-05-27 11:09:07 +08:00
62b3d15991 Update firewall.py 2025-05-27 11:04:38 +08:00
52a305f5cd Update firewall.py 2025-05-27 11:01:21 +08:00
Mr Chen
658305ef28 Merge pull request #748 from midoks/dev
ACME泛域名SSL申请 第二次优化
2025-05-25 20:38:09 +08:00
19295e2832 Update common.js 2025-05-25 20:37:22 +08:00
719e8165f1 Update common.js 2025-05-25 20:20:10 +08:00
Mr Chen
d5ba280654 Merge pull request #747 from midoks/dev
ACME泛域名SSL - 插件优化
2025-05-25 20:14:53 +08:00
00dc48b439 Update index.py 2025-05-25 20:11:06 +08:00
8cc87ba7a0 Update acme.sql 2025-05-25 20:04:59 +08:00
8b2f7ee188 Update common.js 2025-05-25 20:03:18 +08:00
167c551b89 Update common.js 2025-05-25 20:02:42 +08:00
b57968d106 Update common.js 2025-05-25 19:57:26 +08:00
68514b8eae Update index.py 2025-05-25 19:27:54 +08:00
88a8e35793 Update tool_cron.py 2025-05-25 19:21:34 +08:00
ec4dcb2720 Update tool_cron.py 2025-05-25 19:20:15 +08:00
f01b64edd5 Update goedge.py 2025-05-25 19:05:10 +08:00
ef0b2af84b Update tool_cron.py 2025-05-25 19:04:55 +08:00
90af2e0c3c Update install.sh 2025-05-25 01:59:46 +08:00
344393244e Update info.json 2025-05-25 01:54:21 +08:00
96c75eb2d3 php优化 2025-05-25 00:14:07 +08:00
5594cbd1a8 php优化 2025-05-25 00:09:40 +08:00
Mr Chen
cb87abf19a Merge pull request #746 from midoks/dev
Update __init__.py
2025-05-24 23:06:48 +08:00
bf21399113 Update __init__.py 2025-05-24 23:06:24 +08:00
Mr Chen
f0fc8a644b Merge pull request #745 from midoks/dev
放开子目录绑定
2025-05-24 19:32:18 +08:00
a668234f2a Update site.py 2025-05-24 19:31:35 +08:00
6e80450e37 Update __init__.py 2025-05-24 18:54:20 +08:00
5639be6713 Update monitor.py 2025-05-24 18:48:57 +08:00
d36da3dc59 Update init.py 2025-05-24 18:45:59 +08:00
e83c743908 Update __init__.py 2025-05-24 18:45:41 +08:00
3410103859 Update default.sql 2025-05-24 18:45:36 +08:00
2685d9ebec Update .gitignore 2025-05-24 18:40:56 +08:00
c5574b3d93 Update site.js 2025-05-24 15:41:30 +08:00
832d65bac8 Update default.sql 2025-05-24 15:10:00 +08:00
8394f43b3f Update default.sql 2025-05-24 15:09:46 +08:00
Mr Chen
c77ab16f3b Merge pull request #744 from midoks/dev
ssh连接优化
2025-05-24 01:16:31 +08:00
2d10a3a69e Update ssh_local.py 2025-05-24 01:05:41 +08:00
90714961eb Update ssh_local.py 2025-05-24 01:04:26 +08:00
b2586adda0 Update ssh_local.py 2025-05-24 01:03:31 +08:00
d11dbbccb7 Update ssh_local.py 2025-05-24 01:03:08 +08:00
1390afae0e Update ssh_local.py 2025-05-24 01:00:59 +08:00
3ec2d5e757 Update ssh_terminal.py 2025-05-24 00:56:16 +08:00
cc0d0407af Update ssh_terminal.py 2025-05-24 00:56:05 +08:00
1e9e437b1c update 2025-05-24 00:54:02 +08:00
eae75e24f9 Update ssh_terminal.py 2025-05-24 00:53:34 +08:00
045d672d68 Update ssh_local.py 2025-05-24 00:51:38 +08:00
caeff7de55 Update ssh_local.py 2025-05-24 00:51:29 +08:00
b2785070bc Update ssh_terminal.py 2025-05-24 00:46:53 +08:00
545dbeecca 先尝试默认端口 2025-05-24 00:44:49 +08:00
b4fa69642c Update index.py 2025-05-23 23:44:08 +08:00
f84fcc035c Update git.tpl 2025-05-23 23:43:04 +08:00
f556eb9607 Update git.tpl 2025-05-23 23:41:32 +08:00
b8aa2ffc38 Update index.py 2025-05-23 23:36:46 +08:00
2be79ead78 Update index.py 2025-05-23 23:36:12 +08:00
c900048329 update 2025-05-23 23:35:02 +08:00
b7850eaa29 Update index.py 2025-05-23 23:22:27 +08:00
ec5a5c8d15 Update index.py 2025-05-23 23:21:20 +08:00
94c51196cf Update requirements.txt 2025-05-23 23:07:23 +08:00
35c18c807f Update requirements.txt 2025-05-23 23:02:48 +08:00
da3d44fc2a Update requirements.txt 2025-05-23 23:00:34 +08:00
Mr Chen
b9b9ab9006 Merge pull request #743 from midoks/dev
mariadb数据库备份问题
2025-05-23 17:18:16 +08:00
5df23c79e7 Update backup.py 2025-05-23 15:08:00 +08:00
Mr Chen
ee4d49752d Merge pull request #741 from midoks/dev
简单优化
2025-05-19 03:18:05 +08:00
d26bf25359 Update mw.py 2025-05-19 02:40:33 +08:00
b1edc7b2fb Update site.py 2025-05-18 16:14:01 +08:00
459fb086d0 update 2025-05-18 14:12:01 +08:00
Mr Chen
7872391c54 Merge pull request #740 from midoks/dev
webhook优化
2025-05-18 11:09:20 +08:00
c2f4171ee9 update 2025-05-18 11:04:56 +08:00
9fdfa1c22f Update git.tpl 2025-05-18 10:23:23 +08:00
8ad3018fe7 Update git.tpl 2025-05-18 10:22:33 +08:00
64883aa424 update 2025-05-18 10:20:03 +08:00
6a41f68289 update 2025-05-18 09:40:10 +08:00
ffd96b03e5 Update commit.tpl 2025-05-17 21:17:50 +08:00
961dd5a56e Update index.py 2025-05-17 21:07:59 +08:00
Mr Chen
f5cb8ba23d Merge pull request #739 from midoks/dev
简单的优化
2025-05-16 23:57:46 +08:00
6bfe9ea2af Update info.json 2025-05-16 23:48:35 +08:00
134b9ce2f2 php最新版本 2025-05-16 23:44:57 +08:00
54582fb676 mysql配置优化 2025-05-16 23:31:08 +08:00
Mr Chen
2e9864be2a Merge pull request #738 from midoks/dev
面板关联优化
2025-05-16 19:08:50 +08:00
73f01522ed Update public.js 2025-05-16 19:06:48 +08:00
Mr Chen
73a67ebdd6 Merge pull request #736 from midoks/dev
文件管理-右键菜单优化
2025-05-16 04:19:14 +08:00
92c000f63e 右键菜单优化 2025-05-16 04:15:24 +08:00
665d278b52 Update index.py 2025-05-16 02:56:35 +08:00
9393775e90 Update index.py 2025-05-16 02:55:28 +08:00
Mr Chen
fe441c7afe Merge pull request #735 from midoks/dev
mysql9的同步优化
2025-05-16 02:51:06 +08:00
c865ff433b Update index.py 2025-05-16 02:49:16 +08:00
7eb729e809 Update index.py 2025-05-16 02:41:41 +08:00
Mr Chen
f667fbff55 Merge pull request #734 from midoks/dev
细节调优
2025-05-16 02:06:31 +08:00
7c6b5bb200 Update file.py 2025-05-16 02:03:52 +08:00
d00ee1a35a Update file.py 2025-05-16 02:02:20 +08:00
Mr Chen
7364e19051 Merge pull request #733 from midoks/dev
优化
2025-05-16 01:56:29 +08:00
97263ba55d Update files.js 2025-05-16 01:55:42 +08:00
a9cccbb85f Update files.js 2025-05-16 01:55:35 +08:00
Mr Chen
732bdd5a1c Merge pull request #732 from midoks/dev
支持多种压缩和解压
2025-05-16 01:48:53 +08:00
2934d8fd7d 支持多种压缩和解压
7z,tgz,zip,rar
2025-05-16 01:47:31 +08:00
992555e80e Update cmd.md 2025-05-10 14:51:54 +08:00
4a1348403a Update app.sh 2025-05-06 15:42:15 +08:00
Mr Chen
6353a4dc58 Merge pull request #731 from midoks/dev
redis/memcached版本更新
2025-05-03 10:35:45 +08:00
9e45f493c6 update 2025-05-03 10:34:03 +08:00
66fc8c43db Update info.json 2025-05-03 10:31:26 +08:00
e4761d52bc Update info.json 2025-05-03 10:29:30 +08:00
Mr Chen
893eccfa07 Merge pull request #730 from midoks/dev
PHP最新版本
2025-05-01 23:05:58 +08:00
fc3dc8276a update 2025-05-01 21:01:05 +08:00
Mr Chen
9ab5e3354d Merge pull request #729 from midoks/dev
基本优化
2025-05-01 15:32:53 +08:00
ec607798b5 Update index.py 2025-05-01 15:31:13 +08:00
b01a2d15de Update index.py 2025-05-01 15:29:14 +08:00
7e3f40cb20 系统优化加入hosts修改 2025-05-01 15:22:50 +08:00
7a38224198 Update install.sh 2025-05-01 11:56:32 +08:00
5a4f1c3cce update ad 2025-05-01 09:46:23 +08:00
f5287e42ca update 2025-05-01 09:45:57 +08:00
Mr Chen
3ec02b8ead Merge pull request #728 from midoks/dev
0.17.0升级0.18.0升级后,站点修复
2025-04-26 18:15:41 +08:00
d25e4b3093 0.17.0升级0.18.0升级后,站点修复 2025-04-26 18:14:29 +08:00
0b81a1402e Update site_reflect.py 2025-04-26 17:54:05 +08:00
891ba787e1 Update site_reflect.py 2025-04-26 17:53:40 +08:00
85a85a83e4 Update site_reflect.py 2025-04-26 02:51:09 +08:00
449b4e6882 Update site_reflect.py 2025-04-26 01:43:59 +08:00
fba98f5ed6 up 2025-04-26 00:32:43 +08:00
fda19b6103 update 2025-04-18 19:51:49 +08:00
Mr Chen
d6d2325506 Merge pull request #727 from midoks/dev
OP防火墙修复
2025-04-16 00:54:01 +08:00
d4354f1a65 update 2025-04-16 00:49:45 +08:00
7ebe82cf9c Update install.sh 2025-04-16 00:34:08 +08:00
3029f8d263 update 2025-04-15 23:49:42 +08:00
Mr Chen
00d3aaeb22 Merge pull request #726 from midoks/dev
修复mysql问题
2025-04-14 16:59:13 +08:00
a8bd5cbbeb Update index.py 2025-04-14 16:57:05 +08:00
48bcf77deb Create mysql9.2.service.tpl 2025-04-14 16:54:00 +08:00
Mr Chen
a24f3b72bd Merge pull request #725 from midoks/dev
mysql优化
2025-04-14 16:39:53 +08:00
e916e134dc update 2025-04-14 16:22:51 +08:00
b9b18b063c Update index.py 2025-04-14 16:00:22 +08:00
753460c594 Update index.py 2025-04-14 15:59:52 +08:00
e6f8e3e6e3 Update index.py 2025-04-14 15:49:30 +08:00
952c6da41c Update push_notice_msg.py 2025-04-14 15:27:19 +08:00
adb1d0b26d update 2025-04-14 15:24:30 +08:00
Mr Chen
15efadfa9e Merge pull request #723 from midoks/dev
网站统计安装优化
2025-04-13 16:05:48 +08:00
f09cc4996b Update install.sh 2025-04-13 16:04:55 +08:00
01a81156cc Create install.old.sh 2025-04-13 15:58:27 +08:00
89ee88d734 Update logs.py 2025-04-12 14:20:28 +08:00
Mr Chen
23880fdb91 Merge pull request #721 from midoks/dev
简单优化
2025-04-12 14:09:38 +08:00
10628d1c69 Update logs.py 2025-04-12 13:56:38 +08:00
897e54cb86 Update pg.py 2025-04-09 11:41:01 +08:00
85da840688 update 2025-04-08 18:21:53 +08:00
10348168eb Update install_dev.sh 2025-04-08 17:58:35 +08:00
4a2570f96a Update install.sh 2025-04-08 17:57:38 +08:00
Mr Chen
65a4635b09 Merge pull request #720 from midoks/dev
Update files.js
2025-04-05 18:29:31 +08:00
3a5264b783 Update files.js 2025-04-03 00:22:46 +08:00
Mr Chen
b5866f2a90 Merge pull request #719 from midoks/dev
mysql9.0优化
2025-04-02 16:22:02 +08:00
a35913ab78 update 2025-04-02 16:21:16 +08:00
cc27602454 Update index.py 2025-04-02 16:18:44 +08:00
8920a1132c Update index.py 2025-04-02 16:07:40 +08:00
536c76b000 Update index.py 2025-04-02 15:42:06 +08:00
d054f7f9cd Update index.py 2025-04-02 15:39:59 +08:00
Mr Chen
16bab8f0fa Merge pull request #718 from midoks/dev
mysql9.0相关优化
2025-04-02 13:01:39 +08:00
b7aa774eb7 Update index.py 2025-04-02 12:53:11 +08:00
cef521390a Update index.py 2025-04-02 12:50:50 +08:00
f4cda4ec36 Update index.py 2025-04-02 12:48:38 +08:00
628b65a569 update 2025-04-02 12:48:06 +08:00
142f0fc6c9 Update install.sh 2025-04-02 11:06:47 +08:00
fe0f3f63a2 Update index.py 2025-04-01 22:02:42 +08:00
Mr Chen
dd3f5fdb0c Merge pull request #716 from midoks/dev
修复bug(crontab)
2025-03-29 14:09:38 +08:00
Mr Chen
b7dd2fa05d Merge pull request #715 from moonlightwatch/fix/crontab_echo_name_error
fix: rename cron_name to cron_shell
2025-03-29 14:08:16 +08:00
moonlightwatch
1cf471704c fix: rename cron_name to cron_shell 2025-03-29 14:04:21 +08:00
54f8fdeec2 Update my9.2.cnf 2025-03-26 01:20:21 +08:00
7ea45e4c0a Update my9.2.cnf 2025-03-26 01:17:27 +08:00
5b93e616dc Update my9.2.cnf 2025-03-26 01:13:14 +08:00
2c4176de32 Update index.py 2025-03-26 01:07:25 +08:00
114dcea023 update 2025-03-26 00:57:45 +08:00
3c6b5f3573 update 2025-03-25 12:53:08 +08:00
Mr Chen
258b9b610f Merge pull request #713 from midoks/dev
mysql关闭/开启 二进制日志优化
2025-03-25 12:49:22 +08:00
717d2b1ad0 mariadb更新 2025-03-25 12:48:32 +08:00
3cdd7027d6 Update index.py 2025-03-25 12:45:42 +08:00
c5dc755cb6 Update index.py 2025-03-25 12:45:00 +08:00
89d13494c0 Update index.py 2025-03-25 12:43:24 +08:00
6fe6f55df8 Update info.json 2025-03-25 12:26:05 +08:00
2f38ecf505 update 2025-03-25 12:21:18 +08:00
c4ba4b4702 Create my9.2.cnf 2025-03-25 12:19:43 +08:00
eab13531d4 Update index.py 2025-03-25 12:06:48 +08:00
62d78dbed8 update 2025-03-25 11:55:05 +08:00
f5a4f1b275 ad 2025-03-24 23:40:11 +08:00
ebe761b1cf Update linux.conf 2025-03-24 11:18:01 +08:00
6e754f2f7b Update __init__.py 2025-03-24 10:38:37 +08:00
39cd3d1f4d Update init_cron.py 2025-03-24 00:06:42 +08:00
778d595e6e Update crontab.py 2025-03-23 18:24:41 +08:00
5f4622fdcd Update init_cron.py 2025-03-23 17:27:43 +08:00
9664609bbd Update init_cron.py 2025-03-23 17:14:49 +08:00
aa92699562 Update requirements.txt 2025-03-23 17:14:23 +08:00
edc45d5d3b Update mw.tpl 2025-03-23 17:03:31 +08:00
ed732232f2 Update mw.tpl 2025-03-23 16:52:14 +08:00
db04b3f98a update 2025-03-23 16:50:30 +08:00
fb7c5d9d47 update 2025-03-20 11:48:12 +08:00
7d7df74500 Update .gitignore 2025-03-20 00:14:55 +08:00
909ba46f66 Update index.py 2025-03-10 17:55:03 +08:00
df84ad25d6 Update info.json 2025-03-10 17:47:42 +08:00
178cfb17f3 Update index.py 2025-03-10 17:43:02 +08:00
fcef7ec3ca Update index.py 2025-03-08 14:47:35 +08:00
c1e758c9df Revert "Update index.py"
This reverts commit f40cfb7d25.
2025-03-08 14:46:29 +08:00
a06c98d52f Revert "Update index.py"
This reverts commit bf49153973.
2025-03-08 14:46:22 +08:00
bf49153973 Update index.py 2025-03-08 14:43:55 +08:00
dami
f40cfb7d25 Update index.py 2025-03-08 14:37:05 +08:00
dcd4527c75 update 2025-03-06 20:34:57 +08:00
Mr Chen
225ea91f43 Merge pull request #712 from midoks/dev
简单优化
2025-03-01 22:18:31 +08:00
172ca05efa Update install.sh 2025-03-01 22:17:31 +08:00
b3e2c8d9df Update index.py 2025-02-25 20:22:41 +08:00
934327052d up 2025-02-23 22:33:02 +08:00
24a94b4965 Update info.json 2025-02-23 21:59:01 +08:00
c5385541a7 Update tamper_proof_service.py 2025-02-22 10:29:16 +08:00
5be2d5eb22 Update tamper_proof_service.py 2025-02-22 10:27:23 +08:00
3688cf6145 Update tamper_proof_service.py 2025-02-22 10:18:45 +08:00
Mr Chen
1328699da0 Merge pull request #710 from jd82k/master
fix bugs
2025-02-21 17:01:13 +08:00
jd82k
1b0e42c79e Update site.py
fix bugs
2025-02-20 22:40:07 -08:00
jd82k
6ca80e3d8c Update site.js
fix bugs
2025-02-20 22:38:37 -08:00
Mr Chen
d992541a78 Merge pull request #709 from midoks/dev
openresty1.17.1安装时http3参数缺少
2025-02-19 23:43:24 +08:00
d13adc707e Update install.sh 2025-02-19 23:15:18 +08:00
90d00d0d9a Update install.sh 2025-02-19 23:11:07 +08:00
Mr Chen
fbc9685b3c Merge pull request #708 from midoks/dev
php版本升级
2025-02-18 16:13:34 +08:00
5507cfdb7b Update install.sh 2025-02-18 16:12:50 +08:00
2c8de3e7be Create imagemagick.sh 2025-02-16 10:03:47 +08:00
cbba4adb19 Update imagemagick.sh 2025-02-16 09:48:07 +08:00
b1e36d8a71 Update imagemagick.sh 2025-02-16 09:43:42 +08:00
af6403d752 Update imagemagick.sh 2025-02-16 09:42:16 +08:00
232db27a15 update 2025-02-16 09:15:45 +08:00
e04fc75be0 Update index.py 2025-02-15 22:41:49 +08:00
5fd4c84a18 Update ubuntu.sh 2025-02-15 22:26:08 +08:00
ce65fb9234 Update imagemagick.sh 2025-02-15 22:21:34 +08:00
d8d8c630a5 update 2025-02-15 22:13:39 +08:00
08558b1581 Update imagemagick.sh 2025-02-15 21:14:41 +08:00
21637f170f up 2025-02-14 23:23:58 +08:00
Mr Chen
5013ffd38d Merge pull request #707 from midoks/dev
更新说明
2025-02-13 16:40:20 +08:00
f471368d21 Update README.md 2025-02-13 16:39:51 +08:00
Mr Chen
8ddf0168fd Merge pull request #706 from midoks/dev
webhook插件修复
2025-02-12 12:46:30 +08:00
5a4ba1297f Update dashboard.py 2025-02-12 12:44:53 +08:00
0608c531ed Update dashboard.py 2025-02-12 12:41:31 +08:00
5d242de4e2 update 2025-02-12 12:12:33 +08:00
b7efc0394b update 2025-02-11 01:17:13 +08:00
Mr Chen
16681d0193 Merge pull request #704 from midoks/dev
修复插件安装版本判断
2025-02-10 17:26:53 +08:00
31ea0865d1 Update plugin.py 2025-02-10 17:23:52 +08:00
602ad3390c Update README.md 2025-02-06 15:27:41 +08:00
Mr Chen
d8891a1767 Merge pull request #702 from midoks/dev
计划任务修复
2025-02-06 00:36:56 +08:00
2400a0b353 计划任务修复 2025-02-06 00:34:24 +08:00
Mr Chen
de0248d59a Merge pull request #701 from midoks/dev
解决ufw识别问题
2025-02-05 19:31:46 +08:00
3eb72d23f8 Update firewall.py 2025-02-05 19:21:37 +08:00
c0606112b2 update 2025-02-05 19:15:10 +08:00
5decb77f1e Update ubuntu.sh 2025-02-05 18:49:38 +08:00
a04b9487f1 update 2025-02-03 03:55:05 +08:00
8835cd4ab5 Update index.py 2025-02-03 03:31:43 +08:00
b17452a949 Update index.py 2025-02-03 03:30:09 +08:00
2072eee3a4 Update index.py 2025-02-03 03:24:34 +08:00
4321c0e6b3 up 2025-02-03 03:19:31 +08:00
f1f98b2624 Update index.py 2025-02-03 03:15:26 +08:00
ec37cee26c Update index.py 2025-02-03 03:11:00 +08:00
a8adaf7e5a Update index.py 2025-02-03 03:09:21 +08:00
84c763c39e Update phplib.conf 2025-02-03 03:06:43 +08:00
33e86c4f79 Update phplib.conf 2025-02-03 03:03:51 +08:00
c00f93a1d3 Update phplib.conf 2025-02-03 03:03:43 +08:00
81100f21b4 Update index.py 2025-02-03 02:48:30 +08:00
b8a720919f Update index.py 2025-02-03 02:41:32 +08:00
cba37ae2fc Update lam.js 2025-02-03 02:34:52 +08:00
5d15cbd4ea Update index.py 2025-02-03 02:29:45 +08:00
5f87606cf7 Create config.php 2025-02-03 02:29:21 +08:00
9b22efe3d4 Update index.py 2025-02-03 02:28:13 +08:00
675c3b27aa Update info.json 2025-02-03 02:26:40 +08:00
ddd9e70d05 Update install.sh 2025-02-03 02:24:24 +08:00
30ed2049e4 Update info.json 2025-02-03 02:21:19 +08:00
b8092ed6dd Update info.json 2025-02-03 02:19:38 +08:00
c80c0962dd Update info.json 2025-02-03 02:14:16 +08:00
63c223b237 Update install.sh 2025-02-03 02:13:02 +08:00
07aa49accc Update install.sh 2025-02-03 02:12:51 +08:00
c595c541fb lam 2025-02-03 02:09:45 +08:00
e6ec8b65ce Update index.py 2025-02-03 01:41:52 +08:00
bc8c455094 Update index.py 2025-02-03 01:39:51 +08:00
507820d25e Update index.py 2025-02-03 01:31:31 +08:00
35e08295ce Update install.sh 2025-02-03 01:28:16 +08:00
9e581d8608 update 2025-02-03 01:25:59 +08:00
dcb8e69aac Create install_debian.sh 2025-01-29 01:15:38 +08:00
617b354d03 update 2025-01-28 23:41:26 +08:00
76b095b344 Update config.php 2025-01-28 23:25:36 +08:00
Mr Chen
5ff05e8025 Merge pull request #700 from midoks/dev
网站防串改优化
2025-01-28 22:18:07 +08:00
b973a16247 Update tamper_proof_service.py 2025-01-28 22:06:29 +08:00
0cb5d7507f Update tamper_proof_py.service.tpl 2025-01-28 22:03:11 +08:00
2851ebf126 Update tamper_proof_service.py 2025-01-28 22:01:28 +08:00
2f5b1bb205 update 2025-01-28 22:01:05 +08:00
5528336698 Update tamper_proof_service.py 2025-01-28 21:52:13 +08:00
4eda80baa8 Update tamper_proof_service.py 2025-01-28 21:47:48 +08:00
02918d4bcd Update install.sh 2025-01-28 21:39:22 +08:00
8315e3ea96 Update phplib.conf 2025-01-28 17:12:43 +08:00
cae4a2ee13 update 2025-01-28 17:09:49 +08:00
26762eee73 Update phpldapadmin.js 2025-01-28 17:09:03 +08:00
2f05fb12a0 Update ico.png 2025-01-28 17:06:15 +08:00
befdf2e1d3 Update info.json 2025-01-28 16:58:42 +08:00
aac7b98913 Update phplib.conf 2025-01-28 16:55:15 +08:00
baa9b5e6bb Update phplib.conf 2025-01-28 16:52:09 +08:00
99c919811a Update phplib.conf 2025-01-28 16:51:03 +08:00
ac7a4e739e Create ldap.sh 2025-01-28 16:49:26 +08:00
f8936aa7bc Update install.sh 2025-01-28 16:44:36 +08:00
6933c44571 Update index.py 2025-01-28 16:40:20 +08:00
dfb2f4b3af Update index.py 2025-01-28 16:38:19 +08:00
6601aebddf Update index.py 2025-01-28 16:36:04 +08:00
4d2ca9587d update 2025-01-28 16:35:10 +08:00
694a5ceab2 Update index.py 2025-01-28 16:25:53 +08:00
e522093f6c update 2025-01-28 16:25:04 +08:00
feefa2e90a Update install.sh 2025-01-28 16:19:13 +08:00
3709569cd8 Update install.sh 2025-01-28 16:18:51 +08:00
052b4870bf Update install.sh 2025-01-28 16:17:35 +08:00
5cb413a911 Update install.sh 2025-01-28 16:13:36 +08:00
80e77dda3f update 2025-01-28 16:12:32 +08:00
7a3d554d6c Update index.py 2025-01-28 16:09:59 +08:00
ab0fb063cf update 2025-01-28 16:08:01 +08:00
caec558bea Update install.sh 2025-01-28 15:52:04 +08:00
2d44b62fef Update install.sh 2025-01-28 15:50:54 +08:00
f9cc72ba4a update 2025-01-28 15:48:26 +08:00
f8544d0600 update 2025-01-28 15:47:37 +08:00
c96d361b4d Update install.sh 2025-01-28 15:43:27 +08:00
fa5305f332 up 2025-01-28 15:42:56 +08:00
b996bdea93 update 2025-01-28 15:37:08 +08:00
1bae6538f7 Update index.html 2025-01-28 15:36:30 +08:00
5673964de4 Update index.py 2025-01-28 15:33:41 +08:00
25623170bb update 2025-01-28 15:33:14 +08:00
2aa5739cd8 update 2025-01-28 15:31:34 +08:00
bdff56843f Update index.py 2025-01-28 15:23:45 +08:00
6e563e6d74 Update index.py 2025-01-28 15:23:30 +08:00
334a3fb6fe update 2025-01-28 15:20:20 +08:00
a1d130a674 up 2025-01-28 15:02:06 +08:00
e14f2ea247 Update index.py 2025-01-28 14:59:57 +08:00
3f478eef8e Update install.sh 2025-01-28 14:55:42 +08:00
e929274b51 up 2025-01-28 14:47:07 +08:00
526c0301f6 Update tamper_proof_service.py 2025-01-28 12:54:53 +08:00
7e7a19829d Update ubuntu.sh 2025-01-24 17:05:44 +08:00
bc3854b4c4 Update debian.sh 2025-01-24 17:05:31 +08:00
193bf20a3e Update nginx.conf 2025-01-24 16:01:40 +08:00
Mr Chen
4cc5194939 Merge pull request #698 from midoks/dev
openresty配置优化
2025-01-24 15:49:23 +08:00
46a525ae09 Update index.py 2025-01-24 15:42:51 +08:00
6d006a357e Update nginx.conf 2025-01-24 14:28:10 +08:00
fad73b0922 Update push_notice_msg.py 2025-01-17 23:06:40 +08:00
d2d2d4658e update 2025-01-14 18:39:36 +08:00
84e6ce2b48 ad 2025-01-14 18:37:58 +08:00
b91a9963e2 update 2025-01-14 15:49:03 +08:00
Mr Chen
25fcf93185 Merge pull request #697 from midoks/dev
PHP国内安装优化
2025-01-13 00:07:12 +08:00
Mr Chen
26bb2005c1 Merge pull request #696 from jyeric/patch-1
Fix: Unable to move
2025-01-12 23:58:01 +08:00
jyeric
ee58805ae9 Fix: Unable to move 2025-01-12 03:49:32 +08:00
1bfc02a892 Update install.sh 2025-01-10 23:15:01 +08:00
0c7dc4dbee up 2025-01-10 23:14:18 +08:00
42e9859ccb Update install.sh 2025-01-10 23:13:23 +08:00
bf9b6b6046 up 2025-01-10 23:12:56 +08:00
Mr Chen
c10eac5190 Merge pull request #694 from midoks/dev
rsyncd优化
2025-01-10 12:13:07 +08:00
d01ccf1208 Update rsyncd.js 2025-01-10 12:10:06 +08:00
703b9be83e Update rsyncd.js 2025-01-10 12:07:03 +08:00
e0fea93983 update 2025-01-10 12:04:30 +08:00
84ceef47cb Update index.py 2025-01-10 11:48:20 +08:00
255ed5944f Update file.py 2025-01-10 11:36:54 +08:00
Mr Chen
0dc2b635ae Merge pull request #693 from midoks/dev
rsyncd同步-接收优化2
2025-01-08 19:46:41 +08:00
ebd1cfe203 Update index.py 2025-01-08 19:45:32 +08:00
Mr Chen
43b9297476 Merge pull request #692 from midoks/dev
冲突解决
2025-01-08 15:18:39 +08:00
aa2f4a0167 Merge branch 'master' into dev 2025-01-08 15:17:30 +08:00
Mr Chen
ad31d046d4 Merge pull request #691 from midoks/dev
rsyncd同步-接收优化
2025-01-08 15:10:57 +08:00
a67ad5a7db Update rsyncd.js 2025-01-08 15:07:49 +08:00
90d4fb245a Update rsyncd.js 2025-01-08 15:06:16 +08:00
19f55fde6e Update rsyncd.js 2025-01-08 15:03:16 +08:00
227be5258e up 2025-01-08 15:01:48 +08:00
Mr Chen
913190bfeb Merge pull request #690 from midoks/dev
细节优化
2025-01-08 13:05:46 +08:00
0b0097f367 Update mw.py 2025-01-08 13:03:13 +08:00
Mr Chen
97ac8264f2 Merge pull request #689 from midoks/dev
Update monitor.html
2025-01-08 00:31:54 +08:00
d9cca6ccc9 Update monitor.html 2025-01-07 23:53:38 +08:00
Mr Chen
28d0b1fd25 Merge pull request #688 from midoks/dev
修复-错误账户登录不能反应的问题2
2025-01-07 18:52:22 +08:00
cbcfe4cb9d Update login.py 2025-01-07 18:51:03 +08:00
Mr Chen
70c14d3369 Merge pull request #687 from midoks/dev
修复-错误账户登录不能反应的问题
2025-01-07 18:44:22 +08:00
0bcf7edab5 Update login.py 2025-01-07 18:43:39 +08:00
0f410c29f7 Update login.py 2025-01-07 18:37:57 +08:00
b451a6da25 错误登录判断 2025-01-07 18:37:24 +08:00
Mr Chen
e6c7bc1544 Merge pull request #686 from midoks/dev
php openssl编译优化
2025-01-07 17:10:58 +08:00
d1ff8f1cac update 2025-01-07 17:06:45 +08:00
d967100c14 update 2025-01-07 16:25:52 +08:00
8461c20e40 update 2025-01-07 16:24:39 +08:00
Mr Chen
52924f06d2 Merge pull request #684 from midoks/dev
增加命令-修改面板ip
2025-01-07 01:38:47 +08:00
fad4e7bd7d update 2025-01-07 01:36:17 +08:00
Mr Chen
666ee1a083 Merge pull request #683 from midoks/dev
修复计划任务-每星期修改
2025-01-06 22:00:20 +08:00
8f05e47363 修复计划任务-每星期修改 2025-01-06 21:58:31 +08:00
Mr Chen
67d8abf7bf Merge pull request #682 from midoks/dev
反向代理优化
2025-01-06 11:39:43 +08:00
30842a6659 Update site.py 2025-01-06 11:34:56 +08:00
3ee500d339 Update alist.tpl 2025-01-05 21:57:31 +08:00
Mr Chen
c5ade905b0 Merge pull request #681 from midoks/dev
php mysql_xdevapi 在debian下载安装优化
2025-01-04 16:13:45 +08:00
8e6784bf21 update 2025-01-04 16:10:44 +08:00
4eacbca674 update 2025-01-04 16:09:04 +08:00
Mr Chen
149fe72324 Merge pull request #680 from midoks/dev
关于phpmyadmin无法连接高级版本的问题【已解决】
2025-01-04 13:18:37 +08:00
43f752afbc update 2025-01-04 13:01:57 +08:00
19efde1fda update 2025-01-04 13:00:43 +08:00
98f267057b Update app_start.php 2025-01-04 12:59:22 +08:00
4f98894ce4 Update app_start.php 2025-01-04 12:56:24 +08:00
8cb225779e Update app_start.php 2025-01-04 12:55:45 +08:00
57ff303c39 Update phplib.conf 2025-01-04 12:50:55 +08:00
29cae6ae6c Update phplib.conf 2025-01-04 12:50:45 +08:00
e0c761bdf0 Update index.py 2025-01-04 12:46:07 +08:00
6ee1a8dc52 Update mw.py 2025-01-04 12:41:57 +08:00
db69532dde Update openssl.sh 2025-01-04 12:12:23 +08:00
d4c47c16e4 Update all_test.sh 2025-01-04 11:56:03 +08:00
a28733521b update 2025-01-04 11:54:00 +08:00
b957595944 update 2025-01-04 11:53:20 +08:00
b985d42336 update 2025-01-04 11:48:08 +08:00
9d467a13bb Update index_php.py 2025-01-04 05:33:40 +08:00
4629d39980 Update index_php.py 2025-01-04 05:23:14 +08:00
11d245dadf Update index_php.py 2025-01-04 05:22:19 +08:00
bb72b53f19 Update openssl.sh 2025-01-04 04:57:54 +08:00
3bef89d625 update 2025-01-04 04:39:37 +08:00
792b1348c1 Update openssl.sh 2025-01-04 04:06:12 +08:00
7399cd7d45 Update install.sh 2025-01-04 03:39:54 +08:00
d6347f6d4a update 2025-01-04 03:24:04 +08:00
3b5585193f update 2025-01-04 03:22:56 +08:00
5efa218247 Update install.sh 2025-01-04 03:20:18 +08:00
e5d312dbf9 Update install.sh 2025-01-04 03:19:49 +08:00
38e1c07e0b Update install.sh 2025-01-04 02:50:14 +08:00
809c9ea237 update 2025-01-04 02:37:28 +08:00
08a41f039b Update install.sh 2025-01-04 02:27:18 +08:00
3dd14307d0 Update install.sh 2025-01-04 02:25:30 +08:00
4122c11372 Update my8.0.cnf 2025-01-04 02:02:24 +08:00
9360a9cd68 Update my8.0.cnf 2025-01-04 01:48:01 +08:00
24746dab08 update 2025-01-04 01:37:10 +08:00
8879cba15d Update install.sh 2025-01-04 01:17:39 +08:00
Mr Chen
1b38c60f57 Merge pull request #679 from midoks/dev
时区接口与phpmyadmin/mysql[Tar]优化
2025-01-04 00:35:56 +08:00
7c944b27dd update 2025-01-04 00:26:31 +08:00
523e54eeb2 Update index.py 2025-01-03 23:54:04 +08:00
7b08a3f1bc Update mysql-community.js 2025-01-03 23:49:22 +08:00
018826e1a3 Update phpmyadmin.js 2025-01-03 23:47:02 +08:00
Mr Chen
a36b0b78b3 Merge pull request #678 from midoks/dev
修复phpmysqladmin插件
2025-01-03 22:42:44 +08:00
19964d39c1 Update phpmyadmin.js 2025-01-03 22:35:36 +08:00
31fd04456b update 2025-01-03 22:21:02 +08:00
76cf2e8fa5 update 2025-01-03 22:15:01 +08:00
f6b61c935e Update index.py 2025-01-03 22:12:47 +08:00
c736a04b4f Update debian.sh 2024-12-31 00:34:08 +08:00
14432fd6f9 Update install.sh 2024-12-27 17:40:13 +08:00
Mr Chen
047d84acb5 Merge pull request #676 from midoks/dev
面板修改用户名修复
2024-12-26 19:55:51 +08:00
8de4e6a0ee Update user.py 2024-12-26 19:54:37 +08:00
90fbb0e9ac Update requirements.txt 2024-12-26 19:07:19 +08:00
041f36ba00 Update requirements.txt 2024-12-26 19:04:48 +08:00
9e6cc873cb Update update.sh 2024-12-26 18:06:46 +08:00
20a6ced7b5 Update update.sh 2024-12-26 18:04:28 +08:00
34d9682cc1 Update update.sh 2024-12-26 18:02:38 +08:00
4ac797406a Update update.sh 2024-12-26 18:00:42 +08:00
bb3cdb5d85 Update update.sh 2024-12-26 17:56:43 +08:00
Mr Chen
245923d825 Merge pull request #675 from midoks/dev
兼容问题
2024-12-25 21:25:07 +08:00
41c048594e Update files.js 2024-12-25 21:21:54 +08:00
1360d2d066 Update files.js 2024-12-25 21:19:53 +08:00
Mr Chen
6286f03432 Merge pull request #674 from midoks/dev
网站目录 选择优化
2024-12-25 16:50:45 +08:00
c7a99cc61b Update files.py 2024-12-25 16:49:31 +08:00
e4aae5147c Update files.py 2024-12-25 16:35:35 +08:00
2a2e37ca97 Update public.js 2024-12-25 16:32:40 +08:00
a1489959d1 Update site.py 2024-12-25 16:02:41 +08:00
4561e37167 Update site.py 2024-12-25 15:58:52 +08:00
9fa04c9a90 Update site.py 2024-12-25 15:58:07 +08:00
aa4951b7fc Update site.py 2024-12-25 15:53:46 +08:00
53d08c261c Update site.py 2024-12-25 15:53:30 +08:00
74058243c6 Update site.py 2024-12-25 15:40:24 +08:00
62223d53be Update php.py 2024-12-25 15:29:35 +08:00
Mr Chen
06d33758eb Merge pull request #673 from midoks/dev
低版本兼容
2024-12-25 15:04:10 +08:00
af85245b06 Update site.js 2024-12-25 14:56:40 +08:00
01d8ebbd40 update 2024-12-25 14:52:57 +08:00
1c1cd1f434 Update site.js 2024-12-25 14:51:18 +08:00
Mr Chen
aaa801964c Merge pull request #672 from midoks/dev
创建站点兼容问题
2024-12-25 13:00:32 +08:00
01b490dff1 update 2024-12-25 12:52:41 +08:00
Mr Chen
1be1441352 Merge pull request #671 from midoks/dev
防火墙ssh修改端口修复
2024-12-24 23:08:09 +08:00
0b47b56fb5 Update firewall.py 2024-12-24 23:05:46 +08:00
0a1251ad0b Update firewall.py 2024-12-24 23:05:27 +08:00
Mr Chen
a506bebc94 Merge pull request #670 from midoks/dev
防火墙添加优化
2024-12-24 22:31:27 +08:00
26147acfa0 Update firewall.html 2024-12-24 22:27:10 +08:00
Mr Chen
f1d0be9f61 Merge pull request #669 from midoks/dev
兼容问题
2024-12-24 19:54:58 +08:00
45c1e9d28c Update r3.7.txt 2024-12-24 19:52:23 +08:00
Mr Chen
df3db9e632 Merge pull request #667 from midoks/dev
修复反向代理设置问题
2024-12-24 02:45:39 +08:00
8c1e672da7 Update site.py 2024-12-24 02:44:41 +08:00
Mr Chen
4bf5e68a9d Merge pull request #666 from midoks/dev
php版本更新及备份优化
2024-12-24 02:16:49 +08:00
0d4b157b1b Update backup.py 2024-12-24 02:14:20 +08:00
5fd207c84c Update backup.py 2024-12-24 02:14:01 +08:00
6829baba67 Update install.sh 2024-12-23 21:43:22 +08:00
b9983929fc update 2024-12-23 21:42:52 +08:00
Mr Chen
d540e7497b Merge pull request #664 from midoks/dev
站点页面和计划页面登录检查
2024-12-22 18:51:31 +08:00
0e0cc248fa 站点页面和计划页面登录检查 2024-12-22 18:50:58 +08:00
bcf6808e49 Update site.py 2024-12-22 01:33:19 +08:00
e2e27765ee Update site.py 2024-12-22 01:33:08 +08:00
f3b07bda65 Update site.py 2024-12-22 01:03:56 +08:00
Mr Chen
f555f1084f Merge pull request #663 from midoks/dev
@ramondelee 专用功能
2024-12-22 00:37:20 +08:00
212be88efe Update site.js 2024-12-22 00:36:29 +08:00
c131f0ecda Update site.js 2024-12-21 23:12:03 +08:00
Mr Chen
e3afb4b481 Merge pull request #662 from midoks/dev
acme手动验证
2024-12-21 20:32:05 +08:00
ca61f70d37 gorse便捷功能 2024-12-21 20:27:51 +08:00
90850ebfa3 Update site.js 2024-12-21 18:59:46 +08:00
771a6d6e08 Update site.js 2024-12-21 18:59:06 +08:00
55a6d17bc8 Update site.py 2024-12-21 18:35:01 +08:00
649990f2e1 update 2024-12-21 18:19:58 +08:00
48468a1c2d 右键解压方法缺失 2024-12-21 17:06:08 +08:00
dd685b664d acme手动申请ssl 2024-12-21 15:10:39 +08:00
36898e3e11 update 2024-12-21 14:19:53 +08:00
737450ba6e Update ssl_acme.py 2024-12-21 14:15:35 +08:00
0f63145319 Update rhel.sh 2024-12-21 00:50:29 +08:00
6a942db113 Update ubuntu.sh 2024-12-21 00:41:42 +08:00
6119adbe2d Update debian.sh 2024-12-21 00:41:39 +08:00
c31af5cbf4 Update mw.tpl 2024-12-21 00:21:52 +08:00
784629f11b Update cli.sh 2024-12-21 00:17:28 +08:00
Mr Chen
a581b7cdef Merge pull request #659 from midoks/dev
文件大小功能优化
2024-12-20 00:02:37 +08:00
d6918621fa Update files.py 2024-12-19 23:55:16 +08:00
dc54ec241e update 2024-12-19 23:49:57 +08:00
2f94674479 Update index.py 2024-12-19 23:28:22 +08:00
10b94514a7 update 2024-12-19 23:10:55 +08:00
Mr Chen
f5eacd6016 Merge pull request #658 from midoks/dev
插件优化
2024-12-19 17:28:03 +08:00
7383317f0b Merge branch 'master' into dev 2024-12-19 17:27:20 +08:00
26fa9378f5 Update README.md 2024-12-19 17:26:57 +08:00
9f37033e5c Update plugin.py 2024-12-19 17:24:34 +08:00
dc4ff9b694 Update info.json 2024-12-19 17:12:49 +08:00
3c9dc0a127 Update info.json 2024-12-19 17:09:48 +08:00
2afbe1c6fd Merge branch 'master' into dev 2024-12-19 16:38:36 +08:00
Mr Chen
309b5b9563 Merge pull request #657 from midoks/dev
插件位置调整
2024-12-19 16:38:22 +08:00
f64f0ebf4e Update info.json 2024-12-19 16:36:55 +08:00
dd646a155b Update info.json 2024-12-19 16:36:09 +08:00
6db38826d8 update 2024-12-19 16:34:14 +08:00
a18fd9b05c Update info.json 2024-12-19 16:32:27 +08:00
611c7b7b21 update 2024-12-19 16:32:06 +08:00
3961e95a5f update 2024-12-19 16:29:44 +08:00
d6e6a53301 update 2024-12-19 16:26:32 +08:00
e500026017 Update info.json 2024-12-19 16:25:03 +08:00
84632b6296 Update info.json 2024-12-19 16:24:44 +08:00
9b79e93967 Update info.json 2024-12-19 16:22:27 +08:00
Mr Chen
88e7ad0411 Merge pull request #656 from midoks/dev
mysql 快速安装 针对ubuntu24进行优化
2024-12-19 16:15:24 +08:00
d0e96eab91 Update install.sh 2024-12-19 16:13:13 +08:00
6ac78d9eb6 Update install.sh 2024-12-19 16:06:51 +08:00
5d830ae2f8 Update install.sh 2024-12-19 16:01:52 +08:00
178f844420 Update install.sh 2024-12-19 16:01:32 +08:00
adf3df510e Update install.sh 2024-12-19 16:01:12 +08:00
f58c03c429 Update install.sh 2024-12-19 16:00:05 +08:00
15f9edc5c7 Update install.sh 2024-12-19 15:59:22 +08:00
07f77024ab update 2024-12-19 15:57:26 +08:00
5b8ff7e612 Update ubuntu.sh 2024-12-19 15:30:57 +08:00
Mr Chen
1182e7405e Merge pull request #655 from midoks/dev
mw命令添加
2024-12-19 15:25:34 +08:00
9c6d8ef8e6 Update mw.tpl 2024-12-19 15:24:05 +08:00
eb807fb205 Update mw.tpl 2024-12-19 15:22:37 +08:00
Mr Chen
0602fb5569 Merge pull request #654 from midoks/dev
代理优化2
2024-12-19 15:14:41 +08:00
1dd78c3ea1 Update site.py 2024-12-19 15:11:56 +08:00
3175de4576 Update version.py 2024-12-19 15:11:00 +08:00
dfd1f172bb Update site.py 2024-12-19 15:09:42 +08:00
Mr Chen
0f6cf01fd3 Merge pull request #653 from midoks/dev
代理配置优化
2024-12-19 15:05:36 +08:00
3e9e7922b4 Update site.py 2024-12-19 15:01:19 +08:00
eb480c8838 update 2024-12-19 14:43:59 +08:00
a9bc4fe914 Update site.py 2024-12-19 14:21:39 +08:00
3bf1573e36 Update site.py 2024-12-19 14:20:39 +08:00
de6fd60f41 Update site.py 2024-12-19 14:19:17 +08:00
cf72ebdfd8 Update site.py 2024-12-19 14:17:22 +08:00
6e44452807 Update site.py 2024-12-19 14:17:12 +08:00
88c6abb53c Update site.py 2024-12-19 14:14:13 +08:00
27fd93f590 Update site.py 2024-12-19 14:09:25 +08:00
8b391f03c2 Update site.py 2024-12-19 14:08:59 +08:00
ea3033e22a Update site.py 2024-12-19 14:07:29 +08:00
Mr Chen
c88dff350e Merge pull request #652 from midoks/dev
站点代理+跨域设置
2024-12-18 19:36:08 +03:00
73e1a312b5 Update version.py 2024-12-19 00:31:08 +08:00
28c2b6dc77 Update site.py 2024-12-19 00:29:49 +08:00
0348cc55c6 update 2024-12-19 00:13:22 +08:00
e439918e05 Update site.js 2024-12-18 23:18:25 +08:00
Mr Chen
a5a7f405b3 Merge pull request #651 from midoks/dev
代理/重定向功能修复
2024-12-18 18:03:34 +03:00
4cd620fe2b update 2024-12-18 23:01:38 +08:00
b1826a60d2 Update proxy.py 2024-12-18 22:54:46 +08:00
50ec1c59d2 设置手动代理配置 2024-12-18 22:53:02 +08:00
36d604ec49 Update site.py 2024-12-18 22:47:21 +08:00
Mr Chen
7d6407afcf Merge pull request #650 from midoks/dev
Update README.md
2024-12-18 17:43:34 +08:00
92358db548 Update README.md 2024-12-18 17:34:37 +08:00
Mr Chen
161c6a69b1 Merge pull request #649 from midoks/dev
gdrive优化
2024-12-18 16:15:07 +08:00
215e053b6d update 2024-12-18 16:10:08 +08:00
e8a99af37f Update install.sh 2024-12-18 15:50:07 +08:00
de258a2568 Update install.sh 2024-12-18 15:49:40 +08:00
728db39ab7 update 2024-12-18 14:54:35 +08:00
Mr Chen
d885870302 Merge pull request #648 from midoks/dev
监控开启设置修复
2024-12-18 14:35:25 +08:00
2c87079686 Update system.py 2024-12-18 14:34:28 +08:00
e89785c1d2 Update mw.tpl 2024-12-18 14:13:28 +08:00
38f8eff1c5 Update mw.tpl 2024-12-18 14:12:07 +08:00
077394ec99 Update mw.tpl 2024-12-18 14:11:30 +08:00
7c23f85f75 Update mw.tpl 2024-12-18 14:09:24 +08:00
Mr Chen
20c1ceab92 Merge pull request #647 from midoks/dev
valkey命令加入
2024-12-18 12:21:13 +08:00
e5585caa09 Update version.py 2024-12-18 12:20:42 +08:00
a11b49befe update 2024-12-18 12:17:36 +08:00
Mr Chen
58027e4607 Merge pull request #646 from midoks/dev
valkey插件,redis的平替
2024-12-18 02:14:54 +08:00
1285641746 Update index.py 2024-12-18 02:02:51 +08:00
843ac18d2d Update valkey.conf 2024-12-18 01:56:03 +08:00
4383a202f2 update 2024-12-18 01:55:29 +08:00
cda412f6a9 update 2024-12-18 01:39:54 +08:00
f26b84c799 Update index.py 2024-12-18 01:39:07 +08:00
2fc3fd3ef1 update 2024-12-18 01:38:22 +08:00
57d04de8a5 Update redis.js 2024-12-18 01:38:14 +08:00
3e43c22a42 valkey,redis的平替 2024-12-18 01:33:46 +08:00
ea643b58d8 update 2024-12-18 01:21:14 +08:00
d366490fe5 update 2024-12-18 01:18:45 +08:00
83093f4c85 Update plugin.py 2024-12-18 01:15:33 +08:00
Mr Chen
99fcfa5223 Merge pull request #645 from midoks/dev
面板安装脚本优化
2024-12-18 00:30:35 +08:00
f6786b367b Update sql_mysql.py 2024-12-18 00:20:40 +08:00
eb373af6ed update 2024-12-18 00:18:18 +08:00
037e7e907b Update README.md 2024-12-18 00:09:08 +08:00
80844562e9 Update README.md 2024-12-18 00:07:06 +08:00
2a935845bf Update README.md 2024-12-17 23:54:44 +08:00
Mr Chen
3acbad4606 Merge pull request #644 from midoks/dev
更改/合并mysql快速安装方式
2024-12-17 23:35:13 +08:00
1973f6a2b0 删除冗余mysql插件 2024-12-17 23:33:46 +08:00
85e6a678dd Update sql_mysql.py 2024-12-17 23:20:48 +08:00
798c52f23d Update sql_mysql.py 2024-12-17 23:18:56 +08:00
aee405f9e2 update 2024-12-17 22:49:01 +08:00
f82ff2d482 Update rhel.sh 2024-12-17 22:46:00 +08:00
d9d9721249 Update index.py 2024-12-17 22:38:37 +08:00
8ef84763c6 Update index.py 2024-12-17 22:34:35 +08:00
c4f6db4431 update 2024-12-17 22:32:12 +08:00
60a7e7f885 Update mw.tpl 2024-12-17 22:30:50 +08:00
7e3c36cd27 Update version.py 2024-12-17 22:25:48 +08:00
5304abcd00 Update my5.7.cnf 2024-12-17 22:25:00 +08:00
19d94893cb Update index.py 2024-12-17 22:10:45 +08:00
485424b5c9 Update version.py 2024-12-17 21:43:17 +08:00
a8af7bed62 Update public.js 2024-12-17 21:42:55 +08:00
f63e7df28d Update public.js 2024-12-17 21:41:58 +08:00
7e81da6741 Update version.py 2024-12-17 21:37:25 +08:00
0c8e69c252 Update public.js 2024-12-17 21:36:54 +08:00
da8881dd1e Update version.py 2024-12-17 21:25:47 +08:00
d10c0a2fb9 update 2024-12-17 21:22:40 +08:00
34ed4b2f25 Update public.js 2024-12-17 21:20:32 +08:00
a109b148f6 Update install_generic.sh 2024-12-17 21:03:11 +08:00
65c7eeb9c9 update 2024-12-17 20:58:26 +08:00
e45b9b4101 mysql极速办版优化 2024-12-17 20:48:23 +08:00
8c9bfd7e2d update 2024-12-17 18:03:18 +08:00
208e418bba Update index_mysql_apt.py 2024-12-17 17:41:59 +08:00
05278bdacb Update install_generic.sh 2024-12-17 17:38:01 +08:00
5b11b35d5d Update install_generic.sh 2024-12-17 17:31:21 +08:00
9f5844c4de Update install_generic.sh 2024-12-17 17:29:31 +08:00
ae888e6d48 Update install_generic.sh 2024-12-17 17:22:16 +08:00
f5b4af6e38 Update install_generic.sh 2024-12-17 17:20:32 +08:00
84035e0cb1 Update install_generic.sh 2024-12-17 17:18:55 +08:00
6d5c3e81c8 Update install_generic.sh 2024-12-17 17:17:48 +08:00
16db84793d update 2024-12-17 17:15:27 +08:00
8b8a63c352 update 2024-12-17 17:04:50 +08:00
698cf0d263 update 2024-12-17 17:03:45 +08:00
6385d49eeb Update install_generic.sh 2024-12-17 17:00:49 +08:00
43e69909cd update 2024-12-17 16:59:35 +08:00
aeb0f866c8 Update mysql8.4.service.tpl 2024-12-17 16:39:32 +08:00
3e5c005f25 update_dev 2024-12-17 15:50:31 +08:00
bde27382b7 Update install.sh 2024-12-17 15:40:52 +08:00
Mr Chen
c17df789de Merge pull request #643 from midoks/dev
FTP存储空间 插件 修复
2024-12-17 14:12:48 +08:00
ca6a84fec4 Update index.py 2024-12-17 13:54:26 +08:00
1c952ca4cd update 2024-12-15 04:52:14 +08:00
c2c7073cd9 Create install_debian.sh 2024-12-15 04:44:51 +08:00
Mr Chen
6c84be1a82 Merge pull request #642 from midoks/dev
相关更新
2024-12-15 04:27:12 +08:00
16c90290f9 Update index.py 2024-12-15 04:22:07 +08:00
cf707df5e0 Update install.sh 2024-12-15 04:20:40 +08:00
078f1b763b Update install.sh 2024-12-15 04:18:10 +08:00
6060faa3ac Update install.sh 2024-12-15 04:16:36 +08:00
5059157515 update 2024-12-15 04:11:42 +08:00
49924c6b2b update 2024-12-15 04:08:59 +08:00
6ff1781372 update 2024-12-15 04:01:57 +08:00
29fd4d5220 Create my9.1.cnf 2024-12-15 03:42:32 +08:00
484dc13977 Update mw.tpl 2024-12-15 03:40:59 +08:00
59fc82c788 Create mysql9.1.service.tpl 2024-12-15 03:05:47 +08:00
9a4c9154f1 update 2024-12-15 03:01:57 +08:00
9949bb2493 u 2024-12-15 02:22:12 +08:00
07fc6ac8c4 openssl 2024-12-15 02:18:32 +08:00
6a93c3e90f Update openssl_10.sh 2024-12-15 02:16:31 +08:00
7bd88335c4 Update openssl_30.sh 2024-12-15 02:02:14 +08:00
9893e3bac2 Update index.py 2024-12-15 02:00:51 +08:00
946e886799 update 2024-12-15 02:00:38 +08:00
b84301debc Update openssl_30.sh 2024-12-15 01:56:43 +08:00
cb5c95ce03 Update index.py 2024-12-15 01:49:06 +08:00
c0a7e1ddba uppdate 2024-12-15 01:42:30 +08:00
220af054bb Update index.py 2024-12-15 01:33:29 +08:00
a9634f0249 Update index.py 2024-12-15 01:32:43 +08:00
fd77048d4b Update index.py 2024-12-15 01:30:09 +08:00
40cb632c80 Create my9.1.cnf 2024-12-15 01:23:01 +08:00
2313af825e update 2024-12-15 01:21:44 +08:00
762efdaa9a Update install.sh 2024-12-15 01:19:55 +08:00
b58cafb47a Update install.sh 2024-12-15 01:18:22 +08:00
308d909e72 Update install.sh 2024-12-15 01:17:45 +08:00
c88eb37b1a Update install.sh 2024-12-14 22:16:51 +08:00
e3189d39f4 Update install.sh 2024-12-14 21:55:57 +08:00
Mr Chen
de351c7473 Merge pull request #641 from midoks/dev
修复站点备份目录未指定默认值
2024-12-14 18:40:44 +08:00
9d08b7de34 Update mw.py 2024-12-14 18:35:26 +08:00
5cf0745da0 Update file.py 2024-12-14 18:26:55 +08:00
10009b65be Update file.py 2024-12-14 18:19:31 +08:00
Mr Chen
80c1c0b8b4 Merge pull request #640 from midoks/dev
修复站点根目录未指定默认值
2024-12-14 18:08:19 +08:00
9169d8899f Update mw.py 2024-12-14 18:06:18 +08:00
5166e05dbe 修复未指定默认值 2024-12-14 18:04:47 +08:00
e6e9dcb48c update 2024-12-14 17:15:20 +08:00
Mr Chen
712550cec8 Merge pull request #639 from midoks/dev
广告变价
2024-12-14 17:13:30 +08:00
f9061088fe update 2024-12-14 17:11:46 +08:00
Mr Chen
c53390d038 Merge pull request #638 from midoks/dev
常见优化
2024-12-14 17:04:57 +08:00
6fb93b19c9 Update info.json 2024-12-14 16:50:36 +08:00
e07e8391e1 Update gdrive.js 2024-12-14 16:05:49 +08:00
ccd8c056b1 Update install.sh 2024-12-14 15:12:17 +08:00
32ee0cf14c Update install.sh 2024-12-14 15:10:54 +08:00
9a6c02dd9a Update install.sh 2024-12-14 15:10:31 +08:00
3dd77715d8 update 2024-12-14 15:09:51 +08:00
0f99cdb115 Create install.sh 2024-12-14 15:06:45 +08:00
aecd0726e5 Update info.json 2024-12-14 15:05:33 +08:00
258b3495a1 Update install.sh 2024-12-14 14:56:40 +08:00
eb52d1a79a Update install.sh 2024-12-14 14:54:22 +08:00
1ad16b2b94 Create install.sh 2024-12-14 14:51:37 +08:00
fc28136936 Update panel_tools.py 2024-12-14 13:01:31 +08:00
575f3c9ce4 update 2024-12-14 12:47:20 +08:00
7c9ca83b46 Update install.sh 2024-12-14 12:22:50 +08:00
0d6c4010ff update 2024-12-14 05:14:12 +08:00
cb6d9762d5 Update setting.py 2024-12-14 05:01:43 +08:00
a4414d2083 Update sql_mysql.py 2024-12-14 04:52:14 +08:00
5bcae1b00c Update sql_mysql.py 2024-12-14 04:51:09 +08:00
5c01f36fe7 Update sql_mysql.py 2024-12-14 04:49:44 +08:00
84b7d1123e Update sql_mysql.py 2024-12-14 04:49:21 +08:00
Mr Chen
b819f345cf Merge pull request #637 from midoks/dev
xhprof|安全入口|面板端口命令修复
2024-12-14 02:52:48 +08:00
5278116f49 update 2024-12-14 02:47:59 +08:00
af36366a89 Update panel_tools.py 2024-12-14 02:41:39 +08:00
cabba7e2d2 Update panel_tools.py 2024-12-14 02:41:29 +08:00
ef6cc77dc2 update 2024-12-14 02:40:12 +08:00
4b6de5cd9f Update panel_tools.py 2024-12-14 02:34:07 +08:00
403e35c6c5 Update app_start.php 2024-12-14 02:21:31 +08:00
e1dbdc5886 Update index.py 2024-12-14 01:02:47 +08:00
9e0a64a51f Update index.py 2024-12-14 01:01:47 +08:00
971cc3a42a Update index.py 2024-12-14 00:24:59 +08:00
1c109ee86f Update index.py 2024-12-14 00:24:36 +08:00
b84106ae70 Update index.py 2024-12-14 00:24:23 +08:00
05881be9b9 Update index.py 2024-12-14 00:23:54 +08:00
06a7b3da19 Update index.py 2024-12-14 00:20:14 +08:00
9d77f66e47 update 2024-12-14 00:19:32 +08:00
85afff4848 Update app_start.php 2024-12-13 23:36:16 +08:00
8498eaa16d Update app_start.php 2024-12-13 23:28:48 +08:00
1e78341559 Update index.py 2024-12-13 23:21:05 +08:00
e4ed5a1d19 Update app_start.php 2024-12-13 23:19:00 +08:00
7b247d1e6f Update index.py 2024-12-13 23:13:46 +08:00
f98a7298c5 update 2024-12-13 23:10:04 +08:00
8e4e9ddf62 Update index.py 2024-12-13 23:05:31 +08:00
aea7fbe385 Update public.js 2024-12-13 23:05:26 +08:00
Mr Chen
392442b7b7 Merge pull request #636 from midoks/dev
js 兼容mac文件保存命令
2024-12-13 22:29:23 +08:00
cce3102beb Update public.js 2024-12-13 22:25:35 +08:00
fdf2e3854e Update public.js 2024-12-13 22:18:20 +08:00
Mr Chen
95011544c1 Merge pull request #635 from midoks/dev
修复监控设置不生效问题
2024-12-13 21:28:59 +08:00
fc97eb1c14 Update panel_task.py 2024-12-13 20:50:03 +08:00
fc6ec859fe Update panel_task.py 2024-12-13 20:44:50 +08:00
582ea54ed5 Update panel_task.py 2024-12-13 20:34:36 +08:00
Mr Chen
6caedb5b06 Merge pull request #634 from midoks/dev
gorse安装检测
2024-12-13 03:16:47 +08:00
307135d495 Update index.py 2024-12-13 03:14:28 +08:00
f786be41e7 Update index.py 2024-12-13 03:13:13 +08:00
e18ae543ee Update index.py 2024-12-13 03:07:26 +08:00
ab606e0629 Update index.py 2024-12-13 02:32:45 +08:00
b6cda24231 Update install.sh 2024-12-13 02:20:25 +08:00
ad4714418d Update install.sh 2024-12-13 02:19:11 +08:00
986 changed files with 73161 additions and 19860 deletions

8
.gitignore vendored
View File

@@ -176,7 +176,6 @@ plugins/op_auth
plugins/l2tp
plugins/openlitespeed
plugins/tamper_proof
plugins/cryptocurrency_trade
plugins/zimg
plugins/bk_demo
plugins/mail
@@ -189,7 +188,12 @@ plugins/tidb
plugins/goedge-admin
plugins/goedge-node
plugins/goedge-happy
plugins/dztasks
/logs
/data
/plugins/flexcdn
/plugins/tools
/plugins/choose-linux-python
*.md5
/bak
*.tmp

View File

@@ -22,7 +22,6 @@
* SSH终端工具
* 面板收藏功能
* 网站子目录绑定
* 网站备份功能
* 插件方式管理
@@ -37,20 +36,21 @@ Talk is cheap, show me the code. -- linus
```
- [兼容性测试报告](/compatibility.md)
- [常用命令说明](/cmd.md) [ mw default ] [ mw update_dev ]
- [常用命令说明](/cmd.md) [ mw default ] [ mw dev ]
### 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan1.cc)
- [虚位以待](https://bbs.midoks.icu)
### 主要插件介绍
* OpenResty - 轻量级,占有内存少,并发能力强。
* PHP[53-84] - PHP是世界上最好的编程语言。
* PHP[53-85] - PHP是世界上最好的编程语言。
* MySQL - 一种关系数据库管理系统。
* MariaDB - 是MySQL的一个重要分支。
* MySQL[APT/YUM] - 一种关系数据库管理系统。
* MySQL[community] - 一种关系数据库管理系统。
* MongoDB - 一种非关系NOSQL数据库管理系统。
* PostgreSQL - 功能强大的开源数据库。
* phpMyAdmin - 著名Web端MySQL管理工具。
* Memcached - 一个高性能的分布式内存对象缓存系统。
* Redis - 一个高性能的KV数据库。
@@ -94,8 +94,6 @@ PHP[72-84]支持phpMyAdmin[5.2.1]
# AD - VPS推荐 - 🙏
- [ZZZ评测](https://www.zzzvps.com/)
| 服务商 | LOGO | 推广地址 | 优惠码 |
| ------------- |----------|-----------|-------|
| digitalvirt |[![digitalvirt](https://digitalvirt.com/templates/BlueWhite/img/logo-dark.svg)](https://digitalvirt.com/aff.php?aff=154) | https://digitalvirt.com/aff.php?aff=154 | mdserver-web |
@@ -110,28 +108,22 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.18.0
### 版本更新 0.19.0
- 重新架构面板。
- PHP84正式版。
- 加入alist插件。
- 数据管理-常用命令。
- 插件读取优化(加入缓存+定时检查状态)。
- 恢复面板书签。
- 常规更新。
- 常规优化。
### JSDelivr安装地址
### 增加在线更新支持。
- 初始安装
```
curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh | bash
bash <(curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh)
```
- 直接更新
```
curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh | bash
bash <(curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh)
```
- 卸载脚本
@@ -145,14 +137,15 @@ wget --no-check-certificate -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/m
- 初始安装
```
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | bash
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/master/scripts/install.sh | bash
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install.sh)
bash <(curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/master/scripts/install.sh)
```
- 直接更新
```
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh)
```
- 卸载脚本
@@ -167,32 +160,49 @@ wget --no-check-certificate -O uninstall.sh https://raw.githubusercontent.com/mi
- 需已经安装mdserver-web
```
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/app.sh | bash
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/app.sh)
```
### DEV使用
```
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install_dev.sh | bash
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install.sh)
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update.sh)
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install_dev.sh)
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh)
wget --no-check-certificate -O install.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install.sh && bash install.sh
wget --no-check-certificate -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/uninstall.sh && bash uninstall.sh
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh | bash
bash <(curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh)
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/install_dev.sh | bash
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/update_dev.sh | bash
bash <(curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/install.sh)
bash <(curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/update.sh)
bash <(curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/install_dev.sh)
bash <(curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/update_dev.sh)
```
### 旧版安装
### 旧版安装/更新
```
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/old/install.sh | bash
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/old/update.sh | bash
```
### 偶然问题
- 在安装/更新时,突然出现python插件pip,psutil,可尝试如下解决方案
```
cd /www/server/mdserver-web rm -rf lib
cd /www/server/mdserver-web && rm -rf lib64
cd /www/server/mdserver-web && rm -rf bin
cd /www/server/mdserver-web && rm -rf include
mw update/mw update_dev/mw dev
```
### 捐赠地址 USDT(TRC20)
TVbNgrpeGBGZVm5gTLa21ADP7RpnPFhjya

27
cli.sh
View File

@@ -19,12 +19,12 @@ fi
mw_start_task()
{
isStart=$(ps aux |grep 'panel_task.py'|grep -v grep|awk '{print $2}')
if [ "$isStart" == '' ];then
if [ "$isStart" = '' ];then
echo -e "starting mw-tasks... \c"
cd $DIR && python3 panel_task.py >> ${DIR}/logs/panel_task.log 2>&1 &
sleep 0.3
isStart=$(ps aux |grep 'panel_task.py'|grep -v grep|awk '{print $2}')
if [ "$isStart" == '' ];then
if [ "$isStart" = '' ];then
echo -e "\033[31mfailed\033[0m"
echo '------------------------------------------------------'
tail -n 20 $DIR/logs/panel_task.log
@@ -60,7 +60,7 @@ mw_start_debug(){
if [ -f ${DIR}/data/port.pl ];then
port=$(cat ${DIR}/data/port.pl)
fi
cd ${DIR}/web && gunicorn -b :${port} -k eventlet -w 1 app:app
cd ${DIR}/web && gunicorn -b :${port} -k gthread -w 1 app:app
# cd ${DIR}/web && gunicorn -b :${port} -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 app:app
}
@@ -69,7 +69,7 @@ mw_start_panel(){
if [ -f ${DIR}/data/port.pl ];then
port=$(cat ${DIR}/data/port.pl)
fi
cd ${DIR}/web && gunicorn -b :${port} -k eventlet -w 1 app:app
cd ${DIR}/web && gunicorn -b :${port} -k gthread -w 1 app:app
# cd ${DIR}/web && gunicorn -b :${port} -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 app:app
}
@@ -82,17 +82,26 @@ mw_start_bgtask(){
mw_stop()
{
PLIST=`ps -ef|grep app:app |grep -v grep|awk '{print $2}'`
for i in $PLIST
APP_LIST=`ps -ef|grep app:app |grep -v grep|awk '{print $2}'`
APP_LIST=($APP_LIST)
for p in ${APP_LIST[@]}
do
kill -9 $i > /dev/null 2>&1
kill -9 $p > /dev/null 2>&1
done
PIDS=`ps -ef|grep panel_task.py | grep -v grep |awk '{print $2}'`
for p in $PIDS
TASK_LIST=`ps -ef|grep panel_task.py | grep -v grep |awk '{print $2}'`
TASK_LIST=($TASK_LIST)
for p in ${TASK_LIST[@]}
do
kill -9 $p > /dev/null 2>&1
done
zzpids=`ps -A -o stat,ppid,pid | grep -e '^[Zz]' | awk '{print $2}'`
zzpids=($zzpids)
for p in ${zzpids[@]}
do
kill -9 ${p} > /dev/null 2>&1
done
}
case "$1" in

5
cmd.md
View File

@@ -4,11 +4,16 @@
- 面板相关命令
```
mw start | 启动面板服务器
mw stop | 停止面板服务器
mw restart | 重启面板服务器
mw default | 显示登录信息
mw db | 快捷连接MySQL
mw redis | 快捷连接Redis
mw valkey | 快捷连接valkey
mw mongodb | 快捷连接MongoDB
mw pgdb | 快捷连接PostgreSQL
mw ssh | 快捷连接ssh
----------------------------------------
mw open | 开启面板
mw close | 关闭面板

View File

@@ -80,6 +80,7 @@ def runPanelTask():
# 站点过期检查
siteEdateCheck()
# echo "True" > /www/server/mdserver-web/logs/panel_task.lock
lock_file = mw.getTriggerTaskLockFile()
try:
if os.path.exists(lock_file):
@@ -140,7 +141,9 @@ def systemTask():
from utils.system import monitor
try:
while True:
monitor.instance().run()
monitor_status = thisdb.getOption('monitor_status',type='monitor',default='open')
if monitor_status == 'open':
monitor.instance().run()
time.sleep(5)
except Exception as ex:
print('systemTask:',mw.getTracebackInfo())
@@ -181,7 +184,7 @@ def check502():
verlist = [
'52', '53', '54', '55', '56', '70',
'71', '72', '73', '74', '80', '81',
'82', '83', '84'
'82', '83', '84', '85'
]
for ver in verlist:
server_dir = mw.getServerDir()

View File

@@ -57,7 +57,9 @@ def mwcli(mw_input=0):
'(2) 停止面板服务',
'(3) 启动面板服务',
'(4) 重载面板服务',
'(5) 修改面板端口',
'(5) 修改面板IP',
'(6) 修改面板端口',
'(7) 关闭安全入口',
'(10) 查看面板默认信息',
'(11) 修改面板密码',
'(12) 修改面板用户名',
@@ -73,10 +75,12 @@ def mwcli(mw_input=0):
'(26) 关闭二次验证',
'(27) 查看防火墙信息',
'(28) 自动识别防火墙端口到面板',
'(29) 自动识别配置站点信息',
'(100) 开启PHP52显示',
'(101) 关闭PHP52显示',
'(200) 切换Linux系统软件源',
'(201) 简单速度测试',
'(202) SSH终端管理',
'(0) 取消'
]
cmd_list_num = len(cmd_list)
@@ -98,10 +102,11 @@ def mwcli(mw_input=0):
mw_input = 0
nums = [
1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15,
20, 21, 22, 23, 24, 25, 26, 27, 28,
1, 2, 3, 4, 5, 6, 7,
10, 11, 12, 13, 14, 15,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
100, 101,
200, 201
200, 201, 202
]
if not mw_input in nums:
print(raw_tip)
@@ -117,6 +122,16 @@ def mwcli(mw_input=0):
elif mw_input == 4:
os.system(INIT_CMD + " reload")
elif mw_input == 5:
in_ip = mw_input_cmd("请输入设置的面板IP:")
in_ip = in_ip.strip()
ip_text = panel_dir + '/data/iplist.txt'
if not mw.isVaildIp(in_ip):
mw.echoInfo("【"+in_ip+"】: IP不合法")
return
mw.writeFile(ip_text, in_ip)
thisdb.setOption('server_ip', in_ip)
mw.echoInfo("设置面板IP: " + in_ip)
elif mw_input == 6:
in_port = mw_input_cmd("请输入新的面板端口:")
in_port_int = int(in_port.strip())
if in_port_int < 65536 and in_port_int > 0:
@@ -128,6 +143,9 @@ def mwcli(mw_input=0):
else:
mw.echoInfo("端口范围在0-65536之间")
return
elif mw_input == 7:
thisdb.setOption('admin_path', '')
mw.echoInfo("关闭安全入口成功!")
elif mw_input == 10:
os.system(INIT_CMD + " default")
elif mw_input == 11:
@@ -205,14 +223,14 @@ def mwcli(mw_input=0):
else:
mw.echoInfo("二次验证已关闭!")
elif mw_input == 27:
cmd = 'which ufw'
cmd = 'command -v ufw'
run_cmd = False
find_cmd = mw.execShell(cmd)
if find_cmd[0].strip() != '':
run_cmd = True
os.system('ufw status')
cmd = 'which firewall-cmd'
cmd = 'command -v firewall-cmd'
find_cmd = mw.execShell(cmd)
if find_cmd[0].strip() != '':
run_cmd = True
@@ -220,9 +238,12 @@ def mwcli(mw_input=0):
if not run_cmd:
mw.echoInfo("未检测到防火墙!")
elif mw_input == 28:
from utils.firewall import Firewall as MwFirewall
MwFirewall.instance().aIF()
mw.echoInfo("执行自动识别防火墙端口到面板成功!")
elif mw_input == 29:
from utils.site_reflect import parse as MwParse
MwParse()
mw.echoInfo("自动识别配置站点信息成功!")
elif mw_input == 100:
php_conf = panel_dir + '/plugins/php/info.json'
if os.path.exists(php_conf):
@@ -240,10 +261,52 @@ def mwcli(mw_input=0):
mw.writeFile(php_conf, cont)
mw.echoInfo("执行PHP52隐藏成功!")
elif mw_input == 200:
os.system(INIT_CMD + " mirror")
os.system("bash <(curl -sSL https://linuxmirrors.cn/main.sh)")
# os.system(INIT_CMD + " mirror")
elif mw_input == 201:
os.system('curl -Lso- bench.sh | bash')
elif mw_input == 202:
package = mw.getPanelDir()+'/plugins'
dst_plugin = mw.getServerDir() + "/webssh"
if not os.path.exists(dst_plugin):
mw.echoInfo("未安装!")
exit(1)
if not package in sys.path:
sys.path.append(package)
from webssh.index import App
obj = App()
data = obj.get_server_list()
data = json.loads(data)
if data['status']:
wlist = data['data']
wlist_len = len(wlist)
if wlist_len == 0:
mw.echoInfo("SSH终端管理,数据为空!")
exit(1)
if len(sys.argv) == 4:
pos = int(sys.argv[3])
if pos >= wlist_len:
mw.echoInfo("SSH终端管理,超过限制!")
exit(1)
dst_data = wlist[pos]
tmp_host = dst_data["host"]
info = obj.get_server_by_host_data(tmp_host)
pp_info = tmp_host+"|"+info["port"]+"|"+info['username']+"|"+info['password']+""
print(pp_info)
exit(0)
mw.echoInfo("请选择:")
for x in range(wlist_len):
dst_data = wlist[x]
tag = dst_data['host']
if dst_data['ps'] != "":
tag = dst_data['ps']
print(str(x) +") " + tag)
def open_ssh_port():
@@ -283,7 +346,10 @@ def show_panel_pwd():
def show_panel_adminpath():
admin_path = thisdb.getOption('admin_path')
print('/'+admin_path)
if admin_path == '':
print('/login')
else:
print('/'+admin_path)
def set_panel_username(username=None):

View File

@@ -21,8 +21,8 @@ CREATE TABLE IF NOT EXISTS `domain` (
`dnsapi_id` TEXT,
`email` TEXT,
`remark` TEXT,
`effective_date` TEXT,
`expiration_date` TEXT,
`effective_date` TEXT default '',
`expiration_date` TEXT default '',
`error` TEXT,
`status` INTEGER default '0',
`addtime` TEXT

View File

@@ -17,8 +17,16 @@ access_key = "xxx"
# 指定用户
userId = 1
sys.path.append(os.getcwd() + "/class/core")
import mw
if sys.platform != "darwin":
os.chdir("/www/server/mdserver-web")
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
domain = sys.argv[1]
ssl_path = sys.argv[2]

View File

@@ -186,24 +186,25 @@ def initDreplace():
def apaOp(method):
file = initDreplace()
return 'ok'
current_os = mw.getOs()
if current_os == "darwin":
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
# current_os = mw.getOs()
# if current_os == "darwin":
# data = mw.execShell(file + ' ' + method)
# if data[1] == '':
# return 'ok'
# return data[1]
if current_os.startswith("freebsd"):
data = mw.execShell('service ' + getPluginName() + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
# if current_os.startswith("freebsd"):
# data = mw.execShell('service ' + getPluginName() + ' ' + method)
# if data[1] == '':
# return 'ok'
# return data[1]
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return data[1]
# data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
# if data[1] == '':
# return 'ok'
# return data[1]
def start():
@@ -600,10 +601,12 @@ def runHookDstDomain(row):
hookWriteLog('开始申请【'+domain+'】SSL证书')
cmd = "#!/bin/bash\n"
cmd += "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin:/root/.acme.sh\n"
cmd += "export PATH\n"
if mw.isAppleSystem():
user = getRunUser()
cmd += "source /Users/"+user+"/.zshrc\n"
cmd += ". /Users/"+user+"/.zshrc\n"
cmd_data = getDnsapiData(row['dnsapi_id'])
# print(cmd_data)

View File

@@ -13,7 +13,7 @@ VERSION=$2
# acme.sh --uninstall
# source /Users/xxx/.zshrc
# . /Users/xxx/.zshrc
# https://github.com/acmesh-official/acme.sh/wiki/dnsapi
# https://docs.dnspod.com/api-legacy/domains.html#get-the-domain-list
@@ -24,7 +24,7 @@ VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
. ${rootPath}/bin/activate
fi
# pip install cloudflare
@@ -47,7 +47,7 @@ Uninstall_App()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_App
else
Uninstall_App

View File

@@ -274,7 +274,7 @@ function dnsapiAdd(row){
// console.log(row);
var option_name = '';
var option_remark = '';
var option_type = 'cf';
var option_type = 'dns_cf';
var option_val = '';
var option_id = 0;
if (typeof(row) != 'undefined'){
@@ -286,7 +286,6 @@ function dnsapiAdd(row){
}
// console.log(option_name);
function renderDnsapiOption(name, val){
var vlist = {};
if (val != ''){
@@ -303,18 +302,16 @@ function dnsapiAdd(row){
}
var key = getDnsapiKey(name);
var klist = key.split(':');
// console.log(klist);
var option_html = '';
for (var i = 0; i < klist.length; i++) {
var klist_val = '';
if (klist[i] in vlist){
klist_val = vlist[klist[i]];
}
option_html += "\
<span class='tname'>"+klist[i]+"</span>\
option_html += "<span class='tname'>"+klist[i]+"</span>\
<div class='info-r'>\
<input name='"+klist[i]+"' class='bt-input-text mr5' style='width:100%;' value='"+klist_val+"' placeholder='请输入对应值' type='text'>\
</div>";
@@ -379,7 +376,6 @@ function dnsapiAdd(row){
$('select[name="type"]').html(option);
$('select[name="type"]').change(function(){
var name = $(this).val();
if (option_type == name){
renderDnsapiOption(name, option_val);
} else {
@@ -667,11 +663,24 @@ function domainAdd(row){
var rdata = $.parseJSON(data.data);
for (var i = 0; i < rdata.length; i++) {
if (option_dnsapi_id == rdata[i]['id']){
dnsapi_id_html += "<option value='"+rdata[i]['id']+"' selected>"+rdata[i]['name']+"</option>";
dnsapi_id_html += "<option value='"+rdata[i]['id']+"' val='"+rdata[i]['val']+"' selected>"+rdata[i]['name']+"</option>";
} else {
dnsapi_id_html += "<option value='"+rdata[i]['id']+"'>"+rdata[i]['name']+"</option>";
dnsapi_id_html += "<option value='"+rdata[i]['id']+"' val='"+rdata[i]['val']+"'>"+rdata[i]['name']+"</option>";
}
}
$('select[name="dnsapi_id"]').change(function(){
var val = $('select[name="dnsapi_id"]').find("option:selected").attr('val');
var val_arr = val.split("|");
for (var i = 0; i < val_arr.length; i++) {
var param = val_arr[i];
var strictEmailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(strictEmailRegex.test(param)){
$('input[name="email"]').val(param);
}
}
});
$('select[name="dnsapi_id"]').html(dnsapi_id_html);
});
},

View File

@@ -6,8 +6,18 @@ import os
import time
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
# print(sys.platform)
if sys.platform != "darwin":
os.chdir("/www/server/mdserver-web")
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
from utils.crontab import crontab as MwCrontab
app_debug = False
@@ -69,8 +79,6 @@ def createBgTaskByName(name):
if res and res["id"] == args["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
api = crontab_api.crontab_api()
mw_dir = mw.getPanelDir()
cmd = '''
@@ -99,10 +107,10 @@ logs_file=$plugin_path/${rname}.log
'stype': "toShell",
'sname': '',
'sbody': cmd,
'urladdress': '',
'url_address': '',
}
task_id = api.add(params)
task_id = MwCrontab.instance().add(params)
if task_id > 0:
args["task_id"] = task_id
args["name"] = name

View File

@@ -122,7 +122,7 @@ def openPort():
return True
def status():
cmd = "ps aux|grep alist |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
cmd = "ps -ef|grep alist |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'

View File

@@ -4,7 +4,7 @@
"name": "alist",
"title": "Alist",
"shell": "install.sh",
"versions":["3.37.4","3.38.0"],
"versions":["3.37.4","3.38.0","3.45.0"],
"tip": "soft",
"checks": "server/alist",
"path": "server/alist",

View File

@@ -23,7 +23,7 @@ app_start(){
app_stop(){
echo "dztasks stopped"
ps -ef| grep alist | grep -v grep | grep -v python | grep -v sh | awk '{print $2}'| xargs kill
ps -ef| grep alist | grep -v grep | grep -v python | grep -v sh | awk '{print $2}'| xargs kill -9
}

View File

@@ -8,7 +8,7 @@ rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/alist && bash install.sh install 3.37.4
# cd /www/server/mdserver-web/plugins/alist && bash install.sh install 3.37.4
# cd /www/server/mdserver-web/plugins/alist && bash install.sh install 3.45.0
VERSION=$2
@@ -16,16 +16,16 @@ sysArch=`arch`
sysName=`uname`
ALIST_ARCH_NAME=amd64
if [ "$sysArch" == "arm64" ];then
if [ "$sysArch" = "arm64" ];then
ALIST_ARCH_NAME=arm64
elif [ "$sysArch" == "x86_64" ]; then
elif [ "$sysArch" = "x86_64" ]; then
ALIST_ARCH_NAME=amd64
elif [ "$sysArch" == "aarch64" ]; then
elif [ "$sysArch" = "aarch64" ]; then
ALIST_ARCH_NAME=arm64
fi
ALIST_NAME=linux
if [ "$sysName" == "Darwin" ];then
if [ "$sysName" = "Darwin" ];then
ALIST_NAME=darwin
fi
@@ -41,7 +41,7 @@ Install_App()
ALIST_DIR=$serverPath/source/alist
if [ ! -f $ALIST_DIR/${FILE_TGZ} ];then
wget -O $ALIST_DIR/${FILE_TGZ} https://github.com/alist-org/alist/releases/download/v${VERSION}/${FILE_TGZ}
wget --no-check-certificate -O $ALIST_DIR/${FILE_TGZ} https://github.com/alist-org/alist/releases/download/v${VERSION}/${FILE_TGZ}
fi
mkdir -p $serverPath/alist
@@ -86,7 +86,7 @@ Uninstall_App()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_App
else
Uninstall_App

35
plugins/apache/check.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# OpenResty服务名称
service_name="openresty"
# 检查OpenResty是否正在运行
if systemctl is-active --quiet "$service_name"; then
# 检查是否存在僵尸进程
zombie_processes=$(ps -ef | grep -i openresty | grep -v grep | awk '{print $2}' | xargs ps -o state= -p 2>/dev/null | grep -c Z)
if [ "$zombie_processes" -gt 0 ]; then
echo "kill nginx 僵尸进程"
ps -ef|grep nginx| grep -v grep| awk '{print $2}' | xargs kill -9
echo "检测到OpenResty僵尸进程,正在重启服务..."
systemctl restart "$service_name"
echo "服务已重启"
else
echo "OpenResty运行正常"
fi
else
echo "kill nginx"
ps -ef|grep nginx| grep -v grep| awk '{print $2}' | xargs kill -9
echo "OpenResty未运行,正在启动服务..."
systemctl start "$service_name"
echo "服务已启动"
fi
NGINX_IDS=`ps -ef|grep nginx | grep -v grep| awk '{print $2}'`
if [ "$NGINX_IDS" = "" ];then
ps -ef|grep nginx| grep -v grep| awk '{print $2}' | xargs kill -9
systemctl start "$service_name"
echo "OpenResty未运行,正在启动服务..."
fi

View File

@@ -0,0 +1,57 @@
<IfModule !mpm_netware_module>
PidFile "logs/httpd.pid"
</IfModule>
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 250
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_worker_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_netware_module>
ThreadStackSize 65536
StartThreads 250
MinSpareThreads 25
MaxSpareThreads 250
MaxThreads 1000
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_mpmt_os2_module>
StartServers 2
MinSpareThreads 5
MaxSpareThreads 10
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_winnt_module>
ThreadsPerChild 150
MaxConnectionsPerChild 0
</IfModule>
<IfModule !mpm_netware_module>
MaxMemFree 2048
</IfModule>
<IfModule mpm_netware_module>
MaxMemFree 100
</IfModule>

View File

@@ -0,0 +1,105 @@
ServerRoot "{$SERVER_PATH}/apache/httpd"
Listen 8280
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule brotli_module modules/mod_brotli.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
<IfModule unixd_module>
User daemon
Group daemon
</IfModule>
ServerAdmin you@example.com
ServerName localhost:8280
<Directory />
AllowOverride none
Require all denied
</Directory>
DocumentRoot "{$SERVER_PATH}/apache/httpd/htdocs"
<Directory "{$SERVER_PATH}/apache/httpd/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
<Files ".ht*">
Require all denied
</Files>
ErrorLog "logs/error.log"
LogLevel warn
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
# You need to enable mod_logio.c to use %I and %O
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog "logs/access.log" common
</IfModule>
<IfModule alias_module>
ScriptAlias /cgi-bin/ "{$SERVER_PATH}/apache/httpd/cgi-bin/"
</IfModule>
<IfModule cgid_module>
</IfModule>
<Directory "{$SERVER_PATH}/apache/httpd/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule headers_module>
RequestHeader unset Proxy early
</IfModule>
<IfModule mime_module>
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
</IfModule>
EnableSendfile on
Include conf/extra/httpd-info.conf
Include conf/extra/httpd-mpm.conf
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

View File

@@ -0,0 +1,506 @@
#
# This is the main Apache HTTP server configuration file. It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
# In particular, see
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
# for a discussion of each configuration directive.
#
# Do NOT simply read the instructions in here without understanding
# what they do. They're here only as hints or reminders. If you are unsure
# consult the online docs. You have been warned.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path. If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
# will be interpreted as '/logs/access_log'.
#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path. If you point
# ServerRoot at a non-local disk, be sure to specify a local disk on the
# Mutex directive, if file-based mutexes are used. If you wish to share the
# same ServerRoot for multiple httpd daemons, you will need to change at
# least PidFile.
#
ServerRoot "/Users/midoks/Desktop/mwdev/server/apache/httpd"
#
# Mutex: Allows you to set the mutex mechanism and mutex file directory
# for individual mutexes, or change the global defaults
#
# Uncomment and change the directory if mutexes are file-based and the default
# mutex file directory is not on a local disk or is not appropriate for some
# other reason.
#
# Mutex default:logs
#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule authn_file_module modules/mod_authn_file.so
#LoadModule authn_dbm_module modules/mod_authn_dbm.so
#LoadModule authn_anon_module modules/mod_authn_anon.so
#LoadModule authn_dbd_module modules/mod_authn_dbd.so
#LoadModule authn_socache_module modules/mod_authn_socache.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
#LoadModule authz_dbm_module modules/mod_authz_dbm.so
#LoadModule authz_owner_module modules/mod_authz_owner.so
#LoadModule authz_dbd_module modules/mod_authz_dbd.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
#LoadModule auth_form_module modules/mod_auth_form.so
#LoadModule auth_digest_module modules/mod_auth_digest.so
#LoadModule allowmethods_module modules/mod_allowmethods.so
#LoadModule file_cache_module modules/mod_file_cache.so
#LoadModule cache_module modules/mod_cache.so
#LoadModule cache_disk_module modules/mod_cache_disk.so
#LoadModule cache_socache_module modules/mod_cache_socache.so
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
#LoadModule socache_dbm_module modules/mod_socache_dbm.so
#LoadModule socache_memcache_module modules/mod_socache_memcache.so
#LoadModule socache_redis_module modules/mod_socache_redis.so
#LoadModule watchdog_module modules/mod_watchdog.so
#LoadModule macro_module modules/mod_macro.so
#LoadModule dbd_module modules/mod_dbd.so
#LoadModule dumpio_module modules/mod_dumpio.so
#LoadModule buffer_module modules/mod_buffer.so
#LoadModule ratelimit_module modules/mod_ratelimit.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
#LoadModule ext_filter_module modules/mod_ext_filter.so
#LoadModule request_module modules/mod_request.so
#LoadModule include_module modules/mod_include.so
LoadModule filter_module modules/mod_filter.so
#LoadModule substitute_module modules/mod_substitute.so
#LoadModule sed_module modules/mod_sed.so
#LoadModule brotli_module modules/mod_brotli.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
#LoadModule log_debug_module modules/mod_log_debug.so
#LoadModule logio_module modules/mod_logio.so
LoadModule env_module modules/mod_env.so
#LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
#LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
#LoadModule remoteip_module modules/mod_remoteip.so
#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_connect_module modules/mod_proxy_connect.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
#LoadModule proxy_express_module modules/mod_proxy_express.so
#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
#LoadModule session_module modules/mod_session.so
#LoadModule session_cookie_module modules/mod_session_cookie.so
#LoadModule session_dbd_module modules/mod_session_dbd.so
#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
#LoadModule ssl_module modules/mod_ssl.so
#LoadModule http2_module modules/mod_http2.so
#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
LoadModule unixd_module modules/mod_unixd.so
#LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
#LoadModule info_module modules/mod_info.so
#LoadModule cgid_module modules/mod_cgid.so
#LoadModule dav_fs_module modules/mod_dav_fs.so
#LoadModule vhost_alias_module modules/mod_vhost_alias.so
#LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
#LoadModule actions_module modules/mod_actions.so
#LoadModule speling_module modules/mod_speling.so
#LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
#LoadModule rewrite_module modules/mod_rewrite.so
<IfModule unixd_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User daemon
Group daemon
</IfModule>
# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition. These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed. This address appears on some server-generated pages, such
# as error documents. e.g. admin@your-domain.com
#
ServerAdmin you@example.com
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80
#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# <Directory> blocks below.
#
<Directory />
AllowOverride none
Require all denied
</Directory>
#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#
#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/Users/midoks/Desktop/mwdev/server/apache/httpd/htdocs"
<Directory "/Users/midoks/Desktop/mwdev/server/apache/httpd/htdocs">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs/2.4/mod/core.html#options
# for more information.
#
Options Indexes FollowSymLinks
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# AllowOverride FileInfo AuthConfig Limit
#
AllowOverride None
#
# Controls who can get stuff from this server.
#
Require all granted
</Directory>
#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ".ht*">
Require all denied
</Files>
#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog "logs/error_log"
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn
<IfModule log_config_module>
#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
# You need to enable mod_logio.c to use %I and %O
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
#
# The location and format of the access logfile (Common Logfile Format).
# If you do not define any access logfiles within a <VirtualHost>
# container, they will be logged here. Contrariwise, if you *do*
# define per-<VirtualHost> access logfiles, transactions will be
# logged therein and *not* in this file.
#
CustomLog "logs/access_log" common
#
# If you prefer a logfile with access, agent, and referer information
# (Combined Logfile Format) you can use the following directive.
#
#CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
#
# Redirect: Allows you to tell clients about documents that used to
# exist in your server's namespace, but do not anymore. The client
# will make a new request for the document at its new location.
# Example:
# Redirect permanent /foo http://www.example.com/bar
#
# Alias: Maps web paths into filesystem paths and is used to
# access content that does not live under the DocumentRoot.
# Example:
# Alias /webpath /full/filesystem/path
#
# If you include a trailing / on /webpath then the server will
# require it to be present in the URL. You will also likely
# need to provide a <Directory> section to allow access to
# the filesystem path.
#
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the target directory are treated as applications and
# run by the server when requested rather than as documents sent to the
# client. The same rules about trailing "/" apply to ScriptAlias
# directives as to Alias.
#
ScriptAlias /cgi-bin/ "/Users/midoks/Desktop/mwdev/server/apache/httpd/cgi-bin/"
</IfModule>
<IfModule cgid_module>
#
# ScriptSock: On threaded servers, designate the path to the UNIX
# socket used to communicate with the CGI daemon of mod_cgid.
#
#Scriptsock cgisock
</IfModule>
#
# "/Users/midoks/Desktop/mwdev/server/apache/httpd/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/Users/midoks/Desktop/mwdev/server/apache/httpd/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule headers_module>
#
# Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
# backend servers which have lingering "httpoxy" defects.
# 'Proxy' request header is undefined by the IETF, not listed by IANA
#
RequestHeader unset Proxy early
</IfModule>
<IfModule mime_module>
#
# TypesConfig points to the file containing the list of mappings from
# filename extension to MIME-type.
#
TypesConfig conf/mime.types
#
# AddType allows you to add to or override the MIME configuration
# file specified in TypesConfig for specific file types.
#
#AddType application/x-gzip .tgz
#
# AddEncoding allows you to have certain browsers uncompress
# information on the fly. Note: Not all browsers support this.
#
#AddEncoding x-compress .Z
#AddEncoding x-gzip .gz .tgz
#
# If the AddEncoding directives above are commented-out, then you
# probably should define those extensions to indicate media types:
#
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
#
# AddHandler allows you to map certain file extensions to "handlers":
# actions unrelated to filetype. These can be either built into the server
# or added with the Action directive (see below)
#
# To use CGI scripts outside of ScriptAliased directories:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
#AddHandler cgi-script .cgi
# For type maps (negotiated resources):
#AddHandler type-map var
#
# Filters allow you to process content before it is sent to the client.
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
#AddType text/html .shtml
#AddOutputFilter INCLUDES .shtml
</IfModule>
#
# The mod_mime_magic module allows the server to use various hints from the
# contents of the file itself to determine its type. The MIMEMagicFile
# directive tells the module where the hint definitions are located.
#
#MIMEMagicFile conf/magic
#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
#
# MaxRanges: Maximum number of Ranges in a request before
# returning the entire resource, or one of the special
# values 'default', 'none' or 'unlimited'.
# Default setting is to accept 200 Ranges.
#MaxRanges unlimited
#
# EnableMMAP and EnableSendfile: On systems that support it,
# memory-mapping or the sendfile syscall may be used to deliver
# files. This usually improves server performance, but must
# be turned off when serving from networked-mounted
# filesystems or if support for these functions is otherwise
# broken on your system.
# Defaults: EnableMMAP On, EnableSendfile Off
#
#EnableMMAP off
#EnableSendfile on
# Supplemental configuration
#
# The configuration files in the conf/extra/ directory can be
# included to add extra features or to modify the default configuration of
# the server, or you may simply copy their contents here and change as
# necessary.
# Server-pool management (MPM specific)
#Include conf/extra/httpd-mpm.conf
# Multi-language error messages
#Include conf/extra/httpd-multilang-errordoc.conf
# Fancy directory listings
#Include conf/extra/httpd-autoindex.conf
# Language settings
#Include conf/extra/httpd-languages.conf
# User home directories
#Include conf/extra/httpd-userdir.conf
# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf
# Virtual hosts
#Include conf/extra/httpd-vhosts.conf
# Local access to the Apache HTTP Server Manual
#Include conf/extra/httpd-manual.conf
# Distributed authoring and versioning (WebDAV)
#Include conf/extra/httpd-dav.conf
# Various default settings
#Include conf/extra/httpd-default.conf
# Configure mod_proxy_html to understand HTML4/XHTML1
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>
# Secure (SSL/TLS) connections
#Include conf/extra/httpd-ssl.conf
#
# Note: The following must must be present to support
# starting without SSL on platforms with no /dev/random equivalent
# but a statically compiled-in mod_ssl.
#
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

BIN
plugins/apache/ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

25
plugins/apache/index.html Executable file
View File

@@ -0,0 +1,25 @@
<div class="bt-form">
<!-- <div class='plugin_version'></div> -->
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="httpPluginService('apache',$('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('apache', $('.plugin_version').attr('version'));">自启动</p>
<p onclick="pluginConfig('apache');">配置修改</p>
<p onclick="getHttpdStatus();">负载状态</p>
<p onclick="setOpCfg();">MPM性能调整</p>
<p onclick="pluginLogs('apache');">错误日志</p>
<p onclick="otherFunc();">维护功能</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con" style="height: 500px; overflow-y: auto;"></div>
</div>
</div>
</div>
<script type="text/javascript">
// resetPluginWinHeight(600);
$.getScript( "/plugins/file?name=apache&f=js/httpd.js", function(){
httpPluginService('apache');
});
</script>

593
plugins/apache/index.py Executable file
View File

@@ -0,0 +1,593 @@
# coding:utf-8
import sys
import io
import os
import time
import threading
import subprocess
import re
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'apache'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
current_os = mw.getOs()
if current_os == 'darwin':
return '/tmp/' + getPluginName()
if current_os.startswith('freebsd'):
return '/etc/rc.d/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getArgs():
args = sys.argv[2:]
# print(args)
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':',2)
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':',2)
tmp[t[0]] = t[1]
# print(tmp)
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def clearTemp():
path_bin = getServerDir() + "/httpd"
def getConf():
path = getServerDir() + "/httpd/conf/httpd.conf"
return path
def getConfMpm():
path = getServerDir() + "/httpd/conf/extra/httpd-mpm.conf"
return path
def getConfTpl():
path = getPluginDir() + '/conf/httpd.conf'
return path
def getOs():
data = {}
data['os'] = mw.getOs()
data['auth'] = True
return mw.getJson(data)
def getInitDTpl():
path = getPluginDir() + "/init.d/httpd.tpl"
return path
def getPidFile():
file = getConf()
content = mw.readFile(file)
rep = r'pid\s*(.*);'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getFileOwner(filename):
import pwd
stat = os.lstat(filename)
uid = stat.st_uid
pw = pwd.getpwuid(uid)
return pw.pw_name
def checkAuthEq(file, owner='root'):
fowner = getFileOwner(file)
if (fowner == owner):
return True
return False
def confReplace():
service_path = mw.getServerDir()
content = mw.readFile(getConfTpl())
content = content.replace('{$SERVER_PATH}', service_path)
# 主配置文件
nconf = getServerDir() + '/httpd/conf/httpd.conf'
mw.writeFile(nconf, content)
def initDreplace():
file_tpl = getInitDTpl()
service_path = mw.getServerDir()
initD_path = getServerDir() + '/init.d'
# OpenResty is not installed
if not os.path.exists(getServerDir()):
print("ok")
exit(0)
# init.d
file_bin = initD_path + '/' + getPluginName()
if not os.path.exists(initD_path):
os.mkdir(initD_path)
# initd replace
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# config replace
confReplace()
# systemd
# /usr/lib/systemd/system
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/httpd.service'
if os.path.exists(systemDir) and not os.path.exists(systemService):
systemServiceTpl = getPluginDir() + '/init.d/httpd.service.tpl'
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def status():
cmd = "ps -ef|grep 'httpd' |grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def restyOp(method):
file = initDreplace()
# 启动时,先检查一下配置文件
check = getServerDir() + "/httpd/bin/httpd -t"
check_data = mw.execShell(check)
if not check_data[1].find('Syntax OK') > -1:
return check_data[1]
current_os = mw.getOs()
if current_os == "darwin":
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
if current_os.startswith("freebsd"):
mw.execShell('service httpd '+method)
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell('systemctl ' + method + ' httpd')
if data[1] == '':
return 'ok'
return data[1]
def op_submit_systemctl_restart():
current_os = mw.getOs()
if current_os.startswith("freebsd"):
mw.execShell('service httpd restart')
return True
mw.execShell('systemctl restart httpd')
return True
def op_submit_init_restart(file):
mw.execShell(file + ' restart')
def restyOp_restart():
file = initDreplace()
# 启动时,先检查一下配置文件
check = getServerDir() + "/httpd/bin/httpd -t"
check_data = mw.execShell(check)
if not check_data[1].find('Syntax OK') > -1:
return 'ERROR: 配置出错<br><a style="color:red;">' + check_data[1].replace("\n", '<br>') + '</a>'
if not mw.isAppleSystem():
threading.Timer(2, op_submit_systemctl_restart).start()
return 'ok'
threading.Timer(2, op_submit_init_restart, args=(file,)).start()
return 'ok'
def start():
return restyOp('start')
def stop():
r = restyOp('stop')
mw.execShell("ps -ef|grep httpd | grep -v grep | awk '{print $2}'|xargs -r kill")
return r
def restart():
return restyOp_restart()
def reload():
confReplace()
return restyOp('reload')
def initdStatus():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status httpd | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
# freebsd initd install
if current_os.startswith('freebsd'):
import shutil
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('sysrc httpd_enable="YES"')
return 'ok'
mw.execShell('systemctl enable httpd')
return 'ok'
def initdUinstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('sysrc httpd_enable="NO"')
return 'ok'
mw.execShell('systemctl disable httpd')
return 'ok'
def getHttpdStatusPort():
conf = mw.getServerDir() + '/apache/httpd/conf/httpd.conf'
content = mw.readFile(conf)
if not content:
return None
rep = r'^\s*Listen\s*(?:\d+\.\d+\.\d+\.\d+:)?(\d+)' # 匹配非注释行的 Listen 指令,忽略大小写
tmp = re.search(rep, content, re.IGNORECASE | re.MULTILINE)
if tmp:
port = tmp.groups()[0].strip()
return port
return None
def runInfoDone(data):
result = {}
if not data:
return result
# 解析服务器状态数据
lines = data.strip().split('\n')
for line in lines:
if ':' in line:
key, value = line.split(':', 1)
key = key.strip()
value = value.strip()
result[key] = value
return result
def runInfo():
op_status = status()
if op_status == 'stop':
return mw.returnJson(False, "未启动!")
port = getHttpdStatusPort()
if not port:
return mw.returnJson(False, "无法获取端口信息!")
# 取Openresty负载状态
try:
url = 'http://127.0.0.1:%s/server-status?auto' % port
result = mw.httpGet(url, timeout=3)
data = runInfoDone(result)
return mw.getJson(data)
except Exception as e:
try:
url = 'http://' + mw.getHostAddr() + ':%s/server-status?auto' % port
result = mw.httpGet(url)
data = runInfoDone(result)
return mw.getJson(data)
except Exception as e:
return mw.returnJson(False, "apache异常!")
except Exception as e:
return mw.returnJson(False, "apache not started!")
def errorLogPath():
return getServerDir() + '/httpd/logs/error.log'
def getCfg():
cfg = getConfMpm()
content = mw.readFile(cfg)
unitrep = "[kmgKMG]"
# 获取当前 MPM 模块
mpm_module = ""
mpm_match = re.search(r"mpm_(\w+)_module", content)
if mpm_match:
mpm_module = mpm_match.group(1)
# MPM 配置参数
mpm_cfg_args = {
"prefork": [
{"name": "StartServers", "ps": "服务器进程启动数量", 'type': 2},
{"name": "MinSpareServers", "ps": "保持空闲的最小服务器进程数", 'type': 2},
{"name": "MaxSpareServers", "ps": "保持空闲的最大服务器进程数", 'type': 2},
{"name": "MaxRequestWorkers", "ps": "允许启动的最大服务器进程数", 'type': 2},
{"name": "MaxConnectionsPerChild", "ps": "服务器进程服务的最大连接数", 'type': 2},
],
"worker": [
{"name": "StartServers", "ps": "初始服务器进程数", 'type': 2},
{"name": "MinSpareThreads", "ps": "保持空闲的最小工作线程数", 'type': 2},
{"name": "MaxSpareThreads", "ps": "保持空闲的最大工作线程数", 'type': 2},
{"name": "ThreadsPerChild", "ps": "每个服务器进程的工作线程数", 'type': 2},
{"name": "MaxRequestWorkers", "ps": "最大工作线程数", 'type': 2},
{"name": "MaxConnectionsPerChild", "ps": "服务器进程服务的最大连接数", 'type': 2},
],
"event": [
{"name": "StartServers", "ps": "初始服务器进程数", 'type': 2},
{"name": "MinSpareThreads", "ps": "保持空闲的最小工作线程数", 'type': 2},
{"name": "MaxSpareThreads", "ps": "保持空闲的最大工作线程数", 'type': 2},
{"name": "ThreadsPerChild", "ps": "每个服务器进程的工作线程数", 'type': 2},
{"name": "MaxRequestWorkers", "ps": "最大工作线程数", 'type': 2},
{"name": "MaxConnectionsPerChild", "ps": "服务器进程服务的最大连接数", 'type': 2},
],
"netware": [
{"name": "ThreadStackSize", "ps": "每个工作线程分配的堆栈大小", 'type': 2},
{"name": "StartThreads", "ps": "服务器启动时启动的工作线程数", 'type': 2},
{"name": "MinSpareThreads", "ps": "保持空闲的最小线程数", 'type': 2},
{"name": "MaxSpareThreads", "ps": "保持空闲的最大线程数", 'type': 2},
{"name": "MaxThreads", "ps": "同时活跃的最大工作线程数", 'type': 2},
{"name": "MaxConnectionsPerChild", "ps": "线程服务的最大连接数", 'type': 2},
],
"mpmt_os2": [
{"name": "StartServers", "ps": "维护的服务器进程数", 'type': 2},
{"name": "MinSpareThreads", "ps": "每个进程的最小空闲线程数", 'type': 2},
{"name": "MaxSpareThreads", "ps": "每个进程的最大空闲线程数", 'type': 2},
{"name": "MaxConnectionsPerChild", "ps": "每个服务器进程的最大连接数", 'type': 2},
],
"winnt": [
{"name": "ThreadsPerChild", "ps": "服务器进程中的工作线程数", 'type': 2},
{"name": "MaxConnectionsPerChild", "ps": "服务器进程服务的最大连接数", 'type': 2},
]
}
# 通用配置参数
common_cfg_args = [
{"name": "MaxMemFree", "ps": "每个分配器允许持有的最大空闲KB数", 'type': 2},
]
# 合并配置参数
cfg_args = []
if mpm_module in mpm_cfg_args:
cfg_args.extend(mpm_cfg_args[mpm_module])
cfg_args.extend(common_cfg_args)
rdata = []
for i in cfg_args:
# 匹配 MPM 特定配置
rep = r"<IfModule mpm_%s_module>.*?(%s)\s+(\w+).*?</IfModule>" % (mpm_module, i["name"])
k = re.search(rep, content, re.DOTALL)
# 如果没有找到 MPM 特定配置,尝试匹配通用配置
if not k:
rep = r"(%s)\s+(\w+)" % i["name"]
k = re.search(rep, content)
if not k:
continue
key = k.group(1)
v = k.group(2) if len(k.groups()) > 1 else ""
if re.search(unitrep, v):
u = str.upper(v[-1])
v = v[:-1]
if len(u) == 1:
psstr = u + "B," + i["ps"]
else:
psstr = u + "," + i["ps"]
else:
u = ""
kv = {"name": key, "value": v, "unit": u,
"ps": i["ps"], "type": i["type"]}
rdata.append(kv)
return mw.returnJson(True, "ok", rdata)
def replaceChar(value, index, new_char):
return value[:index] + new_char + value[index+1:]
def setCfg():
args = getArgs()
# 检查参数,允许动态参数
cfg = getConfMpm()
mw.backFile(cfg)
content = mw.readFile(cfg)
# 获取当前 MPM 模块
mpm_module = ""
mpm_match = re.search(r"mpm_(\w+)_module", content)
if mpm_match:
mpm_module = mpm_match.group(1)
# 验证参数值
for k, v in args.items():
# 检查是否为数字参数
if not re.search(r"\d+", v):
return mw.returnJson(False, '参数值错误,请输入数字整数')
# 替换 MPM 特定配置
if mpm_module:
def replace_mpm_config(match):
return match.group(1) + k + match.group(2) + v + match.group(3)
rep = r"(<IfModule mpm_%s_module>.*?)%s(\s+)\d+(.*?</IfModule>)" % (mpm_module, k)
if re.search(rep, content, re.DOTALL):
content = re.sub(rep, replace_mpm_config, content, flags=re.DOTALL)
# 替换通用配置
def replace_common_config(match):
return k + match.group(1) + v
rep = r"%s(\s+)\d+" % k
if re.search(rep, content):
content = re.sub(rep, replace_common_config, content)
mw.writeFile(cfg, content)
isError = mw.checkHttpdConfig()
if (isError != True):
mw.restoreFile(cfg)
return mw.returnJson(False, 'ERROR: 配置出错<br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
mw.restartWeb()
return mw.returnJson(True, '设置成功')
def cronAddCheck():
try:
import tool_task
tool_task.createBgTask()
return mw.returnJson(True, '添加检查任务成功')
except Exception as e:
return mw.returnJson(False, '添加检查任务失败:'+str(e))
def cronDelCheck():
try:
import tool_task
tool_task.removeBgTask()
return mw.returnJson(True, '删除检查任务成功')
except Exception as e:
return mw.returnJson(False, '删除检查任务失败:'+str(e))
def cronCheck():
return 'ok'
def installPreInspection():
return 'ok'
if __name__ == "__main__":
version = '2.4'
version_pl = getServerDir() + "/version.pl"
if os.path.exists(version_pl):
version = mw.readFile(version_pl)
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 == 'install_pre_inspection':
print(installPreInspection())
elif func == 'conf':
print(getConf())
elif func == 'get_os':
print(getOs())
elif func == 'run_info':
print(runInfo())
elif func == 'error_log':
print(errorLogPath())
elif func == 'get_cfg':
print(getCfg())
elif func == 'set_cfg':
print(setCfg())
elif func == 'check':
print(cronCheck())
elif func == 'cron_add_check':
print(cronAddCheck())
elif func == 'cron_del_check':
print(cronDelCheck())
else:
print('error')

18
plugins/apache/info.json Executable file
View File

@@ -0,0 +1,18 @@
{
"sort": 0,
"title":"apache",
"tip":"soft",
"name":"apache",
"type":"其他插件",
"ps":"世界排名第一,快速、可靠并且可通过简单的API扩充",
"shell":"install.sh",
"install_pre_inspection":true,
"checks":"server/apache",
"path":"server/apache",
"author":"apache",
"home":"https://downloads.apache.org/httpd/",
"date":"2026-04-11",
"pid": "1",
"versions": ["2.4"],
"updates": ["2.4:66"]
}

View File

@@ -0,0 +1,16 @@
[Unit]
Description=Apache Web Server
After=network.target
[Service]
Type=simple
Environment=LANG=C
ExecStart={$SERVER_PATH}/apache/httpd/bin/httpd $OPTIONS -DFOREGROUND
ExecReload={$SERVER_PATH}/apache/httpd/bin/httpd $OPTIONS -k graceful
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,17 @@
[Unit]
Description=Apache Web Server
After=network.target
[Service]
Type=forking
PIDFile={$SERVER_PATH}/apache/httpd/logs/httpd.pid
ExecStart={$SERVER_PATH}/apache/httpd/bin/apachectl start
ExecReload={$SERVER_PATH}/apache/httpd/bin/apachectl graceful
ExecStop={$SERVER_PATH}/apache/httpd/bin/apachectl stop
PrivateTmp=true
User=www
Group=www
Restart=on-failure
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# chkconfig: 345 85 15
# description: Apache Server
### BEGIN INIT INFO
# Provides: apache
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Apache Server
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/homebrew/bin
# Apache 可执行文件的路径
DAEMON={$SERVER_PATH}/apache/httpd/bin/httpd
# 进程的 PID 文件路径
PIDFILE={$SERVER_PATH}/apache/httpd/logs/httpd.pid
# 根据传入的参数执行不同操作
case "$1" in
start)
echo "Starting Apache..."
$DAEMON -k start
;;
stop)
echo "Stopping Apache..."
$DAEMON -k stop
;;
restart)
echo "Restarting Apache..."
$DAEMON -k restart
;;
status)
if [ -f $PIDFILE ]; then
echo "Apache is running."
else
echo "Apache is not running."
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0

87
plugins/apache/install.sh Executable file
View File

@@ -0,0 +1,87 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/apache && bash install.sh install 2.4
# cd /www/server/mdserver-web/plugins/apache && bash install.sh install 2.4
# cd /www/server/mdserver-web/plugins/apache && bash install.sh upgrade 2.4
# curl -I -H "Accept-Encoding: br" http://localhost
# curl -I -H "Accept-Encoding: zstd" http://localhost
# curl --http3 -v https://www.xxx.com
# apt install ncat -y
# nc -u -v www.xx.com 443
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/apache && python3 plugins/apache/index.py start
# cd /www/server/mdserver-web && python3 plugins/apache/index.py start
# cd /www/server/mdserver-web && python3 plugins/apache/index.py run_info
# ps -ef|grep httpd | grep -v grep | awk '{print $2}'|xargs kill
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
action=$1
type=$2
VERSION=$2
openrestyDir=${serverPath}/source/apache
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 /bin/bash www
fi
if [ "${action}" = "upgrade" ];then
sh -x $curPath/versions/$2/install.sh $1
echo "${VERSION}" > $serverPath/apache/version.pl
mkdir -p $serverPath/web_conf/php/conf
echo 'set $PHP_ENV 0;' > $serverPath/web_conf/php/conf/enable-php-00.conf
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/apache/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/apache/index.py initd_install
exit 0
fi
if [ "${2}" = "" ];then
echo '缺少安装脚本版本...'
exit 0
fi
if [ "${action}" = "uninstall" ];then
if [ -f /usr/lib/systemd/system/httpd.service ] || [ -f /lib/systemd/system/httpd.service ];then
systemctl stop httpd
rm -rf /usr/systemd/system/httpd.service
rm -rf /lib/systemd/system/httpd.service
systemctl daemon-reload
fi
if [ -f $serverPath/apache/init.d/httpd ];then
$serverPath/apache/init.d/httpd stop
fi
rm -rf $serverPath/apache
fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" = "install" ] && [ -d $serverPath/apache ];then
echo "${VERSION}" > $serverPath/apache/version.pl
mkdir -p $serverPath/web_conf/php/conf
echo 'set $PHP_ENV 0;' > $serverPath/web_conf/php/conf/enable-php-00.conf
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/apache/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/apache/index.py initd_install
fi

278
plugins/apache/js/httpd.js Executable file
View File

@@ -0,0 +1,278 @@
function httpPost(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'apache', 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 httpPluginService(_name, version){
var data = {name:_name, func:'status'}
if ( typeof(version) != 'undefined' ){
data['version'] = version;
} else {
version = '';
}
httpPost('status', data, function(data){
if (data.data == 'start'){
orPluginSetService(_name, true, version);
} else {
orPluginSetService(_name, false, version);
}
});
}
function orPluginSetService(_name ,status, version){
var serviceCon ='<p class="status">当前状态:<span>'+(status ? '开启' : '关闭' )+
'</span><span style="color: '+
(status?'#20a53a;':'red;')+
' margin-left: 3px;" class="glyphicon ' + (status?'glyphicon glyphicon-play':'glyphicon-pause')+'"></span></p><div class="sfm-opt">\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\''+(status?'stop':'start')+'\',\''+version+'\')">'+(status?'停止':'启动')+'</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'restart\',\''+version+'\',\'yes\')">重启</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'reload\',\''+version+'\')">重载配置</button>\
</div>';
$(".soft-man-con").html(serviceCon);
}
function orPluginOpService(a, b, v,request_callback) {
var c = "name=" + a + "&func=" + b;
if(v != ''){
c = c + '&version='+v;
}
var d = "";
switch(b) {
case "stop":d = '停止';break;
case "start":d = '启动';break;
case "restart":d = '重启';break;
case "reload":d = '重载';break;
}
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 2}, function() {
httpPost('get_os',{},function(data){
var rdata = $.parseJSON(data.data);
if (!rdata['auth']){
layer.prompt({title: '检查到权限不足,需要输入密码!', formType: 1},function(pwd, index){
layer.close(index);
var data = {'pwd':pwd};
c += '&args='+JSON.stringify(data);
orPluginOpServiceOp(a,b,c,d,a,v,request_callback);
});
} else {
orPluginOpServiceOp(a,b,c,d,a,v,request_callback);
}
});
})
}
function orPluginOpServiceOp(a,b,c,d,a,v,request_callback){
var request_path = "/plugins/run";
if (request_callback == 'yes'){
request_path = "/plugins/callback";
}
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0});
$.post(request_path, c, function(g) {
layer.close(e);
var f = g.data == 'ok' ? msgTpl('{1}{2}服务已{3}',[a,v,d]) : msgTpl('{1}{2}服务{3}失败!',[a,v,d]);
layer.msg(f, {icon: g.data == 'ok' ? 1 : 2});
if( b != "reload" && g.data == 'ok' ) {
if ( b == 'start' ) {
orPluginSetService(a, true, v);
} else if ( b == 'stop' ){
orPluginSetService(a, false, v);
}
}
if( g.status && g.data != 'ok' ) {
layer.msg(g.data, {icon: 2,time: 10000,shade: 0.3});
}
},'json').error(function() {
layer.close(e);
layer.msg('操作异常!', {icon: 2});
});
}
// 定时器变量
var httpdStatusTimer = null;
//查看Apache负载状态
function getHttpdStatus() {
$.post('/plugins/run', {name:'apache', func:'run_info'}, function(data) {
try {
var rdata = $.parseJSON(data.data);
console.log(rdata);
if ('status' in rdata && !rdata.status){
showMsg(rdata.msg, function(){}, null,3000);
return;
}
var con = "<div><table class='table table-hover table-bordered'>\
<tr><th>服务器版本(ServerVersion)</th><td>" + (rdata.ServerVersion || '-') + "</td></tr>\
<tr><th>服务器MPM(ServerMPM)</th><td>" + (rdata.ServerMPM || '-') + "</td></tr>\
<tr><th>服务器构建时间(Server Built)</th><td>" + (rdata['Server Built'] || '-') + "</td></tr>\
<tr><th>当前时间(CurrentTime)</th><td>" + (rdata.CurrentTime || '-') + "</td></tr>\
<tr><th>重启时间(RestartTime)</th><td>" + (rdata.RestartTime || '-') + "</td></tr>\
<tr><th>服务器运行时间(ServerUptime)</th><td>" + (rdata.ServerUptime || '-') + "</td></tr>\
<tr><th>服务器运行秒数(ServerUptimeSeconds)</th><td>" + (rdata.ServerUptimeSeconds || '-') + "</td></tr>\
<tr><th>1分钟负载(Load1)</th><td>" + (rdata.Load1 || '-') + "</td></tr>\
<tr><th>5分钟负载(Load5)</th><td>" + (rdata.Load5 || '-') + "</td></tr>\
<tr><th>15分钟负载(Load15)</th><td>" + (rdata.Load15 || '-') + "</td></tr>\
<tr><th>总访问次数(Total Accesses)</th><td>" + (rdata['Total Accesses'] || '-') + "</td></tr>\
<tr><th>总流量(Total kBytes)</th><td>" + (rdata['Total kBytes'] || '-') + " KB</td></tr>\
<tr><th>总请求时间(Total Duration)</th><td>" + (rdata['Total Duration'] || '-') + "</td></tr>\
<tr><th>CPU用户时间(CPUUser)</th><td>" + (rdata.CPUUser || '-') + "</td></tr>\
<tr><th>CPU系统时间(CPUSystem)</th><td>" + (rdata.CPUSystem || '-') + "</td></tr>\
<tr><th>CPU负载(CPULoad)</th><td>" + (rdata.CPULoad || '-') + "</td></tr>\
<tr><th>每秒请求数(ReqPerSec)</th><td>" + (rdata.ReqPerSec || '-') + "</td></tr>\
<tr><th>每秒流量(BytesPerSec)</th><td>" + (rdata.BytesPerSec || '-') + "</td></tr>\
<tr><th>每请求流量(BytesPerReq)</th><td>" + (rdata.BytesPerReq || '-') + "</td></tr>\
<tr><th>每请求时间(DurationPerReq)</th><td>" + (rdata.DurationPerReq || '-') + "</td></tr>\
<tr><th>活动工作进程(BusyWorkers)</th><td>" + (rdata.BusyWorkers || '-') + "</td></tr>\
<tr><th>优雅关闭进程(GracefulWorkers)</th><td>" + (rdata.GracefulWorkers || '-') + "</td></tr>\
<tr><th>空闲工作进程(IdleWorkers)</th><td>" + (rdata.IdleWorkers || '-') + "</td></tr>\
<tr><th>进程数(Processes)</th><td>" + (rdata.Processes || '-') + "</td></tr>\
<tr><th>总连接数(ConnsTotal)</th><td>" + (rdata.ConnsTotal || '-') + "</td></tr>\
</table></div>";
$(".soft-man-con").html(con);
}catch(err){
showMsg(data.data, function(){}, null,3000);
}
},'json');
}
// 启动自动刷新
function startHttpdStatusAutoRefresh() {
// 先清除现有的定时器
if (httpdStatusTimer) {
clearInterval(httpdStatusTimer);
}
// 立即执行一次
getHttpdStatus();
// 设置定时器,每5秒刷新一次
httpdStatusTimer = setInterval(getHttpdStatus, 5000);
}
// 停止自动刷新
function stopHttpdStatusAutoRefresh() {
if (httpdStatusTimer) {
clearInterval(httpdStatusTimer);
httpdStatusTimer = null;
}
}
function setOpCfg(){
httpPost('get_cfg', {}, function(data){
var rdata = $.parseJSON(data.data);
var rdata = rdata.data;
// console.log(rdata);
var mlist = '';
for (var i = 0; i < rdata.length; i++) {
var w = '70'
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;
}
mlist += '<p style="margin-top:15px;"><span>' + rdata[i].name + '</span>' + ibody + "<b class='unit c9'>"+rdata[i].unit+"</b>" +', <font class="c9">' + rdata[i].ps + '</font></p>';
}
var con = '<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="setOpCfg()">刷新</button>\
<button class="btn btn-success btn-sm" onclick="submitConf()">保存</button>\
</div>\
</div>'
$(".soft-man-con").html(con);
});
}
function submitConf() {
var data = {};
// 收集所有配置参数
$("input[name]").each(function() {
data[$(this).attr('name')] = $(this).val();
});
$("select[name]").each(function() {
data[$(this).attr('name')] = $(this).val() || 'on';
});
// console.log(data);
httpPost('set_cfg', data, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
function otherFunc(){
var con = '<p class="conf_p" style="text-align:center;">\
<button class="btn btn-default btn-sm" onclick="cronAddCheck()">添加检查任务</button> \
<button class="btn btn-default btn-sm" onclick="cronDelCheck()">删除检查任务</button>\
</p>';
$(".soft-man-con").html(con);
}
function cronAddCheck(){
httpPost('cron_add_check', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
function cronDelCheck(){
httpPost('cron_del_check', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}

124
plugins/apache/tool_task.py Normal file
View File

@@ -0,0 +1,124 @@
# coding:utf-8
import sys
import io
import os
import time
import json
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
from utils.crontab import crontab as MwCrontab
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'apache'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/task_config.json"
return conf
def getConfigData():
conf = getTaskConf()
if os.path.exists(conf):
return json.loads(mw.readFile(getTaskConf()))
return {
"task_id": -1,
"period": "minute-n",
"where1": "3",
"hour": "0",
"minute": "0",
}
def createBgTask():
removeBgTask()
createBgTaskByName(getPluginName())
def createBgTaskByName(name):
args = getConfigData()
_name = "[apache]检查任务"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in args and args["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (args["task_id"],)).find()
if res and res["id"] == args["task_id"]:
print("计划任务已经存在!")
return True
mw_dir = mw.getPanelDir()
cmd = '''
mw_dir=%s
rname=%s
plugin_path=%s
script_path=%s
''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "bash $script_path/check.sh"' + "\n"
cmd += 'cd $mw_dir && bash $script_path/check.sh' + "\n"
params = {
'name': _name,
'type': args['period'],
'week': "",
'where1': args['where1'],
'hour': args['hour'],
'minute': args['minute'],
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'url_address': '',
}
task_id = MwCrontab.instance().add(params)
if task_id > 0:
args["task_id"] = task_id
args["name"] = name
mw.writeFile(getTaskConf(), json.dumps(args))
def removeBgTask():
cfg = getConfigData()
if "task_id" in cfg and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
data = MwCrontab.instance().delete(cfg["task_id"])
if data["status"]:
cfg["task_id"] = -1
mw.writeFile(getTaskConf(), json.dumps(cfg))
return True
return False
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()

View File

@@ -0,0 +1,172 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/apache && bash install.sh install 2.4
# cd /www/server/mdserver-web/plugins/apache && bash install.sh install 2.4
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
action=$1
type=$2
VERSION=2.4.68
apacheDir=${serverPath}/source/apache
Install_App()
{
if [ "${action}" = "install" ];then
if [ -d $serverPath/apache ];then
exit 0
fi
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
mkdir -p ${apacheDir}
echo 'install script ...'
OPTIONS=''
# 安装 APR 和 APR-util
APR_VERSION=1.7.6
APR_UTIL_VERSION=1.6.3
if [ ! -f ${apacheDir}/apr-${APR_VERSION}.tar.bz2 ];then
wget --no-check-certificate -O ${apacheDir}/apr-${APR_VERSION}.tar.bz2 https://downloads.apache.org/apr/apr-${APR_VERSION}.tar.bz2 -T 3
fi
if [ ! -f ${apacheDir}/apr-util-${APR_UTIL_VERSION}.tar.bz2 ];then
wget --no-check-certificate -O ${apacheDir}/apr-util-${APR_UTIL_VERSION}.tar.bz2 https://downloads.apache.org/apr/apr-util-${APR_UTIL_VERSION}.tar.bz2 -T 3
fi
# 安装 APR
if [ ! -d ${serverPath}/apache/apr ];then
cd ${apacheDir} && tar -jxf apr-${APR_VERSION}.tar.bz2
cd ${apacheDir}/apr-${APR_VERSION} && ./configure --prefix=${serverPath}/apache/apr
make -j${cpuCore} && make install
if [ "$?" = "0" ];then
# 检查 APR 配置文件
APR_CONFIG=$(find ${serverPath}/apache/apr -name "apr-*config" | head -1)
if [ -z "$APR_CONFIG" ];then
echo "APR installation failed: apr-config not found"
exit 1
fi
echo "APR installed successfully: $APR_CONFIG"
else
echo "APR configure failed"
exit 1
fi
fi
# 安装 APR-util
if [ ! -d ${serverPath}/apache/apr-util ];then
cd ${apacheDir} && tar -jxf apr-util-${APR_UTIL_VERSION}.tar.bz2
cd ${apacheDir}/apr-util-${APR_UTIL_VERSION} && ./configure --prefix=${serverPath}/apache/apr-util --with-apr=${serverPath}/apache/apr
make -j${cpuCore} && make install
if [ "$?" = "0" ];then
# 检查 APR-util 配置文件
APU_CONFIG=$(find ${serverPath}/apache/apr-util -name "apu-*config" | head -1)
if [ -z "$APU_CONFIG" ];then
echo "APR-util installation failed: apu-config not found"
find ${serverPath}/apache/apr-util -name "apu-*config"
exit 1
fi
echo "APR-util installed successfully: $APU_CONFIG"
else
echo "APR-util configure failed"
exit 1
fi
fi
if [ ! -f ${apacheDir}/httpd-${VERSION}.tar.bz2 ];then
wget --no-check-certificate -O ${apacheDir}/httpd-${VERSION}.tar.bz2 https://downloads.apache.org/httpd/httpd-${VERSION}.tar.bz2 -T 3
fi
if [ ! -d ${apacheDir}/httpd-${VERSION} ];then
cd ${apacheDir} && tar -jxf ${apacheDir}/httpd-${VERSION}.tar.bz2
fi
# 检查 APR 和 APR-util 可执行文件
APR_CONFIG=$(find ${serverPath}/apache/apr -name "apr-*config" | head -1)
APU_CONFIG=$(find ${serverPath}/apache/apr-util -name "apu-*config" | head -1)
if [ -z "$APR_CONFIG" ];then
echo "APR config not found"
exit 1
fi
if [ -z "$APU_CONFIG" ];then
echo "APR-util config not found"
exit 1
fi
OPTIONS="${OPTIONS} --with-apr=$APR_CONFIG"
OPTIONS="${OPTIONS} --with-apr-util=$APU_CONFIG"
# if [ "$sysName" != "Darwin" ];then
# OPTIONS="${OPTIONS} --enable-systemd"
# fi
# echo "cd ${apacheDir}/httpd-${VERSION} && ./configure --prefix=$serverPath/apache $OPTIONS"
cd ${apacheDir}/httpd-${VERSION} && ./configure \
--prefix=$serverPath/apache/httpd \
$OPTIONS
make -j${cpuCore} && make install && make clean
if [ -d ${apacheDir}/apr-${APR_VERSION} ];then
rm -rf ${apacheDir}/apr-${APR_VERSION}
fi
if [ -d ${apacheDir}/apr-util-${APR_UTIL_VERSION} ];then
rm -rf ${apacheDir}/apr-util-${APR_UTIL_VERSION}
fi
if [ -d ${apacheDir}/httpd-${APR_UTIL_VERSION} ];then
rm -rf ${apacheDir}/httpd-${APR_UTIL_VERSION}
fi
echo 'installation of apache completed'
}
Uninstall_App()
{
echo 'uninstalling apache completed'
}
action=$1
if [ "${1}" = "install" ];then
Install_App
elif [ "${1}" = "upgrade" ];then
Install_App
else
Uninstall_App
fi

View File

@@ -20,16 +20,6 @@ if os.path.exists(web_dir):
import core.mw as mw
import core.db as db
_ver = sys.version_info
is_py2 = (_ver[0] == 2)
is_py3 = (_ver[0] == 3)
DEBUG = False
if is_py2:
reload(sys)
sys.setdefaultencoding('utf-8')
app_debug = False
if mw.isAppleSystem():
app_debug = True
@@ -81,7 +71,10 @@ def status():
def getConf():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置", [])
rdata = {
'use_sftp':False,
}
return mw.returnJson(False, "未配置", rdata)
data = mw.readFile(cfg)
data = json.loads(data)
return mw.returnJson(True, "OK", data)

View File

@@ -1,4 +1,5 @@
{
"sort":6,
"title":"FTP存储空间",
"hook":["backup"],
"tip":"soft",
@@ -13,5 +14,5 @@
"author":"midoks",
"home":"https://github.com/midoks/mdserver-web",
"date":"2022-10-23",
"pid": "4"
"pid": "5"
}

View File

@@ -24,7 +24,7 @@ Uninstall_App()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_App $2
else
Uninstall_App $2

35
plugins/caddy/check.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# OpenResty服务名称
service_name="caddy"
# 检查OpenResty是否正在运行
if systemctl is-active --quiet "$service_name"; then
# 检查是否存在僵尸进程
zombie_processes=$(ps -ef | grep -i caddy | grep -v grep | awk '{print $2}' | xargs ps -o state= -p 2>/dev/null | grep -c Z)
if [ "$zombie_processes" -gt 0 ]; then
echo "kill caddy 僵尸进程"
ps -ef|grep caddy| grep -v grep| awk '{print $2}' | xargs kill -9
echo "检测到OpenResty僵尸进程,正在重启服务..."
systemctl restart "$service_name"
echo "服务已重启"
else
echo "OpenResty运行正常"
fi
else
echo "kill caddy"
ps -ef|grep caddy| grep -v grep| awk '{print $2}' | xargs kill -9
echo "caddy未运行,正在启动服务..."
systemctl start "$service_name"
echo "服务已启动"
fi
NGINX_IDS=`ps -ef|grep caddy | grep -v grep| awk '{print $2}'`
if [ "$NGINX_IDS" = "" ];then
ps -ef|grep caddy| grep -v grep| awk '{print $2}' | xargs kill -9
systemctl start "$service_name"
echo "caddy未运行,正在启动服务..."
fi

View File

@@ -0,0 +1,13 @@
:8080 {
# Set this path to your site's directory.
root * /tmp
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}

BIN
plugins/caddy/ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

24
plugins/caddy/index.html Executable file
View File

@@ -0,0 +1,24 @@
<div class="bt-form">
<!-- <div class='plugin_version'></div> -->
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="orPluginService('caddy',$('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('caddy', $('.plugin_version').attr('version'));">自启动</p>
<p onclick="pluginConfig('caddy');">配置修改</p>
<p onclick="getOpStatus();">负载状态</p>
<p onclick="setOpCfg();">性能调整</p>
<p onclick="pluginLogs('caddy');">错误日志</p>
<p onclick="otherFunc();">维护功能</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=caddy&f=js/caddy.js", function(){
orPluginService('caddy');
});
</script>

445
plugins/caddy/index.py Executable file
View File

@@ -0,0 +1,445 @@
# coding:utf-8
import sys
import io
import os
import time
import threading
import subprocess
import re
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'caddy'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
current_os = mw.getOs()
if current_os == 'darwin':
return '/tmp/' + getPluginName()
if current_os.startswith('freebsd'):
return '/etc/rc.d/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getArgs():
args = sys.argv[2:]
# print(args)
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':',2)
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':',2)
tmp[t[0]] = t[1]
# print(tmp)
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def getOs():
data = {}
data['os'] = mw.getOs()
data['auth'] = True
return mw.getJson(data)
def getConf():
path = getServerDir() + "/Caddyfile"
return path
def getConfTpl():
path = getPluginDir() + '/conf/Caddyfile'
return path
def getInitDTpl():
path = getPluginDir() + "/init.d/caddy.tpl"
return path
def initDreplace():
file_tpl = getInitDTpl()
service_path = mw.getServerDir()
initD_path = getServerDir() + '/init.d'
# init.d
file_bin = initD_path + '/' + getPluginName()
if not os.path.exists(initD_path):
os.mkdir(initD_path)
# initd replace
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
caddy_file = getConf()
if not os.path.exists(caddy_file):
caddy_file_tpl = getConfTpl()
content = mw.readFile(caddy_file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(caddy_file, content)
# systemd
# /usr/lib/systemd/system
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/caddy.service'
if os.path.exists(systemDir) and not os.path.exists(systemService):
systemServiceTpl = getPluginDir() + '/init.d/caddy.service.tpl'
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def status():
cmd = "ps -ef|grep 'caddy run' |grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def caddyOp(method):
file = initDreplace()
current_os = mw.getOs()
if current_os == "darwin":
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
if current_os.startswith("freebsd"):
data = mw.execShell('service caddy ' + method)
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell('systemctl ' + method + ' caddy')
if data[1] == '':
return 'ok'
return data[1]
def start():
return caddyOp('start')
def stop():
r = caddyOp('stop')
return r
def restart():
return restyOp_restart()
def reload():
confReplace()
return caddyOp('reload')
def initdStatus():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status caddy | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
# freebsd initd install
if current_os.startswith('freebsd'):
import shutil
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="YES"')
return 'ok'
mw.execShell('systemctl enable caddy')
return 'ok'
def initdUinstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="NO"')
return 'ok'
mw.execShell('systemctl disable caddy')
return 'ok'
def runInfo():
op_status = status()
if op_status == 'stop':
return mw.returnJson(False, "未启动!")
def errorLogPath():
return getServerDir() + '/nginx/logs/error.log'
def getCfg():
cfg = getConf()
content = mw.readFile(cfg)
unitrep = "[kmgKMG]"
cfg_args = [
{"name": "worker_processes", "ps": "处理进程,auto表示自动,数字表示进程数", 'type': 2},
{"name": "worker_connections", "ps": "最大并发链接数", 'type': 2},
{"name": "keepalive_timeout", "ps": "连接超时时间", 'type': 2},
{"name": "zstd", "ps": "是否开启zstd压缩传输", 'type': 1},
{"name": "brotli", "ps": "是否开启brotli压缩传输", 'type': 1},
{"name": "gzip", "ps": "是否开启gzip压缩传输", 'type': 1},
{"name": "gzip_min_length", "ps": "最小压缩文件", 'type': 2},
{"name": "gzip_comp_level", "ps": "压缩率", 'type': 2},
{"name": "client_max_body_size", "ps": "最大上传文件", 'type': 2},
{"name": "server_names_hash_bucket_size",
"ps": "服务器名字的hash表大小", 'type': 2},
{"name": "client_header_buffer_size", "ps": "客户端请求头buffer大小", 'type': 2},
]
# {"name": "client_body_buffer_size", "ps": "请求主体缓冲区"}
rdata = []
for i in cfg_args:
rep = r"(%s)\s+(\w+)" % i["name"]
k = re.search(rep, content)
if not k:
return mw.returnJson(False, "获取 key {} 失败".format(k))
k = k.group(1)
v = re.search(rep, content)
if not v:
return mw.returnJson(False, "获取 value {} 失败".format(v))
v = v.group(2)
if re.search(unitrep, v):
u = str.upper(v[-1])
v = v[:-1]
if len(u) == 1:
psstr = u + "B," + i["ps"]
else:
psstr = u + "," + i["ps"]
else:
u = ""
kv = {"name": k, "value": v, "unit": u,
"ps": i["ps"], "type": i["type"]}
rdata.append(kv)
return mw.returnJson(True, "ok", rdata)
def replaceChar(value, index, new_char):
return value[:index] + new_char + value[index+1:]
def makeWorkerCpuAffinity(val):
if val == "auto":
return "auto"
if mw.isNumber(val):
core_num = int(val)
default_core_str = "0"*core_num
core_num_arr = []
for x in range(core_num):
t = replaceChar(default_core_str, x , "1")
core_num_arr.append(t)
return " ".join(core_num_arr)
return 'auto'
def setCfg():
args = getArgs()
data = checkArgs(args, [
'worker_processes', 'worker_connections', 'keepalive_timeout','zstd','brotli',
'gzip', 'gzip_min_length', 'gzip_comp_level', 'client_max_body_size',
'server_names_hash_bucket_size', 'client_header_buffer_size'
])
if not data[0]:
return data[1]
cfg = getConf()
mw.backFile(cfg)
content = mw.readFile(cfg)
unitrep = "[kmgKMG]"
cfg_args = [
{"name": "worker_processes", "ps": "处理进程,auto表示自动,数字表示进程数", 'type': 2},
{"name": "worker_connections", "ps": "最大并发链接数", 'type': 2},
{"name": "keepalive_timeout", "ps": "连接超时时间", 'type': 2},
{"name": "zstd", "ps": "是否开启zstd压缩传输", 'type': 1},
{"name": "brotli", "ps": "是否开启brotli压缩传输", 'type': 1},
{"name": "gzip", "ps": "是否开启压缩传输", 'type': 1},
{"name": "gzip_min_length", "ps": "最小压缩文件", 'type': 2},
{"name": "gzip_comp_level", "ps": "压缩率", 'type': 2},
{"name": "client_max_body_size", "ps": "最大上传文件", 'type': 2},
{"name": "server_names_hash_bucket_size",
"ps": "服务器名字的hash表大小", 'type': 2},
{"name": "client_header_buffer_size", "ps": "客户端请求头buffer大小", 'type': 2},
]
# print(args)
for k, v in args.items():
# print(k, v)
rep = r"%s\s+[^kKmMgG\;\n]+" % k
if k == "worker_processes" or k == "gzip":
if not re.search(r"auto|on|off|\d+", v):
return mw.returnJson(False, '参数值错误')
elif k == "zstd" or k == "brotli":
if not re.search(r"auto|on|off|\d+", v):
return mw.returnJson(False, '参数值错误')
else:
if not re.search(r"\d+", v):
return mw.returnJson(False, '参数值错误,请输入数字整数')
if k == "worker_processes" :
k_wca = "worker_cpu_affinity"
rep_wca = r"%s\s+[^\;\n]+" % k_wca
v_wca = makeWorkerCpuAffinity(v)
newconf = "%s %s" % (k_wca, v_wca)
content = re.sub(rep_wca, newconf, content)
if re.search(rep, content):
newconf = "%s %s" % (k, v)
content = re.sub(rep, newconf, content)
elif re.search(rep, content):
newconf = "%s %s" % (k, v)
content = re.sub(rep, newconf, content)
mw.writeFile(cfg, content)
isError = mw.checkWebConfig()
if (isError != True):
mw.restoreFile(cfg)
return mw.returnJson(False, 'ERROR: 配置出错<br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
mw.restartWeb()
return mw.returnJson(True, '设置成功')
def cronAddCheck():
try:
import tool_task
tool_task.createBgTask()
return mw.returnJson(True, '添加检查任务成功')
except Exception as e:
return mw.returnJson(False, '添加检查任务失败:'+str(e))
def cronDelCheck():
try:
import tool_task
tool_task.removeBgTask()
return mw.returnJson(True, '删除检查任务成功')
except Exception as e:
return mw.returnJson(False, '删除检查任务失败:'+str(e))
def cronCheck():
return 'ok'
def installPreInspection():
return 'ok'
if __name__ == "__main__":
version = '1.27.1'
version_pl = getServerDir() + "/version.pl"
if os.path.exists(version_pl):
version = mw.readFile(version_pl)
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 == 'install_pre_inspection':
print(installPreInspection())
elif func == 'conf':
print(getConf())
elif func == 'get_os':
print(getOs())
elif func == 'run_info':
print(runInfo())
elif func == 'error_log':
print(errorLogPath())
elif func == 'get_cfg':
print(getCfg())
elif func == 'set_cfg':
print(setCfg())
elif func == 'check':
print(cronCheck())
elif func == 'cron_add_check':
print(cronAddCheck())
elif func == 'cron_del_check':
print(cronDelCheck())
else:
print('error')

18
plugins/caddy/info.json Executable file
View File

@@ -0,0 +1,18 @@
{
"sort": 0,
"title":"caddy",
"tip":"soft",
"name":"caddy",
"type":"其他插件",
"ps":"一款功能强大、企业级、开源 Web 服务器,具有用 Go 编写的自动 HTTPS",
"shell":"install.sh",
"install_pre_inspection":true,
"checks":"server/caddy",
"path":"server/caddy",
"author":"caddyserver",
"home":"https://caddyserver.com/",
"date":"2026-04-11",
"pid": "1",
"versions": ["2.11"],
"updates": ["2.11.2"]
}

View File

@@ -0,0 +1,36 @@
# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=simple
User=www
Group=www
ExecStart={$SERVER_PATH}/caddy/bin/caddy run --environ --config {$SERVER_PATH}/caddy/Caddyfile
ExecReload={$SERVER_PATH}/caddy/bin/caddy reload --config {$SERVER_PATH}/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,111 @@
#!/bin/sh
#
# /etc/rc.d/init.d/caddy
#
# Runs the caddy
#
#
# chkconfig: - 85 15
#
### BEGIN INIT INFO
# Provides: caddy
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: caddy
# Should-Stop: caddy
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start caddy at boot time.
# Description: Control caddy.
### END INIT INFO
# Source function library.
if [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
fi
if [ -f /etc/rc.d/init.d/functions ];then
. /etc/rc.d/init.d/functions
fi
# Default values
export HOME={$HOME_DIR}
export USER={$RUN_USER}
NAME=caddy
CADDY_HOME={$SERVER_PATH}/caddy
CADDY_PATH=${CADDY_HOME}/bin/$NAME
CADDY_USER={$RUN_USER}
SERVICENAME="caddy"
LOCKFILE=/tmp/caddy.lock
LOGPATH=${CADDY_HOME}/log
LOGFILE=${LOGPATH}/caddy.log
RETVAL=0
if [ -d $LOGPATH ];then
mkdir -p $LOGPATH
fi
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
DAEMON_OPTS="--check $NAME"
[ ! -z "$CADDY_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${CADDY_USER}"
status(){
isStart=`ps -ef|grep 'caddy run' |grep -v grep|awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "${SERVICENAME} not running"
else
echo -e "${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
start() {
isStart=`ps -ef | grep 'caddy run' | grep -v grep | awk '{print $2}'`
if [ "$isStart" != '' ];then
echo "${SERVICENAME}(pid $(echo $isStart)) already running"
return $RETVAL
fi
cd ${CADDY_HOME}
echo -e "starting ${SERVICENAME}: \c"
${CADDY_PATH} run --environ --config ${CADDY_HOME}/Caddyfile > ${LOGFILE} 2>&1 &
RETVAL=$?
[ $RETVAL = 0 ] && touch ${LOCKFILE} && echo -e "\033[32mdone\033[0m"
return $RETVAL
}
stop() {
pids=`ps -ef | grep 'caddy run' | grep -v grep | awk '{print $2}'`
arr=($pids)
echo -e "stopping caddy... \c"
for p in ${arr[@]}
do
kill -9 $p
done
echo -e "\033[32mdone\033[0m"
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
reload)
stop
start
;;
*)
echo "Usage: ${NAME} {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL

76
plugins/caddy/install.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/caddy && bash install.sh install 1.21.4
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh install 2.11
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh install 1.29.2
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh upgrade 1.29.2
# curl -I -H "Accept-Encoding: br" http://localhost
# curl -I -H "Accept-Encoding: zstd" http://localhost
# curl --http3 -v https://www.xxx.com
# cd /www/server/mdserver-web && python3 plugins/caddy/index.py run_info
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
action=$1
type=$2
VERSION=$2
openrestyDir=${serverPath}/source/caddy
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 /bin/bash www
fi
if [ "${action}" = "upgrade" ];then
sh -x $curPath/versions/$2/install.sh $1
echo "${VERSION}" > $serverPath/caddy/version.pl
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/caddy/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/caddy/index.py initd_install
exit 0
fi
if [ "${2}" = "" ];then
echo '缺少安装脚本版本...'
exit 0
fi
if [ "${action}" = "uninstall" ];then
if [ -f /usr/lib/systemd/system/caddy.service ] || [ -f /lib/systemd/system/caddy.service ];then
systemctl stop caddy
rm -rf /usr/systemd/system/caddy.service
rm -rf /lib/systemd/system/caddy.service
systemctl daemon-reload
fi
if [ -f $serverPath/caddy/init.d/caddy ];then
$serverPath/caddy/init.d/caddy stop
fi
rm -rf $serverPath/caddy
fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" = "install" ] && [ -d $serverPath/caddy ];then
echo "${VERSION}" > $serverPath/caddy/version.pl
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/caddy/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/caddy/index.py initd_install
fi

238
plugins/caddy/js/caddy.js Executable file
View File

@@ -0,0 +1,238 @@
function caddyPost(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'caddy', func:method, args:JSON.stringify(args)}, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function orPluginService(_name, version){
var data = {name:_name, func:'status'}
if ( typeof(version) != 'undefined' ){
data['version'] = version;
} else {
version = '';
}
caddyPost('status', data, function(data){
if (data.data == 'start'){
orPluginSetService(_name, true, version);
} else {
orPluginSetService(_name, false, version);
}
});
}
function orPluginSetService(_name ,status, version){
var serviceCon ='<p class="status">当前状态:<span>'+(status ? '开启' : '关闭' )+
'</span><span style="color: '+
(status?'#20a53a;':'red;')+
' margin-left: 3px;" class="glyphicon ' + (status?'glyphicon glyphicon-play':'glyphicon-pause')+'"></span></p><div class="sfm-opt">\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\''+(status?'stop':'start')+'\',\''+version+'\')">'+(status?'停止':'启动')+'</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'restart\',\''+version+'\',\'yes\')">重启</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'reload\',\''+version+'\')">重载配置</button>\
</div>';
$(".soft-man-con").html(serviceCon);
}
function orPluginOpService(a, b, v,request_callback) {
var c = "name=" + a + "&func=" + b;
if(v != ''){
c = c + '&version='+v;
}
var d = "";
switch(b) {
case "stop":d = '停止';break;
case "start":d = '启动';break;
case "restart":d = '重启';break;
case "reload":d = '重载';break;
}
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 2}, function() {
caddyPost('get_os',{},function(data){
var rdata = $.parseJSON(data.data);
if (!rdata['auth']){
layer.prompt({title: '检查到权限不足,需要输入密码!', formType: 1},function(pwd, index){
layer.close(index);
var data = {'pwd':pwd};
c += '&args='+JSON.stringify(data);
orPluginOpServiceOp(a,b,c,d,a,v,request_callback);
});
} else {
orPluginOpServiceOp(a,b,c,d,a,v,request_callback);
}
});
})
}
function orPluginOpServiceOp(a,b,c,d,a,v,request_callback){
var request_path = "/plugins/run";
if (request_callback == 'yes'){
request_path = "/plugins/callback";
}
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0});
$.post(request_path, c, function(g) {
layer.close(e);
var f = g.data == 'ok' ? msgTpl('{1}{2}服务已{3}',[a,v,d]) : msgTpl('{1}{2}服务{3}失败!',[a,v,d]);
layer.msg(f, {icon: g.data == 'ok' ? 1 : 2});
if( b != "reload" && g.data == 'ok' ) {
if ( b == 'start' ) {
orPluginSetService(a, true, v);
} else if ( b == 'stop' ){
orPluginSetService(a, false, v);
}
}
if( g.status && g.data != 'ok' ) {
layer.msg(g.data, {icon: 2,time: 10000,shade: 0.3});
}
},'json').error(function() {
layer.close(e);
layer.msg('操作异常!', {icon: 2});
});
}
//查看Nginx负载状态
function getOpStatus() {
var loadT = layer.msg('正在处理,请稍后...', { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'openresty', func:'run_info'}, function(data) {
layer.close(loadT);
try {
var rdata = $.parseJSON(data.data);
if ('status' in rdata && !rdata.status){
showMsg(rdata.msg, function(){}, null,3000);
return;
}
var con = "<div><table class='table table-hover table-bordered'>\
<tr><th>活动连接(Active connections)</th><td>" + rdata.active + "</td></tr>\
<tr><th>总连接次数(accepts)</th><td>" + rdata.accepts + "</td></tr>\
<tr><th>总握手次数(handled)</th><td>" + rdata.handled + "</td></tr>\
<tr><th>总请求数(requests)</th><td>" + rdata.requests + "</td></tr>\
<tr><th>请求数(Reading)</th><td>" + rdata.Reading + "</td></tr>\
<tr><th>响应数(Writing)</th><td>" + rdata.Writing + "</td></tr>\
<tr><th>驻留进程(Waiting)</th><td>" + rdata.Waiting + "</td></tr>\
</table></div>";
$(".soft-man-con").html(con);
}catch(err){
showMsg(data.data, function(){}, null,3000);
}
},'json');
}
function setOpCfg(){
caddyPost('get_cfg', {}, function(data){
var rdata = $.parseJSON(data.data);
var rdata = rdata.data;
// console.log(rdata);
var mlist = '';
for (var i = 0; i < rdata.length; i++) {
var w = '70'
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;
}
mlist += '<p style="margin-top:15px;"><span>' + rdata[i].name + '</span>' + ibody + "<b class='unit c9'>"+rdata[i].unit+"</b>" +', <font class="c9">' + rdata[i].ps + '</font></p>';
}
var con = '<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="setOpCfg()">刷新</button>\
<button class="btn btn-success btn-sm" onclick="submitConf()">保存</button>\
</div>\
</div>'
$(".soft-man-con").html(con);
});
}
function submitConf() {
var data = {
worker_processes: $("input[name='worker_processes']").val(),
worker_connections: $("input[name='worker_connections']").val(),
keepalive_timeout: $("input[name='keepalive_timeout']").val(),
zstd: $("select[name='zstd']").val() || 'on',
brotli: $("select[name='brotli']").val() || 'on',
gzip: $("select[name='gzip']").val() || 'on',
gzip_min_length: $("input[name='gzip_min_length']").val(),
gzip_comp_level: $("input[name='gzip_comp_level']").val(),
client_max_body_size: $("input[name='client_max_body_size']").val(),
server_names_hash_bucket_size: $("input[name='server_names_hash_bucket_size']").val(),
client_header_buffer_size: $("input[name='client_header_buffer_size']").val(),
};
// console.log(data);
caddyPost('set_cfg', data, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
function otherFunc(){
var con = '<p class="conf_p" style="text-align:center;">\
<button class="btn btn-default btn-sm" onclick="cronAddCheck()">添加检查任务</button> \
<button class="btn btn-default btn-sm" onclick="cronDelCheck()">删除检查任务</button>\
</p>';
$(".soft-man-con").html(con);
}
function cronAddCheck(){
caddyPost('cron_add_check', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
function cronDelCheck(){
caddyPost('cron_del_check', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}

124
plugins/caddy/tool_task.py Normal file
View File

@@ -0,0 +1,124 @@
# coding:utf-8
import sys
import io
import os
import time
import json
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
from utils.crontab import crontab as MwCrontab
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'caddy'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/task_config.json"
return conf
def getConfigData():
conf = getTaskConf()
if os.path.exists(conf):
return json.loads(mw.readFile(getTaskConf()))
return {
"task_id": -1,
"period": "minute-n",
"where1": "3",
"hour": "0",
"minute": "0",
}
def createBgTask():
removeBgTask()
createBgTaskByName(getPluginName())
def createBgTaskByName(name):
args = getConfigData()
_name = "[caddy]检查任务"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in args and args["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (args["task_id"],)).find()
if res and res["id"] == args["task_id"]:
print("计划任务已经存在!")
return True
mw_dir = mw.getPanelDir()
cmd = '''
mw_dir=%s
rname=%s
plugin_path=%s
script_path=%s
''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "bash $script_path/check.sh"' + "\n"
cmd += 'cd $mw_dir && bash $script_path/check.sh' + "\n"
params = {
'name': _name,
'type': args['period'],
'week': "",
'where1': args['where1'],
'hour': args['hour'],
'minute': args['minute'],
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'url_address': '',
}
task_id = MwCrontab.instance().add(params)
if task_id > 0:
args["task_id"] = task_id
args["name"] = name
mw.writeFile(getTaskConf(), json.dumps(args))
def removeBgTask():
cfg = getConfigData()
if "task_id" in cfg and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
data = MwCrontab.instance().delete(cfg["task_id"])
if data["status"]:
cfg["task_id"] = -1
mw.writeFile(getTaskConf(), json.dumps(cfg))
return True
return False
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()

View File

@@ -0,0 +1,88 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/caddy && bash install.sh install 2.11
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/caddy && bash install.sh upgrade 2.11
# cd /www/server/mdserver-web/plugins/caddy && bash install.sh install 2.11
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
action=$1
type=$2
OS=`uname`
OSNAME=''
case $(uname) in
Darwin) OSNAME="mac" ;;
Linux) OSNAME="linux" ;;
esac
ARCH=`uname -m`
ARCH_NAME=''
case $(uname -m) in
i386) ARCH_NAME="386" ;;
i686) ARCH_NAME="386" ;;
x86_64) ARCH_NAME="amd64" ;;
arm) ARCH_NAME="arm64" ;;
arm64) ARCH_NAME="arm64" ;;
aarch64) ARCH_NAME="arm64" ;;
esac
VERSION=2.11.2
caddyDir=${serverPath}/source/caddy
Install_App()
{
if [ "${action}" = "install" ];then
if [ -d $serverPath/caddy ];then
exit 0
fi
fi
mkdir -p ${caddyDir}
# mkdir -p ${serverPath}/caddy
echo 'install scripts ...'
FILE_NAME="caddy_${VERSION}_${OSNAME}_${ARCH_NAME}.tar.gz"
if [ ! -f ${caddyDir}/${FILE_NAME} ];then
wget --no-check-certificate -O ${caddyDir}/${FILE_NAME} "https://github.com/caddyserver/caddy/releases/download/v${VERSION}/${FILE_NAME}"
fi
echo "cd $serverPath/source/caddy/caddy && tar -zxvf ${caddyDir}/$FILE_NAME"
mkdir -p cd $serverPath/source/caddy/caddy
cd $serverPath/source/caddy/caddy && tar -zxvf ${caddyDir}/$FILE_NAME
if [ "$OSNAME" = "mac" ];then
xattr -cr caddy
fi
if [ ! -f $serverPath/caddy/bin ];then
mkdir -p $serverPath/caddy/bin
mv $serverPath/source/caddy/caddy/* $serverPath/caddy/bin
chmod +x $serverPath/caddy/bin/caddy
fi
echo 'Installation of caddy completed'
}
Uninstall_App()
{
echo 'Uninstalling caddy completed'
}
action=$1
if [ "${1}" = "install" ];then
Install_App
elif [ "${1}" = "upgrade" ];then
Install_App
else
Uninstall_App
fi

View File

@@ -89,6 +89,11 @@ def initConf():
"/var/log/messages.*",
"/var/log/debug.*",
"/var/log/syslog.*",
"/var/log/syslog",
"/var/log/mail.*",
"/var/log/mail.err.*",
"/var/log/mail.info.*",
"/var/log/mail.warn.*",
"/var/log/btmp.*",
"/var/log/sa/sa*",
"/var/log/sysstat/sa*",
@@ -131,11 +136,13 @@ def initConf():
"/var/log/wtmp",
"/var/log/secure",
"/var/log/lastlog",
"/var/log/syslog",
"/var/log/cron",
"/www/wwwlogs",
"/www/server/rsyncd",
"/www/server/acme_pandominassl_apply",
"/www/server/sphinx/index",
"/www/server/manticoresearch",
"/www/server/mongodb/logs",
"/www/server/php/53/var/log",
"/www/server/php/54/var/log",
@@ -151,17 +158,21 @@ def initConf():
"/www/server/php/82/var/log",
"/www/server/php/83/var/log",
"/www/server/php/84/var/log",
"/www/server/php/85/var/log",
"/www/server/openresty/nginx/logs",
"/www/server/phpmyadmin",
"/www/server/apache/httpd/logs",
"/www/server/redis/data",
"/www/server/alist/data/log",
"/www/server/dztasks/logs",
"/www/server/cron",
"/www/server/rsyncd/lsyncd.log",
"/www/server/mdserver-web/logs",
]
for i in clogcom:
if os.path.exists(i):
content += i + "\n"
content += "/www/server/cron\n"
# 清理日志
rootDir = "/var/log"
@@ -241,7 +252,7 @@ def cleanDirLog(path):
def cleanRun():
plugin_dir = getPluginDir()
log_file = getServerDir()+'/clean.log'
cmd = 'python3 '+plugin_dir+'/index.py clean > '+log_file
cmd = 'cd '+mw.getPanelDir()+' && python3 '+plugin_dir+'/index.py clean > '+log_file
os.system(cmd)
return mw.returnJson(True, '执行成功!')

View File

@@ -1,4 +1,5 @@
{
"sort":2,
"title":"日志清理",
"tip":"soft",
"name":"clean",

View File

@@ -13,7 +13,7 @@ serverPath=$(dirname "$rootPath")
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
. ${rootPath}/bin/activate
fi
@@ -35,7 +35,7 @@ Uninstall_app()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_app
else
Uninstall_app

View File

@@ -113,7 +113,7 @@ def removeBgTask():
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
data = MwCrontab.instance().delete(cfg["task_id"])
if data[0]:
if data["status"]:
cfg["task_id"] = -1
mw.writeFile(getTaskConf(), json.dumps(cfg))
return True

View File

@@ -99,7 +99,7 @@ def readConfigTpl():
def status():
data = mw.execShell(
"ps aux|grep cloudreve |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
"ps -ef|grep cloudreve |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
if data[0] == '':
return 'stop'

View File

@@ -16,16 +16,16 @@ sysArch=`arch`
sysName=`uname`
ALIST_ARCH_NAME=amd64
if [ "$sysArch" == "arm64" ];then
if [ "$sysArch" = "arm64" ];then
ALIST_ARCH_NAME=arm64
elif [ "$sysArch" == "x86_64" ]; then
elif [ "$sysArch" = "x86_64" ]; then
ALIST_ARCH_NAME=amd64
elif [ "$sysArch" == "aarch64" ]; then
elif [ "$sysArch" = "aarch64" ]; then
ALIST_ARCH_NAME=aarch64
fi
ALIST_NAME=linux
if [ "$sysName" == "Darwin" ];then
if [ "$sysName" = "Darwin" ];then
ALIST_NAME=darwin
fi
@@ -83,7 +83,7 @@ Uninstall_App()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_App
else
Uninstall_App

View File

@@ -0,0 +1,78 @@
# plugins_cryptocurrency_trade
- https://docs.ccxt.com/en/latest/install.html#python-proxies
数字货币量化交易插件
```
cd /www/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/okex/strategy/st_demo.py
python3 plugins/cryptocurrency_trade/ccxt/okex/strategy/st_demo.py
miniconda3
```
# 免费TV策略
https://cn.tradingview.com/scripts/?script_type=strategies
### tradingview pine 指标
```
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TenCloud
//@version=5
indicator("第一个指标",shorttitle = "开心吧")
ema10 = ta.ema(close, 25)
ema100 = ta.ema(close, 100)
l1=plot(ema10, color=color.red,title = "ema10")
l2=plot(ema100,color = color.green, title = "ema100")
buy = ta.crossover(ema10,ema100)
sell = ta.crossunder(ema10,ema100)
plotchar(buy, text = "buy", color=color.green)
plotchar(sell, text="sell", color=color.red)
l_color = ema10>ema100 ? color.green:color.red
fill(l1,l2,color=color.new(l_color,70))
```
### tradingview pine 策略
```
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TenCloud
//@version=5
strategy("第一个指标",shorttitle = "开心吧", overlay = true, initial_capital = 1000)
ema10 = ta.ema(close, 25)
ema100 = ta.ema(close, 100)
l1=plot(ema10, color=color.red,title = "ema10")
l2=plot(ema100,color = color.green, title = "ema100")
buy = ta.crossover(ema10,ema100)
sell = ta.crossunder(ema10,ema100)
if buy
strategy.entry("long1", strategy.long,1)
if sell
strategy.close("long1", qty_percent = 100,comment = "平仓多单")
// plotchar(buy, text = "buy", color=color.green)
// plotchar(sell, text="sell", color=color.red)
// l_color = ema10>ema100 ? color.green:color.red
// fill(l1,l2,color=color.new(l_color,70))
```

View File

@@ -0,0 +1,555 @@
import ccxt
from datetime import datetime
import time
import sys
import json
import os
import glob
import threading
from pprint import pprint
# print(os.getcwd())
sys.path.append(os.getcwd() + "/class/core")
import mw
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py run
# python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long
# 查看支持的交易所
# print(ccxt.exchanges)
# 代理设置
# exchange = ccxt.poloniex({
# 'proxies': {
# 'http': 'http://127.0.0.1:1088'
# },
# })
# exchange = ccxt.poloniex()
exchange = ccxt.okex()
def getPluginName():
return 'cryptocurrency_trade'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeLog(log_str):
if __name__ == "__main__":
print(log_str)
log_file = getServerDir() + '/logs/datasource.log'
mw.writeFileLog(log_str, log_file, 1 * 1024 * 1024)
return True
def isSetDbConf():
data = getConfigData()
if 'db' in data:
return True
return False
def beforeDate(day=360):
dd = time.time() - day * 86400
d = datetime.fromtimestamp(dd)
day = d.strftime("%Y-%m-%d")
return day
def getTextTimeShow(time):
d = datetime.fromtimestamp(time)
day = d.strftime("%Y-%m-%d %H:%M:%S")
return day
def isSqlError(mysqlMsg):
# 检测数据库执行错误
mysqlMsg = str(mysqlMsg)
if "MySQLdb" in mysqlMsg:
return mw.returnJson(False, 'MySQLdb组件缺失! <br>进入SSH命令行输入: pip install mysql-python | pip install mysqlclient==2.0.3')
if "2002," in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "2003," in mysqlMsg:
return mw.returnJson(False, "Can't connect to MySQL server on '127.0.0.1' (61)")
if "using password:" in mysqlMsg:
return mw.returnJson(False, '数据库密码错误')
if "1045" in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
def pMysqlDb():
# pymysql
db = mw.getMyORM()
data = getConfigData()
db_data = data['db']
db.setHost(db_data['db_host'])
db.setPort(db_data['db_port'])
db.setUser(db_data['db_user'])
db.setPwd(db_data['db_pass'])
db.setDbName(db_data['db_name'])
return db
def makeInsertSql(table, item):
sql = "insert into " + table
keyStr = '('
valueStr = ' values('
for i in item:
# print i, item[i]
keyStr += '`' + str(i) + '`,'
valueStr += "'" + str(item[i]) + "',"
keyStrLen = len(keyStr)
keyStr = keyStr[0:keyStrLen - 1]
keyStr += ') '
valueStrLen = len(valueStr)
valueStr = valueStr[0:valueStrLen - 1]
valueStr += ') '
sql += keyStr
sql += valueStr
return sql
def makeReplaceSql(table, item):
sql = "replace into " + table
keyStr = '('
valueStr = ' values('
for i in item:
# print i, item[i]
keyStr += '`' + str(i) + '`,'
valueStr += "'" + str(item[i]) + "',"
keyStrLen = len(keyStr)
keyStr = keyStr[0:keyStrLen - 1]
keyStr += ') '
valueStrLen = len(valueStr)
valueStr = valueStr[0:valueStrLen - 1]
valueStr += ') '
sql += keyStr
sql += valueStr
return sql
def makeUpdateSql(table, item, mid):
sql = "update " + table + " set "
keyStr = ''
for i in item:
keyStr += '`' + str(i) + '`=' + "'" + item[i] + "',"
keyStrLen = len(keyStr)
keyStr = keyStr[0:keyStrLen - 1]
sql += keyStr
sql += " where id = '" + str(mid) + "'"
return sql
def dataToDb(table_name, data):
pdb = pMysqlDb()
for i in data:
rdata = {
'addtime': int(i[0] / 1000),
'open': i[1],
'high': i[2],
'low': i[3],
'close': i[4],
'vol': i[5],
}
# sql = """SELECT id FROM %s where addtime='%s' LIMIT 1""" % (
# table_name, rdata['addtime'])
# fdata = pdb.query(sql)
# if fdata:
# print(table_name + ":" + str(rdata['addtime']) + ", old to db ok")
# else:
# isql = makeReplaceSql(table_name, rdata)
# r = pdb.execute(isql)
# print(table_name + ":" + str(rdata['addtime']) + ", go to db ok")
isql = makeReplaceSql(table_name, rdata)
r = pdb.execute(isql)
# print(table_name + ":" + str(rdata['addtime']) + ", go to db ok")
return True
def makeTableName(input_type="btc", input_tf="1m"):
table_name = "ct_%s_%s" % (input_type, input_tf)
return table_name
def isHasTable(input_type="btc", input_tf="1m"):
pdb = pMysqlDb()
# input_type = 'btc'
# input_tf = '1m'
table_name = makeTableName(input_type, input_tf)
mtable = pdb.query("show tables like '%s'" % (table_name,))
if len(mtable) != 0:
return True
return False
def createSql(input_type="btc", input_tf="1m"):
pdb = pMysqlDb()
# input_type = 'btc'
# input_tf = '1m'
table_name = makeTableName(input_type, input_tf)
mtable = pdb.query("show tables like '%s'" % (table_name,))
if len(mtable) != 0:
return True
sql_tpl = getPluginDir() + "/conf/create.sql"
content = mw.readFile(sql_tpl)
content = content.replace("xx1", input_type)
content = content.replace("xx2", input_tf)
res = pdb.execute(content)
# pprint(res)
return True
def getDataFetch(symbol, start_time="2023-3-1", input_tf="1m", limit=500):
start_time = datetime.strptime(start_time, '%Y-%m-%d')
end_time = datetime.strptime(end_time, '%Y-%m-%d')
start_time_stamp = int(time.mktime(start_time.timetuple())) * 1000
data = exchange.fetch_ohlcv(symbol, timeframe=input_tf,
since=start_time_stamp, limit=limit)
return data
def getPointData(symbol, start_time=1677713220000, input_tf="1m", limit=500):
data = exchange.fetch_ohlcv(
symbol, timeframe=input_tf, since=start_time, limit=limit)
return data
def toUnixTimeSecond(tf="1m"):
if tf.find("m") > -1:
v = int(tf.replace("m", ''))
return v * 60
if tf.find("h") > -1:
v = int(tf.replace("h", ''))
return v * 3600
if tf.find("d") > -1:
v = int(tf.replace("d", ''))
return v * 86400
return 0
def findAndUpdateData(tag, input_tf="1m", start_time="2023-1-1", limit=300):
pdb = pMysqlDb()
table_name = makeTableName(tag, input_tf)
sql = 'SELECT addtime FROM ' + table_name + ' order by addtime desc LIMIT 1'
qdata = pdb.query(sql)
start_time = datetime.strptime(start_time, '%Y-%m-%d')
start_time = int(time.mktime(start_time.timetuple())) * 1000
if len(qdata) != 0:
start_time = int(qdata[0]['addtime']) * 1000
pre_time = toUnixTimeSecond(input_tf) * 5 * 1000
start_time = start_time - pre_time
# pprint(start_time)
symbol = tag.upper() + "/USDT"
data = getPointData(symbol, start_time, input_tf, limit)
# pprint(data)
# print("------------lini===========")
# pprint(data[1:])
if len(qdata) == 1:
data = data[1:]
dataToDb(table_name, data)
now = time.strftime("%m/%d %H:%M:%S")
data_len = len(data)
msg_head = now + "|虚拟币:" + tag + ",tf:" + \
input_tf + "!,总数:" + str(data_len)
writeLog(msg_head)
if data_len > 0:
# print("new data time", data[data_len - 1][0])
dt = getTextTimeShow(data[data_len - 1][0] / 1000)
msg = now + "|最新日期:" + dt
writeLog(msg)
table_name = makeTableName(tag, input_tf)
sql = "SELECT addtime FROM " + table_name + \
" order by addtime desc limit 10000,1"
qdata = pdb.query(sql)
if len(qdata) > 0:
print(qdata)
# input_tf_time = toUnixTimeSecond(input_tf)
# now_t = int(time.time())
# del_before_t = now_t - input_tf_time * 1000
sql = "delete from %s where addtime<'%d' " % (
table_name, qdata[0]['addtime'],)
writeLog("删除冗余数据:" + str(sql))
pdb.execute(sql)
return True
def dataToDbTpl(tag='btc', input_tf="1m", start_time="2023-1-1", limit=300):
# tag = "btc"
# tf = "1m"
# start_time = "2023-1-1"
# end_time = "2023-3-2"
symbol = tag.lower() + '/USDT'
if not isHasTable(tag, input_tf):
createSql(tag, input_tf)
data = getDataFetch(symbol, start_time, input_tf, limit)
table_name = makeTableName(tag, input_tf)
dataToDb(table_name, data)
now = time.strftime("%m/%d %H:%M:%S")
data_len = len(data)
writeLog(now + "|数据获取成功!,总数:" + str(data_len))
else:
findAndUpdateData(tag, input_tf, start_time, limit)
return True
def dataToDbList(input_tf="1m", start_time="2023-1-1"):
data = getConfigData()
if not 'token' in data:
writeLog("未设置同步配置,需要添加币种!")
return
for t in data['token']:
dataToDbTpl(t, input_tf, start_time)
time.sleep(4)
def dataRunToDb():
data = getConfigData()
if not 'db' in data:
writeLog("数据库未设置!")
return
tag = "btc"
symbol = tag.upper() + '/USDT'
# pprint(exchange.fetch_ticker('XRP/USDT'))
limit_count = 1
start_time = "2023-1-1"
end_time = "2023-3-2"
tf = "1m"
if not isHasTable(tag, tf):
createSql(tag, tf)
data = getDataFetch(symbol, start_time, end_time, tf, limit_count)
table_name = makeTableName(tag, tf)
dataToDb(table_name, data)
china_datetime = str(datetime.now())
data_len = len(data)
writeLog(china_datetime + ":数据获取成功!,总数:" + str(data_len))
else:
findAndUpdateData(tag, tf, start_time, 30)
return data
def startTask():
# 任务队列
try:
while True:
time.sleep(5)
except Exception as e:
time.sleep(60)
startTask()
def setDaemon(t):
if sys.version_info.major == 3 and sys.version_info.minor >= 10:
t.daemon = True
else:
t.setDaemon(True)
return t
def dataDay():
try:
while True:
if not isSetDbConf():
print("数据库未设置!")
else:
start_time = beforeDate(2 * 365)
dataToDbList("1d", start_time=start_time)
time.sleep(3600)
# time.sleep(10)
except Exception as e:
time.sleep(60)
dataDay()
def data4h():
try:
while True:
if not isSetDbConf():
print("数据库未设置!")
else:
start_time = beforeDate(365)
dataToDbList("4h", start_time=start_time)
time.sleep(10)
except Exception as e:
time.sleep(60)
data4h()
def data1h():
try:
while True:
if not isSetDbConf():
print("数据库未设置!")
else:
start_time = beforeDate(365)
dataToDbList("1h", start_time=start_time)
time.sleep(10)
except Exception as e:
print(e)
time.sleep(60)
data1h()
def data15m():
try:
while True:
if not isSetDbConf():
print("数据库未设置!")
else:
start_time = beforeDate(365)
dataToDbList("15m", start_time=start_time)
time.sleep(10)
except Exception as e:
time.sleep(60)
data15m()
def data5m():
try:
while True:
if not isSetDbConf():
print("数据库未设置!")
else:
start_time = beforeDate(180)
dataToDbList("5m", start_time=start_time)
time.sleep(10)
except Exception as e:
time.sleep(60)
data5m()
def data1m():
try:
while True:
if not isSetDbConf():
print("数据库未设置!")
else:
start_time = beforeDate(30)
dataToDbList("1m", start_time=start_time)
time.sleep(10)
except Exception as e:
time.sleep(60)
data1m()
def longRun():
# 日线
d1_tt = threading.Thread(target=dataDay)
d1_tt = setDaemon(d1_tt)
d1_tt.start()
# 4h
h4_tt = threading.Thread(target=data4h)
h4_tt = setDaemon(h4_tt)
h4_tt.start()
# 1h
h1_tt = threading.Thread(target=data1h)
h1_tt = setDaemon(h1_tt)
h1_tt.start()
# 15m
m15_tt = threading.Thread(target=data15m)
m15_tt = setDaemon(m15_tt)
m15_tt.start()
# 5m
m5_tt = threading.Thread(target=data5m)
m5_tt = setDaemon(m5_tt)
m5_tt.start()
# 1m
# h1m_tt = threading.Thread(target=data1m)
# h1m_tt = setDaemon(h1m_tt)
# h1m_tt.start()
startTask()
def dataRun():
do_num = 0
while True:
if do_num > 1:
break
do_num = do_num + 1
dataRunToDb()
time.sleep(6)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'run':
data5m()()
elif func == 'long':
longRun()
elif func == 'demo':
writeLog('111')
else:
print('error')

View File

@@ -0,0 +1,12 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
# bash plugins/cryptocurrency_trade/ccxt/public_data/data.sh
if [ -f ${curPath}/bin/activate ];then
. ${curPath}/bin/activate
fi
python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long

View File

@@ -0,0 +1,19 @@
import time
from datetime import datetime
china_datetime = datetime.now()
print(china_datetime)
# date()
tt = time.time() - 180 * 86400
# print(date("%Y-%m-%d", time.time()))
# t = datetime.strptime(str(time.time() - 180 * 86400), "%Y-%m-%d")
# print(t)
d = datetime.fromtimestamp(tt)
# 精确到毫秒
str1 = d.strftime("%Y-%m-%d")
print(str1)

View File

@@ -0,0 +1,352 @@
import ccxt
import time
import sys
import json
import os
import glob
import threading
import pandas as pd
from decimal import Decimal
from pprint import pprint
from datetime import datetime
# print(os.getcwd())
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = ccxt.poloniex()
def calc_ClosingPriceWithOutStopLossPrice(open_price, stype='buy', profit=0.5):
# profit 百分比 %
v = 0
vf_len = len(str(open_price).split('.')[1])
if stype == 'buy':
v = open_price * (100 + profit) / 100
else:
v = open_price * (100 - profit) / 100
return round(v, vf_len)
def roundVal(price, compare_price):
price = float(price)
csplite = str(compare_price).split('.')
clen = len(csplite)
if clen == 2:
vf_len = len(csplite[1])
return round(price, vf_len)
return price
def roundValCeil(price, compare_price):
price = float(price)
csplite = str(compare_price).split('.')
clen = len(csplite)
if clen == 2:
vf_len = len(csplite[1]) - 1
return round(price, vf_len)
return price
def multiply(a1, a2):
v = Decimal(str(a1)) * Decimal(str(a2))
return v
def addition(a1, a2):
v = Decimal(str(a1)) + Decimal(str(a2))
return v
def subtract(a1, a2):
v = Decimal(str(a1)) - Decimal(str(a2))
return v
def divided(a1, a2):
v = Decimal(str(a1)) / Decimal(str(a2))
return v
def calc_ClosingPrice(open_price, stop_loss_price, stype='buy', profit=0.5):
# profit 百分比 %
v = 0
vf_len = len(str(open_price).split('.')[1])
if stype == 'buy':
v = open_price * (100 + profit) / 100
diff = open_price - stop_loss_price
profit_price = open_price + diff * 1.5
if profit_price > v:
return round(profit_price, vf_len)
else:
v = open_price * (100 - profit) / 100
diff = stop_loss_price - open_price
profit_price = open_price - diff * 1.5
if profit_price < v:
return round(profit_price, vf_len)
return round(v, vf_len)
def toDateFromInt(time_unix, tf_format="%Y-%m-%d %H:%M:%S", time_zone="Asia/Shanghai"):
# 取格式时间
import time
os.environ['TZ'] = time_zone
time_str = time.localtime(time_unix)
time.tzset()
return time.strftime(tf_format, time_str)
def getPluginName():
return 'cryptocurrency_trade'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def getUserCfgData():
data = getConfigData()
if 'user' in data:
try:
udata = mw.deDoubleCrypt('mw', data['user'])
udata = json.loads(udata)
return udata
except Exception as e:
pass
return []
def initEx():
data = getUserCfgData()
# print(data)
if (len(data) > 0):
exchange = ccxt.okex({
"apiKey": data['app_key'],
"secret": data['secret'],
"password": data['password'],
})
return exchange
else:
print("初始化失败,检查原因!")
exchange = ccxt.poloniex()
return exchange
def toUnixTimeSecond(tf="1m"):
if tf.find("m") > -1:
v = int(tf.replace("m", ''))
return v * 60
if tf.find("h") > -1:
v = int(tf.replace("h", ''))
return v * 3600
if tf.find("d") > -1:
v = int(tf.replace("d", ''))
return v * 86400
return 0
def notifyMsg(msg, tf='15m', tag='btc'):
trigger_time = toUnixTimeSecond(tf)
return mw.notifyMessage(msg, '量化交易/' + tag, trigger_time)
def makeTableName(input_type="btc", input_tf="1m"):
table_name = "ct_%s_%s" % (input_type, input_tf,)
return table_name
def writeLog(log_str):
if __name__ == "__main__":
print(log_str)
log_file = getServerDir() + '/logs/strategy.log'
mw.writeFileLog(log_str, log_file)
return True
def writeLogEx(log_str, tag='btc'):
tag = tag.replace('/', '_')
# 各种币的详细API日志
if __name__ == "__main__":
print(log_str)
log_file = getServerDir() + '/logs/strategy_' + tag + '.log'
mw.writeFileLog(log_str, log_file)
return True
def writeLogErrorEx(log_str, tag='btc'):
tag = tag.replace('/', '_')
# 各种币的详细API日志
if __name__ == "__main__":
print(log_str)
log_file = getServerDir() + '/logs/strategy_' + tag + '.err.log'
mw.writeFileLog(log_str, log_file)
return True
def pMysqlDb():
# pymysql
db = mw.getMyORM()
data = getConfigData()
db_data = data['db']
# print(db_data)
db.setHost(db_data['db_host'])
db.setPort(db_data['db_port'])
db.setUser(db_data['db_user'])
db.setPwd(db_data['db_pass'])
db.setDbName(db_data['db_name'])
return db
def getOnlineData(symbol, input_tf="15m", limit=200):
bars = exchange.fetch_ohlcv(symbol, timeframe=input_tf, limit=limit)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
df['dt'] = pd.to_datetime(df['timestamp'], unit='ms')
return df
def toDataFrame(data):
# print(data)
data = sorted(data, key=lambda x: x["addtime"], reverse=False)
dfield = ['addtime', 'open', 'high', 'low', 'close']
v = {}
for dx in dfield:
v[dx] = []
for x in data:
for i in range(len(x)):
field = dfield[i]
# print(i, field)
v[field].append(x[field])
# pprint(data)
frame = pd.DataFrame(v)
# frame = frame.sort_values(by=['addtime'])
frame['dt'] = pd.to_datetime(frame['addtime'], unit='s')
frame.set_index('dt', inplace=True)
frame.index = frame.index.tz_localize('UTC').tz_convert('Asia/Shanghai')
return frame
def getDataFromDb(tf="1m", tag='btc', limit=1000):
tn = makeTableName(tag, tf)
sql = 'select addtime,open,high,low,close from ' + \
tn + ' order by addtime desc limit ' + str(limit)
pdb = pMysqlDb()
fdata = pdb.query(sql)
# print(fdata)
return fdata
def getDataFromDb_DF(tf="5m", tag='btc', limit=1000):
data = getDataFromDb(tf, tag, limit)
rdata = toDataFrame(data)
return rdata
# 消息模板类
class MsgTpl():
__name = ''
__strategy_name = ''
__time_frame = ''
__content = ''
__open_time = ''
__strategy_dt = ''
__stop_loss_price = ''
__closing_price = ''
__open_price = ''
__msg = ''
def setName(self, name):
self.__name = name
def setStrategyName(self, name):
self.__strategy_name = name
def setTimeFrame(self, tf):
self.__time_frame = tf
def setContent(self, content):
self.__content = content
def setOpenTime(self, time):
self.__open_time = toDateFromInt(time)
def setStrategicDt(self, stype='buy'):
if stype == 'buy':
self.__strategy_dt = '做多'
else:
self.__strategy_dt = '做空'
def setStopLossPrice(self, price):
self.__stop_loss_price = price
def setClosingPrice(self, price):
self.__closing_price = price
def setOpenPrice(self, price):
self.__open_price = price
def setMsg(self, msg):
self.__msg = msg
def toText(self):
msg = ''
msg += '名称:' + self.__name + "\n"
if self.__strategy_name != '':
msg += '策略名称:' + self.__strategy_name + "\n"
if self.__time_frame != '':
msg += '时间周期:' + self.__time_frame + "\n"
if self.__content != '':
msg += '策略描述:' + self.__content + "\n"
if self.__open_time != '':
msg += '开盘时间:' + self.__open_time + "\n"
if self.__strategy_dt != '':
msg += '开仓方向:' + self.__strategy_dt + "\n"
if self.__open_price != '':
msg += '开仓价:' + str(self.__open_price) + "\n"
if self.__stop_loss_price != '':
msg += '止损价:' + str(self.__stop_loss_price) + "\n"
if self.__closing_price != '':
msg += '止盈价:' + str(self.__closing_price) + "\n"
msg += '发送时间:' + mw.getDateFromNow() + "\n"
if self.__msg != '':
msg += __msg
return msg

View File

@@ -0,0 +1,57 @@
# import ccxt
# import talib
import sys
import os
import time
# import pandas as pd
from pprint import pprint
from decimal import Decimal
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/func_test.py run
# common.notifyMsg("任务开始")
def toUnixTimeSecond(tf="1m"):
if tf.find("m") > -1:
v = int(tf.replace("m", ''))
return v * 60
if tf.find("h") > -1:
v = int(tf.replace("h", ''))
return v * 3600
if tf.find("d") > -1:
v = int(tf.replace("d", ''))
return v * 86400
return 0
def multiply(a1, a2):
v = Decimal(str(a1)) * Decimal(str(a2))
return v
# print(toUnixTimeSecond("1d"))
# f = 19911.2
# s = common.calc_ClosingPrice(f, 19890.2, 'buy')
# print(s)
# print(sys.version_info)
# os.environ['TZ'] = 'Europe/London'
# time.tzset()
# t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
# print(t)
# v = multiply(26236.8, 0.003)
# print(float(v))
# print(v)
print(float('0.00255234') + float('-0.00000255234'))
v1 = common.addition('0.00255234', '-0.00000255234')
print(v1)

View File

@@ -0,0 +1,440 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/gate_100.py run
# python3 plugins/cryptocurrency_trade/ccxt/strategy/gate_100.py long
import ccxt
import talib
import sys
import os
import time
import json
import pandas as pd
# import pandas_ta as ta
from pprint import pprint
import numpy as np
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = ccxt.gate({
"apiKey": '756e1ff80526cb0ac9620c75680fc506',
"secret": '95ac89362056bcf12ce37aabff6eb7ec78185483105f39b4a35e8dc8db8b4d3c',
})
exchange.load_markets()
# 默认开仓数据
# default_open_num = 10
default_open = {
"BTC/USDT": 0.01,
'ETH/USDT': 30,
'DOT/USDT': 30,
'CEL/USDT': 30,
}
default_sell = {
"BTC/USDT": 0.01,
'ETH/USDT': 0.01,
'DOT/USDT': 5,
'CEL/USDT': 85,
}
# 做多开仓
def onBuyOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做多----------------------------------', symbol)
default_open_num = default_open[symbol]
# 做多开仓 | 市价
data = exchange.createMarketBuyOrder(
symbol, default_open_num, {"tdMode": "cross"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
# 做多-止损价大于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 - 0.003))
# property_val = float(order_data['info']['accFillSz']) + float(order_data['info']['fee'])
property_val = common.addition(
order_data['info']['accFillSz'], order_data['info']['fee'])
property_val = float(property_val)
# 可平仓的数量
property_val = common.roundValCeil(
property_val, order_data['info']['accFillSz'])
common.writeLogEx('可平仓资产:' + str(property_val), symbol)
# 止盈价
diff = float(open_price) - float(stop_loss_price)
closing_price_c = float(open_price) + (diff * 2)
closing_price = float(open_price) * float((1 + profit))
# 选择盈利多的
if closing_price_c > closing_price:
closing_price = closing_price_c
closing_price = common.roundVal(closing_price, stop_loss_price)
# stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价/止盈价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
# 止损条件单
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
# 止赢条件单
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, closing_price, tp_exchange_params)
common.writeLogEx('止赢数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做多 end----------------------------------', symbol)
return True, open_price, closing_price
def onBuyOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做多开仓
# profit 百分比
try:
return onBuyOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def onSellOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做空----------------------------------', symbol)
# 计算借币卖币多多少,以USDT为基准
# sell_num = float(default_open_num) / float(stop_loss_price)
# sell_num = round(sell_num, 8)
sell_num = default_sell[symbol]
# 做空开仓 | 市价
data = exchange.createMarketSellOrder(
symbol, sell_num, {"tdMode": "cross", 'ccy': "USDT"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
common.writeLogEx('可平仓资产:' + str(sell_num), symbol)
# 做空-止损价小于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 + 0.003))
# 止盈价
diff = float(stop_loss_price) - float(open_price)
closing_price_c = float(open_price) - (diff * 2)
closing_price = float(open_price) * float((1 - profit))
# 选择盈利多的
if closing_price_c < closing_price:
closing_price = closing_price_c
closing_price = common.roundVal(closing_price, open_price)
stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
sl_amount = common.multiply(stop_loss_price, sell_num)
# 解决平仓时,未全部平仓
sl_amount = common.addition(sl_amount, 0.1)
common.writeLogEx('止损总价值:' + str(sl_amount), symbol)
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'buy', float(
sl_amount), stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'buy', sl_amount, stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
# 设置 -止盈价
tp_amount = common.multiply(closing_price, sell_num)
# 解决平仓时,未全部平仓
tp_amount = common.addition(tp_amount, 0.1)
common.writeLogEx('止盈总价值:' + str(tp_amount), symbol)
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'buy', float(
tp_amount), closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'buy', tp_amount, closing_price, tp_exchange_params)
common.writeLogEx('止盈价数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做空 end----------------------------------', symbol)
return True, open_price, closing_price
def onSellOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做空开仓
# profit 百分比
try:
return onSellOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def getOnlineData(symbol, input_tf="15m", limit=230):
bars = exchange.fetch_ohlcv(symbol, timeframe=input_tf, limit=limit)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
df['dt'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('dt', inplace=True)
df.index = df.index.tz_localize('UTC').tz_convert('Asia/Shanghai')
return df
def isKdj(last, last_pre):
# 判断是否是金叉
if (float(last_pre['macd']) < 0) and (float(last['macd']) > 0):
return True
return False
def isDeadFork(last, last_pre):
# 判断是否是死叉
if (float(last_pre['macd']) > 0) and (float(last['macd']) < 0):
return True
return False
def getMACD(df, lenght=-60):
if len(df['close'].values) < 100:
return False, None
close_p = df['close'].values
df['dif'], df['dea'], df['macd'] = talib.MACD(close_p,
fastperiod=12,
slowperiod=26,
signalperiod=9)
return df[lenght:]
def getEMA(df):
close_p = df['close'].values
df['ema'] = talib.EMA(np.array(close_p), timeperiod=200)
return df
def doneMacd(data, tag, timeframe):
data = getEMA(data)
ma_data = getMACD(data)
# alen = len(data)
# print(ma_data)
t_data = ma_data.tail(3)
print(t_data)
last_pre = t_data.iloc[0]
last = t_data.iloc[1]
print(last)
# print(last.index)
# print('close:', last['close'], 'ema:', last['ema'])
obj = common.MsgTpl()
symbol = tag.upper() + '/USDT'
obj.setName(symbol)
obj.setStrategyName("MACD检查")
obj.setTimeFrame(timeframe)
obj.setOpenTime(last['timestamp'] / 1000)
now_data = t_data.iloc[2]
# print('now_data:', now_data)
# msg = obj.toText()
# print(msg)
if isKdj(last, last_pre) and last['close'] > last['ema']:
# if isKdj(last, last_pre):
# closing_price = common.calc_ClosingPrice(
# now_data['close'], last_pre['low'], 'buy')
# # print('closing_price:', closing_price)
# 做多止损点
stop_loss_price = last_pre['low']
buy_status, open_price, closing_price = onBuyOrder(
symbol, stop_loss_price, 0.005, timeframe)
if buy_status:
obj.setStrategicDt('buy')
# 做多止损点
obj.setStopLossPrice(str(stop_loss_price))
obj.setOpenPrice(str(open_price))
obj.setClosingPrice(str(closing_price))
obj.setContent("检查到金叉状态")
msg = obj.toText()
print(msg)
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
if isDeadFork(last, last_pre) and last['close'] < last['ema']:
# if isDeadFork(last, last_pre):
# closing_price = common.calc_ClosingPrice(
# now_data['close'], last_pre['high'], 'sell')
# 做空止损点
stop_loss_price = last_pre['high']
sell_status, open_price, closing_price = onSellOrder(
symbol, stop_loss_price, 0.005, timeframe)
if sell_status:
obj.setStopLossPrice(str(stop_loss_price))
obj.setOpenPrice(str(open_price))
obj.setClosingPrice(str(closing_price))
obj.setStrategicDt('sell')
obj.setContent("检查到死叉状态")
msg = obj.toText()
print(msg)
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
def mainProcess(tag, timeframe='15m'):
symbol = tag.upper() + '/USDT'
data = getOnlineData(symbol, timeframe)
doneMacd(data, tag, timeframe)
def foreachList():
tag_list = ['btc']
for tag in tag_list:
mainProcess(tag, '15m')
time.sleep(1)
def longRun():
while True:
foreachList()
time.sleep(3)
def debug():
while True:
mainProcess('xrp', '1m')
time.sleep(3)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'long':
longRun()
elif func == 'run':
debug()
else:
print('error')

View File

@@ -0,0 +1,138 @@
import ccxt
import talib
import sys
import os
import time
import pandas as pd
import pandas_ta as ta
from pprint import pprint
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/hammer_robot.py run
pd.set_option('display.max_rows', None)
exchange = common.initEx()
exchange.load_markets()
entry_rsi = 30
exit_rsi = 40
symbol = 'XRP/USDT'
timeframe = '15m'
tf_mult = exchange.parse_timeframe(timeframe) * 1000
def indicators(data):
data['rsi'] = data.ta.rsi(length=10)
data['ema'] = data.ta.ema(length=200)
# close_p = data['close'].values
# data['rsi'] = talib.RSI(close_p, timeperiod=10)
# data['ema'] = talib.EMA(close_p, timeperiod=200)
return data
def check_buy_sell_signals(df):
last_row_index = len(df.index) - 1
lastest_rsi = round(df['rsi'].iloc[-1], 2)
lastest_price = round(df['close'].iloc[-1], 5)
lastest_ema = round(df['ema'].iloc[-1], 5)
lastest_ts = df['timestamp'].iloc[-1]
msg = "lastest_rsi:" + str(lastest_rsi) + " < entry_rsi:" + str(entry_rsi)
msg += ",lastest_price:" + \
str(lastest_price) + " > lastest_ema:" + str(lastest_ema)
print(msg)
long_cond = (lastest_rsi < entry_rsi) and (lastest_price > lastest_ema)
if long_cond:
print("买入")
order = exchange.create_market_buy_order(symbol, 1)
closed_orders = exchange.fetchClosedOrders(symbol, limit=2)
if len(closed_orders) > 0:
print("closed_orders:", closed_orders)
most_recent_closed_order = closed_orders[-1]
diff = lastest_ts - most_recent_closed_order['timestamp']
last_buy_signal_cnt = int(diff / tf_mult)
exit_cond = (lastest_rsi > exit_rsi) and (last_buy_signal_cnt > 10)
if exit_cond:
print("卖出")
order = exchange.create_market_sell_order(symbol, 1)
return
def get_hammer(df, lenght):
# 影线要大于body的多少倍
factor = 2
hl_range = df['high'] - df['low']
body_hi = df.apply(lambda x: max(x['close'], x['open']), axis=1)
body_lo = df.apply(lambda x: min(x['close'], x['open']), axis=1)
body = body_hi - body_lo
body_avg = ta.ema(body, lenght=lenght)
small_body = body < body_avg
# 上下影线站body的百分比
shadow_percent = 10
# 上影线
up_shadow = df['high'] - body_hi
dn_shadow = body_lo - df['low']
has_up_shadow = up_shadow > shadow_percent / 100 * body
has_dn_shadow = dn_shadow > shadow_percent / 100 * body
downtrend = df['close'] < ta.ema(df['close'], 50)
bullish_hammer = downtrend & small_body & (body > 0) & (
dn_shadow >= factor * body) & (has_up_shadow == False)
return bullish_hammer
def runBot():
bars = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=200)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
# format='%Y-%m-%d %H:%M:%S',
df['dt'] = pd.to_datetime(
df['timestamp'], unit="ms")
df['hammer'] = get_hammer(df, 10)
lastest_hammer = df.iloc[-1, -1]
lastest_price = df.iloc[-1, 0]
print("lastest_price:" + str(lastest_price))
print("lastest_hammer:" + str(lastest_hammer))
print(df.tail())
if lastest_hammer:
print("购买,做多")
notifyMsg("购买,做多")
def longRunBot():
common.notifyMsg("任务开始")
while True:
runBot()
time.sleep(10)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'run':
longRunBot()
else:
print('error')

View File

@@ -0,0 +1,33 @@
[
{
"id":"01",
"name": "MACD-KDJ策略检测|1h",
"file": "macd_kdj.py"
},
{
"id":"02",
"name": "通知测试|60s",
"file": "notify_demo.py"
},
{
"id":"03",
"name": "okex|macd交易策略|15m",
"file": "online_macd_trade.py"
},
{
"id":"04",
"name": "okex|动量交易策略|5m",
"file": "momentun_trade.py"
},
{
"id":"05",
"name": "gate.io|动量交易策略|5m",
"file": "gate_100.py"
},
{
"id":"06",
"name": "仅提醒|Vega交易策略|5m",
"file": "vega_trade.py"
}
]

View File

@@ -0,0 +1,121 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/macd_kdj.py run
# python3 plugins/cryptocurrency_trade/ccxt/strategy/macd_kdj.py long
import ccxt
import talib
import pandas as pd
import time
import sys
import os
from pprint import pprint
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
pd.set_option('display.max_rows', None)
# import warnings
# warnings.filterwarnings('error')
def getMACD(df, lenght=-60):
if len(df['close'].values) < 100:
return False, None
close_p = df['close'].values
df['dif'], df['dea'], df['macd'] = talib.MACD(close_p,
fastperiod=12,
slowperiod=26,
signalperiod=9)
return True, df[lenght:]
def isKdj(last, last_pre):
# 判断是否是金叉
if (float(last_pre['macd']) < 0) and (float(last['macd']) > 0):
return True
return False
def isDeadFork(last, last_pre):
# 判断是否是死叉
if (float(last_pre['macd']) > 0) and (float(last['macd']) < 0):
return True
return False
def checkData():
tag = 'btc'
tf_frame = '1h'
data = common.getDataFromDb_DF(tf_frame, tag, 300)
# print(data)
b, r = getMACD(data)
if b:
# rlen = len(r)
# r = r.copy()
# r['dt'] = pd.to_datetime(
# r['addtime'], unit='s')
# r['dt'] = r['dt'].dt.tz_convert('Asia/Shanghai')
# print(r)
rlen = len(r)
t_data = r.tail(2)
# print(r.tail(2))
last_pre = t_data.iloc[0]
last = t_data.iloc[1]
# print(last_pre)
# print(last)
# print(last_pre['addtime'])
# print(last_pre['open'])
# print(last_pre['high'])
# print(last_pre['low'])
# print(last_pre['close'])
# print(last['addtime'])
# print(last['open'])
# print(last['high'])
# print(last['low'])
# print(last['close'])
now = mw.getDateFromNow()
if isKdj(last, last_pre):
msg = now + "|{}|{}|检查到金叉状态!".format(tag, tf_frame)
common.notifyMsg(msg, tf_frame, tag)
common.writeLog(msg)
if isDeadFork(last, last_pre):
msg = now + "|{}|{}|检查到死叉状态!".format(tag, tf_frame)
common.notifyMsg(msg, tf_frame, tag)
common.writeLog(msg)
def run():
checkData()
def longRun():
while True:
checkData()
time.sleep(3)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'run':
run()
elif func == 'long':
longRun()
else:
print('error')

View File

@@ -0,0 +1,505 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/momentun_trade.py run
# python3 plugins/cryptocurrency_trade/ccxt/strategy/momentun_trade.py long
# 动量策略交易
import ccxt
import talib
import sys
import os
import time
import json
import pandas as pd
# import pandas_ta as ta
from pprint import pprint
import numpy as np
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = common.initEx()
exchange.load_markets()
# 默认开仓数据
# default_open_num = 70
# default_sell_num = 0.003
default_open = {
'BTC/USDT': 30,
'XRP/USDT': 30,
}
default_sell = {
'BTC/USDT': 0.001,
'XRP/USDT': 100,
}
# 做多开仓
def onBuyOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做多----------------------------------', symbol)
default_open_num = default_open[symbol]
# 做多开仓 | 市价
data = exchange.createMarketBuyOrder(
symbol, default_open_num, {"tdMode": "cross"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
# 修正小数点位数
open_price = common.roundVal(open_price, stop_loss_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
# 做多-止损价大于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 - 0.003))
# property_val = float(order_data['info']['accFillSz']) + float(order_data['info']['fee'])
property_val = common.addition(order_data['info'][
'accFillSz'], order_data['info']['fee'])
property_val = float(property_val)
# 可平仓的数量
# property_val = common.roundValCeil(
# property_val, order_data['info']['accFillSz'])
common.writeLogEx('可平仓资产:' + str(property_val), symbol)
# 止盈价
diff = float(open_price) - float(stop_loss_price)
closing_price = float(open_price) + (diff * 1.5)
# closing_price = float(open_price) * float((1 + profit))
# # 选择盈利多的
# if closing_price_c > closing_price:
# closing_price = closing_price_c
closing_price = common.roundVal(closing_price, open_price)
stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价/止盈价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
# 止损条件单
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
# 止赢条件单
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, closing_price, tp_exchange_params)
common.writeLogEx('止盈数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做多 end----------------------------------', symbol)
return True, open_price, closing_price
def onBuyOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做多开仓
# profit 百分比
try:
return onBuyOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def onSellOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做空----------------------------------', symbol)
# 计算借币卖币多多少,以USDT为基准
# sell_num = float(default_open_num) / float(stop_loss_price)
# sell_num = round(sell_num, 8)
# sell_num = default_sell_num
sell_num = default_sell[symbol]
# 做空开仓 | 市价
data = exchange.createMarketSellOrder(
symbol, sell_num, {"tdMode": "cross", 'ccy': "USDT"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
# 修正
open_price = common.roundVal(open_price, stop_loss_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
common.writeLogEx('可平仓资产:' + str(sell_num), symbol)
# 做空-止损价小于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 + 0.003))
# 止盈价
diff = float(stop_loss_price) - float(open_price)
closing_price = float(open_price) - (diff * 1.5)
# closing_price = float(open_price) * float((1 - profit))
# 选择盈利多的
# if closing_price_c < closing_price:
# closing_price = closing_price_c
closing_price = common.roundVal(closing_price, open_price)
stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
sl_amount = common.multiply(stop_loss_price, sell_num)
# 解决平仓时,未全部平仓
sl_amount = common.addition(sl_amount, 0.1)
common.writeLogEx('止损总价值:' + str(sl_amount), symbol)
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'buy', float(
sl_amount), stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'buy', float(sl_amount), stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
# 设置 -止盈价
# tp_amount = closing_price * sell_num
tp_amount = common.multiply(closing_price, sell_num)
# 解决平仓时,未全部平仓
tp_amount = common.addition(tp_amount, 0.1)
common.writeLogEx('止盈总价值:' + str(tp_amount), symbol)
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'buy', float(
tp_amount), closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'buy', float(tp_amount), closing_price, tp_exchange_params)
common.writeLogEx('止盈价数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做空 end----------------------------------', symbol)
return True, open_price, closing_price
def onSellOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做空开仓
# profit 百分比
try:
return onSellOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def getOnlineData(symbol, input_tf="15m", limit=230):
bars = exchange.fetch_ohlcv(symbol, timeframe=input_tf, limit=limit)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
df['dt'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('dt', inplace=True)
df.index = df.index.tz_localize('UTC').tz_convert('Asia/Shanghai')
return df
def isKdj(last, last_pre):
# 判断是否是金叉
if (float(last_pre['macd']) < 0) and (float(last['macd']) > 0):
return True
return False
def isDeadFork(last, last_pre):
# 判断是否是死叉
if (float(last_pre['macd']) > 0) and (float(last['macd']) < 0):
return True
return False
def getMACD(df, lenght=-60):
if len(df['close'].values) < 100:
return False, None
close_p = df['close'].values
df['dif'], df['dea'], df['macd'] = talib.MACD(close_p,
fastperiod=12,
slowperiod=26,
signalperiod=9)
return df[lenght:]
def getTarget(df):
close = df['close'].values
df['ema'] = talib.EMA(np.array(close), timeperiod=10)
df['ema_200'] = talib.EMA(np.array(close), timeperiod=200)
df['ma'] = talib.MA(close, timeperiod=10)
df['rsi'] = talib.RSI(close, timeperiod=14)
return df
# 多头信号
def isBuyCrondSignal(last):
if last['ema'] > last['ma'] and (last['rsi'] > 50 and last['rsi'] < 70) and last['low'] >= last['ma'] and last['close'] > last['open']:
return True
return False
def isBuyFristSignal(data):
data = data.sort_values(by=['timestamp'], ascending=False)
# print(data)
data_len = len(data)
signal_num = 0
first_data = data.iloc[1]
# print(1, first_data['close'], first_data['ema'])
is_buy_signal = isBuyCrondSignal(first_data)
for x in range(2, data_len):
tmp = data.iloc[x]
# print(data.iloc[x])
# print(x, tmp['close'], tmp['ema'])
if isBuyCrondSignal(tmp):
signal_num = + 1
# print('signal_num:', signal_num)
if (tmp['ema'] < tmp['ma']):
break
if str(tmp['ema']) == 'nan':
break
print("is_buy_signal:", is_buy_signal, 'signal_num:', signal_num)
if is_buy_signal and signal_num == 0:
return True
return False
# 空头信号
def isSellCrondSignal(last):
if last['ema'] < last['ma'] and (last['rsi'] > 30 and last['rsi'] < 50) and last['high'] <= last['ema'] and last['close'] < last['open']:
return True
return False
def isSellFristSignal(data):
data = data.sort_values(by=['timestamp'], ascending=False)
# print(data)
data_len = len(data)
signal_num = 0
first_data = data.iloc[1]
# print(1, first_data['close'], first_data['ema'])
is_sell_signal = isSellCrondSignal(first_data)
for x in range(2, data_len):
tmp = data.iloc[x]
# print(data.iloc[x])
# print(x, tmp['close'], tmp['ema'])
if isSellCrondSignal(tmp):
signal_num = + 1
# print('signal_num:', signal_num)
if (tmp['ema'] < tmp['ma']):
break
if str(tmp['ema']) == 'nan':
break
print("is_sell_signal:", is_sell_signal, 'signal_num:', signal_num)
if is_sell_signal and signal_num == 0:
return True
return False
def monentunTrade(data, tag, timeframe):
data = getTarget(data)
# print(data)
key_data = data.tail(3)
print(key_data)
last_pre = key_data.iloc[0]
last = key_data.iloc[1]
obj = common.MsgTpl()
symbol = tag.upper() + '/USDT'
obj.setName(symbol)
obj.setStrategyName("动量交易策略")
obj.setTimeFrame(timeframe)
obj.setOpenTime(last['timestamp'] / 1000)
# 买入信号,并且收盘价要大于200 ema
if isBuyFristSignal(data) and last['close'] > last['ema_200']:
obj.setStrategicDt('buy')
# 做多止损点
stop_loss_price = last['ma']
stop_loss_price = common.roundVal(stop_loss_price, last['open'])
buy_status, open_price, closing_price = onBuyOrder(
symbol, stop_loss_price, 0.005, timeframe)
if buy_status:
# 做多止损点
obj.setStopLossPrice(str(stop_loss_price))
obj.setOpenPrice(str(open_price))
obj.setClosingPrice(str(closing_price))
obj.setContent("动量交易策略做多!")
msg = obj.toText()
print(msg)
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
# 卖出信号,并且收盘价要小于200 ema
# if isSellFristSignal(data) and last['close'] < last['ema_200']:
# obj.setStrategicDt('sell')
# stop_loss_price = last['ma']
# stop_loss_price = common.roundVal(stop_loss_price, last['open'])
# sell_status, open_price, closing_price = onSellOrder(
# symbol, stop_loss_price, 0.005, timeframe)
# if sell_status:
# obj.setStopLossPrice(str(stop_loss_price))
# obj.setOpenPrice(str(open_price))
# obj.setClosingPrice(str(closing_price))
# obj.setStrategicDt('sell')
# obj.setContent("动量交易策略作空!")
# msg = obj.toText()
# print(msg)
# common.notifyMsg(msg, timeframe, tag)
# common.writeLog(msg)
def mainProcess(tag, timeframe='15m'):
symbol = tag.upper() + '/USDT'
data = getOnlineData(symbol, timeframe)
monentunTrade(data, tag, timeframe)
def foreachList():
tag_list = ['btc', 'xrp']
for tag in tag_list:
mainProcess(tag, '15m')
time.sleep(1)
def longRun():
while True:
foreachList()
time.sleep(1)
def debug():
while True:
mainProcess('btc', '5m')
time.sleep(1)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'long':
longRun()
elif func == 'run':
debug()
else:
print('error')

View File

@@ -0,0 +1,48 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/notify_demo.py run
# python3 plugins/cryptocurrency_trade/ccxt/strategy/notify_demo.py long
import ccxt
import talib
import pandas as pd
import time
import sys
import os
from pprint import pprint
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
def run():
print('debug')
def longRun():
while True:
obj = common.MsgTpl()
obj.setName("通知测试")
obj.setStrategyName("无")
obj.setTimeFrame("1m")
obj.setContent("60s通知测试")
msg = obj.toText()
print(msg)
common.notifyMsg(msg, '1m', 'debug')
common.writeLog(msg)
time.sleep(3)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'run':
run()
if func == 'long':
longRun()
else:
print('error')

View File

@@ -0,0 +1,294 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_buy_open
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_buy_close
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_sell_open
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_sell_cloe
# 获取仓位数据
# python3 plugins/cryptocurrency_trade/ccxt/strategy/on_g_test.py t_get_trade
# API地址
# https://www.gate.io/docs/developers/apiv4/zh_CN/#api
import ccxt
import talib
import sys
import os
import time
import pandas as pd
# import pandas_ta as ta
from pprint import pprint
import numpy as np
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = ccxt.gate({
"apiKey": '756e1ff80526cb0ac9620c75680fc506',
"secret": '95ac89362056bcf12ce37aabff6eb7ec78185483105f39b4a35e8dc8db8b4d3c',
})
exchange.load_markets()
def t_get_trade():
data = exchange.fetchPositions()
print(data)
def btc_test():
closing_price = 24599.9
stop_loss_price = 24740.4
# ---------------------------
stop_loss_args = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
print('---------止损价 执行 START ----------------------------------')
sl_amount = stop_loss_price * 0.001
print(amount)
data = exchange.create_order(
'BTC/USDT', 'limit', 'buy', sl_amount, stop_loss_price, stop_loss_args)
print(data)
print('---------止损价 执行 END ----------------------------------')
print('---------止盈价 执行 START ----------------------------------')
closing_price_args = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
cp_amount = closing_price * 0.001
print(amount)
data = exchange.create_order(
'BTC/USDT', 'limit', 'buy', cp_amount, closing_price, closing_price_args)
print(data)
print('---------止盈价 执行 END ----------------------------------')
def testK_buy_open_sz():
# 做多开仓
data = exchange.fetchTicker('BTC/USDT')
print(data)
# data = exchange.createMarketBuyOrder('DOT/USDT', 1, {"tdMode": "cross"})
# print(data)
# print(type(data))
def testK_buy_open():
# 做多开仓
# print(dir(exchange))
# exchange['options']['createMarketBuyOrderRequiresPrice'] = False
data = exchange.fetch_ticker('BTC/USDT')
print("now price:", data['ask'])
amount = 0.001
price = data['ask']
cost = amount * float(price)
print('total price:', cost)
print('amount price:', amount)
# a_amount = round(amount / data['ask'], 5)
# print('amount :', amount)
# print('amount :', str(amount))
#
data = exchange.createOrder(
"BTC/USDT", type="limit", side="buy", amount=amount, price=price, params={'account': "cross_margin"})
# data = exchange.createMarketBuyOrder('BTC/USDT', amount)
print(data)
print(type(data))
# 数据
# {'info': {'clOrdId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'ordId': '554437054223302656', 'sCode': '0', 'sMsg': 'Order placed', 'tag': 'e847386590ce4dBC'}, 'id': '554437054223302656', 'clientOrderId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'timestamp': None, 'datetime': None, 'lastTradeTimestamp': None, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': None, 'postOnly': None, 'side': 'buy', 'price': None, 'stopPrice': None, 'triggerPrice': None, 'average': None, 'cost': None, 'amount': None, 'filled': None, 'remaining': None, 'status': None, 'fee': None, 'trades': [], 'reduceOnly': None, 'fees': []}
# 查询委托单
# order_id = data['info']['ordId']
# order_id = '554437054223302656'
# data = exchange.fetchOrder(order_id, 'BTC/USDT')
# print(data['info'])
# {'info': {'accFillSz': '0.190548', 'algoClOrdId': '', 'algoId': '', 'avgPx': '5.248', 'cTime': '1678441709955', 'cancelSource': '', 'cancelSourceReason': '', 'category': 'normal', 'ccy': 'USDT', 'clOrdId': 'e847386590ce4dBCeaddfd1494dc7080', 'fee': '-0.000190548', 'feeCcy': 'DOT', 'fillPx': '5.248', 'fillSz': '0.190548', 'fillTime': '1678441709957', 'instId': 'DOT-USDT', 'instType': 'MARGIN', 'lever': '10', 'ordId': '554359943143833600', 'ordType': 'market', 'pnl': '0', 'posSide': 'net', 'px': '', 'quickMgnType': '', 'rebate': '0', 'rebateCcy': 'USDT', 'reduceOnly': 'false', 'side': 'buy', 'slOrdPx': '', 'slTriggerPx': '', 'slTriggerPxType': '', 'source': '', 'state': 'filled', 'sz': '1', 'tag': 'e847386590ce4dBC', 'tdMode': 'cross', 'tgtCcy': '', 'tpOrdPx': '', 'tpTriggerPx': '', 'tpTriggerPxType': '', 'tradeId': '81184616', 'uTime': '1678441709960'}, 'id': '554359943143833600', 'clientOrderId': 'e847386590ce4dBCeaddfd1494dc7080', 'timestamp': 1678441709955, 'datetime': '2023-03-10T09:48:29.955Z', 'lastTradeTimestamp': 1678441709957, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': 'IOC', 'postOnly': None, 'side': 'buy', 'price': 5.248, 'stopPrice': None, 'triggerPrice': None, 'average': 5.248, 'cost': 0.999995904, 'amount': 1.0, 'filled': 0.190548, 'remaining': 0.809452, 'status': 'closed', 'fee': {'cost': 0.000190548, 'currency': 'DOT'}, 'trades': [], 'reduceOnly': False, 'fees': [{'cost': 0.000190548, 'currency': 'DOT'}]}
# open_price = data['info']['avgPx']
# print("开仓平均价", open_price)
# # 止盈价
# closing_price = float(open_price) * float((1 + 0.005))
# closing_price = common.roundVal(closing_price, open_price)
# print("止盈价", closing_price)
# # 止损价
# stop_loss_price = float(open_price) * float((1 - 0.01))
# stop_loss_price = common.roundVal(stop_loss_price, open_price)
# print("止损价", stop_loss_price)
# property_val = float(data['info']['accFillSz']) + \
# float(data['info']['fee'])
# # 相同位数
# property_val = common.roundValCeil(property_val, data['info']['accFillSz'])
# print("可平仓资产", property_val)
# closed_orders = exchange.fetchClosedOrders('DOT/USDT', limit=2)
# print('closed_orders', closed_orders)
# print(exchange.fetchBalance())
# 可以用,限价单
# time.sleep(1)
# data = exchange.createLimitSellOrder(
# 'DOT/USDT', property_val, closing_price, {"tdMode": "cross", 'ccy': 'USDT', "reduceOnly": True})
# print(data)
# print(type(data))
# 止损价
# 止盈价
# exchange_params = {
# 'ccy': "USDT",
# 'reduceOnly': True,
# 'tdMode': "cross",
# 'tpOrdPx': "-1",
# 'tpTriggerPx': closing_price,
# 'slOrdPx': "-1",
# 'slTriggerPx': stop_loss_price,
# }
# print('---------止损价 执行----------------------------------')
# data = exchange.create_order(
# 'BTC/USDT', 'limit', 'sell', property_val, closing_price, exchange_params)
# print(data)
# print(type(data))
# print('---------止盈价 执行----------------------------------')
# exchange_params = {
# 'stopPrice': closing_price,
# 'type': 'stopLimit',
# }
# data = exchange.create_order(
# 'DOT/USDT', 'limit', 'sell', property_val, closing_price, exchange_params)
# print(data)
# print(type(data))
def testK_buy_close():
# 平多
data = exchange.create_limit_buy_order(
'DOT/USDT', 1, 5, {"tdMode": "cross"})
print(data)
print(type(data))
# closed_orders = exchange.fetchClosedOrders('BTC/USDT', limit=2)
# print(closed_orders)
# closed_orders = exchange.fetchMyTrades('ETH/USDT', limit=2)
# print(closed_orders)
def testK_sell_open():
# 做空开仓
# data = exchange.createMarketSellOrder(
# 'DOT/USDT', 1, {"tdMode": "cross", 'ccy': "USDT", })
# print(data)
# print(type(data))
# 数据
# {'info': {'clOrdId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'ordId': '554437054223302656', 'sCode': '0', 'sMsg': 'Order placed', 'tag': 'e847386590ce4dBC'}, 'id': '554437054223302656', 'clientOrderId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'timestamp': None, 'datetime': None, 'lastTradeTimestamp': None, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': None, 'postOnly': None, 'side': 'buy', 'price': None, 'stopPrice': None, 'triggerPrice': None, 'average': None, 'cost': None, 'amount': None, 'filled': None, 'remaining': None, 'status': None, 'fee': None, 'trades': [], 'reduceOnly': None, 'fees': []}
# # 查询委托单
# order_id = data['info']['ordId']
order_id = '554516809819832320'
data = exchange.fetchOrder(order_id, 'DOT/USDT')
print(data['info'])
# {'info': {'accFillSz': '0.190548', 'algoClOrdId': '', 'algoId': '', 'avgPx': '5.248', 'cTime': '1678441709955', 'cancelSource': '', 'cancelSourceReason': '', 'category': 'normal', 'ccy': 'USDT', 'clOrdId': 'e847386590ce4dBCeaddfd1494dc7080', 'fee': '-0.000190548', 'feeCcy': 'DOT', 'fillPx': '5.248', 'fillSz': '0.190548', 'fillTime': '1678441709957', 'instId': 'DOT-USDT', 'instType': 'MARGIN', 'lever': '10', 'ordId': '554359943143833600', 'ordType': 'market', 'pnl': '0', 'posSide': 'net', 'px': '', 'quickMgnType': '', 'rebate': '0', 'rebateCcy': 'USDT', 'reduceOnly': 'false', 'side': 'buy', 'slOrdPx': '', 'slTriggerPx': '', 'slTriggerPxType': '', 'source': '', 'state': 'filled', 'sz': '1', 'tag': 'e847386590ce4dBC', 'tdMode': 'cross', 'tgtCcy': '', 'tpOrdPx': '', 'tpTriggerPx': '', 'tpTriggerPxType': '', 'tradeId': '81184616', 'uTime': '1678441709960'}, 'id': '554359943143833600', 'clientOrderId': 'e847386590ce4dBCeaddfd1494dc7080', 'timestamp': 1678441709955, 'datetime': '2023-03-10T09:48:29.955Z', 'lastTradeTimestamp': 1678441709957, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': 'IOC', 'postOnly': None, 'side': 'buy', 'price': 5.248, 'stopPrice': None, 'triggerPrice': None, 'average': 5.248, 'cost': 0.999995904, 'amount': 1.0, 'filled': 0.190548, 'remaining': 0.809452, 'status': 'closed', 'fee': {'cost': 0.000190548, 'currency': 'DOT'}, 'trades': [], 'reduceOnly': False, 'fees': [{'cost': 0.000190548, 'currency': 'DOT'}]}
open_price = data['info']['avgPx']
print("开仓平均价", open_price)
# 止盈价
closing_price = float(open_price) * float((1 - 0.005))
closing_price = common.roundVal(closing_price, open_price)
print("止盈价", closing_price)
# 止损价
stop_loss_price = float(open_price) * float((1 + 0.01))
stop_loss_price = common.roundVal(stop_loss_price, open_price)
print("止损价", stop_loss_price)
property_val = float(data['info']['accFillSz'])
# 相同位数
print("可平仓资产", property_val)
# 止损价
# 止盈价
exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
print('---------止损价 执行----------------------------------')
data = exchange.create_order(
'DOT/USDT', 'limit', 'buy', property_val, closing_price, exchange_params)
print(data)
print(type(data))
def testK_sell_close():
# 平多
data = exchange.create_limit_buy_order(
'DOT/USDT', 1, 5, {"tdMode": "cross"})
print(data)
print(type(data))
# closed_orders = exchange.fetchClosedOrders('BTC/USDT', limit=2)
# print(closed_orders)
# closed_orders = exchange.fetchMyTrades('ETH/USDT', limit=2)
# print(closed_orders)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'long':
longRun()
elif func == 'run':
debug()
elif func == 'test':
testKdan()
elif func == 't_get_trade':
t_get_trade()
elif func == 't_buy_open':
testK_buy_open()
elif func == 't_buy_close':
testK_buy_close()
elif func == 't_sell_open':
testK_sell_open()
elif func == 't_sell_cloe':
testK_sell_close()
else:
print('error')

View File

@@ -0,0 +1,437 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_macd_trade.py run
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_macd_trade.py long
import ccxt
import talib
import sys
import os
import time
import json
import pandas as pd
# import pandas_ta as ta
from pprint import pprint
import numpy as np
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = common.initEx()
exchange.load_markets()
# 默认开仓数据
# default_open_num = 10
default_open = {
'ETH/USDT': 30,
'DOT/USDT': 30,
'CEL/USDT': 30,
}
default_sell = {
'ETH/USDT': 0.02,
'DOT/USDT': 5,
'CEL/USDT': 85,
}
# 做多开仓
def onBuyOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做多----------------------------------', symbol)
default_open_num = default_open[symbol]
# 做多开仓 | 市价
data = exchange.createMarketBuyOrder(
symbol, default_open_num, {"tdMode": "cross"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
# 做多-止损价大于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 - 0.003))
# property_val = float(order_data['info']['accFillSz']) + float(order_data['info']['fee'])
property_val = common.addition(
order_data['info']['accFillSz'], order_data['info']['fee'])
property_val = float(property_val)
# 可平仓的数量
property_val = common.roundValCeil(
property_val, order_data['info']['accFillSz'])
common.writeLogEx('可平仓资产:' + str(property_val), symbol)
# 止盈价
diff = float(open_price) - float(stop_loss_price)
closing_price_c = float(open_price) + (diff * 2)
closing_price = float(open_price) * float((1 + profit))
# 选择盈利多的
if closing_price_c > closing_price:
closing_price = closing_price_c
closing_price = common.roundVal(closing_price, stop_loss_price)
# stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价/止盈价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
# 止损条件单
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
# 止赢条件单
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, closing_price, tp_exchange_params)
common.writeLogEx('止赢数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做多 end----------------------------------', symbol)
return True, open_price, closing_price
def onBuyOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做多开仓
# profit 百分比
try:
return onBuyOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def onSellOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做空----------------------------------', symbol)
# 计算借币卖币多多少,以USDT为基准
# sell_num = float(default_open_num) / float(stop_loss_price)
# sell_num = round(sell_num, 8)
sell_num = default_sell[symbol]
# 做空开仓 | 市价
data = exchange.createMarketSellOrder(
symbol, sell_num, {"tdMode": "cross", 'ccy': "USDT"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
common.writeLogEx('可平仓资产:' + str(sell_num), symbol)
# 做空-止损价小于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 + 0.003))
# 止盈价
diff = float(stop_loss_price) - float(open_price)
closing_price_c = float(open_price) - (diff * 2)
closing_price = float(open_price) * float((1 - profit))
# 选择盈利多的
if closing_price_c < closing_price:
closing_price = closing_price_c
closing_price = common.roundVal(closing_price, open_price)
stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
sl_amount = common.multiply(stop_loss_price, sell_num)
# 解决平仓时,未全部平仓
sl_amount = common.addition(sl_amount, 0.1)
common.writeLogEx('止损总价值:' + str(sl_amount), symbol)
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'buy', float(
sl_amount), stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'buy', sl_amount, stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
# 设置 -止盈价
tp_amount = common.multiply(closing_price, sell_num)
# 解决平仓时,未全部平仓
tp_amount = common.addition(tp_amount, 0.1)
common.writeLogEx('止盈总价值:' + str(tp_amount), symbol)
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'buy', float(
tp_amount), closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'buy', tp_amount, closing_price, tp_exchange_params)
common.writeLogEx('止盈价数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做空 end----------------------------------', symbol)
return True, open_price, closing_price
def onSellOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做空开仓
# profit 百分比
try:
return onSellOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def getOnlineData(symbol, input_tf="15m", limit=230):
bars = exchange.fetch_ohlcv(symbol, timeframe=input_tf, limit=limit)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
df['dt'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('dt', inplace=True)
df.index = df.index.tz_localize('UTC').tz_convert('Asia/Shanghai')
return df
def isKdj(last, last_pre):
# 判断是否是金叉
if (float(last_pre['macd']) < 0) and (float(last['macd']) > 0):
return True
return False
def isDeadFork(last, last_pre):
# 判断是否是死叉
if (float(last_pre['macd']) > 0) and (float(last['macd']) < 0):
return True
return False
def getMACD(df, lenght=-60):
if len(df['close'].values) < 100:
return False, None
close_p = df['close'].values
df['dif'], df['dea'], df['macd'] = talib.MACD(close_p,
fastperiod=12,
slowperiod=26,
signalperiod=9)
return df[lenght:]
def getEMA(df):
close_p = df['close'].values
df['ema'] = talib.EMA(np.array(close_p), timeperiod=200)
return df
def doneMacd(data, tag, timeframe):
data = getEMA(data)
ma_data = getMACD(data)
# alen = len(data)
# print(ma_data)
t_data = ma_data.tail(3)
# print(t_data)
last_pre = t_data.iloc[0]
last = t_data.iloc[1]
# print(last)
# print(last.index)
# print('close:', last['close'], 'ema:', last['ema'])
obj = common.MsgTpl()
symbol = tag.upper() + '/USDT'
obj.setName(symbol)
obj.setStrategyName("MACD检查")
obj.setTimeFrame(timeframe)
obj.setOpenTime(last['timestamp'] / 1000)
now_data = t_data.iloc[2]
# print('now_data:', now_data)
# msg = obj.toText()
# print(msg)
if isKdj(last, last_pre) and last['close'] > last['ema']:
# if isKdj(last, last_pre):
# closing_price = common.calc_ClosingPrice(
# now_data['close'], last_pre['low'], 'buy')
# # print('closing_price:', closing_price)
# 做多止损点
stop_loss_price = last_pre['low']
buy_status, open_price, closing_price = onBuyOrder(
symbol, stop_loss_price, 0.005, timeframe)
if buy_status:
obj.setStrategicDt('buy')
# 做多止损点
obj.setStopLossPrice(str(stop_loss_price))
obj.setOpenPrice(str(open_price))
obj.setClosingPrice(str(closing_price))
obj.setContent("检查到金叉状态")
msg = obj.toText()
print(msg)
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
if isDeadFork(last, last_pre) and last['close'] < last['ema']:
# if isDeadFork(last, last_pre):
# closing_price = common.calc_ClosingPrice(
# now_data['close'], last_pre['high'], 'sell')
# 做空止损点
stop_loss_price = last_pre['high']
sell_status, open_price, closing_price = onSellOrder(
symbol, stop_loss_price, 0.005, timeframe)
if sell_status:
obj.setStopLossPrice(str(stop_loss_price))
obj.setOpenPrice(str(open_price))
obj.setClosingPrice(str(closing_price))
obj.setStrategicDt('sell')
obj.setContent("检查到死叉状态")
msg = obj.toText()
print(msg)
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
def mainProcess(tag, timeframe='15m'):
symbol = tag.upper() + '/USDT'
data = getOnlineData(symbol, timeframe)
doneMacd(data, tag, timeframe)
def foreachList():
tag_list = [
'eth', 'dot'
]
for tag in tag_list:
mainProcess(tag, '15m')
time.sleep(1)
def longRun():
while True:
foreachList()
time.sleep(3)
def debug():
while True:
mainProcess('xrp', '1m')
time.sleep(3)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'long':
longRun()
elif func == 'run':
debug()
else:
print('error')

View File

@@ -0,0 +1,273 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_buy_open
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_buy_close
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_sell_open
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_sell_cloe
# 获取仓位数据
# python3 plugins/cryptocurrency_trade/ccxt/strategy/online_test.py t_get_trade
import ccxt
import talib
import sys
import os
import time
import pandas as pd
# import pandas_ta as ta
from pprint import pprint
import numpy as np
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = common.initEx()
exchange.load_markets()
def t_get_trade():
data = exchange.fetchPositions()
print(data)
def btc_test():
closing_price = 24599.9
stop_loss_price = 24740.4
# ---------------------------
stop_loss_args = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
print('---------止损价 执行 START ----------------------------------')
sl_amount = stop_loss_price * 0.003
print(amount)
data = exchange.create_order(
'BTC/USDT', 'limit', 'buy', sl_amount, stop_loss_price, stop_loss_args)
print(data)
print('---------止损价 执行 END ----------------------------------')
print('---------止盈价 执行 START ----------------------------------')
closing_price_args = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
cp_amount = closing_price * 0.003
print(amount)
data = exchange.create_order(
'BTC/USDT', 'limit', 'buy', cp_amount, closing_price, closing_price_args)
print(data)
print('---------止盈价 执行 END ----------------------------------')
def testK_buy_open_sz():
# 做多开仓
data = exchange.fetchTicker('DOT/USDT')
print(data)
# data = exchange.createMarketBuyOrder('DOT/USDT', 1, {"tdMode": "cross"})
# print(data)
# print(type(data))
def testK_buy_open():
# 做多开仓
data = exchange.createMarketBuyOrder(
'DOT/USDT', 1, {"tdMode": "cross"})
print(data)
print(type(data))
# 数据
# {'info': {'clOrdId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'ordId': '554437054223302656', 'sCode': '0', 'sMsg': 'Order placed', 'tag': 'e847386590ce4dBC'}, 'id': '554437054223302656', 'clientOrderId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'timestamp': None, 'datetime': None, 'lastTradeTimestamp': None, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': None, 'postOnly': None, 'side': 'buy', 'price': None, 'stopPrice': None, 'triggerPrice': None, 'average': None, 'cost': None, 'amount': None, 'filled': None, 'remaining': None, 'status': None, 'fee': None, 'trades': [], 'reduceOnly': None, 'fees': []}
# 查询委托单
order_id = data['info']['ordId']
# order_id = '554437054223302656'
data = exchange.fetchOrder(order_id, 'DOT/USDT')
print(data['info'])
# {'info': {'accFillSz': '0.190548', 'algoClOrdId': '', 'algoId': '', 'avgPx': '5.248', 'cTime': '1678441709955', 'cancelSource': '', 'cancelSourceReason': '', 'category': 'normal', 'ccy': 'USDT', 'clOrdId': 'e847386590ce4dBCeaddfd1494dc7080', 'fee': '-0.000190548', 'feeCcy': 'DOT', 'fillPx': '5.248', 'fillSz': '0.190548', 'fillTime': '1678441709957', 'instId': 'DOT-USDT', 'instType': 'MARGIN', 'lever': '10', 'ordId': '554359943143833600', 'ordType': 'market', 'pnl': '0', 'posSide': 'net', 'px': '', 'quickMgnType': '', 'rebate': '0', 'rebateCcy': 'USDT', 'reduceOnly': 'false', 'side': 'buy', 'slOrdPx': '', 'slTriggerPx': '', 'slTriggerPxType': '', 'source': '', 'state': 'filled', 'sz': '1', 'tag': 'e847386590ce4dBC', 'tdMode': 'cross', 'tgtCcy': '', 'tpOrdPx': '', 'tpTriggerPx': '', 'tpTriggerPxType': '', 'tradeId': '81184616', 'uTime': '1678441709960'}, 'id': '554359943143833600', 'clientOrderId': 'e847386590ce4dBCeaddfd1494dc7080', 'timestamp': 1678441709955, 'datetime': '2023-03-10T09:48:29.955Z', 'lastTradeTimestamp': 1678441709957, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': 'IOC', 'postOnly': None, 'side': 'buy', 'price': 5.248, 'stopPrice': None, 'triggerPrice': None, 'average': 5.248, 'cost': 0.999995904, 'amount': 1.0, 'filled': 0.190548, 'remaining': 0.809452, 'status': 'closed', 'fee': {'cost': 0.000190548, 'currency': 'DOT'}, 'trades': [], 'reduceOnly': False, 'fees': [{'cost': 0.000190548, 'currency': 'DOT'}]}
open_price = data['info']['avgPx']
print("开仓平均价", open_price)
# 止盈价
closing_price = float(open_price) * float((1 + 0.005))
closing_price = common.roundVal(closing_price, open_price)
print("止盈价", closing_price)
# 止损价
stop_loss_price = float(open_price) * float((1 - 0.01))
stop_loss_price = common.roundVal(stop_loss_price, open_price)
print("止损价", stop_loss_price)
property_val = float(data['info']['accFillSz']) + \
float(data['info']['fee'])
# 相同位数
property_val = common.roundValCeil(property_val, data['info']['accFillSz'])
print("可平仓资产", property_val)
# closed_orders = exchange.fetchClosedOrders('DOT/USDT', limit=2)
# print('closed_orders', closed_orders)
# print(exchange.fetchBalance())
# 可以用,限价单
# time.sleep(1)
# data = exchange.createLimitSellOrder(
# 'DOT/USDT', property_val, closing_price, {"tdMode": "cross", 'ccy': 'USDT', "reduceOnly": True})
# print(data)
# print(type(data))
# 止损价
# 止盈价
exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
print('---------止损价 执行----------------------------------')
data = exchange.create_order(
'DOT/USDT', 'limit', 'sell', property_val, closing_price, exchange_params)
print(data)
print(type(data))
# print('---------止盈价 执行----------------------------------')
# exchange_params = {
# 'stopPrice': closing_price,
# 'type': 'stopLimit',
# }
# data = exchange.create_order(
# 'DOT/USDT', 'limit', 'sell', property_val, closing_price, exchange_params)
# print(data)
# print(type(data))
def testK_buy_close():
# 平多
data = exchange.create_limit_buy_order(
'DOT/USDT', 1, 5, {"tdMode": "cross"})
print(data)
print(type(data))
# closed_orders = exchange.fetchClosedOrders('BTC/USDT', limit=2)
# print(closed_orders)
# closed_orders = exchange.fetchMyTrades('ETH/USDT', limit=2)
# print(closed_orders)
def testK_sell_open():
# 做空开仓
# data = exchange.createMarketSellOrder(
# 'DOT/USDT', 1, {"tdMode": "cross", 'ccy': "USDT", })
# print(data)
# print(type(data))
# 数据
# {'info': {'clOrdId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'ordId': '554437054223302656', 'sCode': '0', 'sMsg': 'Order placed', 'tag': 'e847386590ce4dBC'}, 'id': '554437054223302656', 'clientOrderId': 'e847386590ce4dBC58e8b0afb0fe70cc', 'timestamp': None, 'datetime': None, 'lastTradeTimestamp': None, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': None, 'postOnly': None, 'side': 'buy', 'price': None, 'stopPrice': None, 'triggerPrice': None, 'average': None, 'cost': None, 'amount': None, 'filled': None, 'remaining': None, 'status': None, 'fee': None, 'trades': [], 'reduceOnly': None, 'fees': []}
# # 查询委托单
# order_id = data['info']['ordId']
order_id = '554516809819832320'
data = exchange.fetchOrder(order_id, 'DOT/USDT')
print(data['info'])
# {'info': {'accFillSz': '0.190548', 'algoClOrdId': '', 'algoId': '', 'avgPx': '5.248', 'cTime': '1678441709955', 'cancelSource': '', 'cancelSourceReason': '', 'category': 'normal', 'ccy': 'USDT', 'clOrdId': 'e847386590ce4dBCeaddfd1494dc7080', 'fee': '-0.000190548', 'feeCcy': 'DOT', 'fillPx': '5.248', 'fillSz': '0.190548', 'fillTime': '1678441709957', 'instId': 'DOT-USDT', 'instType': 'MARGIN', 'lever': '10', 'ordId': '554359943143833600', 'ordType': 'market', 'pnl': '0', 'posSide': 'net', 'px': '', 'quickMgnType': '', 'rebate': '0', 'rebateCcy': 'USDT', 'reduceOnly': 'false', 'side': 'buy', 'slOrdPx': '', 'slTriggerPx': '', 'slTriggerPxType': '', 'source': '', 'state': 'filled', 'sz': '1', 'tag': 'e847386590ce4dBC', 'tdMode': 'cross', 'tgtCcy': '', 'tpOrdPx': '', 'tpTriggerPx': '', 'tpTriggerPxType': '', 'tradeId': '81184616', 'uTime': '1678441709960'}, 'id': '554359943143833600', 'clientOrderId': 'e847386590ce4dBCeaddfd1494dc7080', 'timestamp': 1678441709955, 'datetime': '2023-03-10T09:48:29.955Z', 'lastTradeTimestamp': 1678441709957, 'symbol': 'DOT/USDT', 'type': 'market', 'timeInForce': 'IOC', 'postOnly': None, 'side': 'buy', 'price': 5.248, 'stopPrice': None, 'triggerPrice': None, 'average': 5.248, 'cost': 0.999995904, 'amount': 1.0, 'filled': 0.190548, 'remaining': 0.809452, 'status': 'closed', 'fee': {'cost': 0.000190548, 'currency': 'DOT'}, 'trades': [], 'reduceOnly': False, 'fees': [{'cost': 0.000190548, 'currency': 'DOT'}]}
open_price = data['info']['avgPx']
print("开仓平均价", open_price)
# 止盈价
closing_price = float(open_price) * float((1 - 0.005))
closing_price = common.roundVal(closing_price, open_price)
print("止盈价", closing_price)
# 止损价
stop_loss_price = float(open_price) * float((1 + 0.01))
stop_loss_price = common.roundVal(stop_loss_price, open_price)
print("止损价", stop_loss_price)
property_val = float(data['info']['accFillSz'])
# 相同位数
print("可平仓资产", property_val)
# 止损价
# 止盈价
exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
print('---------止损价 执行----------------------------------')
data = exchange.create_order(
'DOT/USDT', 'limit', 'buy', property_val, closing_price, exchange_params)
print(data)
print(type(data))
def testK_sell_close():
# 平多
data = exchange.create_limit_buy_order(
'DOT/USDT', 1, 5, {"tdMode": "cross"})
print(data)
print(type(data))
# closed_orders = exchange.fetchClosedOrders('BTC/USDT', limit=2)
# print(closed_orders)
# closed_orders = exchange.fetchMyTrades('ETH/USDT', limit=2)
# print(closed_orders)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'long':
longRun()
elif func == 'run':
debug()
elif func == 'test':
testKdan()
elif func == 't_get_trade':
t_get_trade()
elif func == 't_buy_open':
btc_test()
elif func == 't_buy_close':
testK_buy_close()
elif func == 't_sell_open':
testK_sell_open()
elif func == 't_sell_cloe':
testK_sell_close()
else:
print('error')

View File

@@ -0,0 +1,102 @@
import ccxt
import talib
import sys
import os
import time
import pandas as pd
import pandas_ta as ta
from pprint import pprint
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/rsi_robot.py run
pd.set_option('display.max_rows', None)
exchange = common.initEx()
# 查看隐形方法
# print(dir(exchange))
exchange.load_markets()
entry_rsi = 30
exit_rsi = 40
symbol = 'XRP/USDT'
timeframe = '15m'
tf_mult = exchange.parse_timeframe(timeframe) * 1000
def indicators(data):
data['rsi'] = data.ta.rsi(length=10)
data['ema'] = data.ta.ema(length=200)
# close_p = data['close'].values
# data['rsi'] = talib.RSI(close_p, timeperiod=10)
# data['ema'] = talib.EMA(close_p, timeperiod=200)
return data
def check_buy_sell_signals(df):
last_row_index = len(df.index) - 1
lastest_rsi = round(df['rsi'].iloc[-1], 2)
lastest_price = round(df['close'].iloc[-1], 5)
lastest_ema = round(df['ema'].iloc[-1], 5)
lastest_ts = df['timestamp'].iloc[-1]
msg = "lastest_rsi:" + str(lastest_rsi) + " < entry_rsi:" + str(entry_rsi)
msg += ",lastest_price:" + \
str(lastest_price) + " > lastest_ema:" + str(lastest_ema)
print(msg)
long_cond = (lastest_rsi < entry_rsi) and (lastest_price > lastest_ema)
if long_cond:
print("买入")
order = exchange.create_market_buy_order(symbol, 1)
closed_orders = exchange.fetchClosedOrders(symbol, limit=2)
if len(closed_orders) > 0:
print("closed_orders:", closed_orders)
most_recent_closed_order = closed_orders[-1]
diff = lastest_ts - most_recent_closed_order['timestamp']
last_buy_signal_cnt = int(diff / tf_mult)
exit_cond = (lastest_rsi > exit_rsi) and (last_buy_signal_cnt > 10)
if exit_cond:
print("卖出")
order = exchange.create_market_sell_order(symbol, 1)
return
def runBot():
bars = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=200)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
df['dt'] = pd.to_datetime(df['timestamp'], unit='ms')
df = indicators(df).tail(30)
check_buy_sell_signals(df)
def longRunBot():
while True:
runBot()
time.sleep(10)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'run':
longRunBot()
else:
print('error')

View File

@@ -0,0 +1,536 @@
# cd /www/server/mdserver-web && . bin/activate
# python3 plugins/cryptocurrency_trade/ccxt/strategy/vega_trade.py run
# python3 plugins/cryptocurrency_trade/ccxt/strategy/vega_trade.py long
# 动量策略交易
################
import ccxt
import talib
import sys
import os
import time
import json
import pandas as pd
# import pandas_ta as ta
from pprint import pprint
import numpy as np
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/strategy")
import common
sys.path.append(os.getcwd() + "/class/core")
import mw
exchange = common.initEx()
exchange.load_markets()
# 默认开仓数据
# default_open_num = 70
# default_sell_num = 0.003
default_open = {
'BTC/USDT': 70,
'XRP/USDT': 70,
}
default_sell = {
'BTC/USDT': 0.003,
'XRP/USDT': 185,
}
# 做多开仓
def onBuyOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做多----------------------------------', symbol)
default_open_num = default_open[symbol]
# 做多开仓 | 市价
data = exchange.createMarketBuyOrder(
symbol, default_open_num, {"tdMode": "cross"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
# 修正小数点位数
open_price = common.roundVal(open_price, stop_loss_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
# 做多-止损价大于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 - 0.003))
# property_val = float(order_data['info']['accFillSz']) + float(order_data['info']['fee'])
property_val = common.addition(order_data['info'][
'accFillSz'], order_data['info']['fee'])
property_val = float(property_val)
# 可平仓的数量
# property_val = common.roundValCeil(
# property_val, order_data['info']['accFillSz'])
common.writeLogEx('可平仓资产:' + str(property_val), symbol)
# 止盈价
diff = float(open_price) - float(stop_loss_price)
closing_price = float(open_price) + (diff * 1.5)
# closing_price = float(open_price) * float((1 + profit))
# # 选择盈利多的
# if closing_price_c > closing_price:
# closing_price = closing_price_c
closing_price = common.roundVal(closing_price, open_price)
stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价/止盈价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
# 止损条件单
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
# 止赢条件单
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'sell',
property_val, closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'sell', property_val, closing_price, tp_exchange_params)
common.writeLogEx('止盈数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做多 end----------------------------------', symbol)
return True, open_price, closing_price
def onBuyOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做多开仓
# profit 百分比
try:
return onBuyOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def onSellOrderTry(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 信号只在一个周期内执行一次|start
lock_file = common.getServerDir() + '/signal.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
stype = symbol.replace('/', '_') + '_' + timeframe
trigger_time = common.toUnixTimeSecond(timeframe)
lock_data = json.loads(mw.readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[stype] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
common.writeLogEx('------做空----------------------------------', symbol)
# 计算借币卖币多多少,以USDT为基准
# sell_num = float(default_open_num) / float(stop_loss_price)
# sell_num = round(sell_num, 8)
# sell_num = default_sell_num
sell_num = default_sell[symbol]
# 做空开仓 | 市价
data = exchange.createMarketSellOrder(
symbol, sell_num, {"tdMode": "cross", 'ccy': "USDT"})
common.writeLogEx('开仓数据:', symbol)
common.writeLogEx(json.dumps(data), symbol)
order_id = data['info']['ordId']
order_data = exchange.fetchOrder(order_id, symbol)
common.writeLogEx('订单数据:', symbol)
common.writeLogEx(json.dumps(order_data), symbol)
# 实际开场平均价
open_price = order_data['info']['avgPx']
# 修正
open_price = common.roundVal(open_price, stop_loss_price)
common.writeLogEx('实际开仓价:' + str(open_price), symbol)
common.writeLogEx('可平仓资产:' + str(sell_num), symbol)
# 做空-止损价小于开仓价,重设止损价
if float(stop_loss_price) <= float(open_price):
stop_loss_price = float(open_price) * float((1 + 0.003))
# 止盈价
diff = float(stop_loss_price) - float(open_price)
closing_price = float(open_price) - (diff * 1.5)
# closing_price = float(open_price) * float((1 - profit))
# 选择盈利多的
# if closing_price_c < closing_price:
# closing_price = closing_price_c
closing_price = common.roundVal(closing_price, open_price)
stop_loss_price = common.roundVal(stop_loss_price, open_price)
common.writeLogEx('止盈价:' + str(closing_price), symbol)
common.writeLogEx('止损价:' + str(stop_loss_price), symbol)
# 设置 - 止损价
sl_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'slOrdPx': "-1",
'slTriggerPx': stop_loss_price,
}
sl_amount = common.multiply(stop_loss_price, sell_num)
# 解决平仓时,未全部平仓
sl_amount = common.addition(sl_amount, 0.1)
common.writeLogEx('止损总价值:' + str(sl_amount), symbol)
common.writeLogEx('止损参数:' + json.dumps([symbol, 'limit', 'buy', float(
sl_amount), stop_loss_price, sl_exchange_params]), symbol)
sl_cond_data = exchange.create_order(
symbol, 'limit', 'buy', float(sl_amount), stop_loss_price, sl_exchange_params)
common.writeLogEx('止损价数据:', symbol)
common.writeLogEx(json.dumps(sl_cond_data), symbol)
tp_exchange_params = {
'ccy': "USDT",
'reduceOnly': True,
'tdMode': "cross",
'tpOrdPx': "-1",
'tpTriggerPx': closing_price,
}
# 设置 -止盈价
# tp_amount = closing_price * sell_num
tp_amount = common.multiply(closing_price, sell_num)
# 解决平仓时,未全部平仓
tp_amount = common.addition(tp_amount, 0.1)
common.writeLogEx('止盈总价值:' + str(tp_amount), symbol)
common.writeLogEx('止盈参数:' + json.dumps([symbol, 'limit', 'buy', float(
tp_amount), closing_price, tp_exchange_params]), symbol)
tp_cond_data = exchange.create_order(
symbol, 'limit', 'buy', float(tp_amount), closing_price, tp_exchange_params)
common.writeLogEx('止盈价数据:', symbol)
common.writeLogEx(json.dumps(tp_cond_data), symbol)
common.writeLogEx('------做空 end----------------------------------', symbol)
return True, open_price, closing_price
def onSellOrder(symbol, stop_loss_price, profit=0.005, timeframe='15m'):
# 做空开仓
# profit 百分比
try:
return onSellOrderTry(symbol, stop_loss_price, profit, timeframe)
except Exception as e:
common.writeLogErrorEx(mw.getTracebackInfo(), symbol)
return False, 0, 0
def getOnlineData(symbol, input_tf="15m", limit=500):
bars = exchange.fetch_ohlcv(symbol, timeframe=input_tf, limit=500)
df = pd.DataFrame(bars[:], columns=['timestamp',
'open', 'high', 'low', 'close', 'volume'])
df['dt'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('dt', inplace=True)
df.index = df.index.tz_localize('UTC').tz_convert('Asia/Shanghai')
return df
def isKdj(last, last_pre):
# 判断是否是金叉
if (float(last_pre['macd']) < 0) and (float(last['macd']) > 0):
return True
return False
def isDeadFork(last, last_pre):
# 判断是否是死叉
if (float(last_pre['macd']) > 0) and (float(last['macd']) < 0):
return True
return False
def getTarget(df):
close = df['close'].values
# vega
df['ema144'] = talib.EMA(np.array(close), timeperiod=144)
df['ema169'] = talib.EMA(np.array(close), timeperiod=169)
df['ema288'] = talib.EMA(np.array(close), timeperiod=288)
df['ema388'] = talib.EMA(np.array(close), timeperiod=388)
df['rsi'] = talib.RSI(close, timeperiod=14)
return df
# 多头信号
def isBuyCrondSignal(last):
if last['ema'] > last['ma'] and (last['rsi'] > 50 and last['rsi'] < 70) and last['low'] >= last['ma'] and last['close'] > last['open']:
return True
return False
def isBuyFristSignal(data):
data = data.sort_values(by=['timestamp'], ascending=False)
# print(data)
data_len = len(data)
signal_num = 0
first_data = data.iloc[1]
# print(1, first_data['close'], first_data['ema'])
is_buy_signal = isBuyCrondSignal(first_data)
for x in range(2, data_len):
tmp = data.iloc[x]
# print(data.iloc[x])
# print(x, tmp['close'], tmp['ema'])
if isBuyCrondSignal(tmp):
signal_num = + 1
# print('signal_num:', signal_num)
if (tmp['ema'] < tmp['ma']):
break
if str(tmp['ema']) == 'nan':
break
print("is_buy_signal:", is_buy_signal, 'signal_num:', signal_num)
if is_buy_signal and signal_num == 0:
return True
return False
# 空头信号
def isSellCrondSignal(last):
if last['ema'] < last['ma'] and (last['rsi'] > 30 and last['rsi'] < 50) and last['high'] <= last['ema'] and last['close'] < last['open']:
return True
return False
def isSellFristSignal(data):
data = data.sort_values(by=['timestamp'], ascending=False)
# print(data)
data_len = len(data)
signal_num = 0
first_data = data.iloc[1]
# print(1, first_data['close'], first_data['ema'])
is_sell_signal = isSellCrondSignal(first_data)
for x in range(2, data_len):
tmp = data.iloc[x]
# print(data.iloc[x])
# print(x, tmp['close'], tmp['ema'])
if isSellCrondSignal(tmp):
signal_num = + 1
# print('signal_num:', signal_num)
if (tmp['ema'] < tmp['ma']):
break
if str(tmp['ema']) == 'nan':
break
print("is_sell_signal:", is_sell_signal, 'signal_num:', signal_num)
if is_sell_signal and signal_num == 0:
return True
return False
def isDownTrendCover(data, tag, timeframe):
# print(tag, timeframe, "开始检测是否下跌趋势")
# 下跌趋势回调
key_data = data.tail(2)
last_pre = key_data.iloc[0]
last = key_data.iloc[1]
pdata = data.tail(11)
for x in range(10):
t = pdata.iloc[x]
if t['low'] > t['ema388']:
print(tag, timeframe, "上升震荡行情过滤")
# print(t)
return False
if last['ema144'] > last['ema388']:
return False
print(tag, timeframe, "检查是下跌趋势!")
# 检查是否是下跌趋势
if last['high'] > last['ema388']:
return True
return False
def isUpTrendAndCover(data, tag, timeframe):
# print(tag, timeframe, "开始检测是否上升趋势")
# 上升趋势回调
key_data = data.tail(2)
# print(key_data)
last_pre = key_data.iloc[0]
last = key_data.iloc[1]
pdata = data.tail(11)
for x in range(10):
t = pdata.iloc[x]
if t['low'] < t['ema144']:
print(tag, timeframe, "上升震荡行情过滤")
return False
if last['ema144'] < last['ema388']:
return False
print(tag, timeframe, "检查是上升趋势")
# 检查是否是上升趋势
if last['low'] < last['ema144']:
return True
return False
def vegaTrade(data, tag, timeframe):
data = getTarget(data)
# print(data)
key_data = data.tail(2)
# print(key_data)
# last_pre = key_data.iloc[0]
last = key_data.iloc[1]
# print(last)
obj = common.MsgTpl()
symbol = tag.upper() + '/USDT'
obj.setName(symbol)
obj.setStrategyName("VEGA交易策略|仅具有指导作用")
obj.setTimeFrame(timeframe)
obj.setOpenTime(last['addtime'])
if isUpTrendAndCover(data, tag, timeframe):
obj.setStrategicDt('buy')
obj.setContent("VEGA上升趋势!回调做多~建议!")
msg = obj.toText()
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
if isDownTrendCover(data, tag, timeframe):
obj.setStrategicDt('sell')
obj.setContent("Vega下跌趋势!回调做空~建议!")
msg = obj.toText()
common.notifyMsg(msg, timeframe, tag)
common.writeLog(msg)
def mainProcess(tag, timeframe='5m'):
symbol = tag.upper() + '/USDT'
data = common.getDataFromDb_DF(timeframe, tag.lower())
vegaTrade(data, tag, timeframe)
return True
def foreachList():
tag_list = ['btc', 'xrp', 'eth', 'ltc', 'okb']
for tag in tag_list:
trame_list = ['5m', '15m', '1h', '4h']
for tf in trame_list:
mainProcess(tag, tf)
# time.sleep(1)
def longRun():
while True:
try:
foreachList()
time.sleep(1)
except Exception as e:
print(mw.getTracebackInfo())
time.sleep(3)
def debug():
while True:
mainProcess('btc', '5m')
time.sleep(1)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'long':
longRun()
elif func == 'run':
debug()
else:
print('error')

View File

@@ -0,0 +1,128 @@
'''
pip install git+https://github.com/catalyst-team/catalyst@master --upgrade
cd /www/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && . bin/activate
python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
'''
from datetime import datetime
import akshare as ak
import pandas as pd
import backtrader as bt
class BollStrategy(bt.Strategy): # BOLL策略程序
params = (("nk", 13), # 求均值的天数
('printlog', False),) # 打印log
def __init__(self): # 初始化
self.data_close = self.datas[0].close # 指定价格序列
# 初始化交易指令、买卖价格和手续费
self.order = None
self.buy_price = None
self.buy_comm = None
# Boll指标计算
self.top = bt.indicators.BollingerBands(
self.datas[0], period=self.params.nk).top
self.bot = bt.indicators.BollingerBands(
self.datas[0], period=self.params.nk).bot
# 添加移动均线指标
self.sma = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.nk)
def next(self): # 买卖策略
if self.order: # 检查是否有指令等待执行
return
# 检查是否持仓
"""
if not self.position: # 没有持仓
if self.data_close[0] > self.sma[0]: # 执行买入条件判断:收盘价格上涨突破20日均线
self.order = self.buy(size=100) # 执行买入
else:
if self.data_close[0] < self.sma[0]: # 执行卖出条件判断:收盘价格跌破20日均线
self.order = self.sell(size=100) # 执行卖出
"""
if not self.position: # 没有持仓
if self.data_close[0] < self.bot[0]: # 收盘价格跌破下轨
self.log("BUY CREATE, %.2f" % self.data_close[0])
self.order = self.buy() # 执行买入
else:
if self.data_close[0] > self.top[0]: # 收盘价格上涨突破上轨
self.log("SELL CREATE, %.2f" % self.data_close[0])
self.order = self.sell() # 执行卖出
def log(self, txt, dt=None, do_print=False): # 日志函数
if self.params.printlog or do_print:
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def notify_order(self, order): # 记录交易执行情况
# 如果order为submitted/accepted,返回空
if order.status in [order.Submitted, order.Accepted]:
return
# 指令为buy/sell,报告价格结果
if order.status in [order.Completed]:
if order.isbuy():
self.log(
f"买入:\n价格:{order.executed.price},\
成本:{order.executed.value},\
手续费:{order.executed.comm}"
)
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else:
self.log(
f"卖出:\n价格:{order.executed.price},\
成本: {order.executed.value},\
手续费{order.executed.comm}"
)
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log("交易失败") # 指令取消/交易失败, 报告结果
self.order = None
def notify_trade(self, trade): # 记录交易收益情况
if not trade.isclosed:
return
self.log(f"策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}")
def stop(self): # 回测结束后输出结果
self.log("(BOLL线: %2d日) 期末总资金 %.2f" %
(self.params.nk, self.broker.getvalue()), do_print=True)
code = "600036" # 股票代码
start_cash = 1000000 # 初始自己为1000000
stake = 100 # 单次交易数量为1手
commfee = 0.0005 # 佣金为万5
sdate = '20210101' # 回测时间段
edate = '20220930'
cerebro = bt.Cerebro() # 创建回测系统实例
# 利用AKShare获取股票的前复权数据的前6列
df_qfq = ak.stock_zh_a_hist(
symbol=code, adjust="qfq", start_date=sdate, end_date=edate).iloc[:, :6]
# 处理字段命名,以符合Backtrader的要求
df_qfq.columns = ['date', 'open', 'close', 'high', 'low', 'volume', ]
# 把date作为日期索引,以符合Backtrader的要求
df_qfq.index = pd.to_datetime(df_qfq['date'])
start_date = datetime.strptime(sdate, "%Y%m%d") # 转换日期格式
end_date = datetime.strptime(edate, "%Y%m%d")
# start_date=datetime(2022,1,4)
# end_date=datetime(2022,9,16)
data = bt.feeds.PandasData(
dataname=df_qfq, fromdate=start_date, todate=end_date) # 规范化数据格式
cerebro.adddata(data) # 加载数据
cerebro.addstrategy(BollStrategy, nk=13, printlog=True) # 加载交易策略
cerebro.broker.setcash(start_cash) # broker设置资金
cerebro.broker.setcommission(commission=commfee) # broker手续费
cerebro.addsizer(bt.sizers.FixedSize, stake=stake) # 设置买入数量
print("期初总资金: %.2f" % start_cash)
cerebro.run() # 运行回测
end_value = cerebro.broker.getvalue() # 获取回测结束后的总资金
print("期末总资金: %.2f" % end_value)
cerebro.plot()

View File

@@ -0,0 +1,154 @@
'''
pip install git+https://github.com/catalyst-team/catalyst@master --upgrade
cd /www/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && . bin/activate
python3 plugins/cryptocurrency_trade/ccxt/test/p1.py
'''
from datetime import datetime
import akshare as ak
import pandas as pd
import backtrader as bt
import sys
import os
sys.path.append(os.getcwd() + "/plugins/cryptocurrency_trade/ccxt/strategy")
import common
class BollStrategy(bt.Strategy): # BOLL策略程序
params = (("nk", 13), # 求均值的天数
('printlog', False),) # 打印log
def __init__(self): # 初始化
self.data_close = self.datas[0].close # 指定价格序列
# 初始化交易指令、买卖价格和手续费
self.order = None
self.buy_price = None
self.buy_comm = None
# Boll指标计算
self.top = bt.indicators.BollingerBands(
self.datas[0], period=self.params.nk).top
self.bot = bt.indicators.BollingerBands(
self.datas[0], period=self.params.nk).bot
# 添加移动均线指标
self.sma = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.nk)
def next(self): # 买卖策略
if self.order: # 检查是否有指令等待执行
return
# 检查是否持仓
"""
if not self.position: # 没有持仓
if self.data_close[0] > self.sma[0]: # 执行买入条件判断:收盘价格上涨突破20日均线
self.order = self.buy(size=100) # 执行买入
else:
if self.data_close[0] < self.sma[0]: # 执行卖出条件判断:收盘价格跌破20日均线
self.order = self.sell(size=100) # 执行卖出
"""
if not self.position: # 没有持仓
if self.data_close[0] < self.bot[0]: # 收盘价格跌破下轨
self.log("BUY CREATE, %.2f" % self.data_close[0])
self.order = self.buy() # 执行买入
else:
if self.data_close[0] > self.top[0]: # 收盘价格上涨突破上轨
self.log("SELL CREATE, %.2f" % self.data_close[0])
self.order = self.sell() # 执行卖出
def log(self, txt, dt=None, do_print=False): # 日志函数
if self.params.printlog or do_print:
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def notify_order(self, order): # 记录交易执行情况
# 如果order为submitted/accepted,返回空
if order.status in [order.Submitted, order.Accepted]:
return
# 指令为buy/sell,报告价格结果
if order.status in [order.Completed]:
if order.isbuy():
self.log(
f"买入:\n价格:{order.executed.price},\
成本:{order.executed.value},\
手续费:{order.executed.comm}"
)
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else:
self.log(
f"卖出:\n价格:{order.executed.price},\
成本: {order.executed.value},\
手续费{order.executed.comm}"
)
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log("交易失败") # 指令取消/交易失败, 报告结果
self.order = None
def notify_trade(self, trade): # 记录交易收益情况
if not trade.isclosed:
return
self.log(f"策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}")
def stop(self): # 回测结束后输出结果
self.log("(BOLL线: %2d日) 期末总资金 %.2f" %
(self.params.nk, self.broker.getvalue()), do_print=True)
code = "600036" # 股票代码
start_cash = 1000000 # 初始自己为1000000
stake = 100 # 单次交易数量为1手
commfee = 0.0005 # 佣金为万5
sdate = '20210101' # 回测时间段
edate = '20220930'
cerebro = bt.Cerebro() # 创建回测系统实例
# 利用AKShare获取股票的前复权数据的前6列
# df_qfq = ak.stock_zh_a_hist(
# symbol=code, adjust="qfq", start_date=sdate, end_date=edate).iloc[:, :6]
# 日期 开盘 收盘 最高 最低 成交量
# 0 2021-01-04 40.46 40.40 41.01 39.25 1549523
# 1 2021-01-05 39.99 39.41 40.03 38.67 1387177
# 2 2021-01-06 39.33 41.38 41.43 39.23 1200646
# 3 2021-01-07 41.52 43.13 43.20 41.49 1078322
# 4 2021-01-08 43.52 43.83 44.25 43.04 1299595
# .. ... ... ... ... ... ...
# 420 2022-09-26 34.02 33.95 34.52 33.84 525491
# 421 2022-09-27 33.89 33.90 34.05 33.44 475414
# 422 2022-09-28 33.79 33.67 34.00 33.42 487299
# 423 2022-09-29 33.99 33.15 34.32 33.00 617859
# 424 2022-09-30 33.26 33.65 33.95 33.12 539717
tag = 'btc'
symbol = tag.upper() + '/USDT'
df_qfq = common.getDataFromDb_DF('15m', tag.lower())
print(df_qfq)
# # 处理字段命名,以符合Backtrader的要求
# df_qfq.columns = ['date', 'open', 'close', 'high', 'low', 'volume', ]
# # 把date作为日期索引,以符合Backtrader的要求
# df_qfq.index = pd.to_datetime(df_qfq['date'])
# start_date = datetime.strptime(sdate, "%Y%m%d") # 转换日期格式
# end_date = datetime.strptime(edate, "%Y%m%d")
start_date = datetime(2023, 4, 6)
end_date = datetime(2023, 4, 9)
data = bt.feeds.PandasData(dataname=df_qfq, fromdate=start_date,
todate=end_date) # 规范化数据格式
cerebro.adddata(data) # 加载数据
cerebro.addstrategy(BollStrategy, nk=13, printlog=True) # 加载交易策略
cerebro.broker.setcash(start_cash) # broker设置资金
cerebro.broker.setcommission(commission=commfee) # broker手续费
cerebro.addsizer(bt.sizers.FixedSize, stake=stake) # 设置买入数量
print("期初总资金: %.2f" % start_cash)
cerebro.run() # 运行回测
end_value = cerebro.broker.getvalue() # 获取回测结束后的总资金
print("期末总资金: %.2f" % end_value)
# cerebro.plot(style='candle')

View File

@@ -0,0 +1,61 @@
# coding:utf-8
import pandas as pd
import matplotlib.pyplot as plt
from catalyst import run_algorithm
from catalyst.api import order, record, symbol
'''
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && / bin/activate
cd /www/server/mdserver-web && . bin/activate && source activate catalys
cd /Users/midoks/Desktop/mwdev/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p_test.py
catalyst ingest-exchange -x binance -i btc_usdt -f minute
cd /www/server/mdserver-web && python3 plugins/cryptocurrency_trade/ccxt/test/p_test.py
'''
def initialize(context):
# 初始化
context.asset = symbol('btc_usdt')
def handle_data(context, data):
# 循环策略
order(context.asset, 1)
record(btc=data.current(context.asset, 'price'))
def analyze(context, perf):
print(perf.portfolio_value)
ax1 = plt.subplot(211)
perf.portfolio_value.plot(ax=ax1)
ax1.set_ylabel('portfolio value')
ax2 = plt.subplot(212, sharex=ax1)
perf.btc.plot(ax=ax2)
ax2.set_ylabel('bitcoin value')
plt.show()
if __name__ == "__main__":
run_algorithm(
capital_base=10000,
data_frequency='daily',
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='binance',
quote_currenty='usdt',
start=pd.to_datetime("2018-01-01", utc=True),
end=pd.to_datetime("2018-10-01", utc=True),
)

View File

@@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS `ct_xx1_xx2` (
`addtime` BIGINT(20) not NULL,
`open` float NOT NULL,
`high` float NOT NULL,
`low` float NOT NULL,
`close` float NOT NULL,
`vol` float NOT NULL,
UNIQUE KEY `addtime` (`addtime`)
);

View File

@@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS `ct_order_list` (
`id` BIGINT(20) not NULL,
'strategy_name' varchar(50) NULL,
`symbol` varchar(50) NOT NULL,
`fee` float NOT NULL,
`price` float NOT NULL,
`closing_price` float NOT NULL comment '',
`profit` float NOT NULL,
`source` TEXT,
`addtime` BIGINT(20) not NULL
);

View File

@@ -0,0 +1,14 @@
[program:{$NAME}]
command=bash -c "cd {$RUN_ROOT} && . bin/activate && python3 {$ABS_FILE} long"
directory={$RUN_ROOT}
autorestart=true
startsecs=3
startretries=3
stdout_logfile={$SUP_ROOT}/log/{$NAME}.out.log
stderr_logfile={$SUP_ROOT}/log/{$NAME}.err.log
stdout_logfile_maxbytes=2MB
stderr_logfile_maxbytes=2MB
user=root
priority=999
numprocs=1
process_name=%(program_name)s

View File

@@ -0,0 +1,14 @@
[program:{$NAME}]
command=bash -c "cd {$RUN_ROOT} && . bin/activate && python3 plugins/cryptocurrency_trade/ccxt/public_data/data.py long"
directory={$RUN_ROOT}
autorestart=true
startsecs=3
startretries=3
stdout_logfile={$SUP_ROOT}/log/{$NAME}.out.log
stderr_logfile={$SUP_ROOT}/log/{$NAME}.err.log
stdout_logfile_maxbytes=2MB
stderr_logfile_maxbytes=2MB
user=root
priority=999
numprocs=1
process_name=%(program_name)s

View File

@@ -0,0 +1,350 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import string
import subprocess
import json
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'cryptocurrency_trade'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getFatherDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace(
'{$SERVER_APP}', service_path + '/' + getPluginName())
return content
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':', 1)
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def isSqlError(mysqlMsg):
# 检测数据库执行错误
mysqlMsg = str(mysqlMsg)
if "MySQLdb" in mysqlMsg:
return mw.returnJson(False, 'MySQLdb组件缺失! <br>进入SSH命令行输入: pip install mysql-python | pip install mysqlclient==2.0.3')
if "2002," in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "2003," in mysqlMsg:
return mw.returnJson(False, "Can't connect to MySQL server on '127.0.0.1' (61)")
if "using password:" in mysqlMsg:
return mw.returnJson(False, '数据库密码错误')
if "1045" in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
def getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeConf(data):
cfg_path = getServerDir() + "/data.cfg"
mw.writeFile(cfg_path, json.dumps(data))
return True
def getDbConf():
data = getConfigData()
if 'db' in data:
return mw.returnJson(True, 'ok', data['db'])
return mw.returnJson(False, 'ok', {})
def getUserConf():
data = getConfigData()
if 'user' in data:
return mw.returnJson(True, 'ok', data['user'])
return mw.returnJson(False, 'ok', {})
def restartSup():
cmd = 'python3 plugins/supervisor/index.py restart'
mw.execShell(cmd)
def restartSupDst(name):
cmd = 'python3 plugins/supervisor/index.py restart_job {"name":"' + \
name + '","status":"stop"}'
mw.execShell(cmd)
def syncDataAddTaskUninstall():
sup_path = mw.getServerDir() + '/supervisor'
if not os.path.exists(sup_path):
return mw.returnJson(False, '需要安装并启动supervisor插件')
name = "ct_task"
sup_task_dst = sup_path + '/conf.d/' + name + '.ini'
if os.path.exists(sup_task_dst):
mw.execShell('rm -rf ' + sup_task_dst)
restartSup()
return mw.returnJson(True, '删除同步数据任务成功!')
def syncDataAddTaskInstall():
sup_path = mw.getServerDir() + '/supervisor'
if not os.path.exists(sup_path):
return mw.returnJson(False, '需要安装并启动supervisor插件')
name = "ct_task"
sup_task_tpl = getPluginDir() + '/conf/sup_task.tpl'
sup_task_dst = sup_path + '/conf.d/' + name + '.ini'
content = mw.readFile(sup_task_tpl)
content = content.replace(
'{$RUN_ROOT}', mw.getServerDir() + '/mdserver-web')
content = content.replace(
'{$SUP_ROOT}', sup_path)
content = content.replace(
'{$NAME}', name)
mw.writeFile(sup_task_dst, content)
restartSup()
return mw.returnJson(True, '添加同步数据任务成功!')
def syncDataAddTask():
args = getArgs()
data_args = checkArgs(args, ['check'])
if not data_args[0]:
return data_args[1]
if args['check'] == "0":
return syncDataAddTaskUninstall()
return syncDataAddTaskInstall()
def syncDataDelete():
args = getArgs()
data_args = checkArgs(args, ['token'])
if not data_args[0]:
return data_args[1]
del_token = args['token']
data = getConfigData()
if 'token' in data:
data['token'].remove(del_token)
writeConf(data)
return mw.returnJson(True, '删除成功!')
# callback ---------------------------------- start
def get_datasource_logs(args):
log_file = getServerDir() + '/logs/datasource.log'
if not os.path.exists(log_file):
return '暂无日志'
data = mw.getLastLine(log_file, 10)
return data
def get_strategy_logs(args):
log_file = getServerDir() + '/logs/strategy.log'
if not os.path.exists(log_file):
return '暂无日志'
data = mw.getLastLine(log_file, 10)
return data
def save_body(args):
path = args['path']
encoding = args['encoding']
data = args['data']
tag = args['tag']
if not os.path.exists(path):
return mw.returnData(False, '文件不存在')
try:
if encoding == 'ascii':
encoding = 'utf-8'
data = data.encode(
encoding, errors='ignore').decode(encoding)
fp = open(path, 'w+', encoding=encoding)
fp.write(data)
fp.close()
set_strategy_restart({'id': tag})
return mw.returnData(True, '文件保存成功')
except Exception as ex:
return mw.returnData(False, '文件保存错误:' + str(ex))
def get_strategy_path(args):
abs_id = args['id']
name = "ct_strategy_" + abs_id
abs_file = get_strategy_absfile(abs_id)
return mw.returnData(True, abs_file)
def set_strategy_restart(args):
sup_path = mw.getServerDir() + '/supervisor'
if not os.path.exists(sup_path):
return mw.returnData(False, '需要安装并启动supervisor插件')
abs_id = args['id']
name = "ct_strategy_" + abs_id
sup_strategy_dst = sup_path + '/conf.d/' + name + '.ini'
if not os.path.exists(sup_strategy_dst):
return mw.returnData(False, '策略任务' + abs_id + '未添加!')
restartSupDst(name)
return mw.returnData(True, '重启策略任务' + abs_id + '成功!')
def set_strategy_status(args):
sup_path = mw.getServerDir() + '/supervisor'
if not os.path.exists(sup_path):
return mw.returnData(False, '需要安装并启动supervisor插件')
abs_id = args['id']
name = "ct_strategy_" + abs_id
sup_strategy_dst = sup_path + '/conf.d/' + name + '.ini'
if args['status'] == 'stop':
if os.path.exists(sup_strategy_dst):
os.remove(sup_strategy_dst)
restartSup()
return mw.returnData(True, '删除策略任务' + abs_id + '成功!')
abs_file = get_strategy_absfile(abs_id)
sup_strategy_tpl = getPluginDir() + '/conf/sup_strategy.tpl'
content = mw.readFile(sup_strategy_tpl)
content = content.replace(
'{$RUN_ROOT}', mw.getServerDir() + '/mdserver-web')
content = content.replace(
'{$SUP_ROOT}', sup_path)
content = content.replace(
'{$NAME}', name)
content = content.replace(
'{$ABS_FILE}', abs_file)
mw.writeFile(sup_strategy_dst, content)
restartSup()
return mw.returnData(True, '添加策略任务' + abs_id + '成功!')
def get_strategy_absfile(abs_id):
info = getPluginDir() + '/ccxt/strategy/info.json'
info = json.loads(mw.readFile(info))
path = getPluginDir() + '/ccxt/strategy'
for x in range(len(info)):
if info[x]['id'] == abs_id:
return path + '/' + info[x]['file']
return path + '/abs.py'
def get_strategy_list(args):
info = getPluginDir() + '/ccxt/strategy/info.json'
info = json.loads(mw.readFile(info))
st_path = mw.getServerDir() + '/supervisor/conf.d'
page = 1
page_size = 5
search = ''
data = {}
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
dlist_sum = len(info)
page_start = int((page - 1) * page_size)
page_end = page_start + page_size
if page_end >= dlist_sum:
ret_data = info[page_start:]
else:
ret_data = info[page_start:page_end]
for x in range(len(ret_data)):
strategy_dst = st_path + '/ct_strategy_' + ret_data[x]['id'] + '.ini'
if os.path.exists(strategy_dst):
ret_data[x]['status'] = 'start'
else:
ret_data[x]['status'] = 'stop'
data['data'] = ret_data
data['args'] = args
data['list'] = mw.getPage(
{'count': dlist_sum, 'p': page, 'row': page_size, 'tojs': 'getStrategyList'})
return data
# callback ---------------------------------- end

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,26 @@
<style type="text/css">
.conf_p span{width: 100px;}
.code{padding: 20px 5px;border: 1px solid #e1e1e1;background: #fcfcfc;border-radius: 4px;line-height: 24px;}
.code span {display: block;margin-left: 15px;margin-bottom: 0;}
</style>
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('cryptocurrency_trade');">服务</p>
<p onclick="dbConf();">数据库配置</p>
<p onclick="syncDataList();">同步数据配置</p>
<p onclick="userConf();">账户配置</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
// resetPluginWinWidth(480);
resetPluginWinHeight(400);
$.getScript( "/plugins/file?name=cryptocurrency_trade&f=static/js/cryptocurrency_trade.js",function(){
pluginService('cryptocurrency_trade');
});
</script>

View File

@@ -0,0 +1,347 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import string
import subprocess
import json
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'cryptocurrency_trade'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getFatherDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace(
'{$SERVER_APP}', service_path + '/' + getPluginName())
return content
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':', 1)
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def isSqlError(mysqlMsg):
# 检测数据库执行错误
mysqlMsg = str(mysqlMsg)
if "MySQLdb" in mysqlMsg:
return mw.returnJson(False, 'MySQLdb组件缺失! <br>进入SSH命令行输入: pip install mysql-python | pip install mysqlclient==2.0.3')
if "2002," in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "2003," in mysqlMsg:
return mw.returnJson(False, "Can't connect to MySQL server on '127.0.0.1' (61)")
if "using password:" in mysqlMsg:
return mw.returnJson(False, '数据库密码错误')
if "1045" in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
def initDreplace():
log_dir = getServerDir() + '/logs'
if not os.path.exists(log_dir):
d = mw.execShell('mkdir -p ' + log_dir)
data = getConfigData()
data['token'] = ['btc']
writeConf(data)
return True
def status():
initDreplace()
return 'start'
def start():
syncDataAddTaskInstall()
return 'ok'
def stop():
syncDataAddTaskUninstall()
return 'ok'
def op():
return 'ok'
def getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeConf(data):
cfg_path = getServerDir() + "/data.cfg"
mw.writeFile(cfg_path, json.dumps(data))
return True
def getDbConf():
data = getConfigData()
if 'db' in data:
return mw.returnJson(True, 'ok', data['db'])
return mw.returnJson(False, 'ok', {})
def setDbConf():
args = getArgs()
data_args = checkArgs(args, ['db_host', 'db_port',
'db_name', 'db_user', 'db_pass'])
if not data_args[0]:
return data_args[1]
data = getConfigData()
data['db'] = args
writeConf(data)
db = mw.getMyORM()
db.setHost(args['db_host'])
db.setPort(args['db_port'])
db.setUser(args['db_user'])
db.setPwd(args['db_pass'])
testdata = db.query('select version()')
isError = isSqlError(testdata)
if isError != None:
return isError
return mw.returnJson(True, '保存成功,并连通成功!', [])
def getUserConf():
data = getConfigData()
if 'user' in data:
return mw.returnJson(True, 'ok', data['user'])
return mw.returnJson(False, 'ok', {})
def getUserConf():
data = getConfigData()
if 'user' in data:
try:
udata = mw.deDoubleCrypt('mw', data['user'])
udata = json.loads(udata)
return mw.returnJson(True, 'ok', udata)
except Exception as e:
pass
return mw.returnJson(False, 'ok', {})
def setUserConf():
args = getArgs()
data_args = checkArgs(args, ['app_key', 'secret',
'password', 'uid', 'exchange'])
if not data_args[0]:
return data_args[1]
data = getConfigData()
data['user'] = mw.enDoubleCrypt('mw', json.dumps(args))
writeConf(data)
return mw.returnJson(True, '保存成功!', [])
def syncDataList():
data = getConfigData()
name = "ct_task"
if 'token' in data:
rdata = {}
rdata['task_status'] = False
sup_path = mw.getServerDir() + '/supervisor'
sup_task_dst = sup_path + '/conf.d/' + name + '.ini'
if os.path.exists(sup_task_dst):
rdata['task_status'] = True
rdata['list'] = data['token']
return mw.returnJson(True, 'ok', rdata)
return mw.returnJson(False, 'ok')
def syncDataAdd():
args = getArgs()
data_args = checkArgs(args, ['token'])
if not data_args[0]:
return data_args[1]
add_token = args['token']
data = getConfigData()
if 'token' in data and data['token']:
if not add_token in data['token']:
data['token'].append(add_token)
else:
data['token'] = [add_token]
writeConf(data)
return mw.returnJson(True, '保存成功!')
def restartSup():
cmd = 'python3 plugins/supervisor/index.py restart'
mw.execShell(cmd)
def restartSupDst(name):
cmd = 'python3 plugins/supervisor/index.py restart_job {"name":"' + \
name + '","status":"stop"}'
mw.execShell(cmd)
def syncDataAddTaskUninstall():
sup_path = mw.getServerDir() + '/supervisor'
if not os.path.exists(sup_path):
return mw.returnJson(False, '需要安装并启动supervisor插件')
name = "ct_task"
sup_task_dst = sup_path + '/conf.d/' + name + '.ini'
if os.path.exists(sup_task_dst):
mw.execShell('rm -rf ' + sup_task_dst)
restartSup()
return mw.returnJson(True, '删除同步数据任务成功!')
def syncDataAddTaskInstall():
sup_path = mw.getServerDir() + '/supervisor'
if not os.path.exists(sup_path):
return mw.returnJson(False, '需要安装并启动supervisor插件')
name = "ct_task"
sup_task_tpl = getPluginDir() + '/conf/sup_task.tpl'
sup_task_dst = sup_path + '/conf.d/' + name + '.ini'
content = mw.readFile(sup_task_tpl)
content = content.replace(
'{$RUN_ROOT}', mw.getServerDir() + '/mdserver-web')
content = content.replace(
'{$SUP_ROOT}', sup_path)
content = content.replace(
'{$NAME}', name)
mw.writeFile(sup_task_dst, content)
restartSup()
return mw.returnJson(True, '添加同步数据任务成功!')
def syncDataAddTask():
args = getArgs()
data_args = checkArgs(args, ['check'])
if not data_args[0]:
return data_args[1]
if args['check'] == "0":
return syncDataAddTaskUninstall()
return syncDataAddTaskInstall()
def syncDataDelete():
args = getArgs()
data_args = checkArgs(args, ['token'])
if not data_args[0]:
return data_args[1]
del_token = args['token']
data = getConfigData()
if 'token' in data:
data['token'].remove(del_token)
writeConf(data)
return mw.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(op())
elif func == 'reload':
print(op())
elif func == 'get_db_conf':
print(getDbConf())
elif func == 'set_db_conf':
print(setDbConf())
elif func == 'get_user_conf':
print(getUserConf())
elif func == 'set_user_conf':
print(setUserConf())
elif func == 'sync_data_list':
print(syncDataList())
elif func == 'sync_data_add':
print(syncDataAdd())
elif func == 'sync_data_delete':
print(syncDataDelete())
elif func == 'sync_data_add_task':
print(syncDataAddTask())
else:
print('error')

View File

@@ -0,0 +1,36 @@
{
"hook":[
{
"tag":"menu",
"menu": {
"title":"量化交易",
"name":"cryptocurrency_trade",
"path":"static/html/index.html",
"css_path":"static/css/cryptocurrency_trade.css",
"js_path":"static/js/cryptocurrency_trade.js"
}
},
{
"tag":"global_static",
"global_static": {
"title":"量化交易",
"name":"cryptocurrency_trade",
"css_path":"static/css/ico.css"
}
}
],
"ps": "基于CCXT的数字货币量化交易插件",
"name": "cryptocurrency_trade",
"title": "量化交易",
"versions": ["1.0"],
"tip": "soft",
"checks": "server/cryptocurrency_trade",
"path":"server/cryptocurrency_trade",
"author": "midoks",
"date": "2022-02-25",
"home": "https://github.com/ccxt/ccxt",
"type": "量化交易",
"shell": "install.sh",
"pid": "5",
"sort": 7
}

View File

@@ -0,0 +1,63 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# cd /www/server/mdserver-web/plugins/cryptocurrency_trade && bash install.sh install
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
VERSION=$2
# pip3 install ccxt
if [ -f ${rootPath}/bin/activate ];then
. ${rootPath}/bin/activate
fi
pip3 install ccxt
pip3 install pandas
pip3 install pandas_ta
pip3 install pyTelegramBotAPI
pip3 install catalyst
pip3 install matplotlib==3.2.2
Install_App()
{
echo '正在安装脚本文件...'
mkdir -p $serverPath/source/cryptocurrency_trade
mkdir -p $serverPath/cryptocurrency_trade
echo "${VERSION}" > $serverPath/cryptocurrency_trade/version.pl
if [ ! -f $serverPath/source/cryptocurrency_trade/ta-lib-0.4.0-src.tar.gz ];then
wget -O $serverPath/source/cryptocurrency_trade/ta-lib-0.4.0-src.tar.gz https://sourceforge.net/projects/ta-lib/files/ta-lib/0.4.0/ta-lib-0.4.0-src.tar.gz
fi
if [ ! -d $serverPath/source/cryptocurrency_trade/ta-lib ];then
cd $serverPath/source/cryptocurrency_trade/ta-lib && tar -xzf ta-lib-0.4.0-src.tar.gz
cd ta-lib && ./configure --prefix=/usr && make && make install
rm -rf $serverPath/source/cryptocurrency_trade/ta-lib
pip3 install ta-lib
fi
cd ${rootPath} && python3 ${rootPath}/plugins/cryptocurrency_trade/index.py start
echo '安装完成'
}
Uninstall_App()
{
rm -rf $serverPath/cryptocurrency_trade
cd ${rootPath} && python3 ${rootPath}/plugins/cryptocurrency_trade/index.py stop
echo "卸载完成"
}
action=$1
if [ "${1}" = 'install' ];then
Install_App
else
Uninstall_App
fi

View File

@@ -0,0 +1,11 @@
.screen-all {
padding: 5px;
}
.s-right .panel-default{
margin-bottom: 10px;
}
.s-left .panel-default{
margin-bottom: 10px;
}

View File

@@ -0,0 +1,11 @@
/* menu start */
.menu .current .menu_plugin_cryptocurrency_trade:hover {
background-image: url("/plugins/file?name=cryptocurrency_trade&f=ico.png");
}
.menu .menu_plugin_cryptocurrency_trade {
background-image: url("/plugins/file?name=cryptocurrency_trade&f=ico.png");
}
/* menu end */

View File

@@ -0,0 +1,65 @@
<div class="main-content">
<div class="screen-all">
<div class="content-screen safe bgw mtb15 ptb10 radius4 row" style="height: 300px;">
<!-- start -->
<div class="s-left col-md-8" style="padding-left: 2.5px;padding-right: 5px; overflow-y: scroll;height: 400px;">
<div class="panel panel-default">
<div class="panel-heading">订单数据</div>
<div class="panel-body">Panel content</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">交易图表</div>
<div class="panel-body" style="padding: 0px;">
<div></div>
<div id="k_echarts" style="width: auto;height:400px;"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">策略交易日志</div>
<div class="panel-body" style="padding: 0px;">
<pre id="strategy_log" style="border:none;font-size:12px;white-space: pre;margin: 0px;width: auto;height: 200px;background-color: #333;color:#fff; padding:0 5px">当前没有日志.</pre>
</div>
</div>
</div>
<div class="s-right col-md-4" style="padding-left: 2.5px;padding-right: 5px; overflow-y: scroll;height: 400px;">
<div class="panel panel-default">
<div class="panel-heading">策略配置</div>
<div class="panel-body divtable pd15 relative" style="padding: 2px 2px 5px;">
<table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">
<thead>
<tr>
<th width="20">序列</th>
<th width="120">说明</th>
<th width="10">状态</th>
<th style="text-align: right;" width="50">操作</th>
</tr>
</thead>
<tbody id="strategy_list"></tbody>
</table>
<div class="dataTables_paginate paging_bootstrap pagination">
<ul id="strategy_list_page" class="page"></ul>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">数据源日志</div>
<div class="panel-body" style="padding: 0px;">
<pre id="datasource_log" style="border:none;font-size:12px;white-space: pre;margin: 0px;width: auto;height: 200px;background-color: #333;color:#fff; padding:0 5px">当前没有日志.</pre>
</div>
</div>
</div>
<!-- end -->
</div>
</div>
</div>

View File

@@ -0,0 +1,964 @@
function appPost(method,args,callback, title){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(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:'cryptocurrency_trade', 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 appPostN(method,args,callback, title){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
var _title = '正在获取...';
if (typeof(title) != 'undefined'){
_title = title;
}
$.post('/plugins/run', {name:'cryptocurrency_trade', func:method, args:_args}, function(data) {
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function appAsyncPost(method,args){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
return syncPost('/plugins/run', {name:'cryptocurrency_trade', func:method, args:_args});
}
function appPostCallbak(method, args,callback, script){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'cryptocurrency_trade';
req_data['func'] = method;
if (typeof(script) != 'undefined'){
req_data['script'] = script;
}
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, 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 appPostCallbakNoMsg(method, args,callback, script){
var req_data = {};
req_data['name'] = 'cryptocurrency_trade';
req_data['func'] = method;
if (typeof(script) != 'undefined'){
req_data['script'] = script;
} else {
req_data['script'] = req_data['name'];
}
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function dbConf(){
appPost('get_db_conf','',function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
var db_host = '127.0.0.1';
var db_port = '3306';
var db_name = 'cryptocurrency_trade';
var db_user = 'cryptocurrency_trade';
var db_pass = 'cryptocurrency_trade';
if(rdata['status']){
db_data = rdata['data'];
db_host = db_data['db_host'];
db_port = db_data['db_port'];
db_name = db_data['db_name'];
db_user = db_data['db_user'];
db_pass = db_data['db_pass'];
}
var mlist = '';
mlist += '<p><span>数据库地址</span><input style="width: 250px;" class="bt-input-text mr5" name="db_host" value="'+db_host+'" type="text"></p>'
mlist += '<p><span>数据库端口</span><input style="width: 250px;" class="bt-input-text mr5" name="db_port" value="'+db_port+'" type="text"></p>'
mlist += '<p><span>数据库名称</span><input style="width: 250px;" class="bt-input-text mr5" name="db_name" value="'+db_name+'" type="text"></p>'
mlist += '<p><span>用户名</span><input style="width: 250px;" class="bt-input-text mr5" name="db_user" value="'+db_user+'" type="text"></p>'
mlist += '<p><span>密码</span><input style="width: 250px;" class="bt-input-text mr5" name="db_pass" value="'+db_pass+'" type="text"></p>'
var option = '<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" onclick="submitDbConf()">保存</button>\
</div>\
</div>';
$(".soft-man-con").html(option);
});
}
function submitDbConf(){
var pull_data = {};
pull_data['db_host'] = $('input[name="db_host"]').val();
pull_data['db_port'] = $('input[name="db_port"]').val();
pull_data['db_name'] = $('input[name="db_name"]').val();
pull_data['db_user'] = $('input[name="db_user"]').val();
pull_data['db_pass'] = $('input[name="db_pass"]').val();
appPost('set_db_conf',pull_data,function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata['msg'],{icon:rdata['status']?1:2,time:2000,shade: [0.3, '#000']});
});
}
function userConf(){
appPost('get_user_conf','',function(data){
var rdata = $.parseJSON(data.data);
var app_key = 'app_key';
var secret = 'secret';
var password = 'password';
var uid = 'uid';
var exchange = 'okex';
if(rdata['status']){
db_data = rdata['data'];
app_key = db_data['app_key'];
secret = db_data['secret'];
password = db_data['password'];
uid = db_data['uid'];
exchange = db_data['exchange'];;
}
var mlist = '';
mlist += '<p><span>交易所</span><input style="width: 250px;" class="bt-input-text mr5" name="exchange" value="'+exchange+'" type="text"><font>必填写[okex, binance]</font></p>'
mlist += '<p><span>apiKey</span><input style="width: 250px;" class="bt-input-text mr5" name="app_key" value="'+app_key+'" type="text"><font>必填写</font></p>'
mlist += '<p><span>secret</span><input style="width: 250px;" class="bt-input-text mr5" name="secret" value="'+secret+'" type="text"><font>必填写</font></p>'
mlist += '<p><span>password</span><input style="width: 250px;" class="bt-input-text mr5" name="password" value="'+password+'" type="text"><font>根据情况填写</font></p>'
mlist += '<p><span>uid</span><input style="width: 250px;" class="bt-input-text mr5" name="uid" value="'+uid+'" type="text"><font>根据情况填写</font></p>'
var option = '<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" onclick="submitUserConf()">保存</button>\
</div>\
</div>';
$(".soft-man-con").html(option);
});
}
function submitUserConf(){
var pull_data = {};
pull_data['app_key'] = $('input[name="app_key"]').val();
pull_data['secret'] = $('input[name="secret"]').val();
pull_data['password'] = $('input[name="password"]').val();
pull_data['uid'] = $('input[name="uid"]').val();
pull_data['exchange'] = $('input[name="exchange"]').val();
appPost('set_user_conf',pull_data,function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata['msg'],{icon:rdata['status']?1:2,time:2000,shade: [0.3, '#000']});
});
}
function syncDataList(){
appPost('sync_data_list', {}, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
if (rdata['status']){
var dlist = rdata['data']['list'];
for(i in dlist){
list += '<tr>';
list += '<td>' + dlist[i] +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="syncDataDelete(\''+dlist[i]+'\')" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
}
if( list == '' ){
list = "<tr><td colspan='2'>当前没有数据</td></tr>";
}
var task_status = rdata['data']['task_status'];
var task_status_check = '';
if (task_status){
task_status_check = 'checked';
}
var con = '<div class="safe bgw">\
<div>\
<button onclick="syncDataAdd()" title="添加币种" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加币种</button>\
<div class="ss-text pull-left mr50">\
<em>是否启动</em>\
<div class="ssh-item">\
<input class="btswitch btswitch-ios" id="add_task" type="checkbox" '+task_status_check+'>\
<label class="btswitch-btn" for="add_task" onclick="syncDataAddTask()"></label>\
</div>\
</div>\
</div>\
<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead>\
<th>名称</th>\
<th style="text-align:right;">操作</th></tr>\
</thead>\
<tbody>'+ list +'</tbody>\
</table>\
</div>\
</div>\
</div>';
con += '<div class="code">\
<span>详细如下:</span>\
<span>*:添加同步的币种,都小写,以USDT为本币同步数据。</span>\
<span>*:需要提前安装supervisor插件。</span>\
</div>'
$(".soft-man-con").html(con);
$('#databasePage').html(rdata.page);
});
}
function syncDataAddTask(){
var at_check = $('#add_task').prop('checked');
appPost("sync_data_add_task", {'check':at_check?'0':'1'}, function(data){
rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
syncDataList();
}
},{icon:rdata.status?1:2});
});
}
function syncDataDelete(name){
appPost("sync_data_delete", {"token":name}, function(data){
rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
syncDataList();
}
},{icon:rdata.status?1:2});
});
}
function syncDataAdd() {
layer.open({
type: 1,
area: '500px',
title: '添加同步数据',
closeBtn: 2,
shift: 0,
shadeClose: false,
btn: ['确定', '取消'],
content: "<div class='bt_conter bt-form pd15' style='height:auto;width:100%;'>\
<div class='line'>\
<span class='tname'>名称</span>\
<div class='info-r c4'>\
<input id='name' class='bt-input-text' type='text' name='name' placeholder='请输入名称' style='width:270px' />\
</div>\
</div>\
<ul class='help-info-text c7' style='padding-left: 29px;margin-top:5px;'>\
<li style='color:#F00'>注意:币种名称用小写!</li>\
</ul>\
</div>",
yes: function(index, layero){
var token = $('input[name="name"]').val();
appPost("sync_data_add", {"token":token}, function(data){
rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
syncDataList();
}
},{icon:rdata.status?1:2});
})
return;
}
});
}
function onlineEditStrategyFile(k, f, tag) {
if(k != 0) {
var l = $("#PathPlace input").val();
var h = $("#textBody").val();
var a = $("select[name=encoding]").val();
var loadT = layer.msg("正在保存中...", {icon: 16,time: 0});
appPostCallbakNoMsg('save_body',{'data':h,'path':f,'encoding':a,"tag":tag}, function(data){
var rdata = data.data;
showMsg(rdata.msg, function(){
if (rdata.status){
layer.close(loadT);
}
},{icon: rdata.status ? 1 : 2});
});
return
}
var e = layer.msg("正在读取文件,请稍候...", {icon: 16,time: 0});
var g = f.split(".");
var b = g[g.length - 1];
var d;
switch(b) {
case "html":
var j = {
name: "htmlmixed",
scriptTypes: [{
matches: /\/x-handlebars-template|\/x-mustache/i,
mode: null
}, {
matches: /(text|application)\/(x-)?vb(a|script)/i,
mode: "vbscript"
}]
};
d = j;
break;
case "htm":
var j = {
name: "htmlmixed",
scriptTypes: [{
matches: /\/x-handlebars-template|\/x-mustache/i,
mode: null
}, {
matches: /(text|application)\/(x-)?vb(a|script)/i,
mode: "vbscript"
}]
};
d = j;
break;
case "js":
d = "text/javascript";
break;
case "json":
d = "application/ld+json";
break;
case "css":
d = "text/css";
break;
case "php":
d = "application/x-httpd-php";
break;
case "tpl":
d = "application/x-httpd-php";
break;
case "xml":
d = "application/xml";
break;
case "sql":
d = "text/x-sql";
break;
case "conf":
d = "text/x-nginx-conf";
break;
default:
var j = {
name: "htmlmixed",
scriptTypes: [{
matches: /\/x-handlebars-template|\/x-mustache/i,
mode: null
}, {
matches: /(text|application)\/(x-)?vb(a|script)/i,
mode: "vbscript"
}]
};
d = j
}
$.post("/files/get_body", "path=" + encodeURIComponent(f), function(s) {
if(s.status === false){
layer.msg(s.msg,{icon:5});
return;
}
layer.close(e);
var u = ["utf-8", "GBK", "GB2312", "BIG5"];
var n = "";
var m = "";
var o = "";
for(var p = 0; p < u.length; p++) {
m = s.data.encoding == u[p] ? "selected" : "";
n += '<option value="' + u[p] + '" ' + m + ">" + u[p] + "</option>";
}
var code_mirror = null;
var r = layer.open({
type: 1,
shift: 5,
closeBtn: 1,
area: ["90%", "90%"],
title: "在线编辑[" + f + "]",
btn:['保存','关闭'],
content: '<form class="bt-form pd20">\
<div class="line">\
<p style="color:red;margin-bottom:10px">提示:Ctrl+F 搜索关键字,Ctrl+G 查找下一个,Ctrl+S 保存,Ctrl+Shift+R 查找替换!\
<select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select>\
</p>\
<textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" />\
</div>\
</form>',
success:function(){
$("#textBody").text(s.data.data);
var q = $(window).height() * 0.9;
$("#textBody").height(q - 160);
code_mirror = CodeMirror.fromTextArea(document.getElementById("textBody"), {
extraKeys: {
"Ctrl-F": "findPersistent",
"Ctrl-H": "replaceAll",
"Ctrl-S": function() {
$("#textBody").text(code_mirror.getValue());
onlineEditStrategyFile(2, f,tag);
},
"Cmd-S":function() {
$("#textBody").text(code_mirror.getValue());
onlineEditStrategyFile(2, f,tag);
},
},
mode: d,
lineNumbers: true,
matchBrackets: true,
matchtags: true,
autoMatchParens: true
});
code_mirror.focus();
code_mirror.setSize("auto", q - 150);
$(window).resize(function(){
var q = $(window).height() * 0.9;
code_mirror.setSize("auto", q - 150);
});
},
yes:function(){
$("#textBody").text(code_mirror.getValue());
onlineEditStrategyFile(1, f, tag);
}
});
//////////////////
},'json');
}
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// 大屏页功能 --------------------------------------------------------------------
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
function changeDivH(){
var l = $(window).height();
$('.content-screen').css('height',l-80);
$('.s-right').css('height',l-80-10);
$('.s-left').css('height',l-80-10);
}
function dataSourceLog(){
appPostCallbakNoMsg('get_datasource_logs',{}, function(rdata){
$('#datasource_log').html(rdata.data);
});
}
function dataStrategyLog(){
appPostCallbakNoMsg('get_strategy_logs',{}, function(rdata){
$('#strategy_log').html(rdata.data);
});
}
// $('#strategy_list').find('span[data-id="01"]')
function setStrategyStatus(id,status){
appPostCallbakNoMsg('set_strategy_status',{"id":id,"status":status}, function(data){
var rdata = data.data;
showMsg(rdata.msg,function(){
if (rdata.status){
if (status == 'start'){
$('#strategy_list').find('tr[data-id="'+id+'"] td span').removeClass('glyphicon-pause').addClass('glyphicon-play').css('color','#20a53a');
} else{
$('#strategy_list').find('tr[data-id="'+id+'"] td span').removeClass('glyphicon-play').addClass('glyphicon-pause').css('color','red');
}
}
},{icon:rdata.status?1:2},2000);
});
}
function setStrategyRestart(id){
appPostCallbakNoMsg('set_strategy_restart',{"id":id}, function(data){
console.log(data);
var rdata = data.data;
showMsg(rdata.msg,function(){
if (rdata.status){
}
},{icon:rdata.status?1:2},2000);
});
}
function setStrategyEdit(id){
appPostCallbakNoMsg('get_strategy_path',{"id":id}, function(data){
onlineEditStrategyFile(0,data.data.msg,id);
});
}
function getStrategyList(p=1){
appPostCallbakNoMsg('get_strategy_list',{'page':p}, function(rdata){
// console.log(rdata);
ldata = rdata.data.data;
var tBody = '';
for (var i = 0; i < ldata.length; i++) {
tBody += '<tr data-id="'+ldata[i]['id']+'">'
tBody += '<td>'+ldata[i]['id']+'</td>';
tBody += '<td>'+ldata[i]['name']+'</td>';
if (ldata[i]['status'] == 'start'){
tBody += '<td><span style="color:#20a53a;cursor: pointer;" class="strategy_status glyphicon glyphicon-play"></span></td>';
} else{
tBody += '<td><span style="color:red;cursor: pointer;" class="strategy_status glyphicon glyphicon-pause"></span></td>';
}
tBody += "<td style='text-align: right;'><a class='btlink restart'>重启</a> | <a class='btlink edit'>编辑</a></td>";
tBody +='<tr>';
}
// console.log(tBody);
$('#strategy_list').html(tBody);
$('#strategy_list_page').html(rdata.data.list);
$('#strategy_list .strategy_status').click(function(){
var id = $(this).parent().parent().data('id');
var status = 'stop';
if ($(this).hasClass('glyphicon-pause')){
status = 'start';
}
setStrategyStatus(id,status);
});
$('#strategy_list .restart').click(function(){
var id = $(this).parent().parent().data('id');
setStrategyRestart(id);
});
$('#strategy_list .edit').click(function(){
var id = $(this).parent().parent().data('id');
setStrategyEdit(id);
});
});
}
function calcKLineChats(){
var chartDom = document.getElementById('k_echarts');
var myChart = echarts.init(chartDom);
var option;
const upColor = '#ec0000';
const upBorderColor = '#8A0000';
const downColor = '#00da3c';
const downBorderColor = '#008F28';
// Each item: open,close,lowest,highest
const data0 = splitData([
['2013/1/24', 2320.26, 2320.26, 2287.3, 2362.94],
['2013/1/25', 2300, 2291.3, 2288.26, 2308.38],
['2013/1/28', 2295.35, 2346.5, 2295.35, 2346.92],
['2013/1/29', 2347.22, 2358.98, 2337.35, 2363.8],
['2013/1/30', 2360.75, 2382.48, 2347.89, 2383.76],
['2013/1/31', 2383.43, 2385.42, 2371.23, 2391.82],
['2013/2/1', 2377.41, 2419.02, 2369.57, 2421.15],
['2013/2/4', 2425.92, 2428.15, 2417.58, 2440.38],
['2013/2/5', 2411, 2433.13, 2403.3, 2437.42],
['2013/2/6', 2432.68, 2434.48, 2427.7, 2441.73],
['2013/2/7', 2430.69, 2418.53, 2394.22, 2433.89],
['2013/2/8', 2416.62, 2432.4, 2414.4, 2443.03],
['2013/2/18', 2441.91, 2421.56, 2415.43, 2444.8],
['2013/2/19', 2420.26, 2382.91, 2373.53, 2427.07],
['2013/2/20', 2383.49, 2397.18, 2370.61, 2397.94],
['2013/2/21', 2378.82, 2325.95, 2309.17, 2378.82],
['2013/2/22', 2322.94, 2314.16, 2308.76, 2330.88],
['2013/2/25', 2320.62, 2325.82, 2315.01, 2338.78],
['2013/2/26', 2313.74, 2293.34, 2289.89, 2340.71],
['2013/2/27', 2297.77, 2313.22, 2292.03, 2324.63],
['2013/2/28', 2322.32, 2365.59, 2308.92, 2366.16],
['2013/3/1', 2364.54, 2359.51, 2330.86, 2369.65],
['2013/3/4', 2332.08, 2273.4, 2259.25, 2333.54],
['2013/3/5', 2274.81, 2326.31, 2270.1, 2328.14],
['2013/3/6', 2333.61, 2347.18, 2321.6, 2351.44],
['2013/3/7', 2340.44, 2324.29, 2304.27, 2352.02],
['2013/3/8', 2326.42, 2318.61, 2314.59, 2333.67],
['2013/3/11', 2314.68, 2310.59, 2296.58, 2320.96],
['2013/3/12', 2309.16, 2286.6, 2264.83, 2333.29],
['2013/3/13', 2282.17, 2263.97, 2253.25, 2286.33],
['2013/3/14', 2255.77, 2270.28, 2253.31, 2276.22],
['2013/3/15', 2269.31, 2278.4, 2250, 2312.08],
['2013/3/18', 2267.29, 2240.02, 2239.21, 2276.05],
['2013/3/19', 2244.26, 2257.43, 2232.02, 2261.31],
['2013/3/20', 2257.74, 2317.37, 2257.42, 2317.86],
['2013/3/21', 2318.21, 2324.24, 2311.6, 2330.81],
['2013/3/22', 2321.4, 2328.28, 2314.97, 2332],
['2013/3/25', 2334.74, 2326.72, 2319.91, 2344.89],
['2013/3/26', 2318.58, 2297.67, 2281.12, 2319.99],
['2013/3/27', 2299.38, 2301.26, 2289, 2323.48],
['2013/3/28', 2273.55, 2236.3, 2232.91, 2273.55],
['2013/3/29', 2238.49, 2236.62, 2228.81, 2246.87],
['2013/4/1', 2229.46, 2234.4, 2227.31, 2243.95],
['2013/4/2', 2234.9, 2227.74, 2220.44, 2253.42],
['2013/4/3', 2232.69, 2225.29, 2217.25, 2241.34],
['2013/4/8', 2196.24, 2211.59, 2180.67, 2212.59],
['2013/4/9', 2215.47, 2225.77, 2215.47, 2234.73],
['2013/4/10', 2224.93, 2226.13, 2212.56, 2233.04],
['2013/4/11', 2236.98, 2219.55, 2217.26, 2242.48],
['2013/4/12', 2218.09, 2206.78, 2204.44, 2226.26],
['2013/4/15', 2199.91, 2181.94, 2177.39, 2204.99],
['2013/4/16', 2169.63, 2194.85, 2165.78, 2196.43],
['2013/4/17', 2195.03, 2193.8, 2178.47, 2197.51],
['2013/4/18', 2181.82, 2197.6, 2175.44, 2206.03],
['2013/4/19', 2201.12, 2244.64, 2200.58, 2250.11],
['2013/4/22', 2236.4, 2242.17, 2232.26, 2245.12],
['2013/4/23', 2242.62, 2184.54, 2182.81, 2242.62],
['2013/4/24', 2187.35, 2218.32, 2184.11, 2226.12],
['2013/4/25', 2213.19, 2199.31, 2191.85, 2224.63],
['2013/4/26', 2203.89, 2177.91, 2173.86, 2210.58],
['2013/5/2', 2170.78, 2174.12, 2161.14, 2179.65],
['2013/5/3', 2179.05, 2205.5, 2179.05, 2222.81],
['2013/5/6', 2212.5, 2231.17, 2212.5, 2236.07],
['2013/5/7', 2227.86, 2235.57, 2219.44, 2240.26],
['2013/5/8', 2242.39, 2246.3, 2235.42, 2255.21],
['2013/5/9', 2246.96, 2232.97, 2221.38, 2247.86],
['2013/5/10', 2228.82, 2246.83, 2225.81, 2247.67],
['2013/5/13', 2247.68, 2241.92, 2231.36, 2250.85],
['2013/5/14', 2238.9, 2217.01, 2205.87, 2239.93],
['2013/5/15', 2217.09, 2224.8, 2213.58, 2225.19],
['2013/5/16', 2221.34, 2251.81, 2210.77, 2252.87],
['2013/5/17', 2249.81, 2282.87, 2248.41, 2288.09],
['2013/5/20', 2286.33, 2299.99, 2281.9, 2309.39],
['2013/5/21', 2297.11, 2305.11, 2290.12, 2305.3],
['2013/5/22', 2303.75, 2302.4, 2292.43, 2314.18],
['2013/5/23', 2293.81, 2275.67, 2274.1, 2304.95],
['2013/5/24', 2281.45, 2288.53, 2270.25, 2292.59],
['2013/5/27', 2286.66, 2293.08, 2283.94, 2301.7],
['2013/5/28', 2293.4, 2321.32, 2281.47, 2322.1],
['2013/5/29', 2323.54, 2324.02, 2321.17, 2334.33],
['2013/5/30', 2316.25, 2317.75, 2310.49, 2325.72],
['2013/5/31', 2320.74, 2300.59, 2299.37, 2325.53],
['2013/6/3', 2300.21, 2299.25, 2294.11, 2313.43],
['2013/6/4', 2297.1, 2272.42, 2264.76, 2297.1],
['2013/6/5', 2270.71, 2270.93, 2260.87, 2276.86],
['2013/6/6', 2264.43, 2242.11, 2240.07, 2266.69],
['2013/6/7', 2242.26, 2210.9, 2205.07, 2250.63],
['2013/6/13', 2190.1, 2148.35, 2126.22, 2190.1]
]);
function splitData(rawData) {
const categoryData = [];
const values = [];
for (var i = 0; i < rawData.length; i++) {
categoryData.push(rawData[i].splice(0, 1)[0]);
values.push(rawData[i]);
}
return {
categoryData: categoryData,
values: values
};
}
function calculateMA(dayCount) {
var result = [];
for (var i = 0, len = data0.values.length; i < len; i++) {
if (i < dayCount) {
result.push('-');
continue;
}
var sum = 0;
for (var j = 0; j < dayCount; j++) {
sum += +data0.values[i - j][1];
}
result.push(sum / dayCount);
}
return result;
}
option = {
title: {
text: '上证指数',
left: 0
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
legend: {
data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30']
},
grid: {
left: '10%',
right: '10%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: data0.categoryData,
boundaryGap: false,
axisLine: { onZero: false },
splitLine: { show: false },
min: 'dataMin',
max: 'dataMax'
},
yAxis: {
scale: true,
splitArea: {
show: true
}
},
dataZoom: [
{
type: 'inside',
start: 50,
end: 100
},
{
show: true,
type: 'slider',
top: '90%',
start: 50,
end: 100
}
],
series: [
{
name: '日K',
type: 'candlestick',
data: data0.values,
itemStyle: {
color: upColor,
color0: downColor,
borderColor: upBorderColor,
borderColor0: downBorderColor
},
markPoint: {
label: {
formatter: function (param) {
return param != null ? Math.round(param.value) + '' : '';
}
},
data: [
{
name: 'Mark',
coord: ['2013/5/31', 2300],
value: 2300,
itemStyle: {
color: 'rgb(41,60,85)'
}
},
{
name: 'highest value',
type: 'max',
valueDim: 'highest'
},
{
name: 'lowest value',
type: 'min',
valueDim: 'lowest'
},
{
name: 'average value on close',
type: 'average',
valueDim: 'close'
}
],
tooltip: {
formatter: function (param) {
return param.name + '<br>' + (param.data.coord || '');
}
}
},
markLine: {
symbol: ['none', 'none'],
data: [
[
{
name: 'from lowest to highest',
type: 'min',
valueDim: 'lowest',
symbol: 'circle',
symbolSize: 10,
label: {
show: false
},
emphasis: {
label: {
show: false
}
}
},
{
type: 'max',
valueDim: 'highest',
symbol: 'circle',
symbolSize: 10,
label: {
show: false
},
emphasis: {
label: {
show: false
}
}
}
],
{
name: 'min line on close',
type: 'min',
valueDim: 'close'
},
{
name: 'max line on close',
type: 'max',
valueDim: 'close'
}
]
}
},
{
name: 'MA5',
type: 'line',
data: calculateMA(5),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
{
name: 'MA10',
type: 'line',
data: calculateMA(10),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
{
name: 'MA20',
type: 'line',
data: calculateMA(20),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
{
name: 'MA30',
type: 'line',
data: calculateMA(30),
smooth: true,
lineStyle: {
opacity: 0.5
}
}
]
};
option && myChart.setOption(option);
}
$(document).ready(function(){
var tag = $.getUrlParam('tag');
if(tag == 'cryptocurrency_trade'){
changeDivH();
// 获取数据源更新日志
dataSourceLog();
setInterval(function(){
dataSourceLog();
},3000);
// 获取策略更新日志
dataStrategyLog();
setInterval(function(){
dataStrategyLog();
},5000);
getStrategyList(1);
calcKLineChats();
}
});
$(window).resize(function(){
changeDivH();
});

View File

@@ -26,7 +26,7 @@ Uninstall_App()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_App
else
Uninstall_App

View File

@@ -37,6 +37,7 @@ class nosqlMemcached():
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_STATUS = None
__DB_LOCAL = None
@@ -48,19 +49,36 @@ class nosqlMemcached():
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
mem_path = "{}/memcached".format(mw.getServerDir())
if not os.path.exists(mem_path): return False
if not os.path.exists(mem_path):
self.__DB_STATUS = 'not_installed'
return False
if not self.__DB_LOCAL:
if not self.__config:
self.__DB_STATUS = 'not_installed'
return False
self.__DB_PORT = int(self.__config['port'])
try:
self.__DB_CONN = pymemcache.client.base.PooledClient((self.__DB_HOST,self.__DB_PORT), max_pool_size=4)
# PooledClient 是惰性连接,探测一次,服务未启动时及时返回 False
self.__DB_CONN.version()
self.__DB_STATUS = None
return self.__DB_CONN
except pymemcache.exceptions.MemcacheError:
self.__DB_STATUS = 'not_running'
return False
except (ConnectionRefusedError, OSError):
self.__DB_STATUS = 'not_running'
return False
except Exception:
self.__DB_ERR = mw.getTracebackInfo()
self.__DB_STATUS = 'not_running'
return False
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
def get_status(self):
return self.__DB_STATUS
# 获取配置项
def get_options(self, get=None):
@@ -95,11 +113,20 @@ class nosqlMemcachedCtr():
instance = nosqlMemcached()
return instance
def _connect(self, sid):
obj = self.getInstanceBySid(sid)
conn = obj.conn()
if conn is False:
if obj.get_status() == 'not_installed':
return None, mw.returnData(False, '未安装')
return None, mw.returnData(False, '未启动')
return conn, None
def getItems(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
mem_instance, err = self._connect(sid)
if err:
return err
result = {}
m_items = mem_instance.stats('items')
@@ -122,9 +149,9 @@ class nosqlMemcachedCtr():
def getKeyList(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
mem_instance, err = self._connect(sid)
if err:
return err
p = 1
@@ -194,9 +221,9 @@ class nosqlMemcachedCtr():
def delVal(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
mem_instance, err = self._connect(sid)
if err:
return err
key = args['key']
mem_instance.delete(key)
@@ -205,9 +232,9 @@ class nosqlMemcachedCtr():
def setKv(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
mem_instance, err = self._connect(sid)
if err:
return err
key = args['key']
val = args['val']
@@ -217,9 +244,9 @@ class nosqlMemcachedCtr():
def clear(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
mem_instance, err = self._connect(sid)
if err:
return err
mem_instance.flush_all()
return mw.returnData(True,'清空成功!')

View File

@@ -127,6 +127,7 @@ class nosqlMongodb():
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_STATUS = None
__DB_LOCAL = None
@@ -138,29 +139,51 @@ class nosqlMongodb():
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
mgdb_path = "{}/mongodb".format(mw.getServerDir())
if not os.path.exists(mgdb_path): return False
if not os.path.exists(mgdb_path):
self.__DB_STATUS = 'not_installed'
return False
if not self.__DB_LOCAL:
if not self.__config:
self.__DB_STATUS = 'not_installed'
return False
self.__DB_PORT = int(self.__config['port'])
auth = getConfAuth()
port = getConfPort()
mg_root = pSqliteDb('config').where('id=?', (1,)).getField('mg_root')
# print(auth,self.__DB_HOST,port, self.__DB_PASS)
try:
if auth == 'disabled':
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True)
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True, serverSelectionTimeoutMS=3000)
else:
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True, username='root',password=mg_root)
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=port, directConnection=True, username='root',password=mg_root, serverSelectionTimeoutMS=3000)
self.__DB_CONN.admin.command('ping')
# 节点处于 recovering/startup 时 ping 仍会成功,但读写会抛 NotPrimaryError
try:
hello = self.__DB_CONN.admin.command('hello')
except Exception:
# MongoDB < 5.0 没有 hello 命令
hello = self.__DB_CONN.admin.command('isMaster')
if not (hello.get('isWritablePrimary') or hello.get('ismaster') or hello.get('secondary')):
self.__DB_ERR = 'MongoDB 节点当前不是 primary 或 secondary 状态'
return False
self.__DB_STATUS = None
self.__DB_ERR = None
return self.__DB_CONN
except pymongo.errors.ConnectionFailure:
self.__DB_STATUS = 'not_running'
return False
except Exception as e:
# print(e)
self.__DB_ERR = mw.getTracebackInfo()
except Exception:
self.__DB_STATUS = 'not_running'
return False
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
def get_status(self):
return self.__DB_STATUS
def get_err(self):
return self.__DB_ERR
# 获取配置项
def get_options(self, get=None):
result = {}
@@ -170,7 +193,7 @@ class nosqlMongodb():
keys = ["bind_ip", "port"]
result['host'] = '127.0.0.1'
rep = 'port\s*=\s*(.*)'
rep = r'port\s*=\s*(.*)'
ip_re = re.search(rep, mgdb_content)
if ip_re:
result['port'] = int(ip_re.groups()[0].strip())
@@ -202,11 +225,23 @@ class nosqlMongodbCtr():
instance = nosqlMongodb()
return instance
def _connect(self, sid):
obj = self.getInstanceBySid(sid)
conn = obj.mgdb_conn()
if conn is False:
if obj.get_status() == 'not_installed':
return None, mw.returnData(False, '未安装')
err = obj.get_err()
if err:
return None, mw.returnData(False, err)
return None, mw.returnData(False, '未启动')
return conn, None
def getDbList(self, args):
sid = args['sid']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
mgdb_instance, err = self._connect(sid)
if err:
return err
result = {}
doc_list = mgdb_instance.list_database_names()
@@ -221,9 +256,9 @@ class nosqlMongodbCtr():
sid = args['sid']
name = args['name']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接.')
mgdb_instance, err = self._connect(sid)
if err:
return err
result = {}
collections = mgdb_instance[name].list_collection_names()
@@ -242,9 +277,9 @@ class nosqlMongodbCtr():
if 'size' in args:
size = args['size']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
mgdb_instance, err = self._connect(sid)
if err:
return err
db_instance = mgdb_instance[db]
collection_instance = db_instance[collection]
@@ -303,9 +338,9 @@ class nosqlMongodbCtr():
db = args['db']
collection = args['collection']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
mgdb_instance, err = self._connect(sid)
if err:
return err
db_instance = mgdb_instance[db]
collection_instance = db_instance[collection]

View File

@@ -32,6 +32,7 @@ class nosqlRedis():
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_STATUS = None
__DB_LOCAL = None
@@ -44,9 +45,13 @@ class nosqlRedis():
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
redis_path = "{}/redis".format(mw.getServerDir())
if not os.path.exists(redis_path):
self.__DB_STATUS = 'not_installed'
return False
if not self.__DB_LOCAL:
if not self.__config:
self.__DB_STATUS = 'not_installed'
return False
self.__DB_PASS = self.__config['requirepass']
self.__DB_PORT = int(self.__config['port'])
@@ -55,13 +60,20 @@ class nosqlRedis():
redis_pool = redis.ConnectionPool(host=self.__DB_HOST, port=self.__DB_PORT, password=self.__DB_PASS, db=db_idx, socket_timeout=3)
self.__DB_CONN = redis.Redis(connection_pool=redis_pool)
self.__DB_CONN.ping()
self.__DB_STATUS = None
return self.__DB_CONN
except redis.exceptions.ConnectionError:
self.__DB_STATUS = 'not_running'
return False
except Exception:
self.__DB_ERR = mw.getTracebackInfo()
self.__DB_STATUS = 'not_running'
return False
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
def get_status(self):
return self.__DB_STATUS
# 获取配置项
def get_options(self, get=None):
@@ -112,12 +124,21 @@ class nosqlRedisCtr():
instance = nosqlRedis()
return instance
def _connect(self, sid, idx=0):
obj = self.getInstanceBySid(sid)
conn = obj.redis_conn(idx)
if conn is False:
if obj.get_status() == 'not_installed':
return None, mw.returnData(False, '未安装')
return None, mw.returnData(False, '未启动')
return conn, None
def getList(self, args):
sid = args['sid']
redis_instance = self.getInstanceBySid(sid).redis_conn(0)
if redis_instance is False:
return mw.returnData(False,'无法链接')
redis_instance, err = self._connect(sid, 0)
if err:
return err
redis_info = redis_instance.info()
@@ -166,7 +187,9 @@ class nosqlRedisCtr():
if 'search' in args and args['search'] != '':
search = args['search']
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_instance, err = self._connect(sid, idx)
if err:
return err
total = redis_instance.dbsize()
@@ -251,7 +274,9 @@ class nosqlRedisCtr():
val = args["val"]
endtime = args["endtime"]
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_instance, err = self._connect(sid, idx)
if err:
return err
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
@@ -268,7 +293,9 @@ class nosqlRedisCtr():
sid = args['sid']
idx = args['idx']
name = args["name"]
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_instance, err = self._connect(sid, idx)
if err:
return err
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
@@ -281,7 +308,9 @@ class nosqlRedisCtr():
sid = args['sid']
idx = args['idx']
keys = args["keys"]
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_instance, err = self._connect(sid, idx)
if err:
return err
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
@@ -297,7 +326,9 @@ class nosqlRedisCtr():
idxs = args['idxs']
for idx in idxs:
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_instance, err = self._connect(sid, idx)
if err:
return err
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':

View File

@@ -23,12 +23,15 @@ def singleton(cls):
@singleton
class nosqlMySQL():
__sid = None
__DB_PASS = None
__DB_USER = None
__DB_PORT = 3306
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_STATUS = None
__DB_SOCKET = None
__DB_LOCAL = None
@@ -37,9 +40,25 @@ class nosqlMySQL():
pass
def setSid(self, sid):
self.__sid = sid
self.__config = self.get_options(sid=sid)
def conn(self):
if self.__sid is None:
self.__DB_STATUS = 'not_installed'
return False
if self.__sid is not None:
mycnf_path = "{}/{}/etc/my.cnf".format(mw.getServerDir(),self.__sid)
if not os.path.exists(mycnf_path):
self.__DB_STATUS = 'not_installed'
return False
if not self.__config:
self.__DB_STATUS = 'not_installed'
return False
self.__DB_PORT = int(self.__config['port'])
self.__DB_USER = self.__config['username']
self.__DB_PASS = self.__config['password']
@@ -53,11 +72,19 @@ class nosqlMySQL():
if self.__DB_SOCKET != '':
db.setSocket(self.__DB_SOCKET)
# 实际连通性检查:服务未启动或账号错误时返回 False,调用方统一提示
db.query('select 1')
self.__DB_STATUS = None
return db
except Exception:
self.__DB_ERR = mw.get_error_info()
self.__DB_ERR = mw.getTracebackInfo()
self.__DB_STATUS = 'not_running'
return False
# 连接状态:not_installed 未安装 / not_running 未启动 / None 正常
def get_status(self):
return self.__DB_STATUS
def sqliteDb(self, db_pos_name, dbname='databases'):
mydb_path = mw.getServerDir() +'/'+db_pos_name
name = 'mysql'
@@ -72,8 +99,10 @@ class nosqlMySQL():
result['host'] = '127.0.0.1'
result['username'] = 'root'
if sid in ['mysql', 'mysql-apt', 'mysql-yum']:
if sid in ['mysql', 'mysql-apt', 'mysql-yum', 'mysql-community','mariadb']:
my_cnf_path = "{}/{}/etc/my.cnf".format(mw.getServerDir(),sid)
if not os.path.exists(my_cnf_path):
return False
mydb_content = mw.readFile(my_cnf_path)
if not mydb_content: return False
@@ -118,6 +147,14 @@ class nosqlMySQL():
local_mysql_yum = "{}/mysql-yum/etc/my.cnf".format(mw.getServerDir())
if os.path.exists(local_mysql_yum):
data.append({'name':'本地服务器[yum]', 'val':'mysql-yum'})
local_mysql_yum = "{}/mysql-community/etc/my.cnf".format(mw.getServerDir())
if os.path.exists(local_mysql_yum):
data.append({'name':'本地服务器[Tar]', 'val':'mysql-community'})
local_mysql_yum = "{}/mariadb/etc/my.cnf".format(mw.getServerDir())
if os.path.exists(local_mysql_yum):
data.append({'name':'本地服务器[mariadb]', 'val':'mariadb'})
return mw.returnData(True, 'ok', data)
@singleton
@@ -135,11 +172,20 @@ class nosqlMySQLCtr():
instance.setSid(sid)
return instance
def _connect(self, sid):
obj = self.getInstanceBySid(sid)
conn = obj.conn()
if conn is False:
if obj.get_status() == 'not_installed':
return None, mw.returnData(False, '未安装')
return None, mw.returnData(False, '未启动')
return conn, None
def getDbList(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
result = {}
db_list = my_instance.query('show databases')
@@ -154,9 +200,9 @@ class nosqlMySQLCtr():
sid = args['sid']
db = args['db']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
sql = "select * from information_schema.tables where table_schema = '"+db+"'"
table_list = my_instance.query(sql)
@@ -208,9 +254,9 @@ class nosqlMySQLCtr():
else:
where_sql = ' where '+args_where['field'] + " like '%"+args_where['value']+"%' "
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
my_instance.setDbName(db)
sql = 'select count(*) as num from ' + table + where_sql
@@ -250,9 +296,9 @@ class nosqlMySQLCtr():
sql = 'show processlist';
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
result = my_instance.query(sql)
rdata = {}
@@ -263,9 +309,9 @@ class nosqlMySQLCtr():
sql = 'show status';
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
result = my_instance.query(sql)
rdata = {}
@@ -276,9 +322,9 @@ class nosqlMySQLCtr():
sql = "show status like 'Com_%'";
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
result = my_instance.query(sql)
rdata = {}
@@ -313,9 +359,9 @@ class nosqlMySQLCtr():
def getNetList(self, args):
from datetime import datetime
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
rdata = []
row = {}
@@ -351,9 +397,9 @@ class nosqlMySQLCtr():
def getTopnList(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
is_performance_schema = my_instance.find("SELECT @@performance_schema")
if is_performance_schema is None:
@@ -381,9 +427,9 @@ class nosqlMySQLCtr():
# 查看重复或冗余的索引
def getRedundantIndexes(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
is_performance_schema = my_instance.find("SELECT @@performance_schema")
if is_performance_schema["@@performance_schema"] == 0:
@@ -399,9 +445,9 @@ class nosqlMySQLCtr():
def redundantIndexesCmd(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
is_performance_schema = my_instance.find("SELECT @@performance_schema")
if is_performance_schema["@@performance_schema"] == 0:
@@ -424,29 +470,53 @@ class nosqlMySQLCtr():
from decimal import Decimal
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
my_instance.execute("SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''))")
# ANY_VALUE 是 MySQL 5.7+ 的函数,MariaDB 不支持(报 FUNCTION ANY_VALUE does not exist);
# 上面已去掉 ONLY_FULL_GROUP_BY,MariaDB 可直接取非聚合字段
ver = my_instance.find("SELECT @@version as db_version")
is_mariadb = ver is not None and 'MariaDB' in str(ver.get('db_version', ''))
def any_val(expr):
return expr if is_mariadb else 'ANY_VALUE(' + expr + ')'
data = my_instance.query(
"""
SELECT t.TABLE_SCHEMA as TABLE_SCHEMA, t.TABLE_NAME as TABLE_NAME, t.ENGINE as ENGINE,
IFNULL(t.DATA_LENGTH/1024/1024/1024, 0) as DATA_LENGTH,
IFNULL(t.INDEX_LENGTH/1024/1024/1024, 0) as INDEX_LENGTH,
IFNULL((DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024, 0) AS TOTAL_LENGTH,
c.column_name AS COLUMN_NAME, c.data_type AS DATA_TYPE, c.COLUMN_TYPE AS COLUMN_TYPE,
t.AUTO_INCREMENT AS AUTO_INCREMENT, locate('unsigned', c.COLUMN_TYPE) = 0 AS IS_SIGNED
FROM information_schema.TABLES t
JOIN information_schema.COLUMNS c ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.table_name=c.table_name
WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
GROUP BY TABLE_NAME
ORDER BY TOTAL_LENGTH DESC, AUTO_INCREMENT DESC;
"""
SELECT t.TABLE_SCHEMA as TABLE_SCHEMA, t.TABLE_NAME as TABLE_NAME,
{engine} as ENGINE,
{data_length} as DATA_LENGTH,
{index_length} as INDEX_LENGTH,
{total_length} AS TOTAL_LENGTH,
{column_name} AS COLUMN_NAME, {data_type} AS DATA_TYPE,
{column_type} AS COLUMN_TYPE,
{auto_increment} AS AUTO_INCREMENT,
{is_signed} AS IS_SIGNED
FROM information_schema.TABLES t
JOIN information_schema.COLUMNS c ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.table_name=c.table_name
WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
GROUP BY t.TABLE_SCHEMA, t.TABLE_NAME
ORDER BY TOTAL_LENGTH DESC, AUTO_INCREMENT DESC
""".format(
engine=any_val("t.ENGINE"),
data_length=any_val("IFNULL(t.DATA_LENGTH/1024/1024/1024, 0)"),
index_length=any_val("IFNULL(t.INDEX_LENGTH/1024/1024/1024, 0)"),
total_length=any_val("IFNULL((t.DATA_LENGTH+t.INDEX_LENGTH)/1024/1024/1024, 0)"),
column_name=any_val("c.column_name"),
data_type=any_val("c.data_type"),
column_type=any_val("c.COLUMN_TYPE"),
auto_increment=any_val("t.AUTO_INCREMENT"),
is_signed=any_val("locate('unsigned', c.COLUMN_TYPE) = 0"),
)
)
if data is None:
return mw.returnData(True, 'ok', [])
if isinstance(data, Exception):
return mw.returnData(False, '查询失败: ' + str(data))
for i in range(len(data)):
row = data[i]
@@ -497,9 +567,9 @@ class nosqlMySQLCtr():
# 查看应用端IP连接数总和
def getConnCount(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
data = my_instance.query(
"SELECT user,db,substring_index(HOST,':',1) AS Client_IP,count(1) AS count FROM information_schema.PROCESSLIST "
@@ -521,9 +591,9 @@ class nosqlMySQLCtr():
# 快速找出没有主键的表
def getFpkInfo(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
data = my_instance.query(
"""
@@ -543,9 +613,9 @@ class nosqlMySQLCtr():
def getLockSql(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
data = my_instance.query(
"""
@@ -574,9 +644,9 @@ class nosqlMySQLCtr():
def killLockPid(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
pid = args['pid']
my_instance.execute('kill %s' % pid)
@@ -584,9 +654,9 @@ class nosqlMySQLCtr():
def killAllLock(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
data = self.getLockSql(args)
if data['status']:
@@ -601,9 +671,9 @@ class nosqlMySQLCtr():
def getDeadlockInfo(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
data = my_instance.find("SHOW ENGINE INNODB STATUS")
if data is not None:
@@ -616,29 +686,45 @@ class nosqlMySQLCtr():
def getSlaveStatus(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance, err = self._connect(sid)
if err:
return err
slave_info = my_instance.find('SHOW SLAVE STATUS')
if slave_info is None:
# MySQL 8.0.22+ 使用 SHOW REPLICA STATUS,MySQL 9.0 已移除 SHOW SLAVE STATUS
slave_data = my_instance.query('SHOW REPLICA STATUS')
if isinstance(slave_data, Exception):
# 兼容 MySQL 8.0.22 以下及旧版 MariaDB
slave_data = my_instance.query('SHOW SLAVE STATUS')
if isinstance(slave_data, Exception):
return mw.returnData(False, '获取主从状态失败: ' + str(slave_data))
if slave_data is None or len(slave_data) == 0:
return mw.returnData(True, 'ok', '未开启从库!')
slave_info = slave_data[0]
# 兼容新旧字段名: MySQL 8.0.22+ 将 Slave_*/Seconds_Behind_Master 重命名为 Replica_*/Seconds_Behind_Source
io_running = slave_info.get('Replica_IO_Running', slave_info.get('Slave_IO_Running'))
sql_running = slave_info.get('Replica_SQL_Running', slave_info.get('Slave_SQL_Running'))
seconds_behind = slave_info.get('Seconds_Behind_Source', slave_info.get('Seconds_Behind_Master'))
msg = ''
if slave_info['Auto_Position'] != 1:
if slave_info.get('Auto_Position') != 1:
msg += '你没有开启基于GTID全局事务ID复制,请确保CHANGE MASTER TO MASTER_AUTO_POSITION = 1.\n'
if slave_info['Slave_IO_Running'] == 'Yes' and slave_info['Slave_SQL_Running'] == 'Yes':
if slave_info['Seconds_Behind_Master'] == 0:
if io_running == 'Yes' and sql_running == 'Yes':
if seconds_behind == 0:
msg = "同步正常,无延迟"
return mw.returnData(True, 'ok', msg)
else:
return mw.returnData(True, 'ok', '同步正常,但有延迟,延迟时间为:%s' % slave_info['Seconds_Behind_Master'])
return mw.returnData(True, 'ok', '同步正常,但有延迟,延迟时间为:%s' % seconds_behind)
else:
msg = '主从复制报错,请检查\nSlave_IO_Running状态值是:%s, | Slave_SQL_Running状态值是:%s\nLast_Error错误信息是:%s\nLast_SQL_Error错误信息是:%s\n' \
% (slave_info['Slave_IO_Running'], slave_info['Slave_SQL_Running'], slave_info['Last_Error'], slave_info['Last_SQL_Error'])
error_dict = my_instance.find('select LAST_ERROR_NUMBER,LAST_ERROR_MESSAGE,LAST_ERROR_TIMESTAMP from performance_schema.replication_applier_status_by_worker ORDER BY LAST_ERROR_TIMESTAMP desc limit 1')
% (io_running, sql_running, slave_info.get('Last_Error'), slave_info.get('Last_SQL_Error'))
error_data = my_instance.query('select LAST_ERROR_NUMBER,LAST_ERROR_MESSAGE,LAST_ERROR_TIMESTAMP from performance_schema.replication_applier_status_by_worker ORDER BY LAST_ERROR_TIMESTAMP desc limit 1')
if isinstance(error_data, Exception) or not error_data:
msg += 'MySQL Replication Health is NOT OK!'
return mw.returnData(True, 'ok', msg)
error_dict = error_data[0]
msg += '错误号是:%s \n' % error_dict['LAST_ERROR_NUMBER']
msg += '错误信息是:%s \n' % error_dict['LAST_ERROR_MESSAGE']
msg += '报错时间是:%s \n' % error_dict['LAST_ERROR_TIMESTAMP']

View File

@@ -0,0 +1,825 @@
# coding:utf-8
import sys
import os
import re
import json
import time
import psycopg2
import psycopg2.extras
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
PG_SYSTEM_SCHEMAS = ('pg_catalog', 'information_schema', 'pg_toast')
def getPluginName():
return 'postgresql'
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getConf():
return getServerDir() + '/data/postgresql.conf'
def isInstalled():
return os.path.exists(getConf())
def getPort():
content = mw.readFile(getConf())
if content:
tmp = re.search(r'^[#\s]*port\s*=\s*(\d+)', content, re.M)
if tmp:
return int(tmp.groups()[0])
return 5432
def getSocketDir():
sock_name = '.s.PGSQL.' + str(getPort())
for sock_dir in ['/tmp', getServerDir()]:
if os.path.exists(sock_dir + '/' + sock_name):
return sock_dir
return ''
def quoteIdent(name):
return '"' + str(name).replace('"', '""') + '"'
def quoteTable(name):
return '.'.join(quoteIdent(x) for x in str(name).split('.'))
def fmtValue(value):
if value is None:
return None
if isinstance(value, (dict, list, tuple)):
return json.dumps(value, ensure_ascii=False, default=str)
if isinstance(value, (bytes, bytearray, memoryview)):
return bytes(value).hex()
if isinstance(value, (int, float, str, bool)):
return value
return str(value)
def fmtRows(rows):
ret = []
for row in rows:
item = {}
for k in row:
item[k] = fmtValue(row[k])
ret.append(item)
return ret
class PgClient:
def __init__(self, database='postgres'):
self.database = database
self.status = None
self.error = None
self.conn = None
def connect(self):
if not isInstalled():
self.status = 'not_installed'
return False
try:
host = getSocketDir()
if host == '':
host = '127.0.0.1'
self.conn = psycopg2.connect(database=self.database,
user='postgres',
host=host,
port=getPort(),
connect_timeout=3)
self.conn.autocommit = True
return True
except psycopg2.OperationalError as e:
msg = str(e).strip()
if 'does not exist' in msg:
self.status = 'db_not_found'
elif 'authentication' in msg or 'password' in msg:
self.status = 'auth_error'
else:
self.status = 'not_running'
self.error = msg
except Exception as e:
self.status = 'not_running'
self.error = str(e)
return False
def query(self, sql, params=()):
cur = self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
try:
# 无参数时不能传空 tuple,否则 SQL 里的 % 会被当作占位符
if params:
cur.execute(sql, params)
else:
cur.execute(sql)
rows = cur.fetchall()
return [dict(x) for x in rows]
finally:
cur.close()
def one(self, sql, params=()):
rows = self.query(sql, params)
if len(rows) == 0:
return None
return rows[0]
def execute(self, sql, params=()):
cur = self.conn.cursor()
try:
if params:
cur.execute(sql, params)
else:
cur.execute(sql)
return cur.rowcount
finally:
cur.close()
def close(self):
if self.conn:
self.conn.close()
self.conn = None
def openClient(args, database='postgres'):
client = PgClient(database)
if client.connect():
return client, None
if client.status == 'not_installed':
msg = '未安装'
elif client.status == 'not_running':
msg = '未启动'
elif client.status == 'db_not_found':
msg = '数据库不存在'
elif client.status == 'auth_error':
msg = '连接失败,请检查数据库认证配置'
else:
msg = client.error or '连接失败'
return None, mw.returnData(False, msg)
# 服务器列表
def get_server_list(args):
data = []
if isInstalled():
data.append({'name': '本地服务器', 'val': 'postgresql'})
return mw.returnData(True, 'ok', data)
# 数据库列表
def get_db_list(args):
client, err = openClient(args)
if err:
return err
try:
rows = client.query("select datname from pg_database where datistemplate = false order by datname")
result = {'list': [x['datname'] for x in rows]}
return mw.returnData(True, 'ok', result)
finally:
client.close()
# 数据表列表
def get_table_list(args):
db = args.get('db', '')
client, err = openClient(args, db)
if err:
return err
try:
sql = """
select n.nspname as schemaname, c.relname as tablename
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where c.relkind in ('r', 'p', 'v', 'm', 'f')
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
and n.nspname not like 'pg_temp%'
order by n.nspname, c.relname
"""
rows = client.query(sql)
table_list = []
for x in rows:
if x['schemaname'] == 'public':
table_list.append(x['tablename'])
else:
table_list.append(x['schemaname'] + '.' + x['tablename'])
result = {'list': table_list}
return mw.returnData(True, 'ok', result)
finally:
client.close()
# 数据列表
def get_data_list(args):
db = args.get('db', '')
table = args.get('table', '')
p = 1
size = 10
if 'p' in args:
p = int(args['p'])
if 'size' in args:
size = int(args['size'])
start_index = (p - 1) * size
if table == '':
page_args = {}
page_args['count'] = 0
page_args['tojs'] = 'pgGetDataList'
page_args['p'] = 1
page_args['row'] = size
rdata = {}
rdata['page'] = mw.getPage(page_args)
rdata['list'] = []
rdata['count'] = 0
return mw.returnData(True, 'ok', rdata)
where_sql = ''
where_params = []
args_where = {}
if 'where' in args and isinstance(args['where'], dict):
args_where = args['where']
field = args_where.get('field', '')
if field and field != '0':
field_sql = quoteIdent(field)
value = str(args_where.get('value', ''))
if 'id' in field.lower():
where_sql = ' where ' + field_sql + ' = %s'
where_params.append(value)
else:
where_sql = ' where ' + field_sql + ' like %s'
where_params.append('%' + value + '%')
client, err = openClient(args, db)
if err:
return err
try:
try:
sql = 'select count(*) as num from ' + quoteTable(table) + where_sql
count_row = client.one(sql, tuple(where_params))
count = int(count_row['num'])
sql = 'select * from ' + quoteTable(table) + where_sql + ' limit %s offset %s'
params = tuple(where_params) + (size, start_index)
rows = client.query(sql, params)
rows = fmtRows(rows)
except psycopg2.errors.UndefinedTable:
return mw.returnData(False, '数据表不存在:' + table)
except psycopg2.errors.UndefinedColumn:
return mw.returnData(False, '字段不存在,请刷新后重试')
except psycopg2.Error as e:
return mw.returnData(False, '查询失败:' + str(e).strip())
page_args = {}
page_args['count'] = count
page_args['tojs'] = 'pgGetDataList'
page_args['p'] = p
page_args['row'] = size
rdata = {}
rdata['page'] = mw.getPage(page_args)
rdata['list'] = rows
rdata['count'] = count
rdata['soso_field'] = ''
if field and field != '0':
rdata['soso_field'] = field
return mw.returnData(True, 'ok', rdata)
finally:
client.close()
# 进程列表
def get_proccess_list(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select pid, usename as "user", datname as db,
coalesce(host(client_addr), '本地') as host,
application_name as command, state, query as info,
backend_start, xact_start, query_start,
wait_event_type, wait_event
from pg_stat_activity
where pid <> pg_backend_pid()
and backend_type = 'client backend'
order by pid
"""
rows = fmtRows(client.query(sql))
result = {'list': rows}
return mw.returnData(True, 'ok', result)
finally:
client.close()
# 状态列表
def get_status_list(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select name, setting, coalesce(unit, '') as unit,
category, short_desc
from pg_settings
order by name
"""
rows = fmtRows(client.query(sql))
result = {'list': rows}
return mw.returnData(True, 'ok', result)
finally:
client.close()
# 统计列表
def get_stats_list(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select datname as db,
numbackends as conn,
xact_commit as commit, xact_rollback as rollback,
blks_read, blks_hit,
tup_returned, tup_fetched, tup_inserted, tup_updated, tup_deleted,
deadlocks, conflicts, temp_files, temp_bytes,
round(100.0 * blks_hit / nullif(blks_hit + blks_read, 0), 2) as cache_hit_ratio
from pg_stat_database
where datname is not null
order by datname
"""
rows = fmtRows(client.query(sql))
result = {'list': rows}
return mw.returnData(True, 'ok', result)
finally:
client.close()
def _dbStatSnapshot(client):
sql = """
select coalesce(sum(tup_fetched), 0) as fetched,
coalesce(sum(tup_inserted), 0) as inserted,
coalesce(sum(tup_updated), 0) as updated,
coalesce(sum(tup_deleted), 0) as deleted,
coalesce(sum(xact_commit), 0) as commits
from pg_stat_database
"""
row = client.one(sql)
return {
'fetched': int(row['fetched']),
'inserted': int(row['inserted']),
'updated': int(row['updated']),
'deleted': int(row['deleted']),
'commits': int(row['commits']),
}
# QPS/TPS 指标
def get_net_list(args):
from datetime import datetime
client, err = openClient(args)
if err:
return err
try:
row1 = _dbStatSnapshot(client)
time.sleep(1)
row2 = _dbStatSnapshot(client)
max_conn = client.one("select setting from pg_settings where name = 'max_connections'")
conn_row = client.one("select count(*) as num from pg_stat_activity where backend_type = 'client backend'")
row = {}
row['current_time'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
row['select'] = row2['fetched'] - row1['fetched']
row['insert'] = row2['inserted'] - row1['inserted']
row['update'] = row2['updated'] - row1['updated']
row['delete'] = row2['deleted'] - row1['deleted']
row['conn'] = conn_row['num']
row['max_conn'] = max_conn['setting']
# PostgreSQL 的 pg_stat 不提供网络字节计数器
row['recv_mbps'] = '-'
row['send_mbps'] = '-'
rdata = []
rdata.append(row)
return mw.returnData(True, 'ok', rdata)
finally:
client.close()
# 查询执行次数最频繁的前N条SQL语句
def get_topn_list(args):
client, err = openClient(args)
if err:
return err
try:
avail = client.one("""
select default_version, installed_version
from pg_available_extensions
where name = 'pg_stat_statements'
""")
if avail is None:
return mw.returnData(False, '当前 PostgreSQL 未提供 pg_stat_statements 扩展(缺少 contrib 模块),无法使用该功能。')
# 先检查 shared_preload_libraries —— pg_stat_statements 必须预加载
preload = client.one("select setting from pg_settings where name = 'shared_preload_libraries'")
libs = (preload or {}).get('setting', '') or ''
if 'pg_stat_statements' not in libs:
return mw.returnData(False, "pg_stat_statements 扩展必须在启动时预加载。\n"
"请在 postgresql.conf 添加 shared_preload_libraries = 'pg_stat_statements' 后重启 PostgreSQL。")
# 再检查扩展是否已 CREATE
ext = client.one("select to_regclass('pg_stat_statements') as v")
if ext is None or ext['v'] is None:
return mw.returnData(False, "pg_stat_statements 扩展已预加载,但尚未启用。\n"
"请在当前数据库执行 CREATE EXTENSION pg_stat_statements;")
version_num = int(client.one('show server_version_num')['server_version_num'])
if version_num >= 130000:
total_col = 'total_exec_time'
max_col = 'max_exec_time'
mean_col = 'mean_exec_time'
else:
total_col = 'total_time'
max_col = 'max_time'
mean_col = 'mean_time'
sql = """
select s.query,
coalesce(d.datname, '-') as db,
'-' as last_seen,
s.calls as exec_count,
round(s.{max_col}::numeric, 2) as max_latency,
round(s.{mean_col}::numeric, 2) as avg_latency
from pg_stat_statements s
left join pg_database d on d.oid = s.dbid
""".format(max_col=max_col, mean_col=mean_col)
filter_db = args.get('filter_db', 'no')
if filter_db == 'yes':
sql += ' where d.datname is not null '
sql += ' order by s.calls desc limit 20'
rows = fmtRows(client.query(sql))
return mw.returnData(True, 'ok', rows)
finally:
client.close()
def _redundantIndexes(client):
sql = """
select n.nspname as table_schema,
t.relname as table_name,
ic.relname as redundant_index_name,
coalesce((
select string_agg(a.attname, ',' order by k.ord)
from unnest(i.indkey) with ordinality as k(attnum, ord)
join pg_attribute a on a.attrelid = i.indrelid and a.attnum = k.attnum
), '') as redundant_index_columns,
'DROP INDEX ' || quote_ident(n.nspname) || '.' || quote_ident(ic.relname) as sql_drop_index
from pg_index i
join pg_class t on t.oid = i.indrelid
join pg_namespace n on n.oid = t.relnamespace
join pg_class ic on ic.oid = i.indexrelid
where n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
and not exists (
select 1 from pg_constraint con where con.conindid = i.indexrelid
)
and exists (
select 1
from pg_index i2
join pg_class ic2 on ic2.oid = i2.indexrelid
where i2.indrelid = i.indrelid
and i2.indkey = i.indkey
and i2.indclass = i.indclass
and i2.indcollation = i.indcollation
and i2.indpred is not distinct from i.indpred
and i2.indexprs is not distinct from i.indexprs
and i2.indexrelid <> i.indexrelid
and ic2.relname < ic.relname
)
order by 1, 2, 3
"""
return fmtRows(client.query(sql))
# 查看重复或冗余的索引
def get_redundant_indexes(args):
client, err = openClient(args)
if err:
return err
try:
rows = _redundantIndexes(client)
return mw.returnData(True, 'ok', rows)
finally:
client.close()
# 删除重复或冗余的索引
def redundant_indexes_cmd(args):
client, err = openClient(args)
if err:
return err
try:
rows = _redundantIndexes(client)
index = int(args['index'])
if index >= len(rows):
return mw.returnData(False, '索引不存在,请刷新后重试')
client.execute(rows[index]['sql_drop_index'])
return mw.returnData(True, '执行成功!')
finally:
client.close()
# 统计库里每个表的大小
def get_table_info(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select n.nspname as "TABLE_SCHEMA",
c.relname as "TABLE_NAME",
case c.relkind
when 'r' then 'table'
when 'p' then 'partitioned table'
when 'v' then 'view'
when 'm' then 'materialized view'
else c.relkind::text
end as "ENGINE",
c.reltuples as rows_estimate,
pg_relation_size(c.oid) as data_bytes,
pg_indexes_size(c.oid) as index_bytes,
pg_total_relation_size(c.oid) as total_bytes,
coalesce((
select string_agg(a.attname, ',' order by k.ord)
from pg_index i
join unnest(i.indkey) with ordinality as k(attnum, ord) on true
join pg_attribute a on a.attrelid = i.indrelid and a.attnum = k.attnum
where i.indrelid = c.oid and i.indisprimary
), '-') as "COLUMN_NAME",
coalesce((
select string_agg(format_type(a.atttypid, a.atttypmod), ',' order by k.ord)
from pg_index i
join unnest(i.indkey) with ordinality as k(attnum, ord) on true
join pg_attribute a on a.attrelid = i.indrelid and a.attnum = k.attnum
where i.indrelid = c.oid and i.indisprimary
), '-') as "COLUMN_TYPE"
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where c.relkind in ('r', 'p', 'v', 'm')
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
and n.nspname not like 'pg_temp%'
order by total_bytes desc
"""
rows = client.query(sql)
for i in range(len(rows)):
row = rows[i]
row['DATA_LENGTH'] = round(float(row['data_bytes'] or 0) / 1024 / 1024 / 1024, 2)
row['INDEX_LENGTH'] = round(float(row['index_bytes'] or 0) / 1024 / 1024 / 1024, 2)
row['TOTAL_LENGTH'] = round(float(row['total_bytes'] or 0) / 1024 / 1024 / 1024, 2)
# PostgreSQL 没有 AUTO_INCREMENT,使用 SEQUENCE / IDENTITY
row['AUTO_INCREMENT'] = '-'
row['RESIDUAL_AUTO_INCREMENT'] = '使用 SEQUENCE/IDENTITY'
row['ROWS_ESTIMATE'] = int(row['rows_estimate'] or 0)
del row['data_bytes']
del row['index_bytes']
del row['total_bytes']
return mw.returnData(True, 'ok', fmtRows(rows))
finally:
client.close()
# 查看应用端IP连接数总和
def get_conn_count(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select usename as "user",
coalesce(datname, '空') as db,
coalesce(host(client_addr), '本地') as "Client_IP",
count(*) as count
from pg_stat_activity
where backend_type = 'client backend'
group by usename, datname, client_addr
order by count desc
"""
rows = fmtRows(client.query(sql))
return mw.returnData(True, 'ok', rows)
finally:
client.close()
# 快速找出没有主键的表
def get_fpk_info(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select n.nspname as table_schema, c.relname as table_name
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where c.relkind in ('r', 'p')
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')
and not exists (
select 1 from pg_index i
where i.indrelid = c.oid and i.indisprimary
)
order by n.nspname, c.relname
"""
rows = fmtRows(client.query(sql))
return mw.returnData(True, 'ok', rows)
finally:
client.close()
# 查看当前锁阻塞的SQL
def get_lock_sql(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select coalesce(a.backend_xid::text, '-') as trx_id,
'等待锁' as trx_state,
a.xact_start as trx_started,
a.pid as processlist_id,
a.query as info,
a.usename as "user",
coalesce(host(a.client_addr), '本地') as host,
a.datname as db,
coalesce(a.wait_event_type, '-') as command,
a.state,
'SELECT pg_cancel_backend(' || a.pid || ')' as sql_kill_blocking_query,
pg_blocking_pids(a.pid) as blocking_pids
from pg_stat_activity a
where cardinality(pg_blocking_pids(a.pid)) > 0
and a.backend_type = 'client backend'
order by a.xact_start
"""
rows = fmtRows(client.query(sql))
return mw.returnData(True, 'ok', rows)
finally:
client.close()
# 终止阻塞会话
def kill_lock_pid(args):
client, err = openClient(args)
if err:
return err
try:
pid = int(args['pid'])
data = client.one('select pg_terminate_backend(%s) as ok', (pid,))
if data is None or data['ok'] is not True:
return mw.returnData(False, '结束会话失败,请检查会话是否存在')
return mw.returnData(True, '执行成功!')
finally:
client.close()
# 终止所有阻塞会话
def kill_all_lock(args):
client, err = openClient(args)
if err:
return err
try:
sql = """
select distinct unnest(pg_blocking_pids(pid)) as pid
from pg_stat_activity
where cardinality(pg_blocking_pids(pid)) > 0
and backend_type = 'client backend'
"""
rows = client.query(sql)
count = 0
for x in rows:
data = client.one('select pg_terminate_backend(%s) as ok', (x['pid'],))
if data is not None and data['ok'] is True:
count += 1
return mw.returnData(True, '执行成功,已结束 %s 个阻塞会话' % count)
finally:
client.close()
# 查看死锁信息
def get_deadlock_info(args):
client, err = openClient(args)
if err:
return err
try:
deadlocks = client.one('select coalesce(sum(deadlocks), 0) as num from pg_stat_database')
locks = client.query("""
select pid, usename as "user", datname as db, state,
coalesce(wait_event_type, '-') as wait_event_type,
query
from pg_stat_activity
where cardinality(pg_blocking_pids(pid)) > 0
and backend_type = 'client backend'
""")
msg = 'PostgreSQL 不保存历史死锁明细,仅提供累计次数与当前锁等待。\n'
msg += '数据库累计死锁次数:%s\n' % deadlocks['num']
if len(locks) == 0:
msg += '当前没有处于锁等待的会话。'
else:
msg += '当前锁等待会话:\n'
for x in locks:
msg += 'pid=%s user=%s db=%s state=%s wait=%s\nquery=%s\n' % (
x['pid'], x['user'], x['db'], x['state'], x['wait_event_type'], x['query'])
return mw.returnData(True, 'ok', msg)
finally:
client.close()
# 查看主从复制信息
def get_slave_status(args):
client, err = openClient(args)
if err:
return err
try:
recovery = client.one('select pg_is_in_recovery() as recovery')['recovery']
if recovery is False:
reps = client.query("""
select client_addr, application_name, state, sync_state,
sent_lsn, write_lsn, flush_lsn, replay_lsn,
coalesce(replay_lag::text, '-') as replay_lag
from pg_stat_replication
""")
if len(reps) == 0:
return mw.returnData(True, 'ok', '未开启主从复制:当前为主库,且没有复制的从库连接。')
msg = '当前为主库,从库复制状态:\n'
for x in reps:
msg += '从库地址:%s 应用:%s\n' % (x['client_addr'], x['application_name'])
msg += '状态:%s 同步模式:%s\n' % (x['state'], x['sync_state'])
msg += 'sent_lsn=%s write_lsn=%s flush_lsn=%s replay_lsn=%s\n' % (
x['sent_lsn'], x['write_lsn'], x['flush_lsn'], x['replay_lsn'])
msg += 'replay_lag=%s\n\n' % x['replay_lag']
return mw.returnData(True, 'ok', msg)
# 当前为从库
lag = client.one("""
select coalesce(extract(epoch from (now() - pg_last_xact_replay_timestamp()))::int, 0) as lag
""")
lsn = client.one("""
select pg_last_wal_receive_lsn() as receive_lsn,
pg_last_wal_replay_lsn() as replay_lsn,
pg_last_xact_replay_timestamp() as replay_time
""")
msg = '当前为从库,复制状态:\n'
msg += 'receive_lsn=%s\n' % lsn['receive_lsn']
msg += 'replay_lsn=%s\n' % lsn['replay_lsn']
msg += '最近回放时间=%s\n' % lsn['replay_time']
msg += '延迟时间:%s 秒' % lag['lag']
return mw.returnData(True, 'ok', msg)
finally:
client.close()

View File

@@ -45,4 +45,26 @@
right:0; /* 首行永远固定在左侧 */
z-index:1;
background-color:white;
}
.divtable {
overflow: auto;
/*border: 1px solid #ddd;*/
}
.divtable table {
margin-bottom: 0;
}
.divtable table thead th {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.divtable table tbody td {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}

View File

@@ -6,6 +6,7 @@
<div class="tabs-item" data-name="mongodb">Mongodb</div>
<div class="tabs-item" data-name="memcached">Memcached</div>
<div class="tabs-item" data-name="mysql">MySQL</div>
<div class="tabs-item" data-name="postgresql">PostgreSQL</div>
</div>
</div>
@@ -16,6 +17,99 @@
<div class="prompt_description">当前未安装本地服务器,<a class="btlink install_server" href="/soft/index">点击安装</a></div>
</div>
<!-- postgresql start -->
<div class="tab-con hide" id="postgresql" style="padding: 0px;">
<div class="col-md-12" style="padding: 0px;overflow: hidden;">
<div class="tootls_group tootls_top">
<div class="pull-left">
<div class="pgserver_list" style="float:left;">
<select name="sid" class="bt-input-text c5 mr5">
<option value="0">本地服务器</option>
</select>
</div>
<div class="postgresql_db_list" style="float:left;">
<select name="postgresql_db" class="bt-input-text c5 mr5">
<option value="0">数据库空</option>
</select>
</div>
<div class="postgresql_table_list" style="float:left;">
<select name="postgresql_table" class="bt-input-text c5 mr5">
<option value="0">数据表空</option>
</select>
</div>
<div class="field" style="float:left;">
<select name="postgresql_field_key" class="bt-input-text c5 mr5" style="width:80px;">
<option value="0">无字段</option>
</select>
</div>
<div class="value" style="float:left;">
<input name="postgresql_field_value" type="text" class="bt-input-text" placeholder="请输入查找内容">
</div>
<div style="float:left;">
<button id="postgresql_find" type="button" class="btn btn-success btn-sm mr5 ml5" >查找</button>
<button id="postgresql_common" type="button" class="btn btn-success btn-sm mr5 ml5">常用功能</button>
</div>
</div>
</div>
<div style="position: relative;">
<div id="postgresql_table" class="postgresql_table divtable mtb10">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th><span>编号</span></th>
<th><span>操作类型</span></th>
<th><span>详情</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="postgresql_list_page page">
<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>
</div>
</div>
<hr style="border:none;" />
<div class="col-md-12" style="padding-left: 3px;">
<div id="postgresql_list_tab" style="padding-top:0px;">
<div class="tab-nav">
<span data-name="proccess" class="on">进程</span>
<span data-name="status" class="">状态</span>
<span data-name="stats" class="">统计</span>
</div>
</div>
<div style="position: relative;">
<div id="postgresql_ot_table" class="divtable">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th><span>编号</span></th>
<th><span>操作类型</span></th>
<th><span>详情</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- postgresql end -->
<!-- mysql start -->
<!-- show w-full -->
<div class="tab-con hide" id="mysql" style="padding: 0px;">

View File

@@ -143,6 +143,60 @@ function myPostCBN(method, args, callback){
},'json');
}
function pgPostCB(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'data_query';
req_data['func'] = method;
req_data['script']='sql_postgresql';
args['version'] = '';
if (typeof(args) == 'string' && args == ''){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, 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 pgPostCBN(method, args, callback){
var req_data = {};
req_data['name'] = 'data_query';
req_data['func'] = method;
req_data['script']='sql_postgresql';
args['version'] = '';
if (typeof(args) == 'string' && args == ''){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function selectTab(tab = 'redis'){
$('.tab-view-box .tab-con').addClass('hide').removeClass('show').removeClass('w-full');
@@ -163,6 +217,7 @@ function initTabFunc(tab){
case 'mongodb':initTabMongodb();break;
case 'memcached':initTabMemcached();break;
case 'mysql':initTabMySQL();break;
case 'postgresql':initTabPostgresql();break;
case 'default:':initTabRedis();break;
}
}
@@ -237,7 +292,7 @@ function initTabMemcached(){
$('#memcached_clear_all').unbind('click').click(function(){
var sid = memcachedGetSid();
memPostCB('clear',{'sid':sid} ,function(rdata){
// console.log(rdata);
console.log("xxx",rdata);
showMsg(rdata.data.msg,function(){
if (rdata.data.status){
memcachedGetList();
@@ -927,6 +982,7 @@ function mysqlInitField(f, data){
function mysqlGetServerList(call_func){
closeInstallLayer();
myPostCBN('get_server_list', {}, function(rdata){
var rdata = rdata.data;
if (rdata.data.length != 0){
@@ -951,7 +1007,10 @@ function mysqlGetServerList(call_func){
}
closeInstallLayer();
} else {
showInstallLayer();
layer.msg(rdata.data.msg,{ icon: 7, time: 2000, shade: 0.3 });
setTimeout(function(){
showInstallLayer();
},2050);
}
});
}
@@ -1061,7 +1120,7 @@ function mysqlGetDataList(p){
for (var j = 0; j < fields.length; j++) {
var f = fields[j];
if (f in dlist[i]) {
tbody += '<td style="word-wrap:break-word;word-break:break-all;">'+dlist[i][f]+'</td>';
tbody += '<td title="'+dlist[i][f]+'">'+dlist[i][f]+'</td>';
} else {
tbody += '<td>undefined</td>';
}
@@ -1100,7 +1159,7 @@ function mysqlProcessList(){
for (var j = 0; j < fields.length; j++) {
var f = fields[j];
if (f in dlist[i]) {
tbody += '<td>'+dlist[i][f]+'</td>';
tbody += '<td title="'+dlist[i][f]+'">'+dlist[i][f]+'</td>';
} else {
tbody += '<td>undefined</td>';
}
@@ -1137,7 +1196,7 @@ function mysqlStatusList(){
for (var j = 0; j < fields.length; j++) {
var f = fields[j];
if (f in dlist[i]) {
tbody += '<td>'+dlist[i][f]+'</td>';
tbody += '<td title="'+dlist[i][f]+'">'+dlist[i][f]+'</td>';
} else {
tbody += '<td>undefined</td>';
}
@@ -1174,7 +1233,7 @@ function mysqlStatsList(){
for (var j = 0; j < fields.length; j++) {
var f = fields[j];
if (f in dlist[i]) {
tbody += '<td>'+dlist[i][f]+'</td>';
tbody += '<td title="'+dlist[i][f]+'">'+dlist[i][f]+'</td>';
} else {
tbody += '<td>undefined</td>';
}
@@ -1201,9 +1260,9 @@ function memcachedGetItem(){
function memcachedGetList(){
var sid = memcachedGetSid();
closeInstallLayer();
memPostCB('get_items',{'sid':sid} ,function(rdata){
if (rdata.data.status){
var items = rdata.data.data['items'];
var content = '';
for (var i = 0; i < items.length; i++) {
@@ -1219,10 +1278,14 @@ function memcachedGetList(){
memcachedGetKeyList(1);
});
closeInstallLayer();
memcachedGetKeyList(1);
} else {
showInstallLayer();
layer.msg(rdata.data.msg,{ icon: 7, time: 2000, shade: 0.3 });
setTimeout(function(){
showInstallLayer();
},2050);
}
memcachedGetKeyList(1);
});
}
@@ -1386,7 +1449,6 @@ function mongodbInitField(f, data){
var mogodb_db_list;
function mongodbCollectionName(){
// console.log(mogodb_db_list);
var v = mogodb_db_list.getValue('value');
if (v.length == 0){
// console.log($('#mongodb').data('collection'));
@@ -1397,6 +1459,7 @@ function mongodbCollectionName(){
function mongodbGetList(){
var sid = mongodbGetSid();
closeInstallLayer();
mgdbPostCB('get_db_list',{'sid':sid} ,function(rdata){
// console.log(rdata);
if (rdata.data.status){
@@ -1423,7 +1486,11 @@ function mongodbGetList(){
closeInstallLayer();
} else {
showInstallLayer();
layer.msg(rdata.data.msg,{ icon: 7, time: 2000, shade: 0.3 });
setTimeout(function(){
showInstallLayer();
},2050);
}
});
}
@@ -1606,6 +1673,7 @@ function redisGetIdx(){
function redisGetList(){
var sid = redisGetSid();
closeInstallLayer();
redisPostCB('get_list',{'sid':sid} ,function(rdata){
if (rdata.data.status){
var list = rdata.data.data;
@@ -1627,7 +1695,10 @@ function redisGetList(){
redisGetKeyList(1);
closeInstallLayer();
} else {
showInstallLayer();
layer.msg(rdata.data.msg,{ icon: 7, time: 1000, shade: 0.3 });
setTimeout(function(){
showInstallLayer();
},1050);
}
});
}
@@ -1936,3 +2007,663 @@ function redisBatchClear(){
}
// ------------------------- redis end ---------------------------------
// ------------------------- postgresql start -------------------------------
var pg_timer = null;
var pg_last_error = '';
function pgToastError(msg){
// 轮询失败时避免每 2 秒重复弹出相同的提示
if (!msg || pg_last_error == msg){
return;
}
pg_last_error = msg;
layer.msg(msg,{icon:7,time:2500});
}
function pgHtml(v){
if (v === null || v === undefined){
return '';
}
return String(v).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}
function pgGetSid(){
return $('#postgresql select[name=sid]').val();
}
function pgGetDbName(){
return $('#postgresql .postgresql_db_list select[name=postgresql_db]').val();
}
function pgGetTableName(){
var table = $('#postgresql .postgresql_table_list select[name=postgresql_table]').val();
if (!table || table == '0'){
return '';
}
return table;
}
function pgShowNotice(title, msg){
layer.open({
type: 1,
title: title,
area: ['560px', '260px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20"><pre style="white-space:pre-wrap;word-break:break-all;margin:0;line-height:1.8;">'+pgHtml(msg)+'</pre></div>'
});
}
function pgModalTable(title, list, width, height){
if (!list || list.length == 0){
layer.msg('暂无数据',{icon:7});
return;
}
var fields = mongodbGetDataFields(list);
var thead = '';
for (var i = 0; i < fields.length; i++){
thead += '<th>'+pgHtml(fields[i])+'</th>';
}
var tbody = '';
for (var i = 0; i < list.length; i++){
tbody += '<tr>';
for (var j = 0; j < fields.length; j++){
var f = fields[j];
var val = (f in list[i]) ? list[i][f] : '';
tbody += '<td title="'+pgHtml(val)+'">'+pgHtml(val)+'</td>';
}
tbody += '</tr>';
}
layer.open({
type: 1,
title: title,
area: [width || '900px', height || '420px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20 divtable taskdivtable" style="height:'+(parseInt(height || '420') - 80)+'px;overflow:auto;">\
<table class="table table-hover">\
<thead><tr>'+thead+'</tr></thead>\
<tbody>'+tbody+'</tbody>\
</table>\
</div>'
});
}
function pgInitField(f, data){
var option_html = '<option value="0">无字段</option>';
for (var i = 0; i < f.length; i++){
if (data['soso_field'] == f[i]){
option_html += '<option value="'+pgHtml(f[i])+'" selected>'+pgHtml(f[i])+'</option>';
} else {
option_html += '<option value="'+pgHtml(f[i])+'">'+pgHtml(f[i])+'</option>';
}
}
$('#postgresql select[name="postgresql_field_key"]').html(option_html);
}
function initTabPostgresql(){
clearInterval(pg_timer);
pg_last_error = '';
pgGetServerList(function(){
pgGetDbList();
pgProcessList();
clearInterval(pg_timer);
pg_timer = setInterval(function(){
var name = $('#postgresql_list_tab .tab-nav span.on').data('name');
pgRunPgTab(name);
var fname = $('#cutTab .tabs-item.active').data('name');
if (fname != 'postgresql'){
clearInterval(pg_timer);
}
}, 2000);
});
$('#postgresql_list_tab .tab-nav span').unbind('click').click(function(){
$('#postgresql_list_tab .tab-nav span').removeClass('on');
$(this).addClass('on');
var name = $(this).data('name');
pgRunPgTab(name);
});
$('#postgresql_find').unbind('click').click(function(){
var val = $('#postgresql input[name="postgresql_field_value"]').val();
if (val == ''){
layer.msg('搜索不能为空!',{icon:7});
return;
}
pgGetDataList(1);
});
pgCommonFunc();
}
function pgRunPgTab(name){
switch(name){
case 'proccess':pgProcessList();break;
case 'status':pgStatusList();break;
case 'stats':pgStatsList();break;
}
}
function pgGetServerList(call_func){
closeInstallLayer();
pgPostCBN('get_server_list', {}, function(rdata){
var data = rdata.data;
if (data.data && data.data.length != 0){
var items = data.data;
var content = '';
for (var i = 0; i < items.length; i++){
var t = items[i];
if (i == 0){
content += '<option value="'+t['val']+'" selected>'+t['name']+'</option>';
} else {
content += '<option value="'+t['val']+'">'+t['name']+'</option>';
}
}
$('#postgresql select[name=sid]').html(content);
$('#postgresql select[name=sid]').change(function(){
pgGetDbList();
});
if (typeof(call_func) == 'function'){
call_func();
}
closeInstallLayer();
} else {
layer.msg('当前未安装 PostgreSQL',{icon:7,time:2000,shade:0.3});
setTimeout(function(){
showInstallLayer();
},2050);
}
});
}
function pgGetDbList(){
var sid = pgGetSid();
pgPostCBN('get_db_list',{'sid':sid}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
var items = data.data['list'];
if (items.length == 0){
$('#postgresql .postgresql_db_list select[name=postgresql_db]').html('<option value="0">数据库空</option>');
$('#postgresql .postgresql_table_list select[name=postgresql_table]').html('<option value="0">数据表空</option>');
$('#postgresql_table thead tr').html('');
$('#postgresql_table tbody').html('');
$('.postgresql_list_page').html('<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>');
return;
}
var content = '';
for (var i = 0; i < items.length; i++){
var name = items[i];
if (i == 0){
content += '<option value="'+pgHtml(name)+'" selected>database['+pgHtml(name)+']</option>';
} else {
content += '<option value="'+pgHtml(name)+'">database['+pgHtml(name)+']</option>';
}
}
$('#postgresql .postgresql_db_list select[name=postgresql_db]').html(content);
$('#postgresql .postgresql_db_list select[name=postgresql_db]').change(function(){
pgGetTableList(1);
});
pgGetTableList(1);
});
}
function pgGetTableList(p){
var sid = pgGetSid();
var db = pgGetDbName();
if (!db || db == '0'){
return;
}
pgPostCBN('get_table_list',{'sid':sid,'db':db}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
var items = data.data['list'];
if (items.length == 0){
$('#postgresql .postgresql_table_list select[name=postgresql_table]').html('<option value="0">数据表空</option>');
$('#postgresql_table thead tr').html('');
$('#postgresql_table tbody').html('');
$('.postgresql_list_page').html('<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>');
return;
}
var content = '';
for (var i = 0; i < items.length; i++){
var name = items[i];
if (i == 0){
content += '<option value="'+pgHtml(name)+'" selected>table['+pgHtml(name)+']</option>';
} else {
content += '<option value="'+pgHtml(name)+'">table['+pgHtml(name)+']</option>';
}
}
$('#postgresql .postgresql_table_list select[name=postgresql_table]').html(content);
$('#postgresql .postgresql_table_list select[name=postgresql_table]').change(function(){
pgGetDataList(1);
});
pgGetDataList(1);
});
}
function pgGetDataList(p){
var sid = pgGetSid();
var db = pgGetDbName();
var table = pgGetTableName();
var pg_field = $('#postgresql select[name="postgresql_field_key"]').val();
var pg_value = $('#postgresql input[name="postgresql_field_value"]').val();
var request_data = {
'sid': sid,
'db': db,
'table': table,
'p': p,
'size': 10
};
if (pg_field != '0' && pg_field){
request_data['where'] = {field: pg_field, value: pg_value};
} else {
request_data['where'] = {};
}
pgPostCB('get_data_list', request_data, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
var rdata2 = data.data;
var dlist = rdata2['list'];
var fields = mongodbGetDataFields(dlist);
if (fields.length != 0){
pgInitField(fields, rdata2);
}
var header_field = '';
for (var i = 0; i < fields.length; i++){
header_field += '<th>'+pgHtml(fields[i])+'</th>';
}
$('#postgresql_table thead tr').html(header_field);
var tbody = '';
for (var i = 0; i < dlist.length; i++){
tbody += '<tr>';
for (var j = 0; j < fields.length; j++){
var f = fields[j];
var val = (f in dlist[i]) ? dlist[i][f] : '';
tbody += '<td title="'+pgHtml(val)+'">'+pgHtml(val)+'</td>';
}
tbody += '</tr>';
}
$('#postgresql_table tbody').html(tbody);
$('#postgresql .postgresql_list_page').html(rdata2['page']);
});
}
function pgRenderOtTable(dlist){
var fields = mongodbGetDataFields(dlist);
var header_field = '';
for (var i = 0; i < fields.length; i++){
header_field += '<th>'+pgHtml(fields[i])+'</th>';
}
$('#postgresql_ot_table thead tr').html(header_field);
var tbody = '';
for (var i = 0; i < dlist.length; i++){
tbody += '<tr>';
for (var j = 0; j < fields.length; j++){
var f = fields[j];
var val = (f in dlist[i]) ? dlist[i][f] : '';
tbody += '<td title="'+pgHtml(val)+'">'+pgHtml(val)+'</td>';
}
tbody += '</tr>';
}
$('#postgresql_ot_table tbody').html(tbody);
}
function pgProcessList(){
pgPostCBN('get_proccess_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgToastError(data.msg);
return;
}
pg_last_error = '';
pgRenderOtTable(data.data['list']);
});
}
function pgStatusList(){
pgPostCBN('get_status_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgToastError(data.msg);
return;
}
pg_last_error = '';
pgRenderOtTable(data.data['list']);
});
}
function pgStatsList(){
pgPostCBN('get_stats_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgToastError(data.msg);
return;
}
pg_last_error = '';
pgRenderOtTable(data.data['list']);
});
}
function pgCommonFunc(){
$('#postgresql_common').unbind('click').click(function(){
layer.open({
type: 1,
title: "PostgreSQL常用功能",
area: ['600px', '200px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20">\
<button style="margin-bottom: 8px;" id="pg_top_nsql" type="button" class="btn btn-default btn-sm">查询执行次数最频繁的前N条SQL语句</button>\
<button style="margin-bottom: 8px;" id="pg_net_stat" type="button" class="btn btn-default btn-sm">PostgreSQL服务器的QPS/TPS指标</button>\
<button style="margin-bottom: 8px;" id="pg_redundant_indexes" type="button" class="btn btn-default btn-sm">查看重复或冗余的索引</button>\
<button style="margin-bottom: 8px;" id="pg_table_info" type="button" class="btn btn-default btn-sm">统计库里每个表的大小</button>\
<button style="margin-bottom: 8px;" id="pg_conn_count" type="button" class="btn btn-default btn-sm">查看应用端IP连接数总和</button>\
<button style="margin-bottom: 8px;" id="pg_fpk_info" type="button" class="btn btn-default btn-sm">快速找出没有主键的表</button>\
<button style="margin-bottom: 8px;" id="pg_lock_sql" type="button" class="btn btn-default btn-sm">查看当前锁阻塞的SQL</button>\
<button style="margin-bottom: 8px;" id="pg_deadlock_info" type="button" class="btn btn-default btn-sm">查看死锁信息</button>\
<button style="margin-bottom: 8px;" id="pg_slave_status" type="button" class="btn btn-default btn-sm">查看主从复制信息</button>\
</div>',
success:function(i,l){
$('#pg_top_nsql').click(function(){ pgCommonFuncTopN(); });
$('#pg_net_stat').click(function(){ pgCommonFuncNet(); });
$('#pg_redundant_indexes').click(function(){ pgCommonFuncRedundantIndexes(); });
$('#pg_table_info').click(function(){ pgCommonFuncTableInfo(); });
$('#pg_conn_count').click(function(){ pgCommonFuncConnCount(); });
$('#pg_fpk_info').click(function(){ pgCommonFuncFpkInfo(); });
$('#pg_lock_sql').click(function(){ pgCommonFuncLockSQL(); });
$('#pg_deadlock_info').click(function(){ pgCommonFuncDeadlockInfo(); });
$('#pg_slave_status').click(function(){ pgCommonFuncSlaveStatus(); });
}
});
});
}
function pgCommonFuncTopN(){
pgPostCBN('get_topn_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgShowNotice('查询执行次数最频繁的前N条SQL语句', data.msg);
return;
}
pgModalTable('查询执行次数最频繁的前N条SQL语句', data.data, '1000px', '450px');
});
}
function pgCommonFuncNet(){
pgPostCBN('get_net_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgShowNotice('PostgreSQL服务器的QPS/TPS指标', data.msg);
return;
}
pgModalTable('PostgreSQL服务器的QPS/TPS指标(网络带宽需在系统层监控)', data.data, '1000px', '360px');
});
}
function pgCommonFuncRedundantIndexes(){
function renderList(){
pgPostCBN('get_redundant_indexes',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
var items = data.data;
if (items.length == 0){
layer.msg('没有发现重复或冗余的索引',{icon:7});
return;
}
var tbody = '';
for (var i = 0; i < items.length; i++){
tbody += '<tr>\
<td>'+pgHtml(items[i]['table_schema'])+'</td>\
<td>'+pgHtml(items[i]['table_name'])+'</td>\
<td>'+pgHtml(items[i]['redundant_index_name'])+'</td>\
<td>'+pgHtml(items[i]['redundant_index_columns'])+'</td>\
<td><a class="pg_drop_index btlink" index="'+i+'">删除</a></td>\
</tr>';
}
layer.open({
type: 1,
title: "查看重复或冗余的索引",
area: ['1000px', '420px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20 divtable taskdivtable">\
<table class="table table-hover" id="pg_redundant_table">\
<thead><tr>\
<th>库名</th><th>表名</th><th>冗余索引</th><th>字段</th><th>操作</th>\
</tr></thead>\
<tbody>'+tbody+'</tbody>\
</table>\
</div>',
success: function(){
$('#pg_redundant_table .pg_drop_index').click(function(){
var index = $(this).attr('index');
layer.confirm('确定删除索引 '+pgHtml(items[index]['redundant_index_name'])+' ?', {btn:['确定','取消']}, function(li){
pgPostCB('redundant_indexes_cmd', {'sid':pgGetSid(),'index':index}, function(r2){
var d = r2.data;
showMsg(d.msg,function(){
if (d.status){
layer.close(li);
renderList();
}
},{icon: d.status ? 1 : 2}, 2000);
});
});
});
}
});
});
}
renderList();
}
function pgCommonFuncTableInfo(){
pgPostCBN('get_table_info',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgShowNotice('统计库里每个表的大小(单位 GB)', data.msg);
return;
}
pgModalTable('统计库里每个表的大小(单位 GB)', data.data, '1200px', '460px');
});
}
function pgCommonFuncConnCount(){
pgPostCBN('get_conn_count',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
pgShowNotice('查看应用端IP连接数总和', data.msg);
return;
}
pgModalTable('查看应用端IP连接数总和', data.data, '700px', '420px');
});
}
function pgCommonFuncFpkInfo(){
pgPostCBN('get_fpk_info',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
pgModalTable('快速找出没有主键的表', data.data, '800px', '400px');
});
}
function pgCommonFuncLockSQL(){
function renderSQL(){
pgPostCBN('get_lock_sql',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
var items = data.data;
var tbody = '';
for (var i = 0; i < items.length; i++){
var t = '<tr>';
t += '<td>'+pgHtml(items[i]['trx_id'])+'</td>';
t += '<td>'+pgHtml(items[i]['trx_state'])+'</td>';
t += '<td>'+pgHtml(items[i]['trx_started'])+'</td>';
t += '<td>'+pgHtml(items[i]['processlist_id'])+'</td>';
t += '<td title="'+pgHtml(items[i]['info'])+'">'+pgHtml(items[i]['info'])+'</td>';
t += '<td>'+pgHtml(items[i]['user'])+'</td>';
t += '<td>'+pgHtml(items[i]['host'])+'</td>';
t += '<td>'+pgHtml(items[i]['db'])+'</td>';
t += '<td>'+pgHtml(items[i]['command'])+'</td>';
t += '<td>'+pgHtml(items[i]['state'])+'</td>';
t += '<td>'+pgHtml(items[i]['sql_kill_blocking_query'])+'</td>';
t += '<td><a class="exec btlink" index="'+i+'">执行</a></td>';
t += '</tr>';
tbody += t;
}
$('#pg_lock_table tbody').html(tbody);
$('#pg_lock_table tbody .exec').click(function(){
var index = $(this).attr('index');
var pid = items[index]['processlist_id'];
pgPostCB('kill_lock_pid', {'sid':pgGetSid(),'pid':pid}, function(r2){
var d = r2.data;
showMsg(d.msg,function(){
if (d.status){
renderSQL();
}
},{icon: d.status ? 1 : 2}, 2000);
});
});
});
}
layer.open({
type: 1,
title: "查看当前锁阻塞的SQL",
area: ['1100px', '420px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20 divtable taskdivtable">\
<div class="mr20 pull-left" style="border-right: 1px solid #ccc; padding-right: 20px;">\
<button id="pg_kill_all" type="button" class="btn btn-default btn-sm">关闭所有阻塞</button>\
</div>\
<hr />\
<table class="table table-hover" id="pg_lock_table">\
<thead><tr>\
<th>事务ID</th><th>事务状态</th><th>执行时间</th><th>线程ID</th>\
<th>Info</th><th>user</th><th>host</th><th>db</th>\
<th>command</th><th>state</th><th>kill</th><th>操作</th>\
</tr></thead>\
<tbody></tbody>\
</table>\
</div>',
success:function(){
renderSQL();
$('#pg_kill_all').unbind('click').click(function(){
pgPostCB('kill_all_lock', {'sid':pgGetSid()}, function(r2){
var d = r2.data;
showMsg(d.msg,function(){
if (d.status){
renderSQL();
}
},{icon: d.status ? 1 : 2}, 2000);
});
});
}
});
}
function pgCommonFuncDeadlockInfo(){
function renderText(){
pgPostCBN('get_deadlock_info',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
$('#pg_info_log').val(data.data);
});
}
layer.open({
type: 1,
title: "查看死锁信息",
area: ['800px', '400px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd15">\
<textarea readonly="" style="margin: 0px;height: 330px;width: 100%;background-color: #333;color:#fff; padding:0 5px" id="pg_info_log"></textarea>\
</div>',
success:function(){
renderText();
}
});
}
function pgCommonFuncSlaveStatus(){
function renderText(){
pgPostCBN('get_slave_status',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
return;
}
$('#pg_info_log').val(data.data);
});
}
layer.open({
type: 1,
title: "查看主从复制信息",
area: ['800px', '400px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd15">\
<textarea readonly="" style="margin: 0px;height: 330px;width: 100%;background-color: #333;color:#fff; padding:0 5px" id="pg_info_log"></textarea>\
</div>',
success:function(){
renderText();
}
});
}
// ------------------------- postgresql end ---------------------------------

View File

@@ -1,5 +1,5 @@
{
"sort": 7,
"sort": 1000,
"ps": "Docker是一个开源的应用容器引擎",
"name": "docker",
"title": "Docker",

View File

@@ -13,7 +13,7 @@ serverPath=$(dirname "$rootPath")
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
. ${rootPath}/bin/activate
fi
# {
@@ -40,7 +40,7 @@ fi
Install_Docker()
{
# which docker
# if [ "$?" == "0" ];then
# if [ "$?" = "0" ];then
# echo '安装已经完成docker'
# exit 0
# fi
@@ -69,7 +69,7 @@ Uninstall_Docker()
{
CMD=yum
which apt
if [ "$?" == "0" ];then
if [ "$?" = "0" ];then
CMD=apt
fi
@@ -97,7 +97,7 @@ Uninstall_Docker()
}
action=$1
if [ "${1}" == 'install' ];then
if [ "${1}" = 'install' ];then
Install_Docker
else
Uninstall_Docker

View File

@@ -0,0 +1,48 @@
[general]
# 监听地址和端口
listen_addr = "0.0.0.0:8080"
# DoH 路径
path = "/dns-query"
# TLS 配置(如果需要 HTTPS)
# tls_cert_path = "/etc/doh-proxy/cert.pem"
# tls_key_path = "/etc/doh-proxy/key.pem"
# 并发请求限制
max_concurrent_requests = 512
# 日志文件
log_file = "{$SERVER_PATH}/doh/doh-proxy.log"
[upstream]
# 上游 DNS 服务器
upstream_addr = "1.1.1.1:443"
bootstrap_addr = "1.1.1.1:53"
# 上游 DoH 服务器 URL(如果使用标准的 DoH 端点)
# upstream_url = "https://cloudflare-dns.com/dns-query"
# 超时设置
timeout = 10
# 重试次数
tries = 3
# 启用 TCP 保活
tcp_keepalive = 30
[cache]
# 缓存设置
max_entries = 65536
min_ttl = 60
max_ttl = 3600
[network]
# 网络设置
tcp_fastopen = true
reuse_port = true
[log]
# 日志级别:debug, info, warn, error
level = "info"

BIN
plugins/doh/ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Some files were not shown because too many files have changed in this diff Show More