Compare commits

...
332 Commits
Author SHA1 Message Date
Mr Chen c4a844cadb Merge pull request #209 from midoks/dev
0.9.13
2022-10-11 12:47:26 +08:00
midoks a88a281175 0.9.13
0.9.13
2022-10-11 12:46:35 +08:00
midoks f3f3b1c6bd Update init.lua 2022-10-11 12:35:59 +08:00
midoks 4259ac51cb up 2022-10-11 11:41:32 +08:00
midoks 4db1357d3d 更新mysql版本 2022-10-11 09:03:53 +08:00
midoks 15873e0824 Update op_waf.js 2022-10-11 00:40:21 +08:00
midoks dcdb07f76d up 2022-10-11 00:35:13 +08:00
midoks 8b70637479 Update index.py 2022-10-10 23:28:36 +08:00
midoks c77085fea4 Update index.py 2022-10-10 23:27:20 +08:00
midoks a265f3d0d5 Update index.py 2022-10-10 23:24:54 +08:00
midoks 7ea486cd1d Update index.py 2022-10-10 23:22:43 +08:00
midoks 0e31e87e28 Update index.py 2022-10-10 23:22:04 +08:00
midoks 8c621c892e Update index.py 2022-10-10 23:16:59 +08:00
midoks 32bcae603c Update index.py 2022-10-10 23:16:48 +08:00
midoks 98ec21446d Update index.py 2022-10-10 22:41:36 +08:00
midoks 0ee3682502 Update redis.service.tpl 2022-10-10 22:11:51 +08:00
midoks c609d1a012 Update redis.service.tpl 2022-10-10 22:05:55 +08:00
midoks 27b1a78879 up 2022-10-10 22:03:21 +08:00
midoks 773de840a5 Update redis.js 2022-10-10 21:55:00 +08:00
midoks 91d6ff3c54 Update index.py 2022-10-10 21:52:11 +08:00
midoks 03376bd42d Update redis.conf 2022-10-10 21:50:04 +08:00
midoks 036c5114c2 Update index.py 2022-10-10 21:35:51 +08:00
midoks a772e70fde Update index.py 2022-10-10 21:33:20 +08:00
midoks 53055bbdef Update index.py 2022-10-10 21:31:43 +08:00
midoks f81d598fcf Update index.py 2022-10-10 21:13:44 +08:00
midoks 3530e83bb9 up 2022-10-10 21:09:35 +08:00
midoks 1271b2f637 Update index.py 2022-10-10 21:00:30 +08:00
midoks 2dc6bc7753 Update index.py 2022-10-10 20:58:45 +08:00
midoks e52d9e3ea3 Update index.py 2022-10-10 20:55:45 +08:00
midoks d8a570e55e Update index.html 2022-10-10 20:46:07 +08:00
midoks f4ceaf667b php-yum更新 2022-10-10 20:43:48 +08:00
midoks 958ba16b85 Update index.html 2022-10-10 20:28:44 +08:00
midoks 73039777bb Update index.py 2022-10-10 20:06:00 +08:00
midoks 864e4c910c PHP添加会话管理功能 2022-10-10 19:54:23 +08:00
midoks 4da57405af Update init.lua 2022-10-10 13:01:27 +08:00
midoks dff638571a Update init.lua 2022-10-10 12:45:31 +08:00
midoks c7d9ec51cc up 2022-10-10 12:36:42 +08:00
midoks 501c575f73 up 2022-10-10 12:13:45 +08:00
midoks 0fd966ca65 up 2022-10-10 02:14:31 +08:00
midoks 172dde2794 Update mariadb.js 2022-10-09 23:26:50 +08:00
midoks 78fdc80652 优化mysql进入phpmyadmin 2022-10-09 23:24:47 +08:00
midoks 01b8c9b8ff Update init.lua 2022-10-09 22:47:28 +08:00
midoks b840086d4d op防火墙更新1 2022-10-09 21:29:40 +08:00
midoks 4c73f13f2d up 2022-10-09 11:36:57 +08:00
midoks f31c1aae96 up 2022-10-09 10:39:46 +08:00
midoks 5c24a831db Update index.py 2022-10-09 02:04:17 +08:00
midoks 91d07eebad Update install.sh 2022-10-09 01:59:17 +08:00
midoks 3b51ef2434 up 2022-10-09 01:49:17 +08:00
midoks 31c5e42b09 Update index.html 2022-10-09 01:38:15 +08:00
midoks b8b3a237ef up 2022-10-09 01:37:14 +08:00
midoks 5cb2aefbbc up 2022-10-09 01:25:53 +08:00
midoks 19173af3e2 Update logs_backup.py 2022-10-09 00:31:15 +08:00
midoks 3dc493108b Update mw.tpl 2022-10-09 00:30:03 +08:00
midoks 55af62000b Update logs_backup.py 2022-10-09 00:26:28 +08:00
midoks a1c8c48761 Update index.js 2022-10-08 22:45:44 +08:00
midoks 8c3ec0a103 Update index.js 2022-10-08 22:40:23 +08:00
midoks 5cbde31105 Update tool_task.py 2022-10-08 18:15:57 +08:00
midoks 04dd94032e Update tool_task.py 2022-10-08 18:12:45 +08:00
midoks 8a11195b0d Update tool_task.py 2022-10-08 18:08:38 +08:00
midoks 1eb76baae7 改变弹框方式 2022-10-08 16:05:24 +08:00
midoks 2669d6f021 Update init.lua 2022-10-08 15:21:17 +08:00
midoks 6f13a03a2c Update config_api.py 2022-10-08 14:24:58 +08:00
Mr Chen 9c97e1c41c Merge pull request #205 from midoks/dev
0.9.12
2022-10-08 14:21:46 +08:00
midoks 37245ca1e8 0.9.12
* 日志清理插件优化。
* 计划任务显示完整。
* 加入gitea插件。
* 融合mw-cli命令。
* 加快php编译速度。
* swap加上调整功能。
* 其他细节优化。
2022-10-08 14:20:47 +08:00
midoks f706a8a2ea up 2022-10-08 14:03:01 +08:00
midoks e6af6b2062 up 2022-10-07 21:29:00 +08:00
midoks f5b056c965 init 2022-10-07 01:00:02 +08:00
midoks 8c768e8a04 Create tool_task.py 2022-10-07 00:47:26 +08:00
midoks 1d6f4feccb Update soft.js 2022-10-07 00:46:32 +08:00
midoks 49c32dc9c1 Update index.py 2022-10-06 17:52:25 +08:00
midoks 17a865c45d Update install.sh 2022-10-06 17:28:37 +08:00
midoks 0090681ab2 Update index.py 2022-10-06 17:25:15 +08:00
midoks 4d3a6c27f7 up 2022-10-06 17:19:36 +08:00
midoks abf39428fc Update index.py 2022-10-06 17:08:46 +08:00
midoks ec11904959 up 2022-10-06 17:07:26 +08:00
midoks d18f16a2b8 up 2022-10-06 15:32:30 +08:00
midoks 7fbe421b0c 加快php编译速度 2022-10-06 14:16:46 +08:00
midoks 81c7929240 Update install.sh 2022-10-06 14:09:46 +08:00
midoks 76c655872b Update install.sh 2022-10-06 14:09:22 +08:00
midoks 7b09776392 Update install.sh 2022-10-06 14:08:52 +08:00
midoks 0b28077e08 up 2022-10-06 14:07:10 +08:00
midoks ccc00e8b5d 更新版本 2022-10-06 13:40:52 +08:00
midoks 202e04c62d Update install.sh 2022-10-06 13:30:50 +08:00
midoks 01cd35305e Update ubuntu.sh 2022-10-06 13:10:44 +08:00
midoks 2f0d7d1d07 融合mw-cli结束2 2022-10-06 11:22:42 +08:00
midoks 714af23627 融合mw-cli结束 2022-10-06 11:13:09 +08:00
midoks 0a9eb721c6 Delete mw-cli 2022-10-06 11:12:18 +08:00
midoks 5e71c20e2a up 2022-10-06 11:12:01 +08:00
midoks 3c24d9f9a9 Update mw.tpl 2022-10-06 09:32:46 +08:00
midoks 78bdcb79c8 Update index.py 2022-10-05 20:51:38 +08:00
midoks aaf3389460 Update index.py 2022-10-05 20:50:39 +08:00
midoks 9f2cb58812 Update index.py 2022-10-05 20:50:31 +08:00
midoks c6099fb7ce Update gitea.service.tpl 2022-10-05 20:45:01 +08:00
midoks 3fb4d88c4a Update gitea.service.tpl 2022-10-05 20:44:43 +08:00
midoks f90fec182c Update install.sh 2022-10-05 20:39:55 +08:00
midoks ba86217a1a Update mw.py 2022-10-05 20:37:02 +08:00
midoks 9a7bcdc1c4 up 2022-10-05 20:34:43 +08:00
midoks 43b1f5ed86 Update gitea.service.tpl 2022-10-05 20:08:41 +08:00
midoks 68ca194c2d Update gitea.service.tpl 2022-10-05 20:05:27 +08:00
midoks 061eaabe79 Update gitea.service.tpl 2022-10-05 19:50:08 +08:00
midoks 420e830ed9 Update crontab_api.py 2022-10-05 17:52:09 +08:00
midoks 8e9cba6646 Update phplib.conf 2022-10-05 14:06:20 +08:00
midoks e0c183c1ac 加入gitea 2022-10-03 12:27:44 +08:00
midoks 18c59da28d Update crontab.js 2022-10-02 15:33:14 +08:00
midoks 71f2d66966 计划任务 显示完整 2022-10-02 15:23:29 +08:00
midoks abd6cdd738 日志清理 插件优化 2022-10-02 15:05:13 +08:00
midoks dd7b1707c3 Update README.md 2022-10-02 09:33:21 +08:00
Mr Chen 1282babb06 Merge pull request #202 from midoks/dev
0.9.11
2022-10-02 09:27:12 +08:00
midoks 71770ec406 0.9.11 2022-10-02 09:25:33 +08:00
midoks f36495f0fd Update app.sh 2022-10-02 02:04:29 +08:00
midoks 1cc4813c52 up 2022-10-01 20:38:28 +08:00
midoks 2ae74d6199 up 2022-10-01 20:14:28 +08:00
midoks 92d83bb82d Update index.py 2022-10-01 20:09:32 +08:00
midoks f14d55fcc6 Update index.py 2022-10-01 20:09:11 +08:00
midoks 062de09b3b Update app.sh 2022-10-01 19:53:11 +08:00
midoks 5cbd53a667 Update mw.tpl 2022-10-01 19:49:00 +08:00
midoks cf645d1f20 Update mw.tpl 2022-10-01 19:45:45 +08:00
midoks 5b8cf7bb0a #201 2022-10-01 18:57:15 +08:00
midoks f5161bca66 随机端口-WEB面板 2022-10-01 17:58:51 +08:00
midoks 5934be02bd Update setting.py 2022-10-01 16:56:18 +08:00
midoks 9e9f10b06f 端口随机 2022-10-01 16:41:55 +08:00
midoks 0fafeabcf0 up 2022-09-30 16:13:49 +08:00
midoks f98e4db019 Update index.py 2022-09-29 23:07:12 +08:00
midoks ec00e9d17e Update index.py 2022-09-29 23:06:53 +08:00
midoks b236bd85c9 up 2022-09-29 22:21:12 +08:00
midoks 40a8620745 Update task.py 2022-09-29 18:56:20 +08:00
midoks 0307828a82 Update index.py 2022-09-28 23:20:38 +08:00
midoks e7d2eddc20 Update install.sh 2022-09-28 19:49:35 +08:00
midoks 8c41b4c3fa Update install.sh 2022-09-28 19:46:22 +08:00
midoks 3ea67beea9 Update install.sh 2022-09-28 19:46:13 +08:00
midoks a346da07ad Update install.sh 2022-09-28 19:45:52 +08:00
midoks 067ee597a7 Update index.py 2022-09-28 19:15:58 +08:00
midoks aac7704208 Update index.py 2022-09-28 19:15:34 +08:00
midoks 3a10aa7809 Update index.py 2022-09-28 19:12:50 +08:00
midoks 1b4582574c Update imail.service.tpl 2022-09-28 19:10:41 +08:00
midoks 51b8738cbc Update index.py 2022-09-28 19:10:22 +08:00
midoks 0dd3c1844e Update index.py 2022-09-28 19:09:46 +08:00
midoks 0dabfdacbd Update imail.tpl 2022-09-28 19:08:21 +08:00
midoks d0166f03bb Update info.json 2022-09-28 19:04:09 +08:00
midoks b102d4dd1f up 2022-09-28 19:02:07 +08:00
midoks 576f553317 Update index.html 2022-09-26 21:44:58 +08:00
midoks 31a0903514 Update public.js 2022-09-26 21:15:26 +08:00
midoks 796c19b5dc Update install.sh 2022-09-26 21:00:52 +08:00
midoks b7902ae2d0 Update install.sh 2022-09-26 21:00:07 +08:00
midoks 7deaf2822a Update index.py 2022-09-26 20:57:37 +08:00
midoks 7e78c2dac4 up 2022-09-26 20:57:26 +08:00
midoks f341c80fbe up imail 2022-09-26 20:51:23 +08:00
midoks b593cc4708 init 2022-09-26 17:04:32 +08:00
midoks 7a8c83ee90 Update index.py 2022-09-25 18:54:47 +08:00
midoks 8c410b272d Update index.py 2022-09-25 17:59:16 +08:00
midoks ecacb44df8 Update index.py 2022-09-25 13:54:48 +08:00
midoks dcfaa1a6c9 Update index.py 2022-09-25 13:52:37 +08:00
midoks c51e50f815 Update index.py 2022-09-25 13:52:21 +08:00
midoks 84b0fbc8ef Update index.py 2022-09-25 13:41:52 +08:00
midoks 4d83c44a73 Update index.py 2022-09-25 13:11:28 +08:00
midoks 4d82835658 mysql 初始化 删除冗余账户 2022-09-25 13:09:19 +08:00
midoks cf863662e0 Update mw.py 2022-09-23 17:09:44 +08:00
midoks 4a66b76963 Update mw.py 2022-09-23 16:54:38 +08:00
midoks 0da43b6ccb 调整接口 2022-09-23 16:10:24 +08:00
midoks c2ad19a4de 后台解压测试 2022-09-22 09:50:18 +08:00
midoks db6538b57c 网站同步优化 2022-09-22 00:27:28 +08:00
Mr Chen 535f6ddc77 Merge pull request #199 from midoks/dev
0.9.10
2022-09-21 23:11:44 +08:00
midoks aa3950ccfe 0.9.10 2022-09-21 23:10:18 +08:00
midoks 8a81f8bb83 Update site_api.py 2022-09-21 17:54:32 +08:00
midoks 55d987c0bd 修复批量添加 2022-09-21 17:42:32 +08:00
midoks 416e9e7cda 如果目录存在,就不初始化 2022-09-21 17:30:59 +08:00
midoks eedaef7eec Update site_api.py 2022-09-21 17:06:19 +08:00
midoks 3265deed3d Update site_api.py 2022-09-21 17:01:41 +08:00
midoks 1c7db0e2ec 优化open_basedir配置2 2022-09-21 16:51:42 +08:00
midoks 7872891797 Update site.js 2022-09-21 16:17:11 +08:00
midoks 8b074090a7 前端配置 2022-09-21 15:37:00 +08:00
midoks 50f198e2d3 优化open_basedir配置 2022-09-21 15:12:10 +08:00
midoks 07e017c9a7 Update lib.sh 2022-09-20 17:46:01 +08:00
midoks ca0aed7240 up 2022-09-20 17:17:47 +08:00
midoks 0126bcb68c Update info.json 2022-09-20 17:14:38 +08:00
midoks 7c37df5dec Update all_test.sh 2022-09-20 17:12:06 +08:00
midoks 33bc6e19e7 up 2022-09-20 17:10:09 +08:00
midoks 35d42a5603 up 2022-09-20 16:32:11 +08:00
midoks 8a79beab89 up 2022-09-20 14:40:45 +08:00
midoks cafff1d522 up 2022-09-20 14:29:46 +08:00
midoks e266d85c91 ip 2022-09-20 12:10:27 +08:00
midoks e873ea8639 Update install.sh 2022-09-20 12:01:02 +08:00
midoks 0cdc23a096 Update install.sh 2022-09-20 11:55:32 +08:00
midoks 2c0231155d 优化 日志读取 2022-09-20 11:30:04 +08:00
midoks 5583db0c70 Update crontab_api.py 2022-09-20 00:24:40 +08:00
midoks 2eeef4d8bd Update mw.py 2022-09-20 00:22:11 +08:00
midoks 5a93b07968 加入开发模式开关 2022-09-19 20:47:12 +08:00
midoks b5195ba685 mail 开发阶段 2022-09-19 20:07:34 +08:00
midoks 4c05747942 移动到:https://github.com/mw-plugin/mail
稳定后,再合并。
2022-09-19 20:05:05 +08:00
midoks 3722f57347 up 2022-09-19 16:16:25 +08:00
midoks b7a3c32d3f ip 2022-09-19 15:01:17 +08:00
midoks 6c0cb42e35 优化 urllib + header 2022-09-19 14:34:47 +08:00
midoks a84e7a16a3 Update index.html 2022-09-19 14:13:18 +08:00
midoks fab1cb1bbe Update install.sh 2022-09-19 13:41:20 +08:00
midoks b46d7c1dee Update mail.js 2022-09-19 13:31:55 +08:00
midoks 8f4dda2d65 up 2022-09-19 11:25:43 +08:00
midoks e21d17e342 up 2022-09-18 21:16:22 +08:00
midoks 87eab46ed6 Update index.py 2022-09-18 20:37:10 +08:00
midoks e0ebed3080 up 2022-09-18 20:00:23 +08:00
midoks 372dbc8995 mail 添加域名 2022-09-18 00:05:45 +08:00
midoks 33faf1e54c Update index.html 2022-09-17 22:39:42 +08:00
midoks 47f67275d5 up 2022-09-17 21:09:53 +08:00
midoks e45ebc5f11 Update index.py 2022-09-16 13:47:57 +08:00
midoks 9ee570e3bb Update config_api.py 2022-09-16 12:15:39 +08:00
midoks cc80ec7839 Update index.js 2022-09-16 12:14:07 +08:00
midoks e7174a2111 Update index.js 2022-09-16 12:13:34 +08:00
midoks ef6adfd82d Update index.js 2022-09-16 12:11:09 +08:00
midoks daf6c9bff8 优化 2022-09-16 12:05:50 +08:00
midoks 9f02092788 Update system_api.py 2022-09-16 11:52:20 +08:00
midoks b314ebeed3 cpu tips 优化
gogs 统计优化
2022-09-16 11:49:20 +08:00
midoks 38f8fe9a38 画丿 2022-09-15 17:59:37 +08:00
midoks c0e1512195 init 2022-09-15 00:16:08 +08:00
midoks b616854baa redis 添加性能调整功能 2022-09-14 20:50:32 +08:00
midoks 1ad9546ae4 Update install.sh 2022-09-13 23:48:01 +08:00
midoks fb3aac37ec Update install.sh 2022-09-13 23:42:54 +08:00
midoks 598f964e91 Update install.sh 2022-09-13 23:41:34 +08:00
midoks d9e46f1065 Update install.sh 2022-09-13 23:34:37 +08:00
midoks 565d011191 Update index.html 2022-09-13 22:04:18 +08:00
midoks 6ae6e5fafc Update info.json 2022-09-13 21:53:30 +08:00
midoks eb1c0efda1 Update gettext.sh 2022-09-13 21:06:11 +08:00
midoks 98bc816b21 up 2022-09-13 21:02:55 +08:00
Mr Chen 85735287c3 Merge pull request #195 from midoks/dev
Update README.md
2022-09-12 10:06:43 +08:00
midoks d59022ae44 Update README.md 2022-09-12 10:02:24 +08:00
Mr Chen 70a17af9d8 Merge pull request #192 from midoks/dev
优化OP反代面板之后显示错误
2022-09-11 20:07:48 +08:00
midoks 09feeb11d2 zhu 2022-09-11 20:00:10 +08:00
midoks d95e1e68c4 优化OP反代面板之后显示错误的错误 2022-09-11 19:58:15 +08:00
Mr Chen 6e484babe9 Merge pull request #191 from h88782481/dev
Update index.py
2022-09-11 19:00:37 +08:00
JiRan d37ff296f6 Update index.py 2022-09-11 18:59:16 +08:00
Mr Chen f95d25f080 Merge pull request #190 from h88782481/dev
Dev
2022-09-11 18:53:16 +08:00
JiRan fd35db3dd8 Update index.py 2022-09-11 18:45:44 +08:00
JiRan f22e10a496 Update mw.py 2022-09-11 18:40:41 +08:00
midoks 52f80ec3b7 Update debian.sh 2022-09-11 17:32:16 +08:00
Mr Chen 41fd11c0f4 Merge pull request #187 from midoks/dev
fix cmd.md
2022-09-10 11:08:36 +08:00
midoks f8a5e7dab5 Update cmd.md 2022-09-10 11:07:33 +08:00
Mr Chen 4b71d6b3d7 Merge pull request #185 from midoks/dev
0.9.9
2022-09-09 21:31:36 +08:00
midoks becb7f8c7f Update README.md 2022-09-09 21:21:33 +08:00
midoks 3da7b57242 Update README.md 2022-09-08 23:39:33 +08:00
midoks 42e8057356 Update memcached.sh 2022-09-08 21:49:03 +08:00
midoks e082baabe8 PHP加入igbinary扩展 2022-09-08 21:16:59 +08:00
midoks 74d565c99a 0.9.9 2022-09-08 15:40:47 +08:00
midoks 750efbf430 Update xhprof.sh 2022-09-07 14:39:43 +08:00
midoks 68112ba978 Update install.sh 2022-09-07 10:16:03 +08:00
midoks e994375fc8 Update cloudfare_real_ip.conf 2022-09-07 09:54:20 +08:00
midoks 998f677ee7 Create cloudfare_real_ip.conf 2022-09-07 09:06:15 +08:00
midoks 8b1b50938d Update README.md 2022-09-06 22:41:11 +08:00
midoks 3dbece0b5e Update README.md 2022-09-06 22:19:57 +08:00
midoks e9f1e522de Update README.md 2022-09-06 22:19:21 +08:00
midoks 8a815159c1 Update README.md 2022-09-06 22:08:42 +08:00
midoks c8af676d6f up 2022-09-06 22:07:12 +08:00
midoks 3bee84a52f Update README.md 2022-09-06 21:54:07 +08:00
midoks 82828aacf6 优化gogs插件 2022-09-06 17:45:56 +08:00
midoks e4de3cff61 更新图标 2022-09-06 15:35:03 +08:00
midoks 4ed7f5d7fd Update index.py 2022-09-05 23:06:31 +08:00
midoks 7b956c73e4 Update index.py 2022-09-05 22:58:53 +08:00
midoks 8535dd2306 up 2022-09-05 22:56:38 +08:00
midoks e13df3ae58 Update index.py 2022-09-05 22:49:57 +08:00
midoks 44fa68f52d Update index.py 2022-09-05 22:48:25 +08:00
midoks d72abb1e30 修复php-yum无法更改性能调整 2022-09-05 22:33:30 +08:00
midoks aad4343a59 Update whmcs.conf 2022-09-05 11:36:00 +08:00
midoks 6b5717b04f 优化的配置模板 2022-09-04 18:16:04 +08:00
midoks 655946a467 Update install.sh 2022-09-04 17:18:45 +08:00
midoks 80f3d98162 Update update_dev.sh 2022-09-04 17:07:51 +08:00
midoks d73be680e2 Update README.md 2022-09-04 17:04:48 +08:00
midoks ad9595b3b2 Update update_dev.sh 2022-09-04 17:01:47 +08:00
midoks 8a337fcfd6 Update site_api.py 2022-09-03 23:37:17 +08:00
midoks 38b1dba395 卸载是停止 2022-09-03 23:08:41 +08:00
midoks 7195de0418 up 2022-09-03 21:31:22 +08:00
midoks 20cb30ba51 Update update_dev.sh 2022-09-03 21:24:26 +08:00
midoks 2a7c96b0f5 Update install_dev.sh 2022-09-03 21:24:08 +08:00
midoks 8503e6ebe9 增加 amazon 2022-09-03 21:21:12 +08:00
midoks be2c2a2436 Update phplib.conf 2022-09-03 19:00:18 +08:00
midoks 8a247c93d4 Update memcached.sh 2022-09-03 17:54:55 +08:00
midoks b4cdc7fc2d Update memcached.sh 2022-09-03 17:43:23 +08:00
midoks cc3f1ed01a Update README.md 2022-09-03 15:53:22 +08:00
midoks 4db4284362 Update README.md 2022-09-03 15:51:03 +08:00
midoks 3c2e517c61 Update README.md 2022-09-03 14:17:01 +08:00
midoks 1d712d1f84 Update README.md 2022-09-03 14:08:17 +08:00
midoks f1e1e3c82c Update README.md 2022-09-03 13:43:18 +08:00
midoks 8e587cf055 Update install.sh 2022-09-02 23:16:41 +08:00
Mr Chen 277b95f74b Merge pull request #183 from itcbx/dev
修复rsyncd在debian或ubuntu下安装失败的bug.
2022-09-01 19:41:19 +08:00
iOSHackers b89b180ee9 修复rsyncd在debian或ubuntu下安装失败的bug. 2022-09-01 19:21:52 +08:00
midoks 3e89c35111 Update phplib.conf 2022-08-31 23:22:34 +08:00
midoks 52f7939b06 Update phplib.conf 2022-08-31 23:21:39 +08:00
midoks 13d038e855 mysql,mariadb删除,不再支持程序删除。 2022-08-31 22:00:23 +08:00
midoks 325046d3c2 Update index.py 2022-08-31 21:53:59 +08:00
midoks 8cb3b578e0 Update index.py 2022-08-31 21:52:19 +08:00
midoks 3b5a5206fc Update index.py 2022-08-31 21:50:03 +08:00
Mr Chen 1517d8d2d7 Merge pull request #181 from midoks/dev
0.9.7
2022-08-29 13:15:36 +08:00
midoks ba55477492 up 2022-08-29 13:14:41 +08:00
midoks e363833437 Update install.sh 2022-08-29 13:12:37 +08:00
midoks 6ec51baedb Update install.sh 2022-08-29 12:48:28 +08:00
midoks 0fdf62499b Update index.py 2022-08-29 12:22:59 +08:00
midoks 1498e23b48 Update haproxy.js 2022-08-29 12:14:13 +08:00
midoks 106ce839d8 Update index.html 2022-08-29 12:13:40 +08:00
midoks eed561dadc Update haproxy.conf 2022-08-29 12:09:13 +08:00
midoks c97ec1cbba up 2022-08-29 12:08:02 +08:00
midoks 29802d8066 up 2022-08-29 11:32:29 +08:00
midoks 9a51bc4b4e Update index.py 2022-08-29 00:35:46 +08:00
midoks 082f697706 Update index.py 2022-08-29 00:34:58 +08:00
midoks 6e026f2998 Update install.sh 2022-08-28 23:35:31 +08:00
midoks c647f0c02d Update haproxy.tpl 2022-08-28 23:26:02 +08:00
midoks da99297253 Update haproxy.service.tpl 2022-08-28 23:25:31 +08:00
midoks 4ab982827e 优化 2022-08-28 23:02:37 +08:00
midoks d3a4db511a haproxy init 2022-08-28 22:50:17 +08:00
midoks fa9e4e3b06 Update index.py 2022-08-24 15:31:44 +08:00
midoks e7cd941f0f Update index.py 2022-08-24 15:16:59 +08:00
midoks c641606ecd #175
统计流量区分类型
2022-08-23 11:13:44 +08:00
Mr Chen 021a360462 Merge pull request #177 from midoks/dev
优化getLocalIp方法
2022-08-23 07:37:59 +08:00
midoks 9104280ff1 不再全部测试 2022-08-23 07:37:11 +08:00
midoks 0ea0f2d13d 优化getLocalIp方法 2022-08-23 07:35:34 +08:00
Mr Chen 289e251480 Merge pull request #176 from midoks/dev
php74版本退回
2022-08-23 07:03:14 +08:00
midoks ce421cfb89 Update install.sh 2022-08-23 06:52:54 +08:00
Mr Chen bec41f2c63 Merge pull request #174 from midoks/dev
代码改变版本号
2022-08-22 13:28:50 +08:00
midoks 3a34974ec9 Update config_api.py 2022-08-22 13:26:48 +08:00
midoks a7c9fff283 up 2022-08-22 11:55:30 +08:00
midoks c36cca61a1 Update centos.sh 2022-08-22 11:52:05 +08:00
Mr Chen 42edf12d01 Merge pull request #172 from midoks/dev
0.9.6
2022-08-22 11:44:39 +08:00
midoks d6799e89c4 0.9.6 2022-08-22 11:43:11 +08:00
midoks 4b4006c9da Update index.html 2022-08-21 12:23:39 +08:00
midoks 33bb042b41 up 2022-08-17 19:16:51 +08:00
midoks be2e91b9ce mariadb up 2022-08-17 19:14:36 +08:00
midoks db424f8912 mariadb up 2022-08-17 19:12:12 +08:00
midoks bfca2e313a Update rsyncd.js 2022-08-17 12:01:28 +08:00
midoks 1de51747e6 Update supervisor.js 2022-08-17 09:28:25 +08:00
midoks 8a623b490b supervisor增加错误查看 2022-08-17 09:25:08 +08:00
midoks b5b8ef7e46 Update .gitignore 2022-08-16 22:08:07 +08:00
midoks daa561b6c4 Update README.md 2022-08-16 18:42:03 +08:00
midoks 9bc30db1ad Update README.md 2022-08-16 18:38:35 +08:00
midoks 1a9d506d61 Update README.md 2022-08-16 18:35:29 +08:00
midoks 62b5d812e2 Update install.sh 2022-08-16 17:29:10 +08:00
midoks 433c9ab5ea Update files_api.py 2022-08-16 11:51:46 +08:00
midoks a7a6976204 增加插件[备份]功能。
1. json: "hook":["backup"]   -- 备份钩子开启
2.crontab的执行周期添加优化。
2022-08-16 04:45:21 +08:00
206 changed files with 6958 additions and 6787 deletions
+2 -2
View File
@@ -5,9 +5,9 @@ name: MW APP MySQL55
on:
push:
branches: [ "master" ]
branches: [ "run_test" ]
pull_request:
branches: [ "master" ]
branches: [ "run_test" ]
permissions:
contents: read
+2 -2
View File
@@ -5,9 +5,9 @@ name: MW APP MySQL56
on:
push:
branches: [ "master" ]
branches: [ "run_test" ]
pull_request:
branches: [ "master" ]
branches: [ "run_test" ]
permissions:
contents: read
+2 -2
View File
@@ -5,9 +5,9 @@ name: MW APP MySQL57
on:
push:
branches: [ "master" ]
branches: [ "run_test" ]
pull_request:
branches: [ "master" ]
branches: [ "run_test" ]
permissions:
contents: read
+2 -2
View File
@@ -5,9 +5,9 @@ name: MW APP MySQL80
on:
push:
branches: [ "master" ]
branches: [ "run_test" ]
pull_request:
branches: [ "master" ]
branches: [ "run_test" ]
permissions:
contents: read
+2 -2
View File
@@ -5,9 +5,9 @@ name: MW APP PHP
on:
push:
branches: [ "master" ]
branches: [ "run_test" ]
pull_request:
branches: [ "master" ]
branches: [ "run_test" ]
permissions:
contents: read
+6 -2
View File
@@ -122,12 +122,14 @@ data/datadir.pl
data/502Task.pl
data/default.pl
data/backup.pl
data/debug.pl
data/default_site.pl
lib/python*
bin
pyvenv.cfg
include
share
pip-selfcheck.json
scripts/mdserver-web
@@ -140,16 +142,18 @@ data/restart.pl
data/ssl.pl
data/edate.pl
data/osname.pl
data/only_netio_counters.pl
data/system.db-journal
data/hook_*.json
plugins/l2tp
plugins/openlitespeed
plugins/gdrive
plugins/mtproxy
plugins/zimg
plugins/bk_demo
plugins/mail
debug.out
+41 -12
View File
@@ -1,4 +1,10 @@
### mdserver-web 0.9.5
<p align="center">
<img alt="logo" src="https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/logo.png" height="140" />
<h3 align="center">mdserver-web</h3>
<p align="center">一款简单Linux面板服务</p>
</p>
### 简介
简单的Linux面板,感谢BT.CN写出如此好的web管理软件。我一看到,就知道这是我一直想要的页面化管理方式。
复制了后台管理界面,按照自己想要的方式写了一版。
@@ -61,6 +67,19 @@ PHP[53-72]支持phpMyAdmin[4.4.15]
PHP[72-81]支持phpMyAdmin[5.2.0]
```
# 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.la/)
# AD - VPS推荐 - 🙏
- [ZZZ评测](https://www.zzzvps.com/)
| 服务商 | LOGO | 推广地址 | 优惠码 |
| ------------- |----------|-----------|-------|
| digitalvirt |[![digitalvirt](https://digitalvirt.com/templates/BlueWhite/img/logo-dark.svg)](https://digitalvirt.com/aff.php?aff=154) | https://digitalvirt.com/aff.php?aff=154 | 9SYDY7UH0U |
| 搬瓦工 |[![搬瓦工](https://bwh81.net/templates/organicbandwagon/images/logo.png)](https://bandwagonhost.com/aff.php?aff=54161) | https://bandwagonhost.com/aff.php?aff=54161 | BWH3HYATVBJW |
# Docker
- 由[DDSRem](https://github.com/DDSRem)开发维护。
@@ -71,14 +90,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.9.5
* 页面更新优化[2].
* 修复maridb的用户管理[2].
* Gogs初始化提示更人性.
* MySQL&&MariaDB修改密码修复.
* MySQL&&MariaDB导入修复.
### 版本更新 0.9.13
* 优化弹框。
* 修复计划任务[日志切割]。
* 优化mysql的与phpmyadmin的连接。
* PHP添加`会话管理`功能。
* redis优化。
* 更新mysql[5.7]的安装。
* OP防火墙部分功能优化。
### JSDelivr安装地址
@@ -124,16 +144,25 @@ curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/qu
```
curl -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 -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install_dev.sh | bash
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/update_dev.sh | bash
```
### 捐赠地址 USDT(TRC20)
TVbNgrpeGBGZVm5gTLa21ADP7RpnPFhjya
### 微信赞助
[![截图](/route/static/img/weixin_zz.jpg)](/route/static/img/weixin_zz.jpg)
[![截图](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/img/weixin_zz.jpg)](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/img/weixin_zz.jpg)
### 无图不真相
[![截图](/route/static/mdw.jpg)](/route/static/mdw.jpg)
[![截图](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/mdw.jpg)](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/mdw.jpg)
### Stargazers over time
@@ -143,7 +172,7 @@ curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/up
### 感谢开发赞助
[![digitalvirt](https://digitalvirt.com/templates/BlueWhite/img/logo-dark.svg)](https://digitalvirt.com/)
[![digitalvirt](https://digitalvirt.com/templates/BlueWhite/img/logo-dark.svg)](https://digitalvirt.com/aff.php?aff=154)
### 授权许可
+16 -2
View File
@@ -15,7 +15,7 @@ from flask import request
class config_api:
__version = '0.9.5'
__version = '0.9.13'
def __init__(self):
pass
@@ -207,6 +207,14 @@ class config_api:
mw.execShell("chown root.root " + filename)
return mw.returnJson(True, '面板已关闭!')
def openDebugApi(self):
filename = 'data/debug.pl'
if os.path.exists(filename):
os.remove(filename)
return mw.returnJson(True, '开发模式关闭!')
mw.writeFile(filename, 'True')
return mw.returnJson(True, '开发模式开启!')
def setIpv6StatusApi(self):
ipv6_file = 'data/ipv6.pl'
if os.path.exists('data/ipv6.pl'):
@@ -316,11 +324,17 @@ class config_api:
data['admin_path'] = mw.readFile(admin_path_file)
ipv6_file = 'data/ipv6.pl'
if os.path.exists('data/ipv6.pl'):
if os.path.exists(ipv6_file):
data['ipv6'] = 'checked'
else:
data['ipv6'] = ''
debug_file = 'data/debug.pl'
if os.path.exists(debug_file):
data['debug'] = 'checked'
else:
data['debug'] = ''
ssl_file = 'data/ssl.pl'
if os.path.exists('data/ssl.pl'):
data['ssl'] = 'checked'
+23 -16
View File
@@ -167,7 +167,7 @@ class crontab_api:
logFile = mw.getServerDir() + '/cron/' + echo['echo'] + '.log'
if not os.path.exists(logFile):
return mw.returnJson(False, '当前日志为空!')
log = mw.getNumLines(logFile, 500)
log = mw.getLastLine(logFile, 500)
return mw.returnJson(True, log)
def addApi(self):
@@ -295,9 +295,18 @@ class crontab_api:
# 取数据列表
def getDataListApi(self):
stype = request.form.get('type', '')
bak_data = []
if stype == 'sites' or stype == 'databases':
hookPath = mw.getPanelDataDir() + "/hook_backup.json"
if os.path.exists(hookPath):
t = mw.readFile(hookPath)
bak_data = json.loads(t)
if stype == 'databases':
db_list = {}
db_list['orderOpt'] = []
db_list['orderOpt'] = bak_data
path = mw.getServerDir() + '/mysql'
if not os.path.exists(path + '/mysql.db'):
db_list['data'] = []
@@ -307,8 +316,9 @@ class crontab_api:
return mw.getJson(db_list)
data = {}
data['orderOpt'] = bak_data
data['data'] = mw.M(stype).field('name,ps').select()
data['orderOpt'] = []
return mw.getJson(data)
##### ----- start ----- ###
@@ -404,23 +414,20 @@ class crontab_api:
script_dir = mw.getServerDir() + "/mdserver-web/scripts"
wheres = {
'path': head + "python " + script_dir + "/backup.py path " + param['sname'] + " " + str(param['save']),
'site': head + "python " + script_dir + "/backup.py site " + param['sname'] + " " + str(param['save']),
'database': head + "python " + script_dir + "/backup.py database " + param['sname'] + " " + str(param['save']),
'logs': head + "python " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
'path': head + "python3 " + script_dir + "/backup.py path " + param['sname'] + " " + str(param['save']),
'site': head + "python3 " + script_dir + "/backup.py site " + param['sname'] + " " + str(param['save']),
'database': head + "python3 " + script_dir + "/backup.py database " + param['sname'] + " " + str(param['save']),
'logs': head + "python3 " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
'rememory': head + "/bin/bash " + script_dir + '/rememory.sh'
}
if param['backup_to'] != 'localhost':
cfile = mw.getServerDir() + "/mdserver-web/plugin/" + \
param['backup_to'] + "/" + param['backup_to'] + "_main.py"
if not os.path.exists(cfile):
cfile = script_dir + "/backup_" + \
param['backup_to'] + ".py"
cfile = mw.getPluginDir() + "/" + \
param['backup_to'] + "/index.py"
wheres = {
'path': head + "python " + cfile + " path " + param['sname'] + " " + str(param['save']),
'site': head + "python " + cfile + " site " + param['sname'] + " " + str(param['save']),
'database': head + "python " + cfile + " database " + param['sname'] + " " + str(param['save']),
'logs': head + "python " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
'path': head + "python3 " + cfile + " path " + param['sname'] + " " + str(param['save']),
'site': head + "python3 " + cfile + " site " + param['sname'] + " " + str(param['save']),
'database': head + "python3 " + cfile + " database " + param['sname'] + " " + str(param['save']),
'logs': head + "python3 " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
'rememory': head + "/bin/bash " + script_dir + '/rememory.sh'
}
try:
+4 -5
View File
@@ -36,7 +36,7 @@ class files_api:
return mw.returnJson(False, '文件不存在', (path,))
try:
data = mw.getNumLines(path, int(line))
data = mw.getLastLine(path, int(line))
return mw.returnJson(True, 'OK', data)
except Exception as ex:
return mw.returnJson(False, u'无法正确读取文件!' + str(ex))
@@ -676,8 +676,7 @@ class files_api:
data['encoding'] = 'utf-8'
if char['encoding'] == 'Big5':
data['encoding'] = 'BIG5'
if not char['encoding'] in ['GBK', 'utf-8',
'BIG5']:
if not char['encoding'] in ['GBK', 'utf-8', 'BIG5']:
data['encoding'] = 'utf-8'
try:
if sys.version_info[0] == 2:
@@ -760,7 +759,7 @@ class files_api:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
if stype == 'zip':
os.system("cd " + path + " && unzip -d '" + dfile +
"' '" + sfile + "' > " + tmps + " 2>&1")
"' '" + sfile + "' > " + tmps + " 2>&1 &")
else:
sfiles = ''
for sfile in sfile.split(','):
@@ -768,7 +767,7 @@ class files_api:
continue
sfiles += " '" + sfile + "'"
os.system("cd " + path + " && tar -zxvf " + sfiles +
" -C " + dfile + " > " + tmps + " 2>&1")
" -C " + dfile + " > " + tmps + " 2>&1 &")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件解压成功!', (sfile, dfile))
return mw.returnJson(True, '文件解压成功!')
+18 -7
View File
@@ -59,22 +59,30 @@ class firewall_api:
# 添加放行端口
def addAcceptPortApi(self):
if not self.getFwStatus():
return mw.returnJson(False, '防火墙启动时,才能添加规则!')
import re
import time
port = request.form.get('port', '').strip()
ps = request.form.get('ps', '').strip()
stype = request.form.get('type', '').strip()
data = self.addAcceptPortArgs(port, ps, stype)
return mw.getJson(data)
# 添加放行端口
def addAcceptPortArgs(self, port, ps, stype):
import re
import time
if not self.getFwStatus():
self.setFw(0)
rep = "^\d{1,5}(:\d{1,5})?$"
if not re.search(rep, port):
return mw.returnJson(False, '端口范围不正确!')
return mw.returnData(False, '端口范围不正确!')
if mw.M('firewall').where("port=?", (port,)).count() > 0:
return mw.returnJson(False, '您要放行的端口已存在,无需重复放行!')
return mw.returnData(False, '您要放行的端口已存在,无需重复放行!')
msg = mw.getInfo('放行端口[{1}]成功', (port,))
mw.writeLog("防火墙管理", msg)
@@ -83,7 +91,7 @@ class firewall_api:
self.addAcceptPort(port)
self.firewallReload()
return mw.returnJson(True, '添加放行(' + port + ')端口成功!')
return mw.returnData(True, '添加放行(' + port + ')端口成功!')
# 删除IP屏蔽
def delDropAddressApi(self):
@@ -290,6 +298,9 @@ class firewall_api:
return mw.returnJson(True, '开发机不能设置!')
status = request.form.get('status', '1')
return mw.getJson(self.setFw(status))
def setFw(self, status):
if status == '1':
if self.__isUfw:
mw.execShell('/usr/sbin/ufw disable')
@@ -313,7 +324,7 @@ class firewall_api:
mw.execShell('/etc/init.d/iptables save')
mw.execShell('/etc/init.d/iptables restart')
return mw.returnJson(True, '设置成功!')
return mw.returnData(True, '设置成功!')
def delPanelLogsApi(self):
mw.M('logs').where('id>?', (0,)).delete()
+64 -25
View File
@@ -57,10 +57,22 @@ def getPluginDir():
return getRunDir() + '/plugins'
def getPanelDataDir():
return getRunDir() + '/data'
def getServerDir():
return getRootDir() + '/server'
def getLogsDir():
return getRootDir() + '/wwwlogs'
def getBackupDir():
return getRootDir() + '/backup'
def getWwwDir():
file = getRunDir() + '/data/site.pl'
if os.path.exists(file):
@@ -73,14 +85,6 @@ def setWwwDir(wdir):
return writeFile(file, wdir)
def getLogsDir():
return getRootDir() + '/wwwlogs'
def getBackupDir():
return getRootDir() + '/backup'
def setBackupDir(bdir):
file = getRunDir() + '/data/backup.pl'
return writeFile(file, bdir)
@@ -163,13 +167,13 @@ def restartWeb():
# systemd
systemd = '/lib/systemd/system/openresty.service'
if os.path.exists(systemd):
execShell('systemctl restart openresty')
execShell('systemctl reload openresty')
return True
# initd
initd = getServerDir() + '/openresty/init.d/openresty'
if os.path.exists(initd):
execShell(initd + ' ' + 'restart')
execShell(initd + ' ' + 'reload')
return True
return False
@@ -402,6 +406,30 @@ def writeFile(filename, str):
return False
def backFile(self, file, act=None):
"""
@name 备份配置文件
@param file 需要备份的文件
@param act 如果存在,则备份一份作为默认配置
"""
file_type = "_bak"
if act:
file_type = "_def"
execShell("/usr/bin/cp -p {0} {1}".format(file, file + file_type))
def restoreFile(self, file, act=None):
"""
@name 还原配置文件
@param file 需要还原的文件
@param act 如果存在,则还原默认配置
"""
file_type = "_bak"
if act:
file_type = "_def"
execShell("/usr/bin/cp -p {1} {0}".format(file, file + file_type))
def HttpGet(url, timeout=10):
"""
发送GET请求
@@ -524,7 +552,7 @@ def getSpeed():
return json.loads(data)
def getLastLine(inputfile, lineNum):
def getLastLineBk(inputfile, lineNum):
# 读文件指定倒数行数
try:
fp = open(inputfile, 'rb')
@@ -557,7 +585,7 @@ def getLastLine(inputfile, lineNum):
# return getMsg('TASK_SLEEP')
def getNumLines(path, num, p=1):
def getLastLine(path, num, p=1):
pyVersion = sys.version_info[0]
try:
import html
@@ -596,7 +624,7 @@ def getNumLines(path, num, p=1):
t_buf = fp.read(to_read)
if pyVersion == 3:
if type(t_buf) == bytes:
t_buf = t_buf.decode('utf-8')
t_buf = t_buf.decode("utf-8", "ignore").strip()
buf = t_buf + buf
fp.seek(-to_read, 1)
if pos - to_read == 0:
@@ -605,7 +633,7 @@ def getNumLines(path, num, p=1):
break
fp.close()
except Exception as e:
return ''
return str(e)
return "\n".join(data)
@@ -646,16 +674,14 @@ def getLocalIp():
try:
ipaddress = readFile(filename)
if not ipaddress or ipaddress == '127.0.0.1':
raise Exception("ip is empty!")
cmd = "curl -4 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text"
ip = execShell(cmd)
result = ip[0].strip()
if result == '':
raise Exception("ipv4 is empty!")
writeFile(filename, result)
return result
return ipaddress
except Exception as e:
cmd = "curl -4 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text"
ip = execShell(cmd)
result = ip[0].strip()
if result == '':
raise e
writeFile(filename, result)
return result
except Exception as e:
cmd = "curl -6 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text"
ip = execShell(cmd)
@@ -664,6 +690,8 @@ def getLocalIp():
return '127.0.0.1'
writeFile(filename, result)
return result
finally:
pass
return '127.0.0.1'
@@ -710,13 +738,24 @@ def getStrBetween(startStr, endStr, srcStr):
def getCpuType():
cpuType = ''
if isAppleSystem():
cmd = "system_profiler SPHardwareDataType | grep 'Processor Name' | awk -F ':' '{print $2}'"
cpuinfo = execShell(cmd)
return cpuinfo[0].strip()
# 取CPU类型
cpuinfo = open('/proc/cpuinfo', 'r').read()
rep = "model\s+name\s+:\s+(.+)"
tmp = re.search(rep, cpuinfo)
cpuType = None
tmp = re.search(rep, cpuinfo, re.I)
if tmp:
cpuType = tmp.groups()[0]
else:
cpuinfo = execShell('LANG="en_US.UTF-8" && lscpu')[0]
rep = "Model\s+name:\s+(.+)"
tmp = re.search(rep, cpuinfo, re.I)
if tmp:
cpuType = tmp.groups()[0]
return cpuType
+53 -4
View File
@@ -114,6 +114,7 @@ class plugins_api:
return mw.returnJson(False, '配置文件不存在!', ())
pluginInfo = json.loads(mw.readFile(infoJsonPos))
self.hookInstall(pluginInfo)
execstr = "cd " + os.getcwd() + "/plugins/" + \
name + " && /bin/bash " + pluginInfo["shell"] \
@@ -131,6 +132,55 @@ class plugins_api:
mw.triggerTask()
return mw.returnJson(True, '已将安装任务添加到队列!')
def hookInstallFile(self, hook_name, info):
hookPath = mw.getPanelDataDir() + "/hook_" + hook_name + ".json"
data = []
if os.path.exists(hookPath):
t = mw.readFile(hookPath)
data = json.loads(t)
isNeedAdd = True
for x in range(len(data)):
if data[x]['title'] == info['title'] and data[x]['name'] == info['name']:
isNeedAdd = False
if isNeedAdd:
tmp = {}
tmp['title'] = info['title']
tmp['name'] = info['name']
data.append(tmp)
mw.writeFile(hookPath, json.dumps(data))
def hookUninstallFile(self, hook_name, info):
hookPath = mw.getPanelDataDir() + "/hook_" + hook_name + ".json"
data = []
if os.path.exists(hookPath):
t = mw.readFile(hookPath)
data = json.loads(t)
for idx in range(len(data)):
if data[idx]['title'] == info['title'] and data[idx]['name'] == info['name']:
data.remove(data[idx])
mw.writeFile(hookPath, json.dumps(data))
def hookInstall(self, info):
if 'hook' in info:
hooks = info['hook']
for x in hooks:
if x in ['backup']:
self.hookInstallFile(x, info)
return True
return False
def hookUninstall(self, info):
if 'hook' in info:
hooks = info['hook']
for x in hooks:
if x in ['backup']:
self.hookUninstallFile(x, info)
return True
return False
def uninstallOldApi(self):
rundir = mw.getRunDir()
name = request.form.get('name', '')
@@ -147,7 +197,6 @@ class plugins_api:
return mw.returnJson(False, "配置文件不存在!", ())
pluginInfo = json.loads(mw.readFile(infoJsonPos))
execstr = "cd " + os.getcwd() + "/plugins/" + \
name + " && /bin/bash " + pluginInfo["shell"] \
+ " uninstall " + version
@@ -175,13 +224,13 @@ class plugins_api:
return mw.returnJson(False, "配置文件不存在!", ())
pluginInfo = json.loads(mw.readFile(infoJsonPos))
self.hookUninstall(pluginInfo)
execstr = "cd " + os.getcwd() + "/plugins/" + \
name + " && /bin/bash " + pluginInfo["shell"] \
+ " uninstall " + version
data = mw.execShell(execstr)
if mw.isAppleSystem():
if mw.isDebugMode():
print(execstr)
print(data[0], data[1])
self.removeIndex(name, version)
@@ -793,7 +842,7 @@ class plugins_api:
print('getIndexList:', e)
# 使用gevent模式时,无法使用多进程
#plist = self.checkStatusMProcess(plist)
# plist = self.checkStatusMProcess(plist)
plist = self.checkStatusMThreads(plist)
return plist
+40 -25
View File
@@ -340,10 +340,16 @@ class site_api:
name = mw.M('sites').where("id=?", (mid,)).getField('name')
data = {}
data['logs'] = self.getLogsStatus(name)
data['runPath'] = self.getSiteRunPath(mid)
data['userini'] = False
if os.path.exists(path + '/.user.ini'):
data['userini'] = True
data['runPath'] = self.getSiteRunPath(mid)
if data['runPath']['runPath'] != '/':
if os.path.exists(path + data['runPath']['runPath'] + '/.user.ini'):
data['userini'] = True
data['pass'] = self.getHasPwd(name)
data['path'] = path
data['name'] = name
@@ -351,15 +357,18 @@ class site_api:
def setDirUserIniApi(self):
path = request.form.get('path', '')
runPath = request.form.get('runPath', '')
filename = path + '/.user.ini'
self.delUserInI(path)
if os.path.exists(filename):
self.delUserInI(path)
mw.execShell("which chattr && chattr -i " + filename)
os.remove(filename)
return mw.returnJson(True, '已清除防跨站设置!')
mw.writeFile(filename, 'open_basedir=' + path +
'/:/www/server/php:/tmp/:/proc/')
self.setDirUserINI(path, runPath)
mw.execShell("which chattr && chattr +i " + filename)
return mw.returnJson(True, '已打开防跨站设置!')
def logsOpenApi(self):
@@ -497,7 +506,7 @@ class site_api:
certName = request.form.get('certName', '')
siteName = request.form.get('siteName', '')
try:
path = self.sslDir + siteName
path = self.sslDir + siteName.strip()
if not os.path.exists(path):
return mw.returnJson(False, '证书不存在!')
@@ -730,11 +739,11 @@ class site_api:
if conf.find('ssl_certificate') == -1:
return mw.returnJson(False, '当前未开启SSL')
to = """#error_page 404/404.html;
#HTTP_TO_HTTPS_START
# HTTP_TO_HTTPS_START
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
#HTTP_TO_HTTPS_END"""
# HTTP_TO_HTTPS_END"""
conf = conf.replace('#error_page 404/404.html;', to)
mw.writeFile(file, conf)
@@ -1095,6 +1104,7 @@ class site_api:
sitePath = mw.M('sites').where('id=?', (mid,)).getField('path')
newPath = sitePath + runPath
# 处理Nginx
filename = self.getHostConf(siteName)
if os.path.exists(filename):
@@ -1104,8 +1114,7 @@ class site_api:
conf = conf.replace(path, newPath)
mw.writeFile(filename, conf)
self.delUserInI(sitePath)
self.setDirUserINI(newPath)
self.setDirUserINI(sitePath, runPath)
mw.restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -1562,7 +1571,7 @@ class site_api:
# location ~* ^{from}(.*)$ {
tpl = """
# PROXY-START/
#PROXY-START/
location ^~ {from} {
proxy_pass {to};
proxy_set_header Host {host};
@@ -1585,7 +1594,7 @@ location ^~ {from} {
add_header Cache-Control no-cache;
}
}
# PROXY-END/
#PROXY-END/
"""
# replace
@@ -1829,13 +1838,13 @@ location ^~ {from} {
logPath = mw.getLogsDir() + '/' + siteName + '.log'
if not os.path.exists(logPath):
return mw.returnJson(False, '日志为空')
return mw.returnJson(True, mw.getNumLines(logPath, 100))
return mw.returnJson(True, mw.getLastLine(logPath, 100))
def getErrorLogs(self, siteName):
logPath = mw.getLogsDir() + '/' + siteName + '.error.log'
if not os.path.exists(logPath):
return mw.returnJson(False, '日志为空')
return mw.returnJson(True, mw.getNumLines(logPath, 100))
return mw.returnJson(True, mw.getLastLine(logPath, 100))
# 取日志状态
def getLogsStatus(self, siteName):
@@ -2094,12 +2103,16 @@ location ^~ {from} {
return rewriteList
def createRootDir(self, path):
autoInit = False
if not os.path.exists(path):
autoInit = True
os.makedirs(path)
if not mw.isAppleSystem():
mw.execShell('chown -R www:www ' + path)
mw.writeFile(path + '/index.html', 'Work has started!!!')
mw.execShell('chmod -R 755 ' + path)
if autoInit:
mw.writeFile(path + '/index.html', 'Work has started!!!')
mw.execShell('chmod -R 755 ' + path)
def nginxAddDomain(self, webname, domain, port):
file = self.getHostConf(webname)
@@ -2182,19 +2195,16 @@ location ^~ {from} {
return mw.returnJson(False, '您添加的域名已存在!')
mw.M('domain').where('pid=?', (opid,)).delete()
self.createRootDir(self.sitePath)
self.nginxAddConf()
# 添加更多域名
for domain in siteMenu['domainlist']:
sdomain = domain
swebname = self.siteName
spid = str(pid)
self.addDomain(domain, webname, pid)
self.addDomain(domain, self.siteName, pid)
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
self.createRootDir(self.sitePath)
self.nginxAddConf()
data = {}
data['siteStatus'] = False
mw.restartWeb()
@@ -2350,7 +2360,9 @@ location ^~ {from} {
return True
# 设置目录防御
def setDirUserINI(self, newPath):
def setDirUserINI(self, sitePath, runPath):
newPath = sitePath + runPath
filename = newPath + '/.user.ini'
if os.path.exists(filename):
mw.execShell("chattr -i " + filename)
@@ -2358,8 +2370,11 @@ location ^~ {from} {
return mw.returnJson(True, '已清除防跨站设置!')
self.delUserInI(newPath)
mw.writeFile(filename, 'open_basedir=' +
newPath + '/:/www/server/php:/tmp/:/proc/')
openPath = 'open_basedir={}/:{}/'.format(newPath, sitePath)
if runPath == '/':
openPath = 'open_basedir={}/'.format(sitePath)
mw.writeFile(filename, openPath + ':/www/server/php:/tmp/:/proc/')
mw.execShell("chattr +i " + filename)
return mw.returnJson(True, '已打开防跨站设置!')
+52 -40
View File
@@ -162,7 +162,7 @@ class system_api:
except:
port = mw.readFile('data/port.pl')
except:
port = '8888'
port = '7200'
domain = ''
if os.path.exists('data/domain.conf'):
domain = mw.readFile('data/domain.conf')
@@ -201,9 +201,9 @@ class system_api:
def getLoadAverage(self):
c = os.getloadavg()
data = {}
data['one'] = float(c[0])
data['five'] = float(c[1])
data['fifteen'] = float(c[2])
data['one'] = round(float(c[0]), 2)
data['five'] = round(float(c[1]), 2)
data['fifteen'] = round(float(c[2]), 2)
data['max'] = psutil.cpu_count() * 2
data['limit'] = data['max']
data['safe'] = data['max'] * 0.75
@@ -276,8 +276,17 @@ class system_api:
def getCpuInfo(self, interval=1):
# 取CPU信息
cpuCount = psutil.cpu_count()
cpuLogicalNum = psutil.cpu_count(logical=False)
used = psutil.cpu_percent(interval=interval)
return used, cpuCount
if os.path.exists('/proc/cpuinfo'):
c_tmp = mw.readFile('/proc/cpuinfo')
d_tmp = re.findall("physical id.+", c_tmp)
cpuLogicalNum = len(set(d_tmp))
used_all = psutil.cpu_percent(percpu=True)
cpu_name = mw.getCpuType() + " * {}".format(cpuLogicalNum)
return used, cpuCount, used_all, cpu_name, cpuCount, cpuLogicalNum
def getMemInfo(self):
# 取内存信息
@@ -437,12 +446,35 @@ class system_api:
os.system('echo > /tmp/panelBoot.pl')
return total, count
def psutilNetIoCounters(self):
'''
统计网卡流量
'''
stat_pl = 'data/only_netio_counters.pl'
if os.path.exists(stat_pl):
local_lo = (0, 0, 0, 0)
ioName = psutil.net_io_counters(pernic=True).keys()
for x in ioName:
if x.find("lo") > -1:
local_lo = psutil.net_io_counters(
pernic=True).get(x)[:4]
all_io = psutil.net_io_counters()[:4]
result_io = tuple([all_io[i] - local_lo[i]
for i in range(0, len(all_io))])
# print(local_lo)
# print(all_io)
# print(result_io)
return result_io
return psutil.net_io_counters()[:4]
def getNetWork(self):
# return self.GetNetWorkApi(get);
# 取网络流量信息
try:
# 取网络流量信息
networkIo = psutil.net_io_counters()[:4]
networkIo = self.psutilNetIoCounters()
if not "otime" in session:
session['up'] = networkIo[0]
session['down'] = networkIo[1]
@@ -470,38 +502,7 @@ class system_api:
return networkInfo
except Exception as e:
# print(e)
return None
def getNetWorkApi(self):
# 取网络流量信息
try:
tmpfile = 'data/network.temp'
networkIo = psutil.net_io_counters()[:4]
if not os.path.exists(tmpfile):
mw.writeFile(tmpfile, str(
networkIo[0]) + '|' + str(networkIo[1]) + '|' + str(int(time.time())))
lastValue = mw.readFile(tmpfile).split('|')
ntime = time.time()
networkInfo = {}
networkInfo['upTotal'] = networkIo[0]
networkInfo['downTotal'] = networkIo[1]
networkInfo['up'] = round(
float(networkIo[0] - int(lastValue[0])) / 1024 / (ntime - int(lastValue[2])), 2)
networkInfo['down'] = round(
float(networkIo[1] - int(lastValue[1])) / 1024 / (ntime - int(lastValue[2])), 2)
networkInfo['downPackets'] = networkIo[3]
networkInfo['upPackets'] = networkIo[2]
mw.writeFile(tmpfile, str(
networkIo[0]) + '|' + str(networkIo[1]) + '|' + str(int(time.time())))
# networkInfo['cpu'] = self.GetCpuInfo(0.1)
return networkInfo
except:
print("getNetWork error:", e)
return None
def getNetWorkIoData(self, start, end):
@@ -567,14 +568,19 @@ class system_api:
def setControl(self, stype, day):
filename = 'data/control.conf'
stat_pl = 'data/only_netio_counters.pl'
if stype == '0':
mw.execShell("rm -f " + filename)
mw.execShell("rm -rf " + filename)
elif stype == '1':
_day = int(day)
if _day < 1:
return mw.returnJson(False, "设置失败!")
mw.writeFile(filename, day)
elif stype == '2':
mw.execShell("rm -rf " + stat_pl)
elif stype == '3':
mw.execShell("echo 'True' > " + stat_pl)
elif stype == 'del':
if not mw.isRestart():
return mw.returnJson(False, '请等待所有安装任务完成再执行')
@@ -597,6 +603,12 @@ class system_api:
else:
data['day'] = 30
data['status'] = False
if os.path.exists(stat_pl):
data['stat_all_status'] = True
else:
data['stat_all_status'] = False
return mw.getJson(data)
return mw.returnJson(True, "设置成功!")
+3
View File
@@ -68,6 +68,9 @@ class ORM:
def setPort(self, port):
self.__DB_PORT = port
def setUser(self, user):
self.__DB_USER = user
def setPwd(self, pwd):
self.__DB_PASS = pwd
+6
View File
@@ -77,6 +77,12 @@ class ORM:
def getPwd(self):
return self.__DB_PASS
def setDbName(self, name):
self.__DB_NAME = name
def setUser(self, user):
self.__DB_USER = user
def execute(self, sql):
# 执行SQL语句返回受影响行
if not self.__Conn():
+8 -8
View File
@@ -13,7 +13,7 @@ service mw [start|stop|reload|restart|status]
```
sytemctl [start|stop|reload|restart|status] openresty
systemctl [start|stop|reload|restart|status] openresty
```
@@ -21,7 +21,7 @@ sytemctl [start|stop|reload|restart|status] openresty
```
sytemctl [start|stop|reload|restart|status] mysql
systemctl [start|stop|reload|restart|status] mysql
```
@@ -29,7 +29,7 @@ sytemctl [start|stop|reload|restart|status] mysql
```
sytemctl [start|stop|reload|restart|status] mariadb
systemctl [start|stop|reload|restart|status] mariadb
```
@@ -37,16 +37,16 @@ sytemctl [start|stop|reload|restart|status] mariadb
```
sytemctl [start|stop|reload|restart|status] php[54-81]
systemctl [start|stop|reload|restart|status] php[54-81]
sytemctl start php71
systemctl start php71
```
- Redis
```
sytemctl [start|stop|reload|restart|status] redis
systemctl [start|stop|reload|restart|status] redis
```
@@ -54,7 +54,7 @@ sytemctl [start|stop|reload|restart|status] redis
```
sytemctl [start|stop|reload|restart|status] memcached
systemctl [start|stop|reload|restart|status] memcached
```
@@ -63,6 +63,6 @@ sytemctl [start|stop|reload|restart|status] memcached
```
sytemctl [start|stop|reload|restart|status] sphinx
systemctl [start|stop|reload|restart|status] sphinx
```
+3 -4
View File
@@ -46,10 +46,9 @@ CREATE TABLE IF NOT EXISTS `firewall` (
INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES
(1, '80', '网站默认端口', '0000-00-00 00:00:00'),
(2, '7200', 'WEB面板', '0000-00-00 00:00:00'),
(3, '22', 'SSH远程管理服务', '0000-00-00 00:00:00'),
(4, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00'),
(5, '443', 'HTTPS', '0000-00-00 00:00:00');
(2, '22', 'SSH远程管理服务', '0000-00-00 00:00:00'),
(3, '443', 'HTTPS', '0000-00-00 00:00:00'),
(4, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
-86
View File
@@ -1,86 +0,0 @@
#!/www/server/mdserver-web/bin/python
# description: mdserver-web cli tools
# ln -s /www/server/mdserver-web/mw-cli /usr/bin/mw-cli
import os
import sys
def mw_start():
"""
Start mdserver-web
"""
os.system('systemctl start mw')
print("服务已启动")
def mw_stop():
"""
stop mdserver-web
"""
os.system('systemctl stop mw')
print("服务已停止")
def mw_restart():
"""
restart mdserver-web
"""
os.system('systemctl restart mw')
print("服务已重启")
def mw_reset_username():
"""
reset mdserver-web username
"""
from tools import set_panel_username
user_name = input("请输入新的用户名: ")
set_panel_username(user_name)
def mw_reset_pwd():
"""
reset mdserver-web password
"""
from tools import set_panel_pwd
pwd = input("请输入新的密码: ")
set_panel_pwd(pwd, True)
if __name__ == '__main__':
if os.geteuid() != 0:
print("请使用root账户执行该命令.")
sys.exit(1)
os.chdir("/www/server/mdserver-web")
sys.path.append(os.getcwd() + "/class/core")
try:
str = '''
==== mdserver-web cli tools ====
1. 启动服务 2. 停止服务
3. 重启服务 4. 修改用户名
5. 修改密码
=================================
'''
if len(sys.argv) == 2:
sw = sys.argv[1]
else:
print(str)
sw = input("请输入您要进行的操作: ")
if sw == '1':
mw_start()
elif sw == '2':
mw_stop()
elif sw == '3':
mw_restart()
elif sw == '4':
mw_reset_username()
elif sw == '5':
mw_reset_pwd()
else:
print("操作不存在")
except KeyboardInterrupt:
print("\n操作已终止")
+5 -1
View File
@@ -3,6 +3,7 @@
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('clean');">服务</p>
<p onclick="pluginConfig('clean');">配置修改</p>
<p onclick="pluginLogs('clean',null,'run_log');">运行日志</p>
<p onclick="pRead()">说明</p>
</div>
<div class="bt-w-con pd15">
@@ -16,7 +17,10 @@ pluginService('clean');
function pRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/clean/index.py clean</li>';
readme += '<li>启动后,假如到计划中[2:30]执行。</li>';
readme += '<li>【*】代表要删除。</li>';
readme += '<li>添加/删除清除日志,可在`配置修改`中添加/删除。</li>';
readme += '<li>如果是目录,会寻找【.log】后缀的文件清空。</li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
+96 -70
View File
@@ -53,34 +53,95 @@ def getArgs():
return tmp
def getLockFile():
return getServerDir() + "/installed_lock.pl"
def runLog():
return getServerDir() + "/clean.log"
def status():
if os.path.exists(getConf()):
initConf()
if os.path.exists(getLockFile()):
return "start"
return 'stop'
def initConf():
conf = getConf()
if not os.path.exists(conf):
content = ""
clog = [
"/var/log/cron-*",
"/var/log/maillog-*",
"/var/log/secure-*",
"/var/log/spooler-*",
"/var/log/yum.log-*",
"/var/log/messages-*",
"/var/log/btmp-*",
"/var/log/audit/audit.log.*",
"/var/log/rhsm/rhsm.log-*",
"/var/log/rhsm/rhsmcertd.log-*",
"/tmp/yum_save_*",
"/tmp/tmp.*",
]
for i in clog:
content += i + "\n"
# 常用日志
clogcom = [
"/var/log/messages",
"/var/log/btmp",
"/var/log/wtmp",
"/var/log/secure",
"/var/log/lastlog",
"/var/log/cron",
"/www/server/cron"
]
for i in clogcom:
if os.path.exists(i):
content += i + "\n"
# 清理日志
rootDir = "/var/log"
l = os.listdir(rootDir)
for x in range(len(l)):
abspath = rootDir + "/" + l[x]
content += abspath + "\n"
mw.writeFile(conf, content)
def start():
file = initDreplace()
data = mw.execShell(file + ' start')
if data[1] == '':
initConf()
lock_file = getLockFile()
if not os.path.exists(lock_file):
mw.writeFile(lock_file, "")
import tool_task
tool_task.createBgTask()
return 'ok'
return 'fail'
def stop():
file = initDreplace()
data = mw.execShell(file + ' stop')
if data[1] == '':
initConf()
lock_file = getLockFile()
if os.path.exists(lock_file):
os.remove(lock_file)
import tool_task
tool_task.removeBgTask()
return 'ok'
return 'fail'
def reload():
file = initDreplace()
data = mw.execShell(file + ' reload')
if data[1] == '':
return 'ok'
return 'fail'
return 'ok'
def get_filePath_fileName_fileExt(filename):
@@ -93,15 +154,20 @@ def cleanFileLog(path):
filepath, shotname, extension = get_filePath_fileName_fileExt(path)
if extension == ".log":
cmd = "echo \"\" > " + path
tmp = mw.execShell(cmd)
if tmp[1] != "":
cmd += " | error:" + tmp[1].strip()
print(cmd)
print(mw.execShell(cmd))
def cleanSelfFileLog(path):
filepath, shotname, extension = get_filePath_fileName_fileExt(path)
cmd = "echo \"\" > " + path
print(cmd)
print(mw.execShell(cmd))
if extension == ".log":
cmd = "echo \"\" > " + path
tmp = mw.execShell(cmd)
if tmp[1] != "":
cmd += " | error:" + tmp[1].strip()
print(cmd)
def cleanDirLog(path):
@@ -115,70 +181,28 @@ def cleanDirLog(path):
def cleanLog():
# 清理日志
rootDir = "/var/log"
print("clean start")
clog = [
"rm -rf /var/log/cron-*",
"rm -rf /var/log/maillog-*",
"rm -rf /var/log/secure-*",
"rm -rf /var/log/spooler-*",
"rm -rf /var/log/yum.log-*",
"rm -rf /var/log/messages-*",
"rm -rf /var/log/btmp-*",
"rm -rf /var/log/audit/audit.log.*",
"rm -rf /var/log/rhsm/rhsm.log-*",
"rm -rf /var/log/rhsm/rhsmcertd.log-*",
"rm -rf /tmp/yum_save_*",
"rm -rf /tmp/tmp.*",
]
for i in clog:
print(i)
mw.execShell(i)
# 常用日志
clogcom = [
"/var/log/messages",
"/var/log/btmp",
"/var/log/wtmp",
"/var/log/secure",
"/var/log/lastlog",
"/var/log/cron",
]
for i in clogcom:
if os.path.exists(i):
mw.execShell("echo \"\" > " + i)
l = os.listdir(rootDir)
for x in range(len(l)):
abspath = rootDir + "/" + l[x]
if os.path.isfile(abspath):
cleanFileLog(abspath)
if os.path.isdir(abspath):
cleanDirLog(abspath)
print("conf clean")
confFile = getServerDir()
# mw.readFile()
confFile = confFile + "/clean.conf"
clist = mw.readFile(confFile).strip()
conf = getConf()
clist = mw.readFile(conf).strip()
clist = clist.split("\n")
for x in clist:
abspath = x.strip()
if abspath.find('*') > 1:
cmd = 'rm -rf ' + abspath
print(cmd)
data = mw.execShell(cmd)
# print(data)
continue
if os.path.exists(abspath):
if os.path.isfile(abspath):
cleanSelfFileLog(abspath)
continue
if os.path.isdir(abspath):
cleanDirLog(abspath)
print("conf clean end")
print("clean end")
continue
if __name__ == "__main__":
func = sys.argv[1]
@@ -194,6 +218,8 @@ if __name__ == "__main__":
print(reload())
elif func == 'conf':
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'clean':
cleanLog()
else:
+6 -2
View File
@@ -13,20 +13,24 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
Install_app()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/clean
echo "" > $serverPath/clean/clean.conf
cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py start
echo "${VERSION}" > $serverPath/clean/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_app()
{
cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py stop
rm -rf $serverPath/clean
echo "Uninstall_clean" > $install_tmp
}
+156
View File
@@ -0,0 +1,156 @@
# coding:utf-8
import sys
import io
import os
import time
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'clean'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/task_config.json"
return conf
def getConfigData():
try:
return json.loads(mw.readFile(getTaskConf()))
except:
pass
return []
def getConfigTpl():
tpl = {
"name": "",
"task_id": -1,
}
return tpl
def createBgTask():
removeBgTask()
args = {
"period": "day",
"hour": "2",
"minute": "30",
}
createBgTaskByName(getPluginName(), args)
def createBgTaskByName(name, args):
cfg = getConfigTpl()
_name = "[勿删]日志清理[" + name + "]"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
api = crontab_api.crontab_api()
period = args['period']
_hour = ''
_minute = ''
_where1 = ''
_type_day = "day"
if period == 'day':
_type_day = 'day'
_hour = args['hour']
_minute = args['minute']
elif period == 'minute-n':
_type_day = 'minute-n'
_where1 = args['minute-n']
_minute = ''
mw_dir = mw.getRunDir()
cmd = '''
mw_dir=%s
rname=%s
plugin_path=%s
script_path=%s
logs_file=$plugin_path/${rname}.log
''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "python3 $script_path/index.py clean >> $logs_file 2>&1"' + "\n"
cmd += 'cd $mw_dir && python3 $script_path/index.py clean >> $logs_file 2>&1' + "\n"
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
params = {
'name': _name,
'type': _type_day,
'week': "",
'where1': _where1,
'hour': _hour,
'minute': _minute,
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'urladdress': '',
}
task_id = api.add(params)
if task_id > 0:
cfg["task_id"] = task_id
cfg["name"] = name
_dd = getConfigData()
_dd.append(cfg)
mw.writeFile(getTaskConf(), json.dumps(_dd))
def removeBgTask():
cfg_list = getConfigData()
for x in range(len(cfg_list)):
cfg = cfg_list[x]
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
cfg_list[x] = cfg
mw.writeFile(getTaskConf(), '[]')
return True
return False
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
echo `date`
GITADDR="{$GITROOTURL}/{$USERNAME}/{$PROJECT}.git"
GIT_SDIR="{$CODE_DIR}"
GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}"
GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
git config --global credential.helper store
# echo $GIT_PROJECT_DIR
if [ ! -d $GIT_PROJECT_DIR ];then
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
git clone $GITADDR
fi
unset GIT_DIR
cd $GIT_PROJECT_DIR && git pull
# func 2
# cd $GIT_PROJECT_DIR && env -i git pull origin master
#更新的目的地址
WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT}
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
sysName=`uname`
if [ $sysName == 'Darwin' ]; then
USER=$(who | sed -n "2,1p" |awk '{print $1}')
chown -R $USER:staff $WEB_PATH
else
chown -R www:www $WEB_PATH
fi
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
echo `date`
GITADDR="{$GITROOTURL}/{$USERNAME}/{$PROJECT}"
GIT_SDIR="{$CODE_DIR}"
GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}"
GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
# echo $GIT_PROJECT_DIR
if [ ! -d $GIT_PROJECT_DIR ];then
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
git clone $GITADDR
fi
unset GIT_DIR
cd $GIT_PROJECT_DIR && git pull
# func 2
# cd $GIT_PROJECT_DIR && env -i git pull origin master
WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT}
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
sysName=`uname`
if [ $sysName == 'Darwin' ]; then
USER=$(who | sed -n "2,1p" |awk '{print $1}')
chown -R $USER:staff $WEB_PATH
else
chown -R www:www $WEB_PATH
fi
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
sh -x {$PATH}/commit 2>{$PATH}/sh.log
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+24
View File
@@ -0,0 +1,24 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('gitea');">服务</p>
<p onclick="pluginInitD('gitea');">自启动</p>
<!-- <p onclick="pluginConfig('gitea',null, 'init_conf');">启动配置</p> -->
<p onclick="gogsEdit();">手动编辑</p>
<p onclick="pluginConfig('gitea',null, 'conf');">配置文件</p>
<p onclick="gogsSetConfig();">配置修改</p>
<p onclick="giteaUserList();">用户列表</p>
<p onclick="pluginLogs('gitea',null,'run_log');">运行日志</p>
<p onclick="pluginLogs('gitea',null,'post_receive_log');" title="提交post-receive日志">提交日志</p>
<p onclick="giteaRead();">使用说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=gitea&f=js/gitea.js",function(){
pluginService('gitea');
});
</script>
@@ -11,11 +11,10 @@ sys.path.append(os.getcwd() + "/class/core")
import mw
cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
info = mw.execShell(cmd)
p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
sys.path.append(p)
import psutil
# cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
# info = mw.execShell(cmd)
# p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
# sys.path.append(p)
app_debug = False
@@ -24,15 +23,12 @@ if mw.isAppleSystem():
def getPluginName():
return 'gogs'
return 'gitea'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
sys.path.append(getPluginDir() + "/class")
import mysqlDb
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -61,18 +57,28 @@ def getArgs():
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 getInitdConfTpl():
path = getPluginDir() + "/init.d/gogs.tpl"
path = getPluginDir() + "/init.d/gitea.tpl"
return path
def getInitdConf():
path = getServerDir() + "/init.d/gogs"
path = getServerDir() + "/init.d/gitea"
return path
def getConf():
path = getServerDir() + "/custom/conf/app.ini"
if not os.path.exists(path):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
return path
@@ -95,7 +101,7 @@ def getHomeDir():
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return '/Users/' + user
else:
return '/root'
return 'git'
def getRunUser():
@@ -104,7 +110,7 @@ def getRunUser():
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return user
else:
return 'root'
return 'git'
__SR = '''#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
@@ -140,13 +146,16 @@ def initDreplace():
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
conf_bin = getConf()
if not os.path.exists(conf_bin):
mw.execShell('mkdir -p ' + getServerDir() + '/custom/conf')
conf_tpl = getConfTpl()
content = mw.readFile(conf_tpl)
content = contentReplace(content)
mw.writeFile(conf_bin, content)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/gitea.service'
systemServiceTpl = getPluginDir() + '/init.d/gitea.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
log_path = getServerDir() + '/log'
if not os.path.exists(log_path):
@@ -159,9 +168,14 @@ def getRootUrl():
content = mw.readFile(getConf())
rep = 'ROOT_URL\s*=\s*(.*)'
tmp = re.search(rep, content)
if not tmp:
return ''
return tmp.groups()[0]
if tmp:
return tmp.groups()[0]
rep = 'EXTERNAL_URL\s*=\s*(.*)'
tmp = re.search(rep, content)
if tmp:
return tmp.groups()[0]
return ''
def getSshPort():
@@ -192,8 +206,11 @@ def getRootPath():
def getDbConfValue():
content = mw.readFile(getConf())
conf = getConf()
if not os.path.exists(conf):
return {}
content = mw.readFile(conf)
rep_scope = "\[database\](.*?)\["
tmp = re.findall(rep_scope, content, re.S)
@@ -207,18 +224,72 @@ def getDbConfValue():
return r
def pMysqlDb():
conf = getDbConfValue()
def pMysqlDb(conf):
host = conf['HOST'].split(':')
conn = mysqlDb.mysqlDb()
# pymysql
db = mw.getMyORM()
# MySQLdb |
# db = mw.getMyORMDb()
conn.setHost(host[0])
conn.setUser(conf['USER'])
conn.setPwd(conf['PASSWD'])
conn.setPort(int(host[1]))
conn.setDb(conf['NAME'])
return conn
db.setPort(int(host[1]))
db.setUser(conf['USER'])
if 'PASSWD' in conf:
db.setPwd(conf['PASSWD'])
else:
db.setPwd(conf['PASSWORD'])
db.setDbName(conf['NAME'])
# db.setSocket(getSocketFile())
db.setCharset("utf8")
return db
def pSqliteDb(conf):
# print(conf)
import db
psDb = db.Sql()
# 默认
gsdir = getServerDir() + '/data'
dbname = 'gitea'
if conf['PATH'][0] == '/':
# 绝对路径
pass
else:
path = conf['PATH'].split('/')
gsdir = getServerDir() + '/' + path[0]
dbname = path[1].split('.')[0]
# print(gsdir, dbname)
psDb.dbPos(gsdir, dbname)
return psDb
def getGiteaDbType(conf):
if 'DB_TYPE' in conf:
return conf['DB_TYPE']
if 'TYPE' in conf:
return conf['TYPE']
return 'NONE'
def pQuery(sql):
conf = getDbConfValue()
gtype = getGiteaDbType(conf)
if gtype == 'sqlite3':
db = pSqliteDb(conf)
data = db.query(sql, []).fetchall()
return data
elif gtype == 'mysql':
db = pMysqlDb(conf)
return db.query(sql)
print("仅支持mysql|sqlite3配置")
exit(0)
def isSqlError(mysqlMsg):
@@ -244,93 +315,66 @@ def isSqlError(mysqlMsg):
return mw.returnData(True, 'OK')
def start():
is_frist = True
conf_bin = getConf()
if os.path.exists(conf_bin):
is_frist = False
def appOp(method):
file = initDreplace()
if is_frist:
return "第一次启动Gogs,默认使用MySQL连接!<br>可以在配置文件中重新设置,再启动!"
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return 'fail'
conn = pMysqlDb()
list_table = conn.query('show tables')
data = isSqlError(list_table)
if not data['status']:
return data['msg']
data = mw.execShell(__SR + file + ' start')
data = mw.execShell(__SR + file + ' ' + method)
if data[1] == '':
return 'ok'
return data[0]
def start():
return appOp('start')
def stop():
file = initDreplace()
data = mw.execShell(__SR + file + ' stop')
if data[1] == '':
return 'ok'
return data[1]
return appOp('stop')
def restart():
file = initDreplace()
data = mw.execShell(__SR + file + ' restart')
if data[1] == '':
return 'ok'
return data[1]
return appOp('restart')
def reload():
file = initDreplace()
data = mw.execShell(__SR + file + ' reload')
if data[1] == '':
return 'ok'
return data[1]
return appOp('reload')
def initdStatus():
if not app_debug:
os_name = mw.getOs()
if os_name == 'darwin':
return "Apple Computer does not support"
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
return 'fail'
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status gitea | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
import shutil
if not app_debug:
os_name = mw.getOs()
if os_name == 'darwin':
return "Apple Computer does not support"
if mw.isAppleSystem():
return "Apple Computer does not support"
mem_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(mem_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('chkconfig --add ' + getPluginName())
mw.execShell('systemctl enable gitea')
return 'ok'
def initdUinstall():
if not app_debug:
os_name = mw.getOs()
if os_name == 'darwin':
return "Apple Computer does not support"
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('chkconfig --del ' + getPluginName())
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable gitea')
return 'ok'
def runLog():
log_path = getServerDir() + '/log/gogs.log'
log_path = getServerDir() + '/log/gitea.log'
return log_path
@@ -340,6 +384,10 @@ def postReceiveLog():
def getGogsConf():
conf = getConf()
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
gets = [
{'name': 'DOMAIN', 'type': -1, 'ps': '服务器域名'},
{'name': 'ROOT_URL', 'type': -1, 'ps': '公开的完整URL路径'},
@@ -360,7 +408,7 @@ def getGogsConf():
{'name': 'SHOW_FOOTER_VERSION', 'type': 2, 'ps': 'Gogs版本信息'},
{'name': 'SHOW_FOOTER_TEMPLATE_LOAD_TIME', 'type': 2, 'ps': 'Gogs模板加载时间'},
]
conf = mw.readFile(getConf())
conf = mw.readFile(conf)
result = []
for g in gets:
@@ -370,7 +418,7 @@ def getGogsConf():
continue
g['value'] = tmp.groups()[0]
result.append(g)
return mw.getJson(result)
return mw.returnJson(True, 'OK', result)
def submitGogsConf():
@@ -402,18 +450,27 @@ def submitGogsConf():
def userList():
conf = getConf()
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
conf = getDbConfValue()
gtype = getGiteaDbType(conf)
if gtype != 'mysql':
return mw.returnJson(False, "仅支持mysql数据操作!")
import math
args = getArgs()
page = 1
page_size = 10
data = checkArgs(args, ['page', 'page_size'])
if not data[0]:
return data[1]
page = int(args['page'])
page_size = int(args['page_size'])
tojs = args['tojs']
search = ''
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'search' in args:
search = args['search']
@@ -421,17 +478,14 @@ def userList():
data['root_url'] = getRootUrl()
pm = pMysqlDb()
start = (page - 1) * page_size
list_count = pm.query('select count(id) as num from user')
count = list_count[0][0]
list_count = pQuery('select count(id) as num from user')
list_data = pm.query(
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size))
page_info = {'count': count, 'p': page,
'row': page_size, 'tojs': 'gogsUserList'}
data['list'] = mw.getPage(page_info)
data['list'] = mw.getPage(
{'count': count, 'p': page, 'row': page_size, 'tojs': tojs})
data['page'] = page
data['page_size'] = page_size
data['page_count'] = int(math.ceil(count / page_size))
@@ -556,8 +610,8 @@ def projectScriptLoad():
cc_content = mw.readFile(commit_tpl)
sshUrl = 'http://127.0.0.1:' + getHttpPort()
cc_content = cc_content.replace('{$GITROOTURL}', sshUrl)
gitPath = getRootPath()
cc_content = cc_content.replace('{$GITROOTURL}', gitPath)
cc_content = cc_content.replace('{$CODE_DIR}', codeDir)
cc_content = cc_content.replace('{$USERNAME}', user)
cc_content = cc_content.replace('{$PROJECT}', args['name'])
@@ -570,11 +624,9 @@ def projectScriptLoad():
def projectScriptUnload():
args = getArgs()
if not 'user' in args:
return mw.returnJson(True, 'username missing')
if not 'name' in args:
return mw.returnJson(True, 'project name missing')
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
@@ -591,11 +643,10 @@ def projectScriptUnload():
def projectScriptDebug():
args = getArgs()
if not 'user' in args:
return mw.returnJson(True, 'username missing')
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
if not 'name' in args:
return mw.returnJson(True, 'project name missing')
user = args['user']
name = args['name'] + '.git'
commit_log = getRootPath() + '/' + user + '/' + name + \
@@ -634,14 +685,8 @@ def getTotalStatistics():
st = status()
data = {}
if st.strip() == 'start':
pm = pMysqlDb()
list_count = pm.query('select count(id) as num from repository')
if list_count.find("error") > -1:
data['status'] = False
data['count'] = 0
return mw.returnJson(False, 'fail', data)
list_count = pQuery('select count(id) as num from repository')
count = list_count[0]["num"]
data['status'] = True
data['count'] = count
data['ver'] = mw.readFile(getServerDir() + '/version.pl').strip()
+16
View File
@@ -0,0 +1,16 @@
{
"ps": "Gitea 是一个开源社区驱动的轻量级代码托管解决方案。",
"name": "gitea",
"title": "Gitea",
"versions": ["1.17.2"],
"tip": "soft",
"checks": "server/gitea",
"path":"server/gitea",
"author": "gitea",
"date": "2022-10-03",
"home": "https://dl.gitea.io/",
"type": "Git服务器",
"shell": "install.sh",
"pid": "3",
"sort": 7
}
+20
View File
@@ -0,0 +1,20 @@
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
[Service]
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory={$SERVER_PATH}/gitea
ExecStart={$SERVER_PATH}/gitea/gitea web
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
RemainAfterExit=yes
#AmbientCapabilities=CAP_NET_BIND_SERVICE
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
+110
View File
@@ -0,0 +1,110 @@
#!/bin/sh
#
# /etc/rc.d/init.d/Gitea
#
# Runs the Gogs
#
#
# chkconfig: - 85 15
#
### BEGIN INIT INFO
# Provides: Gitea
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: mysql postgresql
# Should-Stop: mysql postgresql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start Gitea at boot time.
# Description: Control Gitea.
### END INIT INFO
# Source function library.
if [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
fi
if [ -f /etc/rc.d/init.d/functions ];then
. /etc/rc.d/init.d/functions
fi
# Default values
export HOME={$HOME_DIR}
export USER={$RUN_USER}
NAME=gitea
GOGS_HOME={$SERVER_PATH}/gitea
GOGS_PATH=${GOGS_HOME}/$NAME
GOGS_USER={$RUN_USER}
SERVICENAME="gitea"
LOCKFILE=/tmp/gitea.lock
LOGPATH=${GOGS_HOME}/log
LOGFILE=${LOGPATH}/gitea.log
RETVAL=0
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
DAEMON_OPTS="--check $NAME"
[ ! -z "$GOGS_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${GOGS_USER}"
status(){
isStart=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "${SERVICENAME} not running"
else
echo -e "${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
start() {
isStart=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'`
if [ "$isStart" != '' ];then
echo "${SERVICENAME}(pid $(echo $isStart)) already running"
return $RETVAL
fi
cd ${GOGS_HOME}
echo -e "Starting ${SERVICENAME}: \c"
${GOGS_PATH} web > ${LOGFILE} 2>&1 &
RETVAL=$?
[ $RETVAL = 0 ] && touch ${LOCKFILE} && echo -e "\033[32mdone\033[0m"
return $RETVAL
}
stop() {
pids=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'`
arr=($pids)
echo -e "Stopping gitea... \c"
for p in ${arr[@]}
do
kill -9 $p
done
echo -e "\033[32mdone\033[0m"
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
reload)
stop
start
;;
*)
echo "Usage: ${NAME} {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL
+111
View File
@@ -0,0 +1,111 @@
#!/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
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
URL_DOWNLOAD=https://dl.gitea.io/
getOs(){
os=`uname`
if [ "Darwin" == "$os" ];then
echo 'darwin'
else
echo 'linux'
fi
return 0
}
getBit(){
echo `getconf LONG_BIT`
}
Install_App()
{
mkdir -p $serverPath/source/gitea
if id git &> /dev/null ;then
echo "git UID is `id -u git`"
echo "git Shell is `grep "^git:" /etc/passwd |cut -d':' -f7 `"
else
groupadd git
useradd -g git git
fi
echo '正在安装脚本文件...' > $install_tmp
version=$1
os=`getOs`
git config --global push.default simple
if [ "darwin" == "$os" ];then
file=gitea-${version}-darwin-10.12-amd64
else
file=gitea-${version}-linux-amd64
fi
file_xz="${file}.xz"
echo "wget -O $serverPath/source/gitea/$file_xz ${URL_DOWNLOAD}/gitea/${version}/${file_xz}"
if [ ! -f $serverPath/source/gitea/$file_xz ];then
wget -O $serverPath/source/gitea/$file_xz ${URL_DOWNLOAD}/gitea/${version}/${file_xz}
fi
cd $serverPath/source/gitea && xz -k -d $file_xz
if [ -f $file ];then
mkdir -p $serverPath/gitea
mv $serverPath/source/gitea/$file $serverPath/gitea/gitea
chmod +x $serverPath/gitea/gitea
chown -R git:git $serverPath/gitea
fi
if [ -d $serverPath/gitea ];then
echo $version > $serverPath/gitea/version.pl
cd ${rootPath} && python3 plugins/gitea/index.py start
cd ${rootPath} && python3 plugins/gitea/index.py initd_install
fi
echo 'install success' > $install_tmp
}
Uninstall_App()
{
if [ -f /usr/lib/systemd/system/gitea.service ];then
systemctl stop gitea
systemctl disable gitea
rm -rf /usr/lib/systemd/system/gitea.service
systemctl daemon-reload
fi
if [ -f $serverPath/gitea/initd/gitea ];then
$serverPath/gitea/initd/gitea stop
fi
rm -rf $serverPath/gitea
echo 'uninstall success' > $install_tmp
}
action=$1
version=$2
if [ "${1}" == 'install' ];then
Install_App $version
else
Uninstall_App $version
fi
+353
View File
@@ -0,0 +1,353 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function gogsPost(method,args,callback, title){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(str2Obj(args));
} else {
_args = JSON.stringify(args);
}
var _title = '正在获取...';
if (typeof(title) != 'undefined'){
_title = title;
}
var loadT = layer.msg(_title, { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'gitea', func:method, args:_args}, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function gogsSetConfig(){
gogsPost('get_gogs_conf', '', function(data){
var rrdata = $.parseJSON(data.data);
if (!rrdata.status){
layer.msg(rrdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var rdata = rrdata.data;
var mlist = '';
for (var i = 0; i < rdata.length; i++) {
var w = '140';
if (rdata[i].name == 'error_reporting') w = '250';
var ibody = '<input style="width: ' + w + 'px;" class="bt-input-text mr5" name="' + rdata[i].name + '" value="' + rdata[i].value + '" type="text" >';
switch (rdata[i].type) {
case 0:
var selected_1 = (rdata[i].value == 1) ? 'selected' : '';
var selected_0 = (rdata[i].value == 0) ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
<option value="1" ' + selected_1 + '>开启</option>\
<option value="0" ' + selected_0 + '>关闭</option>\
</select>';
break;
case 1:
var selected_1 = (rdata[i].value == 'On') ? 'selected' : '';
var selected_0 = (rdata[i].value == 'Off') ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
<option value="On" ' + selected_1 + '>开启</option>\
<option value="Off" ' + selected_0 + '>关闭</option></select>'
break;
case 2:
var selected_1 = (rdata[i].value == 'true') ? 'selected' : '';
var selected_0 = (rdata[i].value == 'false') ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
<option value="true" ' + selected_1 + '>开启</option>\
<option value="false" ' + selected_0 + '>关闭</option></select>'
break;
}
mlist += '<p><span>' + rdata[i].name + '</span>' + ibody + ', <font>' + rdata[i].ps + '</font></p>'
}
var html = '<style>.conf_p p{margin-bottom: 2px}</style><div class="conf_p" style="margin-bottom:0">\
' + mlist + '\
<div style="margin-top:10px; padding-right:15px" class="text-right">\
<button class="btn btn-success btn-sm mr5" onclick="gogsSetConfig()">刷新</button>\
<button class="btn btn-success btn-sm" onclick="submitGogsConf()">保存</button></div>\
</div>';
$(".soft-man-con").html(html);
});
}
//提交PHP配置
function submitGogsConf() {
var data = {
DOMAIN: $("input[name='DOMAIN']").val(),
ROOT_URL: $("input[name='ROOT_URL']").val(),
HTTP_ADDR: $("select[name='HTTP_ADDR']").val(),
HTTP_PORT: $("input[name='HTTP_PORT']").val(),
START_SSH_SERVER: $("select[name='START_SSH_SERVER']").val() || 'false',
SSH_PORT: $("input[name='SSH_PORT']").val(),
REQUIRE_SIGNIN_VIEW: $("select[name='REQUIRE_SIGNIN_VIEW']").val() || 'false',
ENABLE_CAPTCHA: $("select[name='ENABLE_CAPTCHA']").val() || 'true',
DISABLE_REGISTRATION: $("select[name='DISABLE_REGISTRATION']").val() || 'false',
ENABLE_NOTIFY_MAIL: $("select[name='ENABLE_NOTIFY_MAIL']").val() || 'false',
FORCE_PRIVATE: $("select[name='FORCE_PRIVATE']").val() || 'false',
SHOW_FOOTER_BRANDING: $("select[name='SHOW_FOOTER_BRANDING']").val() || 'false',
SHOW_FOOTER_VERSION: $("select[name='SHOW_FOOTER_VERSION']").val() || 'false',
SHOW_FOOTER_TEMPLATE_LOAD_TIME: $("select[name='SHOW_FOOTER_TEMPLATE_LOAD_TIME']").val() || 'false',
};
gogsPost('submit_gogs_conf', data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
gogsSetConfig();
});
}
function gogsEdit(){
gogsPost('gogs_edit',{} , function(data){
// console.log(data);
var rdata = $.parseJSON(data.data);
var edit = '<p class="status">通用的手动编辑:</p>';
edit +='<div class="sfm-opt">\
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['post_receive']+'\');">post-receive.tpl</button>\
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['commit']+'\');">commit.tpl</button>\
</div>';
$(".soft-man-con").html(edit);
});
}
function giteaUserList(page, search) {
var _data = {};
if (typeof(page) =='undefined'){
var page = 1;
}
_data['page'] = page;
_data['page_size'] = 10;
if(typeof(search) != 'undefined'){
_data['search'] = search;
}
_data['tojs'] = 'giteaUserList';
gogsPost('user_list', _data, function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找用户名" id="find_user" style="height: 28px; border-radius: 3px;width: 435px;">';
content += '<button class="btn btn-success btn-sm" onclick="userFind();">查找</button></div>';
content += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
content += '<thead><tr>';
content += '<th>序号</th>';
content += '<th>用户或组织</th>';
content += '<th>邮件地址</th>';
content += '<th>操作(<a href="'+rdata['data']['root_url']+'" class="btlink" target="_blank">WEB管理</a>)</th>';
content += '</tr></thead>';
content += '<tbody>';
ulist = rdata['data']['data'];
for (i in ulist){
email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
content += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td>'+ulist[i]["name"]+'</td>'+
'<td>'+email+'</td>'+
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i]["name"]+'\')">项目管理</a></td>'+
'</tr>';
}
content += '</tbody>';
content += '</table></div>';
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
content += page;
$(".soft-man-con").html(content);
});
}
function userProjectList(user, search){
var req = {};
if (!isNaN(user)){
req['page'] = user;
req['name'] = user = getCookie('gogsUserSelected');
} else {
req['page'] = 1;
req['name'] = user;
setCookie('gogsUserSelected', user);
}
req['page_size'] = 5;
req['search'] = '';
if(typeof(search) != 'undefined'){
req['search'] = search;
}
$('.layui-layer-close1').click();
gogsPost('user_project_list', req, function(data){
var rdata = [];
try {
rdata = $.parseJSON(data.data);
} catch(e){}
if (!rdata['status']){
layer.msg(rdata['msg'], { icon: 2 });
return;
}
var list = '';
// console.log(rdata);
var project_list = rdata['data']['data'];
for (i in project_list) {
var name = project_list[i]['name'];
list += '<tr><td>'+name+'</td>\
<td>\
<a class="btlink" target="_blank" href="'+rdata['data']['root_url']+user+'/'+name+'">源码</a> | \
<a class="btlink" onclick="projectScript(\''+user+'\',\''+name+'\','+project_list[i]['has_hook']+');">脚本</a>\
</td>\
</tr>';
}
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
var loadOpen = layer.open({
type: 1,
title: '用户('+user+')项目列表',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div>\
<div class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th>项目</th><th>操作</th></tr></thead>\
<tbody>" + list + "</tbody>\
</table>" +
page +
"</div></div></div>"
});
});
}
function projectScript(user, name,has_hook){
// console.log(user,name,has_hook);
var html = '';
if (has_hook){
html += '<button onclick="projectScriptEdit(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">手动编辑</button>';
html += '<button onclick="projectScriptDebug(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">调试日志</button>';
html += '<button onclick="projectScriptLoad(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">重新加载</button>';
html += '<button onclick="projectScriptUnload(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">卸载脚本</button>';
} else {
html += '<button onclick="projectScriptLoad(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">加载脚本</button>';
}
var loadOpen = layer.open({
type: 1,
title: '['+user+']['+name+']脚本设置',
area: '240px',
content:'<div class="change-default pd20">'+html+'</div>'
});
}
function projectScriptEdit(user,name){
gogsPost('project_script_edit', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['data']['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
}
function projectScriptLoad(user,name){
gogsPost('project_script_load', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
userProjectList(1);
}, 2000);
});
}
function projectScriptUnload(user,name){
gogsPost('project_script_unload', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
userProjectList(1);
}, 2000);
});
}
function projectScriptDebug(user,name){
gogsPost('project_script_debug', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
}
function getRsaPublic(){
gogsPost('get_rsa_public', {}, function(data){
var rdata = $.parseJSON(data.data);
var con = '<div class="tab-con">\
<div class="myKeyCon ptb15">\
<textarea style="margin:0px;width:580px;height:110px;outline:none;" spellcheck="false">'+rdata.mw+'</textarea>\
</div>\
<ul class="help-info-text c7 pull-left"></ul>\
</div>'
layer.open({
type: 1,
area: "600px",
title: '本机公钥',
closeBtn: 2,
shift: 5,
shadeClose: false,
content:con
});
});
}
function giteaRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>默认使用MySQL,第一个启动加载各种配置,并修改成正确的数据库配置</li>';
readme += '<li>邮件端口使用456,gogs仅支持使用STARTTLS的SMTP协议</li>';
readme += '<li>如果使用项目中脚本本地同步,<a target="_blank" href="https://github.com/midoks/mdserver-web/wiki/%E6%8F%92%E4%BB%B6%E7%AE%A1%E7%90%86%5Bgogs%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%5D#%E5%90%AF%E5%8A%A8gogs%E5%90%8E%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BD%BF%E7%94%A8hook%E8%84%9A%E6%9C%AC%E5%90%8C%E6%AD%A5%E4%BB%A3%E7%A0%81%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AFssh%E7%AB%AF%E5%8F%A3">点击查看</></li>';
readme += '<li><a href="#" onclick="getRsaPublic();">点击查看本机公钥</></li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
}
-91
View File
@@ -1,91 +0,0 @@
# coding: utf-8
import re
import os
import sys
# sys.path.append("/usr/local/lib/python3.6/site-packages")
class mysqlDb:
__DB_PASS = None
__DB_USER = 'root'
__DB_PORT = 3306
__DB_HOST = 'localhost'
__DB_NAME = 'test'
__DB_CONN = None
__DB_CUR = None
__DB_ERR = None
__DB_CNF = '/etc/my.cnf'
def __Conn(self):
'''连接MYSQL数据库'''
try:
socket = '/www/server/mysql/mysql.sock'
try:
import MySQLdb
except Exception as ex:
self.__DB_ERR = ex
return False
try:
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
port=self.__DB_PORT, db=self.__DB_NAME, charset="utf8", connect_timeout=10, unix_socket=socket)
except MySQLdb.Error as e:
self.__DB_HOST = '127.0.0.1'
self.__DB_CONN = MySQLdb.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
port=self.__DB_PORT, db=self.__DB_NAME, charset="utf8", connect_timeout=10, unix_socket=socket)
self.__DB_CUR = self.__DB_CONN.cursor()
return True
except MySQLdb.Error as e:
self.__DB_ERR = e
return False
def setHost(self, host):
self.__DB_HOST = host
def setPwd(self, pwd):
self.__DB_PASS = pwd
def setUser(self, user):
self.__DB_USER = user
def setPort(self, port):
self.__DB_PORT = port
def setDb(self, name):
self.__DB_NAME = name
def getPwd(self):
return self.__DB_PASS
def execute(self, sql):
# 执行SQL语句返回受影响行
if not self.__Conn():
return self.__DB_ERR
try:
result = self.__DB_CUR.execute(sql)
self.__DB_CONN.commit()
self.__Close()
return result
except Exception as ex:
return ex
def query(self, sql):
# 执行SQL语句返回数据集
if not self.__Conn():
return self.__DB_ERR
try:
self.__DB_CUR.execute(sql)
result = self.__DB_CUR.fetchall()
# 将元组转换成列表
# data = map(list, result)
self.__Close()
return result
except Exception as ex:
return "error: " + str(ex)
# 关闭连接
def __Close(self):
self.__DB_CUR.close()
self.__DB_CONN.close()
+23 -18
View File
@@ -31,9 +31,6 @@ def getPluginName():
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
sys.path.append(getPluginDir() + "/class")
import mysqlDb
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -235,16 +232,24 @@ def getDbConfValue():
def pMysqlDb(conf):
host = conf['HOST'].split(':')
conn = mysqlDb.mysqlDb()
# pymysql
db = mw.getMyORM()
# MySQLdb |
# db = mw.getMyORMDb()
conn.setHost(host[0])
conn.setUser(conf['USER'])
conn.setPwd(conf['PASSWD'])
conn.setPort(int(host[1]))
conn.setDb(conf['NAME'])
return conn
db.setPort(int(host[1]))
db.setUser(conf['USER'])
if 'PASSWD' in conf:
db.setPwd(conf['PASSWD'])
else:
db.setPwd(conf['PASSWORD'])
db.setDbName(conf['NAME'])
# db.setSocket(getSocketFile())
db.setCharset("utf8")
return db
def pSqliteDb(conf):
@@ -457,6 +462,11 @@ def userList():
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
conf = getDbConfValue()
gtype = getGogsDbType(conf)
if gtype != 'mysql':
return mw.returnJson(False, "仅支持mysql数据操作!")
import math
args = getArgs()
@@ -476,7 +486,7 @@ def userList():
start = (page - 1) * page_size
list_count = pQuery('select count(id) as num from user')
count = list_count[0][0]
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size))
data['list'] = mw.getPage({'count': count, 'p': page,
@@ -681,12 +691,7 @@ def getTotalStatistics():
data = {}
if st.strip() == 'start':
list_count = pQuery('select count(id) as num from repository')
if list_count.find("error") > -1:
data['status'] = False
data['count'] = 0
return mw.returnJson(False, 'fail', data)
count = list_count[0]["num"]
data['status'] = True
data['count'] = count
data['ver'] = mw.readFile(getServerDir() + '/version.pl').strip()
+1
View File
@@ -29,6 +29,7 @@ getBit(){
Install_gogs()
{
mkdir -p $serverPath/source/gogs
echo '正在安装脚本文件...' > $install_tmp
+4 -4
View File
@@ -163,11 +163,11 @@ function gogsUserList(page, search) {
ulist = rdata['data']['data'];
for (i in ulist){
email = ulist[i][2] == '' ? '无' : ulist[i][2];
content += '<tr><td>'+ulist[i][0]+'</td>'+
'<td>'+ulist[i][1]+'</td>'+
email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
content += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td>'+ulist[i]["name"]+'</td>'+
'<td>'+email+'</td>'+
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i][1]+'\')">项目管理</a></td>'+
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i]["name"]+'\')">项目管理</a></td>'+
'</tr>';
}
+37
View File
@@ -0,0 +1,37 @@
global
daemon
log 127.0.0.1 local0
pidfile /tmp/haproxy.pid
maxconn 4000
user haproxy
group haproxy
defaults
mode http
log global
option httplog
timeout connect 10s
timeout client 15s
timeout server 15s
listen stats
mode http
bind *:10800
stats enable
stats uri /haproxy
stats realm Haproxy\ Statistics
stats auth admin:admin
frontend http-in
bind *:1080
default_backend servers
option forwardfor
option httpclose
backend servers
balance roundrobin
server web1 0.0.0.0:9090 check
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

+18
View File
@@ -0,0 +1,18 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('haproxy');">服务</p>
<p onclick="pluginInitD('haproxy');">自启动</p>
<p onclick="pluginConfigTpl('haproxy');">配置修改</p>
<p onclick="pluginLogs('haproxy','','run_log',30);">运行日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=haproxy&f=js/haproxy.js", function(){
pluginService('haproxy');
});
</script>
+253
View File
@@ -0,0 +1,253 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import string
import subprocess
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'haproxy'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getConfTpl():
path = getPluginDir() + "/conf/haproxy.conf"
return path
def getConf():
path = getServerDir() + "/haproxy.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('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def 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 configTpl():
path = getPluginDir() + '/tpl'
pathFile = os.listdir(path)
tmp = []
for one in pathFile:
file = path + '/' + one
tmp.append(file)
return mw.getJson(tmp)
def readConfigTpl():
args = getArgs()
data = checkArgs(args, ['file'])
if not data[0]:
return data[1]
content = mw.readFile(args['file'])
content = contentReplace(content)
return mw.returnJson(True, 'ok', content)
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$SERVER_APP}', service_path + '/haproxy')
return content
def status():
data = mw.execShell(
"ps -ef|grep haproxy |grep -v grep | grep -v python | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/' + getPluginName()
# initd replace
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = contentReplace(content)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# config replace
conf_bin = getConf()
if not os.path.exists(conf_bin):
conf_content = mw.readFile(getConfTpl())
conf_content = contentReplace(conf_content)
mw.writeFile(getServerDir() + '/haproxy.conf', conf_content)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/haproxy.service'
systemServiceTpl = getPluginDir() + '/init.d/haproxy.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def haOp(method):
file = initDreplace()
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' haproxy')
if data[1] == '':
return 'ok'
return 'fail'
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
def start():
return haOp('start')
def stop():
return haOp('stop')
def restart():
return haOp('restart')
def reload():
return haOp('reload')
def initdStatus():
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status haproxy | 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 haproxy')
return 'ok'
def initdUinstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable haproxy')
return 'ok'
def runLog():
path = getConf()
content = mw.readFile(path)
rep = 'log\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
def getPort():
path = getConf()
content = mw.readFile(path)
rep = 'listen\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'conf':
print(getConf())
elif func == 'config_tpl':
print(configTpl())
elif func == 'read_config_tpl':
print(readConfigTpl())
elif func == 'run_log':
print(runLog())
elif func == 'query_log':
print(queryLog())
else:
print('error')
+19
View File
@@ -0,0 +1,19 @@
{
"sort": 7,
"ps": "可靠、高性能的TCP/HTTP负载平衡器",
"name": "haproxy",
"title": "haproxy",
"shell": "install.sh",
"versions":["2.6"],
"updates":["2.6"],
"tip": "soft",
"checks": "server/haproxy",
"path": "server/haproxy",
"display": 1,
"author": "midoks",
"date": "2022-08-26",
"home": "https://www.haproxy.org/",
"doc1": "https://www.haproxy.org/",
"type": 0,
"pid": "4"
}
@@ -0,0 +1,13 @@
[Unit]
Description=he Reliable, High Performance TCP/HTTP Load Balancer
After=network.target
[Service]
Type=forking
ExecStartPre={$SERVER_PATH}/haproxy/sbin/haproxy -c -f {$SERVER_PATH}/haproxy/haproxy.conf
ExecStart={$SERVER_PATH}/haproxy/sbin/haproxy -D -f {$SERVER_PATH}/haproxy/haproxy.conf
ExecReload={$SERVER_PATH}/haproxy/sbin/haproxy -f {$SERVER_PATH}/haproxy/haproxy.conf -c -q
Restart=on-failure
[Install]
WantedBy=multi-user.target
+119
View File
@@ -0,0 +1,119 @@
#!/bin/sh
#
# chkconfig: - 85 15
# description: HA-Proxy is a TCP/HTTP reverse proxy which is particularly suited \
# for high availability environments.
# processname: haproxy
# config: /etc/haproxy/haproxy.cfg
# pidfile: /var/run/haproxy.pid
# Script Author: Simon Matter <simon.matter@invoca.ch>
# Version: 2004060600
# Source function library.
if [ -f /etc/init.d/functions ]; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
echo ".."
fi
# Source networking configuration.
if [ -f /etc/sysconfig/network ];then
. /etc/sysconfig/network
fi
# Check that networking is up.
# [ ${NETWORKING} = "no" ] && exit 0
HAPROXYDIR={$SERVER_PATH}/haproxy
BASENAME=haproxy
# This is our service name
#BASENAME=`basename $0`
#if [ -L $0 ]; then
# BASENAME=`find $0 -name $BASENAME -printf %l`
# BASENAME=`basename $BASENAME`
#fi
[ -f $HAPROXYDIR/etc/$BASENAME.conf ] || exit 1
RETVAL=0
start() {
$HAPROXYDIR/sbin/$BASENAME -c -q -f $HAPROXYDIR/etc/$BASENAME.conf
if [ $? -ne 0 ]; then
echo "Errors found in configuration file, check it with '$BASENAME check'."
return 1
fi
echo -n "Starting $BASENAME: "
daemon $HAPROXYDIR/sbin/$BASENAME -D -f $HAPROXYDIR/etc/$BASENAME.conf
RETVAL=$?
# echo
# [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$BASENAME
return $RETVAL
}
stop() {
echo -n "Shutting down $BASENAME: "
killproc $BASENAME -USR1
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$BASENAME
[ $RETVAL -eq 0 ] && rm -f /var/run/$BASENAME.pid
return $RETVAL
}
restart() {
$HAPROXYDIR/sbin/$BASENAME -c -q -f $HAPROXYDIR/etc/$BASENAME.conf
if [ $? -ne 0 ]; then
echo "Errors found in configuration file, check it with '$BASENAME check'."
return 1
fi
stop
start
}
reload() {
$HAPROXYDIR/sbin/$BASENAME -c -q -f $HAPROXYDIR/etc/$BASENAME.conf
if [ $? -ne 0 ]; then
echo "Errors found in configuration file, check it with '$BASENAME check'."
return 1
fi
$HAPROXYDIR/sbin/$BASENAME -D -f $HAPROXYDIR/$BASENAME.conf -p /var/run/$BASENAME.pid -sf $(cat /var/run/$BASENAME.pid)
}
check() {
$HAPROXYDIR/sbin/$BASENAME -c -q -V -f $HAPROXYDIR/etc/$BASENAME.conf
}
rhstatus() {
status $BASENAME
}
condrestart() {
[ -e /var/lock/subsys/$BASENAME ] && restart || :
}
# See how we were called.
case "$1" in
start) start ;;
stop) stop ;;
restart) restart;;
reload) reload;;
condrestart) condrestart ;;
status) rhstatus ;;
check) check ;;
*)
echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|check}"
exit 1
esac
exit $?
+52
View File
@@ -0,0 +1,52 @@
#!/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
echo $action $type
if id haproxy &> /dev/null ;then
echo "haproxy UID is `id -u haproxy`"
echo "haproxy Shell is `grep "^haproxy:" /etc/passwd |cut -d':' -f7 `"
else
groupadd haproxy
useradd -g haproxy haproxy
fi
if [ "${2}" == "" ];then
echo '缺少安装脚本...' > $install_tmp
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
echo '缺少安装脚本2...' > $install_tmp
exit 0
fi
if [ "${action}" == "uninstall" ];then
if [ -f /usr/lib/systemd/system/haproxy.service ] || [ -f /lib/systemd/system/haproxy.service ];then
systemctl stop haproxy
systemctl disable haproxy
rm -rf /usr/lib/systemd/system/haproxy.service
rm -rf /lib/systemd/system/haproxy.service
systemctl daemon-reload
fi
fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ] && [ -d $serverPath/haproxy ];then
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/haproxy/index.py start ${type}
cd ${rootPath} && python3 ${rootPath}/plugins/haproxy/index.py initd_install ${type}
fi
+53
View File
@@ -0,0 +1,53 @@
function spPostMin(method, args, callback){
var req_data = {};
req_data['name'] = 'haproxy';
req_data['func'] = method;
if (typeof(args) != 'undefined' && args!=''){
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function spPost(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
spPostMin(method,args,function(data){
layer.close(loadT);
if(typeof(callback) == 'function'){
callback(data);
}
});
}
function secToTime(s) {
var t;
if(s > -1){
var hour = Math.floor(s/3600);
var min = Math.floor(s/60) % 60;
var sec = s % 60;
if(hour < 10) {
t = '0'+ hour + ":";
} else {
t = hour + ":";
}
if(min < 10){t += "0";}
t += min + ":";
if(sec < 10){t += "0";}
t += sec.toFixed(2);
}
return t;
}
+70
View File
@@ -0,0 +1,70 @@
#!/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")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
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}'`
VERSION=2.6.4
MIN_VERSION=2.6
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/haproxy
APP_DIR=${serverPath}/source/haproxy
mkdir -p $APP_DIR
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
if [ $sysName == 'Darwin' ]; then
wget -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
else
curl -sSLo ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
fi
fi
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
curl -sSLo ${APP_DIR}/haproxy-${VERSION}.tar.gz https://www.haproxy.org/download/${MIN_VERSION}/src/haproxy-${VERSION}.tar.gz
fi
cd ${APP_DIR} && tar -zxvf haproxy-${VERSION}.tar.gz
if [ "$OSNAME" == "macos" ];then
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=osx && make install PREFIX=$serverPath/haproxy
else
cd ${APP_DIR}/haproxy-${VERSION} && make TARGET=linux-glibc && make install PREFIX=$serverPath/haproxy
fi
echo $MIN_VERSION > $serverPath/haproxy/version.pl
echo 'Install_HA' > $install_tmp
}
Uninstall_App()
{
if [ -f $serverPath/haproxy/initd/haproxy ];then
$serverPath/haproxy/initd/haproxy stop
fi
rm -rf $serverPath/haproxy
echo "Uninstall_HA" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

+20
View File
@@ -0,0 +1,20 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('imail');">服务</p>
<p onclick="pluginInitD('imail');">自启动</p>
<p onclick="pluginConfig('imail',null, 'conf');">配置文件</p>
<p onclick="pluginLogs('imail',null,'run_log', 50);">运行日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=imail&f=js/imail.js", function(){
mail.init();
pluginService('imail');
});
</script>
+218
View File
@@ -0,0 +1,218 @@
# 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/imail'
__SR = ''
def __init__(self):
self.__setupPath = self.getServerDir()
self.__SR = '''#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
export USER=%s
export HOME=%s && ''' % ( self.getRunUser(), self.getHomeDir())
def getArgs(self):
args = sys.argv[3:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def __release_port(self, port):
from collections import namedtuple
try:
import firewall_api
firewall_api.firewall_api().addAcceptPortArgs(port, 'IMail-Server', 'port')
return port
except Exception as e:
return "Release failed {}".format(e)
def openPort(self):
for i in ["25", "110", "143", "465", "995", "993", "587"]:
self.__release_port(i)
return True
def getPluginName(self):
return 'imail'
def getPluginDir(self):
return mw.getPluginDir() + '/' + self.getPluginName()
def getServerDir(self):
return mw.getServerDir() + '/' + self.getPluginName()
def getInitdConfTpl(self):
path = self.getPluginDir() + "/init.d/imail.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):
data = mw.execShell(
"ps -ef|grep " + self.getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
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 + '/imail.service'
systemServiceTpl = self.getPluginDir() + '/init.d/imail.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
log_path = self.getServerDir() + '/logs'
if not os.path.exists(log_path):
os.mkdir(log_path)
return file_bin
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(self.__SR + 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 initd_status(self):
if mw.isAppleSystem():
return "Apple Computer does not support"
cmd = 'systemctl status imail | grep loaded | grep "enabled;"'
data = mw.execShell(cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initd_install(self):
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl enable imail')
return 'ok'
def initd_uinstall(self):
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable imail')
return 'ok'
def conf(self):
conf_path = self.getServerDir() + '/custom/conf/app.conf'
if not os.path.exists(conf_path):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":1080")
return self.getServerDir() + '/custom/conf/app.conf'
def run_log(self):
ilog = self.getServerDir() + '/logs/imail.log'
if not os.path.exists(ilog):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":1080")
return self.getServerDir() + '/logs/imail.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": "简单邮件服务[DEV]",
"name": "imail",
"title": "邮件服务",
"shell": "install.sh",
"versions":["0.0.17"],
"updates":["0.0.17"],
"tip": "soft",
"checks": "server/imail",
"path": "server/imail",
"display": 1,
"author": "midoks",
"date": "2022-09-26",
"home": "https://github.com/midoks/mdserver-web",
"type": 0,
"pid": "5"
}
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=Imail Simple Mail Server
After=network.target
[Service]
Type=forking
ExecStart={$SERVER_PATH}/imail/init.d/imail start
ExecStop={$SERVER_PATH}/imail/init.d/imail stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
+89
View File
@@ -0,0 +1,89 @@
#!/bin/bash
# chkconfig: 2345 55 25
# description: Imail Service
### BEGIN INIT INFO
# Provides: bt
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts Imail
# Description: starts the Imail
### END INIT INFO
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# Source function library.
if [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
fi
if [ -f /etc/rc.d/init.d/functions ];then
. /etc/rc.d/init.d/functions
fi
app_path={$SERVER_PATH}/imail
SERVICENAME="imail"
im_start(){
isStart=`ps -ef|grep 'imail service' |grep -v grep|awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "Starting imail... \c"
cd $app_path && ${app_path}/imail service &
isStart=""
while [[ "$isStart" == "" ]];
do
echo -e ".\c"
sleep 0.5
isStart=$(lsof -n -P -i:25|grep LISTEN|grep -v grep|awk '{print $2}'|xargs)
let n+=1
if [ $n -gt 15 ];then
break;
fi
done
if [ "$isStart" == '' ];then
echo -e "\033[31mfailed\033[0m"
echo '------------------------------------------------------'
tail -n 20 ${app_path}/logs/run_away.log
echo '------------------------------------------------------'
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
}
im_stop(){
pids=`ps -ef|grep 'imail service' |grep -v grep|awk '{print $2}'`
arr=($pids)
echo -e "Stopping ${SERVICENAME}... \c"
for p in ${arr[@]}
do
kill -9 $p
done
echo -e "\033[32mdone\033[0m"
}
im_status(){
isStart=`ps -ef|grep 'imail service' |grep -v grep|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') im_start;;
'stop') im_stop;;
'status') im_status;;
'reload')
im_stop
im_start;;
'restart')
im_stop
im_start;;
esac
+25
View File
@@ -0,0 +1,25 @@
#!/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
+95
View File
@@ -0,0 +1,95 @@
var mail = {
plugin_name: 'imail',
init: function () {
var _this = this;
},
str2Obj:function(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
},
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'] = 'mail';
data['func'] = method;
data['version'] = $('.plugin_version').attr('version');
if (typeof(args) == 'string'){
data['args'] = JSON.stringify(this.str2Obj(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'] = 'mail';
data['func'] = method;
data['version'] = $('.plugin_version').attr('version');
if (typeof(args) == 'string'){
data['args'] = JSON.stringify(this.str2Obj(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');
}
}
+109
View File
@@ -0,0 +1,109 @@
#!/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.0.17
# bash install.sh install 0.0.16
## cd /www/server/mdserver-web/plugins/imail && bash install.sh install 0.0.16
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"
fi
}
load_vars() {
OS=$(uname | tr '[:upper:]' '[:lower:]')
TARGET_DIR="$serverPath/imail"
}
get_download_url() {
DOWNLOAD_URL="https://github.com/midoks/imail/releases/download/$VERSION/imail_${VERSION}_${OS}_${ARCH}.tar.gz"
}
# 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_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
load_vars
get_arch
get_download_url
DOWNLOAD_FILE="$(mktemp).tar.gz"
download_file $DOWNLOAD_URL $DOWNLOAD_FILE
if [ ! -d "$TARGET_DIR" ]; then
mkdir -p "$TARGET_DIR"
fi
tar -C "$TARGET_DIR" -zxf $DOWNLOAD_FILE
rm -rf $DOWNLOAD_FILE
pushd "$TARGET_DIR/scripts" >/dev/null 2>&1
bash make.sh
if [ -d $serverPath/imail ];then
echo "$VERSION" > $serverPath/imail/version.pl
cd ${rootPath} && python3 ${rootPath}/plugins/imail/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/imail/index.py initd_install
fi
echo 'install successful' > $install_tmp
}
Uninstall_App()
{
cd ${rootPath} && python3 ${rootPath}/plugins/imail/index.py initd_uninstall
cd ${rootPath} && python3 ${rootPath}/plugins/imail/index.py stop
rm -rf $serverPath/imail
echo "install fail" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+17 -3
View File
@@ -304,7 +304,7 @@ def getErrorLog():
if 'close' in args:
mw.writeFile(filename, '')
return mw.returnJson(False, '日志已清空')
info = mw.getNumLines(filename, 18)
info = mw.getLastLine(filename, 18)
return mw.returnJson(True, 'OK', info)
@@ -343,6 +343,7 @@ def initMariaDbPwd():
time.sleep(5)
serverdir = getServerDir()
myconf = serverdir + "/etc/my.cnf"
pwd = mw.getRandomString(16)
db_option = "-S " + serverdir + "/mysql.sock"
@@ -363,6 +364,16 @@ def initMariaDbPwd():
pwd + ' -e "drop database test";'
mw.execShell(drop_test_db)
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
return True
@@ -2180,8 +2191,11 @@ def installPreInspection(version):
def uninstallPreInspection(version):
# return "请手动删除MySQL[{}]".format(version)
return 'ok'
stop(version)
if mw.isDebugMode():
return 'ok'
return "请手动删除MariaDB[{}]<br/> rm -rf {}".format(version, getServerDir())
if __name__ == "__main__":
func = sys.argv[1]
+5 -1
View File
@@ -817,6 +817,7 @@ function openPhpmyadmin(name,username,password){
layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
return;
}
var phpmyadmin_cfg = rdata;
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
var rdata = $.parseJSON(data.data);
@@ -824,7 +825,10 @@ function openPhpmyadmin(name,username,password){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
return;
}
$("#toPHPMyAdmin").attr('action',rdata.data);
var home_page = rdata.data;
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@");
$("#toPHPMyAdmin").attr('action',home_page);
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
+9 -4
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.6.8
MY_VER=10.6.9
Install_app()
{
@@ -57,10 +57,15 @@ Install_app()
fi
# ----- cpu end ------
# https://mirrors.aliyun.com/mariadb/mariadb-10.8.3/source/mariadb-10.8.3.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# https://mirrors.aliyun.com/mariadb/mariadb-10.8.3/source/mariadb-10.8.3.tar.gz
wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
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.6.8/source/mariadb-10.6.8.tar.gz
if [ "$?" != "0" ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
+6 -4
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.7.4
MY_VER=10.7.5
Install_app()
{
@@ -58,14 +58,16 @@ Install_app()
# ----- cpu end ------
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
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
if [ "$?" != "0" ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/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 \
+6 -3
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.8.3
MY_VER=10.8.4
Install_app()
{
@@ -58,8 +58,11 @@ Install_app()
# ----- cpu end ------
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
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
if [ "$?" != "0" ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
+16 -4
View File
@@ -21,14 +21,26 @@ OSNAME=`cat ${rootPath}/data/osname.pl`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
Install_app_mac()
{
if [ ! -f $serverPath/source/mongodb-macos-x86_64-${VERSION}.tgz ];then
wget -O $serverPath/source/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz
mkdir -p $serverPath/mongodb
if [ "$VERSION" == "5.0" ];then
G_VERSION="5.0.11"
elif [[ "$VERSION" == "4.4" ]]; then
G_VERSION="4.4.11"
fi
cd $serverPath/source && tar -zxvf mongodb-macos-x86_64-${VERSION}.tgz
cd mongodb-macos-x86_64-${VERSION} && mv ./* $serverPath/mongodb
if [ ! -f $serverPath/source/mongodb-macos-x86_64-${G_VERSION}.tgz ];then
wget -O $serverPath/source/mongodb-macos-x86_64-${G_VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${G_VERSION}.tgz
fi
cd $serverPath/source && tar -zxvf mongodb-macos-x86_64-${G_VERSION}.tgz
cd mongodb-macos-x86_64-${G_VERSION} && mv ./* $serverPath/mongodb
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+107
View File
@@ -0,0 +1,107 @@
[client]
user = root
#password = your_password
port = 3306
socket = {$SERVER_APP_PATH}/mysql.sock
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
user = mysql
port = 3306
socket = {$SERVER_APP_PATH}/mysql.sock
basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
default_storage_engine = InnoDB
key_buffer_size = 8M
max_allowed_packet = 100M
table_open_cache = 32
sort_buffer_size = 256K
net_buffer_length = 4K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=0
query_cache_size = 4M
tmp_table_size = 8M
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535
skip-name-resolve=1
#skip-grant-tables
#skip-networking
#skip-external-locking
#loose-skip-innodb
log-bin=mysql-bin
binlog_format=mixed
slow_query_log=1
slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log
long_query_time=10
#log_queries_not_using_indexes=on
#log_slow_admin_statements=1
#log_slow_slave_statements=1
expire_logs_days=30
relay-log=mdserver
relay-log-index=mdserver
#master
#binlog-do-db
binlog-ignore-db = test
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
#slave
log-slave-updates = 1
skip-slave-start = 1
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_additional_mem_pool_size = 2M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 120
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 1
innodb_write_io_threads = 1
innodb_file_per_table=1
innodb_large_prefix = 1
secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
@@ -7,8 +7,8 @@ socket = {$SERVER_APP_PATH}/mysql.sock
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
;sha256_password_private_key_path=mysql.pem
;sha256_password_public_key_path=mysql.pub
sha256_password_private_key_path=mysql.pem
sha256_password_public_key_path=mysql.pub
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
user = mysql
+1 -1
View File
@@ -53,7 +53,7 @@
.conf_p span {
display: inline-block;
margin-right: 10px;
width: 95px;
width: 135px;
text-align: right;
}
</style>
+30 -4
View File
@@ -333,7 +333,7 @@ def getErrorLog():
if 'close' in args:
mw.writeFile(filename, '')
return mw.returnJson(False, '日志已清空')
info = mw.getNumLines(filename, 18)
info = mw.getLastLine(filename, 18)
return mw.returnJson(True, 'OK', info)
@@ -404,6 +404,7 @@ def initMysqlPwd():
time.sleep(5)
serverdir = getServerDir()
myconf = serverdir + "/etc/my.cnf"
pwd = mw.getRandomString(16)
# cmd_pass = serverdir + '/bin/mysqladmin -uroot password ' + pwd
@@ -426,6 +427,17 @@ def initMysqlPwd():
pwd + ' -e "drop database test";'
mw.execShell(drop_test_db)
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
return True
@@ -468,6 +480,17 @@ def initMysql8Pwd():
myconf + ' -uroot -p' + pwd + ' -e "drop database test";'
mw.execShell(drop_test_db)
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
return True
@@ -475,7 +498,7 @@ def initMysql8Pwd():
def myOp(version, method):
# import commands
init_file = initDreplace()
init_file = initDreplace(version)
try:
isInited = initMysqlData()
if not isInited:
@@ -2338,8 +2361,11 @@ def installPreInspection(version):
def uninstallPreInspection(version):
# return "请手动删除MySQL[{}]".format(version)
return 'ok'
stop(version)
if mw.isDebugMode():
return 'ok'
return "请手动删除MySQL[{}]<br/> rm -rf {}".format(version, getServerDir())
if __name__ == "__main__":
func = sys.argv[1]
+27 -4
View File
@@ -68,6 +68,26 @@ function myAsyncPost(method,args){
return syncPost('/plugins/run', {name:'mysql', func:method, args:_args});
}
function vaildPhpmyadmin(url,username,password){
console.log("Authorization: Basic " + btoa(username + ":" + password));
$.ajax({
type: "GET",
url: url,
dataType: 'json',
async: false,
username:username,
password:password,
headers: {
"Authorization": "Basic " + btoa(username + ":" + password)
},
data: 'vaild',
success: function (){
alert('Thanks for your comment!');
}
});
}
function runInfo(){
myPost('run_info','',function(data){
@@ -818,16 +838,19 @@ function openPhpmyadmin(name,username,password){
layer.msg('当前为[mariadb]模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
return;
}
// console.log(data);
var phpmyadmin_cfg = rdata;
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
return;
}
$("#toPHPMyAdmin").attr('action',rdata.data);
var home_page = rdata.data;
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@")
$("#toPHPMyAdmin").attr('action',home_page);
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
setTimeout(function(){ window.location.href = '/soft'; },3000);
@@ -836,7 +859,7 @@ function openPhpmyadmin(name,username,password){
//检查版本
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'version'});
bigVer = data.data.split('.')[0]
bigVer = data.data.split('.')[0];
if (bigVer>=4.5){
setTimeout(function(){
+1 -1
View File
@@ -74,7 +74,7 @@ Install_mysql()
OPENSSL_VERSION=`openssl version|awk '{print $2}'|awk -F '.' '{print $1}'`
if [ "${OPENSSL_VERSION}" -ge "3" ];then
#openssl version to high
cd $serverPath/mdserver-web/plugins/php/lib && /bin/bash openssl.sh
cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl"
fi
+4 -4
View File
@@ -17,7 +17,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mysqlDir=${serverPath}/source/mysql
VERSION="5.7.37"
VERSION="5.7.39"
Install_mysql()
@@ -61,14 +61,14 @@ Install_mysql()
fi
# ----- cpu end ------
cd $serverPath/mdserver-web/plugins/mysql/lib && /bin/bash rpcgen.sh
cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
fi
#检测文件是否损坏.
md5_mysql_ok=d0489fc3880248a58759c50bfb286dbb
md5_mysql_ok=db1b672fc257bd46356c7af26dd22801
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -89,7 +89,7 @@ Install_mysql()
OPENSSL_VERSION=`openssl version|awk '{print $2}'|awk -F '.' '{print $1}'`
if [ "${OPENSSL_VERSION}" -ge "3" ];then
#openssl version to high
cd $serverPath/mdserver-web/plugins/php/lib && /bin/bash openssl.sh
cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl"
fi
+2 -2
View File
@@ -95,7 +95,7 @@ Install_mysql()
fi
# ----- cpu end ------
cd $serverPath/mdserver-web/plugins/mysql/lib && /bin/bash rpcgen.sh
cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh
INSTALL_CMD=cmake
# check cmake version
@@ -132,7 +132,7 @@ Install_mysql()
OPENSSL_VERSION=`openssl version|awk '{print $2}'|awk -F '.' '{print $1}'`
if [ "${OPENSSL_VERSION}" -ge "3" ];then
#openssl version to high
cd $serverPath/mdserver-web/plugins/php/lib && /bin/bash openssl.sh
cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl"
fi
+2 -2
View File
@@ -1,6 +1,6 @@
lua_shared_dict limit 30m;
lua_shared_dict drop_ip 30m;
lua_shared_dict drop_sum 30m;
lua_shared_dict drop_ip 10m;
lua_shared_dict drop_sum 10m;
lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
access_by_lua_file {$WAF_PATH}/lua/init.lua;
+1 -1
View File
@@ -232,7 +232,7 @@
<p onclick="wafGloabl();">全局配置</p>
<p onclick="wafSite();">站点配置</p>
<p onclick="wafHistory();">封锁历史</p>
<!-- <p onclick="wafLogs();">操作日志</p> -->
<p onclick="wafLogs();">操作日志</p>
</div>
<!-- lib-con -->
<div class="bt-w-con pd15">
+39 -5
View File
@@ -111,7 +111,7 @@ def initSiteInfo():
tmp['log'] = True
tmp['get'] = True
tmp['post'] = True
tmp['open'] = False
tmp['open'] = True
tmp['cc'] = config_contents['cc']
tmp['retry'] = config_contents['retry']
@@ -122,7 +122,22 @@ def initSiteInfo():
tmp['scan'] = config_contents['scan']
cdn_header = ['x-forwarded-for',
'x-real-ip', 'HTTP_CF_CONNECTING_IP']
'x-real-ip',
'x-forwarded',
'forwarded-for',
'forwarded',
'true-client-ip',
'client-ip',
'ali-cdn-real-ip',
'cdn-src-ip',
'cdn-real-ip',
'cf-connecting-ip',
'cf-connecting-ip',
'x-cluster-client-ip',
'wl-proxy-client-ip',
'proxy-client-ip',
'true-client-ip',
'HTTP_CF_CONNECTING_IP']
tmp['cdn_header'] = cdn_header
disable_upload_ext = ["php", "jsp"]
@@ -163,6 +178,7 @@ def initTotalInfo():
tmp['get'] = 0
tmp['post'] = 0
tmp['total'] = 0
tmp['url_ext'] = 0
_name = {}
_name[name] = tmp
total_contents['sites'] = _name
@@ -186,10 +202,12 @@ def status():
def contentReplace(content):
service_path = mw.getServerDir()
waf_path = getServerDir() + "/waf"
waf_root = getServerDir()
waf_path = waf_root + "/waf"
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$WAF_PATH}', waf_path)
content = content.replace('{$WAF_ROOT}', waf_root)
return content
@@ -201,6 +219,14 @@ def initDreplace():
cmd = 'cp -rf ' + sdir + ' ' + path
mw.execShell(cmd)
logs_path = path + '/logs'
if not os.path.exists(logs_path):
mw.execShell('mkdir -p ' + logs_path)
debug_log = path + '/debug.log'
if not os.path.exists(debug_log):
mw.execShell('echo "" > ' + debug_log)
config = path + '/waf/config.json'
content = mw.readFile(config)
content = json.loads(content)
@@ -214,6 +240,11 @@ def initDreplace():
content = contentReplace(content)
mw.writeFile(config, content)
config_common = path + "/waf/lua/common.lua"
content = mw.readFile(config_common)
content = contentReplace(content)
mw.writeFile(config_common, content)
waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
waf_tpl = getPluginDir() + "/conf/luawaf.conf"
content = mw.readFile(waf_tpl)
@@ -224,6 +255,9 @@ def initDreplace():
initSiteInfo()
initTotalInfo()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + path)
def start():
initDreplace()
@@ -800,7 +834,7 @@ def getLogsList():
return data[1]
data = []
path = mw.getLogsDir() + '/waf'
path = getServerDir() + '/logs'
if not os.path.exists(path):
return mw.returnJson(False, '还未生成!', [])
@@ -823,7 +857,7 @@ def getSafeLogs():
if not data[0]:
return data[1]
path = mw.getLogsDir() + '/waf'
path = getServerDir() + '/logs'
file = path + '/' + args['siteName'] + '_' + args['toDate'] + '.log'
if not os.path.exists(file):
return mw.returnJson(False, "文件不存在!")
+2 -2
View File
@@ -19,12 +19,12 @@ Install_of(){
echo '0.1' > $serverPath/op_waf/version.pl
echo 'install ok' > $install_tmp
cd ${rootPath} && python3 plugins/op_waf/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py start
}
Uninstall_of(){
cd ${rootPath} && python3 plugins/op_waf/index.py stop
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
rm -rf $serverPath/op_waf
}
+17 -17
View File
@@ -28,7 +28,7 @@ function setRequestCode(ruleName, statusCode){
title: "设置响应代码【" + ruleName + "】",
area: '300px',
shift: 5,
closeBtn: 2,
closeBtn: 1,
shadeClose: true,
content: '<div class="bt-form pd20 pb70">\
<div class="line">\
@@ -144,7 +144,7 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
type: 1,
title: "设置CC规则",
area: '540px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@@ -184,7 +184,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
type: 1,
title: "设置恶意容忍规则",
area: '500px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@@ -339,7 +339,7 @@ function setObjConf(ruleName, type) {
type: 1,
title: "编辑规则【" + ruleName + "】",
area: ['700px', '530px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -405,7 +405,7 @@ function scanRule() {
type: 1,
title: "常用扫描器过滤规则",
area: '650px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@@ -571,7 +571,7 @@ function ipWhite(type) {
type: 1,
title: "管理IP白名单",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 ipv4_list">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -714,7 +714,7 @@ function ipBlack(type) {
type: 1,
title: "管理IP黑名单",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="tab_list"><div class="tab_block active">IPv4黑名单</div><div class="tab_block">IPv6黑名单</div></div>\
<div class="pd15 ipv4_block">\
@@ -824,12 +824,12 @@ function wafScreen(){
<div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\
<div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\
<div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">0</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</span></div>\
<div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">恶意文件上传</span><span class="val">0</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">0</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.url_ext+'</span></div>\
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">0</span></div>\
</div>';
@@ -975,7 +975,7 @@ function siteWafLog(siteName) {
type: 1,
title: "日志【" + siteName + "】",
area: ['880px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="lib-box pd15 lib-box-log">\
<div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\
@@ -1071,7 +1071,7 @@ function siteLogCon(siteName, day, page) {
type: 1,
title: time + "详情",
area: '600px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
@@ -1190,7 +1190,7 @@ function siteRuleAdmin(siteName, ruleName, type) {
type: 1,
title: "管理网站过滤规则【" + title + "】",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -1237,7 +1237,7 @@ function cdnHeader(siteName, type) {
type: 1,
title: "管理网站【" + siteName + "】CDN-Headers",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -1342,7 +1342,7 @@ function setSiteObjConf(siteName, ruleName, type) {
type: 1,
title: "编辑网站【" + siteName + "】规则【" + ruleName + "】",
area: ['700px', '530px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="divtable">\
@@ -1394,7 +1394,7 @@ function siteWafConfig(siteName, type) {
type: 1,
title: "网站配置【" + siteName + "】",
area: ['700px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div id="s_w_c"></div>'
});
+173
View File
@@ -0,0 +1,173 @@
# coding:utf-8
import sys
import io
import os
import time
import json
import os
import sys
import time
import string
import json
import hashlib
import shlex
import datetime
import subprocess
import re
from random import Random
TEST_URL = "http://t1.cn/"
# TEST_URL = "https://www.zzzvps.com/"
def httpGet(url, timeout=10):
import urllib.request
try:
req = urllib.request.urlopen(url, timeout=timeout)
result = req.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpGet__UA(url, ua, timeout=10):
import urllib.request
headers = {'user-agent': ua}
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)
result = response.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpPost(url, data, timeout=10):
"""
发送POST请求
@url 被请求的URL地址(必需)
@data POST参数,可以是字符串或字典(必需)
@timeout 超时时间默认60秒
return string
"""
if sys.version_info[0] == 2:
try:
import urllib
import urllib2
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.urlencode(data)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req, timeout=timeout)
return response.read()
except Exception as ex:
return str(ex)
else:
try:
import urllib.request
import ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
except:
pass
data = urllib.parse.urlencode(data).encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req, timeout=timeout)
result = response.read()
if type(result) == bytes:
result = result.decode('utf-8')
return result
except Exception as ex:
return str(ex)
def test_Dir():
'''
目录保存
'''
url = TEST_URL + '?t=../etc/passwd'
print("args test start")
url_val = httpGet(url, 10)
# print(url_val)
print("args test end")
def test_UA():
'''
user-agent 过滤
'''
url = TEST_URL
print("user-agent test start")
url_val = httpGet__UA(url, 'ApacheBench')
print(url_val)
print("user-agent test end")
def test_POST():
'''
user-agent 过滤
'''
url = TEST_URL
print("POST test start")
url_val = httpPost(url, {'data': "substr($mmsss,0,1)"})
# url_val = httpPost(url, {'data': "123123"})
print(url_val)
print("POST test end")
def test_scan():
'''
目录保存
'''
url = TEST_URL + '/acunetix_wvs_security_test?t=1'
print("scan test start")
url_val = httpGet(url, 10)
print(url_val)
print("scan test end")
def test_CC():
'''
目录保存
'''
url = TEST_URL + 'ok.txt'
print("CC test start")
for x in range(122):
url_val = httpGet(url, 10)
print(url_val)
print("CC test end")
def test_url_ext():
'''
目录保存
'''
url = TEST_URL + 't.sql'
print("url_ext start")
url_val = httpGet(url, 10)
print(url_val)
print("url_ext end")
def test_start():
# test_Dir()
# test_UA()
# test_POST()
# test_scan()
# test_CC()
test_url_ext()
if __name__ == "__main__":
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/op_waf && sh install.sh uninstall 0.1 && sh install.sh install 0.1')
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/ && python3 plugins/openresty/index.py stop && python3 plugins/openresty/index.py start')
test_start()
View File
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# yum -y install httpd-tools
# ab -c 1000 -n 1000000 http://xx.xx.xx/
python3 index.py
+158
View File
@@ -0,0 +1,158 @@
# coding:utf-8
import sys
import io
import os
import time
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'op_waf'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/task_config.json"
return conf
def getConfigData():
try:
return json.loads(mw.readFile(getTaskConf()))
except:
pass
return []
def getConfigTpl():
tpl = {
"name": "",
"task_id": -1,
}
return tpl
def createBgTask():
removeBgTask()
args = {
"period": "minute-n",
"minute-n": "3",
}
createBgTaskByName(getPluginName(), args)
def createBgTaskByName(name, args):
cfg = getConfigTpl()
_name = "[勿删]OP防火墙后台任务[" + name + "]"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
api = crontab_api.crontab_api()
period = args['period']
_hour = ''
_minute = ''
_where1 = ''
_type_day = "day"
if period == 'day':
_type_day = 'day'
_hour = args['hour']
_minute = args['minute']
elif period == 'minute-n':
_type_day = 'minute-n'
_where1 = args['minute-n']
_minute = ''
cmd = '''
rname=%s
plugin_path=%s
script_path=%s
logs_file=$plugin_path/${rname}.log
''' % (name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "python3 $script_path/tool_task.py run >> $logs_file 2>&1"' + "\n"
cmd += 'python3 $script_path/tool_task.py run >> $logs_file 2>&1' + "\n"
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
params = {
'name': _name,
'type': _type_day,
'week': "",
'where1': _where1,
'hour': _hour,
'minute': _minute,
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'urladdress': '',
}
task_id = api.add(params)
if task_id > 0:
cfg["task_id"] = task_id
cfg["name"] = name
_dd = getConfigData()
_dd.append(cfg)
mw.writeFile(getTaskConf(), json.dumps(_dd))
def removeBgTask():
cfg_list = getConfigData()
for x in range(len(cfg_list)):
cfg = cfg_list[x]
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
cfg_list[x] = cfg
mw.writeFile(getTaskConf(), '[]')
return True
return False
def run():
print('op lua run ok')
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()
elif action == "run":
run()
+1 -1
View File
@@ -1 +1 @@
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/btwaf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true}
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/waf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true}
+168 -30
View File
@@ -1,26 +1,89 @@
local setmetatable = setmetatable
local _M = { _VERSION = '0.01' }
local _M = { _VERSION = '0.02' }
local mt = { __index = _M }
local json = require "cjson"
local ngx_match = ngx.re.find
local debug_mode = false
function _M.new(self, cpath, rpath, logdir)
-- ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath)
local opt = {
cpath = cpath,
rpath = rpath,
logdir = logdir,
config = '',
site_config = '',
params = nil
local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/"
local logdir = waf_root.."/logs/"
local rpath = cpath.."/rule/"
function _M.new(self)
local self = {
waf_root = waf_root,
cpath = cpath,
rpath = rpath,
logdir = logdir,
config = '',
site_config = '',
server_name = '',
params = nil
}
local p = setmetatable(opt, mt)
return p
return setmetatable(self, mt)
end
function _M.setDebug(self, mode)
debug_mode = mode
end
-- 调试方式
function _M.D(self, msg)
if not debug_mode then return true end
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = tostring( key)..':'.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
local fp = io.open(waf_root.."/debug.log", "ab")
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
local function write_file_clear(filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
end
function _M.setConfData( self, config, site_config )
self.config = config
self.site_config = site_config
@@ -94,6 +157,10 @@ function _M.compare_ip(self,ips)
end
function _M.to_json(self, msg)
return json.encode(msg)
end
function _M.return_message(self, status, msg)
ngx.header.content_type = "application/json;"
ngx.status = status
@@ -136,20 +203,15 @@ function _M.write_file(self, filename, body)
return true
end
function _M.write_file_clear(self, filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
return write_file_clear(filename, body)
end
function _M.write_drop_ip(self, is_drop, drop_time)
local filename = self.cpath .. 'drop_ip.log'
local filename = self.logdir .. 'drop_ip.log'
local fp = io.open(filename,'ab')
local server_name = self.params["server_name"]
local ip = self.params["server_name"]
@@ -234,11 +296,21 @@ function _M.read_file(self, name)
end
function _M.read_file_table( self, name )
return self:select_rule(self:read_file('args'))
return self:select_rule(self:read_file(name))
end
local function timer_at_inc_log(premature)
local total_path = cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
if not tbody then
return false
end
return write_file_clear(total_path,tbody)
end
function _M.inc_log(self, name, rule)
local server_name = self.params['server_name']
local total_path = self.cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
@@ -246,7 +318,10 @@ function _M.inc_log(self, name, rule)
tbody = self:read_file_body(total_path)
if not tbody then return false end
end
local total = json.decode(tbody)
-- 开始计算
if not total['sites'] then total['sites'] = {} end
if not total['sites'][server_name] then total['sites'][server_name] = {} end
if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end
@@ -256,13 +331,15 @@ function _M.inc_log(self, name, rule)
total['total'] = total['total'] + 1
total['sites'][server_name][name] = total['sites'][server_name][name] + 1
total['rules'][name] = total['rules'][name] + 1
local total_log = json.encode(total)
if not total_log then return false end
ngx.shared.limit:set(total_path,total_log)
if not ngx.shared.limit:get('mw_waf_timeout') then
self:write_file_clear(total_path,total_log)
ngx.shared.limit:set('mw_waf_timeout',1,5)
end
-- 异步执行
ngx.timer.at(1, timer_at_inc_log)
end
@@ -289,9 +366,66 @@ function _M.get_server_name(self)
end
-- function _M.get_sn(self)
-- retun string.gsub(self:get_server_name(),'_','.')
-- end
function _M.is_ngx_match_orgin(self,rule,match, sign)
if ngx_match(ngx.unescape_uri(match), rule,"isjo") then
error_rule = rule .. ' >> ' .. sign .. ':' .. match
return true
end
return false
end
function _M.ngx_match_string(self, rule, content,sign)
local t = self:is_ngx_match_orgin(rule, content, sign)
if t then
return true
end
return false
end
function _M.ngx_match_list(self, rules, content)
for i,rule in ipairs(rules)
do
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match_ua(self, rules, content)
-- ngx.header.content_type = "text/html"
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match_post(self, rules, content)
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2],content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match(self, rules, sbody, rule_name)
@@ -341,6 +475,7 @@ end
function _M.write_log(self, name, rule)
local ip = self.params['ip']
local retry = self.config['retry']['retry']
local retry_time = self.config['retry']['retry_time']
@@ -352,6 +487,7 @@ function _M.write_log(self, name, rule)
else
ngx.shared.drop_ip:set(ip,1,retry_cycle)
end
if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end
local method = ngx.req.get_method()
if error_rule then
@@ -384,10 +520,13 @@ end
function _M.get_client_ip(self)
local client_ip = "unknown"
local server_name = self.params['server_name']
-- self:D("fff..."..client_ip..server_name)
if self.site_config[server_name] then
if self.site_config[server_name]['cdn'] then
for _,v in ipairs(self.site_config[server_name]['cdn_header'])
do
-- C:D("vv:"..v..tostring(request_header[v]))
if request_header[v] ~= nil and request_header[v] ~= "" then
local header_tmp = request_header[v]
if type(header_tmp) == "table" then header_tmp = header_tmp[1] end
@@ -408,7 +547,6 @@ end
function _M.is_site_config(self,cname)
local server_name = self.params["server_name"]
if self.site_config[server_name] ~= nil then
if cname == 'cc' then
return self.site_config[server_name][cname]['open']
+163 -168
View File
@@ -1,65 +1,55 @@
local cpath = "{$WAF_PATH}/"
local rpath = "{$WAF_PATH}/rule/"
local logdir = "{$ROOT_PATH}/wwwlogs/waf/"
local json = require "cjson"
local ngx_match = ngx.re.find
local _C = require "common"
local C = _C:new(cpath, rpath, logdir)
local __C = require "common"
local C = __C:new()
config = C:read_file_body_decode(cpath .. 'config.json')
local site_config = C:read_file_body_decode(cpath .. 'site.json')
local waf_root = "{$WAF_ROOT}"
config = C:read_file_body_decode(waf_root.."/waf/"..'config.json')
local site_config = C:read_file_body_decode(waf_root.."/waf/"..'site.json')
C:setConfData(config, site_config)
-- D func
local function D(msg)
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = key..':'..val.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
if not debug_mode then return true end
local fp = io.open(cpath..'debug.log', 'ab')
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
local user_agent_rules = C:read_file('user_agent')
local post_rules = C:read_file('post')
local cookie_rules = C:read_file('cookie')
local server_name = string.gsub(C:get_server_name(),'_','.')
-- C:D("sss:"..C:get_server_name())
function initParams()
local data = {}
data['ip'] = C:get_client_ip()
data['ipn'] = C:arrip(data['ip'])
data['server_name'] = server_name
-- data['ip'] = C:get_client_ip()
-- data['ipn'] = C:arrip(data['ip'])
data['request_header'] = ngx.req.get_headers()
data['uri'] = ngx.unescape_uri(ngx.var.uri)
data['server_name'] = string.gsub(C:get_server_name(),'_','.')
data['uri_request_args'] = ngx.req.get_uri_args()
data['method'] = ngx.req.get_method()
data['request_uri'] = ngx.var.request_uri
data['cookie'] = ngx.var.http_cookie
return data
end
local params = initParams()
C:setParams(params)
C:setDebug(true)
local server_name = params["server_name"]
params['ip'] = C:get_client_ip()
params['ipn'] = C:arrip(params['ip'])
C:D(server_name)
function get_return_state(rstate,rmsg)
result = {}
@@ -102,20 +92,20 @@ function save_ip_on(data)
end
end
function remove_btwaf_drop_ip()
function remove_waf_drop_ip()
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data=json.decode(ret)
result=is_chekc_table(ip_data,uri_request_args['ip'])
result = is_chekc_table(ip_data,uri_request_args['ip'])
os.execute("sleep " .. 0.6)
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2)
ip_data2 = json.decode(ret2)
if result == 3 then
for k,v in pairs(ip_data2)
do
if uri_request_args['ip'] == v['ip'] then
v['time']=0
v['time'] = 0
end
end
end
@@ -125,7 +115,7 @@ function remove_btwaf_drop_ip()
return get_return_state(true,uri_request_args['ip'] .. '已解封')
end
function clean_btwaf_drop_ip()
function clean_waf_drop_ip()
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2)
@@ -155,15 +145,7 @@ function min_route()
end
end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
function waf_args()
function waf_get_args()
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(args_rules, params['uri_request_args'],'args') then
C:write_log('args','regular')
@@ -196,8 +178,20 @@ function waf_ip_black()
end
function waf_user_agent()
-- user_agent 过滤
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match_ua(user_agent_rules,params['request_header']['user-agent']) then
C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'],user_agent_html)
return true
end
return false
end
function waf_drop()
local count,_ = ngx.shared.drop_ip:get(ip)
local count , _ = ngx.shared.drop_ip:get(ip)
if not count then return false end
if count > config['retry'] then
ngx.exit(config['cc']['status'])
@@ -206,28 +200,33 @@ function waf_drop()
return false
end
function waf_user_agent()
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match(user_agent_rules,params['request_header']['user-agent'],'user_agent') then
C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'],user_agent_html)
return true
end
return false
end
function cc()
function waf_cc()
local ip = params['ip']
local ip_lock = ngx.shared.drop_ip:get(ip)
if ip_lock then
if ip_lock > 0 then
ngx.exit(config['cc']['status'])
return true
end
end
if not config['cc']['open'] or not C:is_site_config('cc') then return false end
local request_uri = params['request_uri']
local endtime = config['cc']['endtime']
if not config['cc']['open'] or not site_cc then return false end
local token = ngx.md5(ip .. '_' .. request_uri)
local count,_ = ngx.shared.limit:get(token)
local count = ngx.shared.limit:get(token)
local limit = config['cc']['limit']
local cycle = config['cc']['cycle']
if count then
if count > limit then
local safe_count,_ = ngx.shared.drop_sum:get(ip)
if count > limit then
local safe_count, _ = ngx.shared.drop_sum:get(ip)
if not safe_count then
ngx.shared.drop_sum:set(ip,1,86400)
safe_count = 1
@@ -236,23 +235,22 @@ function cc()
end
local lock_time = (endtime * safe_count)
if lock_time > 86400 then lock_time = 86400 end
ngx.shared.drop_ip:set(ip,retry+1,lock_time)
-- lock_time = 10
ngx.shared.drop_ip:set(ip,1,lock_time)
C:write_log('cc',cycle..'秒内累计超过'..limit..'次请求,封锁' .. lock_time .. '秒')
C:write_drop_ip('cc',lock_time)
if not server_name then
insert_ip_list(ip,lock_time,os.time(),'1111')
else
insert_ip_list(ip,lock_time,os.time(),server_name)
end
ngx.exit(config['cc']['status'])
return true
else
ngx.shared.limit:incr(token,1)
end
else
ngx.shared.limit:set(token,1,cycle)
ngx.shared.drop_sum:set(ip,1,86400)
ngx.shared.limit:set(token, 1, cycle)
end
return false
end
--强制验证是否使用正常浏览器访问网站
@@ -287,20 +285,25 @@ end
function waf_scan_black()
-- 扫描软件禁止
if not config['scan']['open'] or not C:is_site_config('scan') then return false end
if C:is_ngx_match(scan_black_rules['cookie'],params["request_header"]["cookie"],false) then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
if C:is_ngx_match(scan_black_rules['args'],params["request_uri"],false) then
if not params["cookie"] then
if C:ngx_match_string(scan_black_rules['cookie'], tostring(params["cookie"]),'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
end
if C:ngx_match_string(scan_black_rules['args'], params["request_uri"], 'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
for key,value in pairs(params["request_header"])
do
if C:is_ngx_match(scan_black_rules['header'], key, false) then
if C:ngx_match_string(scan_black_rules['header'], key, 'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
@@ -309,20 +312,9 @@ function waf_scan_black()
return false
end
function waf_post_referer()
if params['method'] ~= "POST" then return false end
if C:is_ngx_match(referer_local, params['request_header']['Referer'],'post') then
C:write_log('post_referer','regular')
C:return_html(config['post']['status'],post_html)
return true
end
return false
end
function waf_post()
if not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end
if waf_post_referer() then return true end
content_length = tonumber(params["request_header"]['content-length'])
max_len = 640 * 1020000
if content_length > max_len then return false end
@@ -333,7 +325,19 @@ function waf_post()
return false
end
if C:is_ngx_match(post_rules,request_args,'post') then
for key, val in pairs(request_args) do
if type(val) == "table" then
if type(val[1]) == "boolean" then
return false
end
data = table.concat(val, ", ")
else
data = val
end
end
if C:is_ngx_match_post(post_rules,data) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
return true
@@ -366,10 +370,11 @@ function post_data_chekc()
end
if not list_list then return false end
aaa=nil
aaa = nil
for k,v in pairs(request_args)
do
aaa=v
aaa = v
end
if not aaa then return false end
@@ -381,7 +386,7 @@ function post_data_chekc()
if not data_len then return false end
if arrlen(data_len) ==0 then return false end
if C:is_ngx_match(post_rules,data_len,'post') then
if C:is_ngx_match_post(post_rules , data_len) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
return true
@@ -406,7 +411,7 @@ end
function post_X_Forwarded()
if not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end
if C:is_ngx_match(post_rules,params["request_header"]['X-forwarded-For'],'post') then
if C:is_ngx_match_post(post_rules,params["request_header"]['X-forwarded-For']) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
return true
@@ -415,39 +420,39 @@ function post_X_Forwarded()
end
function php_path()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_php_path'])
do
if ngx_match(uri,rule .. "/?.*\\.php$","isjo") then
C:write_log('php_path','regular')
C:return_html(config['other']['status'],other_html)
return C:return_message(200,uri)
end
end
return false
end
-- function php_path()
-- if site_config[server_name] == nil then return false end
-- for _,rule in ipairs(site_config[server_name]['disable_php_path'])
-- do
-- if C:ngx_match_string(params['uri'],rule .. "/?.*\\.php$","isjo") then
-- C:write_log('php_path','regular')
-- C:return_html(config['other']['status'],other_html)
-- return C:return_message(200,uri)
-- end
-- end
-- return false
-- end
function url_path()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_path'])
do
if ngx_match(uri,rule,"isjo") then
C:write_log('path','regular')
C:return_html(config['other']['status'],other_html)
return true
end
end
return false
end
-- function url_path()
-- if site_config[server_name] == nil then return false end
-- for _,rule in ipairs(site_config[server_name]['disable_path'])
-- do
-- if ngx_match(uri,rule,"isjo") then
-- C:write_log('path','regular')
-- C:return_html(config['other']['status'],other_html)
-- return true
-- end
-- end
-- return false
-- end
function url_ext()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_ext'])
do
if ngx_match(uri,"\\."..rule.."$","isjo") then
if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then
C:write_log('url_ext','regular')
C:return_html(config['other']['status'],other_html)
C:return_html(config['other']['status'], other_html)
return true
end
end
@@ -555,7 +560,7 @@ function waf_cookie()
if not params["request_header"]['cookie'] then return false end
if type(params["request_header"]['cookie']) ~= "string" then return false end
request_cookie = string.lower(params["request_header"]['cookie'])
if C:is_ngx_match(cookie_rules,request_cookie,'cookie') then
if C:ngx_match_list(cookie_rules,request_cookie,'cookie') then
C:write_log('cookie','regular')
C:return_html(config['cookie']['status'],cookie_html)
return true
@@ -563,55 +568,45 @@ function waf_cookie()
return false
end
function waf_referer()
if params["method"] ~= "GET" then return false end
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(referer_local,params["request_header"]['Referer'],'args') then
C:write_log('get_referer','regular')
C:return_html(config['get']['status'], get_html)
return true
end
return false
end
function waf()
min_route()
-- white ip
if waf_ip_white() then return true end
waf_ip_black()
-- black ip
if waf_ip_black() then return true end
waf_drop()
waf_user_agent()
-- cc setting
if waf_drop() then return true end
if waf_cc() then return true end
waf_url()
-- ua check
if waf_user_agent() then return true end
if waf_url() then return true end
if params["method"] == "GET" then
waf_referer()
waf_cookie()
end
-- cookie检查
if waf_cookie() then return true end
-- args参数拦截
if waf_get_args() then return true end
if params["method"] == "POST" then
waf_referer()
waf_cookie()
end
-- 扫描软件禁止
if waf_scan_black() then return true end
waf_args()
waf_scan_black()
waf_post()
post_data_chekc()
local server_name = params["server_name"]
if site_config[server_name] then
X_Forwarded()
post_X_Forwarded()
php_path()
url_path()
url_ext()
url_rule_ex()
url_tell()
post_data()
if waf_post() then return true end
if post_data_chekc() then return true end
if site_config[server_name]['open'] then
if X_Forwarded() then return true end
if post_X_Forwarded() then return true end
-- url_path()
if url_ext() then return true end
-- url_rule_ex()
-- url_tell()
-- post_data()
end
end
+1 -1
View File
@@ -1 +1 @@
[[1, "(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)", "\u5173\u952e\u8bcd\u8fc7\u6ee41", 0]]
[[1,"(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)","关键词过滤1",0],[1,"(ApacheBench)","AB测试",0]]
+1 -1
View File
@@ -1 +1 @@
{"rules":{"user_agent":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}
{"rules":{"url_ext":0,"user_agent":0,"scan":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}
-309
View File
@@ -1,309 +0,0 @@
# coding:utf-8
import sys
import io
import os
import time
import subprocess
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'openresty'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def clearTemp():
path_bin = getServerDir() + "/nginx"
mw.execShell('rm -rf ' + path_bin + '/client_body_temp')
mw.execShell('rm -rf ' + path_bin + '/fastcgi_temp')
mw.execShell('rm -rf ' + path_bin + '/proxy_temp')
mw.execShell('rm -rf ' + path_bin + '/scgi_temp')
mw.execShell('rm -rf ' + path_bin + '/uwsgi_temp')
def getConf():
path = getServerDir() + "/nginx/conf/nginx.conf"
return path
def getConfTpl():
path = getPluginDir() + '/conf/nginx.conf'
return path
def getOs():
data = {}
data['os'] = mw.getOs()
ng_exe_bin = getServerDir() + "/nginx/sbin/nginx"
if checkAuthEq(ng_exe_bin, 'root'):
data['auth'] = True
else:
data['auth'] = False
return mw.getJson(data)
def getInitDTpl():
path = getPluginDir() + "/init.d/nginx.tpl"
return path
def makeConf():
vhost = getServerDir() + '/nginx/conf/vhost'
if not os.path.exists(vhost):
os.mkdir(vhost)
php_status = getServerDir() + '/nginx/conf/php_status'
if not os.path.exists(php_status):
os.mkdir(php_status)
def getFileOwner(filename):
import pwd
stat = os.lstat(filename)
uid = stat.st_uid
pw = pwd.getpwuid(uid)
return pw.pw_name
def checkAuthEq(file, owner='root'):
fowner = getFileOwner(file)
if (fowner == owner):
return True
return False
def confReplace():
service_path = os.path.dirname(os.getcwd())
content = mw.readFile(getConfTpl())
content = content.replace('{$SERVER_PATH}', service_path)
user = 'www'
user_group = 'www'
if mw.getOs() == 'darwin':
# macosx do
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
# user = 'root'
user_group = 'staff'
content = content.replace('{$EVENT_MODEL}', 'kqueue')
else:
content = content.replace('{$EVENT_MODEL}', 'epoll')
content = content.replace('{$OS_USER}', user)
content = content.replace('{$OS_USER_GROUP}', user_group)
nconf = getServerDir() + '/nginx/conf/nginx.conf'
__content = mw.readFile(nconf)
if __content.find('#user'):
mw.writeFile(getServerDir() + '/nginx/conf/nginx.conf', content)
# give nginx root permission
ng_exe_bin = getServerDir() + "/nginx/sbin/nginx"
if not checkAuthEq(ng_exe_bin, 'root'):
args = getArgs()
sudoPwd = args['pwd']
cmd_own = 'chown -R ' + 'root:' + user_group + ' ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_own))
cmd_mod = 'chmod 755 ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_mod))
cmd_s = 'chmod u+s ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_s))
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
# Openresty is not installed
if not os.path.exists(getServerDir()):
print("ok")
exit(0)
file_bin = initD_path + '/' + getPluginName()
if not os.path.exists(initD_path):
os.mkdir(initD_path)
# initd replace
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# config replace
confReplace()
# make nginx vhost or other
makeConf()
return file_bin
def status():
data = mw.execShell(
"ps -ef|grep nginx |grep -v grep | grep -v python | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def start():
file = initDreplace()
data = mw.execShell(file + ' start')
if data[1] == '':
return 'ok'
return data[1]
def stop():
file = initDreplace()
data = mw.execShell(file + ' stop')
clearTemp()
if data[1] == '':
return 'ok'
return data[1]
def restart():
file = initDreplace()
data = mw.execShell(file + ' restart')
if data[1] == '':
return 'ok'
return data[1]
def reload():
file = initDreplace()
data = mw.execShell(file + ' reload')
if data[1] == '':
return 'ok'
return data[1]
def initdStatus():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
return 'fail'
def initdInstall():
import shutil
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('chkconfig --add ' + getPluginName())
return 'ok'
def initdUinstall():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('chkconfig --del ' + getPluginName())
initd_bin = getInitDFile()
os.remove(initd_bin)
return 'ok'
def runInfo():
# 取Openresty负载状态
try:
result = mw.httpGet('http://127.0.0.1/nginx_status')
tmp = result.split()
data = {}
data['active'] = tmp[2]
data['accepts'] = tmp[9]
data['handled'] = tmp[7]
data['requests'] = tmp[8]
data['Reading'] = tmp[11]
data['Writing'] = tmp[13]
data['Waiting'] = tmp[15]
return mw.getJson(data)
except Exception as e:
return 'oprenresty not started'
def errorLogPath():
return getServerDir() + '/nginx/logs/error.log'
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'conf':
print(getConf())
elif func == 'get_os':
print(getOs())
elif func == 'run_info':
print(runInfo())
elif func == 'error_log':
print(errorLogPath())
else:
print('error')
+3
View File
@@ -13,7 +13,10 @@
</div>
</div>
<!-- <script type="text/javascript" src="/plugins/file?name=openresty&f=js/openresty.js"></script> -->
<script type="text/javascript">
$.getScript( "/plugins/file?name=openresty&f=js/openresty.js", function(){
orPluginService('openresty');
});
+29 -1
View File
@@ -4,6 +4,7 @@ import sys
import io
import os
import time
import threading
import subprocess
sys.path.append(os.getcwd() + "/class/core")
@@ -216,6 +217,33 @@ def restyOp(method):
return data[1]
def op_submit_systemctl_restart():
mw.execShell('systemctl restart openresty')
def op_submit_init_restart(file):
mw.execShell(file + ' restart')
def restyOp_restart():
file = initDreplace()
# 启动时,先检查一下配置文件
check = getServerDir() + "/bin/openresty -t"
check_data = mw.execShell(check)
if not check_data[1].find('test is successful') > -1:
return check_data[1]
if not mw.isAppleSystem():
threading.Timer(2, op_submit_systemctl_restart, args=()).start()
# submit_restart1()
return 'ok'
threading.Timer(2, op_submit_init_restart, args=(file,)).start()
# submit_restart2(file)
return 'ok'
def start():
return restyOp('start')
@@ -225,7 +253,7 @@ def stop():
def restart():
return restyOp('restart')
return restyOp_restart()
def reload():
+3 -2
View File
@@ -24,7 +24,6 @@ else
useradd -g www -s /bin/bash www
fi
# cd /www/server/mdserver-web/plugins/openresty && /bin/bash install.sh install 1.21.4.1
Install_openresty()
{
# ----- cpu start ------
@@ -59,10 +58,12 @@ Install_openresty()
# --with-openssl=$serverPath/source/lib/openssl-1.0.2q
cd ${openrestyDir}/openresty-${VERSION} && ./configure \
--prefix=$serverPath/openresty \
--with-ipv6 \
--with-http_v2_module \
--with-http_ssl_module \
--with-http_slice_module \
--with-http_stub_status_module
--with-http_stub_status_module \
--with-http_realip_module
make -j${cpuCore} && make install && make clean
+12 -253
View File
@@ -36,14 +36,14 @@ function orPluginSetService(_name ,status, version){
(status?'#20a53a;':'red;')+
' margin-left: 3px;" class="glyphicon ' + (status?'glyphicon glyphicon-play':'glyphicon-pause')+'"></span></p><div class="sfm-opt">\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\''+(status?'stop':'start')+'\',\''+version+'\')">'+(status?'停止':'启动')+'</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'restart\',\''+version+'\')">重启</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'restart\',\''+version+'\',\'yes\')">重启</button>\
<button class="btn btn-default btn-sm" onclick="orPluginOpService(\''+_name+'\',\'reload\',\''+version+'\')">重载配置</button>\
</div>';
$(".soft-man-con").html(serviceCon);
}
function orPluginOpService(a, b, v) {
function orPluginOpService(a, b, v,request_callback) {
var c = "name=" + a + "&func=" + b;
if(v != ''){
@@ -67,19 +67,25 @@ function orPluginOpService(a, b, v) {
layer.close(index);
var data = {'pwd':pwd};
c += '&args='+JSON.stringify(data);
orPluginOpServiceOp(a,b,c,d,a,v);
orPluginOpServiceOp(a,b,c,d,a,v,request_callback);
});
} else {
orPluginOpServiceOp(a,b,c,d,a,v);
orPluginOpServiceOp(a,b,c,d,a,v,request_callback);
}
});
})
}
function orPluginOpServiceOp(a,b,c,d,a,v){
function orPluginOpServiceOp(a,b,c,d,a,v,request_callback){
var request_path = "/plugins/run";
if (request_callback == 'yes'){
request_path = "/plugins/callback";
}
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0});
$.post("/plugins/run", c, function(g) {
$.post(request_path, c, function(g) {
layer.close(e);
var f = g.data == 'ok' ? msgTpl('{1}{2}服务已{3}',[a,v,d]) : msgTpl('{1}{2}服务{3}失败!',[a,v,d]);
@@ -97,9 +103,6 @@ function orPluginOpServiceOp(a,b,c,d,a,v){
layer.msg(g.data, {icon: 2,time: 10000,shade: 0.3});
}
// setTimeout(function(){
// location.reload();
// },2000);
},'json').error(function() {
layer.close(e);
layer.msg('操作异常!', {icon: 2});
@@ -131,247 +134,3 @@ function getOpenrestyStatus() {
}
},'json');
}
//nginx
function nginxSoftMain(name, version) {
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.get('/system?action=GetConcifInfo', function(rdata) {
layer.close(loadT);
nameA = rdata['web'];
var status = name == 'nginx' ? '<p onclick="GetNginxStatus()">' + lan.soft.nginx_status + '</p>' : '';
var menu = '';
if (version != undefined || version != '') {
var menu = '<p onclick="softChangeVer(\'' + name + '\',\'' + version + '\')">' + lan.soft.nginx_version + '</p>';
}
var waf = ''
if (name == 'nginx') {
waf = '<p onclick="waf()">' + lan.soft.waf_title + '</p>'
}
var logsPath = (name == 'nginx') ? '/www/wwwlogs/nginx_error.log' : '/www/wwwlogs/error_log';
layer.open({
type: 1,
area: '640px',
title: name + '管理',
closeBtn: 2,
shift: 0,
content: '<div class="bt-w-main" style="width:640px;">\
<div class="bt-w-menu">\
<p class="bgw" onclick="service(\'' + name + '\',' + nameA.status + ')">' + lan.soft.web_service + '</p>\
<p onclick="configChange(\'' + name + '\')">' + lan.soft.config_edit + '</p>\
' + waf + '\
' + menu + '\
' + status + '\
<p onclick="showLogs(\'' + logsPath + '\')">错误日志</p>\
</div>\
<div id="webEdit-con" class="bt-w-con pd15" style="height:555px;overflow:auto">\
<div class="soft-man-con"></div>\
</div>\
</div>'
});
service(name, nameA.status);
$(".bt-w-menu p").click(function() {
//var i = $(this).index();
$(this).addClass("bgw").siblings().removeClass("bgw");
});
});
}
//显示指定日志
function showLogs(logPath) {
var loadT = layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/ajax?action=GetOpeLogs', { path: logPath }, function(rdata) {
layer.close(loadT);
if (rdata.msg == '') rdata.msg = '当前没有日志!';
var ebody = '<div class="soft-man-con"><textarea readonly="" style="margin: 0px;width: 500px;height: 520px;background-color: #333;color:#fff; padding:0 5px" id="error_log">' + rdata.msg + '</textarea></div>';
$(".soft-man-con").html(ebody);
var ob = document.getElementById('error_log');
ob.scrollTop = ob.scrollHeight;
});
}
//WAF防火墙
function waf() {
var loadT = layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.get("/waf?action=GetConfig", function(rdata) {
layer.close(loadT);
if (rdata.status == -1) {
layer.msg(lan.soft.waf_not, { icon: 5, time: 5000 });
return;
}
var whiteList = ""
for (var i = 0; i < rdata.ipWhitelist.length; i++) {
if (rdata.ipWhitelist[i] == "") continue;
whiteList += "<tr><td>" + rdata.ipWhitelist[i] + "</td><td><a href=\"javascript:deleteWafKey('ipWhitelist','" + rdata.ipWhitelist[i] + "');\">" + lan.public.del + "</a></td></tr>";
}
var blackList = ""
for (var i = 0; i < rdata.ipBlocklist.length; i++) {
if (rdata.ipBlocklist[i] == "") continue;
blackList += "<tr><td>" + rdata.ipBlocklist[i] + "</td><td><a href=\"javascript:deleteWafKey('ipBlocklist','" + rdata.ipBlocklist[i] + "');\">" + lan.public.del + "</a></td></tr>";
}
var cc = rdata.CCrate.split('/')
var con = "<div class='wafConf'>\
<div class='wafConf-btn'>\
<span>" + lan.soft.waf_title + "</span><div class='ssh-item'>\
<input class='btswitch btswitch-ios' id='closeWaf' type='checkbox' " + (rdata.status == 1 ? 'checked' : '') + ">\
<label class='btswitch-btn' for='closeWaf' onclick='CloseWaf()'></label>\
</div>\
<div class='pull-right'>\
<button class='btn btn-default btn-sm' onclick='gzEdit()'>" + lan.soft.waf_edit + "</button>\
<button class='btn btn-default btn-sm' onclick='upLimit()'>" + lan.soft.waf_up_title + "</button>\
</div>\
</div>\
<div class='wafConf_checkbox label-input-group ptb10 relative'>\
<input type='checkbox' id='waf_UrlDeny' " + (rdata['UrlDeny'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('UrlDeny','" + (rdata['UrlDeny'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_UrlDeny'>" + lan.soft.waf_input1 + "</label>\
<input type='checkbox' id='waf_CookieMatch' " + (rdata['CookieMatch'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('CookieMatch','" + (rdata['CookieMatch'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_CookieMatch'>" + lan.soft.waf_input2 + "</label>\
<input type='checkbox' id='waf_postMatch' " + (rdata['postMatch'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('postMatch','" + (rdata['postMatch'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_postMatch'>" + lan.soft.waf_input3 + "</label>\
<input type='checkbox' id='waf_CCDeny' " + (rdata['CCDeny'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('CCDeny','" + (rdata['CCDeny'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_CCDeny'>" + lan.soft.waf_input4 + "</label>\
<input type='checkbox' id='waf_attacklog' " + (rdata['attacklog'] == 'on' ? 'checked' : '') + " onclick=\"SetWafConfig('attacklog','" + (rdata['attacklog'] == 'on' ? 'off' : 'on') + "')\" /><label for='waf_attacklog'>" + lan.soft.waf_input5 + "</label>\
<span class='glyphicon glyphicon-folder-open' style='position: absolute; right: 10px; top: 12px; color: orange;cursor: pointer' onclick='openPath(\"/www/wwwlogs/waf\")'></span>\
</div>\
<div class='wafConf_cc'>\
<span>" + lan.soft.waf_input6 + "</span><input id='CCrate_1' class='bt-input-text' type='number' value='" + cc[0] + "' style='width:80px;margin-right:30px'/>\
<span>" + lan.soft.waf_input7 + "(" + lan.bt.s + ")</span><input id='CCrate_2' class='bt-input-text' type='number' value='" + cc[1] + "' style='width:80px;'/>\
<button onclick=\"SetWafConfig('CCrate','')\" class='btn btn-default btn-sm'>" + lan.public.ok + "</button>\
</div>\
<div class='wafConf_ip'>\
<fieldset>\
<legend>" + lan.soft.waf_input8 + "</legend>\
<input type='text' id='ipWhitelist_val' class='bt-input-text mr5' placeholder='" + lan.soft.waf_ip + "' style='width:175px;' /><button onclick=\"addWafKey('ipWhitelist')\" class='btn btn-default btn-sm'>" + lan.public.add + "</button>\
<div class='table-overflow'><table class='table table-hover'>" + whiteList + "</table></div>\
</fieldset>\
<fieldset>\
<legend>" + lan.soft.waf_input9 + "</legend>\
<input type='text' id='ipBlocklist_val' class='bt-input-text mr5' placeholder='" + lan.soft.waf_ip + "' style='width:175px;' /><button onclick=\"addWafKey('ipBlocklist')\" class='btn btn-default btn-sm'>" + lan.public.add + "</button>\
<div class='table-overflow'><table class='table table-hover'>" + blackList + "</table></div>\
</fieldset>\
</div>\
</div>"
$(".soft-man-con").html(con);
});
}
//上传限制
function upLimit() {
var loadT = layer.msg(lan.public.the_get, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.get("/waf?action=GetConfig", function(rdata) {
layer.close(loadT);
var black_fileExt = ''
for (var i = 0; i < rdata.black_fileExt.length; i++) {
black_fileExt += "<tr><td>" + rdata.black_fileExt[i] + "</td><td><a style='float:right;' href=\"javascript:deleteWafKey('black_fileExt','" + rdata.black_fileExt[i] + "');\">" + lan.public.del + "</a></td></tr>";
}
if ($("#blacktable").html() != undefined) {
$("#blacktable").html(black_fileExt);
$("#black_fileExt_val").val('');
return;
}
layer.open({
type: 1,
area: '300px',
title: lan.soft.waf_up_title,
closeBtn: 2,
shift: 0,
content: "<div class='dirBinding mlr15'>" +
"<input class='bt-input-text mr5' type='text' placeholder='" + lan.soft.waf_up_from1 + "' id='black_fileExt_val' style='height: 28px; border-radius: 3px;width: 219px;margin-top:15px' />" +
"<button class='btn btn-success btn-sm' onclick=\"addWafKey('black_fileExt')\">" + lan.public.add + "</button>" +
"</div>" +
"<div class='divtable' style='margin:15px'><table class='table table-hover' width='100%' style='margin-bottom:0'>" +
"<thead><tr><th>" + lan.soft.waf_up_from2 + "</th><th width='100' class='text-right'>" + lan.public.action + "</th></tr></thead>" +
"<tbody id='blacktable'>" + black_fileExt + "</tbody>" +
"</table></div>"
});
});
}
//设置waf状态
function closeWaf() {
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/waf?action=SetStatus', '', function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
if (rdata.status) waf();
});
}
//取规则文件
function getWafFile(name) {
onlineEditFile(0, '/www/server/panel/vhost/wafconf/' + name);
}
//规则编辑
function gzEdit() {
layer.open({
type: 1,
area: '360px',
title: lan.soft.waf_edit,
closeBtn: 2,
shift: 0,
content: "<div class='gzEdit'><button class='btn btn-default btn-sm' onclick=\"GetWafFile('cookie')\">Cookie</button>\
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('post')\">POST</button>\
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('url')\">URL</button>\
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('user-agent')\">User-Agent</button>\
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('args')\">Args</button>\
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('whiteurl')\">" + lan.soft.waf_url_white + "</button>\
<button class='btn btn-default btn-sm' onclick=\"GetWafFile('returnhtml')\">" + lan.soft.waf_index + "</button>\
<button class='btn btn-default btn-sm' onclick=\"updateWaf('returnhtml')\">" + lan.soft.waf_cloud + "</button></div>"
});
}
//更新WAF规则
function updateWaf() {
var loadT = layer.msg(lan.soft.waf_update, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/waf?action=updateWaf', '', function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
});
}
//设置WAF配置值
function setWafConfig(name, value) {
if (name == 'CCrate') {
var CCrate_1 = $("#CCrate_1").val();
var CCrate_2 = $("#CCrate_2").val();
if (CCrate_1 < 1 || CCrate_1 > 3000 || CCrate_2 < 1 || CCrate_2 > 1800) {
layer.msg(lan.soft.waf_cc_err, { icon: 5 });
return;
}
value = CCrate_1 + '/' + CCrate_2;
}
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/waf?action=SetConfigString', 'name=' + name + '&value=' + value, function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
if (rdata.status) waf();
});
}
//删除WAF指定值
function deleteWafKey(name, value) {
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/waf?action=SetConfigList&act=del', 'name=' + name + '&value=' + value, function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
if (rdata.status) waf();
if (name == 'black_fileExt') upLimit();
});
}
//删除WAF指定值
function addWafKey(name) {
var value = $('#' + name + '_val').val();
var loadT = layer.msg(lan.public.the, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/waf?action=SetConfigList&act=add', 'name=' + name + '&value=' + value, function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
if (rdata.status) waf();
if (name == 'black_fileExt') upLimit();
});
}
+39
View File
@@ -1,3 +1,41 @@
<style type="text/css">
.bt-w-main{
height: 600px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
@@ -13,6 +51,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
+185 -3
View File
@@ -417,8 +417,8 @@ def setFpmConfig(version):
max_spare_servers = args['max_spare_servers']
pm = args['pm']
file = getServerDir() + '/php' + version + '/php-fpm.d/www.conf'
conf = mw.readFile(file)
filefpm = getFpmConfFile(version)
conf = mw.readFile(filefpm)
rep = "\s*pm.max_children\s*=\s*([0-9]+)\s*"
conf = re.sub(rep, "\npm.max_children = " + max_children, conf)
@@ -437,7 +437,7 @@ def setFpmConfig(version):
rep = "\s*pm\s*=\s*(\w+)\s*"
conf = re.sub(rep, "\npm = " + pm + "\n", conf)
mw.writeFile(file, conf)
mw.writeFile(filefpm, conf)
reload(version)
msg = mw.getInfo('设置PHP-{1}并发设置,max_children={2},start_servers={3},min_spare_servers={4},max_spare_servers={5}',
@@ -490,6 +490,180 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
content = mw.execShell(
'cat /etc/php/' + version + '/fpm/conf.d/*' + " | grep -v '^;' |tr -s '\n'")
content = content[0]
if save_handler == "memcached":
if not re.search("memcached.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "memcache":
if not content.find('memcache') > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "redis":
if not content.find('redis') > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
mw.writeFile(filename, phpini)
reload(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = ["/tmp", "/var/lib/php/sessions", session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version):
filename = getConf(version)
if not os.path.exists(filename):
@@ -688,6 +862,14 @@ if __name__ == "__main__":
print(setFpmConfig(version))
elif func == 'get_fpm_status':
print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func':
print(getDisableFunc(version))
elif func == 'set_disable_func':
+145
View File
@@ -368,6 +368,151 @@ function disableFunc(version) {
$(".soft-man-con").html(con);
});
}
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//设置禁用函数
function setDisableFunc(version, act, fs) {
var fsArr = fs.split(',');
+20
View File
@@ -2,6 +2,11 @@
{
"name": "pdo",
"versions": [
"56",
"70",
"71",
"72",
"73",
"74",
"80",
"81",
@@ -16,6 +21,11 @@
"name": "mysqlnd",
"versions": [
"56",
"70",
"71",
"72",
"73",
"74",
"80",
"81",
"82"
@@ -29,6 +39,11 @@
"name": "sqlite3",
"versions": [
"56",
"70",
"71",
"72",
"73",
"74",
"80",
"81",
"82"
@@ -50,6 +65,11 @@
"name": "odbc",
"versions": [
"56",
"70",
"71",
"72",
"73",
"74",
"80",
"81",
"82"
-12
View File
@@ -3,18 +3,6 @@ export PATH=$PATH:/opt/local/bin:/opt/local/sbin:/opt/local/share/man:/usr/local
DIR=$(cd "$(dirname "$0")"; pwd)
# cd /www/server/mdserver-web/scripts/quick && bash debug.sh
# cd /www/server/mdserver-web/plugins/php && bash all_test.sh
# cd /www/server/mdserver-web/plugins/php && bash install.sh install 71
# cd /www/server/mdserver-web/plugins/php/versions/52/ && bash gd.sh install 52
# cd /www/server/mdserver-web/plugins/php/versions/52/ && bash openssl.sh install 52
# cd /www/server/mdserver-web/plugins/php/versions/81/ && bash imagemagick.sh install 81
# cd /www/server/mdserver-web/plugins/php/versions/70/ && bash imagemagick.sh install 70
PHP_VER=71
echo "php${PHP_VER} -- start"
cmd_ext=$(ls -l $DIR/versions/$PHP_VER/ |awk '{print $9}')
+38
View File
@@ -1,3 +1,40 @@
<style type="text/css">
.bt-w-main{
height: 600px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
@@ -13,6 +50,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>

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