Compare commits

..
656 Commits
Author SHA1 Message Date
Mr Chen 4769ce5be8 Merge pull request #431 from midoks/dev
0.15.2
2023-08-05 15:12:37 +08:00
midoks 8e16cbf7f9 0.15.2 2023-08-05 15:06:22 +08:00
midoks 4225d4c040 Update common.py 2023-08-05 14:43:14 +08:00
midoks b578f2fddc Update common.py 2023-08-05 14:42:43 +08:00
midoks 961c3423fd Update common.py 2023-08-05 14:29:52 +08:00
midoks 8040c8c67a Update common.py 2023-08-05 14:21:25 +08:00
midoks 5aca7d7c26 Update common.py 2023-08-05 14:17:16 +08:00
midoks d9f99e6b7c Update common.py 2023-08-05 14:17:01 +08:00
midoks 3addb46708 Update common.py 2023-08-05 13:46:19 +08:00
midoks e6b493237d 优化初始化安装SSH端口识别 2023-08-05 13:36:13 +08:00
midoks 7f42054a14 Update ubuntu.sh 2023-08-05 12:29:39 +08:00
midoks 501af3da15 Update plugins_api.py 2023-08-05 12:01:46 +08:00
midoks 68727cbe91 Update site_api.py 2023-08-05 11:28:33 +08:00
midoks c5207961f3 Update index.py 2023-08-05 01:52:49 +08:00
midoks a04e05c7e8 Update index.py 2023-08-05 01:19:42 +08:00
midoks 5b8cca24aa Update index.py 2023-08-05 00:46:41 +08:00
midoks cafe58f3fc Update index.py 2023-08-05 00:45:04 +08:00
midoks d1e2781eb9 Update index.py 2023-08-05 00:44:48 +08:00
midoks 67c899fc84 Update index.py 2023-08-05 00:43:06 +08:00
midoks 7432548ff9 Update index.py 2023-08-05 00:24:35 +08:00
midoks 0c2c136097 Update index.py 2023-08-04 23:58:21 +08:00
midoks 2a7e21951b Update my8.0.cnf 2023-08-04 22:49:18 +08:00
midoks 066185e404 网站设置反向代理升级功能 2023-08-04 20:27:20 +08:00
midoks bd431f1647 docker阶段性完成 2023-08-03 18:37:14 +08:00
midoks 0a6e88d81d update 2023-08-03 17:00:12 +08:00
midoks 02c9988ef7 Update docker.js 2023-08-03 00:24:13 +08:00
midoks 5ee7df4a46 Update nginx.conf 2023-08-03 00:14:16 +08:00
midoks 5f382c0034 update 2023-08-03 00:06:01 +08:00
midoks 63d17c4d77 Update docker.js 2023-08-02 23:24:10 +08:00
midoks 38722c1dc2 Update index.py 2023-08-02 17:51:29 +08:00
midoks ea982b7261 Update README.md 2023-08-02 17:50:22 +08:00
midoks 73d9edced8 使用mariadb二进制导入备份文件 2023-08-02 17:36:27 +08:00
midoks af03c004a3 Update rsyncd.js 2023-08-02 15:35:30 +08:00
midoks ddd9e70ac2 Update rsyncd.js 2023-08-02 15:29:32 +08:00
midoks 8976a7a147 Update rsyncd.js 2023-08-02 15:26:55 +08:00
midoks 677ff8ec0c Update README.md 2023-08-02 15:10:42 +08:00
midoks 47d240e2b8 rsyncd添加优化 2023-08-02 15:10:23 +08:00
midoks 1f7bd76875 Update crontab_api.py 2023-08-02 14:27:04 +08:00
midoks f04c70f022 计划任务自动脚本运行时间 2023-08-02 14:04:00 +08:00
midoks 5044cc5db9 Update README.md 2023-08-02 00:06:51 +08:00
midoks 4329b90ac4 Update info.json 2023-08-01 23:58:10 +08:00
midoks f7873b6dcd Update init_cmd.py 2023-07-25 00:03:20 +08:00
midoks a80d666786 update 2023-07-24 23:52:38 +08:00
Mr Chen 0598704dce Merge pull request #428 from midoks/dev
修复centos9源安装问题
2023-07-22 12:54:17 +08:00
midoks 8f19a05755 Update rhel.sh 2023-07-22 12:53:07 +08:00
midoks f320d7cc69 Update rhel.sh 2023-07-22 12:26:56 +08:00
midoks 1e97929a24 Update push_notice_msg.py 2023-07-21 12:10:55 +08:00
Mr Chen c66bbac97e Merge pull request #427 from midoks/dev
python3.7 urllib3在亚马逊降级
2023-07-20 16:14:22 +08:00
midoks 1f7a0d2795 Create r3.7.txt 2023-07-20 16:04:18 +08:00
midoks f05ce79e63 Update rhel.sh 2023-07-20 15:55:11 +08:00
midoks 9f3d06191a PHP提示优化 2023-07-19 18:35:27 +08:00
Mr Chen 2c6614a5ff Merge pull request #426 from midoks/dev
赞助换域名
2023-07-18 15:23:49 +08:00
midoks 905bad29cf Update README.md 2023-07-18 15:22:19 +08:00
midoks 9ba572a8ce AD修改 2023-07-16 17:23:45 +08:00
Mr Chen 85fc333d2c Merge pull request #424 from midoks/dev
0.15.1
2023-07-15 23:04:39 +08:00
midoks 5bc27a4725 Update config_api.py 2023-07-15 22:53:38 +08:00
midoks e5acf206f5 Update cli.sh 2023-07-15 20:43:13 +08:00
midoks ae7afc2eb5 Update rhel.sh 2023-07-15 20:34:46 +08:00
midoks 5c8527a5de 监控页面-自定义时间优化。 2023-07-15 19:33:17 +08:00
midoks 274592229e Update rhel.sh 2023-07-15 15:51:03 +08:00
midoks 60ddb13f8e Update rhel.sh 2023-07-15 15:50:35 +08:00
midoks f62af00fb7 Update rhel.sh 2023-07-15 15:49:28 +08:00
midoks 9c6faefffd Update rhel.sh 2023-07-15 15:38:14 +08:00
midoks c9e27c2add 优化
* [插件]docker - 添加IP地址池。
* PHP下载中国优化。
2023-07-15 15:00:00 +08:00
midoks 97b1e8b9b3 Update rhel.sh 2023-07-15 12:34:47 +08:00
midoks 18cdcd1436 修复子目录绑定-伪静态问题。 2023-07-13 10:36:16 +08:00
midoks 7d783c64b6 OP防火墙优化
站点配置-状态关闭后,不再防御。
2023-07-13 00:40:46 +08:00
midoks 0b65d69750 Update __init__.py 2023-07-12 22:18:55 +08:00
midoks 693dbb8cf1 Update __init__.py 2023-07-12 22:17:58 +08:00
midoks 117a99e729 增加标识 2023-07-12 09:46:58 +08:00
midoks 45d4b8a5de update 2023-07-11 16:25:34 +08:00
midoks a5791051b1 Update debian.sh 2023-07-11 16:11:20 +08:00
midoks dc3f8f8e0b 自动同步gitee 2023-07-11 12:21:48 +08:00
midoks bf1d00c012 Update config_api.py 2023-07-10 22:41:13 +08:00
midoks 51cf851cea Update site.js 2023-07-10 22:38:37 +08:00
midoks 1e09408eb9 Update index.py 2023-07-10 22:13:46 +08:00
midoks 7659865caf Update lib.sh 2023-07-05 22:19:44 +08:00
Mr Chen ad1851d068 Merge pull request #423 from midoks/dev
requests兼容低版本
2023-07-05 18:05:33 +08:00
midoks e174652afc Update requirements.txt 2023-07-05 18:02:40 +08:00
midoks a95e7aacd7 Update r3.6.txt 2023-07-05 18:00:36 +08:00
Mr Chen 6aa638ef9a Merge pull request #422 from midoks/dev
Update requirements.txt
2023-07-05 13:03:14 +08:00
midoks 6f3d50bae5 Update requirements.txt 2023-07-05 13:01:08 +08:00
Mr Chen 301a5a95b8 Merge pull request #421 from midoks/dev
AD
2023-07-05 12:51:37 +08:00
midoks d35b9dccc7 AD信息 2023-07-05 12:49:47 +08:00
midoks 82680605ac mvirtua ad 2023-07-05 12:47:05 +08:00
midoks 5b148b3d1a Update requirements.txt 2023-07-05 10:20:04 +08:00
Mr Chen 714acd20e5 Merge pull request #420 from midoks/dev
0.15.0
2023-07-04 20:55:21 +08:00
midoks bf58cd8acc Update config_api.py 2023-07-04 20:52:57 +08:00
midoks 059053d27c mysql安装成功后,删除原文件 2023-07-03 22:22:11 +08:00
midoks 185e73c26a Update index.py 2023-07-03 22:12:55 +08:00
midoks 569511d321 update 2023-07-03 22:08:00 +08:00
midoks f88bf5059f Update README.md 2023-07-03 17:52:56 +08:00
midoks 05b63b8d2b Update index.py 2023-07-03 17:45:12 +08:00
midoks 3a197b273d Update docker.js 2023-07-03 17:37:14 +08:00
midoks f4fdbab41c Update index.py 2023-07-03 17:35:34 +08:00
midoks f6b2940657 docker插件容器创建OK 2023-07-03 17:34:58 +08:00
midoks 78b9ac5df0 up 2023-07-03 11:53:54 +08:00
midoks 3ea4272307 Update docker.js 2023-07-02 16:29:10 +08:00
midoks efc7cee9ad Update docker.js 2023-07-02 15:36:38 +08:00
midoks 5c4805453d Update docker.js 2023-07-02 15:27:25 +08:00
midoks f6da241c85 update 2023-07-02 14:38:56 +08:00
midoks d5b6eb2325 update 2023-07-01 22:06:54 +08:00
midoks 6ed2cddf71 Update docker.js 2023-07-01 21:35:46 +08:00
midoks 9c31d76442 docker update 2023-07-01 21:34:04 +08:00
midoks 7aecbaf7df Update docker.js 2023-07-01 15:22:41 +08:00
midoks ee81a86d24 update 2023-07-01 15:17:43 +08:00
midoks 0a60d66732 update 2023-07-01 14:46:22 +08:00
midoks c3e3cff472 Update docker.js 2023-07-01 12:37:15 +08:00
midoks 194d46eb6a Update docker.js 2023-07-01 12:37:02 +08:00
midoks d66bc94edc Update docker.js 2023-07-01 12:34:09 +08:00
midoks fb4ffcd343 Update index.py 2023-07-01 12:30:58 +08:00
midoks 10c235e317 Update r3.6.txt 2023-07-01 12:25:32 +08:00
midoks 9c156928d8 up 2023-07-01 12:24:04 +08:00
midoks 771905d7f6 Update requirements.txt 2023-07-01 12:23:01 +08:00
midoks cd21b3f3e7 Update r3.6.txt 2023-07-01 12:22:18 +08:00
midoks 982026db24 update 2023-07-01 12:21:07 +08:00
midoks f9b91d9989 Update docker.js 2023-07-01 12:17:30 +08:00
midoks f7b1159bd7 update 2023-07-01 12:15:51 +08:00
midoks 6aa49ddbcf Update rhel.sh 2023-07-01 11:48:06 +08:00
midoks 866eddac1d Update lib.sh 2023-07-01 10:19:42 +08:00
midoks af0cce4216 Update install.sh 2023-07-01 10:16:39 +08:00
midoks 3951322d86 Update install_dev.sh 2023-07-01 10:16:23 +08:00
midoks dfdd16b444 Update index.py 2023-07-01 10:11:15 +08:00
midoks aa8fec2b7e update 2023-07-01 09:52:53 +08:00
midoks 2a8958ab84 Update index.py 2023-07-01 00:32:36 +08:00
midoks f5125670ee Update index.py 2023-07-01 00:19:24 +08:00
midoks 2a8d4fb7a9 Update requirements.txt 2023-07-01 00:14:04 +08:00
midoks 59f7fe2290 Update requirements.txt 2023-07-01 00:07:30 +08:00
midoks 928db6e7e7 Update requirements.txt 2023-07-01 00:02:13 +08:00
midoks f3927bd6cf Update requirements.txt 2023-07-01 00:01:32 +08:00
midoks bb92727b56 Update requirements.txt 2023-07-01 00:00:14 +08:00
midoks 21b80b1fce Update index.py 2023-06-30 23:54:05 +08:00
midoks 637da92834 up 2023-06-30 23:43:51 +08:00
midoks f5859626a9 update 2023-06-30 21:57:42 +08:00
midoks 003449eb0a update 2023-06-30 12:30:28 +08:00
midoks d27f926191 update 2023-06-30 12:16:25 +08:00
midoks 7483247d4d up 2023-06-30 10:17:02 +08:00
midoks 1ad841d3af Update docker.js 2023-06-30 00:09:15 +08:00
midoks 27376d879c up 2023-06-30 00:09:09 +08:00
midoks 8b824447c1 Update php.service.tpl 2023-06-29 18:29:39 +08:00
midoks a1d26dcd45 Update intl.sh 2023-06-29 16:25:12 +08:00
midoks 5e68c7bf0a Update install.sh 2023-06-29 13:00:08 +08:00
midoks 481ae16713 Update index.py 2023-06-29 12:59:05 +08:00
midoks 2d2bd39f9e Update intl.sh 2023-06-29 12:02:48 +08:00
midoks 7246a878a5 Update intl.sh 2023-06-29 12:00:37 +08:00
midoks 542ee3cdb0 Update intl.sh 2023-06-29 11:59:59 +08:00
midoks 69503b223b update 2023-06-29 11:43:56 +08:00
midoks 78d8fa7ebf Update lib.sh 2023-06-29 10:54:26 +08:00
midoks 21e9d8f2d8 Update update_dev.sh 2023-06-29 10:49:10 +08:00
midoks 3c6adfbd44 Update install.sh 2023-06-29 10:41:10 +08:00
midoks c0e70abe6d Update install_dev.sh 2023-06-29 10:40:31 +08:00
midoks f174e71228 Update app.py 2023-06-29 10:25:14 +08:00
midoks 7a9a811ea6 Update app.py 2023-06-29 10:21:39 +08:00
midoks c7e3d9d9a3 Update app.py 2023-06-29 10:20:39 +08:00
midoks 161f7a1bc0 Update app.py 2023-06-29 10:18:52 +08:00
midoks 175cce0131 Update lib.sh 2023-06-29 10:11:52 +08:00
midoks 3735897ed2 Update lib.sh 2023-06-29 09:59:06 +08:00
midoks 30bfa5a630 Update lib.sh 2023-06-29 09:56:24 +08:00
midoks 594fdb4712 Update lib.sh 2023-06-29 09:55:14 +08:00
midoks 31a441ea02 update 2023-06-29 09:52:30 +08:00
midoks 06f7087fad Update requirements.txt 2023-06-29 09:30:06 +08:00
midoks e7b8f5afdc Update index.py 2023-06-29 09:25:55 +08:00
midoks 6b57addfa7 Update index.py 2023-06-28 19:11:44 +08:00
midoks aea435fbaf Update index.py 2023-06-28 18:53:45 +08:00
midoks 9cd6656946 u 2023-06-28 16:04:17 +08:00
midoks 4f7df4b3c3 Update index.py 2023-06-28 14:58:45 +08:00
midoks 70d12b7b8d docker 2023-06-28 14:53:59 +08:00
midoks fe576c820a Update requirements.txt 2023-06-28 04:09:09 +08:00
midoks b48a53e0d7 Create nezha.conf 2023-06-28 04:04:44 +08:00
midoks 4701839c33 up 2023-06-28 03:40:23 +08:00
midoks 916bc67c4d Update cert_api.py 2023-06-28 03:21:11 +08:00
midoks d7bba830cc Update requirements.txt 2023-06-28 02:33:11 +08:00
midoks 7a28f8f57a Update index.py 2023-06-28 02:30:28 +08:00
midoks 41ee25aa7b update 2023-06-28 02:21:59 +08:00
midoks c8aa91cfa3 up 2023-06-28 02:09:28 +08:00
midoks 98f27498b0 Update index.py 2023-06-28 01:57:06 +08:00
midoks 5444fe6455 Update index.py 2023-06-28 01:40:41 +08:00
midoks 9627c6e47b Update index.py 2023-06-28 01:32:14 +08:00
midoks 13597d6282 Update index.py 2023-06-28 01:21:15 +08:00
midoks d09494e3aa Update index.py 2023-06-28 01:14:15 +08:00
midoks d35439d286 Update index.py 2023-06-28 01:14:03 +08:00
midoks ced48bab47 nezha 测试OK 2023-06-28 01:02:58 +08:00
midoks fe2df6cc8d up 2023-06-28 00:08:38 +08:00
midoks 8bdfe15101 nezha 60% 2023-06-28 00:04:07 +08:00
midoks 42e9983b88 Update config.json 2023-06-27 15:56:43 +08:00
midoks 9b7c0b6f99 up 2023-06-27 15:11:38 +08:00
midoks e421292c9e up 2023-06-27 14:13:04 +08:00
midoks 7b4d31779a Update install.sh 2023-06-27 01:31:52 +08:00
midoks f3b09056f3 init nezha plugin 2023-06-26 23:06:06 +08:00
midoks a92ccea6c5 lrzsz 2023-06-26 11:57:07 +08:00
midoks 9da77a0a9b up 2023-06-24 22:37:02 +08:00
midoks c233ecaaa7 up 2023-06-22 16:06:04 +08:00
midoks 5828b8b8cb up 2023-06-22 16:00:09 +08:00
midoks a4a1a2c83c up 2023-06-20 16:39:36 +08:00
midoks 0e20bc182c up 2023-06-19 20:28:44 +08:00
midoks 99c0b0a81a Update site_api.py 2023-06-17 23:20:24 +08:00
midoks 3fa199fec4 acme部署问题 2023-06-17 23:18:15 +08:00
midoks 194c36c6d8 tg ad 2023-06-15 01:43:21 +08:00
midoks 2fb542f6b4 Update all_test.sh 2023-06-14 01:25:55 +08:00
midoks 60af43ed31 Update intl.sh 2023-06-14 01:24:15 +08:00
midoks 9f02cf9744 Update install.sh 2023-06-14 01:21:47 +08:00
midoks 846bd270df Update yaf.sh 2023-06-14 01:14:47 +08:00
midoks d910d4f462 up 2023-06-14 00:31:20 +08:00
midoks 13f5b1bf02 up 2023-06-13 18:34:57 +08:00
midoks 1fc3fd6247 Update lib.sh 2023-06-13 18:03:53 +08:00
midoks 36e3feb886 Update requirements.txt 2023-06-13 17:46:00 +08:00
midoks 0ca34afacd Update lib.sh 2023-06-13 17:43:39 +08:00
midoks ffb3288f3d Update requirements.txt 2023-06-13 17:40:55 +08:00
midoks e2f68a73ed Update requirements.txt 2023-06-13 17:34:23 +08:00
midoks 92fa8da2f6 Update lib.sh 2023-06-13 17:19:23 +08:00
midoks 7c96ddd63e Update lib.sh 2023-06-13 17:14:50 +08:00
midoks c4e7872179 Update lib.sh 2023-06-13 17:14:31 +08:00
midoks d399cb2bb4 Update install.sh 2023-06-13 16:38:04 +08:00
midoks 985cbc7eca Update install.sh 2023-06-13 16:36:48 +08:00
midoks 27ed21a17d update 2023-06-10 15:09:31 +08:00
midoks 972165ba1a Update lib.sh 2023-05-30 17:53:16 +08:00
midoks e76eb4d0e8 Update client_check_member.py 2023-05-29 18:40:12 +08:00
midoks fd05c40dbb up 2023-05-29 18:34:37 +08:00
midoks a1a7fa5c82 网站备注优化 2023-05-28 19:59:31 +08:00
midoks 531de1407f Update push_notice_msg.py 2023-05-28 19:00:42 +08:00
midoks ca455f13e8 ad 2023-05-28 14:50:53 +08:00
midoks ab5342b01f Update docker.js 2023-05-27 00:18:44 +08:00
midoks a5a57c5718 update 2023-05-27 00:18:39 +08:00
midoks 27999b21e6 Update config.json 2023-05-24 23:04:59 +08:00
midoks d2c6caeef2 Update client_temp.py 2023-05-23 20:46:32 +08:00
midoks de30d8a41f Create client_temp.py 2023-05-23 20:42:08 +08:00
midoks d3abc8e7b2 up 2023-05-18 17:10:50 +08:00
midoks b7aad65eb5 Update site_api.py 2023-05-17 13:36:35 +08:00
midoks 240b1dec27 修正网站搜索功能 2023-05-16 20:34:12 +08:00
midoks 4756e0f68b Update push_notice_msg.py 2023-05-15 19:30:38 +08:00
midoks 59f62b948a Update push_notice_msg.py 2023-05-15 19:30:00 +08:00
midoks 0ab0741031 up 2023-05-15 19:23:32 +08:00
midoks 2fd2f6e844 AD 2023-05-15 19:20:58 +08:00
midoks e534c6177a update 2023-05-15 19:14:43 +08:00
midoks 897c6322fc Update install.sh 2023-05-14 23:57:41 +08:00
midoks 201e93f946 Update requirements.txt 2023-05-14 19:09:02 +08:00
Mr Chen a78fd957ec Merge pull request #411 from midoks/dev
更新pip库2
2023-05-14 19:05:30 +08:00
midoks 3ce037b0a1 Update requirements.txt 2023-05-14 19:03:39 +08:00
midoks f3176340f8 Update requirements.txt 2023-05-14 19:02:58 +08:00
midoks 7bfe096e8d Update requirements.txt 2023-05-14 19:00:45 +08:00
Mr Chen 066428fca8 Merge pull request #410 from midoks/dev
更新pip版本
2023-05-14 18:46:51 +08:00
midoks a1313846c8 Update requirements.txt 2023-05-14 18:43:47 +08:00
midoks 0433123abd Update requirements.txt 2023-05-14 18:36:50 +08:00
midoks 72e99844dd Update requirements.txt 2023-05-14 18:31:19 +08:00
Mr Chen 3a7882e7fa Merge pull request #409 from midoks/dev
0.14.5
2023-05-14 13:12:27 +08:00
midoks bec2a9a12c 0.14.5
* 软件管理-搜索功能。
* 文件-右键功能优化。
2023-05-14 13:10:17 +08:00
midoks 8f02363782 Update files.html 2023-05-12 11:22:38 +08:00
midoks 939c847f3e Update plugins_api.py 2023-05-10 18:23:06 +08:00
midoks a623039db7 完成搜索功能 2023-05-10 18:20:48 +08:00
midoks b7f49a1839 Update soft.html 2023-05-10 17:59:17 +08:00
midoks f1f60870f6 up 2023-05-09 12:46:09 +08:00
midoks 3b04739fd4 up 2023-05-09 12:45:25 +08:00
midoks fdf1e0b0be up 2023-05-09 12:39:44 +08:00
midoks d3385f526f Update client_check_member.py 2023-05-09 11:37:39 +08:00
midoks 20f9095b93 up 2023-05-09 09:17:54 +08:00
midoks 757cf483a2 Update client_ad.py 2023-05-08 12:07:36 +08:00
midoks 1712cfd024 Update client_ad.py 2023-05-08 12:03:16 +08:00
midoks 2b524cbe75 Update client_ad.py 2023-05-08 11:57:01 +08:00
midoks 607d384000 Update client_ad.py 2023-05-08 11:29:09 +08:00
midoks 14cdc7b82e Update client_ad.py 2023-05-08 11:15:27 +08:00
midoks c3219bcba2 Update client_check_member.py 2023-05-07 23:15:06 +08:00
Mr Chen a12c4dd78e Merge pull request #407 from midoks/dev
0.14.4
2023-05-06 14:54:52 +08:00
midoks 39c6f19592 Update README.md 2023-05-06 14:54:34 +08:00
midoks f18c05a097 0.14.4 2023-05-06 14:53:16 +08:00
midoks 80f296ea19 redat 系列 php74之后都需要安装oniguruma
debian系统,不需要
2023-05-06 14:42:54 +08:00
midoks b3e9283a58 Update rhel.sh 2023-05-06 14:37:25 +08:00
midoks 2e140a3ae1 Update index.py 2023-05-06 14:18:46 +08:00
midoks 4d733c8886 Update index.py 2023-05-06 14:16:50 +08:00
midoks 62a7320baf Update rhel.sh 2023-05-06 13:59:02 +08:00
midoks 3dc7c2f5c1 Update rhel.sh 2023-05-06 13:52:55 +08:00
midoks fe62bbee06 Update rhel.sh 2023-05-06 13:24:47 +08:00
midoks f7c0cd82a0 Update rhel.sh 2023-05-06 13:22:49 +08:00
midoks 13a2014558 Update rhel.sh 2023-05-06 12:49:25 +08:00
midoks 5981f94376 Update rhel.sh 2023-05-06 12:30:51 +08:00
midoks 005e0f1513 Update rhel.sh 2023-05-06 12:27:54 +08:00
midoks 63a0f0fbdc Update rhel.sh 2023-05-05 23:32:07 +08:00
midoks edc0be11a1 Update rhel.sh 2023-05-05 23:22:22 +08:00
midoks 908b6e67c6 Update rhel.sh 2023-05-05 23:21:57 +08:00
midoks dfe46332db up 2023-05-05 22:49:39 +08:00
midoks fcdf2e18b2 Update config_api.py 2023-05-05 22:19:33 +08:00
midoks 3c8f9bcf96 Update config.js 2023-05-05 22:19:26 +08:00
midoks ebadd6d80d 端口修改后,跳转优化 2023-05-05 22:16:53 +08:00
Mr Chen 6062699074 Merge pull request #406 from midoks/dev
0.14.3
2023-05-05 20:52:04 +08:00
midoks df9d57ba70 Update README.md 2023-05-05 20:50:20 +08:00
midoks ffca953539 up 2023-05-05 20:49:45 +08:00
midoks bd4946124f Update install.sh 2023-05-05 18:21:10 +08:00
midoks 8e18c63cee up 2023-05-05 17:52:13 +08:00
midoks d201ca2574 Update install_dev.sh 2023-05-05 17:51:09 +08:00
midoks b644f91090 安装时curl库软连接修复 2023-05-05 16:59:47 +08:00
midoks 931f51cf59 Update client_ad.py 2023-05-05 14:12:14 +08:00
midoks 0909a11fd9 Update client_ad.py 2023-05-05 14:03:45 +08:00
midoks 2ba2833699 Update client_ad.py 2023-05-05 13:59:14 +08:00
midoks 20389263fb Update client_ad.py 2023-05-04 20:41:10 +08:00
midoks 86141ccf3a Update my5.7.cnf 2023-05-04 16:42:59 +08:00
midoks b2fdf84ca0 Update index.py 2023-05-04 16:39:46 +08:00
midoks 8fbc456e1a Update my5.7.cnf 2023-05-04 13:19:21 +08:00
midoks 4e43382496 Update client_ad.py 2023-05-03 18:29:37 +08:00
midoks 0326d4f112 Update client_ad.py 2023-05-03 18:05:33 +08:00
midoks a87c13c5e0 Update client_ad.py 2023-05-03 13:02:21 +08:00
midoks 5f3720c855 Update client_ad.py 2023-05-03 12:50:41 +08:00
midoks f548e020c4 up 2023-05-03 12:33:56 +08:00
midoks 7f21781c0b Update tgclient.py 2023-05-03 12:33:01 +08:00
midoks 680b0f09f2 Update client_ad.py 2023-05-03 12:22:31 +08:00
midoks 482943a63c Update client_ad.py 2023-05-03 10:53:49 +08:00
midoks 2871aee18e Create client_ad.py 2023-05-03 10:53:18 +08:00
midoks ff46d9b36e up 2023-05-02 21:39:18 +08:00
midoks fd5fcba543 up 2023-05-02 13:25:07 +08:00
Mr Chen fe04e02e88 Merge pull request #405 from midoks/dev
0.14.2
2023-05-02 12:11:48 +08:00
midoks 93554332a7 Update README.md 2023-05-02 12:10:37 +08:00
midoks b541c7e1b7 Update config_api.py 2023-05-02 12:09:02 +08:00
midoks 1dec1a286a Update docker.js 2023-05-02 12:07:51 +08:00
midoks b17510104d up 2023-05-02 11:55:32 +08:00
midoks c2c8ea0ce6 Update install.sh 2023-05-02 11:52:56 +08:00
midoks acbdb013ae Update install.sh 2023-05-02 11:42:16 +08:00
midoks b025f21765 Update index.py 2023-05-02 11:36:28 +08:00
midoks 1afc8a69e5 Update index.py 2023-05-02 11:35:21 +08:00
midoks 743fc9e8d3 Update index.py 2023-05-02 11:35:06 +08:00
midoks 8d692d2b3b Update install.sh 2023-05-02 11:34:00 +08:00
midoks a0b362e691 Update index.py 2023-05-02 11:31:25 +08:00
midoks 98e1c2ae8f Update install.sh 2023-05-02 11:26:27 +08:00
midoks c0e5915285 Update index.html 2023-05-02 11:23:46 +08:00
midoks 667a0fd0fd Update install.sh 2023-05-02 11:19:03 +08:00
midoks 8ed5f283b0 Update client_check_member.py 2023-05-01 17:30:03 +08:00
midoks 643c370d30 up 2023-05-01 17:26:02 +08:00
midoks 4601303065 up 2023-05-01 16:05:54 +08:00
midoks 14940d6734 Delete mdioks.session 2023-05-01 15:09:14 +08:00
midoks fdc2b0f5c4 Update client_holding.py 2023-05-01 15:08:40 +08:00
midoks cf0b233f63 Update client_check_member.py 2023-05-01 14:51:54 +08:00
midoks b3a7ef2206 Create client_holding.py 2023-05-01 14:49:50 +08:00
midoks 9a3ca3e833 Update index.html 2023-04-30 10:17:28 +08:00
midoks 9afff8df3f Update index.py 2023-04-30 01:13:00 +08:00
midoks ccd0b06223 Update tgclient.py 2023-04-30 01:04:16 +08:00
midoks 7b495fe9bf Update tgclient.py 2023-04-29 16:24:19 +08:00
midoks 2c3fb75e8f Update tgclient.js 2023-04-29 16:11:09 +08:00
midoks 53b606602f up 2023-04-29 16:10:30 +08:00
midoks ecef0cf994 up 2023-04-29 16:01:10 +08:00
midoks 3691d41b23 Update client_change_username.py 2023-04-28 21:47:13 +08:00
midoks 1f66457a3e Update client_change_username.py 2023-04-28 17:25:38 +08:00
midoks 8e05beccfd Update tgclient.py 2023-04-28 17:22:56 +08:00
midoks 35424eae1f up 2023-04-28 17:21:13 +08:00
midoks ed6df6d527 up 2023-04-28 17:03:41 +08:00
midoks 4366c4afde Update tgclient.py 2023-04-24 22:05:34 +08:00
midoks 4bb059f62f Update info.json 2023-04-24 21:23:44 +08:00
midoks aa8f618d9c Update tgclient.py 2023-04-24 21:15:47 +08:00
midoks dfd753e4c1 up 2023-04-24 21:07:25 +08:00
midoks e38daf3c89 Update tgclient.py 2023-04-24 20:51:54 +08:00
midoks 535838fc5e Update tgclient.py 2023-04-24 20:44:28 +08:00
midoks 797853bd61 Update tgclient.py 2023-04-24 20:36:49 +08:00
midoks 0de3aff045 up 2023-04-24 20:32:41 +08:00
midoks 0b7b48ab23 up 2023-04-24 20:31:31 +08:00
midoks 5ff0a0bfbc Update index.py 2023-04-21 21:03:30 +08:00
midoks 9131f44d67 Update install.sh 2023-04-21 13:02:42 +08:00
midoks 6b86bb9d2b Update docker.js 2023-04-21 13:00:05 +08:00
midoks dc06d6beda Update install.sh 2023-04-21 12:58:50 +08:00
midoks 2c8ea2498e Update install.sh 2023-04-21 12:55:38 +08:00
midoks 6b01173b61 Update push_notice_msg.py 2023-04-20 12:41:56 +08:00
midoks 883c554850 up 2023-04-20 12:19:33 +08:00
midoks d267da351c Update push_ad.py 2023-04-16 23:48:24 +08:00
midoks 13a39f4d6a up 2023-04-16 20:50:30 +08:00
Mr Chen cff1d5ee89 Merge pull request #403 from midoks/dev
0.14.1
2023-04-16 20:42:39 +08:00
midoks bf5274c313 0.14.1
* 安装优化。
* 加入OP负载均衡插件。
* 网站防篡改程序(测试中)。
2023-04-16 20:41:39 +08:00
midoks 5623e3efac Update requirements.txt 2023-04-16 20:38:03 +08:00
midoks b93bb6c64c Update requirements.txt 2023-04-16 20:37:24 +08:00
midoks c9962f169e Update requirements.txt 2023-04-16 20:36:01 +08:00
midoks 080f343ee2 Update push_ad.py 2023-04-15 10:57:19 +08:00
midoks 5aeaf13f16 负载均衡插件 2023-04-13 15:42:01 +08:00
midoks 528094cfa7 网站防篡改程序 2023-04-13 15:33:15 +08:00
midoks ed3e3336b2 Update push_notice_msg.py 2023-04-13 15:28:38 +08:00
Mr Chen a75a49c2ae Merge pull request #402 from midoks/dev
0.14.0
2023-04-13 15:21:19 +08:00
midoks 1204e72f41 0.14.0
* 加入系统加固插件。
2023-04-13 15:20:15 +08:00
midoks 13ca5544a5 Update system_safe.tpl 2023-04-13 15:14:32 +08:00
midoks e53fe26d52 Update system_safe.tpl 2023-04-13 15:09:20 +08:00
midoks 13772399f6 Update system_safe.py 2023-04-13 15:05:06 +08:00
midoks 98f11e2662 Update plugins_api.py 2023-04-13 14:49:46 +08:00
midoks f0b0302f75 Update install.sh 2023-04-13 14:42:07 +08:00
midoks 5b9b466cb9 系统加固放出 2023-04-13 14:39:18 +08:00
midoks 5588a11ea5 Update cert_request.py 2023-04-10 22:35:09 +08:00
midoks da05a4ef19 up 2023-04-10 22:34:12 +08:00
midoks 34cf899529 Update mw.py 2023-04-04 12:43:09 +08:00
midoks 0d7d67b012 up 2023-04-04 12:42:47 +08:00
midoks 5b778bfc0d Update vip_api.py 2023-04-04 12:20:28 +08:00
midoks 6ce414cecf up 2023-04-03 22:39:07 +08:00
midoks c8160b63e7 up 2023-04-03 22:30:08 +08:00
midoks 68d957fd6e Update README.md 2023-04-03 19:34:05 +08:00
midoks f09c438500 Update config.html 2023-04-03 17:46:18 +08:00
Mr Chen 9bc9944a3e Merge pull request #401 from midoks/dev
0.13.6
2023-04-03 17:43:58 +08:00
midoks 9e4c2b13d5 Update README.md 2023-04-03 17:43:05 +08:00
midoks cd7143047f 0.13.6
1.修复初始化安装,缺少解压命令。
2.加入aes加密/解密方法
2023-04-03 17:41:48 +08:00
midoks d608ac4d94 Update install.sh 2023-04-03 16:48:53 +08:00
midoks 9fedf9d10d Update push_notice_msg.py 2023-04-01 10:37:33 +08:00
midoks 9936191da2 up 2023-04-01 10:35:54 +08:00
midoks 538eba3acf up 2023-03-31 22:37:40 +08:00
midoks e39ee9a6f7 VIP用户管理 2023-03-30 21:57:33 +08:00
Mr Chen e1820ad5b3 Merge pull request #400 from midoks/dev
0.13.5
2023-03-30 17:31:54 +08:00
midoks 22133f1a6c 0.13.5
### 版本更新 0.13.5

* 添加邮件通知功能。
* 修复初始安装脚本。
2023-03-30 17:30:15 +08:00
midoks 0041cbdff3 添加邮件通知功能 2023-03-30 17:18:40 +08:00
midoks 889da3c769 Update install.sh 2023-03-30 11:59:55 +08:00
midoks d086eb9c61 Update install.sh 2023-03-30 11:56:48 +08:00
midoks 832fa9cd1a Update install_dev.sh 2023-03-30 11:54:40 +08:00
midoks 8c19fb9629 Update config_api.py 2023-03-30 11:22:36 +08:00
midoks a2e4dd6753 Update push_notice_msg.py 2023-03-30 11:22:19 +08:00
midoks 22ba7dda55 Update install.sh 2023-03-29 16:35:09 +08:00
midoks 2ffa36eecb up 2023-03-29 16:32:46 +08:00
Mr Chen fe5843b35d Merge pull request #398 from midoks/dev
修复python pip源安装
2023-03-29 16:27:46 +08:00
midoks e95acbe947 Update lib.sh 2023-03-29 16:08:55 +08:00
midoks aed8319dd3 Update push_ad.py 2023-03-29 14:08:06 +08:00
midoks babe1b885e Update push_notice_msg.py 2023-03-29 13:17:38 +08:00
midoks 0612f52402 Update push_notice_msg.py 2023-03-29 13:03:52 +08:00
midoks db67cea737 AD 2023-03-29 13:01:12 +08:00
midoks 52cf675843 Update install_dev.sh 2023-03-29 08:49:26 +08:00
Mr Chen 3421bf6ab5 Merge pull request #397 from midoks/dev
0.13.4
2023-03-28 23:54:51 +08:00
midoks 2f39bd600b Update config_api.py
### 版本更新 0.13.4

无重大更新

* 国内安装不在依赖gitee。
* tgbot优化。
2023-03-28 23:53:14 +08:00
midoks acd5ec69e8 Update tgbot.py 2023-03-28 23:49:59 +08:00
midoks 09878728af Update push_ad.py 2023-03-28 20:25:09 +08:00
midoks af82e9f129 Update push_notice_msg.py 2023-03-28 20:23:08 +08:00
midoks c74630e738 Update push_notice_msg.py 2023-03-28 20:19:49 +08:00
midoks e4e0697b4b Update push_notice_msg.py 2023-03-28 20:18:52 +08:00
midoks 11b5ac658b Update mw.tpl 2023-03-28 18:00:50 +08:00
midoks 1306731164 up 2023-03-28 17:47:59 +08:00
midoks bb6c933aee Update README.md 2023-03-28 17:41:50 +08:00
midoks d6a93ef1e6 Update info.json 2023-03-28 17:18:59 +08:00
midoks 6610da402a Update info.json 2023-03-28 17:18:47 +08:00
midoks 3ace9cf51e Update install.sh 2023-03-28 16:54:21 +08:00
midoks 49c7ec6073 Update tgbot.py 2023-03-28 16:31:46 +08:00
midoks 8cf526667e up 2023-03-25 22:05:19 +08:00
midoks 6c42876411 Update receive_faq.py 2023-03-25 21:58:08 +08:00
midoks 79471e3806 Update receive_faq.py 2023-03-25 21:56:50 +08:00
midoks cad06425fc Update lib.sh 2023-03-23 15:24:49 +08:00
midoks 6f1e11e474 Update lib.sh 2023-03-23 15:21:22 +08:00
midoks 59d13e50ce Update rhel.sh 2023-03-22 22:26:32 +08:00
midoks 5da0746240 Update push_bbs_ntid.py 2023-03-22 18:00:32 +08:00
midoks 192ea8b029 Update push_bbs_ntid.py 2023-03-22 17:34:18 +08:00
midoks bfc20b3e42 Update push_tmp_msg.py 2023-03-22 17:01:50 +08:00
midoks 56bee5c752 Update push_tmp_msg.py 2023-03-22 16:41:26 +08:00
midoks 312df5de1f Create push_bbs_ntid.py 2023-03-22 16:41:23 +08:00
midoks 4d3640286c Update README.md 2023-03-20 17:49:48 +08:00
midoks 20930806b6 Update install.sh 2023-03-20 12:19:35 +08:00
midoks 71360b61da Update install.sh 2023-03-20 12:04:54 +08:00
midoks 411645c9e2 Update install.sh 2023-03-20 12:01:46 +08:00
midoks 3de4e1bfff up 2023-03-19 00:21:36 +08:00
midoks 34285f6051 Update push_tmp_msg.py 2023-03-19 00:20:23 +08:00
midoks 84f0cda89b up 2023-03-18 18:32:30 +08:00
midoks 04012085ce Update mdw.jpg 2023-03-17 19:18:27 +08:00
midoks 9ad00f3ce7 Update push_tmp_msg.py 2023-03-16 22:36:25 +08:00
midoks 609a4ed351 Update tgbot.py 2023-03-16 21:34:44 +08:00
midoks 5ca74fd312 Update push_tmp_msg.py 2023-03-16 19:22:36 +08:00
midoks 3b1bb06c68 Update push_tmp_msg.py 2023-03-16 18:57:09 +08:00
midoks b6b7de42d6 Update push_tmp_msg.py 2023-03-16 18:53:29 +08:00
midoks 3aa3b532ac Update push_tmp_msg.py 2023-03-16 18:48:19 +08:00
midoks 290c740ab1 Update push_tmp_msg.py 2023-03-16 18:43:02 +08:00
midoks 23fd4ca1de Create push_tmp_msg.py 2023-03-16 18:42:42 +08:00
midoks c128a799b2 Update receive_faq.py 2023-03-16 15:50:52 +08:00
midoks 401c103b76 Update receive_faq.py 2023-03-16 15:47:14 +08:00
midoks 6fb88eb428 Update push_ad.py 2023-03-16 15:33:18 +08:00
midoks 956f20d295 tgbot init命令分离 2023-03-16 15:30:43 +08:00
midoks 03f8578a37 Update README.md 2023-03-16 13:04:29 +08:00
Mr Chen 265e17beac Merge pull request #393 from midoks/dev
0.13.3
2023-03-16 13:00:56 +08:00
midoks f3d83ad8a5 Update README.md 2023-03-16 12:58:06 +08:00
midoks 39b376a7cb Update webstats_common.lua 2023-03-16 12:24:02 +08:00
midoks 07858794ef Update webstats_common.lua 2023-03-16 12:02:33 +08:00
midoks 391473fc14 Update lib.sh 2023-03-15 23:26:23 +08:00
midoks 0993adcc5f Update lib.sh 2023-03-15 23:24:47 +08:00
midoks 90b1d88111 Update lib.sh 2023-03-15 23:17:49 +08:00
midoks 87098cff95 up 2023-03-15 23:00:37 +08:00
midoks e6e64b2a4c Update mysql.js 2023-03-15 22:59:23 +08:00
midoks 81436ea81b Update index.html 2023-03-15 22:57:22 +08:00
midoks cf7d29190d Update index.html 2023-03-15 22:53:36 +08:00
midoks 4ff62ec6ad Update tgbot.py 2023-03-15 22:09:53 +08:00
midoks dac3ccce8d Update tgbot.py 2023-03-15 21:53:41 +08:00
midoks 10bd7aa70f Update tool_migrate.py 2023-03-15 18:28:31 +08:00
midoks dec0afc3d3 Update tool_migrate.py 2023-03-15 18:25:43 +08:00
midoks 2331853b3b Update info.json 2023-03-15 18:13:34 +08:00
midoks b9e063e423 Update README.md 2023-03-15 18:11:35 +08:00
midoks 52294948b2 Update config_api.py 2023-03-15 18:09:20 +08:00
midoks 87bec2b988 Update tgbot.py 2023-03-15 18:06:14 +08:00
midoks 9ab91ecc93 Update index.py 2023-03-15 17:48:05 +08:00
midoks 18312a3596 Update tgbot.py 2023-03-15 17:37:35 +08:00
midoks 8fb35440c8 Update info.json 2023-03-15 17:35:28 +08:00
midoks a874934379 Update receive_faq.py 2023-03-15 17:34:05 +08:00
midoks 2c4e4aea3f Update info.json 2023-03-15 17:22:36 +08:00
midoks 6b115261be up 2023-03-15 17:19:15 +08:00
midoks 059ce6228b Update receive_faq.py 2023-03-15 15:09:03 +08:00
midoks cfa396b4bb 更新 2023-03-14 20:03:53 +08:00
midoks 11e4b377ed up 2023-03-14 15:21:33 +08:00
midoks 31fe2aab92 Update receive_faq.py 2023-03-14 13:36:00 +08:00
midoks 19042a9088 Update receive_faq.py 2023-03-14 11:48:54 +08:00
midoks 2eb4543c3b Update receive_faq.py 2023-03-14 01:54:58 +08:00
midoks e33ccbfc7d Update tgbot.py 2023-03-14 01:54:08 +08:00
midoks ed8c9eed0a Update receive_faq.py 2023-03-14 01:50:56 +08:00
midoks 7163a7bbcf Update receive_faq.py 2023-03-14 01:46:19 +08:00
midoks 3f1c23ec8b Update receive_faq.py 2023-03-14 01:32:52 +08:00
midoks 3a6cb0ae2a Update receive_faq.py 2023-03-14 01:15:14 +08:00
midoks 936492d410 up 2023-03-14 01:10:04 +08:00
midoks 39d265aae7 Update tgbot.py 2023-03-14 00:15:27 +08:00
midoks 5a33098dd3 Update tgbot.py 2023-03-14 00:09:52 +08:00
midoks c9927c3fb9 tgbot加入扩展机制 2023-03-14 00:09:30 +08:00
midoks da90386816 Update tool_migrate.py 2023-03-13 11:29:00 +08:00
midoks 6be4c5977b up 2023-03-13 02:33:29 +08:00
midoks bbf93bfd9e up 2023-03-13 02:33:22 +08:00
midoks a2570af5f7 Update webstats_common.lua 2023-03-13 01:33:07 +08:00
midoks 77120cf31b up 2023-03-12 12:13:43 +08:00
midoks 395f449b93 Update webstats_common.lua 2023-03-12 12:09:53 +08:00
midoks 8be5f4aa7b Update info.json 2023-03-11 22:54:23 +08:00
midoks 3ccebf4f47 Update index.py 2023-03-11 22:48:42 +08:00
midoks 15d48accad Update tgbot.py 2023-03-11 22:43:15 +08:00
midoks d0045d831c Update tgbot.py 2023-03-11 22:42:39 +08:00
midoks a7cac3d671 up 2023-03-11 20:47:31 +08:00
midoks 7bc7fdecae Update webstats_common.lua 2023-03-11 16:40:45 +08:00
midoks 480663e2ad Update tools.py 2023-03-11 15:41:15 +08:00
midoks 2290efd060 Update config_api.py 2023-03-11 15:36:11 +08:00
midoks dece5a0532 Update config_api.py 2023-03-11 15:30:16 +08:00
midoks b0a44d24d4 Update config_api.py 2023-03-11 15:28:13 +08:00
midoks d092d9f5f2 up 2023-03-11 15:24:40 +08:00
midoks 944b3e779c Update config_api.py 2023-03-11 15:21:43 +08:00
midoks 55dc2715e9 Update config_api.py 2023-03-11 15:20:13 +08:00
midoks 84bf3abd5d Update config_api.py 2023-03-11 15:15:49 +08:00
midoks 00c9157f9b up 2023-03-11 15:15:27 +08:00
midoks faa95b0d88 Update config_api.py 2023-03-11 15:07:06 +08:00
midoks 52d0b3c940 Update config_api.py 2023-03-11 15:04:20 +08:00
midoks 0141028d41 Update config_api.py 2023-03-11 15:02:15 +08:00
midoks 9e6bf08a72 Update config_api.py 2023-03-11 15:01:46 +08:00
midoks 49ff9750cb Update config_api.py 2023-03-11 14:58:18 +08:00
midoks 75b2b4dbc2 Update config_api.py 2023-03-11 14:56:43 +08:00
midoks 667c60dda0 Update config.js 2023-03-11 14:55:48 +08:00
midoks aa6818f953 Update config_api.py 2023-03-11 14:52:58 +08:00
midoks 6f884fe60a panel ssl https 功能添加 2023-03-11 14:48:38 +08:00
midoks a56d53c672 Update config_api.py 2023-03-11 14:29:28 +08:00
midoks 00b1788172 up 2023-03-11 14:26:22 +08:00
midoks cee268fcbc Update config_api.py 2023-03-11 13:56:20 +08:00
midoks 40dd929823 Update config_api.py 2023-03-11 13:47:16 +08:00
midoks b59949e181 Update config_api.py 2023-03-11 13:41:36 +08:00
midoks 9c5975253a Update cert_api.py 2023-03-11 13:23:30 +08:00
midoks 62003b987a Update discuzx.conf 2023-03-10 14:12:27 +08:00
midoks df0a454c3a up 2023-03-10 14:09:40 +08:00
midoks 02048c3265 Update webstats_common.lua 2023-03-10 13:19:58 +08:00
midoks 65649d171d Update tgbot.py 2023-03-09 19:11:51 +08:00
midoks a136da6ec2 Update tgbot.py 2023-03-09 17:23:28 +08:00
midoks 3b25ca7e60 Update tgbot.py 2023-03-09 16:28:11 +08:00
midoks c5cf8f8afb Update info.json 2023-03-09 15:40:54 +08:00
midoks 89f7d464ab Update info.json 2023-03-09 15:28:00 +08:00
midoks 4cac6d1921 Update info.json 2023-03-09 15:25:37 +08:00
midoks dca5c82d2f Update webstats_common.lua 2023-03-09 14:56:43 +08:00
midoks 08988130b5 Update config_api.py 2023-03-09 03:00:30 +08:00
Mr Chen 8849001384 Merge pull request #392 from midoks/dev
升级图表echarts
2023-03-09 02:49:57 +08:00
midoks ae0a6b5079 升级图表echarts 2023-03-09 02:44:57 +08:00
Mr Chen d6c6ae5561 Merge pull request #391 from midoks/dev
0.13.2
2023-03-09 01:49:10 +08:00
midoks a6dc15f22d 0.13.2
* supervisor添加重启功能。
* 加入滚动写入日志 mw.writeFileLog方法。
* mysql导出优化优化。
* 添加tgbot插件[仅测试]。
* TelegramBot机器人通知-加入配置。
* mariadb更新版本。
* 在线文件编辑优化。
2023-03-09 01:47:35 +08:00
midoks 360b962bd2 Update mw.py 2023-03-09 01:42:55 +08:00
midoks 37d37e0f1d Update task.py 2023-03-09 01:32:05 +08:00
midoks ddc6da9172 Update mw.py 2023-03-09 01:30:19 +08:00
midoks ceba7ab673 up 2023-03-09 01:26:39 +08:00
midoks 384704b8e5 Update mw.py 2023-03-09 01:10:04 +08:00
midoks 232d0c2f74 Update mw.py 2023-03-09 01:01:00 +08:00
midoks ef8e6f07f5 Update mw.py 2023-03-09 00:43:34 +08:00
midoks 435e565559 Update mw.py 2023-03-09 00:42:15 +08:00
midoks ec9d7e337d Update mw.py 2023-03-09 00:36:46 +08:00
midoks b5c7a2a778 Update task.py 2023-03-09 00:32:23 +08:00
midoks 72d9c9b761 Update task.py 2023-03-09 00:28:59 +08:00
midoks 30812e1fba Update task.py 2023-03-09 00:08:49 +08:00
midoks c95cb07e8d Update task.py 2023-03-09 00:05:45 +08:00
midoks f3f2ea8ef0 通知限制频率 2023-03-08 19:40:23 +08:00
midoks 9e5a5192cb Update mw.py 2023-03-08 18:02:30 +08:00
midoks 271b3d448c Update mw.py 2023-03-08 18:01:06 +08:00
midoks b7424e7195 Update config_api.py 2023-03-08 17:57:23 +08:00
midoks b607527e1f Update config_api.py 2023-03-08 17:56:18 +08:00
midoks 3c42a4e450 对通知配置进行加密处理 2023-03-08 17:56:07 +08:00
midoks b11fd9508a Update .gitignore 2023-03-08 17:29:42 +08:00
midoks dc0504cf24 Delete notify.json 2023-03-08 17:25:12 +08:00
midoks 1d8b82395f Update public.js 2023-03-08 16:25:30 +08:00
midoks 39ac55760e Update config_api.py 2023-03-08 16:20:02 +08:00
midoks ef6071956d 在线文件编辑优化 2023-03-08 16:14:28 +08:00
midoks bbbe1c84ce Update mw.py 2023-03-07 19:24:03 +08:00
midoks 064252daad Update config.html 2023-03-07 19:20:07 +08:00
midoks 3cb63c6265 Update index.html 2023-03-07 16:28:48 +08:00
midoks b541abad42 Update index.py 2023-03-07 13:44:28 +08:00
midoks 547027be0d Update install.sh 2023-03-06 23:40:56 +08:00
midoks d786b2524a up 2023-03-06 23:21:55 +08:00
midoks abac345628 Update info.json 2023-03-06 23:10:12 +08:00
midoks d4290cbdd2 mariadb更新版本 2023-03-06 22:29:20 +08:00
midoks cfd2d99e24 Update mw.py 2023-03-06 21:31:24 +08:00
midoks 28437ccfb0 Update mw.py 2023-03-06 21:30:18 +08:00
midoks 43bf755609 Update mw.py 2023-03-06 20:35:06 +08:00
midoks de225fc8b9 0.13.1.2 2023-03-06 20:28:29 +08:00
midoks 44f891f7a3 Update mw.py 2023-03-06 20:12:52 +08:00
midoks 64d1387b03 Telegram Bot机器人通知 加入配置 2023-03-06 19:32:36 +08:00
midoks 51ccbefb04 up 2023-03-06 17:15:41 +08:00
midoks 29e3017e51 up 2023-03-06 16:49:42 +08:00
midoks 197e2d80c6 Update tgbot.py 2023-03-06 16:42:29 +08:00
midoks b8f04043bc Update tgbot.service.tpl 2023-03-06 16:41:25 +08:00
midoks 2ed70b4b96 Update tgbot.py 2023-03-06 16:39:27 +08:00
midoks d056c37be5 Update index.py 2023-03-06 16:33:18 +08:00
midoks e75abae4b9 Update tgbot.service.tpl 2023-03-06 16:32:05 +08:00
midoks 3e695770d7 Update config_api.py 2023-03-06 16:26:49 +08:00
midoks 7301edbc5a 添加tgbot插件
现在只是为了获取chat_id
2023-03-06 16:19:13 +08:00
Mr Chen 704b256408 Merge pull request #390 from midoks/dev
网站统计优化
2023-03-05 18:36:57 +08:00
midoks e129051a06 Update webstats_common.lua 2023-03-05 18:34:35 +08:00
Mr Chen d38e9f7ad0 Merge pull request #389 from midoks/dev
OP防火墙优化
2023-03-05 18:07:54 +08:00
midoks c696742866 Update init.lua 2023-03-05 18:03:41 +08:00
midoks 046389df99 Update init.lua 2023-03-05 17:37:01 +08:00
midoks 3e244ed227 导出优化 2023-03-05 14:04:16 +08:00
midoks 5016aedb0f Update index.py 2023-03-05 02:08:04 +08:00
midoks c1cd45a5f3 Update my8.0.cnf 2023-03-05 00:00:59 +08:00
midoks 79c9865a5d Update index.py 2023-03-04 23:53:54 +08:00
midoks 4082f29424 加入滚动写入日志 2023-03-04 23:07:23 +08:00
midoks d777a29d8c Update update.sh 2023-03-04 21:47:12 +08:00
Mr Chen 04e43e051e Merge pull request #388 from midoks/dev
局部优化
2023-03-02 16:57:17 +08:00
midoks dffe9a77e7 Update layout.html 2023-03-02 00:57:02 +08:00
midoks 1b1462586e Update orm.py 2023-03-02 00:49:44 +08:00
midoks f11d2db761 添加重启功能 2023-03-01 18:41:32 +08:00
midoks 842c16540a Update index.py 2023-03-01 18:03:14 +08:00
midoks 614cc1032f Update webstats_log.lua 2023-03-01 14:03:46 +08:00
midoks ad46b2050e Update config.json 2023-03-01 01:40:57 +08:00
midoks 8109989927 Update layout.html 2023-02-28 19:41:13 +08:00
Mr Chen 9d9b39dfe2 Merge pull request #387 from midoks/dev
0.13.1
2023-02-28 19:11:06 +08:00
midoks 422514c40a 0.13.1
* 关闭issue,建立bbs.midoks.me。问题集中处理,发挥群众的力量。
* 添加站操作回调钩子site_cb。 网站统计和OP防火墙不再手动重载配置
* 修复ubuntu20 pureftp 安装时,端口没有加入安全里
* 增加global_static hook关键字,并优化menu的文件加载hook
* 各种细节优化。
2023-02-28 19:09:54 +08:00
midoks 632568643b Update site_api.py 2023-02-28 17:08:26 +08:00
midoks a5f29a2a6a Update cert_api.py 2023-02-28 16:26:31 +08:00
midoks b02705aa5a up 2023-02-28 03:00:46 +08:00
midoks 1f9ab560e3 Update files.js 2023-02-28 02:18:39 +08:00
midoks b3970326cd Update index.py 2023-02-28 01:57:19 +08:00
midoks f6d008e0b6 Update index.py 2023-02-28 01:50:54 +08:00
midoks 6f9a49ad7a up 2023-02-28 01:48:51 +08:00
midoks fc3c7d334a Update public.js 2023-02-28 00:17:39 +08:00
midoks 1030d1b923 site_cb 添加站操作回调钩子。 网站统计和OP防火墙不再手动重载配置 2023-02-28 00:02:16 +08:00
midoks 94d4a90bcc Update webstats_common.lua 2023-02-27 19:35:52 +08:00
midoks da4b872666 Update README.md 2023-02-27 17:57:17 +08:00
midoks cf15b19f4b Update install.sh 2023-02-26 21:46:25 +08:00
midoks aa9cdaada4 Update commit.tpl 2023-02-26 03:16:45 +08:00
midoks 659c9fe16b 修复ubuntu 20 pureftp 安装时,端口没有加入安全里 2023-02-26 02:20:06 +08:00
midoks 2b8c6d6e43 Update firewall_api.py 2023-02-26 01:39:52 +08:00
midoks 263f83088f Update firewall_api.py 2023-02-26 01:38:55 +08:00
midoks 374c938ac0 Update firewall_api.py 2023-02-26 01:38:32 +08:00
midoks 6aa73b0cae Update firewall_api.py 2023-02-26 01:36:45 +08:00
midoks 7f731ae06f Update README.md 2023-02-26 01:12:08 +08:00
midoks f87aff704c Update rhel.sh 2023-02-25 23:36:14 +08:00
midoks be9fa87133 Update rhel.sh 2023-02-25 23:31:36 +08:00
midoks de6fc19dee Create discuz.conf 2023-02-25 21:33:50 +08:00
midoks 3987c6d3dc Update config_api.py 2023-02-25 08:37:26 +08:00
midoks 96875052cd Update index.py 2023-02-25 08:25:05 +08:00
midoks 583de57f96 Update plugins_api.py 2023-02-25 08:21:20 +08:00
midoks 41b7245f03 Update plugins_api.py 2023-02-25 08:15:38 +08:00
midoks ee3684706f Update info.json 2023-02-25 07:48:32 +08:00
midoks 07936dfb81 update 2023-02-25 07:35:46 +08:00
midoks 5c46202be0 增加global_static hook关键字,并优化menu的文件加载hook
"hook":[
		{
			"tag":"global_static",
			"global_static": {
				"css_path":"menu/own_style.css",
				"js_path":"js/own_style.js"
			}
		}
	],
2023-02-25 07:26:48 +08:00
midoks 7123a15457 Update install.sh 2023-02-24 18:08:46 +08:00
midoks 4aeb45b1d5 Update install.sh 2023-02-24 17:55:13 +08:00
midoks 006a62be22 Update lib.sh 2023-02-24 17:25:04 +08:00
midoks 1e91d11125 Update mw.tpl 2023-02-24 17:22:22 +08:00
midoks 99fb4aa723 up 2023-02-24 17:14:28 +08:00
midoks 5c5bbb2da2 up 2023-02-24 17:12:31 +08:00
midoks 8b05045901 Update install.sh 2023-02-24 17:07:24 +08:00
midoks 1b73439525 Update install_dev.sh 2023-02-24 17:00:10 +08:00
midoks ec51ad016a Update install_dev.sh 2023-02-24 16:57:24 +08:00
midoks a42fae66ac Update install_dev.sh 2023-02-24 16:53:48 +08:00
midoks b4c635c2e5 Update install_dev.sh 2023-02-24 16:49:03 +08:00
midoks 9802bc5915 Update pure-ftpd.conf 2023-02-24 13:29:16 +08:00
226 changed files with 16721 additions and 1223 deletions
+16
View File
@@ -0,0 +1,16 @@
name: sync2gitee
on: [push]
jobs:
repo-sync:
runs-on: ubuntu-latest
steps:
- name: Mirror the Github organization repos to Gitee.
uses: Yikun/hub-mirror-action@master
with:
src: 'github/midoks'
dst: 'gitee/midoks'
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
dst_token: ${{ secrets.GITEE_TOKEN }}
static_list: "mdserver-web"
force_update: true
+7 -4
View File
@@ -151,18 +151,18 @@ data/system.db-journal
data/hook_*.json data/hook_*.json
data/letsencrypt.json data/letsencrypt.json
data/basic_auth.json data/basic_auth.json
data/notify.json
data/api.json data/api.json
data/bind_domain.pl data/bind_domain.pl
data/unauthorized_status.pl
plugins/vip_* plugins/vip_*
plugins/own_* plugins/own_*
plugins/my_* plugins/my_*
plugins/l2tp plugins/l2tp
plugins/openlitespeed plugins/openlitespeed
plugins/system_safe
plugins/tamper_proof plugins/tamper_proof
plugins/tamper_proof_* plugins/cryptocurrency_trade
plugins/op_load_balance
plugins/gdrive plugins/gdrive
plugins/mtproxy plugins/mtproxy
plugins/zimg plugins/zimg
@@ -175,4 +175,7 @@ plugins/file_search
debug.out debug.out
data/unauthorized_status.pl
mdioks.session-journal
*.session
+25 -22
View File
@@ -29,6 +29,7 @@
基本上可以使用,后续会继续优化!欢迎提供意见! 基本上可以使用,后续会继续优化!欢迎提供意见!
- 吹水组 - https://t.me/mdserver_web - 吹水组 - https://t.me/mdserver_web
- 交流论坛 - https://bbs.midoks.me
``` ```
如果出现问题,最好私给我面板信息。不要让我猜。如果不提供,不要提出问题,自行解决。 — 座右铭 如果出现问题,最好私给我面板信息。不要让我猜。如果不提供,不要提出问题,自行解决。 — 座右铭
@@ -78,7 +79,7 @@ PHP[72-82]支持phpMyAdmin[5.2.0]
# 特别赞助 # 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.la/) - [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.pw/)
# AD - VPS推荐 - 🙏 # AD - VPS推荐 - 🙏
@@ -87,6 +88,7 @@ PHP[72-82]支持phpMyAdmin[5.2.0]
| 服务商 | LOGO | 推广地址 | 优惠码 | | 服务商 | 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 | | 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 |
| mvirtua |[![mvirtua](https://mvirtua.com/upload/logo-black.png)](https://mvirtua.com/aff/FUSKXVDH) | https://mvirtua.com/aff/FUSKXVDH | mdserver-web (全场8折)|
# Docker # Docker
@@ -98,33 +100,34 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
``` ```
### 版本更新 0.13.0 ### 版本更新 0.15.2
* 一键迁移插件。 * OpenResty升级到1.21.4.2
* 修复acme ssl申请。 * 计划任务自动脚本运行时间
* IP识别优化。 * rsyncd添加优化
* 解决删除站点残留的问题。 * 使用mariadb二进制导入备份文件
* 各种细节优化。 * docker插件-镜像导入导出功能
* 网站设置反向代理升级功能
* 优化初始化安装SSH端口识别
### JSDelivr安装地址 ### JSDelivr安装地址
- 初始安装 - 初始安装
``` ```
curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh | bash curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh | bash
``` ```
- 直接更新 - 直接更新
``` ```
curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh | bash curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh | bash
``` ```
- 卸载脚本 - 卸载脚本
``` ```
wget -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/uninstall.sh && bash uninstall.sh wget --no-check-certificate -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/uninstall.sh && bash uninstall.sh
``` ```
### 备用地址 ### 备用地址
@@ -132,20 +135,20 @@ wget -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scri
- 初始安装 - 初始安装
``` ```
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | bash curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | bash
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install.sh | bash curl --insecure -fsSL https://code.midoks.me/midoks/mdserver-web/raw/branch/master/scripts/install.sh | bash
``` ```
- 直接更新 - 直接更新
``` ```
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash
``` ```
- 卸载脚本 - 卸载脚本
``` ```
wget -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/uninstall.sh && bash uninstall.sh wget --no-check-certificate -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/uninstall.sh && bash uninstall.sh
``` ```
@@ -154,22 +157,22 @@ wget -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/maste
- 需已经安装mdserver-web - 需已经安装mdserver-web
``` ```
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/app.sh | bash curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/app.sh | bash
``` ```
### DEV使用 ### DEV使用
``` ```
curl -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/install_dev.sh | bash
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
wget -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/uninstall.sh && bash uninstall.sh wget --no-check-certificate -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/uninstall.sh && bash uninstall.sh
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh | bash curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh | bash
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/install_dev.sh | bash curl --insecure -fsSL https://code.midoks.me/midoks/mdserver-web/raw/branch/dev/scripts/install_dev.sh | bash
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash curl --insecure -fsSL https://code.midoks.me/midoks/mdserver-web/raw/branch/dev/scripts/update_dev.sh | bash
``` ```
### 捐赠地址 USDT(TRC20) ### 捐赠地址 USDT(TRC20)
+1
View File
@@ -28,6 +28,7 @@ from route import app, socketio
from gevent.pywsgi import WSGIServer from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler from geventwebsocket.handler import WebSocketHandler
from gevent import monkey from gevent import monkey
monkey.patch_all() monkey.patch_all()
+10 -10
View File
@@ -371,8 +371,7 @@ fi
response = urllib.request.urlopen(req, timeout=timeout) response = urllib.request.urlopen(req, timeout=timeout)
return response return response
except Exception as ex: except Exception as ex:
# self.getError()
self.getError()
raise Exception("requestsPost: {}".format(self.getError(str(ex)))) raise Exception("requestsPost: {}".format(self.getError(str(ex))))
def getRequestJson(self, response): def getRequestJson(self, response):
@@ -931,7 +930,8 @@ fi
index).encode() index).encode()
) )
X509Req.set_pubkey(pk) X509Req.set_pubkey(pk)
X509Req.set_version(2) # X509Req.set_version(2)
X509Req.set_version(0)
X509Req.sign(pk, self.__digest) X509Req.sign(pk, self.__digest)
return OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_ASN1, X509Req) return OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_ASN1, X509Req)
@@ -1007,7 +1007,7 @@ fi
try: try:
result = {} result = {}
x509 = OpenSSL.crypto.load_certificate( x509 = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM, public.readFile(pem_file)) OpenSSL.crypto.FILETYPE_PEM, mw.readFile(pem_file))
# 取产品名称 # 取产品名称
issuer = x509.get_issuer() issuer = x509.get_issuer()
result['issuer'] = '' result['issuer'] = ''
@@ -1281,16 +1281,16 @@ fullchain.pem 粘贴到证书输入框
# 获取当前正在使用此证书的网站目录 # 获取当前正在使用此证书的网站目录
def getSslUsedSite(self, save_path): def getSslUsedSite(self, save_path):
pkey_file = '{}/privkey.pem'.format(save_path) pkey_file = '{}/privkey.pem'.format(save_path)
pkey = public.readFile(pkey_file) pkey = mw.readFile(pkey_file)
if not pkey: if not pkey:
return False return False
cert_paths = 'vhost/cert' cert_paths = 'vhost/cert'
import panelSite import panelSite
args = public.dict_obj() args = mw.dict_obj()
args.siteName = '' args.siteName = ''
for c_name in os.listdir(cert_paths): for c_name in os.listdir(cert_paths):
skey_file = '{}/{}/privkey.pem'.format(cert_paths, c_name) skey_file = '{}/{}/privkey.pem'.format(cert_paths, c_name)
skey = public.readFile(skey_file) skey = mw.readFile(skey_file)
if not skey: if not skey:
continue continue
if skey == pkey: if skey == pkey:
@@ -1298,7 +1298,7 @@ fullchain.pem 粘贴到证书输入框
run_path = panelSite.panelSite().GetRunPath(args) run_path = panelSite.panelSite().GetRunPath(args)
if not run_path: if not run_path:
continue continue
sitePath = public.M('sites').where( sitePath = mw.M('sites').where(
'name=?', c_name).getField('path') 'name=?', c_name).getField('path')
if not sitePath: if not sitePath:
continue continue
@@ -1316,7 +1316,7 @@ fullchain.pem 粘贴到证书输入框
self.__config['orders'] = {} self.__config['orders'] = {}
import panelSite import panelSite
siteObj = panelSite.panelSite() siteObj = panelSite.panelSite()
args = public.dict_obj() args = mw.dict_obj()
for siteName in os.listdir(cert_path): for siteName in os.listdir(cert_path):
try: try:
cert_file = '{}/{}/fullchain.pem'.format(cert_path, siteName) cert_file = '{}/{}/fullchain.pem'.format(cert_path, siteName)
@@ -1522,7 +1522,7 @@ fullchain.pem 粘贴到证书输入框
self.__config['orders'][i]['auth_to'] = auth_to self.__config['orders'][i]['auth_to'] = auth_to
# 是否到了允许重试的时间 # 是否到了允许重试的时间
if 'next_retry_time' in self._config['orders'][i]: if 'next_retry_time' in self.__config['orders'][i]:
timeout = self.__config['orders'][i][ timeout = self.__config['orders'][i][
'next_retry_time'] - int(time.time()) 'next_retry_time'] - int(time.time())
if timeout > 0: if timeout > 0:
+8 -7
View File
@@ -840,7 +840,8 @@ class cert_request:
index).encode() index).encode()
) )
X509Req.set_pubkey(pk) X509Req.set_pubkey(pk)
X509Req.set_version(2) # X509Req.set_version(2)
X509Req.set_version(0)
X509Req.sign(pk, self.__digest) X509Req.sign(pk, self.__digest)
return OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_ASN1, X509Req) return OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_ASN1, X509Req)
@@ -916,7 +917,7 @@ class cert_request:
try: try:
result = {} result = {}
x509 = OpenSSL.crypto.load_certificate( x509 = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM, public.readFile(pem_file)) OpenSSL.crypto.FILETYPE_PEM, mw.readFile(pem_file))
# 取产品名称 # 取产品名称
issuer = x509.get_issuer() issuer = x509.get_issuer()
result['issuer'] = '' result['issuer'] = ''
@@ -1186,16 +1187,16 @@ fullchain.pem 粘贴到证书输入框
# 获取当前正在使用此证书的网站目录 # 获取当前正在使用此证书的网站目录
def getSslUsedSite(self, save_path): def getSslUsedSite(self, save_path):
pkey_file = '{}/privkey.pem'.format(save_path) pkey_file = '{}/privkey.pem'.format(save_path)
pkey = public.readFile(pkey_file) pkey = mw.readFile(pkey_file)
if not pkey: if not pkey:
return False return False
cert_paths = 'vhost/cert' cert_paths = 'vhost/cert'
import panelSite import panelSite
args = public.dict_obj() args = mw.dict_obj()
args.siteName = '' args.siteName = ''
for c_name in os.listdir(cert_paths): for c_name in os.listdir(cert_paths):
skey_file = '{}/{}/privkey.pem'.format(cert_paths, c_name) skey_file = '{}/{}/privkey.pem'.format(cert_paths, c_name)
skey = public.readFile(skey_file) skey = mw.readFile(skey_file)
if not skey: if not skey:
continue continue
if skey == pkey: if skey == pkey:
@@ -1203,7 +1204,7 @@ fullchain.pem 粘贴到证书输入框
run_path = panelSite.panelSite().GetRunPath(args) run_path = panelSite.panelSite().GetRunPath(args)
if not run_path: if not run_path:
continue continue
sitePath = public.M('sites').where( sitePath = mw.M('sites').where(
'name=?', c_name).getField('path') 'name=?', c_name).getField('path')
if not sitePath: if not sitePath:
continue continue
@@ -1221,7 +1222,7 @@ fullchain.pem 粘贴到证书输入框
self.__config['orders'] = {} self.__config['orders'] = {}
import panelSite import panelSite
siteObj = panelSite.panelSite() siteObj = panelSite.panelSite()
args = public.dict_obj() args = mw.dict_obj()
for siteName in os.listdir(cert_path): for siteName in os.listdir(cert_path):
try: try:
cert_file = '{}/{}/fullchain.pem'.format(cert_path, siteName) cert_file = '{}/{}/fullchain.pem'.format(cert_path, siteName)
+12
View File
@@ -33,6 +33,7 @@ from flask import redirect
def init(): def init():
initDB() initDB()
initDBSshPort()
initUserInfo() initUserInfo()
initInitD() initInitD()
initInitTask() initInitTask()
@@ -62,6 +63,17 @@ def initDB():
print(str(ex)) print(str(ex))
def initDBSshPort():
# SSH端口必须放开
import firewall_api
cmd_data = mw.execShell(
"cat /etc/ssh/sshd_config | grep '^Port \d*' | tail -1")
ssh_port = cmd_data[0].replace("Port ", '').strip()
if ssh_port == '':
ssh_port = '22'
firewall_api.firewall_api().addAcceptPortArgs(ssh_port, 'SSH远程管理服务', 'port')
def doContentReplace(src, dst): def doContentReplace(src, dst):
content = mw.readFile(src) content = mw.readFile(src)
content = content.replace("{$SERVER_PATH}", mw.getRunDir()) content = content.replace("{$SERVER_PATH}", mw.getRunDir())
+183 -7
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api: class config_api:
__version = '0.13.0' __version = '0.15.2'
__api_addr = 'data/api.json' __api_addr = 'data/api.json'
def __init__(self): def __init__(self):
@@ -348,7 +348,23 @@ class config_api:
keyPath = 'ssl/private.pem' keyPath = 'ssl/private.pem'
certPath = 'ssl/cert.pem' certPath = 'ssl/cert.pem'
if not os.path.exists(certPath): if not os.path.exists(certPath):
mw.createSSL() # 不再自动生成证书
# mw.createSSL()
cert['privateKey'] = ''
cert['is_https'] = ''
cert['certPem'] = ''
cert['rep'] = os.path.exists('ssl/input.pl')
cert['info'] = {'endtime': 0, 'subject': '无',
'notAfter': '无', 'notBefore': '无', 'issuer': '无'}
return cert
panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if not os.path.exists(panel_ssl):
cert['is_https'] = ''
else:
ssl_data = mw.readFile(panel_ssl)
if ssl_data.find('$server_port !~ 443') != -1:
cert['is_https'] = 'checked'
cert['privateKey'] = mw.readFile(keyPath) cert['privateKey'] = mw.readFile(keyPath)
cert['certPem'] = mw.readFile(certPath) cert['certPem'] = mw.readFile(certPath)
@@ -380,13 +396,86 @@ class config_api:
mw.writeFile('ssl/input.pl', 'True') mw.writeFile('ssl/input.pl', 'True')
return mw.returnJson(True, '证书已保存!') return mw.returnJson(True, '证书已保存!')
# 设置面板SSL证书设置
def setPanelHttpToHttpsApi(self):
bind_domain = 'data/bind_domain.pl'
if not os.path.exists(bind_domain):
return mw.returnJson(False, '先要绑定域名!')
keyPath = 'ssl/private.pem'
if not os.path.exists(keyPath):
return mw.returnJson(False, '未申请SSL证书!')
is_https = request.form.get('https', '').strip()
panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if not os.path.exists(panel_ssl):
return mw.returnJson(False, '未开启面板SSL!')
if is_https == 'false':
conf = mw.readFile(panel_ssl)
if conf:
if conf.find('ssl_certificate') == -1:
return mw.returnJson(False, '当前未开启SSL')
to = "#error_page 404/404.html;\n\
#HTTP_TO_HTTPS_START\n\
if ($server_port !~ 443){\n\
rewrite ^(/.*)$ https://$host$1 permanent;\n\
}\n\
#HTTP_TO_HTTPS_END"
conf = conf.replace('#error_page 404/404.html;', to)
mw.writeFile(panel_ssl, conf)
else:
conf = mw.readFile(panel_ssl)
if conf:
rep = "\n\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
conf = re.sub(rep, '', conf)
rep = "\s+if.+server_port.+\n.+\n\s+\s*}"
conf = re.sub(rep, '', conf)
mw.writeFile(panel_ssl, conf)
mw.restartWeb()
action = '开启'
if is_https == 'true':
action = '关闭'
return mw.returnJson(True, action + 'HTTPS跳转成功!')
# 删除面板证书
def delPanelSslApi(self):
bind_domain = 'data/bind_domain.pl'
if not os.path.exists(bind_domain):
return mw.returnJson(False, '未绑定域名!')
siteName = mw.readFile(bind_domain).strip()
src_letpath = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
dst_letpath = mw.getRunDir() + '/ssl'
dst_csrpath = dst_letpath + '/cert.pem'
dst_keypath = dst_letpath + '/private.pem'
if os.path.exists(src_letpath) or os.path.exists(dst_csrpath):
if os.path.exists(src_letpath):
mw.execShell('rm -rf ' + src_letpath)
if os.path.exists(dst_csrpath):
mw.execShell('rm -rf ' + dst_csrpath)
if os.path.exists(dst_keypath):
mw.execShell('rm -rf ' + dst_keypath)
# mw.restartWeb()
return mw.returnJson(True, '已经删除SSL!')
# mw.restartWeb()
return mw.returnJson(False, '已经不存在SSL!')
# 申请面板let证书 # 申请面板let证书
def applyPanelLetSslApi(self): def applyPanelLetSslApi(self):
# check domain is bind? # check domain is bind?
bind_domain = 'data/bind_domain.pl' bind_domain = 'data/bind_domain.pl'
if not os.path.exists(bind_domain): if not os.path.exists(bind_domain):
return mw.returnJson(False, '未绑定域名!') return mw.returnJson(False, '先要绑定域名!')
siteName = mw.readFile(bind_domain).strip() siteName = mw.readFile(bind_domain).strip()
auth_to = mw.getRunDir() + "/tmp" auth_to = mw.getRunDir() + "/tmp"
@@ -404,6 +493,8 @@ class config_api:
dst_csrpath = dst_letpath + '/cert.pem' dst_csrpath = dst_letpath + '/cert.pem'
dst_keypath = dst_letpath + '/private.pem' dst_keypath = dst_letpath + '/private.pem'
is_already_apply = False
if not os.path.exists(src_letpath): if not os.path.exists(src_letpath):
import cert_api import cert_api
data = cert_api.cert_api().applyCertApi(to_args) data = cert_api.cert_api().applyCertApi(to_args)
@@ -415,6 +506,8 @@ class config_api:
msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[ msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>' 'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
return mw.returnJson(data['status'], msg, data['msg']) return mw.returnJson(data['status'], msg, data['msg'])
else:
is_already_apply = True
mw.buildSoftLink(src_csrpath, dst_csrpath, True) mw.buildSoftLink(src_csrpath, dst_csrpath, True)
mw.buildSoftLink(src_keypath, dst_keypath, True) mw.buildSoftLink(src_keypath, dst_keypath, True)
@@ -426,6 +519,9 @@ class config_api:
if os.path.exists(tmp_well_know): if os.path.exists(tmp_well_know):
mw.execShell('rm -rf ' + tmp_well_know) mw.execShell('rm -rf ' + tmp_well_know)
if is_already_apply:
return mw.returnJson(True, '重复申请!', data)
return mw.returnJson(True, '申请成功!', data) return mw.returnJson(True, '申请成功!', data)
def setPanelDomainApi(self): def setPanelDomainApi(self):
@@ -509,8 +605,6 @@ class config_api:
return mw.returnJson(True, 'SSL已关闭,请使用http协议访问面板!') return mw.returnJson(True, 'SSL已关闭,请使用http协议访问面板!')
else: else:
try: try:
if not os.path.exists('ssl/input.ssl'):
mw.createSSL()
mw.writeFile(sslConf, 'True') mw.writeFile(sslConf, 'True')
keyPath = mw.getRunDir() + '/ssl/private.pem' keyPath = mw.getRunDir() + '/ssl/private.pem'
@@ -661,6 +755,67 @@ class config_api:
mw.writeLog('面板设置', '将未授权响应状态码设置为:{}'.format(status_code)) mw.writeLog('面板设置', '将未授权响应状态码设置为:{}'.format(status_code))
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
def getNotifyApi(self):
# 获取
data = mw.getNotifyData(True)
return mw.returnData(True, 'ok', data)
def setNotifyApi(self):
tag = request.form.get('tag', '').strip()
data = request.form.get('data', '').strip()
cfg = mw.getNotifyData(False)
crypt_data = mw.enDoubleCrypt(tag, data)
if tag in cfg:
cfg[tag]['cfg'] = crypt_data
else:
t = {'cfg': crypt_data}
cfg[tag] = t
mw.writeNotify(cfg)
return mw.returnData(True, '设置成功')
def setNotifyTestApi(self):
# 异步通知验证
tag = request.form.get('tag', '').strip()
tag_data = request.form.get('data', '').strip()
if tag == 'tgbot':
t = json.loads(tag_data)
test_bool = mw.tgbotNotifyTest(t['app_token'], t['chat_id'])
if test_bool:
return mw.returnData(True, '验证成功')
return mw.returnData(False, '验证失败')
if tag == 'email':
t = json.loads(tag_data)
test_bool = mw.emailNotifyTest(t)
if test_bool:
return mw.returnData(True, '验证成功')
return mw.returnData(False, '验证失败')
return mw.returnData(False, '暂时未支持该验证')
def setNotifyEnableApi(self):
# 异步通知验证
tag = request.form.get('tag', '').strip()
tag_enable = request.form.get('enable', '').strip()
data = mw.getNotifyData(False)
op_enable = True
op_action = '开启'
if tag_enable != 'true':
op_enable = False
op_action = '关闭'
if tag in data:
data[tag]['enable'] = op_enable
mw.writeNotify(data)
return mw.returnData(True, op_action + '成功')
def getPanelTokenApi(self): def getPanelTokenApi(self):
api_file = self.__api_addr api_file = self.__api_addr
tmp = mw.readFile(api_file) tmp = mw.readFile(api_file)
@@ -824,7 +979,9 @@ class config_api:
data['username'] = mw.M('users').where( data['username'] = mw.M('users').where(
"id=?", (1,)).getField('username') "id=?", (1,)).getField('username')
# databases hook 获取 data['hook_tag'] = request.args.get('tag', '')
# databases hook
database_hook_file = 'data/hook_database.json' database_hook_file = 'data/hook_database.json'
if os.path.exists(database_hook_file): if os.path.exists(database_hook_file):
df = mw.readFile(database_hook_file) df = mw.readFile(database_hook_file)
@@ -833,7 +990,7 @@ class config_api:
else: else:
data['hook_database'] = [] data['hook_database'] = []
# menu hook 获取 # menu hook
menu_hook_file = 'data/hook_menu.json' menu_hook_file = 'data/hook_menu.json'
if os.path.exists(menu_hook_file): if os.path.exists(menu_hook_file):
df = mw.readFile(menu_hook_file) df = mw.readFile(menu_hook_file)
@@ -842,4 +999,23 @@ class config_api:
else: else:
data['hook_menu'] = [] data['hook_menu'] = []
# global_static hook
global_static_hook_file = 'data/hook_global_static.json'
if os.path.exists(global_static_hook_file):
df = mw.readFile(global_static_hook_file)
df = json.loads(df)
data['hook_global_static'] = df
else:
data['hook_global_static'] = []
# notiy config
notify_data = mw.getNotifyData(True)
notify_tag_list = ['tgbot', 'email']
for tag in notify_tag_list:
new_tag = 'notify_' + tag + '_enable'
data[new_tag] = ''
if tag in notify_data and 'enable' in notify_data[tag]:
if notify_data[tag]['enable']:
data[new_tag] = 'checked'
return data return data
+21 -2
View File
@@ -508,6 +508,22 @@ class crontab_api:
else: else:
head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n" head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n"
start_head = '''
SCRIPT_RUN_TIME="0s"
MW_ToSeconds()
{
SEC=$1
if [ $SEC -lt 60 ]; then
SCRIPT_RUN_TIME="${SEC}s"
elif [ $SEC -ge 60 ] && [ $SEC -lt 3600 ];then
SCRIPT_RUN_TIME="$(( SEC / 60 ))m$(( SEC % 60 ))s"
elif [ $SEC -ge 3600 ]; then
SCRIPT_RUN_TIME="$(( SEC / 3600 ))h$(( (SEC % 3600) / 60 ))m$(( (SEC % 3600) % 60 ))s"
fi
}
START_MW_SHELL_TIME=`date +%s`
'''
source_bin_activate = ''' source_bin_activate = '''
export LANG=en_US.UTF-8 export LANG=en_US.UTF-8
MW_PATH=%s/bin/activate MW_PATH=%s/bin/activate
@@ -515,7 +531,7 @@ if [ -f $MW_PATH ];then
source $MW_PATH source $MW_PATH
fi''' % (mw.getRunDir(),) fi''' % (mw.getRunDir(),)
head = head + source_bin_activate + "\n" head = head + start_head + source_bin_activate + "\n"
log = '.log' log = '.log'
script_dir = mw.getRunDir() + "/scripts" script_dir = mw.getRunDir() + "/scripts"
@@ -557,7 +573,10 @@ fi''' % (mw.getRunDir(),)
shell += ''' shell += '''
echo "----------------------------------------------------------------------------" echo "----------------------------------------------------------------------------"
endDate=`date +"%Y-%m-%d %H:%M:%S"` endDate=`date +"%Y-%m-%d %H:%M:%S"`
echo "★[$endDate] Successful" END_MW_SHELL_TIME=`date +"%s"`
((SHELL_COS_TIME=($END_MW_SHELL_TIME-$START_MW_SHELL_TIME)))
MW_ToSeconds $SHELL_COS_TIME
echo "★[$endDate] Successful | Script Run [$SCRIPT_RUN_TIME] "
echo "----------------------------------------------------------------------------" echo "----------------------------------------------------------------------------"
''' '''
cronPath = mw.getServerDir() + '/cron' cronPath = mw.getServerDir() + '/cron'
+1 -1
View File
@@ -65,7 +65,7 @@ class Sql():
self.__DB_TABLE = table self.__DB_TABLE = table
return self return self
def where(self, where, param): def where(self, where, param=()):
# WHERE条件 # WHERE条件
if where: if where:
self.__OPT_WHERE = " WHERE " + where self.__OPT_WHERE = " WHERE " + where
+10 -9
View File
@@ -123,12 +123,12 @@ class firewall_api:
address = port address = port
if self.__isUfw: if self.__isUfw:
mw.execShell('ufw delete deny from ' + address + ' to any') mw.execShell('ufw delete deny from ' + address + ' to any')
elif self.__isIptables:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
elif self.__isFirewalld: elif self.__isFirewalld:
mw.execShell( mw.execShell(
'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'') 'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'')
elif self.__isIptables:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
else: else:
pass pass
@@ -149,14 +149,15 @@ class firewall_api:
return mw.returnJson(False, '失败,不能删除当前面板端口!') return mw.returnJson(False, '失败,不能删除当前面板端口!')
if self.__isUfw: if self.__isUfw:
mw.execShell('ufw delete allow ' + port + '/tcp') mw.execShell('ufw delete allow ' + port + '/tcp')
elif self.__isIptables:
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
elif self.__isFirewalld: elif self.__isFirewalld:
port = port.replace(':', '-')
mw.execShell( mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp') 'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
mw.execShell( mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp') 'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
elif self.__isIptables:
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
else: else:
pass pass
msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,)) msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
@@ -438,13 +439,13 @@ class firewall_api:
def addAcceptPort(self, port): def addAcceptPort(self, port):
if self.__isUfw: if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp') mw.execShell('ufw allow ' + port + '/tcp')
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
elif self.__isFirewalld: elif self.__isFirewalld:
port = port.replace(':', '-') port = port.replace(':', '-')
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp' cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd) mw.execShell(cmd)
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
else: else:
pass pass
return True return True
+356 -8
View File
@@ -22,10 +22,14 @@ import hashlib
import shlex import shlex
import datetime import datetime
import subprocess import subprocess
import glob
import base64
import re import re
import db
from random import Random from random import Random
import db
def execShell(cmdstring, cwd=None, timeout=None, shell=True): def execShell(cmdstring, cwd=None, timeout=None, shell=True):
@@ -80,6 +84,10 @@ def getPanelDataDir():
return getRunDir() + '/data' return getRunDir() + '/data'
def getPanelTmp():
return getRunDir() + '/tmp'
def getServerDir(): def getServerDir():
return getRootDir() + '/server' return getRootDir() + '/server'
@@ -536,6 +544,14 @@ def getDate():
return time.strftime('%Y-%m-%d %X', time.localtime()) return time.strftime('%Y-%m-%d %X', time.localtime())
def getDateFromNow(tf_format="%Y-%m-%d %H:%M:%S", time_zone="Asia/Shanghai"):
# 取格式时间
import time
os.environ['TZ'] = time_zone
time.tzset()
return time.strftime(tf_format, time.localtime())
def getDataFromInt(val): def getDataFromInt(val):
time_format = '%Y-%m-%d %H:%M:%S' time_format = '%Y-%m-%d %H:%M:%S'
time_str = time.localtime(val) time_str = time.localtime(val)
@@ -551,10 +567,39 @@ def writeLog(stype, msg, args=()):
uid = session['uid'] uid = session['uid']
except Exception as e: except Exception as e:
pass pass
# print(getTracebackInfo()) # writeFileLog(getTracebackInfo())
return writeDbLog(stype, msg, args, uid) return writeDbLog(stype, msg, args, uid)
def writeFileLog(msg, path=None, limit_size=50 * 1024 * 1024, save_limit=3):
log_file = getServerDir() + '/mdserver-web/logs/debug.log'
if path != None:
log_file = path
if os.path.exists(log_file):
size = os.path.getsize(log_file)
if size > limit_size:
log_file_rename = log_file + "_" + \
time.strftime("%Y-%m-%d_%H%M%S") + '.log'
os.rename(log_file, log_file_rename)
logs = sorted(glob.glob(log_file + "_*"))
count = len(logs)
save_limit = count - save_limit
for i in range(count):
if i > save_limit:
break
os.remove(logs[i])
# print('|---多余日志[' + logs[i] + ']已删除!')
f = open(log_file, 'ab+')
msg += "\n"
if __name__ == '__main__':
print(msg)
f.write(msg.encode('utf-8'))
f.close()
return True
def writeDbLog(stype, msg, args=(), uid=1): def writeDbLog(stype, msg, args=(), uid=1):
try: try:
import time import time
@@ -673,7 +718,7 @@ def enCrypt(key, strings):
result = f.encrypt(strings) result = f.encrypt(strings)
return result.decode('utf-8') return result.decode('utf-8')
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -692,7 +737,7 @@ def deCrypt(key, strings):
result = f.decrypt(strings).decode('utf-8') result = f.decrypt(strings).decode('utf-8')
return result return result
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -711,7 +756,7 @@ def enDoubleCrypt(key, strings):
result = f.encrypt(strings) result = f.encrypt(strings)
return result.decode('utf-8') return result.decode('utf-8')
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -729,10 +774,137 @@ def deDoubleCrypt(key, strings):
result = f.decrypt(strings).decode('utf-8') result = f.decrypt(strings).decode('utf-8')
return result return result
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
def aesEncrypt(data, key='ABCDEFGHIJKLMNOP', vi='0102030405060708'):
# aes加密
# @param data 被加密的数据
# @param key 加解密密匙 16位
# @param vi 16位
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
if not isinstance(data, bytes):
data = data.encode()
# AES_CBC_KEY = os.urandom(32)
# AES_CBC_IV = os.urandom(16)
AES_CBC_KEY = key.encode()
AES_CBC_IV = vi.encode()
# print("AES_CBC_KEY:", AES_CBC_KEY)
# print("AES_CBC_IV:", AES_CBC_IV)
padder = padding.PKCS7(algorithms.AES.block_size).padder()
padded_data = padder.update(data) + padder.finalize()
cipher = Cipher(algorithms.AES(AES_CBC_KEY),
modes.CBC(AES_CBC_IV),
backend=default_backend())
encryptor = cipher.encryptor()
edata = encryptor.update(padded_data)
# print(edata)
# print(str(edata))
# print(edata.decode())
return edata
def aesDecrypt(data, key='ABCDEFGHIJKLMNOP', vi='0102030405060708'):
# aes加密
# @param data 被解密的数据
# @param key 加解密密匙 16位
# @param vi 16位
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
if not isinstance(data, bytes):
data = data.encode()
AES_CBC_KEY = key.encode()
AES_CBC_IV = vi.encode()
cipher = Cipher(algorithms.AES(AES_CBC_KEY),
modes.CBC(AES_CBC_IV),
backend=default_backend())
decryptor = cipher.decryptor()
ddata = decryptor.update(data)
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
data = unpadder.update(ddata)
try:
uppadded_data = data + unpadder.finalize()
except ValueError:
raise Exception('无效的加密信息!')
return uppadded_data
def aesEncrypt_Crypto(data, key, vi):
# 该方法保留,暂时不使用
# aes加密
# @param data 被加密的数据
# @param key 加解密密匙 16位
# @param vi 16位
from Crypto.Cipher import AES
cryptor = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
# 判断是否含有中文
zhmodel = re.compile(u'[\u4e00-\u9fff]')
match = zhmodel.search(data)
if match == None:
# 无中文时
add = 16 - len(data) % 16
pad = lambda s: s + add * chr(add)
data = pad(data)
enctext = cryptor.encrypt(data.encode('utf8'))
else:
# 含有中文时
data = data.encode()
add = 16 - len(data) % 16
data = data + add * (chr(add)).encode()
enctext = cryptor.encrypt(data)
encodestrs = base64.b64encode(enctext).decode('utf8')
return encodestrs
def aesDecrypt_Crypto(data, key, vi):
# 该方法保留,暂时不使用
# aes加密
# @param data 被加密的数据
# @param key 加解密密匙 16位
# @param vi 16位
from crypto.Cipher import AES
data = data.encode('utf8')
encodebytes = base64.urlsafe_b64decode(data)
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
text_decrypted = cipher.decrypt(encodebytes)
# 判断是否含有中文
zhmodel = re.compile(u'[\u4e00-\u9fff]')
match = zhmodel.search(text_decrypted)
if match == False:
# 无中文时补位
unpad = lambda s: s[0:-s[-1]]
text_decrypted = unpad(text_decrypted)
text_decrypted = text_decrypted.decode('utf8').rstrip() # 去掉补位的右侧空格
return text_decrypted
def buildSoftLink(src, dst, force=False): def buildSoftLink(src, dst, force=False):
''' '''
建立软连接 建立软连接
@@ -1043,6 +1215,12 @@ def formatDate(format="%Y-%m-%d %H:%M:%S", times=None):
return time.strftime(format, time_local) return time.strftime(format, time_local)
def strfToTime(sdate):
# 转换时间
import time
return time.strftime('%Y-%m-%d', time.strptime(sdate, '%b %d %H:%M:%S %Y %Z'))
def checkIp(ip): def checkIp(ip):
# 检查是否为IPv4地址 # 检查是否为IPv4地址
import re import re
@@ -1233,7 +1411,7 @@ def makeConf():
file = getRunDir() + '/data/json/config.json' file = getRunDir() + '/data/json/config.json'
if not os.path.exists(file): if not os.path.exists(file):
c = {} c = {}
c['title'] = '金蝉面板' c['title'] = '金灵面板'
c['home'] = 'http://github/midoks/mdserver-web' c['home'] = 'http://github/midoks/mdserver-web'
c['recycle_bin'] = True c['recycle_bin'] = True
c['template'] = 'default' c['template'] = 'default'
@@ -1533,7 +1711,7 @@ def getCertName(certPath):
result['notAfter'], "%Y-%m-%d")) - time.time()) / 86400) result['notAfter'], "%Y-%m-%d")) - time.time()) / 86400)
return result return result
except Exception as e: except Exception as e:
# print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return None return None
@@ -1631,6 +1809,176 @@ def getMyORMDb():
o = ormDb.ORM() o = ormDb.ORM()
return o return o
##################### notify start #########################################
def initNotifyConfig():
p = getNotifyPath()
if not os.path.exists(p):
writeFile(p, '{}')
return True
def getNotifyPath():
path = 'data/notify.json'
return path
def getNotifyData(is_parse=False):
initNotifyConfig()
notify_file = getNotifyPath()
notify_data = readFile(notify_file)
data = json.loads(notify_data)
if is_parse:
tag_list = ['tgbot', 'email']
for t in tag_list:
if t in data and 'cfg' in data[t]:
data[t]['data'] = json.loads(deDoubleCrypt(t, data[t]['cfg']))
return data
def writeNotify(data):
p = getNotifyPath()
return writeFile(p, json.dumps(data))
def tgbotNotifyChatID():
data = getNotifyData(True)
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
return t['chat_id']
return ''
def tgbotNotifyObject():
data = getNotifyData(True)
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
import telebot
bot = telebot.TeleBot(app_token)
return True, bot
return False, None
def tgbotNotifyMessage(app_token, chat_id, msg):
import telebot
bot = telebot.TeleBot(app_token)
try:
data = bot.send_message(chat_id, msg)
return True
except Exception as e:
writeFileLog(str(e))
return False
def tgbotNotifyHttpPost(app_token, chat_id, msg):
try:
url = 'https://api.telegram.org/bot' + app_token + '/sendMessage'
post_data = {
'chat_id': chat_id,
'text': msg,
}
rdata = httpPost(url, post_data)
return True
except Exception as e:
writeFileLog(str(e))
return False
def tgbotNotifyTest(app_token, chat_id):
msg = 'MW-通知验证测试OK'
return tgbotNotifyHttpPost(app_token, chat_id, msg)
def emailNotifyMessage(data):
'''
邮件通知
'''
sys.path.append(os.getcwd() + "/class/plugin")
import memail
try:
if data['smtp_ssl'] == 'ssl':
memail.sendSSL(data['smtp_host'], data['smtp_port'],
data['username'], data['password'],
data['to_mail_addr'], data['subject'], data['content'])
else:
memail.send(data['smtp_host'], data['smtp_port'],
data['username'], data['password'],
data['to_mail_addr'], data['subject'], data['content'])
return True
except Exception as e:
print(getTracebackInfo())
return False
def emailNotifyTest(data):
# print(data)
data['subject'] = 'MW通知测试'
data['content'] = data['mail_test']
return emailNotifyMessage(data)
def notifyMessageTry(msg, stype='common', trigger_time=300, is_write_log=True):
lock_file = getPanelTmp() + '/notify_lock.json'
if not os.path.exists(lock_file):
writeFile(lock_file, '{}')
lock_data = json.loads(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
else:
lock_data[stype] = {'do_time': time.time()}
writeFile(lock_file, json.dumps(lock_data))
if is_write_log:
writeLog("通知管理[" + stype + "]", msg)
data = getNotifyData(True)
# tag_list = ['tgbot', 'email']
# tagbot
do_notify = False
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
i = sys.version_info
# telebot 在python小于3.7无法使用
if i[0] < 3 or i[1] < 7:
do_notify = tgbotNotifyHttpPost(
t['app_token'], t['chat_id'], msg)
else:
do_notify = tgbotNotifyMessage(
t['app_token'], t['chat_id'], msg)
if 'email' in data and 'enable' in data['email']:
if data['email']['enable']:
t = data['email']['data']
t['subject'] = 'MW通知'
t['content'] = msg
do_notify = emailNotifyMessage(t)
return do_notify
def notifyMessage(msg, stype='common', trigger_time=300, is_write_log=True):
try:
return notifyMessageTry(msg, stype, trigger_time, is_write_log)
except Exception as e:
writeFileLog(getTracebackInfo())
return False
##################### notify end #########################################
##################### ssh start ######################################### ##################### ssh start #########################################
def getSshDir(): def getSshDir():
+33 -14
View File
@@ -71,8 +71,9 @@ class plugins_api:
if not mw.isNumber(sType): if not mw.isNumber(sType):
sType = 0 sType = 0
# print sPage # print(sPage, sType)
data = self.getPluginList(sType, int(sPage)) search = request.args.get('search', '').lower()
data = self.getPluginList(sType, search, int(sPage))
return mw.getJson(data) return mw.getJson(data)
def menuGetAbsPath(self, tag, path): def menuGetAbsPath(self, tag, path):
@@ -91,7 +92,7 @@ class plugins_api:
t = mw.readFile(menu_file) t = mw.readFile(menu_file)
tlist = json.loads(t) tlist = json.loads(t)
for menu_data in tlist: for menu_data in tlist:
if 'path' in menu_data: if tag == menu_data['name'] and 'path' in menu_data:
tpath = self.menuGetAbsPath(tag, menu_data['path']) tpath = self.menuGetAbsPath(tag, menu_data['path'])
content = mw.readFile(tpath) content = mw.readFile(tpath)
data['plugin_content'] = content data['plugin_content'] = content
@@ -138,7 +139,7 @@ class plugins_api:
def initApi(self): def initApi(self):
plugin_names = { plugin_names = {
'openresty': '1.21.4.1', 'openresty': '1.21.4.2',
'php': '56', 'php': '56',
'swap': '1.1', 'swap': '1.1',
'mysql': '5.7', 'mysql': '5.7',
@@ -256,13 +257,14 @@ class plugins_api:
data = json.loads(t) data = json.loads(t)
for idx in range(len(data)): for idx in range(len(data)):
if data[idx]['title'] == info['title'] and data[idx]['name'] == info['name']: if data[idx]['name'] == info['name']:
data.remove(data[idx]) data.remove(data[idx])
break
mw.writeFile(hookPath, json.dumps(data)) mw.writeFile(hookPath, json.dumps(data))
def hookInstall(self, info): def hookInstall(self, info):
valid_hook = ['backup', 'database'] valid_hook = ['backup', 'database']
valid_list_hook = ['menu'] valid_list_hook = ['menu', 'global_static', 'site_cb']
if 'hook' in info: if 'hook' in info:
hooks = info['hook'] hooks = info['hook']
for h in hooks: for h in hooks:
@@ -280,7 +282,7 @@ class plugins_api:
def hookUninstall(self, info): def hookUninstall(self, info):
valid_hook = ['backup', 'database'] valid_hook = ['backup', 'database']
valid_list_hook = ['menu'] valid_list_hook = ['menu', 'global_static', 'site_cb']
if 'hook' in info: if 'hook' in info:
hooks = info['hook'] hooks = info['hook']
for h in hooks: for h in hooks:
@@ -780,7 +782,18 @@ class plugins_api:
print(e) print(e)
return plugins_info return plugins_info
def getAllListPage(self, sType='0', page=1, pageSize=10): def searchKey(self, info, kw):
try:
if info['title'].lower().find(kw) > -1:
return True
if info['ps'].lower().find(kw) > -1:
return True
if info['name'].lower().find(kw) > -1:
return True
except Exception as e:
return False
def getAllListPage(self, sType='0', kw='', page=1, pageSize=10):
plugins_info = [] plugins_info = []
for dirinfo in os.listdir(self.__plugin_dir): for dirinfo in os.listdir(self.__plugin_dir):
if dirinfo[0:1] == '.': if dirinfo[0:1] == '.':
@@ -791,11 +804,14 @@ class plugins_api:
if os.path.exists(json_file): if os.path.exists(json_file):
try: try:
data = json.loads(mw.readFile(json_file)) data = json.loads(mw.readFile(json_file))
# 判断是否搜索
if kw != '' and not self.searchKey(data, kw):
continue
tmp_data = self.makeList(data, sType) tmp_data = self.makeList(data, sType)
for index in range(len(tmp_data)): for index in range(len(tmp_data)):
plugins_info.append(tmp_data[index]) plugins_info.append(tmp_data[index])
except Exception as e: except Exception as e:
print(e) print(mw.getTracebackInfo())
start = (page - 1) * pageSize start = (page - 1) * pageSize
end = start + pageSize end = start + pageSize
@@ -925,14 +941,14 @@ class plugins_api:
return plugins_info return plugins_info
def getPluginList(self, sType, sPage=1, sPageSize=10): def getPluginList(self, sType, kw='', sPage=1, sPageSize=10):
# print sType, sPage, sPageSize # print(sType, kw, sPage, sPageSize)
ret = {} ret = {}
ret['type'] = json.loads(mw.readFile(self.__type)) ret['type'] = json.loads(mw.readFile(self.__type))
# plugins_info = self.getAllListThread(sType) # plugins_info = self.getAllListThread(sType)
# plugins_info = self.getAllListProcess(sType) # plugins_info = self.getAllListProcess(sType)
data = self.getAllListPage(sType, sPage, sPageSize) data = self.getAllListPage(sType, kw, sPage, sPageSize)
ret['data'] = data[0] ret['data'] = data[0]
args = {} args = {}
@@ -1014,8 +1030,11 @@ class plugins_api:
# shell 调用 # shell 调用
def run(self, name, func, version='', args='', script='index'): def run(self, name, func, version='', args='', script='index'):
path = self.__plugin_dir + \
'/' + name + '/' + script + '.py' path = self.__plugin_dir + '/' + name + '/' + script + '.py'
if not os.path.exists(path):
path = self.__plugin_dir + '/' + name + '/' + name + '.py'
py = 'python3 ' + path py = 'python3 ' + path
if args == '': if args == '':
+158 -60
View File
@@ -72,24 +72,60 @@ class site_api:
mw.execShell("mkdir -p " + self.sslLetsDir + mw.execShell("mkdir -p " + self.sslLetsDir +
" && chmod -R 755 " + self.sslLetsDir) " && chmod -R 755 " + self.sslLetsDir)
def runHook(self, hook_name, func_name):
# 站点操作Hook
hook_file = 'data/hook_site_cb.json'
hook_cfg = []
if os.path.exists(hook_file):
t = mw.readFile(hook_file)
hook_cfg = json.loads(t)
hook_num = len(hook_cfg)
if hook_num == 0:
return
import plugins_api
pa = plugins_api.plugins_api()
for x in range(hook_num):
hook_data = hook_cfg[x]
if func_name in hook_data:
app_name = hook_data["name"]
run_func = hook_data[func_name]['func']
# print(app_name, run_func)
pa.run(app_name, run_func)
return True
##### ----- start ----- ### ##### ----- start ----- ###
def listApi(self): def listApi(self):
limit = request.form.get('limit', '10') limit = request.form.get('limit', '10')
p = request.form.get('p', '1') p = request.form.get('p', '1')
type_id = request.form.get('type_id', '0').strip() type_id = request.form.get('type_id', '0').strip()
search = request.form.get('search', '').strip()
start = (int(p) - 1) * (int(limit)) start = (int(p) - 1) * (int(limit))
siteM = mw.M('sites').field('id,name,path,status,ps,addtime,edate') siteM = mw.M('sites').field('id,name,path,status,ps,addtime,edate')
if type_id != '' and int(type_id) >= 0:
siteM.where('type_id=?', (type_id,)) sql_where = ''
if search != '':
sql_where = " name like '%" + search + "%' or ps like '%" + search + "%' "
if type_id != '' and int(type_id) >= 0 and search != '':
sql_where = sql_where + " and type_id=" + type_id + ""
elif type_id != '' and int(type_id) >= 0:
sql_where = " type_id=" + type_id
if sql_where != '':
siteM.where(sql_where)
_list = siteM.limit((str(start)) + ',' + _list = siteM.limit((str(start)) + ',' +
limit).order('id desc').select() limit).order('id desc').select()
for i in range(len(_list)): if _list != None:
_list[i]['backup_count'] = mw.M('backup').where( for i in range(len(_list)):
"pid=? AND type=?", (_list[i]['id'], 0)).count() _list[i]['backup_count'] = mw.M('backup').where(
"pid=? AND type=?", (_list[i]['id'], 0)).count()
_ret = {} _ret = {}
_ret['data'] = _list _ret['data'] = _list
@@ -751,6 +787,9 @@ class site_api:
mw.execShell('echo "lets" > "' + path + '/README"') mw.execShell('echo "lets" > "' + path + '/README"')
elif ssl_type == 'acme': elif ssl_type == 'acme':
ssl_acme_dir = mw.getAcmeDir() + '/' + site_name ssl_acme_dir = mw.getAcmeDir() + '/' + site_name
if not os.path.exists(ssl_acme_dir):
ssl_acme_dir = mw.getAcmeDir() + '/' + site_name + '_ecc'
acme_csrpath = ssl_acme_dir + '/fullchain.cer' acme_csrpath = ssl_acme_dir + '/fullchain.cer'
acme_keypath = ssl_acme_dir + '/' + site_name + '.key' acme_keypath = ssl_acme_dir + '/' + site_name + '.key'
if mw.md5(mw.readFile(acme_csrpath)) == mw.md5(mw.readFile(csr_path)): if mw.md5(mw.readFile(acme_csrpath)) == mw.md5(mw.readFile(csr_path)):
@@ -1272,6 +1311,7 @@ class site_api:
mw.M('domain').add('pid,name,port,addtime', mw.M('domain').add('pid,name,port,addtime',
(pid, domain_name, domain_port, mw.getDate())) (pid, domain_name, domain_port, mw.getDate()))
self.runHook('site_cb', 'add')
return mw.returnJson(True, '域名添加成功!') return mw.returnJson(True, '域名添加成功!')
def addDirBindApi(self): def addDirBindApi(self):
@@ -1395,13 +1435,15 @@ class site_api:
data['data'] = mw.readFile(filename) data['data'] = mw.readFile(filename)
data['rlist'] = [] data['rlist'] = []
for ds in os.listdir(self.rewritePath): for ds in os.listdir(self.rewritePath):
if ds[0:1] == '.':
continue
if ds == 'list.txt': if ds == 'list.txt':
continue continue
data['rlist'].append(ds[0:len(ds) - 5]) data['rlist'].append(ds[0:len(ds) - 5])
data['filename'] = filename data['filename'] = filename
return mw.getJson(data) return mw.getJson(data)
# 修改物理路径 # 修改物理路径
def setPathApi(self): def setPathApi(self):
mid = request.form.get('id', '') mid = request.form.get('id', '')
path = request.form.get('path', '') path = request.form.get('path', '')
@@ -1828,19 +1870,16 @@ class site_api:
if _id == '' or _siteName == '': if _id == '' or _siteName == '':
return mw.returnJson(False, "必填项不能为空!") return mw.returnJson(False, "必填项不能为空!")
_old_config = mw.readFile( proxy_file = "{}/{}/{}.conf".format(self.proxyPath, _siteName, _id)
"{}/{}/{}.conf".format(self.proxyPath, _siteName, _id)) mw.backFile(proxy_file)
if _old_config == False: mw.writeFile(proxy_file, _config)
return mw.returnJson(False, "非法操作")
mw.writeFile("{}/{}/{}.conf".format(self.proxyPath,
_siteName, _id), _config)
rule_test = mw.checkWebConfig() rule_test = mw.checkWebConfig()
if rule_test != True: if rule_test != True:
mw.writeFile("{}/{}/{}.conf".format(self.proxyPath, mw.restoreFile(proxy_file)
_siteName, _id), _old_config) mw.removeBackFile(proxy_file)
return mw.returnJson(False, "OpenResty 配置测试不通过, 请重试: {}".format(rule_test)) return mw.returnJson(False, "OpenResty 配置测试不通过, 请重试: {}".format(rule_test))
mw.removeBackFile(proxy_file)
self.operateRedirectConf(_siteName, 'start') self.operateRedirectConf(_siteName, 'start')
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, "ok") return mw.returnJson(True, "ok")
@@ -1881,21 +1920,20 @@ class site_api:
_from = request.form.get('from', '') _from = request.form.get('from', '')
_to = request.form.get('to', '') _to = request.form.get('to', '')
_host = request.form.get('host', '') _host = request.form.get('host', '')
_name = request.form.get('name', '')
_open_proxy = request.form.get('open_proxy', '') _open_proxy = request.form.get('open_proxy', '')
_open_cache = request.form.get('open_cache', '')
_cache_time = request.form.get('cache_time', '')
_id = request.form.get('id', '')
if _siteName == "" or _from == "" or _to == "" or _host == "": # print(_name, _siteName, _from, _to, _host)
if _name == "" or _siteName == "" or _from == "" or _to == "" or _host == "":
return mw.returnJson(False, "必填项不能为空") return mw.returnJson(False, "必填项不能为空")
data_path = self.getProxyDataPath(_siteName)
data_content = mw.readFile(
data_path) if os.path.exists(data_path) else ""
data = json.loads(data_content) if data_content != "" else []
rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?" rep = "http(s)?\:\/\/([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+([a-zA-Z0-9][a-zA-Z0-9]{0,62})+.?"
if not re.match(rep, _to): if not re.match(rep, _to):
return mw.returnJson(False, "错误的目标地址!") return mw.returnJson(False, "错误的目标地址!")
# _to = _to.strip("/")
# get host from url # get host from url
try: try:
if _host == "$host": if _host == "$host":
@@ -1904,7 +1942,11 @@ class site_api:
except: except:
return mw.returnJson(False, "错误的目标地址") return mw.returnJson(False, "错误的目标地址")
# location ~* ^{from}(.*)$ { proxy_site_path = self.getProxyDataPath(_siteName)
data_content = mw.readFile(
proxy_site_path) if os.path.exists(proxy_site_path) else ""
data = json.loads(data_content) if data_content != "" else []
tpl = "#PROXY-START\n\ tpl = "#PROXY-START\n\
location ^~ {from} {\n\ location ^~ {from} {\n\
proxy_pass {to};\n\ proxy_pass {to};\n\
@@ -1912,12 +1954,29 @@ location ^~ {from} {\n\
proxy_set_header X-Real-IP $remote_addr;\n\ proxy_set_header X-Real-IP $remote_addr;\n\
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\
proxy_set_header REMOTE-HOST $remote_addr;\n\ proxy_set_header REMOTE-HOST $remote_addr;\n\
proxy_set_header Upgrade $http_upgrade;\n\
proxy_set_header Connection $connection_upgrade;\n\
proxy_http_version 1.1;\n\
\n\ \n\
add_header X-Cache $upstream_cache_status;\n\ add_header X-Cache $upstream_cache_status;\n\
proxy_ignore_headers Set-Cookie Cache-Control expires;\n\
add_header Cache-Control no-cache;\n\
\n\ \n\
set $static_files_app 0;\n\ {proxy_cache}\n\
}\n\
# PROXY-END"
tpl_proxy_cache = "\n\
if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\
{\n\
expires {cache_time}m;\n\
}\n\
proxy_ignore_headers Set-Cookie Cache-Control expires;\n\
proxy_cache mw_cache;\n\
proxy_cache_key \"$host$uri$is_args$args\";\n\
proxy_cache_valid 200 304 301 302 {cache_time}m;\n\
"
tpl_proxy_nocache = "\n\
set $static_files_app 0; \n\
if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\ if ( $uri ~* \"\.(gif|png|jpg|css|js|woff|woff2)$\" )\n\
{\n\ {\n\
set $static_files_app 1;\n\ set $static_files_app 1;\n\
@@ -1927,8 +1986,7 @@ location ^~ {from} {\n\
{\n\ {\n\
add_header Cache-Control no-cache;\n\ add_header Cache-Control no-cache;\n\
}\n\ }\n\
}\n\ "
#PROXY-END"
# replace # replace
if _from[0] != '/': if _from[0] != '/':
@@ -1936,28 +1994,69 @@ location ^~ {from} {\n\
tpl = tpl.replace("{from}", _from, 999) tpl = tpl.replace("{from}", _from, 999)
tpl = tpl.replace("{to}", _to) tpl = tpl.replace("{to}", _to)
tpl = tpl.replace("{host}", _host, 999) tpl = tpl.replace("{host}", _host, 999)
tpl = tpl.replace("{cache_time}", _cache_time, 999)
_id = mw.md5("{}+{}+{}".format(_from, _to, _siteName)) if _open_cache == 'on':
for item in data: tpl_proxy_cache = tpl_proxy_cache.replace(
if item["id"] == _id: "{cache_time}", _cache_time, 999)
return mw.returnJson(False, "已存在该规则!") tpl = tpl.replace("{proxy_cache}", tpl_proxy_cache, 999)
if item["from"] == _from: else:
return mw.returnJson(False, "代理目录已存在!") tpl = tpl.replace("{proxy_cache}", tpl_proxy_nocache, 999)
data.append({
"from": _from, proxy_action = 'add'
"to": _to, if _id == "":
"host": _host, _id = mw.md5("{}".format(_name))
"id": _id else:
}) proxy_action = 'edit'
conf_proxy = "{}/{}.conf".format(self.getProxyPath(_siteName), _id)
conf_bk = "{}/{}.conf.txt".format(self.getProxyPath(_siteName), _id)
mw.writeFile(conf_proxy, tpl)
rule_test = mw.checkWebConfig()
if rule_test != True:
os.remove(conf_proxy)
return mw.returnJson(False, "OpenResty配置测试不通过, 请重试: {}".format(rule_test))
if proxy_action == "add":
# 添加代理
_id = mw.md5("{}".format(_name))
for item in data:
if item["name"] == _name:
return mw.returnJson(False, "名称重复!")
if item["from"] == _from:
return mw.returnJson(False, "代理目录已存在!")
data.append({
"name": _name,
"from": _from,
"to": _to,
"host": _host,
"open_cache": _open_cache,
"open_proxy": _open_proxy,
"cache_time": _cache_time,
"id": _id,
})
else:
# 修改代理
dindex = -1
for x in range(len(data)):
if data[x]["id"] == _id:
dindex = x
break
if dindex < 0:
return mw.returnJson(False, "异常请求")
data[dindex]['from'] = _from
data[dindex]['to'] = _to
data[dindex]['host'] = _host
data[dindex]['open_cache'] = _open_cache
data[dindex]['open_proxy'] = _open_proxy
data[dindex]['cache_time'] = _cache_time
conf_file = "{}/{}.conf".format(self.getProxyPath(_siteName), _id)
if _open_proxy != 'on': if _open_proxy != 'on':
conf_file = "{}/{}.conf.txt".format( os.rename(conf_proxy, conf_bk)
self.getProxyPath(_siteName), _id)
mw.writeFile(data_path, json.dumps(data))
mw.writeFile(conf_file, tpl)
mw.writeFile(proxy_site_path, json.dumps(data))
self.operateProxyConf(_siteName, 'start') self.operateProxyConf(_siteName, 'start')
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, "ok", {"hash": _id}) return mw.returnJson(True, "ok", {"hash": _id})
@@ -1988,10 +2087,10 @@ location ^~ {from} {\n\
self.getProxyPath(_siteName), _id) self.getProxyPath(_siteName), _id)
mw.execShell(cmd) mw.execShell(cmd)
except: except:
return mw.returnJson(False, "删除失败!") return mw.returnJson(False, "删除反代失败!")
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, "删除成功!") return mw.returnJson(True, "删除反代成功!")
def getSiteTypesApi(self): def getSiteTypesApi(self):
# 取网站分类 # 取网站分类
@@ -2058,7 +2157,7 @@ location ^~ {from} {\n\
##### ----- end ----- ### ##### ----- end ----- ###
# 域名编码转换 # 域名编码转换
def toPunycode(self, domain): def toPunycode(self, domain):
import re import re
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
@@ -2066,7 +2165,7 @@ location ^~ {from} {\n\
tmp = domain.split('.') tmp = domain.split('.')
newdomain = '' newdomain = ''
for dkey in tmp: for dkey in tmp:
# 匹配非ascii字符 # 匹配非ascii字符
match = re.search(u"[\x80-\xff]+", dkey) match = re.search(u"[\x80-\xff]+", dkey)
if not match: if not match:
newdomain += dkey + '.' newdomain += dkey + '.'
@@ -2530,16 +2629,18 @@ location ^~ {from} {\n\
self.createRootDir(self.sitePath) self.createRootDir(self.sitePath)
self.nginxAddConf() self.nginxAddConf()
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
# 添加更多域名 # 添加更多域名
for domain in siteMenu['domainlist']: for domain in siteMenu['domainlist']:
self.addDomain(domain, self.siteName, pid) self.addDomain(domain, self.siteName, pid)
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
data = {} data = {}
data['siteStatus'] = False data['siteStatus'] = False
mw.restartWeb() mw.restartWeb()
self.runHook('site_cb', 'add')
return mw.returnJson(True, '添加成功') return mw.returnJson(True, '添加成功')
def deleteWSLogs(self, webname): def deleteWSLogs(self, webname):
@@ -2608,6 +2709,8 @@ location ^~ {from} {\n\
mw.M('binding').where("pid=?", (sid,)).delete() mw.M('binding').where("pid=?", (sid,)).delete()
mw.restartWeb() mw.restartWeb()
self.runHook('site_cb', 'delete')
return mw.returnJson(True, '站点删除成功!') return mw.returnJson(True, '站点删除成功!')
def setEndDate(self, sid, edate): def setEndDate(self, sid, edate):
@@ -2617,7 +2720,7 @@ location ^~ {from} {\n\
mw.writeLog('TYPE_SITE', '设置成功,站点到期后将自动停止!', (siteName, edate)) mw.writeLog('TYPE_SITE', '设置成功,站点到期后将自动停止!', (siteName, edate))
return mw.returnJson(True, '设置成功,站点到期后将自动停止!') return mw.returnJson(True, '设置成功,站点到期后将自动停止!')
# ssl相关方法 start # ssl相关方法 start
def setSslConf(self, siteName): def setSslConf(self, siteName):
file = self.getHostConf(siteName) file = self.getHostConf(siteName)
conf = mw.readFile(file) conf = mw.readFile(file)
@@ -2716,9 +2819,4 @@ location ^~ {from} {\n\
mw.execShell("chattr +i " + filename) mw.execShell("chattr +i " + filename)
return mw.returnJson(True, '已打开防跨站设置!') return mw.returnJson(True, '已打开防跨站设置!')
# ssl相关方法 end
# 转换时间
def strfToTime(self, sdate):
import time
return time.strftime('%Y-%m-%d', time.strptime(sdate, '%b %d %H:%M:%S %Y %Z'))
# ssl相关方法 end
+10
View File
@@ -755,6 +755,8 @@ class system_api:
#!/bin/bash #!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
P_VER=`python3 -V | awk '{print $2}'`
if [ ! -f /www/server/mdserver-web/bin/activate ];then if [ ! -f /www/server/mdserver-web/bin/activate ];then
cd /www/server/mdserver-web && python3 -m venv . cd /www/server/mdserver-web && python3 -m venv .
cd /www/server/mdserver-web && source /www/server/mdserver-web/bin/activate cd /www/server/mdserver-web && source /www/server/mdserver-web/bin/activate
@@ -769,6 +771,14 @@ if [ ! -z "$cn" ];then
fi fi
cd /www/server/mdserver-web && pip3 install -r /www/server/mdserver-web/requirements.txt -i $PIPSRC cd /www/server/mdserver-web && pip3 install -r /www/server/mdserver-web/requirements.txt -i $PIPSRC
P_VER_D=`echo "$P_VER"|awk -F '.' '{print $1}'`
P_VER_M=`echo "$P_VER"|awk -F '.' '{print $2}'`
NEW_P_VER=${P_VER_D}.${P_VER_M}
if [ -f /www/server/mdserver-web/version/r${NEW_P_VER}.txt ];then
cd /www/server/mdserver-web && pip3 install -r /www/server/mdserver-web/version/r${NEW_P_VER}.txt -i $PIPSRC
fi
''' '''
os.system(update_env) os.system(update_env)
self.restartMw() self.restartMw()
+48
View File
@@ -0,0 +1,48 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# VIP用户管理
# ---------------------------------------------------------------------------------
import mw
from flask import request
import requests
class vip_api:
api_url = 'https://wo.midoks.me/api/wp-json/vip'
def __init__(self):
pass
def loginApi(self):
username = request.form.get('username', '')
password = request.form.get('password', '')
password = mw.aesEncrypt(password)
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}
print("name:", str(username))
print("pwd:", str(password))
args = {
'name': username,
'pass': password
}
data = requests.post(self.api_url + '/v1/login',
data=args, headers=headers)
print(data.text)
return mw.returnJson(False, "测试中!")
+43
View File
@@ -0,0 +1,43 @@
# coding: utf-8
import smtplib
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), addr))
def send(smtp_host, smtp_port, username, password, to_mail, subject, content):
smtp = smtplib.SMTP()
smtp.connect(smtp_host, port=smtp_port)
smtp.login(user=username, password=password)
msg = MIMEText(content, 'plain', 'utf-8')
msg['From'] = _format_addr(username)
msg['To'] = _format_addr(to_mail)
msg['Subject'] = Header(subject, 'utf-8').encode()
smtp.sendmail(from_addr=username, to_addrs=to_mail, msg=msg.as_string())
return True
def sendSSL(smtp_host, smtp_port, username, password, to_mail, subject, content):
smtp = smtplib.SMTP_SSL(smtp_host, port=smtp_port)
smtp.login(user=username, password=password)
msg = MIMEText(content, 'plain', 'utf-8')
msg['From'] = _format_addr(username)
msg['To'] = _format_addr(to_mail)
msg['Subject'] = Header(subject, 'utf-8').encode()
smtp.sendmail(from_addr=username, to_addrs=to_mail, msg=msg.as_string())
smtp.quit()
return True
+3
View File
@@ -65,6 +65,9 @@ class ORM:
def setCharset(self, charset): def setCharset(self, charset):
self.__DB_CHARSET = charset self.__DB_CHARSET = charset
def setHost(self, host):
self.__DB_HOST = host
def setPort(self, port): def setPort(self, port):
self.__DB_PORT = port self.__DB_PORT = port
+2 -2
View File
@@ -16,7 +16,7 @@ mw_start_task()
{ {
isStart=$(ps aux |grep 'task.py'|grep -v grep|awk '{print $2}') isStart=$(ps aux |grep 'task.py'|grep -v grep|awk '{print $2}')
if [ "$isStart" == '' ];then if [ "$isStart" == '' ];then
echo -e "Starting mw-tasks... \c" echo -e "starting mw-tasks... \c"
cd $DIR && python3 task.py >> ${DIR}/logs/task.log 2>&1 & cd $DIR && python3 task.py >> ${DIR}/logs/task.log 2>&1 &
sleep 0.3 sleep 0.3
isStart=$(ps aux |grep 'task.py'|grep -v grep|awk '{print $2}') isStart=$(ps aux |grep 'task.py'|grep -v grep|awk '{print $2}')
@@ -30,7 +30,7 @@ mw_start_task()
fi fi
echo -e "\033[32mdone\033[0m" echo -e "\033[32mdone\033[0m"
else else
echo "Starting mw-tasks... mw-tasks (pid $(echo $isStart)) already running" echo "starting mw-tasks... mw-tasks (pid $(echo $isStart)) already running"
fi fi
} }
+20 -17
View File
@@ -16,6 +16,7 @@ cd /www/server/mdserver-web/plugins/php/versions && bash all_test.sh
| CentOS 9 Stream |✅ |✅ | | CentOS 9 Stream |✅ |✅ |
| Debian 10.3 |✅ |✅ | | Debian 10.3 |✅ |✅ |
| Debian 11.3 |✅ |✅ | | Debian 11.3 |✅ |✅ |
| Debian 12.0 |✅ |✅ |
| Ubuntu 18.04 |✅ |✅ | | Ubuntu 18.04 |✅ |✅ |
| Ubuntu 20.04 |✅ |✅ | | Ubuntu 20.04 |✅ |✅ |
| Ubuntu 22.04 |✅ |✅ | | Ubuntu 22.04 |✅ |✅ |
@@ -28,23 +29,24 @@ cd /www/server/mdserver-web/plugins/php/versions && bash all_test.sh
| 系统名称 |PHP53 |PHP54 |PHP55 |PHP56 |PHP70 |PHP71 |PHP72 |PHP73 |PHP74 |PHP80 |PHP81 | | 系统名称 |PHP53 |PHP54 |PHP55 |PHP56 |PHP70 |PHP71 |PHP72 |PHP73 |PHP74 |PHP80 |PHP81 |PHP82 |
| ----------------- |-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------| | ----------------- |-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
| CentOS 7.9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | CentOS 7.9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 8.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | CentOS 8.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 8 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | CentOS 8 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 9 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | CentOS 9 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 10.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Debian 10.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 11.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Debian 11.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 18.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Debian 12 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 20.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Ubuntu 18.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 22.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Ubuntu 20.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Fedora 31 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Ubuntu 22.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Fedora 32 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Fedora 31 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| AlmaLinux 9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Fedora 32 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| RockyLinux 8.6 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | AlmaLinux 9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Arch Linux |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | RockyLinux 8.6 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| openSUSE 15.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ | | Arch Linux |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| openSUSE 15.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
@@ -56,6 +58,7 @@ cd /www/server/mdserver-web/plugins/php/versions && bash all_test.sh
| CentOS 9 Stream |✅ |✅ |✅ |✅ | | CentOS 9 Stream |✅ |✅ |✅ |✅ |
| Debian 10.3 |✅ |✅ |✅ |✅ | | Debian 10.3 |✅ |✅ |✅ |✅ |
| Debian 11.3 |✅ |✅ |✅ |✅ | | Debian 11.3 |✅ |✅ |✅ |✅ |
| Debian 12 |✅ |✅ |✅ |✅ |
| Ubuntu 18.04 |✅ |✅ |✅ |✅ | | Ubuntu 18.04 |✅ |✅ |✅ |✅ |
| Ubuntu 20.04 |✅ |✅ |✅ |✅ | | Ubuntu 20.04 |✅ |✅ |✅ |✅ |
| Ubuntu 22.04 |✅ |✅ |✅ |✅ | | Ubuntu 22.04 |✅ |✅ |✅ |✅ |
+2 -3
View File
@@ -46,9 +46,8 @@ CREATE TABLE IF NOT EXISTS `firewall` (
INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES
(1, '80', '网站默认端口', '0000-00-00 00:00:00'), (1, '80', '网站默认端口', '0000-00-00 00:00:00'),
(2, '22', 'SSH远程管理服务', '0000-00-00 00:00:00'), (2, '443', 'HTTPS', '0000-00-00 00:00:00'),
(3, '443', 'HTTPS', '0000-00-00 00:00:00'), (3, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
(4, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
+2 -9
View File
@@ -39,20 +39,13 @@ server
allow all; allow all;
} }
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$ location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
{ {
expires 30d; expires 30d;
error_log off; error_log /dev/null;
access_log /dev/null; access_log /dev/null;
} }
location ~ .*\\.(js|css)?$
{
expires 12h;
error_log off;
access_log /dev/null;
}
access_log {$LOGPATH}/{$SERVER_NAME}.log main; access_log {$LOGPATH}/{$SERVER_NAME}.log main;
error_log {$LOGPATH}/{$SERVER_NAME}.error.log; error_log {$LOGPATH}/{$SERVER_NAME}.error.log;
} }
+3 -10
View File
@@ -35,18 +35,11 @@ server
allow all; allow all;
} }
location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$ location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
{ {
expires 30d; error_log /dev/null;
error_log off;
access_log /dev/null; access_log /dev/null;
} expires 30d;
location ~ .*\\.(js|css)?$
{
expires 12h;
error_log off;
access_log /dev/null;
} }
access_log {$LOGPATH}/{$SERVER_MAIN}_{$DIRBIND}.log; access_log {$LOGPATH}/{$SERVER_MAIN}_{$DIRBIND}.log;
+1
View File
@@ -0,0 +1 @@
存放VIP关键数据
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+58
View File
@@ -0,0 +1,58 @@
<style type="text/css">
.docker-sub {
border-bottom: 1px solid #ccc;
height: 30px;
line-height: 30px;
margin-bottom: 15px;
}
.docker-sub .on {
border-bottom: 2px solid #20a53a;
color: #20a53a;
font-weight: bold;
font-family: "宋体";
}
.docker-sub span {
display: inline-block;
font-size: 14px;
height: 30px;
padding: 0 25px;
cursor: pointer;
}
.docker-environments {
resize: none;
width: 330px;
height: 80px;
line-height: 20px;
padding: 5px 8px;
border: 1px solid #ddd;
font-size: 12px;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('docker');">服务</p>
<p onclick="pluginInitD('docker');">自启动</p>
<p onclick="dockerConList();">容器列表</p>
<p onclick="dockerImageList();">镜像列表</p>
<p onclick="dockerImageOutput();">镜像导出</p>
<p onclick="dockerIpList();">IP地址池</p>
<p onclick="repoList();">仓库</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinWidth(800);
resetPluginWinHeight(400);
$.getScript( "/plugins/file?name=docker&f=js/docker.js", function(){
pluginService('docker', $('.plugin_version').attr('version'));
});
</script>
+860
View File
@@ -0,0 +1,860 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
import docker
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getDClient():
try:
client = docker.from_env()
except Exception as e:
client = docker.DockerClient(
base_url='unix:///Users/midoks/.docker/run/docker.sock')
return client
def getPluginName():
return 'docker'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getConf():
path = getServerDir() + "/redis.conf"
return path
def getConfTpl():
path = getPluginDir() + "/config/redis.conf"
return path
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
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(self, data, ck=[]):
for i in range(len(ck)):
print(data[i])
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def status():
data = mw.execShell(
"ps -ef|grep docker |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
return ''
def dockerOp(method):
file = initDreplace()
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' docker')
if data[1] == '':
return 'ok'
return data[1]
return 'fail'
def start():
return dockerOp('start')
def stop():
return dockerOp('stop')
def restart():
status = dockerOp('restart')
log_file = runLog()
mw.execShell("echo '' > " + log_file)
return status
def reload():
return dockerOp('reload')
def initdStatus():
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl enable ' + getPluginName())
return 'ok'
def initdUinstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable ' + getPluginName())
return 'ok'
# UTC时间转换为时间戳
def utc_to_local(utc_time_str, utc_format='%Y-%m-%dT%H:%M:%S'):
import pytz
import datetime
import time
local_tz = pytz.timezone('Asia/Chongqing')
local_format = "%Y-%m-%d %H:%M"
utc_dt = datetime.datetime.strptime(utc_time_str, utc_format)
local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)
time_str = local_dt.strftime(local_format)
return int(time.mktime(time.strptime(time_str, local_format)))
def conList():
c = getDClient()
clist = c.containers.list(all=True)
conList = []
for con in clist:
tmp = con.attrs
tmp['Created'] = utc_to_local(tmp['Created'].split('.')[0])
conList.append(tmp)
return conList
def conListData():
try:
clist = conList()
except Exception as e:
return mw.returnJson(False, '未开启Docker')
return mw.returnJson(True, 'ok', clist)
def dockerRemoveCon():
args = getArgs()
data = checkArgs(args, ['Hostname'])
if not data[0]:
return data[1]
Hostname = args['Hostname']
c = getDClient()
try:
conFind = c.containers.get(Hostname)
try:
path_list = conFind.attrs['GraphDriver'][
'Data']['LowerDir'].split(':')
for i in path_list:
mw.execShell('chattr -R -i %s' % i)
except:
pass
conFind.remove(force=True)
return mw.returnJson(True, '成功删除!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def dockerLogCon():
args = getArgs()
data = checkArgs(args, ['Hostname'])
if not data[0]:
return data[1]
Hostname = args['Hostname']
c = getDClient()
try:
conFind = c.containers.get(Hostname)
if not conFind:
return mw.returnJson(False, 'The specified container does not exist!')
log = conFind.logs()
if not isinstance(log, str):
log = log.decode()
return mw.returnJson(True, log)
except docker.errors.APIError as ex:
return mw.returnJson(False, 'Get Logs failed')
def dockerRunCon():
# 启动容器
args = getArgs()
data = checkArgs(args, ['Hostname'])
if not data[0]:
return data[1]
Hostname = args['Hostname']
c = getDClient()
try:
conFind = c.containers.get(Hostname)
if not conFind:
return mw.returnJson(False, 'The specified container does not exist!')
conFind.start()
return mw.returnJson(True, '启动成功!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '启动失败!' + str(ex))
def dockerStopCon():
# 停止容器
args = getArgs()
data = checkArgs(args, ['Hostname'])
if not data[0]:
return data[1]
Hostname = args['Hostname']
c = getDClient()
try:
conFind = c.containers.get(Hostname)
if not conFind:
return mw.returnJson(False, 'The specified container does not exist!')
conFind.stop()
return mw.returnJson(True, '停止成功!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '停止失败!' + str(ex))
def dockerExec():
# 容器执行命令
args = getArgs()
data = checkArgs(args, ['Hostname'])
if not data[0]:
return data[1]
Hostname = args['Hostname']
debug_path = 'data/debug.pl'
if os.path.exists(debug_path):
return mw.returnJson(False, '开发模式不能进入!')
c = getDClient()
try:
conFind = c.containers.get(Hostname)
cmd = 'docker container exec -it %s /bin/sh' % Hostname
return mw.returnJson(True, cmd)
except docker.errors.APIError as ex:
return mw.returnJson(False, '连接失败!')
def imageList():
imageList = []
c = getDClient()
ilist = c.images.list()
for image in ilist:
tmp_attrs = image.attrs
if len(tmp_attrs['RepoTags']) == 1:
tmp_image = {}
tmp_image['Id'] = tmp_attrs['Id'].split(':')[1][:12]
tmp_image['RepoTags'] = tmp_attrs['RepoTags'][0]
tmp_image['Size'] = tmp_attrs['Size']
tmp_image['Labels'] = tmp_attrs['Config']['Labels']
tmp_image['Comment'] = tmp_attrs['Comment']
tmp_image['Created'] = utc_to_local(
tmp_attrs['Created'].split('.')[0])
imageList.append(tmp_image)
else:
for i in range(len(tmp_attrs['RepoTags'])):
tmp_image = {}
tmp_image['Id'] = tmp_attrs['Id'].split(':')[1][:12]
tmp_image['RepoTags'] = tmp_attrs['RepoTags'][i]
tmp_image['Size'] = tmp_attrs['Size']
tmp_image['Labels'] = tmp_attrs['Config']['Labels']
tmp_image['Comment'] = tmp_attrs['Comment']
tmp_image['Created'] = utc_to_local(
tmp_attrs['Created'].split('.')[0])
imageList.append(tmp_image)
imageList = sorted(imageList, key=lambda x: x['Created'], reverse=True)
return imageList
def dockerPull():
# pull Dockr 官方镜像
args = getArgs()
data = checkArgs(args, ['images'])
if not data[0]:
return data[1]
images = args['images']
if ':' in images:
pass
else:
images = images + ':latest'
c = getDClient()
try:
ret = c.images.pull(images)
if ret:
return mw.returnJson(True, '拉取成功!')
else:
return mw.returnJson(False, '拉取失败,请检查镜像名称或是否需要登录docker进行下载')
except:
ret = mw.execShell('docker image pull %s' % images)
if 'invalid' in ret[-1]:
return mw.returnJson(False, '拉取失败,请检查镜像名称或是否需要登录docker进行下载')
else:
return mw.returnJson(True, '拉取成功!')
def dockerPlulPath(path):
if not path and path == '':
return mw.returnJson(False, 'Invalid address')
ret = mw.execShell('docker image pull %s' % path)
if 'invalid' in ret[-1]:
return mw.returnJson(False, '拉取失败,请检查镜像名称或是否需要登录docker进行下载')
else:
return mw.returnJson(True, '拉取成功!')
def dockerPullReg():
# pull Dockr 官方镜像
args = getArgs()
data = checkArgs(args, ['path'])
if not data[0]:
return data[1]
path = args['path']
return dockerPlulPath(path)
# 判断镜像是否存在
def checkImage(path):
image_list = imageList()
for i in image_list:
if path == i["RepoTags"]:
return mw.returnData(False, '镜像已存在!')
def dockerPullPrivateNew():
# pull Dockr 官方镜像
args = getArgs()
data = checkArgs(args, ['path'])
if not data[0]:
return data[1]
path = args['path']
check = checkImage(path)
if check:
return mw.getJson(check)
my_repo = repoList()
if not my_repo:
return mw.returnJson(False, '未登录任何私人存储库,请登录然后拉取')
return dockerPlulPath(path)
def imageListData():
try:
ilist = imageList()
except Exception as e:
return mw.returnJson(False, '未开启Docker')
return mw.returnJson(True, 'ok', ilist)
def dockerRemoveImage():
args = getArgs()
data = checkArgs(args, ['imageId', 'repoTags'])
if not data[0]:
return data[1]
repoTags = args['repoTags']
imageId = args['imageId']
c = getDClient()
try:
c.images.remove(repoTags)
return mw.returnJson(True, '成功删除')
except:
try:
c.images.remove(imageId)
return mw.returnJson(True, '成功删除!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '删除失败, 当前镜像正在使用!')
def getImageListFunc(dbname=''):
bkDir = mw.getRootDir() + '/backup/docker'
blist = os.listdir(bkDir)
r = []
bname = 'db_' + dbname
blen = len(bname)
for x in blist:
fbstr = x[0:blen]
if fbstr == bname:
r.append(x)
return r
def dockerImagePickDir():
bkDir = mw.getRootDir() + '/backup/docker'
return mw.returnJson(True, 'ok', bkDir)
def dockerImagePickList():
bkDir = mw.getRootDir() + '/backup/docker'
if not os.path.exists(bkDir):
os.mkdir(bkDir)
r = os.listdir(bkDir)
rr = []
for x in range(0, len(r)):
p = bkDir + '/' + r[x]
data = {}
data['name'] = r[x]
rsize = os.path.getsize(p)
data['size'] = mw.toSize(rsize)
t = os.path.getctime(p)
t = time.localtime(t)
data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', t)
rr.append(data)
data['file'] = p
return mw.returnJson(True, 'ok', rr)
def dockerImagePickSave():
# image 导出
args = getArgs()
data = checkArgs(args, ['images'])
if not data[0]:
return data[1]
bkDir = mw.getRootDir() + '/backup/docker/'
images = args['images']
try:
file_name = bkDir + \
str(time.strftime('%Y%m%d_%H%M%S', time.localtime())) + '.tar.gz'
mw.execShell('docker image save %s | gzip > %s' %
(images, file_name))
return mw.returnJson(True, '导出镜像 {} 成功!'.format(file_name))
except docker.errors.APIError as ex:
return mw.returnJson(False, '操作失败: ' + str(ex))
def dockerImagePickLoad():
# 镜像文件导入
args = getArgs()
data = checkArgs(args, ['file'])
if not data[0]:
return data[1]
try:
file_path = args['file']
if not os.path.exists(file_path):
return mw.returnJson(False, '文件不存在')
if file_path.endswith('.tar'):
mw.execShell('docker image load < %s' % file_path)
elif file_path.endswith('.tar.gz'):
mw.execShell('gunzip -c %s | docker image load' % file_path)
else:
return mw.returnJson(False, '不支持改文件类型!')
return mw.returnJson(True, '导入镜像文件成功!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '操作失败: ' + str(ex))
def dockerLoginCheck(user_name, user_pass, registry):
# 登陆验证
cmd = 'docker login -u=%s -p %s %s' % (user_name, user_pass, registry)
# print(cmd)
login_test = mw.execShell(cmd)
# print(login_test)
ret = 'required$|Error'
ret2 = re.findall(ret, login_test[-1])
if len(ret2) == 0:
return True
else:
return False
def getDockerIpListData():
# 取IP列表
path = getServerDir()
ipConf = path + '/iplist.json'
if not os.path.exists(ipConf):
return []
iplist = json.loads(mw.readFile(ipConf))
return iplist
def getDockerIpList():
data = getDockerIpListData()
return mw.returnJson(True, 'ok!', data)
def dockerAddIP():
# 添加IP
args = getArgs()
data = checkArgs(args, ['address', 'netmask', 'gateway'])
if not data[0]:
return data[1]
path = getServerDir()
ipConf = path + '/iplist.json'
if not os.path.exists(ipConf):
iplist = []
mw.writeFile(ipConf, json.dumps(iplist))
iplist = json.loads(mw.readFile(ipConf))
ipInfo = {
'address': args['address'],
'netmask': args['netmask'],
'gateway': args['gateway'],
}
iplist.append(ipInfo)
mw.writeFile(ipConf, json.dumps(iplist))
return mw.returnJson(True, '添加成功!')
def dockerDelIP():
# 删除IP
args = getArgs()
data = checkArgs(args, ['address'])
if not data[0]:
return data[1]
path = getServerDir()
ipConf = path + '/iplist.json'
if not os.path.exists(ipConf):
return mw.returnJson(False, '指定的IP不存在。!')
iplist = json.loads(mw.readFile(ipConf))
newList = []
for ipInfo in iplist:
if ipInfo['address'] == args['address']:
continue
newList.append(ipInfo)
mw.writeFile(ipConf, json.dumps(newList))
return mw.returnJson(True, '成功删除!')
def getDockerCreateInfo():
# 取创建依赖
import psutil
data = {}
data['images'] = imageList()
data['memSize'] = int(psutil.virtual_memory().total / 1024 / 1024)
data['iplist'] = getDockerIpListData()
return mw.returnJson(True, 'ok!', data)
def __release_port(port):
from collections import namedtuple
try:
import firewall_api
firewall_api.firewall_api().addAcceptPortArgs(port, 'docker', 'port')
return port
except Exception as e:
return "Release failed {}".format(e)
def dockerPortCheck():
args = getArgs()
data = checkArgs(args, ['port'])
if not data[0]:
return data[1]
port = args['port']
is_ok = IsPortExists(port)
if is_ok:
return mw.returnJson(True, 'ok')
return mw.returnJson(False, 'fail')
def IsPortExists(port):
# 判断端口是否被占用
ret = __check_dst_port(ip='localhost', port=port)
ret2 = __check_dst_port(ip='0.0.0.0', port=port)
if ret:
return ret
if not ret and ret2:
return ret2
if not ret and not ret2:
return False
def __check_dst_port(ip, port, timeout=3):
# 端口检测
import socket
ok = True
try:
s = socket.socket()
s.settimeout(timeout)
s.connect((ip, port))
s.close()
except:
ok = False
return ok
def dockerCreateCon():
args = getArgs()
data = checkArgs(args, ['environments', 'command',
'entrypoint', 'image', 'mem_limit', 'ports', 'volumes'])
if not data[0]:
return data[1]
environments = args['environments']
environments = environments.strip().split()
command = args['command']
entrypoint = args['entrypoint']
image = args['image']
mem_limit = args['mem_limit']
ports = args['ports']
ports = ports.replace('[', '(').replace(']', ')')
volumes = args['volumes']
# if __name__ == "__main__":
# print(args)
try:
c = getDClient()
conObject = c.containers.run(
image=image,
mem_limit=mem_limit + 'M',
ports=eval(ports),
auto_remove=False,
command=command,
detach=True,
stdin_open=True,
tty=True,
entrypoint=entrypoint,
privileged=True,
volumes=json.loads(volumes),
cpu_shares=10,
environment=environments
)
if conObject:
__release_port(ports)
return mw.returnJson(True, '创建成功!')
return mw.returnJson(False, '创建失败!')
except docker.errors.APIError as ex:
return mw.returnJson(False, '创建失败!' + str(ex))
def dockerLogin():
args = getArgs()
# print(args)
data = checkArgs(args, ['user', 'passwd', 'hub_name',
'namespace', 'registry', 'repository_name'])
if not data[0]:
return data[1]
user_name = args['user']
user_pass = args['passwd']
registry = args['registry']
hub_name = args['hub_name']
namespace = args['namespace']
repository_name = args['repository_name']
ret_status = dockerLoginCheck(user_name, user_pass, registry)
path = getServerDir()
if ret_status:
user_file = path + '/user.json'
user_info = mw.readFile(user_file)
if not user_info:
user_info = []
else:
user_info = json.loads(user_info)
ret = {}
ret['user_name'] = user_name
ret['user_pass'] = user_pass
ret['registry'] = registry
ret['hub_name'] = hub_name
ret['namespace'] = namespace
ret['repository_name'] = repository_name
if not registry:
ret['registry'] = "docker.io"
user_info.append(ret)
mw.writeFile(user_file, json.dumps(user_info))
return mw.returnJson(True, '成功登录!')
return mw.returnJson(False, '登录失败!')
# 删除用户信息
def delete_user_info(registry):
path = getServerDir()
user_file = path + '/user.json'
user_info = mw.readFile(user_file)
if user_info:
user_info = json.loads(user_info)
for i in range(len(user_info)):
if registry in user_info[i].values():
del(user_info[i])
mw.writeFile(user_file, json.dumps(user_info))
return True
def dockerLogout():
args = getArgs()
data = checkArgs(args, ['registry'])
if not data[0]:
return data[1]
registry = args['registry']
if registry == "docker.io":
registry = ""
login_test = mw.execShell('docker logout %s' % registry)
if registry == "":
registry = "docker.io"
ret = 'required$|Error'
ret2 = re.findall(ret, login_test[-1])
delete_user_info(registry)
if len(ret2) == 0:
return mw.returnJson(True, '退出成功')
else:
return mw.returnJson(True, '退出失败')
def repoList():
path = getServerDir()
repostory_info = []
user_file = path + '/user.json'
if os.path.exists(user_file):
user_info = mw.readFile(user_file)
user_info = json.loads(user_info)
for i in user_info:
tmp = {}
tmp["hub_name"] = i["hub_name"]
tmp["registry"] = i["registry"]
tmp["namespace"] = i["namespace"]
tmp['repository_name'] = i["repository_name"]
repostory_info.append(tmp)
return mw.returnJson(True, 'ok', repostory_info)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'conf':
print(getConf())
elif func == 'con_list':
print(conListData())
elif func == 'docker_con_log':
print(dockerLogCon())
elif func == 'docker_remove_con':
print(dockerRemoveCon())
elif func == 'docker_run_con':
print(dockerRunCon())
elif func == 'docker_stop_con':
print(dockerStopCon())
elif func == 'docker_exec':
print(dockerExec())
elif func == 'docker_pull':
print(dockerPull())
elif func == 'docker_pull_reg':
print(dockerPullReg())
elif func == 'image_list':
print(imageListData())
elif func == 'image_pick_dir':
print(dockerImagePickDir())
elif func == 'image_pick_save':
print(dockerImagePickSave())
elif func == 'image_pick_load':
print(dockerImagePickLoad())
elif func == 'image_pick_list':
print(dockerImagePickList())
elif func == 'docker_get_iplist':
print(getDockerIpList())
elif func == 'docker_del_ip':
print(dockerDelIP())
elif func == 'docker_add_ip':
print(dockerAddIP())
elif func == 'get_docker_create_info':
print(getDockerCreateInfo())
elif func == 'docker_create_con':
print(dockerCreateCon())
elif func == 'docker_remove_image':
print(dockerRemoveImage())
elif func == 'docker_port_check':
print(dockerPortCheck())
elif func == 'docker_login':
print(dockerLogin())
elif func == 'docker_logout':
print(dockerLogout())
elif func == 'repo_list':
print(repoList())
else:
print('error')
+19
View File
@@ -0,0 +1,19 @@
{
"sort": 7,
"ps": "Docker是一个开源的应用容器引擎",
"name": "docker",
"title": "Docker",
"shell": "install.sh",
"versions":["1.0"],
"updates":["1.0"],
"tip": "soft",
"checks": "server/docker",
"path": "server/docker",
"display": 1,
"author": "Zend",
"date": "2017-04-01",
"home": "https://docker.io",
"doc1":"https://docker-py.readthedocs.io/",
"type": 0,
"pid": "2"
}
+84
View File
@@ -0,0 +1,84 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
# cd /www/server/mdserver-web/plugins/docker && /bin/bash install.sh uninstall 1.0
# cd /www/server/mdserver-web/plugins/docker && /bin/bash install.sh install 1.0
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
Install_Docker()
{
# which docker
# if [ "$?" == "0" ];then
# echo '安装已经完成docker' > $install_tmp
# exit 0
# fi
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
if [ ! -d $serverPath/docker ];then
curl -fsSL https://get.docker.com | bash
mkdir -p $serverPath/docker
fi
pip install docker
pip install pytz
if [ -d $serverPath/docker ];then
echo "${VERSION}" > $serverPath/docker/version.pl
echo '安装完成' > $install_tmp
cd ${rootPath} && python3 ${rootPath}/plugins/docker/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/docker/index.py initd_install
fi
}
Uninstall_Docker()
{
CMD=yum
which apt
if [ "$?" == "0" ];then
CMD=apt
fi
if [ -f /usr/lib/systemd/system/docker.service ];then
systemctl stop docker
systemctl disable docker
rm -rf /usr/lib/systemd/system/docker.service
systemctl daemon-reload
fi
$CMD remove -y docker docker-ce-cli containerd.io
# docker-client \
# docker-client-latest \
# docker-common \
# docker-latest \
# docker-latest-logrotate \
# docker-logrotate \
# docker-selinux \
# docker-engine-selinux \
# docker-engine \
# docker-ce
rm -rf $serverPath/docker
echo "Uninstall_Docker" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_Docker
else
Uninstall_Docker
fi
+1084
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -33,7 +33,11 @@ if [ ! -d $WEB_PATH ];then
mkdir -p $WEB_PATH mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
else else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH if [ -f $GIT_PROJECT_DIR/exclude.list ];then
rsync -vauP --delete --exclude-from="$GIT_PROJECT_DIR/exclude.list" $GIT_PROJECT_DIR/ $WEB_PATH
else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
fi
fi fi
sysName=`uname` sysName=`uname`
+2 -2
View File
@@ -1,8 +1,8 @@
{ {
"ps": "Gitea 是一个开源社区驱动的轻量级代码托管解决方案。", "ps": "Gitea是一个开源社区驱动的轻量级代码托管解决方案。",
"name": "gitea", "name": "gitea",
"title": "Gitea", "title": "Gitea",
"versions": ["1.17.2"], "versions": ["1.17.2","1.18.5"],
"tip": "soft", "tip": "soft",
"install_pre_inspection":false, "install_pre_inspection":false,
"uninstall_pre_inspection":true, "uninstall_pre_inspection":true,
+1 -1
View File
@@ -14,7 +14,7 @@ if [ -f ${rootPath}/bin/activate ];then
fi fi
URL_DOWNLOAD=https://dl.gitea.io/ URL_DOWNLOAD=https://dl.gitea.com
bash ${rootPath}/scripts/getos.sh bash ${rootPath}/scripts/getos.sh
+2 -2
View File
@@ -739,7 +739,7 @@ def importDbBackup():
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root') pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile() sock = getSocketFile()
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \ mysql_cmd = getServerDir() + '/bin/mariadb -S ' + sock + ' -uroot -p' + pwd + \
' ' + name + ' < ' + file_path_sql ' ' + name + ' < ' + file_path_sql
# print(mysql_cmd) # print(mysql_cmd)
@@ -800,7 +800,7 @@ def importDbExternal():
sock = getSocketFile() sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd os.environ["MYSQL_PWD"] = pwd
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \ mysql_cmd = getServerDir() + '/bin/mariadb -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql pwd + ' ' + name + ' < ' + import_sql
# print(mysql_cmd) # print(mysql_cmd)
+1 -1
View File
@@ -8,7 +8,7 @@
"uninstall_pre_inspection":true, "uninstall_pre_inspection":true,
"checks": "server/mariadb", "checks": "server/mariadb",
"path": "server/mariadb", "path": "server/mariadb",
"versions":["10.6","10.7","10.8","10.9"], "versions":["10.6","10.7","10.8","10.9","10.11","11.0"],
"shell":"install.sh", "shell":"install.sh",
"checks":"server/mariadb", "checks":"server/mariadb",
"path":"server/mariadb", "path":"server/mariadb",
+1 -1
View File
@@ -1185,7 +1185,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.11.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
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 ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+1 -1
View File
@@ -13,7 +13,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.6.9 MY_VER=10.6.12
Install_app() Install_app()
{ {
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.7.4 MY_VER=10.7.8
Install_app() Install_app()
{ {
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.8.5 MY_VER=10.8.7
Install_app() Install_app()
{ {
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.9.2 MY_VER=10.9.5
Install_app() Install_app()
{ {
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.0.1
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
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 ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+2 -1
View File
@@ -2474,7 +2474,8 @@ def doFullSyncUser(version=''):
if not os.path.exists(bak_file): if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \ dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
mw.execShell(dump_sql_data) mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40}) writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+1 -1
View File
@@ -1208,7 +1208,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+2 -1
View File
@@ -2434,7 +2434,8 @@ def doFullSyncUser(version=''):
if not os.path.exists(bak_file): if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \ dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
mw.execShell(dump_sql_data) mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40}) writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+1 -1
View File
@@ -1208,7 +1208,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+1 -1
View File
@@ -39,7 +39,7 @@ max_connections = 500
max_connect_errors = 100 max_connect_errors = 100
open_files_limit = 65535 open_files_limit = 65535
skip-name-resolve=1 skip_name_resolve=1
#skip-grant-tables #skip-grant-tables
#skip-networking #skip-networking
#skip-external-locking #skip-external-locking
+1 -1
View File
@@ -41,7 +41,7 @@ max_connections = 500
max_connect_errors = 100 max_connect_errors = 100
open_files_limit = 65535 open_files_limit = 65535
skip-name-resolve=1 skip_name_resolve=1
#skip-grant-tables #skip-grant-tables
#skip-networking #skip-networking
#skip-external-locking #skip-external-locking
+3 -2
View File
@@ -17,6 +17,7 @@ datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID} server-id = {$SERVER_ID}
explicit_defaults_for_timestamp=true
default_storage_engine = InnoDB default_storage_engine = InnoDB
@@ -40,7 +41,7 @@ max_connect_errors = 100
open_files_limit = 2560 open_files_limit = 2560
max_allowed_packet = 128M max_allowed_packet = 128M
skip_name_resolve = 1 skip_name_resolve=1
skip-ssl skip-ssl
#skip-networking #skip-networking
#skip-external-locking #skip-external-locking
@@ -95,7 +96,7 @@ innodb_file_per_table = 1
innodb_large_prefix = 1 innodb_large_prefix = 1
secure-file-priv={$SERVER_APP_PATH}/tmp secure-file-priv={$SERVER_APP_PATH}/tmp
#secure-file-priv=disabled
[mysqldump] [mysqldump]
quick quick
+4 -4
View File
@@ -8,8 +8,8 @@ default-character-set = UTF8MB4
[mysqld] [mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf !include {$SERVER_APP_PATH}/etc/mode/classic.cnf
sha256_password_private_key_path=mysql.pem sha256_password_private_key_path={$SERVER_APP_PATH}/data/mysql.pem
sha256_password_public_key_path=mysql.pub sha256_password_public_key_path={$SERVER_APP_PATH}/data/mysql.pub
authentication_policy=mysql_native_password authentication_policy=mysql_native_password
pid-file = {$SERVER_APP_PATH}/data/mysql.pid pid-file = {$SERVER_APP_PATH}/data/mysql.pid
@@ -40,7 +40,7 @@ max_connect_errors = 100
open_files_limit = 2560 open_files_limit = 2560
max_allowed_packet = 128M max_allowed_packet = 128M
skip_name_resolve = 1 skip_name_resolve=1
#skip-networking #skip-networking
#skip-external-locking #skip-external-locking
#loose-skip-innodb #loose-skip-innodb
@@ -71,7 +71,7 @@ log_replica_updates = 1
# Prevent replication from starting automatically with MySQL # Prevent replication from starting automatically with MySQL
#skip_replica_start = 1 #skip_replica_start = 1
#replicate-do-db #replicate-do-db
slave_skip_errors=1062 replica_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1 -1
View File
@@ -16,7 +16,7 @@
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p> <p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div> </div>
<div class="bt-w-con pd15"> <div class="bt-w-con pd15">
<div class="soft-man-con" style="height: 530px; overflow: auto;"></div> <div class="soft-man-con"></div>
</div> </div>
</div> </div>
+26 -13
View File
@@ -167,7 +167,6 @@ def pMysqlDb():
def makeInitRsaKey(version=''): def makeInitRsaKey(version=''):
datadir = getServerDir() + "/data" datadir = getServerDir() + "/data"
mysql_pem = datadir + "/mysql.pem" mysql_pem = datadir + "/mysql.pem"
if not os.path.exists(mysql_pem): if not os.path.exists(mysql_pem):
rdata = mw.execShell( rdata = mw.execShell(
@@ -176,12 +175,11 @@ def makeInitRsaKey(version=''):
rdata = mw.execShell( rdata = mw.execShell(
'cd ' + datadir + ' && openssl rsa -in mysql.pem -pubout -out mysql.pub') 'cd ' + datadir + ' && openssl rsa -in mysql.pem -pubout -out mysql.pub')
# print(rdata) # print(rdata)
if not mw.isAppleSystem():
if not mw.isAppleSystem(): mw.execShell('cd ' + datadir + ' && chmod 400 mysql.pem')
mw.execShell('cd ' + datadir + ' && chmod 400 mysql.pem') mw.execShell('cd ' + datadir + ' && chmod 444 mysql.pub')
mw.execShell('cd ' + datadir + ' && chmod 444 mysql.pub') mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pem')
mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pem') mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pub')
mw.execShell('cd ' + datadir + ' && chown mysql:mysql mysql.pub')
def initDreplace(version=''): def initDreplace(version=''):
@@ -251,6 +249,14 @@ def initDreplace(version=''):
return file_bin return file_bin
def process_status():
cmd = "ps -ef|grep mysql |grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def status(version=''): def status(version=''):
path = getConf() path = getConf()
if not os.path.exists(path): if not os.path.exists(path):
@@ -383,7 +389,7 @@ def initMysql57Data():
myconf = serverdir + "/etc/my.cnf" myconf = serverdir + "/etc/my.cnf"
user = pGetDbUser() user = pGetDbUser()
cmd = 'cd ' + serverdir + ' && ./bin/mysqld --defaults-file=' + myconf + \ cmd = 'cd ' + serverdir + ' && ./bin/mysqld --defaults-file=' + myconf + \
' --initialize-insecure --explicit_defaults_for_timestamp' ' --initialize-insecure --explicit_defaults_for_timestamp --user=mysql'
data = mw.execShell(cmd) data = mw.execShell(cmd)
# print(data) # print(data)
return False return False
@@ -450,7 +456,7 @@ def initMysqlPwd():
def initMysql8Pwd(): def initMysql8Pwd():
time.sleep(2) time.sleep(8)
serverdir = getServerDir() serverdir = getServerDir()
myconf = serverdir + "/etc/my.cnf" myconf = serverdir + "/etc/my.cnf"
@@ -540,7 +546,12 @@ def my8cmd(version, method):
else: else:
mw.execShell('systemctl start mysql') mw.execShell('systemctl start mysql')
initMysql8Pwd() for x in range(10):
mydb_status = process_status()
if mydb_status == 'start':
initMysql8Pwd()
break
time.sleep(1)
if mw.isAppleSystem(): if mw.isAppleSystem():
cmd_init_stop = init_file + ' stop' cmd_init_stop = init_file + ' stop'
@@ -562,11 +573,11 @@ def my8cmd(version, method):
def appCMD(version, action): def appCMD(version, action):
makeInitRsaKey(version)
if version == '8.0' or version == '5.7': if version == '8.0' or version == '5.7':
status = my8cmd(version, action) status = my8cmd(version, action)
else: else:
status = myOp(version, action) status = myOp(version, action)
makeInitRsaKey(version)
return status return status
@@ -2665,8 +2676,10 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20}) writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file): if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \ dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + "\" " + sync_db + " > " + bak_file port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data) mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40}) writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+2 -2
View File
@@ -181,7 +181,7 @@ function changeMySQLDataPath(act) {
$.post('/database?action=GetMySQLInfo', '', function(rdata) { $.post('/database?action=GetMySQLInfo', '', function(rdata) {
var LimitCon = '<p class="conf_p">\ var LimitCon = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\ <input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\ <span onclick="changePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>'; </p>';
$(".soft-man-con").html(LimitCon); $(".soft-man-con").html(LimitCon);
}); });
@@ -1208,7 +1208,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+1
View File
@@ -86,6 +86,7 @@ Install_mysql()
make -j${cpuCore} && make install && make clean make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mysql ];then if [ -d $serverPath/mysql ];then
rm -rf ${mysqlDir}/mysql-${VERSION}
echo '5.5' > $serverPath/mysql/version.pl echo '5.5' > $serverPath/mysql/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp
else else
+1
View File
@@ -105,6 +105,7 @@ Install_mysql()
if [ -d $serverPath/mysql ];then if [ -d $serverPath/mysql ];then
rm -rf ${mysqlDir}/mysql-${VERSION}
echo '5.6' > $serverPath/mysql/version.pl echo '5.6' > $serverPath/mysql/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp
else else
+1
View File
@@ -118,6 +118,7 @@ Install_mysql()
make -j${cpuCore} && make install && make clean make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mysql ];then if [ -d $serverPath/mysql ];then
rm -rf ${mysqlDir}/mysql-${VERSION}
echo '5.7' > $serverPath/mysql/version.pl echo '5.7' > $serverPath/mysql/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp
else else
+1
View File
@@ -210,6 +210,7 @@ Install_mysql()
make -j${cpuCore} && make install && make clean make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mysql ];then if [ -d $serverPath/mysql ];then
rm -rf ${mysqlDir}/mysql-${VERSION}
echo '8.0' > $serverPath/mysql/version.pl echo '8.0' > $serverPath/mysql/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp
else else
Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

+26
View File
@@ -0,0 +1,26 @@
<div class="bt-form">
<div class="bt-w-main">
<div class='plugin_version'></div>
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('nezha',$('.plugin_version').attr('version'));">面板服务</p>
<p onclick="pluginInitD('nezha',$('.plugin_version').attr('version'));">面板自启动</p>
<p onclick="nezha.cfg($('.plugin_version').attr('version'));">面板配置</p>
<p onclick="pluginConfig('nezha', $('.plugin_version').attr('version'), 'conf');">面板配置文件</p>
<p onclick="pluginService('nezha', $('.plugin_version').attr('version'), 'agent');">AGENT服务</p>
<p onclick="pluginInitD('nezha', $('.plugin_version').attr('version'), 'agent');">AGENT自启动</p>
<p onclick="nezha.agent_cfg($('.plugin_version').attr('version'));">AGENT配置</p>
<p onclick="nezha.readme();">说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(530);
$.getScript( "/plugins/file?name=nezha&f=js/nezha.js", function(){
nezha.init();
pluginService('nezha');
});
</script>
+364
View File
@@ -0,0 +1,364 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import socket
import json
from datetime import datetime
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
class App:
__setupPath = '/www/server/nezha'
__cfg = ''
__agent_cfg = ''
def __init__(self):
self.__setupPath = self.getServerDir()
self.__cfg = self.__setupPath + '/nezha.cfg'
self.__agent_cfg = self.__setupPath + '/agent.cfg'
def getArgs(self):
args = sys.argv[3:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':', 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(self, 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 __release_port(self, port):
from collections import namedtuple
try:
import firewall_api
firewall_api.firewall_api().addAcceptPortArgs(port, 'nezha', 'port')
return port
except Exception as e:
return "Release failed {}".format(e)
def openPort(self):
for i in ["9527", "5555"]:
self.__release_port(i)
return True
def getPluginName(self):
return 'nezha'
def getPluginDir(self):
return mw.getPluginDir() + '/' + self.getPluginName()
def getServerDir(self):
return mw.getServerDir() + '/' + self.getPluginName()
def getInitdConfTpl(self):
path = self.getPluginDir() + "/init.d/nezha.tpl"
return path
def getInitdAgentConfTpl(self):
path = self.getPluginDir() + "/init.d/nezha-agent.tpl"
return path
def getHomeDir(self):
if mw.isAppleSystem():
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return '/Users/' + user
else:
return '/root'
def getRunUser(self):
if mw.isAppleSystem():
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return user
else:
return 'root'
def status(self):
cmd = "ps -ef|grep " + self.getPluginName() + \
" |grep -v grep | grep -v nezha-agent | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return "stop"
return 'start'
def status_agent(self):
cmd = "ps -ef | grep nezha-agent | grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def contentReplace(self, content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$RUN_USER}', self.getRunUser())
content = content.replace('{$HOME_DIR}', self.getHomeDir())
return content
def initDreplace(self):
file_tpl = self.getInitdConfTpl()
service_path = mw.getServerDir()
initD_path = self.getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
self.openPort()
file_bin = initD_path + '/' + self.getPluginName()
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = self.contentReplace(content)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/nezha.service'
systemServiceTpl = self.getPluginDir() + '/init.d/nezha.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = self.contentReplace(se_content)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def contentAgentReplace(self, content):
path = self.__agent_cfg
if os.path.exists(path):
data = self.get_agent_cfg()
content = content.replace('{$APP_HOST}', data['host'])
content = content.replace('{$APP_SECRET}', data['secret'])
return content
def initDAgent(self):
file_tpl = self.getInitdAgentConfTpl()
initD_path = self.getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_agent_bin = initD_path + '/nezha-agent'
content = mw.readFile(file_tpl)
content = self.contentReplace(content)
content = self.contentAgentReplace(content)
mw.writeFile(file_agent_bin, content)
mw.execShell('chmod +x ' + file_agent_bin)
# systemd
sysDir = mw.systemdCfgDir()
sysService = sysDir + '/nezha-agent.service'
sysServiceTpl = self.getPluginDir() + '/init.d/nezha-agent.service.tpl'
service_path = mw.getServerDir()
content = mw.readFile(sysServiceTpl)
content = self.contentReplace(content)
content = self.contentAgentReplace(content)
mw.writeFile(sysService, content)
mw.execShell('systemctl daemon-reload')
return file_agent_bin
def init_cfg(self):
self.initDreplace()
self.initDAgent()
def imOp(self, method):
file = self.initDreplace()
if not mw.isAppleSystem():
cmd = 'systemctl {} {}'.format(method, self.getPluginName())
data = mw.execShell(cmd)
if data[1] == '':
return 'ok'
return 'fail'
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[0]
def start(self):
return self.imOp('start')
def stop(self):
return self.imOp('stop')
def restart(self):
return self.imOp('restart')
def reload(self):
return self.imOp('reload')
def agOp(self, method):
file = self.initDAgent()
path = self.__agent_cfg
if not os.path.exists(path):
return '请先设置Agent配置!'
if not mw.isAppleSystem():
cmd = 'systemctl {} {}'.format(method, 'nezha-agent')
data = mw.execShell(cmd)
if data[1] == '':
return 'ok'
return 'fail'
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[0]
def start_agent(self):
return self.agOp('start')
def stop_agent(self):
return self.agOp('stop')
def restart_agent(self):
return self.agOp('restart')
def reload_agent(self):
return self.agentOp('reload')
def initd_status(self):
cmd = 'systemctl status nezha | grep loaded | grep "enabled;"'
data = mw.execShell(cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initd_install(self):
mw.execShell('systemctl enable nezha')
return 'ok'
def initd_uninstall(self):
mw.execShell('systemctl disable nezha')
return 'ok'
def initd_status_agent(self):
cmd = 'systemctl status nezha-agent | grep loaded | grep "enabled;"'
data = mw.execShell(cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initd_install_agent(self):
mw.execShell('systemctl enable nezha-agent')
return 'ok'
def initd_uninstall_agent(self):
mw.execShell('systemctl disable nezha-agent')
return 'ok'
def conf(self):
return self.getServerDir() + '/dashboard/data/config.yaml'
def nezha_cfg(self):
path = self.__cfg
if not os.path.exists(path):
d = {}
cmd_un = 'cd ' + self.getServerDir() + '/dashboard && ./nezha conf -u ""'
mw.execShell(cmd_un)
td = mw.execShell(cmd_un)
d['username'] = td[0].strip()
pwd = mw.getRandomString(16)
cmd_pwd = 'cd ' + self.getServerDir() + '/dashboard && ./nezha conf -u "" -p ' + pwd
td = mw.execShell(cmd_pwd)
d['password'] = pwd
mw.writeFile(path, mw.enDoubleCrypt('nezha', mw.getJson(d)))
info = mw.readFile(path)
info = mw.deDoubleCrypt('nezha', info)
info = json.loads(info)
return mw.returnJson(True, 'ok', info)
def nezha_save_cfg(self):
args = self.getArgs()
data = self.checkArgs(args, ['username', 'password'])
if not data[0]:
return data[1]
path = self.__cfg
cmd = 'cd ' + self.getServerDir() + '/dashboard && ./nezha conf -su "' + \
args['username'] + '" -p ' + args['password']
# print(cmd)
t = mw.execShell(cmd)
# print(t)
mw.writeFile(path, mw.enDoubleCrypt('nezha', mw.getJson(args)))
return mw.returnJson(True, '修改成功!')
def get_agent_cfg(self):
path = self.__agent_cfg
info = mw.readFile(path)
info = mw.deDoubleCrypt('agent', info)
info = json.loads(info)
return info
def agent_cfg(self):
path = self.__agent_cfg
if not os.path.exists(path):
d = {}
d['host'] = '127.0.0.1:5555'
d['secret'] = 'secret'
mw.writeFile(path, mw.enDoubleCrypt('agent', mw.getJson(d)))
info = self.get_agent_cfg()
return mw.returnJson(True, 'ok', info)
def agent_save_cfg(self):
args = self.getArgs()
data = self.checkArgs(args, ['host', 'secret'])
if not data[0]:
return data[1]
path = self.__agent_cfg
mw.writeFile(path, mw.enDoubleCrypt('agent', mw.getJson(args)))
return mw.returnJson(True, '修改成功!')
def run_log(self):
return self.getServerDir() + '/logs/nezha.log'
if __name__ == "__main__":
func = sys.argv[1]
classApp = App()
try:
data = eval("classApp." + func + "()")
print(data)
except Exception as e:
print('error:' + str(e))
+18
View File
@@ -0,0 +1,18 @@
{
"sort": 7,
"ps": "哪吒监控面板/改造版",
"name": "nezha",
"title": "哪吒监控",
"shell": "install.sh",
"versions":["0.15.2"],
"tip": "soft",
"checks": "server/nezha",
"path": "server/nezha",
"display": 1,
"author": "midoks",
"date": "2023-06-26",
"home": "https://github.com/midoks/nezha",
"doc1": "https://nezha.wiki/",
"type": 0,
"pid": "5"
}
@@ -0,0 +1,30 @@
[Unit]
Description=Nezha Agent
After=syslog.target
#After=network.target
#After=nezha-dashboard.service
[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
Type=simple
User=root
Group=root
WorkingDirectory={$SERVER_PATH}/nezha/agent/
ExecStart={$SERVER_PATH}/nezha/agent/nezha-agent -s {$APP_HOST} -p {$APP_SECRET}
Restart=always
#Environment=DEBUG=true
# Some distributions may not support these hardening directives. If you cannot start the service due
# to an unknown option, comment out the ones not supported by your version of systemd.
#ProtectSystem=full
#PrivateDevices=yes
#PrivateTmp=yes
#NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
+90
View File
@@ -0,0 +1,90 @@
#!/bin/bash
# chkconfig: 2345 55 25
# description: Nezha Agent Service
### BEGIN INIT INFO
# Provides: Nezha Agent
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts Nezha Agent
# Description: starts the Nezha Agent
### END INIT INFO
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
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
SERVICENAME=nezha-agent
LOG_PATH={$SERVER_PATH}/nezha/logs
APP_PATH={$SERVER_PATH}/nezha/agent
APP_HOST={$APP_HOST}
APP_SECRET={$APP_SECRET}
app_start(){
isStart=`ps -ef|grep "${SERVICENAME}" | grep -v grep | grep -v python | grep -v "/bin/bash" | awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "Starting ${SERVICENAME}... \c"
cd $APP_PATH
exec nohup ${APP_PATH}/${SERVICENAME} -d -s ${APP_HOST} -p ${APP_SECRET} >> ${LOG_PATH}/${SERVICENAME}.log 2>&1 &
isStart=""
while [[ "$isStart" == "" ]];
do
echo -e ".\c"
sleep 0.5
isStart=$(ps -ef|grep "${SERVICENAME}" |grep -v grep | grep -v python | grep -v "/bin/bash" | awk '{print $2}')
let n+=1
if [ $n -gt 15 ];then
break;
fi
done
if [ "$isStart" == '' ];then
echo -e "\033[31mError: ${SERVICENAME} service startup failed.\033[0m"
return;
fi
echo -e "\033[32mdone\033[0m"
else
echo "Starting ${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
app_stop(){
pids=`ps -ef | grep "${SERVICENAME}" | grep -v grep | grep -v python | grep -v "/bin/bash" |awk '{print $2}'`
arr=($pids)
echo -e "Stopping ${SERVICENAME}... \c"
for p in ${arr[@]}
do
# echo "$p"
kill -9 $p
done
echo -e "\033[32mdone\033[0m"
}
app_status(){
isStart=`ps -ef | grep "${SERVICENAME}" | grep -v grep | grep -v python | grep -v "/bin/bash" | awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "${SERVICENAME} not running"
else
echo -e "${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
case "$1" in
'start') app_start;;
'stop') app_stop;;
'status') app_status;;
'reload')
app_stop
app_start;;
'restart')
app_stop
app_start;;
esac
+30
View File
@@ -0,0 +1,30 @@
[Unit]
Description=Nezha Dashborad
After=syslog.target
After=network.target
After=mariadb.service mysqld.service postgresql.service memcached.service redis.service
[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
Type=simple
#User=root
#Group=root
WorkingDirectory={$SERVER_PATH}/nezha/dashboard/
ExecStart={$SERVER_PATH}/nezha/dashboard/nezha web
Restart=always
#Environment=DEBUG=true
# Some distributions may not support these hardening directives. If you cannot start the service due
# to an unknown option, comment out the ones not supported by your version of systemd.
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
+87
View File
@@ -0,0 +1,87 @@
#!/bin/bash
# chkconfig: 2345 55 25
# description: Nezha Service
### BEGIN INIT INFO
# Provides: Nezha
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts Nezha
# Description: starts the Nezha
### END INIT INFO
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
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
SERVICENAME=nezha
LOG_PATH={$SERVER_PATH}/${SERVICENAME}/logs
APP_PATH={$SERVER_PATH}/${SERVICENAME}/dashboard
app_start(){
isStart=`ps -ef|grep "${SERVICENAME} web" | grep -v grep | grep -v python | grep -v "/bin/bash" | awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "Starting ${SERVICENAME}... \c"
cd $APP_PATH && exec nohup ${APP_PATH}/${SERVICENAME} web >> ${LOG_PATH}/${SERVICENAME}.log 2>&1 &
isStart=""
while [[ "$isStart" == "" ]];
do
echo -e ".\c"
sleep 0.5
isStart=$(ps -ef|grep "${SERVICENAME} web" |grep -v grep | grep -v python | grep -v "/bin/bash" | awk '{print $2}')
let n+=1
if [ $n -gt 15 ];then
break;
fi
done
if [ "$isStart" == '' ];then
echo -e "\033[31mError: ${SERVICENAME} service startup failed.\033[0m"
return;
fi
echo -e "\033[32mdone\033[0m"
else
echo "Starting ${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
app_stop(){
pids=`ps -ef | grep "${SERVICENAME} web" | grep -v grep | grep -v python | grep -v "/bin/bash" |awk '{print $2}'`
arr=($pids)
echo -e "Stopping ${SERVICENAME}... \c"
for p in ${arr[@]}
do
# echo "$p"
kill -9 $p
done
echo -e "\033[32mdone\033[0m"
}
app_status(){
isStart=`ps -ef | grep "${SERVICENAME} web" | grep -v grep | grep -v python | grep -v "/bin/bash" | awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "${SERVICENAME} not running"
else
echo -e "${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
case "$1" in
'start') app_start;;
'stop') app_stop;;
'status') app_status;;
'reload')
app_stop
app_start;;
'restart')
app_stop
app_start;;
esac
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
type=$2
if [ "${2}" == "" ];then
echo '缺少安装脚本...' > $install_tmp
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
echo '缺少安装脚本2...' > $install_tmp
exit 0
fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "uninstall" ];then
if [ -f /usr/lib/systemd/system/nezha.service ] || [ -f /lib/systemd/system/nezha.service ] ;then
systemctl stop nezha
systemctl disable nezha
rm -rf /usr/lib/systemd/system/nezha.service
rm -rf /lib/systemd/system/nezha.service
systemctl daemon-reload
fi
if [ -f /usr/lib/systemd/system/nezha-agent.service ] || [ -f /lib/systemd/system/nezha-agent.service ] ;then
systemctl stop nezha-agent
systemctl disable nezha-agent
rm -rf /usr/lib/systemd/system/nezha-agent.service
rm -rf /lib/systemd/system/nezha-agent.service
systemctl daemon-reload
fi
fi
+184
View File
@@ -0,0 +1,184 @@
var nezha = {
plugin_name: 'nezha',
init: function () {
var _this = this;
},
send:function(info){
var tips = info['tips'];
var method = info['method'];
var args = info['data'];
var callback = info['success'];
var loadT = layer.msg(tips, { icon: 16, time: 0, shade: 0.3 });
var data = {};
data['name'] = 'nezha';
data['func'] = method;
data['version'] = $('.plugin_version').attr('version');
if (typeof(args) == 'string'){
data['args'] = JSON.stringify(toArrayObject(args));
} else {
data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', data, function(res) {
layer.close(loadT);
if (!res.status){
layer.msg(res.msg,{icon:2,time:10000});
return;
}
var ret_data = $.parseJSON(res.data);
console.log("send:",ret_data);
// if (!ret_data.status){
// layer.msg(ret_data.msg,{icon:2,time:2000});
// return;
// }
// console.log("send2:",ret_data);
if(typeof(callback) == 'function'){
callback(ret_data);
}
},'json');
},
postCallback:function(info){
var tips = info['tips'];
var method = info['method'];
var args = info['data'];
var callback = info['success'];
var loadT = layer.msg(tips, { icon: 16, time: 0, shade: 0.3 });
var data = {};
data['name'] = 'nezha';
data['func'] = method;
data['version'] = $('.plugin_version').attr('version');
if (typeof(args) == 'string'){
data['args'] = JSON.stringify(toArrayObject(args));
} else {
data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', data, function(res) {
layer.close(loadT);
if (!res.status){
layer.msg(res.msg,{icon:2,time:10000});
return;
}
var ret_data = $.parseJSON(res.data);
if (!ret_data.status){
layer.msg(ret_data.msg,{icon:2,time:2000});
return;
}
if(typeof(callback) == 'function'){
callback(res);
}
},'json');
},
repeatPwd:function (a, id) {
$("#"+id).val(randomStrPwd(a))
},
save_cfg:function(version){
var username = $("input[name='username']").val();
var password = $("input[name='password']").val();
this.send({
tips:'正在设置中...',
data:{'username':username,'password':password},
method:'nezha_save_cfg',
success:function(rdata){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
}
});
},
cfg:function(version){
this.send({
tips:'正在获取中...',
method:'nezha_cfg',
success:function(data){
var d = data.data;
var value = '<p>\
<span>用户名</span>\
<input id="nz_username" style="width: 160px;" class="bt-input-text mr5" name="username" value="'+d['username']+'" type="text">\
,<span title="随机用户名" class="glyphicon glyphicon-repeat cursor" onclick="nezha.repeatPwd(8,\'nz_username\')"></span>\
</p>';
value += '<p>\
<span>密码</span>\
<input id="nz_password" style="width: 160px;" class="bt-input-text mr5" name="password" value="'+d['password']+'" type="text">\
,<span title="随机密码" class="glyphicon glyphicon-repeat cursor" onclick="nezha.repeatPwd(16,\'nz_password\')"></span>\
</p>';
var conf = '<style>.conf_p p{margin-bottom: 2px;} .conf_p span {width: 50px;}</style><div class="conf_p" style="margin-bottom:0">\
' + value + '\
<div style="margin-top:10px; padding-right:15px" class="text-right">\
<button class="btn btn-success btn-sm mr5" onclick="nezha.cfg(\'' + version + '\')">刷新</button>\
<button class="btn btn-success btn-sm" onclick="nezha.save_cfg(\'' + version + '\')">保存</button>\
</div>\
</div>'
$(".soft-man-con").html(conf);
}
});
},
agent_save_cfg:function(version){
var host = $("input[name='host']").val();
var secret = $("input[name='secret']").val();
this.send({
tips:'正在设置中...',
data:{'host':host,'secret':secret},
method:'agent_save_cfg',
success:function(rdata){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
}
});
},
agent_cfg:function(version){
this.send({
tips:'正在获取中...',
method:'agent_cfg',
success:function(data){
var d = data.data;
var value = '<p>\
<span>地址</span>\
<input id="nz_username" style="width: 160px;" class="bt-input-text mr5" name="host" value="'+d['host']+'" type="text">\
,<font>如1.1.1.1:5444</font>\
</p>';
value += '<p>\
<span>密钥</span>\
<input id="nz_password" style="width: 160px;" class="bt-input-text mr5" name="secret" value="'+d['secret']+'" type="text">\
,<font>密钥</font>\
</p>';
var conf = '<style>.conf_p p{margin-bottom: 2px;} .conf_p span {width: 50px;}</style><div class="conf_p" style="margin-bottom:0">\
' + value + '\
<div style="margin-top:10px; padding-right:15px" class="text-right">\
<button class="btn btn-success btn-sm mr5" onclick="nezha.agent_cfg(\'' + version + '\')">刷新</button>\
<button class="btn btn-success btn-sm" onclick="nezha.agent_save_cfg(\'' + version + '\')">保存</button>\
</div>\
</div>'
$(".soft-man-con").html(conf);
}
});
},
readme:function (){
var readme = '<ul class="help-info-text c7">';
readme += '<li>安装时不会自动启动。</li>';
readme += '<li>哪吒面板是改造版,用户名和密码登录【面板配置】,不依赖github/gitee/gitlab。</li>';
readme += '<li>Agent需要先手动填写正确信息。</li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
}
}
+158
View File
@@ -0,0 +1,158 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=0.15.2
# bash install.sh install 0.15.2
# cd /www/server/mdserver-web/plugins/nezha && bash install.sh install 0.15.2
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/nezha && bash install.sh install 0.15.2
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
OSNAME_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
ARCH="amd64"
get_arch() {
TMP_ARCH=`arch`
if [ "$TMP_ARCH" == "x86_64" ];then
ARCH="amd64"
elif [ "$TMP_ARCH" == "aarch64" ];then
ARCH="arm64"
else
echo $ARCH
fi
}
load_vars() {
OS=$(uname | tr '[:upper:]' '[:lower:]')
TARGET_DIR="$serverPath/nezha/dashboard"
## China_IP
if [[ -z "${CN}" ]]; then
if [[ $(curl -m 10 -s https://ipapi.co/json | grep 'China') != "" ]]; then
CN=true
fi
fi
if [[ -z "${CN}" ]]; then
GITHUB_RAW_URL="raw.githubusercontent.com/midoks/nezha/main"
GITHUB_URL="github.com"
else
GITHUB_RAW_URL="cdn.jsdelivr.net/gh/midoks/nezha@main"
GITHUB_URL="dn-dao-github-mirror.daocloud.io"
fi
echo $GITHUB_RAW_URL
echo $GITHUB_URL
}
# download file
download_file() {
url="${1}"
destination="${2}"
printf "Fetching ${url} \n\n"
if test -x "$(command -v curl)"; then
code=$(curl --connect-timeout 15 -w '%{http_code}' -L "${url}" -o "${destination}")
elif test -x "$(command -v wget)"; then
code=$(wget -t2 -T15 -O "${destination}" --server-response "${url}" 2>&1 | awk '/^ HTTP/{print $2}' | tail -1)
else
printf "\e[1;31mNeither curl nor wget was available to perform http requests.\e[0m\n"
exit 1
fi
if [ "${code}" != 200 ]; then
printf "\e[1;31mRequest failed with code %s\e[0m\n" $code
exit 1
else
printf "\n\e[1;33mDownload succeeded\e[0m\n"
fi
}
Install_dashborad(){
echo '正在安装哪吒监控...' > $install_tmp
mkdir -p $serverPath/source
if [ ! -f $TARGET_DIR/nezha ];then
DOWNLOAD_URL="https://${GITHUB_URL}/midoks/nezha/releases/download/v${VERSION}/nezha-${OS}-${ARCH}.zip"
DOWNLOAD_FILE="$(mktemp).zip"
download_file $DOWNLOAD_URL $DOWNLOAD_FILE
if [ ! -d $TARGET_DIR ]; then
mkdir -p $TARGET_DIR
fi
unzip $DOWNLOAD_FILE -d $TARGET_DIR
rm -rf $DOWNLOAD_FILE
fi
}
Install_agent(){
echo -e "正在下载监控端" > $install_tmp
mkdir -p $serverPath/source
version=v0.15.1
AGENT_TARGET_DIR="$serverPath/nezha/agent"
DOWNLOAD_URL="https://${GITHUB_URL}/nezhahq/agent/releases/download/${version}/nezha-agent_${OS}_${ARCH}.zip"
DOWNLOAD_FILE="$(mktemp).zip"
if [ ! -f $AGENT_TARGET_DIR/nezha-agent ];then
download_file $DOWNLOAD_URL $DOWNLOAD_FILE
if [ ! -d $AGENT_TARGET_DIR ]; then
mkdir -p $AGENT_TARGET_DIR
fi
unzip $DOWNLOAD_FILE -d $AGENT_TARGET_DIR
rm -rf $DOWNLOAD_FILE
fi
}
Install_App()
{
load_vars
get_arch
Install_dashborad
Install_agent
if [ -d $serverPath/nezha ];then
echo "$VERSION" > $serverPath/nezha/version.pl
cd ${rootPath} && python3 ${rootPath}/plugins/nezha/index.py init_cfg
fi
echo 'install successful' > $install_tmp
}
Uninstall_App()
{
cd ${rootPath} && python3 ${rootPath}/plugins/nezha/index.py initd_uninstall
cd ${rootPath} && python3 ${rootPath}/plugins/nezha/index.py initd_uninstall_agent
cd ${rootPath} && python3 ${rootPath}/plugins/nezha/index.py stop
cd ${rootPath} && python3 ${rootPath}/plugins/nezha/index.py stop_agent
rm -rf $serverPath/nezha
echo "install fail" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
@@ -0,0 +1,2 @@
## 指定共享内存
lua_shared_dict healthcheck 10m;
@@ -0,0 +1,64 @@
location / {
proxy_pass http://{$UPSTREAM_NAME};
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $proxy_host;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
#location /upstream_status {
# allow 127.0.0.1;
# deny all;
# access_log off;
# default_type text/plain;
# content_by_lua_block {
# local hc = require "resty.upstream.healthcheck"
# ngx.say("OpenResty Worker PID: ", ngx.worker.pid())
# ngx.print(hc.status_page())
# }
#}
location /upstream_status_{$UPSTREAM_NAME} {
allow 127.0.0.1;
deny all;
access_log off;
default_type text/plain;
content_by_lua_block {
local json = require "cjson"
local ok, upstream = pcall(require, "ngx.upstream")
if not ok then
ngx.print("[]")
return
end
local get_primary_peers = upstream.get_primary_peers
local get_backup_peers = upstream.get_backup_peers
local upstream_name = "{$UPSTREAM_NAME}"
peers, err = get_primary_peers(upstream_name)
if not peers then
ngx.print("[]")
return
end
peers_backup, err = get_backup_peers(upstream_name)
if peers_backup then
for k, v in pairs(peers_backup) do
table.insert(peers,v)
end
end
ngx.print(json.encode(peers))
}
}
@@ -0,0 +1,5 @@
upstream {$UPSTREAM_NAME}
{
{$NODE_ALGO}
{$NODE_SERVER_LIST}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

+21
View File
@@ -0,0 +1,21 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('op_load_balance');">服务</p>
<p onclick="loadBalanceList();">负载均衡</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript" src="/plugins/file?name=op_load_balance&f=js/app.js"></script>
<script type="text/javascript">
resetPluginWinWidth(800);
resetPluginWinHeight(300);
$.getScript( "/plugins/file?name=op_load_balance&f=js/app.js", function(){
pluginService('op_load_balance');
});
</script>
+474
View File
@@ -0,0 +1,474 @@
# coding:utf-8
import sys
import io
import os
import time
import subprocess
import json
import re
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'op_load_balance'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
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(':')
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def 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 getConf():
path = getServerDir() + "/cfg.json"
if not os.path.exists(path):
mw.writeFile(path, '[]')
c = mw.readFile(path)
return json.loads(c)
def writeConf(data):
path = getServerDir() + "/cfg.json"
mw.writeFile(path, json.dumps(data))
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$APP_PATH}', app_path)
return content
def restartWeb():
mw.opWeb('stop')
mw.opWeb('start')
def loadBalanceConf():
path = mw.getServerDir() + '/web_conf/nginx/vhost/load_balance.conf'
return path
def initDreplace():
dst_conf_tpl = getPluginDir() + '/conf/load_balance.conf'
dst_conf = loadBalanceConf()
if not os.path.exists(dst_conf):
con = mw.readFile(dst_conf_tpl)
mw.writeFile(dst_conf, con)
def status():
if not mw.getWebStatus():
return 'stop'
dst_conf = loadBalanceConf()
if not os.path.exists(dst_conf):
return 'stop'
return 'start'
def start():
initDreplace()
restartWeb()
return 'ok'
def stop():
dst_conf = loadBalanceConf()
os.remove(dst_conf)
deleteLoadBalanceAllCfg()
restartWeb()
return 'ok'
def restart():
restartWeb()
return 'ok'
def reload():
restartWeb()
return 'ok'
def installPreInspection():
check_op = mw.getServerDir() + "/openresty"
if not os.path.exists(check_op):
return "请先安装OpenResty"
return 'ok'
def deleteLoadBalanceAllCfg():
cfg = getConf()
upstream_dir = mw.getServerDir() + '/web_conf/nginx/upstream'
lua_dir = mw.getServerDir() + '/web_conf/nginx/lua/init_worker_by_lua_file'
rewrite_dir = mw.getServerDir() + '/web_conf/nginx/rewrite'
vhost_dir = mw.getServerDir() + '/web_conf/nginx/vhost'
for conf in cfg:
upstream_file = upstream_dir + '/' + conf['upstream_name'] + '.conf'
if os.path.exists(upstream_file):
os.remove(upstream_file)
lua_file = lua_dir + '/' + conf['upstream_name'] + '.lua'
if os.path.exists(lua_file):
os.remove(lua_file)
rewrite_file = rewrite_dir + '/' + conf['domain'] + '.conf'
mw.writeFile(rewrite_file, '')
path = vhost_dir + '/' + conf['domain'] + '.conf'
content = mw.readFile(path)
content = re.sub('include ' + upstream_file + ';' + "\n", '', content)
mw.writeFile(path, content)
mw.opLuaInitWorkerFile()
def makeConfServerList(data):
slist = ''
for x in data:
slist += 'server '
slist += x['ip'] + ':' + x['port']
if x['state'] == '0':
slist += ' down;\n\t'
continue
if x['state'] == '2':
slist += ' backup;\n\t'
continue
slist += ' weight=' + x['weight']
slist += ' max_fails=' + x['max_fails']
slist += ' fail_timeout=' + x['fail_timeout'] + "s;\n\t"
return slist
def makeLoadBalanceAllCfg(row):
# 生成所有配置
cfg = getConf()
upstream_dir = mw.getServerDir() + '/web_conf/nginx/upstream'
rewrite_dir = mw.getServerDir() + '/web_conf/nginx/rewrite'
vhost_dir = mw.getServerDir() + '/web_conf/nginx/vhost'
upstream_tpl = getPluginDir() + '/conf/upstream.tpl.conf'
rewrite_tpl = getPluginDir() + '/conf/rewrite.tpl.conf'
if not os.path.exists(upstream_dir):
os.makedirs(upstream_dir)
conf = cfg[row]
# replace vhost start
vhost_file = vhost_dir + '/' + conf['domain'] + '.conf'
vcontent = mw.readFile(vhost_file)
vhost_find_str = 'upstream/' + conf['upstream_name'] + '.conf'
vhead = 'include ' + mw.getServerDir() + '/web_conf/nginx/' + \
vhost_find_str + ';'
vpos = vcontent.find(vhost_find_str)
if vpos < 0:
vcontent = vhead + "\n" + vcontent
mw.writeFile(vhost_file, vcontent)
# replace vhost end
# make upstream start
upstream_file = upstream_dir + '/' + conf['upstream_name'] + '.conf'
content = ''
if len(conf['node_list']) > 0:
content = mw.readFile(upstream_tpl)
slist = makeConfServerList(conf['node_list'])
content = content.replace('{$NODE_SERVER_LIST}', slist)
content = content.replace('{$UPSTREAM_NAME}', conf['upstream_name'])
if conf['node_algo'] != 'polling':
content = content.replace('{$NODE_ALGO}', conf['node_algo'] + ';')
else:
content = content.replace('{$NODE_ALGO}', '')
mw.writeFile(upstream_file, content)
# make upstream end
# make rewrite start
rewrite_file = rewrite_dir + '/' + conf['domain'] + '.conf'
rcontent = ''
if len(conf['node_list']) > 0:
rcontent = mw.readFile(rewrite_tpl)
rcontent = rcontent.replace('{$UPSTREAM_NAME}', conf['upstream_name'])
mw.writeFile(rewrite_file, rcontent)
# make rewrite end
# health check start
lua_dir = mw.getServerDir() + '/web_conf/nginx/lua/init_worker_by_lua_file'
lua_init_worker_file = lua_dir + '/' + conf['upstream_name'] + '.lua'
if conf['node_health_check'] == 'ok':
lua_dir_tpl = getPluginDir() + '/lua/health_check.lua.tpl'
content = mw.readFile(lua_dir_tpl)
content = content.replace('{$UPSTREAM_NAME}', conf['upstream_name'])
content = content.replace('{$DOMAIN}', conf['domain'])
mw.writeFile(lua_init_worker_file, content)
else:
if os.path.exists(lua_init_worker_file):
os.remove(lua_init_worker_file)
mw.opLuaInitWorkerFile()
# health check end
return True
def add_load_balance(args):
data = checkArgs(
args, ['domain', 'upstream_name', 'node_algo', 'node_list', 'node_health_check'])
if not data[0]:
return data[1]
domain_json = args['domain']
tmp = json.loads(domain_json)
domain = tmp['domain']
cfg = getConf()
cfg_len = len(cfg)
tmp = {}
tmp['domain'] = domain
tmp['data'] = args['domain']
tmp['upstream_name'] = args['upstream_name']
tmp['node_algo'] = args['node_algo']
tmp['node_list'] = args['node_list']
tmp['node_health_check'] = args['node_health_check']
cfg.append(tmp)
writeConf(cfg)
import site_api
sobj = site_api.site_api()
domain_path = mw.getWwwDir() + '/' + domain
ps = '负载均衡[' + domain + ']'
data = sobj.add(domain_json, '80', ps, domain_path, '00')
makeLoadBalanceAllCfg(cfg_len)
mw.restartWeb()
return mw.returnJson(True, '添加成功', data)
def edit_load_balance(args):
data = checkArgs(
args, ['row', 'node_algo', 'node_list', 'node_health_check'])
if not data[0]:
return data[1]
row = int(args['row'])
cfg = getConf()
tmp = cfg[row]
tmp['node_algo'] = args['node_algo']
tmp['node_list'] = args['node_list']
tmp['node_health_check'] = args['node_health_check']
cfg[row] = tmp
writeConf(cfg)
makeLoadBalanceAllCfg(row)
mw.restartWeb()
return mw.returnJson(True, '修改成功', data)
def loadBalanceList():
cfg = getConf()
return mw.returnJson(True, 'ok', cfg)
def loadBalanceDelete():
args = getArgs()
data = checkArgs(args, ['row'])
if not data[0]:
return data[1]
row = int(args['row'])
cfg = getConf()
data = cfg[row]
import site_api
sobj = site_api.site_api()
sid = mw.M('sites').where('name=?', (data['domain'],)).getField('id')
if type(sid) == list:
del(cfg[row])
writeConf(cfg)
return mw.returnJson(False, '已经删除了!')
status = sobj.delete(sid, data['domain'], 1)
status_data = json.loads(status)
if status_data['status']:
del(cfg[row])
writeConf(cfg)
upstream_dir = mw.getServerDir() + '/web_conf/nginx/upstream'
rewrite_dir = mw.getServerDir() + '/web_conf/nginx/rewrite'
upstream_file = upstream_dir + '/' + data['upstream_name'] + '.conf'
if os.path.exists(upstream_file):
os.remove(upstream_file)
rewrite_file = rewrite_dir + '/' + data['domain'] + '.conf'
if os.path.exists(rewrite_file):
mw.writeFile(rewrite_file, '')
return mw.returnJson(status_data['status'], status_data['msg'])
def http_get(url):
ret = re.search(r'https://', url)
if ret:
try:
from gevent import monkey
monkey.patch_ssl()
import requests
ret = requests.get(url=str(url), verify=False, timeout=10)
status = [200, 301, 302, 404, 403]
if ret.status_code in status:
return True
else:
return False
except:
return False
else:
try:
if sys.version_info[0] == 2:
import urllib2
rec = urllib2.urlopen(url, timeout=3)
else:
import urllib.request
rec = urllib.request.urlopen(url, timeout=3)
status = [200, 301, 302, 404, 403]
if rec.getcode() in status:
return True
return False
except:
return False
def checkUrl():
args = getArgs()
data = checkArgs(args, ['ip', 'port', 'path'])
if not data[0]:
return data[1]
ip = args['ip']
port = args['port']
path = args['path']
if port == '443':
url = 'https://' + str(ip) + ':' + str(port) + str(path.strip())
else:
url = 'http://' + str(ip) + ':' + str(port) + str(path.strip())
ret = http_get(url)
if not ret:
return mw.returnJson(False, '访问节点[%s]失败' % url)
return mw.returnJson(True, '访问节点[%s]成功' % url)
def getHealthStatus():
args = getArgs()
data = checkArgs(args, ['row'])
if not data[0]:
return data[1]
row = int(args['row'])
cfg = getConf()
data = cfg[row]
url = 'http://' + data['domain'] + \
'/upstream_status_' + data['upstream_name']
url_data = mw.httpGet(url)
return mw.returnJson(True, 'ok', json.loads(url_data))
def getLogs():
args = getArgs()
data = checkArgs(args, ['domain'])
if not data[0]:
return data[1]
domain = args['domain']
logs = mw.getLogsDir() + '/' + domain + '.log'
return logs
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'install_pre_inspection':
print(installPreInspection())
elif func == 'add_load_balance':
print(addLoadBalance())
elif func == 'load_balance_list':
print(loadBalanceList())
elif func == 'load_balance_delete':
print(loadBalanceDelete())
elif func == 'check_url':
print(checkUrl())
elif func == 'get_logs':
print(getLogs())
elif func == 'get_health_status':
print(getHealthStatus())
else:
print('error')
+16
View File
@@ -0,0 +1,16 @@
{
"title":"OP负载均衡",
"tip":"soft",
"name":"op_load_balance",
"type":"其他插件",
"install_pre_inspection":true,
"ps":"基于OpenResty的负载均衡",
"shell":"install.sh",
"checks":"server/op_load_balance",
"path":"server/op_load_balance",
"author":"midoks",
"home":"https://github.com/midoks",
"date":"2023-02-02",
"pid": "1",
"versions": ["1.0"]
}
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
version=$2
sys_os=`uname`
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
if [ "$sys_os" == "Darwin" ];then
BAK='_bak'
else
BAK=''
fi
Install_App(){
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/op_load_balance
echo "${version}" > $serverPath/op_load_balance/version.pl
cd ${rootPath} && python3 ${rootPath}/plugins/op_load_balance/index.py start
echo 'install ok' > $install_tmp
}
Uninstall_App(){
cd ${rootPath} && python3 ${rootPath}/plugins/op_load_balance/index.py stop
rm -rf $serverPath/op_load_balance
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+606
View File
@@ -0,0 +1,606 @@
function ooPost(method,args,callback){
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 });
$.post('/plugins/run', {name:'op_load_balance', 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 ooAsyncPost(method,args){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
return syncPost('/plugins/run', {name:'op_load_balance', func:method, args:_args});
}
function ooPostCallbak(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'op_load_balance';
req_data['func'] = method;
args['version'] = '1.0';
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 addNode(){
layer.open({
type: 1,
area: ['450px','580px'],
title: '添加节点',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:['提交','关闭'],
content: "<form class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>IP地址</span>\
<div class='info-r'>\
<input name='ip' class='bt-input-text mr5' placeholder='负载名称,可以是英文字母和下划线,不能使用中文' type='text' style='width:250px' value='127.0.0.1'>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>端口</span>\
<div class='info-r'>\
<input name='port' class='bt-input-text mr5' type='text' style='width:250px' value='80'>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>验证文件路径</span>\
<div class='info-r'>\
<input name='path' class='bt-input-text mr5' type='text' style='width:250px' value='/'>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>节点状态</span>\
<div class='info-r'>\
<select name='state'>\
<option value='1'>参与者</option>\
<option value='2'>备份</option>\
<option value='0'>停用</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>权重</span>\
<div class='info-r'>\
<input name='weight' class='bt-input-text mr5' type='text' style='width:250px' value='1'>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>阈值</span>\
<div class='info-r'>\
<input name='max_fails' class='bt-input-text mr5' type='text' style='width:250px' value='2'>次\
</div>\
</div>\
<div class='line'>\
<span class='tname'>恢复时间</span>\
<div class='info-r'>\
<input name='fail_timeout' class='bt-input-text mr5' type='text' style='width:250px' value='10'>秒\
</div>\
</div>\
<ul style='margin-left:10px' class='help-info-text c7'>\
<li>备份状态: 指当其它节点都无法使用时才会使用此节点</li>\
<li>参与状态: 正常参与负载均衡,请至少添加1个普通节点</li>\
<li>验证文件路径: 用于检查文件路径地址是否可用</li>\
<li>IP地址: 仅支持IP地址,否则无法正常参与负载均衡</li>\
<li>阈值: 在恢复时间的时间段内,如果OpenResty与节点通信尝试失败的次数达到此值,OpenResty就认为服务器不可用</li>\
</ul>\
</form>",
success:function(){
},
yes:function(index) {
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var path = $('input[name="path"]').val();
var state = $('select[name="state"]').val();
var weight = $('input[name="weight"]').val();
var max_fails = $('input[name="max_fails"]').val();
var fail_timeout = $('input[name="fail_timeout"]').val();
ooPost('check_url', {ip:ip,port:port,path:path},function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg, function(){
if (rdata.status){
layer.close(index);
$('#nodecon .nulltr').hide();
var tbody = '<tr>';
tbody +='<td>'+ip+'</td>';
tbody +='<td>'+port+'</td>';
tbody +='<td>'+path+'</td>';
tbody +="<td><select name='state'>";
var state_option_list = {
'1':'参与者',
'2':'备份',
'0':'停用',
}
for (i in state_option_list) {
if (i == state){
tbody +="<option value='"+i+"' selected>"+state_option_list[i]+"</option>";
} else{
tbody +="<option value='"+i+"'>"+state_option_list[i]+"</option>";
}
}
tbody +="</select></td>";
tbody +='<td><input type="number" name="weight" value="'+weight+'" style="width:50px"></td>';
tbody +='<td><input type="number" name="max_fails" value="'+max_fails+'" style="width:50px"></td>';
tbody +='<td><input type="number" name="fail_timeout" value="'+fail_timeout+'" style="width:50px"></td>';
tbody +='<td class="text-right" width="50"><a class="btlink minus delete">删除</a></td>';
tbody += '</tr>';
$('#nodecon').append(tbody);
$('#nodecon .delete').click(function(){
$(this).parent().parent().remove();
if ($('#nodecon tr').length == 1 ){
$('#nodecon .nulltr').show();
}
});
}
},{ icon: rdata.status ? 1 : 2 }, 2000);
});
}
});
}
function addBalance(){
layer.open({
type: 1,
area: ['750px','460px'],
title: '创建负载',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:['提交','关闭'],
content: "<form class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>域名</span>\
<div class='info-r'><textarea name='load_domain' class='bt-input-text mr5' placeholder='' style='width:95%;resize: none;height:90px;line-height:20px;'></textarea></div>\
</div>\
<div class='line'>\
<span class='tname'>负载名称</span>\
<div class='info-r'>\
<input name='upstream_name' class='bt-input-text mr5' placeholder='负载名称,可以是英文字母和下划线,不能使用中文' type='text' style='width:95%' value=''>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>节点调度</span>\
<div class='info-r'>\
<select name='node_algo'>\
<option value='polling'>轮询[默认]</option>\
<option value='ip_hash'>ip_hash</option>\
<option value='fair'>fair</option>\
<option value='url_hash'>url_hash</option>\
<option value='least_conn'>least_conn</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>节点健康检查</span>\
<div class='info-r'>\
<input type='checkbox' name='node_health_check' checked>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>节点</span>\
<div class='info-r'>\
<div class='table-con divtable' style='max-height:120px;overflow:auto; margin-bottom:8px;width:95%'>\
<table class='table table-hover' id='fixTable3'>\
<thead>\
<tr>\
<th width='120'>IP地址</th>\
<th width='60'>端口</th>\
<th width='120'>验证路径</th>\
<th width='60'>状态</th>\
<th width='60'>权重</th>\
<th width='60'>阀值</th>\
<th width='120'>恢复时间</th>\
<th width='80' class='text-right'>操作</th>\
</tr>\
</thead>\
<tbody id='nodecon'>\
<tr class='nulltr'>\
<td colspan='8' align='center'>当前节点为空,请至少添加一个普通节点</td>\
</tr>\
</tbody>\
</table>\
</div>\
<span class='btn btn-success btn-sm add_node' style='vertical-align:0'>添加节点</span>\
</div>\
</div>\
</form>",
success:function(){
$('textarea[name="load_domain"]').attr('placeholder','每行填写一个域名,默认为80端口。\n泛解析添加方法 *.domain.com\n如另加端口格式为 www.domain.com:88');
var rval = getRandomString(6);
$('input[name="upstream_name"]').val('load_balance_'+rval);
$('.add_node').click(function(){
addNode();
});
},
yes:function(index) {
var data = {};
var upstream_name = $('input[name="upstream_name"]').val();
if (upstream_name == ''){
layer.msg('负载名称不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var domain = $('textarea[name="load_domain"]').val().replace('http://','').replace('https://','').split("\n");
if (domain[0] == ''){
layer.msg('域名不能为空!',{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var domainlist = '';
for(var i=1; i<domain.length; i++){
domainlist += '"'+domain[i]+'",';
}
domain ='{"domain":"'+domain[0]+'","domainlist":['+domainlist+'],"count":'+domain.length+'}';//拼接json
data['domain'] = domain;
data['upstream_name'] = upstream_name;
data['node_algo'] = $('select[name="node_algo"]').val();
data['node_health_check'] = 'fail';
if ($('input[name="node_health_check"]').prop('checked')){
data['node_health_check'] = 'ok';
}
var node_list = [];
$('#nodecon tr').each(function(){
var ip = $(this).find('td').eq(0).text();
var port = $(this).find('td').eq(1).text();
if (port == ''){return;}
var path = $(this).find('td').eq(2).text();
var state = $(this).find('select[name="state"]').val();
var weight = $(this).find('input[name="weight"]').val();
var max_fails = $(this).find('input[name="max_fails"]').val();
var fail_timeout = $(this).find('input[name="fail_timeout"]').val();
var tmp = {
ip:ip,
port:port,
path:path,
state:state,
weight:weight,
max_fails:max_fails,
fail_timeout:fail_timeout,
}
node_list.push(tmp);
});
data['node_list'] = node_list;
ooPostCallbak('add_load_balance', data, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg, function(){
layer.close(index);
loadBalanceListRender();
},{ icon: rdata.status ? 1 : 2 }, 2000);
});
}
});
}
function editBalance(data, row){
layer.open({
type: 1,
area: ['750px','400px'],
title: '编辑负载',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:['提交','关闭'],
content: "<form class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>负载名称</span>\
<div class='info-r'><input name='upstream_name' class='bt-input-text mr5' type='text' style='width:95%;background: rgb(238, 238, 238);' value='' readonly></div>\
</div>\
<div class='line'>\
<span class='tname'>节点调度</span>\
<div class='info-r'>\
<select name='node_algo'>\
<option value='polling'>轮询[默认]</option>\
<option value='ip_hash'>ip_hash</option>\
<option value='fair'>fair</option>\
<option value='url_hash'>url_hash</option>\
<option value='least_conn'>least_conn</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>节点健康检查</span>\
<div class='info-r'>\
<input type='checkbox' name='node_health_check'>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>节点</span>\
<div class='info-r'>\
<div class='table-con divtable' style='max-height:120px;overflow:auto; margin-bottom:8px;width:95%'>\
<table class='table table-hover' id='fixTable3'>\
<thead>\
<tr>\
<th width='120'>IP地址</th>\
<th width='60'>端口</th>\
<th width='120'>验证路径</th>\
<th width='60'>状态</th>\
<th width='60'>权重</th>\
<th width='60'>阀值</th>\
<th width='120'>恢复时间</th>\
<th width='80' class='text-right'>操作</th>\
</tr>\
</thead>\
<tbody id='nodecon'>\
<tr class='nulltr'>\
<td colspan='8' align='center'>当前节点为空,请至少添加一个普通节点</td>\
</tr>\
</tbody>\
</table>\
</div>\
<span class='btn btn-success btn-sm add_node' style='vertical-align:0'>添加节点</span>\
</div>\
</div>\
</form>",
success:function(){
$('input[name="upstream_name"]').val(data['upstream_name']);
$('select[name="node_algo"]').val(data['node_algo']);
$('input[name="node_health_check"]').prop('checked',false);
if (data['node_health_check'] == 'ok'){
$('input[name="node_health_check"]').prop('checked',true);
}
var node_list = data['node_list'];
if (node_list.length>0){
$('#nodecon .nulltr').hide();
}
var state_option_list = {
'1':'参与者',
'2':'备份',
'0':'停用',
}
for (var n in node_list) {
var tbody = '<tr>';
tbody +='<td>'+node_list[n]['ip']+'</td>';
tbody +='<td>'+node_list[n]['port']+'</td>';
tbody +='<td>'+node_list[n]['path']+'</td>';
tbody +="<td><select name='state'>";
for (i in state_option_list) {
if (i == node_list[n]['state']){
tbody +="<option value='"+i+"' selected>"+state_option_list[i]+"</option>";
} else{
tbody +="<option value='"+i+"'>"+state_option_list[i]+"</option>";
}
}
tbody +="</select></td>";
tbody +='<td><input type="number" name="weight" value="'+node_list[n]['weight']+'" style="width:50px"></td>';
tbody +='<td><input type="number" name="max_fails" value="'+node_list[n]['max_fails']+'" style="width:50px"></td>';
tbody +='<td><input type="number" name="fail_timeout" value="'+node_list[n]['fail_timeout']+'" style="width:50px"></td>';
tbody +='<td class="text-right" width="50"><a class="btlink minus delete">删除</a></td>';
tbody += '</tr>';
$('#nodecon').append(tbody);
}
$('#nodecon .delete').click(function(){
$(this).parent().parent().remove();
if ($('#nodecon tr').length == 1 ){
$('#nodecon .nulltr').show();
}
});
$('.add_node').click(function(){
addNode();
});
},
yes:function(index) {
var data = {};
data['node_algo'] = $('select[name="node_algo"]').val();
data['node_health_check'] = 'fail';
if ($('input[name="node_health_check"]').prop('checked')){
data['node_health_check'] = 'ok';
}
var node_list = [];
$('#nodecon tr').each(function(){
var ip = $(this).find('td').eq(0).text();
var port = $(this).find('td').eq(1).text();
if (port == ''){return;}
var path = $(this).find('td').eq(2).text();
var state = $(this).find('select[name="state"]').val();
var weight = $(this).find('input[name="weight"]').val();
var max_fails = $(this).find('input[name="max_fails"]').val();
var fail_timeout = $(this).find('input[name="fail_timeout"]').val();
var tmp = {
ip:ip,
port:port,
path:path,
state:state,
weight:weight,
max_fails:max_fails,
fail_timeout:fail_timeout,
}
node_list.push(tmp);
});
data['node_list'] = node_list;
data['row'] = row;
ooPostCallbak('edit_load_balance', data, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg, function(){
layer.close(index);
loadBalanceListRender();
},{ icon: rdata.status ? 1 : 2 }, 2000);
});
}
});
}
function loadBalanceListRender(){
ooPost('load_balance_list', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var alist = rdata.data;
var tbody = '';
for (var i = 0; i < alist.length; i++) {
tbody += '<tr>';
tbody += '<td>'+alist[i]['domain']+'</td>';
tbody += '<td>'+alist[i]['upstream_name']+'</td>';
tbody += '<td>'+alist[i]['node_list'].length+'</td>';
tbody += '<td><a class="btlink log_look" data-row="'+i+'">查看</a></td>';
tbody += '<td><a class="btlink health_status" data-row="'+i+'">查看</a></td>';
tbody += '<td style="text-align: right;"><a class="btlink edit" data-row="'+i+'">修改</a> | <a class="btlink delete" data-row="'+i+'">删除</a></td>';
tbody += '</tr>';
}
$('#nodeTable').html(tbody);
$('.nodeTablePage .Pcount').text('共'+alist.length+'条');
$('#nodeTable .edit').click(function(){
var row = $(this).data('row');
editBalance(alist[row],row);
});
$('#nodeTable .log_look').click(function(){
var row = $(this).data('row');
var args = {'domain':alist[row]['domain']};
pluginRollingLogs('op_load_balance','','get_logs',JSON.stringify(args),20);
});
$('#nodeTable .health_status').click(function(){
var row = $(this).data('row');
ooPost('get_health_status', {row:row}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var tval = '';
for (var i = 0; i < rdata.data.length; i++) {
tval += '<tr>';
tval += '<td>'+rdata.data[i]['name']+'</td>';
if (typeof(rdata.data[i]['down']) != 'undefined' && rdata.data[i]['down']){
tval += '<td><span style="color:red;">不正常</span></td>';
} else{
tval += '<td><span class="btlink">正常</span></td>';
}
tval += '</tr>';
}
var tbody = "<div class='bt-form pd20'>\
<div>\
<div id='gitea_table' class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead>\
<tr>\
<th width='120'>地址</th>\
<th width='60'>状态</th>\
</tr>\
</thead>\
<tbody>"+tval+"</tbody>\
</table>\
</div>\
</div>\
</div>";
layer.open({
type: 1,
area: ['500px','300px'],
title: '节点状态',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:['提交','关闭'],
content:tbody,
});
});
});
$('#nodeTable .delete').click(function(){
var row = $(this).data('row');
ooPost('load_balance_delete', {row:row}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg, function(){
loadBalanceListRender();
},{ icon: rdata.status ? 1 : 2 }, 2000);
});
});
});
}
function loadBalanceList() {
var body = '<div class="bt-box active" style="display: block;">\
<div class="mb10">\
<button class="btn btn-success btn-sm" data-index="0" onclick="addBalance()">添加负载</button>\
<div class="divtable mt10">\
<table class="table table-hover">\
<thead>\
<tr>\
<th>网站</th>\
<th>负载名称</th>\
<th>节点</th>\
<th>日志</th>\
<th>状态</th>\
<th width="100" style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody id="nodeTable"></tbody>\
</table>\
<div class="nodeTablePage page" data-type="nodePage">\
<div><span class="Pcount">共0条</span></div>\
</div>\
</div>\
</div>\
</div>\
</div>';
$(".soft-man-con").html(body);
loadBalanceListRender();
}
@@ -0,0 +1,18 @@
local hc = require "resty.upstream.healthcheck"
local ok, err = hc.spawn_checker {
shm = "healthcheck",
type = "http",
upstream = "{$UPSTREAM_NAME}",
http_req = "GET / HTTP/1.0\r\nHost: {$UPSTREAM_NAME}\r\n\r\n",
interval = 2000,
timeout = 6000,
fall = 3,
rise = 2,
valid_statuses = {200, 302},
concurrency = 20,
}
if not ok then
ngx.log(ngx.ERR, "=======> load balance health checker error: ", err)
return
end
+13 -1
View File
@@ -1,4 +1,16 @@
{ {
"hook":[
{
"tag":"site_cb",
"site_cb": {
"title":"网站统计",
"name":"op_waf",
"add":{"func":"reload"},
"update":{"func":"reload"},
"delete":{"func":"reload"}
}
}
],
"title":"OP防火墙", "title":"OP防火墙",
"tip":"soft", "tip":"soft",
"name":"op_waf", "name":"op_waf",
@@ -12,5 +24,5 @@
"home":"https://github.com/loveshell/ngx_lua_waf", "home":"https://github.com/loveshell/ngx_lua_waf",
"date":"2019-04-21", "date":"2019-04-21",
"pid": "1", "pid": "1",
"versions": ["0.2.5"] "versions": ["0.2.6"]
} }
+53 -42
View File
@@ -344,13 +344,22 @@ local function waf_cc_increase()
local make_uri = "/"..make_uri_str local make_uri = "/"..make_uri_str
if params['uri_request_args']['token'] then if params['uri_request_args']['token'] then
ngx.header.content_type = "application/json"
local args_token = params['uri_request_args']['token'] local args_token = params['uri_request_args']['token']
if args_token == make_token then if args_token == make_token then
ngx.shared.waf_limit:set(cache_token, 1, config['safe_verify']['time']) ngx.shared.waf_limit:set(cache_token, 1, tonumber(config['safe_verify']['time']))
local data = get_return_state(0, "ok") local data = get_return_state(0, "ok")
ngx.say(json.encode(data)) ngx.say(json.encode(data))
ngx.exit(200) ngx.exit(200)
end end
-- C:D("debug[args]:"..tostring(params['uri_request_args']['debug']))
-- if params['uri_request_args']['debug'] == 'ok' then
-- ngx.header.content_type = "application/json"
-- local data = get_return_state(0, "ok")
-- ngx.say(json.encode(data))
-- ngx.exit(200)
-- end
end end
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str) local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
@@ -524,49 +533,51 @@ end
function waf() function waf()
min_route() min_route()
-- C:D("min_route") -- C:D("min_route")
-- white ip
if waf_ip_white() then return true end
-- C:D("waf_ip_white")
-- url white
if waf_url_white() then return true end
-- C:D("waf_url_white")
-- black ip
if waf_ip_black() then return true end
-- C:D("waf_ip_black")
-- 封禁ip返回
if waf_drop_ip() then return true end
-- C:D("waf_drop_ip")
-- ua check
if waf_user_agent() then return true end
-- C:D("waf_user_agent")
if waf_url() then return true end
-- C:D("waf_url")
-- cc setting
if waf_cc_increase() then return true end
-- C:D("waf_cc_increase")
if waf_cc() then return true end
-- C:D("waf_cc")
-- cookie检查
if waf_cookie() then return true end
-- C:D("waf_cookie")
-- args参数拦截
if waf_get_args() then return true end
-- C:D("waf_get_args")
-- 扫描软件禁止
if waf_scan_black() then return true end
-- C:D("waf_scan_black")
if waf_post() then return true end
-- C:D("waf_post")
if site_config[server_name] and site_config[server_name]['open'] then if site_config[server_name] and site_config[server_name]['open'] then
-- white ip
if waf_ip_white() then return true end
-- C:D("waf_ip_white")
-- url white
if waf_url_white() then return true end
-- C:D("waf_url_white")
-- black ip
if waf_ip_black() then return true end
-- C:D("waf_ip_black")
-- 封禁ip返回
if waf_drop_ip() then return true end
-- C:D("waf_drop_ip")
-- ua check
if waf_user_agent() then return true end
-- C:D("waf_user_agent")
if waf_url() then return true end
-- C:D("waf_url")
-- cc setting
if waf_cc_increase() then return true end
-- C:D("waf_cc_increase")
if waf_cc() then return true end
-- C:D("waf_cc")
-- cookie检查
if waf_cookie() then return true end
-- C:D("waf_cookie")
-- args参数拦截
if waf_get_args() then return true end
-- C:D("waf_get_args")
-- 扫描软件禁止
if waf_scan_black() then return true end
-- C:D("waf_scan_black")
if waf_post() then return true end
-- C:D("waf_post")
--------------------------------------------------------
--------------------------------------------------------
if X_Forwarded() then return true end if X_Forwarded() then return true end
-- C:D("X_Forwarded") -- C:D("X_Forwarded")
if post_X_Forwarded() then return true end if post_X_Forwarded() then return true end
+19 -12
View File
@@ -60,19 +60,26 @@ http
limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m; limit_conn_zone $server_name zone=perserver:10m;
server_tokens off; # CACEH_BEGIN
access_log off; proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_cache_path {$SERVER_PATH}/openresty/nginx/proxy_cache_temp levels=1:2 keys_zone=mw_cache:512m inactive=5m max_size=2g use_temp_path=off;
#proxy timeout
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
server { fastcgi_cache_key "$scheme$request_method$host$request_uri";
listen 80; fastcgi_cache_path {$SERVER_PATH}/openresty/nginx/fastcgi_cache_temp levels=1:2 keys_zone=mw_cache_fcgi:100m inactive=60m max_size=5g;
listen [::]:80; fastcgi_cache_use_stale error timeout invalid_header http_500;
server_name 127.0.0.1; fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
allow 127.0.0.1; # CACEH_END
location /nginx_status {
stub_status on; server_tokens off;
access_log off; access_log /dev/null;
}
}
include {$SERVER_PATH}/web_conf/nginx/vhost/*.conf; include {$SERVER_PATH}/web_conf/nginx/vhost/*.conf;
} }
@@ -0,0 +1,10 @@
server {
listen 80;
listen [::]:80;
server_name 127.0.0.1;
allow 127.0.0.1;
location /nginx_status {
stub_status on;
access_log off;
}
}
@@ -0,0 +1,4 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
+12
View File
@@ -180,6 +180,17 @@ def confReplace():
cmd_s = 'chmod u+s ' + ng_exe_bin cmd_s = 'chmod u+s ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_s)) os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_s))
# vhost
vhost_dir = mw.getServerDir() + '/web_conf/nginx/vhost'
vhost_tpl_dir = getPluginDir() + '/conf/vhost'
# print(vhost_dir, vhost_tpl_dir)
vhost_list = ['0.websocket.conf', '0.nginx_status.conf']
for f in vhost_list:
a_conf = vhost_dir + '/' + f
a_conf_tpl = vhost_tpl_dir + '/' + f
if not os.path.exists(a_conf):
mw.writeFile(a_conf, mw.readFile(a_conf_tpl))
def initDreplace(): def initDreplace():
@@ -290,6 +301,7 @@ def restart():
def reload(): def reload():
confReplace()
return restyOp('reload') return restyOp('reload')
+2 -2
View File
@@ -12,6 +12,6 @@
"home":"http://openresty.org", "home":"http://openresty.org",
"date":"2017-11-24", "date":"2017-11-24",
"pid": "1", "pid": "1",
"versions": ["1.17.8.2","1.19.3.1","1.21.4.1"], "versions": ["1.17.8.2","1.19.3.1","1.21.4.2"],
"updates": ["1.17.8.2","1.19.3.1","1.21.4.1"] "updates": ["1.17.8.2","1.19.3.1","1.21.4.2"]
} }
+12 -1
View File
@@ -59,10 +59,21 @@ Install_openresty()
mkdir -p ${openrestyDir} mkdir -p ${openrestyDir}
echo '正在安装脚本文件...' > $install_tmp echo '正在安装脚本文件...' > $install_tmp
# wget -O openresty-1.21.4.1.tar.gz https://openresty.org/download/openresty-1.21.4.1.tar.gz
if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then
wget -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://openresty.org/download/openresty-${VERSION}.tar.gz wget --no-check-certificate -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://openresty.org/download/openresty-${VERSION}.tar.gz -T 3
fi fi
DOWNLOAD_SIZE=`wc -c ${openrestyDir}/openresty-${VERSION}.tar.gz | awk '{print $1}'`
if [ "$DOWNLOAD_SIZE" == "0" ];then
echo 'download failed, download again'
rm -rf ${openrestyDir}/openresty-${VERSION}.tar.gz
fi
# Last Download Method
if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then
wget --no-check-certificate -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://dl.midoks.me/soft/openresty/openresty-${VERSION}.tar.gz -T 3
fi
cd ${openrestyDir} && tar -zxvf openresty-${VERSION}.tar.gz cd ${openrestyDir} && tar -zxvf openresty-${VERSION}.tar.gz
+1 -1
View File
@@ -658,7 +658,7 @@ function phpLibConfig(version){
//安装扩展 //安装扩展
function installPHPLib(version, name, title, pathinfo) { function installPHPLib(version, name, title, pathinfo) {
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() { layer.confirm('您真的要卸载{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
name = name.toLowerCase(); name = name.toLowerCase();
var data = "name=" + name + "&version=" + version + "&type=1"; var data = "name=" + name + "&version=" + version + "&type=1";
+1 -1
View File
@@ -672,7 +672,7 @@ function installPHPLib(version, name, title, pathinfo) {
//卸载扩展 //卸载扩展
function uninstallPHPLib(version, name, title, pathinfo) { function uninstallPHPLib(version, name, title, pathinfo) {
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() { layer.confirm('您真的要卸载{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
name = name.toLowerCase(); name = name.toLowerCase();
var data = 'name=' + name + '&version=' + version; var data = 'name=' + name + '&version=' + version;
phpPost('uninstall_lib', version, data, function(data){ phpPost('uninstall_lib', version, data, function(data){
+2 -2
View File
@@ -12,9 +12,9 @@ version=$1
action=$2 action=$2
if [ -f /lib/systemd/system/php${version}-php-fpm.service ];then if [ -f /lib/systemd/system/php${version}-php-fpm.service ];then
systemctl ${action} php${version} systemctl ${action} php${version}-php-fpm
elif [[ -f /usr/lib/systemd/system/php${version}-php-fpm.service ]]; then elif [[ -f /usr/lib/systemd/system/php${version}-php-fpm.service ]]; then
systemctl ${action} php${version} systemctl ${action} php${version}-php-fpm
else else
$serverPath/php/init.d/php${version} ${action} $serverPath/php/init.d/php${version} ${action}
fi fi
+1
View File
@@ -7,6 +7,7 @@ Description=The PHP {$VERSION} FastCGI Process Manager
After=network.target After=network.target
[Service] [Service]
Environment="LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/www/server/lib/icu/lib"
PIDFile={$SERVER_PATH}/php/{$VERSION}/var/run/php-fpm.pid PIDFile={$SERVER_PATH}/php/{$VERSION}/var/run/php-fpm.pid
ExecStart={$SERVER_PATH}/php/{$VERSION}/sbin/php-fpm --nodaemonize --fpm-config {$SERVER_PATH}/php/{$VERSION}/etc/php-fpm.conf ExecStart={$SERVER_PATH}/php/{$VERSION}/sbin/php-fpm --nodaemonize --fpm-config {$SERVER_PATH}/php/{$VERSION}/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID ExecReload=/bin/kill -USR2 $MAINPID
+2 -1
View File
@@ -49,6 +49,7 @@ fi
cd ${curPath} && sh -x $curPath/versions/$2/install.sh $1 cd ${curPath} && sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then
#初始化 #初始化
@@ -59,6 +60,7 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then
echo "install PHP${type} extend start" echo "install PHP${type} extend start"
# cd /www/server/mdserver-web/plugins/php/versions/common && bash iconv.sh install 53 # cd /www/server/mdserver-web/plugins/php/versions/common && bash iconv.sh install 53
# cd /www/server/mdserver-web/plugins/php/versions/common && bash intl.sh install 73
# cd /www/server/mdserver-web/plugins/php/versions/common && bash gd.sh install 56 # cd /www/server/mdserver-web/plugins/php/versions/common && bash gd.sh install 56
# cd /www/server/mdserver-web/plugins/php/versions/common && bash openssl.sh install 56 # cd /www/server/mdserver-web/plugins/php/versions/common && bash openssl.sh install 56
# cd /www/server/mdserver-web/plugins/php/versions/common && bash sodium.sh install 81 # cd /www/server/mdserver-web/plugins/php/versions/common && bash sodium.sh install 81
@@ -72,7 +74,6 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then
cd ${rootPath}/plugins/php/versions/common && bash gettext.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash gettext.sh install ${type}
cd ${rootPath}/plugins/php/versions/common && bash redis.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash redis.sh install ${type}
cd ${rootPath}/plugins/php/versions/common && bash memcached.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash memcached.sh install ${type}
cd ${rootPath}/plugins/php/versions/common && bash zlib.sh install ${type}
if [ "${type}" -gt "72" ];then if [ "${type}" -gt "72" ];then
cd ${rootPath}/plugins/php/versions/common && bash zip.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash zip.sh install ${type}
+1 -1
View File
@@ -665,7 +665,7 @@ function installPHPLib(version, name, title, pathinfo) {
//卸载扩展 //卸载扩展
function uninstallPHPLib(version, name, title, pathinfo) { function uninstallPHPLib(version, name, title, pathinfo) {
layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() { layer.confirm('您真的要卸载{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
name = name.toLowerCase(); name = name.toLowerCase();
var data = 'name=' + name + '&version=' + version; var data = 'name=' + name + '&version=' + version;
phpPost('uninstall_lib', version, data, function(data){ phpPost('uninstall_lib', version, data, function(data){
+14 -5
View File
@@ -15,11 +15,20 @@ SOURCE_ROOT=$rootPath/source/lib
if [ ! -d ${SERVER_ROOT}/freetype ];then if [ ! -d ${SERVER_ROOT}/freetype ];then
cd $SOURCE_ROOT cd $SOURCE_ROOT
wget -O freetype-2.12.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.gz -T 5
tar zxvf freetype-2.12.1.tar.gz if [ ! -f $SOURCE_ROOT/freetype-2.12.1.tar.gz ];then
cd freetype-2.12.1 wget -O freetype-2.12.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.gz -T 5
fi
if [ ! -d $SOURCE_ROOT/freetype-2.12.1 ];then
tar zxvf freetype-2.12.1.tar.gz
cd freetype-2.12.1
else
cd freetype-2.12.1
fi
./configure --prefix=${SERVER_ROOT}/freetype && make && make install ./configure --prefix=${SERVER_ROOT}/freetype && make && make install
cd $SOURCE_ROOT cd $SOURCE_ROOT && rm -rf freetype-2.12.1
#rm -rf freetype-2.12.1.tar.gz #rm -rf freetype-2.12.1.tar.gz
#rm -rf freetype-2.12.1
fi fi
+14 -5
View File
@@ -15,11 +15,20 @@ SOURCE_ROOT=$rootPath/source/lib
if [ ! -d ${SERVER_ROOT}/freetype_old ];then if [ ! -d ${SERVER_ROOT}/freetype_old ];then
cd $SOURCE_ROOT cd $SOURCE_ROOT
wget -O freetype-2.7.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.7.1.tar.gz -T 5
tar zxvf freetype-2.7.1.tar.gz if [ ! -f $SOURCE_ROOT/freetype-2.7.1.tar.gz ];then
cd freetype-2.7.1 wget -O freetype-2.7.1.tar.gz --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.7.1.tar.gz -T 5
fi
if [ ! -d $SOURCE_ROOT/freetype-2.7.1 ];then
tar zxvf freetype-2.7.1.tar.gz
cd freetype-2.7.1
else
cd freetype-2.7.1
fi
./configure --prefix=${SERVER_ROOT}/freetype_old && make && make install ./configure --prefix=${SERVER_ROOT}/freetype_old && make && make install
#cd $SOURCE_ROOT cd $SOURCE_ROOT && rm -rf freetype-2.7.1
#rm -rf freetype-2.7.1.tar.gz #rm -rf freetype-2.7.1.tar.gz
#rm -rf freetype-2.7.1
fi fi
+16
View File
@@ -24,6 +24,22 @@ mkdir -p $serverPath/php
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.gz ];then if [ ! -f $sourcePath/php/php-${version}.tar.gz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.gz https://museum.php.net/php5/php-${version}.tar.gz wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.gz https://museum.php.net/php5/php-${version}.tar.gz
fi fi
+16
View File
@@ -24,6 +24,22 @@ mkdir -p $serverPath/php
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz
fi fi
+16
View File
@@ -24,6 +24,22 @@ mkdir -p $serverPath/php
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.gz ];then if [ ! -f $sourcePath/php/php-${version}.tar.gz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.gz https://museum.php.net/php5/php-${version}.tar.gz wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.gz https://museum.php.net/php5/php-${version}.tar.gz
fi fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz
fi fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php5/php-${version}.tar.xz
fi fi
+16
View File
@@ -23,6 +23,22 @@ cd ${rootPath}/plugins/php/lib && /bin/bash freetype_old.sh
cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh cd ${rootPath}/plugins/php/lib && /bin/bash zlib.sh
if [ ! -d $sourcePath/php/php${PHP_VER} ];then if [ ! -d $sourcePath/php/php${PHP_VER} ];then
# ----------------------------------------------------------------------- #
# 中国优化安装
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
LOCAL_ADDR=common
if [ ! -z "$cn" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "cn" ];then
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://mirrors.sohu.com/php/php-${version}.tar.xz
fi
fi
# ----------------------------------------------------------------------- #
if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then if [ ! -f $sourcePath/php/php-${version}.tar.xz ];then
wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz wget --no-check-certificate -O $sourcePath/php/php-${version}.tar.xz https://museum.php.net/php7/php-${version}.tar.xz
fi fi

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