Compare commits

..
304 Commits
Author SHA1 Message Date
Mr Chen 265e17beac Merge pull request #393 from midoks/dev
0.13.3
2023-03-16 13:00:56 +08:00
midoks f3d83ad8a5 Update README.md 2023-03-16 12:58:06 +08:00
midoks 39b376a7cb Update webstats_common.lua 2023-03-16 12:24:02 +08:00
midoks 07858794ef Update webstats_common.lua 2023-03-16 12:02:33 +08:00
midoks 391473fc14 Update lib.sh 2023-03-15 23:26:23 +08:00
midoks 0993adcc5f Update lib.sh 2023-03-15 23:24:47 +08:00
midoks 90b1d88111 Update lib.sh 2023-03-15 23:17:49 +08:00
midoks 87098cff95 up 2023-03-15 23:00:37 +08:00
midoks e6e64b2a4c Update mysql.js 2023-03-15 22:59:23 +08:00
midoks 81436ea81b Update index.html 2023-03-15 22:57:22 +08:00
midoks cf7d29190d Update index.html 2023-03-15 22:53:36 +08:00
midoks 4ff62ec6ad Update tgbot.py 2023-03-15 22:09:53 +08:00
midoks dac3ccce8d Update tgbot.py 2023-03-15 21:53:41 +08:00
midoks 10bd7aa70f Update tool_migrate.py 2023-03-15 18:28:31 +08:00
midoks dec0afc3d3 Update tool_migrate.py 2023-03-15 18:25:43 +08:00
midoks 2331853b3b Update info.json 2023-03-15 18:13:34 +08:00
midoks b9e063e423 Update README.md 2023-03-15 18:11:35 +08:00
midoks 52294948b2 Update config_api.py 2023-03-15 18:09:20 +08:00
midoks 87bec2b988 Update tgbot.py 2023-03-15 18:06:14 +08:00
midoks 9ab91ecc93 Update index.py 2023-03-15 17:48:05 +08:00
midoks 18312a3596 Update tgbot.py 2023-03-15 17:37:35 +08:00
midoks 8fb35440c8 Update info.json 2023-03-15 17:35:28 +08:00
midoks a874934379 Update receive_faq.py 2023-03-15 17:34:05 +08:00
midoks 2c4e4aea3f Update info.json 2023-03-15 17:22:36 +08:00
midoks 6b115261be up 2023-03-15 17:19:15 +08:00
midoks 059ce6228b Update receive_faq.py 2023-03-15 15:09:03 +08:00
midoks cfa396b4bb 更新 2023-03-14 20:03:53 +08:00
midoks 11e4b377ed up 2023-03-14 15:21:33 +08:00
midoks 31fe2aab92 Update receive_faq.py 2023-03-14 13:36:00 +08:00
midoks 19042a9088 Update receive_faq.py 2023-03-14 11:48:54 +08:00
midoks 2eb4543c3b Update receive_faq.py 2023-03-14 01:54:58 +08:00
midoks e33ccbfc7d Update tgbot.py 2023-03-14 01:54:08 +08:00
midoks ed8c9eed0a Update receive_faq.py 2023-03-14 01:50:56 +08:00
midoks 7163a7bbcf Update receive_faq.py 2023-03-14 01:46:19 +08:00
midoks 3f1c23ec8b Update receive_faq.py 2023-03-14 01:32:52 +08:00
midoks 3a6cb0ae2a Update receive_faq.py 2023-03-14 01:15:14 +08:00
midoks 936492d410 up 2023-03-14 01:10:04 +08:00
midoks 39d265aae7 Update tgbot.py 2023-03-14 00:15:27 +08:00
midoks 5a33098dd3 Update tgbot.py 2023-03-14 00:09:52 +08:00
midoks c9927c3fb9 tgbot加入扩展机制 2023-03-14 00:09:30 +08:00
midoks da90386816 Update tool_migrate.py 2023-03-13 11:29:00 +08:00
midoks 6be4c5977b up 2023-03-13 02:33:29 +08:00
midoks bbf93bfd9e up 2023-03-13 02:33:22 +08:00
midoks a2570af5f7 Update webstats_common.lua 2023-03-13 01:33:07 +08:00
midoks 77120cf31b up 2023-03-12 12:13:43 +08:00
midoks 395f449b93 Update webstats_common.lua 2023-03-12 12:09:53 +08:00
midoks 8be5f4aa7b Update info.json 2023-03-11 22:54:23 +08:00
midoks 3ccebf4f47 Update index.py 2023-03-11 22:48:42 +08:00
midoks 15d48accad Update tgbot.py 2023-03-11 22:43:15 +08:00
midoks d0045d831c Update tgbot.py 2023-03-11 22:42:39 +08:00
midoks a7cac3d671 up 2023-03-11 20:47:31 +08:00
midoks 7bc7fdecae Update webstats_common.lua 2023-03-11 16:40:45 +08:00
midoks 480663e2ad Update tools.py 2023-03-11 15:41:15 +08:00
midoks 2290efd060 Update config_api.py 2023-03-11 15:36:11 +08:00
midoks dece5a0532 Update config_api.py 2023-03-11 15:30:16 +08:00
midoks b0a44d24d4 Update config_api.py 2023-03-11 15:28:13 +08:00
midoks d092d9f5f2 up 2023-03-11 15:24:40 +08:00
midoks 944b3e779c Update config_api.py 2023-03-11 15:21:43 +08:00
midoks 55dc2715e9 Update config_api.py 2023-03-11 15:20:13 +08:00
midoks 84bf3abd5d Update config_api.py 2023-03-11 15:15:49 +08:00
midoks 00c9157f9b up 2023-03-11 15:15:27 +08:00
midoks faa95b0d88 Update config_api.py 2023-03-11 15:07:06 +08:00
midoks 52d0b3c940 Update config_api.py 2023-03-11 15:04:20 +08:00
midoks 0141028d41 Update config_api.py 2023-03-11 15:02:15 +08:00
midoks 9e6bf08a72 Update config_api.py 2023-03-11 15:01:46 +08:00
midoks 49ff9750cb Update config_api.py 2023-03-11 14:58:18 +08:00
midoks 75b2b4dbc2 Update config_api.py 2023-03-11 14:56:43 +08:00
midoks 667c60dda0 Update config.js 2023-03-11 14:55:48 +08:00
midoks aa6818f953 Update config_api.py 2023-03-11 14:52:58 +08:00
midoks 6f884fe60a panel ssl https 功能添加 2023-03-11 14:48:38 +08:00
midoks a56d53c672 Update config_api.py 2023-03-11 14:29:28 +08:00
midoks 00b1788172 up 2023-03-11 14:26:22 +08:00
midoks cee268fcbc Update config_api.py 2023-03-11 13:56:20 +08:00
midoks 40dd929823 Update config_api.py 2023-03-11 13:47:16 +08:00
midoks b59949e181 Update config_api.py 2023-03-11 13:41:36 +08:00
midoks 9c5975253a Update cert_api.py 2023-03-11 13:23:30 +08:00
midoks 62003b987a Update discuzx.conf 2023-03-10 14:12:27 +08:00
midoks df0a454c3a up 2023-03-10 14:09:40 +08:00
midoks 02048c3265 Update webstats_common.lua 2023-03-10 13:19:58 +08:00
midoks 65649d171d Update tgbot.py 2023-03-09 19:11:51 +08:00
midoks a136da6ec2 Update tgbot.py 2023-03-09 17:23:28 +08:00
midoks 3b25ca7e60 Update tgbot.py 2023-03-09 16:28:11 +08:00
midoks c5cf8f8afb Update info.json 2023-03-09 15:40:54 +08:00
midoks 89f7d464ab Update info.json 2023-03-09 15:28:00 +08:00
midoks 4cac6d1921 Update info.json 2023-03-09 15:25:37 +08:00
midoks dca5c82d2f Update webstats_common.lua 2023-03-09 14:56:43 +08:00
midoks 08988130b5 Update config_api.py 2023-03-09 03:00:30 +08:00
Mr Chen 8849001384 Merge pull request #392 from midoks/dev
升级图表echarts
2023-03-09 02:49:57 +08:00
midoks ae0a6b5079 升级图表echarts 2023-03-09 02:44:57 +08:00
Mr Chen d6c6ae5561 Merge pull request #391 from midoks/dev
0.13.2
2023-03-09 01:49:10 +08:00
midoks a6dc15f22d 0.13.2
* supervisor添加重启功能。
* 加入滚动写入日志 mw.writeFileLog方法。
* mysql导出优化优化。
* 添加tgbot插件[仅测试]。
* TelegramBot机器人通知-加入配置。
* mariadb更新版本。
* 在线文件编辑优化。
2023-03-09 01:47:35 +08:00
midoks 360b962bd2 Update mw.py 2023-03-09 01:42:55 +08:00
midoks 37d37e0f1d Update task.py 2023-03-09 01:32:05 +08:00
midoks ddc6da9172 Update mw.py 2023-03-09 01:30:19 +08:00
midoks ceba7ab673 up 2023-03-09 01:26:39 +08:00
midoks 384704b8e5 Update mw.py 2023-03-09 01:10:04 +08:00
midoks 232d0c2f74 Update mw.py 2023-03-09 01:01:00 +08:00
midoks ef8e6f07f5 Update mw.py 2023-03-09 00:43:34 +08:00
midoks 435e565559 Update mw.py 2023-03-09 00:42:15 +08:00
midoks ec9d7e337d Update mw.py 2023-03-09 00:36:46 +08:00
midoks b5c7a2a778 Update task.py 2023-03-09 00:32:23 +08:00
midoks 72d9c9b761 Update task.py 2023-03-09 00:28:59 +08:00
midoks 30812e1fba Update task.py 2023-03-09 00:08:49 +08:00
midoks c95cb07e8d Update task.py 2023-03-09 00:05:45 +08:00
midoks f3f2ea8ef0 通知限制频率 2023-03-08 19:40:23 +08:00
midoks 9e5a5192cb Update mw.py 2023-03-08 18:02:30 +08:00
midoks 271b3d448c Update mw.py 2023-03-08 18:01:06 +08:00
midoks b7424e7195 Update config_api.py 2023-03-08 17:57:23 +08:00
midoks b607527e1f Update config_api.py 2023-03-08 17:56:18 +08:00
midoks 3c42a4e450 对通知配置进行加密处理 2023-03-08 17:56:07 +08:00
midoks b11fd9508a Update .gitignore 2023-03-08 17:29:42 +08:00
midoks dc0504cf24 Delete notify.json 2023-03-08 17:25:12 +08:00
midoks 1d8b82395f Update public.js 2023-03-08 16:25:30 +08:00
midoks 39ac55760e Update config_api.py 2023-03-08 16:20:02 +08:00
midoks ef6071956d 在线文件编辑优化 2023-03-08 16:14:28 +08:00
midoks bbbe1c84ce Update mw.py 2023-03-07 19:24:03 +08:00
midoks 064252daad Update config.html 2023-03-07 19:20:07 +08:00
midoks 3cb63c6265 Update index.html 2023-03-07 16:28:48 +08:00
midoks b541abad42 Update index.py 2023-03-07 13:44:28 +08:00
midoks 547027be0d Update install.sh 2023-03-06 23:40:56 +08:00
midoks d786b2524a up 2023-03-06 23:21:55 +08:00
midoks abac345628 Update info.json 2023-03-06 23:10:12 +08:00
midoks d4290cbdd2 mariadb更新版本 2023-03-06 22:29:20 +08:00
midoks cfd2d99e24 Update mw.py 2023-03-06 21:31:24 +08:00
midoks 28437ccfb0 Update mw.py 2023-03-06 21:30:18 +08:00
midoks 43bf755609 Update mw.py 2023-03-06 20:35:06 +08:00
midoks de225fc8b9 0.13.1.2 2023-03-06 20:28:29 +08:00
midoks 44f891f7a3 Update mw.py 2023-03-06 20:12:52 +08:00
midoks 64d1387b03 Telegram Bot机器人通知 加入配置 2023-03-06 19:32:36 +08:00
midoks 51ccbefb04 up 2023-03-06 17:15:41 +08:00
midoks 29e3017e51 up 2023-03-06 16:49:42 +08:00
midoks 197e2d80c6 Update tgbot.py 2023-03-06 16:42:29 +08:00
midoks b8f04043bc Update tgbot.service.tpl 2023-03-06 16:41:25 +08:00
midoks 2ed70b4b96 Update tgbot.py 2023-03-06 16:39:27 +08:00
midoks d056c37be5 Update index.py 2023-03-06 16:33:18 +08:00
midoks e75abae4b9 Update tgbot.service.tpl 2023-03-06 16:32:05 +08:00
midoks 3e695770d7 Update config_api.py 2023-03-06 16:26:49 +08:00
midoks 7301edbc5a 添加tgbot插件
现在只是为了获取chat_id
2023-03-06 16:19:13 +08:00
Mr Chen 704b256408 Merge pull request #390 from midoks/dev
网站统计优化
2023-03-05 18:36:57 +08:00
midoks e129051a06 Update webstats_common.lua 2023-03-05 18:34:35 +08:00
Mr Chen d38e9f7ad0 Merge pull request #389 from midoks/dev
OP防火墙优化
2023-03-05 18:07:54 +08:00
midoks c696742866 Update init.lua 2023-03-05 18:03:41 +08:00
midoks 046389df99 Update init.lua 2023-03-05 17:37:01 +08:00
midoks 3e244ed227 导出优化 2023-03-05 14:04:16 +08:00
midoks 5016aedb0f Update index.py 2023-03-05 02:08:04 +08:00
midoks c1cd45a5f3 Update my8.0.cnf 2023-03-05 00:00:59 +08:00
midoks 79c9865a5d Update index.py 2023-03-04 23:53:54 +08:00
midoks 4082f29424 加入滚动写入日志 2023-03-04 23:07:23 +08:00
midoks d777a29d8c Update update.sh 2023-03-04 21:47:12 +08:00
Mr Chen 04e43e051e Merge pull request #388 from midoks/dev
局部优化
2023-03-02 16:57:17 +08:00
midoks dffe9a77e7 Update layout.html 2023-03-02 00:57:02 +08:00
midoks 1b1462586e Update orm.py 2023-03-02 00:49:44 +08:00
midoks f11d2db761 添加重启功能 2023-03-01 18:41:32 +08:00
midoks 842c16540a Update index.py 2023-03-01 18:03:14 +08:00
midoks 614cc1032f Update webstats_log.lua 2023-03-01 14:03:46 +08:00
midoks ad46b2050e Update config.json 2023-03-01 01:40:57 +08:00
midoks 8109989927 Update layout.html 2023-02-28 19:41:13 +08:00
Mr Chen 9d9b39dfe2 Merge pull request #387 from midoks/dev
0.13.1
2023-02-28 19:11:06 +08:00
midoks 422514c40a 0.13.1
* 关闭issue,建立bbs.midoks.me。问题集中处理,发挥群众的力量。
* 添加站操作回调钩子site_cb。 网站统计和OP防火墙不再手动重载配置
* 修复ubuntu20 pureftp 安装时,端口没有加入安全里
* 增加global_static hook关键字,并优化menu的文件加载hook
* 各种细节优化。
2023-02-28 19:09:54 +08:00
midoks 632568643b Update site_api.py 2023-02-28 17:08:26 +08:00
midoks a5f29a2a6a Update cert_api.py 2023-02-28 16:26:31 +08:00
midoks b02705aa5a up 2023-02-28 03:00:46 +08:00
midoks 1f9ab560e3 Update files.js 2023-02-28 02:18:39 +08:00
midoks b3970326cd Update index.py 2023-02-28 01:57:19 +08:00
midoks f6d008e0b6 Update index.py 2023-02-28 01:50:54 +08:00
midoks 6f9a49ad7a up 2023-02-28 01:48:51 +08:00
midoks fc3c7d334a Update public.js 2023-02-28 00:17:39 +08:00
midoks 1030d1b923 site_cb 添加站操作回调钩子。 网站统计和OP防火墙不再手动重载配置 2023-02-28 00:02:16 +08:00
midoks 94d4a90bcc Update webstats_common.lua 2023-02-27 19:35:52 +08:00
midoks da4b872666 Update README.md 2023-02-27 17:57:17 +08:00
midoks cf15b19f4b Update install.sh 2023-02-26 21:46:25 +08:00
midoks aa9cdaada4 Update commit.tpl 2023-02-26 03:16:45 +08:00
midoks 659c9fe16b 修复ubuntu 20 pureftp 安装时,端口没有加入安全里 2023-02-26 02:20:06 +08:00
midoks 2b8c6d6e43 Update firewall_api.py 2023-02-26 01:39:52 +08:00
midoks 263f83088f Update firewall_api.py 2023-02-26 01:38:55 +08:00
midoks 374c938ac0 Update firewall_api.py 2023-02-26 01:38:32 +08:00
midoks 6aa73b0cae Update firewall_api.py 2023-02-26 01:36:45 +08:00
midoks 7f731ae06f Update README.md 2023-02-26 01:12:08 +08:00
midoks f87aff704c Update rhel.sh 2023-02-25 23:36:14 +08:00
midoks be9fa87133 Update rhel.sh 2023-02-25 23:31:36 +08:00
midoks de6fc19dee Create discuz.conf 2023-02-25 21:33:50 +08:00
midoks 3987c6d3dc Update config_api.py 2023-02-25 08:37:26 +08:00
midoks 96875052cd Update index.py 2023-02-25 08:25:05 +08:00
midoks 583de57f96 Update plugins_api.py 2023-02-25 08:21:20 +08:00
midoks 41b7245f03 Update plugins_api.py 2023-02-25 08:15:38 +08:00
midoks ee3684706f Update info.json 2023-02-25 07:48:32 +08:00
midoks 07936dfb81 update 2023-02-25 07:35:46 +08:00
midoks 5c46202be0 增加global_static hook关键字,并优化menu的文件加载hook
"hook":[
		{
			"tag":"global_static",
			"global_static": {
				"css_path":"menu/own_style.css",
				"js_path":"js/own_style.js"
			}
		}
	],
2023-02-25 07:26:48 +08:00
midoks 7123a15457 Update install.sh 2023-02-24 18:08:46 +08:00
midoks 4aeb45b1d5 Update install.sh 2023-02-24 17:55:13 +08:00
midoks 006a62be22 Update lib.sh 2023-02-24 17:25:04 +08:00
midoks 1e91d11125 Update mw.tpl 2023-02-24 17:22:22 +08:00
midoks 99fb4aa723 up 2023-02-24 17:14:28 +08:00
midoks 5c5bbb2da2 up 2023-02-24 17:12:31 +08:00
midoks 8b05045901 Update install.sh 2023-02-24 17:07:24 +08:00
midoks 1b73439525 Update install_dev.sh 2023-02-24 17:00:10 +08:00
midoks ec51ad016a Update install_dev.sh 2023-02-24 16:57:24 +08:00
midoks a42fae66ac Update install_dev.sh 2023-02-24 16:53:48 +08:00
midoks b4c635c2e5 Update install_dev.sh 2023-02-24 16:49:03 +08:00
midoks 9802bc5915 Update pure-ftpd.conf 2023-02-24 13:29:16 +08:00
Mr Chen 196fbbdd7d Merge pull request #382 from midoks/dev
0.13.0
2023-02-24 05:59:59 +08:00
midoks fa278abd50 Update index.py 2023-02-24 05:53:33 +08:00
midoks f9b2dbcb5e Update index.py 2023-02-24 05:46:39 +08:00
midoks a8808be9ae Update index.py 2023-02-24 05:41:50 +08:00
midoks 4122de13e3 Update index.py 2023-02-24 05:39:52 +08:00
midoks 4acae8e5f5 up 2023-02-24 05:38:59 +08:00
midoks 1abb611c3e 版本更新 0.13.0 2023-02-24 05:17:44 +08:00
midoks 726f9fa0d2 #374 2023-02-24 04:15:23 +08:00
midoks cfb64caadc Update site_api.py 2023-02-24 04:09:50 +08:00
midoks f501dd5150 Update site_api.py 2023-02-24 04:07:19 +08:00
midoks d1fe006e39 Update site_api.py 2023-02-24 03:28:48 +08:00
midoks d4db5dbfac up 2023-02-24 03:28:18 +08:00
midoks efa512a3f6 #374 2023-02-24 03:16:52 +08:00
midoks b53436343d up 2023-02-24 02:40:09 +08:00
midoks bb1a634f3c Update site_api.py 2023-02-24 02:29:14 +08:00
midoks acda55cc55 Update index.py 2023-02-24 01:40:02 +08:00
midoks 0ff0728517 Update index.py 2023-02-24 01:30:17 +08:00
midoks c575f55354 Update app.js 2023-02-24 01:05:32 +08:00
midoks d58339dbcb Update index.py 2023-02-24 00:07:19 +08:00
midoks f6a18fa25f Update index.py 2023-02-24 00:03:48 +08:00
midoks 3016eff372 Update app.js 2023-02-23 17:29:38 +08:00
midoks ca518591f3 up 2023-02-23 17:27:15 +08:00
midoks d2c74f2243 up 2023-02-23 17:17:46 +08:00
midoks 71dbf8e359 Update app.js 2023-02-23 15:39:16 +08:00
midoks cb2ad0ca82 up 2023-02-23 15:18:44 +08:00
midoks a157db7879 Update index.py 2023-02-23 03:32:30 +08:00
midoks fb949f4ee6 up 2023-02-23 01:25:00 +08:00
midoks b91ae3fde2 Update index.py 2023-02-22 23:46:28 +08:00
midoks b508e8003b Update index.py 2023-02-22 23:13:44 +08:00
midoks 0632a4b535 Update index.py 2023-02-22 23:13:17 +08:00
midoks 397e0b89a5 Update index.py 2023-02-22 22:59:45 +08:00
midoks 2427bf81cd Update index.py 2023-02-22 22:44:16 +08:00
midoks 4179bbf580 Update index.py 2023-02-22 22:40:29 +08:00
midoks b93c3bb88e Update index.py 2023-02-22 22:37:19 +08:00
midoks a52c854afd Update index.py 2023-02-22 22:36:10 +08:00
midoks d7e5cf1f45 Update index.py 2023-02-22 21:55:49 +08:00
midoks cfb444deac Update files_api.py 2023-02-22 20:54:54 +08:00
midoks 78615451ac up 2023-02-22 20:52:12 +08:00
midoks 0134643c83 Update db.py 2023-02-22 18:18:40 +08:00
midoks 70ddd1c86f Update index.py 2023-02-22 17:55:17 +08:00
midoks 808dc743ef Update files_api.py 2023-02-22 14:59:40 +08:00
midoks e30693f9f2 Update files_api.py 2023-02-22 14:28:01 +08:00
midoks 5c97fbe011 Update __init__.py 2023-02-22 14:27:48 +08:00
midoks 6419a18525 up 2023-02-21 21:10:34 +08:00
midoks 4a804e9243 Update index.py 2023-02-19 18:12:08 +08:00
midoks d44526004f up 2023-02-19 18:02:26 +08:00
midoks c1f402b278 up 2023-02-19 00:10:06 +08:00
midoks 45a3eec1b5 Update install_dev.sh 2023-02-18 23:09:51 +08:00
midoks d6f41ceb6a Update install_dev.sh 2023-02-18 23:06:53 +08:00
midoks a1bc0f6faf Update install_dev.sh 2023-02-18 22:58:21 +08:00
midoks 8420961cf7 Update install_dev.sh 2023-02-18 22:54:58 +08:00
midoks 421594c01d Update install_dev.sh 2023-02-18 22:48:30 +08:00
midoks ca13e8ad77 Update install_dev.sh 2023-02-18 22:46:05 +08:00
midoks f161f24253 up 2023-02-18 22:44:42 +08:00
midoks e5ab03951f Update README.md 2023-02-18 22:08:13 +08:00
midoks 5b45bab36d Update install_dev.sh 2023-02-18 22:06:51 +08:00
midoks 0594d3f9ce Update README.md 2023-02-18 22:04:11 +08:00
midoks ad541216c5 up 2023-02-18 16:59:33 +08:00
midoks 1adc0c1405 Update rhel.sh 2023-02-18 15:35:16 +08:00
midoks b22185b374 Update rhel.sh 2023-02-18 14:09:02 +08:00
midoks 02f3107e93 Update app.js 2023-02-18 02:04:52 +08:00
midoks 52fece867d up 2023-02-18 01:49:20 +08:00
midoks 2e3578dcf1 up 2023-02-18 01:39:26 +08:00
midoks 73b09a7886 up 2023-02-17 22:39:49 +08:00
midoks f33c7e5a5e up 2023-02-17 19:57:03 +08:00
midoks 3e90db2c8d Update system_api.py 2023-02-17 19:54:44 +08:00
midoks d599363609 Update index.py 2023-02-17 16:30:32 +08:00
midoks ec3167f239 Update __init__.py 2023-02-17 16:30:25 +08:00
midoks 2b1099b6e9 Update __init__.py 2023-02-17 15:42:28 +08:00
midoks e55a0760e3 Update mw.tpl 2023-02-17 15:22:15 +08:00
midoks 5c1353a38f Update mw.tpl 2023-02-17 15:20:52 +08:00
midoks f95684b316 Update mw.tpl 2023-02-17 15:20:39 +08:00
midoks 6fc729ccf9 Update __init__.py 2023-02-17 15:17:41 +08:00
midoks 45d0c4fc4a Update __init__.py 2023-02-17 15:16:11 +08:00
midoks 6759b9055c ip 2023-02-17 15:01:26 +08:00
midoks de694b2465 up 2023-02-17 14:56:44 +08:00
midoks c7b3daca36 up 2023-02-16 17:02:33 +08:00
midoks 452769233f up 2023-02-16 17:00:09 +08:00
midoks 8d196a3aa1 Update index.py 2023-02-16 16:26:22 +08:00
midoks 01baf509ad up 2023-02-16 15:49:55 +08:00
midoks d59ee2c843 Update install.sh 2023-02-16 15:39:08 +08:00
midoks 8919d5734e Update index.py 2023-02-16 14:15:15 +08:00
midoks bb91b30d6d Update index.py 2023-02-16 14:06:41 +08:00
midoks 103ab2e099 Update index.py 2023-02-15 22:45:44 +08:00
midoks 0d33d0db79 Update install.sh 2023-02-15 22:35:29 +08:00
midoks 6d9f4cfa08 Update tools.py 2023-02-15 22:31:22 +08:00
midoks c88c95ba21 Update macos.sh 2023-02-15 22:26:53 +08:00
midoks a705f6a8e4 Update install.sh 2023-02-15 22:24:51 +08:00
midoks 3f40ed0a01 up 2023-02-15 22:24:46 +08:00
midoks 39653896bf Update install_dev.sh 2023-02-15 22:15:08 +08:00
midoks 31d665d962 Update install.sh 2023-02-15 22:05:16 +08:00
midoks 811fa4a40d Update install_dev.sh 2023-02-15 22:04:58 +08:00
midoks 320f58424d Update README.md 2023-02-15 21:56:19 +08:00
midoks 376f0f0a4e up 2023-02-15 21:55:21 +08:00
midoks 0efb700cee Update README.md 2023-02-15 15:54:14 +08:00
midoks ff3fcae366 Update config_api.py 2023-02-15 15:50:55 +08:00
Mr Chen 22d94ce67c Merge pull request #371 from midoks/dev
安装脚本优化3
2023-02-14 22:24:04 +08:00
midoks 042fd7ac6d Update ubuntu.sh 2023-02-14 22:23:04 +08:00
midoks 1a48f52dad up 2023-02-14 22:22:06 +08:00
Mr Chen fc5970c65d Merge pull request #370 from midoks/dev
安装脚本优化2
2023-02-14 22:09:05 +08:00
midoks e758698ee2 Update debian.sh 2023-02-14 22:02:28 +08:00
Mr Chen ea03bb056a Merge pull request #369 from midoks/dev
安装脚本优化
2023-02-14 21:59:22 +08:00
midoks 088346fd5e 安装脚本优化 2023-02-14 21:58:30 +08:00
midoks cbcb686363 Update firewall_api.py 2023-02-14 21:07:22 +08:00
105 changed files with 4408 additions and 489 deletions
+5 -1
View File
@@ -151,8 +151,10 @@ data/system.db-journal
data/hook_*.json data/hook_*.json
data/letsencrypt.json data/letsencrypt.json
data/basic_auth.json data/basic_auth.json
data/notify.json
data/api.json data/api.json
data/bind_domain.pl data/bind_domain.pl
data/unauthorized_status.pl
plugins/vip_* plugins/vip_*
plugins/own_* plugins/own_*
@@ -162,6 +164,7 @@ plugins/openlitespeed
plugins/system_safe plugins/system_safe
plugins/tamper_proof plugins/tamper_proof
plugins/tamper_proof_* plugins/tamper_proof_*
plugins/cryptocurrency_trade
plugins/op_load_balance plugins/op_load_balance
plugins/gdrive plugins/gdrive
plugins/mtproxy plugins/mtproxy
@@ -175,4 +178,5 @@ plugins/file_search
debug.out debug.out
data/unauthorized_status.pl
+7 -11
View File
@@ -29,6 +29,7 @@
基本上可以使用,后续会继续优化!欢迎提供意见! 基本上可以使用,后续会继续优化!欢迎提供意见!
- 吹水组 - https://t.me/mdserver_web - 吹水组 - https://t.me/mdserver_web
- 交流论坛 - https://bbs.midoks.me
``` ```
如果出现问题,最好私给我面板信息。不要让我猜。如果不提供,不要提出问题,自行解决。 — 座右铭 如果出现问题,最好私给我面板信息。不要让我猜。如果不提供,不要提出问题,自行解决。 — 座右铭
@@ -73,7 +74,7 @@ phpMyAdmin[4.4.15]支持MySQL[5.5-5.7]
phpMyAdmin[5.2.0]支持MySQL[8.0] phpMyAdmin[5.2.0]支持MySQL[8.0]
PHP[53-72]支持phpMyAdmin[4.4.15] PHP[53-72]支持phpMyAdmin[4.4.15]
PHP[72-81]支持phpMyAdmin[5.2.0] PHP[72-82]支持phpMyAdmin[5.2.0]
``` ```
# 特别赞助 # 特别赞助
@@ -98,16 +99,11 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
``` ```
### 版本更新 0.12.3 ### 版本更新 0.13.3
* 优先使用firewalld防火墙。 * tgbot插件[增加扩展功能]。
* PHP[APT]加入curl扩展。 * ssl功能优化。
* 配置添加【未认证响应状态】功能。 * 网站统计-计划任务归档优化。
* 存在ipv6时,启动时强制开启。
* OP防火墙-性能优化。
* 网站统计优化。
* 优化backup_ftp插件。
* 各种细节优化。
### JSDelivr安装地址 ### JSDelivr安装地址
@@ -135,7 +131,7 @@ wget -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scri
``` ```
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | bash curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | bash
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install.sh | bash
``` ```
- 直接更新 - 直接更新
+2 -3
View File
@@ -371,8 +371,7 @@ fi
response = urllib.request.urlopen(req, timeout=timeout) response = urllib.request.urlopen(req, timeout=timeout)
return response return response
except Exception as ex: except Exception as ex:
# self.getError()
self.getError()
raise Exception("requestsPost: {}".format(self.getError(str(ex)))) raise Exception("requestsPost: {}".format(self.getError(str(ex))))
def getRequestJson(self, response): def getRequestJson(self, response):
@@ -1522,7 +1521,7 @@ fullchain.pem 粘贴到证书输入框
self.__config['orders'][i]['auth_to'] = auth_to self.__config['orders'][i]['auth_to'] = auth_to
# 是否到了允许重试的时间 # 是否到了允许重试的时间
if 'next_retry_time' in self._config['orders'][i]: if 'next_retry_time' in self.__config['orders'][i]:
timeout = self.__config['orders'][i][ timeout = self.__config['orders'][i][
'next_retry_time'] - int(time.time()) 'next_retry_time'] - int(time.time())
if timeout > 0: if timeout > 0:
+185 -12
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api: class config_api:
__version = '0.12.3' __version = '0.13.3'
__api_addr = 'data/api.json' __api_addr = 'data/api.json'
def __init__(self): def __init__(self):
@@ -348,7 +348,23 @@ class config_api:
keyPath = 'ssl/private.pem' keyPath = 'ssl/private.pem'
certPath = 'ssl/cert.pem' certPath = 'ssl/cert.pem'
if not os.path.exists(certPath): if not os.path.exists(certPath):
mw.createSSL() # 不再自动生成证书
# mw.createSSL()
cert['privateKey'] = ''
cert['is_https'] = ''
cert['certPem'] = ''
cert['rep'] = os.path.exists('ssl/input.pl')
cert['info'] = {'endtime': 0, 'subject': '无',
'notAfter': '无', 'notBefore': '无', 'issuer': '无'}
return cert
panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if not os.path.exists(panel_ssl):
cert['is_https'] = ''
else:
ssl_data = mw.readFile(panel_ssl)
if ssl_data.find('$server_port !~ 443') != -1:
cert['is_https'] = 'checked'
cert['privateKey'] = mw.readFile(keyPath) cert['privateKey'] = mw.readFile(keyPath)
cert['certPem'] = mw.readFile(certPath) cert['certPem'] = mw.readFile(certPath)
@@ -380,13 +396,86 @@ class config_api:
mw.writeFile('ssl/input.pl', 'True') mw.writeFile('ssl/input.pl', 'True')
return mw.returnJson(True, '证书已保存!') return mw.returnJson(True, '证书已保存!')
# 设置面板SSL证书设置
def setPanelHttpToHttpsApi(self):
bind_domain = 'data/bind_domain.pl'
if not os.path.exists(bind_domain):
return mw.returnJson(False, '先要绑定域名!')
keyPath = 'ssl/private.pem'
if not os.path.exists(keyPath):
return mw.returnJson(False, '未申请SSL证书!')
is_https = request.form.get('https', '').strip()
panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if not os.path.exists(panel_ssl):
return mw.returnJson(False, '未开启面板SSL!')
if is_https == 'false':
conf = mw.readFile(panel_ssl)
if conf:
if conf.find('ssl_certificate') == -1:
return mw.returnJson(False, '当前未开启SSL')
to = "#error_page 404/404.html;\n\
#HTTP_TO_HTTPS_START\n\
if ($server_port !~ 443){\n\
rewrite ^(/.*)$ https://$host$1 permanent;\n\
}\n\
#HTTP_TO_HTTPS_END"
conf = conf.replace('#error_page 404/404.html;', to)
mw.writeFile(panel_ssl, conf)
else:
conf = mw.readFile(panel_ssl)
if conf:
rep = "\n\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
conf = re.sub(rep, '', conf)
rep = "\s+if.+server_port.+\n.+\n\s+\s*}"
conf = re.sub(rep, '', conf)
mw.writeFile(panel_ssl, conf)
mw.restartWeb()
action = '开启'
if is_https == 'true':
action = '关闭'
return mw.returnJson(True, action + 'HTTPS跳转成功!')
# 删除面板证书
def delPanelSslApi(self):
bind_domain = 'data/bind_domain.pl'
if not os.path.exists(bind_domain):
return mw.returnJson(False, '未绑定域名!')
siteName = mw.readFile(bind_domain).strip()
src_letpath = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
dst_letpath = mw.getRunDir() + '/ssl'
dst_csrpath = dst_letpath + '/cert.pem'
dst_keypath = dst_letpath + '/private.pem'
if os.path.exists(src_letpath) or os.path.exists(dst_csrpath):
if os.path.exists(src_letpath):
mw.execShell('rm -rf ' + src_letpath)
if os.path.exists(dst_csrpath):
mw.execShell('rm -rf ' + dst_csrpath)
if os.path.exists(dst_keypath):
mw.execShell('rm -rf ' + dst_keypath)
# mw.restartWeb()
return mw.returnJson(True, '已经删除SSL!')
# mw.restartWeb()
return mw.returnJson(False, '已经不存在SSL!')
# 申请面板let证书 # 申请面板let证书
def applyPanelLetSslApi(self): def applyPanelLetSslApi(self):
# check domain is bind? # check domain is bind?
bind_domain = 'data/bind_domain.pl' bind_domain = 'data/bind_domain.pl'
if not os.path.exists(bind_domain): if not os.path.exists(bind_domain):
return mw.returnJson(False, '未绑定域名!') return mw.returnJson(False, '先要绑定域名!')
siteName = mw.readFile(bind_domain).strip() siteName = mw.readFile(bind_domain).strip()
auth_to = mw.getRunDir() + "/tmp" auth_to = mw.getRunDir() + "/tmp"
@@ -404,6 +493,8 @@ class config_api:
dst_csrpath = dst_letpath + '/cert.pem' dst_csrpath = dst_letpath + '/cert.pem'
dst_keypath = dst_letpath + '/private.pem' dst_keypath = dst_letpath + '/private.pem'
is_already_apply = False
if not os.path.exists(src_letpath): if not os.path.exists(src_letpath):
import cert_api import cert_api
data = cert_api.cert_api().applyCertApi(to_args) data = cert_api.cert_api().applyCertApi(to_args)
@@ -415,6 +506,8 @@ class config_api:
msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[ msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>' 'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
return mw.returnJson(data['status'], msg, data['msg']) return mw.returnJson(data['status'], msg, data['msg'])
else:
is_already_apply = True
mw.buildSoftLink(src_csrpath, dst_csrpath, True) mw.buildSoftLink(src_csrpath, dst_csrpath, True)
mw.buildSoftLink(src_keypath, dst_keypath, True) mw.buildSoftLink(src_keypath, dst_keypath, True)
@@ -426,6 +519,9 @@ class config_api:
if os.path.exists(tmp_well_know): if os.path.exists(tmp_well_know):
mw.execShell('rm -rf ' + tmp_well_know) mw.execShell('rm -rf ' + tmp_well_know)
if is_already_apply:
return mw.returnJson(True, '重复申请!', data)
return mw.returnJson(True, '申请成功!', data) return mw.returnJson(True, '申请成功!', data)
def setPanelDomainApi(self): def setPanelDomainApi(self):
@@ -509,8 +605,6 @@ class config_api:
return mw.returnJson(True, 'SSL已关闭,请使用http协议访问面板!') return mw.returnJson(True, 'SSL已关闭,请使用http协议访问面板!')
else: else:
try: try:
if not os.path.exists('ssl/input.ssl'):
mw.createSSL()
mw.writeFile(sslConf, 'True') mw.writeFile(sslConf, 'True')
keyPath = mw.getRunDir() + '/ssl/private.pem' keyPath = mw.getRunDir() + '/ssl/private.pem'
@@ -661,6 +755,60 @@ class config_api:
mw.writeLog('面板设置', '将未授权响应状态码设置为:{}'.format(status_code)) mw.writeLog('面板设置', '将未授权响应状态码设置为:{}'.format(status_code))
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
def getNotifyApi(self):
# 获取
data = mw.getNotifyData(True)
return mw.returnData(True, 'ok', data)
def setNotifyApi(self):
tag = request.form.get('tag', '').strip()
data = request.form.get('data', '').strip()
cfg = mw.getNotifyData(False)
crypt_data = mw.enDoubleCrypt(tag, data)
if tag in cfg:
cfg[tag]['cfg'] = crypt_data
else:
t = {'cfg': crypt_data}
cfg[tag] = t
mw.writeNotify(cfg)
return mw.returnData(True, '设置成功')
def setNotifyTestApi(self):
# 异步通知验证
tag = request.form.get('tag', '').strip()
tag_data = request.form.get('data', '').strip()
if tag == 'tgbot':
t = json.loads(tag_data)
test_bool = mw.tgbotNotifyTest(t['app_token'], t['chat_id'])
if test_bool:
return mw.returnData(True, '验证成功')
return mw.returnData(False, '验证失败')
return mw.returnData(False, '暂时未支持该验证')
def setNotifyEnableApi(self):
# 异步通知验证
tag = request.form.get('tag', '').strip()
tag_enable = request.form.get('enable', '').strip()
data = mw.getNotifyData(False)
op_enable = True
op_action = '开启'
if tag_enable != 'true':
op_enable = False
op_action = '关闭'
if tag in data:
data[tag]['enable'] = op_enable
mw.writeNotify(data)
return mw.returnData(True, op_action + '成功')
def getPanelTokenApi(self): def getPanelTokenApi(self):
api_file = self.__api_addr api_file = self.__api_addr
tmp = mw.readFile(api_file) tmp = mw.readFile(api_file)
@@ -693,10 +841,6 @@ class config_api:
def setPanelTokenApi(self): def setPanelTokenApi(self):
op_type = request.form.get('op_type', '').strip() op_type = request.form.get('op_type', '').strip()
api_file = self.__api_addr
tmp = mw.readFile(api_file)
data = json.loads(tmp)
if op_type == '1': if op_type == '1':
token = mw.getRandomString(32) token = mw.getRandomString(32)
data['token'] = mw.md5(token) data['token'] = mw.md5(token)
@@ -706,7 +850,14 @@ class config_api:
mw.writeFile(api_file, json.dumps(data)) mw.writeFile(api_file, json.dumps(data))
return mw.returnJson(True, 'ok', token) return mw.returnJson(True, 'ok', token)
elif op_type == '2': api_file = self.__api_addr
if not os.path.exists(api_file):
return mw.returnJson(False, "先在API接口配置")
else:
tmp = mw.readFile(api_file)
data = json.loads(tmp)
if op_type == '2':
data['open'] = not data['open'] data['open'] = not data['open']
stats = {True: '开启', False: '关闭'} stats = {True: '开启', False: '关闭'}
if not 'token_crypt' in data: if not 'token_crypt' in data:
@@ -721,6 +872,7 @@ class config_api:
return mw.returnJson(not not data['open'], token) return mw.returnJson(not not data['open'], token)
elif op_type == '3': elif op_type == '3':
limit_addr = request.form.get('limit_addr', '').strip() limit_addr = request.form.get('limit_addr', '').strip()
data['limit_addr'] = limit_addr.split('\n') data['limit_addr'] = limit_addr.split('\n')
mw.writeLog('API配置', '变更IP限制为[%s]' % limit_addr) mw.writeLog('API配置', '变更IP限制为[%s]' % limit_addr)
@@ -820,7 +972,9 @@ class config_api:
data['username'] = mw.M('users').where( data['username'] = mw.M('users').where(
"id=?", (1,)).getField('username') "id=?", (1,)).getField('username')
# databases hook 获取 data['hook_tag'] = request.args.get('tag', '')
# databases hook
database_hook_file = 'data/hook_database.json' database_hook_file = 'data/hook_database.json'
if os.path.exists(database_hook_file): if os.path.exists(database_hook_file):
df = mw.readFile(database_hook_file) df = mw.readFile(database_hook_file)
@@ -829,7 +983,7 @@ class config_api:
else: else:
data['hook_database'] = [] data['hook_database'] = []
# menu hook 获取 # menu hook
menu_hook_file = 'data/hook_menu.json' menu_hook_file = 'data/hook_menu.json'
if os.path.exists(menu_hook_file): if os.path.exists(menu_hook_file):
df = mw.readFile(menu_hook_file) df = mw.readFile(menu_hook_file)
@@ -838,4 +992,23 @@ class config_api:
else: else:
data['hook_menu'] = [] data['hook_menu'] = []
# global_static hook
global_static_hook_file = 'data/hook_global_static.json'
if os.path.exists(global_static_hook_file):
df = mw.readFile(global_static_hook_file)
df = json.loads(df)
data['hook_global_static'] = df
else:
data['hook_global_static'] = []
# notiy config
notify_data = mw.getNotifyData(True)
notify_tag_list = ['tgbot', 'email']
for tag in notify_tag_list:
new_tag = 'notify_' + tag + '_enable'
data[new_tag] = ''
if tag in notify_data and 'enable' in notify_data[tag]:
if notify_data[tag]['enable']:
data[new_tag] = 'checked'
return data return data
+1 -1
View File
@@ -348,7 +348,7 @@ class Sql():
except Exception as ex: except Exception as ex:
return "error: " + str(ex) return "error: " + str(ex)
def query(self, sql, param): def query(self, sql, param=()):
# 执行SQL语句返回数据集 # 执行SQL语句返回数据集
self.__getConn() self.__getConn()
try: try:
+111 -2
View File
@@ -247,8 +247,8 @@ class files_api:
os.remove(task_log) os.remove(task_log)
return mw.returnJson(True, '任务已删除!') return mw.returnJson(True, '任务已删除!')
# 上传文件
def uploadFileApi(self): def uploadFileApi(self):
# 上传文件
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from flask import request from flask import request
@@ -263,6 +263,8 @@ class files_api:
if os.path.exists(filename): if os.path.exists(filename):
s_path = filename s_path = filename
p_stat = os.stat(s_path) p_stat = os.stat(s_path)
# print(filename)
f.save(filename) f.save(filename)
os.chown(filename, p_stat.st_uid, p_stat.st_gid) os.chown(filename, p_stat.st_uid, p_stat.st_gid)
os.chmod(filename, p_stat.st_mode) os.chmod(filename, p_stat.st_mode)
@@ -271,6 +273,86 @@ class files_api:
mw.writeLog('文件管理', msg) mw.writeLog('文件管理', msg)
return mw.returnMsg(True, '上传成功!') return mw.returnMsg(True, '上传成功!')
# 设置文件和目录权限
def setMode(self, path):
s_path = os.path.dirname(path)
p_stat = os.stat(s_path)
os.chown(path, p_stat.st_uid, p_stat.st_gid)
os.chmod(path, p_stat.st_mode)
def uploadSegmentApi(self):
# 分段上传
path = request.form.get('path', '')
name = request.form.get('name', '')
size = request.form.get('size')
start = request.form.get('start')
dir_mode = request.form.get('dir_mode', '')
file_mode = request.form.get('file_mode', '')
if not mw.fileNameCheck(name):
return mw.returnJson(False, '文件名中不能包含特殊字符!')
if path == '/':
return mw.returnJson(False, '不能直接上传文件到系统根目录!')
if name.find('./') != -1 or path.find('./') != -1:
return mw.returnJson(False, '错误的参数')
if not os.path.exists(path):
os.makedirs(path, 493)
if not dir_mode != '' or not file_mode != '':
mw.setMode(path)
save_path = os.path.join(
path, name + '.' + str(int(size)) + '.upload.tmp')
d_size = 0
if os.path.exists(save_path):
d_size = os.path.getsize(save_path)
if d_size != int(start):
return str(d_size)
f = open(save_path, 'ab')
b64_data = request.form.get('b64_data', '0')
if b64_data == '1':
import base64
b64_data = base64.b64decode(args.b64_data)
f.write(b64_data)
else:
upload_files = request.files.getlist("blob")
for tmp_f in upload_files:
f.write(tmp_f.read())
f.close()
f_size = os.path.getsize(save_path)
if f_size != int(size):
return str(f_size)
new_name = os.path.join(path, name)
if os.path.exists(new_name):
if new_name.find('.user.ini') != -1:
mw.execShell("chattr -i " + new_name)
try:
os.remove(new_name)
except:
mw.execShell("rm -f %s" % new_name)
os.renames(save_path, new_name)
if dir_mode != '' and dir_mode != '':
mode_tmp1 = dir_mode.split(',')
mw.setMode(path, mode_tmp1[0])
mw.setOwn(path, mode_tmp1[1])
mode_tmp2 = file_mode.split(',')
mw.setMode(new_name, mode_tmp2[0])
mw.setOwn(new_name, mode_tmp2[1])
else:
self.setMode(new_name)
msg = mw.getInfo('上传文件[{1}] 到 [{2}]成功!', (new_name, path))
mw.writeLog('文件管理', msg)
return mw.returnMsg(True, '上传成功!')
def getRecycleBinApi(self): def getRecycleBinApi(self):
rPath = self.rPath rPath = self.rPath
if not os.path.exists(rPath): if not os.path.exists(rPath):
@@ -626,7 +708,7 @@ class files_api:
return not path in nDirs return not path in nDirs
def getDirSize(self, path): def getDirSize(self, path):
if mw.getOs() == 'darwin': if mw.isAppleSystem():
tmp = mw.execShell('du -sh ' + path) tmp = mw.execShell('du -sh ' + path)
else: else:
tmp = mw.execShell('du -sbh ' + path) tmp = mw.execShell('du -sbh ' + path)
@@ -905,6 +987,33 @@ class files_api:
return mw.getJson(data) return mw.getJson(data)
def execShellApi(self):
# 执行SHELL命令
shell = request.form.get('shell', '').strip()
path = request.form.get('path', '').strip()
disabled = ['vi', 'vim', 'top', 'passwd', 'su']
tmp = shell.split(' ')
if tmp[0] in disabled:
return mw.returnJson(False, '禁止执行[{}]'.format(tmp[0]))
shellStr = '''#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
cd %s
%s
''' % (path, shell)
mw.writeFile('/tmp/panelShell.sh', shellStr)
mw.execShell(
'nohup bash /tmp/panelShell.sh > /tmp/panelShell.pl 2>&1 &')
return mw.returnJson(True, 'ok')
def getExecShellMsgApi(self):
# 取SHELL执行结果
fileName = '/tmp/panelShell.pl'
if not os.path.exists(fileName):
return ''
status = not mw.processExists('bash', None, '/tmp/panelShell.sh')
return mw.returnJson(status, mw.getNumLines(fileName, 200))
def __get_stats(self, filename, path=None): def __get_stats(self, filename, path=None):
filename = filename.replace('//', '/') filename = filename.replace('//', '/')
try: try:
+12 -11
View File
@@ -36,10 +36,10 @@ class firewall_api:
iptables_file = mw.systemdCfgDir() + '/iptables.service' iptables_file = mw.systemdCfgDir() + '/iptables.service'
if os.path.exists('/usr/sbin/firewalld'): if os.path.exists('/usr/sbin/firewalld'):
self.__isFirewalld = True self.__isFirewalld = True
elif os.path.exists(iptables_file):
self.__isIptables = True
elif os.path.exists('/usr/sbin/ufw'): elif os.path.exists('/usr/sbin/ufw'):
self.__isUfw = True self.__isUfw = True
elif os.path.exists(iptables_file):
self.__isIptables = True
elif mw.isAppleSystem(): elif mw.isAppleSystem():
self.__isMac = True self.__isMac = True
@@ -123,12 +123,12 @@ class firewall_api:
address = port address = port
if self.__isUfw: if self.__isUfw:
mw.execShell('ufw delete deny from ' + address + ' to any') mw.execShell('ufw delete deny from ' + address + ' to any')
elif self.__isIptables:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
elif self.__isFirewalld: elif self.__isFirewalld:
mw.execShell( mw.execShell(
'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'') 'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'')
elif self.__isIptables:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
else: else:
pass pass
@@ -149,14 +149,15 @@ class firewall_api:
return mw.returnJson(False, '失败,不能删除当前面板端口!') return mw.returnJson(False, '失败,不能删除当前面板端口!')
if self.__isUfw: if self.__isUfw:
mw.execShell('ufw delete allow ' + port + '/tcp') mw.execShell('ufw delete allow ' + port + '/tcp')
elif self.__isIptables:
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
elif self.__isFirewalld: elif self.__isFirewalld:
port = port.replace(':', '-')
mw.execShell( mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp') 'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
mw.execShell( mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp') 'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
elif self.__isIptables:
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
else: else:
pass pass
msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,)) msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
@@ -438,13 +439,13 @@ class firewall_api:
def addAcceptPort(self, port): def addAcceptPort(self, port):
if self.__isUfw: if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp') mw.execShell('ufw allow ' + port + '/tcp')
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
elif self.__isFirewalld: elif self.__isFirewalld:
port = port.replace(':', '-') port = port.replace(':', '-')
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp' cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd) mw.execShell(cmd)
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
else: else:
pass pass
return True return True
+238 -9
View File
@@ -22,6 +22,8 @@ import hashlib
import shlex import shlex
import datetime import datetime
import subprocess import subprocess
import glob
import re import re
import db import db
from random import Random from random import Random
@@ -80,6 +82,10 @@ def getPanelDataDir():
return getRunDir() + '/data' return getRunDir() + '/data'
def getPanelTmp():
return getRunDir() + '/tmp'
def getServerDir(): def getServerDir():
return getRootDir() + '/server' return getRootDir() + '/server'
@@ -123,6 +129,23 @@ def getAcmeDir():
return acme return acme
def getAcmeDomainDir(domain):
acme_dir = getAcmeDir()
acme_domain = acme_dir + '/' + domain
acme_domain_ecc = acme_domain + '_ecc'
if os.path.exists(acme_domain_ecc):
acme_domain = acme_domain_ecc
return acme_domain
def fileNameCheck(filename):
f_strs = [';', '&', '<', '>']
for fs in f_strs:
if filename.find(fs) != -1:
return False
return True
def triggerTask(): def triggerTask():
isTask = getRunDir() + '/tmp/panelTask.pl' isTask = getRunDir() + '/tmp/panelTask.pl'
writeFile(isTask, 'True') writeFile(isTask, 'True')
@@ -519,6 +542,14 @@ def getDate():
return time.strftime('%Y-%m-%d %X', time.localtime()) return time.strftime('%Y-%m-%d %X', time.localtime())
def getDateFromNow(tf_format="%Y-%m-%d %H:%M:%S", time_zone="Asia/Shanghai"):
# 取格式时间
import time
os.environ['TZ'] = time_zone
time.tzset()
return time.strftime(tf_format, time.localtime())
def getDataFromInt(val): def getDataFromInt(val):
time_format = '%Y-%m-%d %H:%M:%S' time_format = '%Y-%m-%d %H:%M:%S'
time_str = time.localtime(val) time_str = time.localtime(val)
@@ -534,10 +565,39 @@ def writeLog(stype, msg, args=()):
uid = session['uid'] uid = session['uid']
except Exception as e: except Exception as e:
pass pass
# print(getTracebackInfo()) # writeFileLog(getTracebackInfo())
return writeDbLog(stype, msg, args, uid) return writeDbLog(stype, msg, args, uid)
def writeFileLog(msg, path=None, limit_size=50 * 1024 * 1024, save_limit=3):
log_file = getServerDir() + '/mdserver-web/logs/debug.log'
if path != None:
log_file = path
if os.path.exists(log_file):
size = os.path.getsize(log_file)
if size > limit_size:
log_file_rename = log_file + "_" + \
time.strftime("%Y-%m-%d_%H%M%S") + '.log'
os.rename(log_file, log_file_rename)
logs = sorted(glob.glob(log_file + "_*"))
count = len(logs)
save_limit = count - save_limit
for i in range(count):
if i > save_limit:
break
os.remove(logs[i])
# print('|---多余日志[' + logs[i] + ']已删除!')
f = open(log_file, 'ab+')
msg += "\n"
if __name__ == '__main__':
print(msg)
f.write(msg.encode('utf-8'))
f.close()
return True
def writeDbLog(stype, msg, args=(), uid=1): def writeDbLog(stype, msg, args=(), uid=1):
try: try:
import time import time
@@ -656,7 +716,7 @@ def enCrypt(key, strings):
result = f.encrypt(strings) result = f.encrypt(strings)
return result.decode('utf-8') return result.decode('utf-8')
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -675,7 +735,7 @@ def deCrypt(key, strings):
result = f.decrypt(strings).decode('utf-8') result = f.decrypt(strings).decode('utf-8')
return result return result
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -694,7 +754,7 @@ def enDoubleCrypt(key, strings):
result = f.encrypt(strings) result = f.encrypt(strings)
return result.decode('utf-8') return result.decode('utf-8')
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -712,7 +772,7 @@ def deDoubleCrypt(key, strings):
result = f.decrypt(strings).decode('utf-8') result = f.decrypt(strings).decode('utf-8')
return result return result
except: except:
print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return strings return strings
@@ -988,7 +1048,7 @@ def getLocalIp():
try: try:
ipaddress = readFile(filename) ipaddress = readFile(filename)
if not ipaddress or ipaddress == '127.0.0.1': if not ipaddress or ipaddress == '127.0.0.1':
cmd = "curl -4 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text" cmd = "curl --insecure -4 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text"
ip = execShell(cmd) ip = execShell(cmd)
result = ip[0].strip() result = ip[0].strip()
if result == '': if result == '':
@@ -997,7 +1057,7 @@ def getLocalIp():
return result return result
return ipaddress return ipaddress
except Exception as e: except Exception as e:
cmd = "curl -6 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text" cmd = "curl --insecure -6 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text"
ip = execShell(cmd) ip = execShell(cmd)
result = ip[0].strip() result = ip[0].strip()
if result == '': if result == '':
@@ -1122,6 +1182,15 @@ def setOwn(filename, user, group=None):
return True return True
def setMode(filename, mode):
# 设置文件权限
if not os.path.exists(filename):
return False
mode = int(str(mode), 8)
os.chmod(filename, mode)
return True
def checkPort(port): def checkPort(port):
# 检查端口是否合法 # 检查端口是否合法
ports = ['21', '443', '888'] ports = ['21', '443', '888']
@@ -1207,7 +1276,7 @@ def makeConf():
file = getRunDir() + '/data/json/config.json' file = getRunDir() + '/data/json/config.json'
if not os.path.exists(file): if not os.path.exists(file):
c = {} c = {}
c['title'] = '大圣面板' c['title'] = '金蝉面板'
c['home'] = 'http://github/midoks/mdserver-web' c['home'] = 'http://github/midoks/mdserver-web'
c['recycle_bin'] = True c['recycle_bin'] = True
c['template'] = 'default' c['template'] = 'default'
@@ -1507,7 +1576,7 @@ def getCertName(certPath):
result['notAfter'], "%Y-%m-%d")) - time.time()) / 86400) result['notAfter'], "%Y-%m-%d")) - time.time()) / 86400)
return result return result
except Exception as e: except Exception as e:
# print(getTracebackInfo()) writeFileLog(getTracebackInfo())
return None return None
@@ -1605,6 +1674,141 @@ def getMyORMDb():
o = ormDb.ORM() o = ormDb.ORM()
return o return o
##################### notify start #########################################
def initNotifyConfig():
p = getNotifyPath()
if not os.path.exists(p):
writeFile(p, '{}')
return True
def getNotifyPath():
path = 'data/notify.json'
return path
def getNotifyData(is_parse=False):
initNotifyConfig()
notify_file = getNotifyPath()
notify_data = readFile(notify_file)
data = json.loads(notify_data)
if is_parse:
tag_list = ['tgbot']
for t in tag_list:
if t in data and 'cfg' in data[t]:
data[t]['data'] = json.loads(deDoubleCrypt(t, data[t]['cfg']))
return data
def writeNotify(data):
p = getNotifyPath()
return writeFile(p, json.dumps(data))
def tgbotNotifyChatID():
data = getNotifyData(True)
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
return t['chat_id']
return ''
def tgbotNotifyObject():
data = getNotifyData(True)
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
import telebot
bot = telebot.TeleBot(app_token)
return True, bot
return False, None
def tgbotNotifyMessage(app_token, chat_id, msg):
import telebot
bot = telebot.TeleBot(app_token)
try:
data = bot.send_message(chat_id, msg)
return True
except Exception as e:
writeFileLog(str(e))
return False
def tgbotNotifyHttpPost(app_token, chat_id, msg):
try:
url = 'https://api.telegram.org/bot' + app_token + '/sendMessage'
post_data = {
'chat_id': chat_id,
'text': msg,
}
rdata = httpPost(url, post_data)
return True
except Exception as e:
writeFileLog(str(e))
return False
def tgbotNotifyTest(app_token, chat_id):
msg = 'MW-通知验证测试OK'
return tgbotNotifyHttpPost(app_token, chat_id, msg)
def notifyMessageTry(msg, stype='common', trigger_time=300, is_write_log=True):
lock_file = getPanelTmp() + '/notify_lock.json'
if not os.path.exists(lock_file):
writeFile(lock_file, '{}')
lock_data = json.loads(readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False
else:
lock_data[stype] = {'do_time': time.time()}
writeFile(lock_file, json.dumps(lock_data))
if is_write_log:
writeLog("通知管理[" + stype + "]", msg)
data = getNotifyData(True)
# tag_list = ['tgbot', 'email']
# tagbot
do_notify = False
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
i = sys.version_info
# telebot 在python小于3.7无法使用
if i[0] < 3 or i[1] < 7:
do_notify = tgbotNotifyHttpPost(
t['app_token'], t['chat_id'], msg)
else:
do_notify = tgbotNotifyMessage(
t['app_token'], t['chat_id'], msg)
return do_notify
def notifyMessage(msg, stype='common', trigger_time=300, is_write_log=True):
try:
return notifyMessageTry(msg, stype, trigger_time, is_write_log)
except Exception as e:
writeFileLog(getTracebackInfo())
return False
##################### notify end #########################################
##################### ssh start ######################################### ##################### ssh start #########################################
def getSshDir(): def getSshDir():
@@ -1614,6 +1818,31 @@ def getSshDir():
return '/root/.ssh' return '/root/.ssh'
def processExists(pname, exe=None, cmdline=None):
# 进程是否存在
try:
import psutil
pids = psutil.pids()
for pid in pids:
try:
p = psutil.Process(pid)
if p.name() == pname:
if not exe and not cmdline:
return True
else:
if exe:
if p.exe() == exe:
return True
if cmdline:
if cmdline in p.cmdline():
return True
except:
pass
return False
except:
return True
def createRsa(): def createRsa():
# ssh-keygen -t rsa -P "" -C "midoks@163.com" # ssh-keygen -t rsa -P "" -C "midoks@163.com"
ssh_dir = getSshDir() ssh_dir = getSshDir()
+7 -5
View File
@@ -91,7 +91,7 @@ class plugins_api:
t = mw.readFile(menu_file) t = mw.readFile(menu_file)
tlist = json.loads(t) tlist = json.loads(t)
for menu_data in tlist: for menu_data in tlist:
if 'path' in menu_data: if tag == menu_data['name'] and 'path' in menu_data:
tpath = self.menuGetAbsPath(tag, menu_data['path']) tpath = self.menuGetAbsPath(tag, menu_data['path'])
content = mw.readFile(tpath) content = mw.readFile(tpath)
data['plugin_content'] = content data['plugin_content'] = content
@@ -256,13 +256,14 @@ class plugins_api:
data = json.loads(t) data = json.loads(t)
for idx in range(len(data)): for idx in range(len(data)):
if data[idx]['title'] == info['title'] and data[idx]['name'] == info['name']: if data[idx]['name'] == info['name']:
data.remove(data[idx]) data.remove(data[idx])
break
mw.writeFile(hookPath, json.dumps(data)) mw.writeFile(hookPath, json.dumps(data))
def hookInstall(self, info): def hookInstall(self, info):
valid_hook = ['backup', 'database'] valid_hook = ['backup', 'database']
valid_list_hook = ['menu'] valid_list_hook = ['menu', 'global_static', 'site_cb']
if 'hook' in info: if 'hook' in info:
hooks = info['hook'] hooks = info['hook']
for h in hooks: for h in hooks:
@@ -280,7 +281,7 @@ class plugins_api:
def hookUninstall(self, info): def hookUninstall(self, info):
valid_hook = ['backup', 'database'] valid_hook = ['backup', 'database']
valid_list_hook = ['menu'] valid_list_hook = ['menu', 'global_static', 'site_cb']
if 'hook' in info: if 'hook' in info:
hooks = info['hook'] hooks = info['hook']
for h in hooks: for h in hooks:
@@ -795,7 +796,8 @@ class plugins_api:
for index in range(len(tmp_data)): for index in range(len(tmp_data)):
plugins_info.append(tmp_data[index]) plugins_info.append(tmp_data[index])
except Exception as e: except Exception as e:
print(e) print(json_file)
print(mw.getTracebackInfo())
start = (page - 1) * pageSize start = (page - 1) * pageSize
end = start + pageSize end = start + pageSize
+42 -10
View File
@@ -72,6 +72,30 @@ class site_api:
mw.execShell("mkdir -p " + self.sslLetsDir + mw.execShell("mkdir -p " + self.sslLetsDir +
" && chmod -R 755 " + self.sslLetsDir) " && chmod -R 755 " + self.sslLetsDir)
def runHook(self, hook_name, func_name):
# 站点操作Hook
hook_file = 'data/hook_site_cb.json'
hook_cfg = []
if os.path.exists(hook_file):
t = mw.readFile(hook_file)
hook_cfg = json.loads(t)
hook_num = len(hook_cfg)
if hook_num == 0:
return
import plugins_api
pa = plugins_api.plugins_api()
for x in range(hook_num):
hook_data = hook_cfg[x]
if func_name in hook_data:
app_name = hook_data["name"]
run_func = hook_data[func_name]['func']
# print(app_name, run_func)
pa.run(app_name, run_func)
return True
##### ----- start ----- ### ##### ----- start ----- ###
def listApi(self): def listApi(self):
limit = request.form.get('limit', '10') limit = request.form.get('limit', '10')
@@ -550,7 +574,7 @@ class site_api:
return mw.returnJson(False, '使用中,先关闭再删除') return mw.returnJson(False, '使用中,先关闭再删除')
mw.execShell('rm -rf ' + ssl_lets_dir) mw.execShell('rm -rf ' + ssl_lets_dir)
elif ssl_type == 'acme': elif ssl_type == 'acme':
ssl_acme_dir = mw.getAcmeDir() + '/' + site_name ssl_acme_dir = mw.getAcmeDomainDir(site_name)
csr_acme_path = ssl_acme_dir + '/fullchain.cer' # 生成证书路径 csr_acme_path = ssl_acme_dir + '/fullchain.cer' # 生成证书路径
if mw.md5(mw.readFile(csr_acme_path)) == mw.md5(mw.readFile(csr_path)): if mw.md5(mw.readFile(csr_acme_path)) == mw.md5(mw.readFile(csr_path)):
return mw.returnJson(False, '使用中,先关闭再删除') return mw.returnJson(False, '使用中,先关闭再删除')
@@ -587,9 +611,9 @@ class site_api:
csr_path = self.sslLetsDir + '/' + site_name + '/fullchain.pem' # 生成证书路径 csr_path = self.sslLetsDir + '/' + site_name + '/fullchain.pem' # 生成证书路径
key_path = self.sslLetsDir + '/' + site_name + '/privkey.pem' # 密钥文件路径 key_path = self.sslLetsDir + '/' + site_name + '/privkey.pem' # 密钥文件路径
elif ssl_type == 'acme': elif ssl_type == 'acme':
csr_path = mw.getAcmeDir() + '/' + site_name + '/fullchain.cer' # 生成证书路径 acme_dir = mw.getAcmeDomainDir(site_name)
key_path = mw.getAcmeDir() + '/' + site_name + '/' + \ csr_path = acme_dir + '/fullchain.cer' # 生成证书路径
site_name + '.key' # 密钥文件路径 key_path = acme_dir + '/' + site_name + '.key' # 密钥文件路径
key = mw.readFile(key_path) key = mw.readFile(key_path)
csr = mw.readFile(csr_path) csr = mw.readFile(csr_path)
@@ -989,16 +1013,17 @@ class site_api:
# print(cmd) # print(cmd)
result = mw.execShell(cmd) result = mw.execShell(cmd)
src_path = acme_dir + '/' + domains[0] src_path = mw.getAcmeDomainDir(domains[0])
src_cert = src_path + '/fullchain.cer' src_cert = src_path + '/fullchain.cer'
src_key = src_path + '/' + domains[0] + '.key' src_key = src_path + '/' + domains[0] + '.key'
src_cert.replace("\*", "*")
msg = '签发失败,您尝试申请证书的失败次数已达上限!<p>1、检查域名是否绑定到对应站点</p>\ msg = '签发失败,您尝试申请证书的失败次数已达上限!<p>1、检查域名是否绑定到对应站点</p>\
<p>2、检查域名是否正确解析到本服务器,或解析还未完全生效</p>\ <p>2、检查域名是否正确解析到本服务器,或解析还未完全生效</p>\
<p>3、如果您的站点设置了反向代理,或使用了CDN,请先将其关闭</p>\ <p>3、如果您的站点设置了反向代理,或使用了CDN,请先将其关闭</p>\
<p>4、如果您的站点设置了301重定向,请先将其关闭</p>\ <p>4、如果您的站点设置了301重定向,请先将其关闭</p>\
<p>5、如果以上检查都确认没有问题,请尝试更换DNS服务商</p>' <p>5、如果以上检查都确认没有问题,请尝试更换DNS服务商</p>'
if not os.path.exists(src_cert.replace("\*", "*")): if not os.path.exists(src_cert):
data = {} data = {}
data['err'] = result data['err'] = result
data['out'] = result[0] data['out'] = result[0]
@@ -1271,6 +1296,7 @@ class site_api:
mw.M('domain').add('pid,name,port,addtime', mw.M('domain').add('pid,name,port,addtime',
(pid, domain_name, domain_port, mw.getDate())) (pid, domain_name, domain_port, mw.getDate()))
self.runHook('site_cb', 'add')
return mw.returnJson(True, '域名添加成功!') return mw.returnJson(True, '域名添加成功!')
def addDirBindApi(self): def addDirBindApi(self):
@@ -1400,7 +1426,7 @@ class site_api:
data['filename'] = filename data['filename'] = filename
return mw.getJson(data) return mw.getJson(data)
# 修改物理路径 # 修改物理路径
def setPathApi(self): def setPathApi(self):
mid = request.form.get('id', '') mid = request.form.get('id', '')
path = request.form.get('path', '') path = request.form.get('path', '')
@@ -2529,16 +2555,18 @@ location ^~ {from} {\n\
self.createRootDir(self.sitePath) self.createRootDir(self.sitePath)
self.nginxAddConf() self.nginxAddConf()
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
# 添加更多域名 # 添加更多域名
for domain in siteMenu['domainlist']: for domain in siteMenu['domainlist']:
self.addDomain(domain, self.siteName, pid) self.addDomain(domain, self.siteName, pid)
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
data = {} data = {}
data['siteStatus'] = False data['siteStatus'] = False
mw.restartWeb() mw.restartWeb()
self.runHook('site_cb', 'add')
return mw.returnJson(True, '添加成功') return mw.returnJson(True, '添加成功')
def deleteWSLogs(self, webname): def deleteWSLogs(self, webname):
@@ -2588,6 +2616,8 @@ location ^~ {from} {\n\
mw.execShell('rm -rf ' + ssl_acme_dir) mw.execShell('rm -rf ' + ssl_acme_dir)
mw.M('sites').where("id=?", (sid,)).delete() mw.M('sites').where("id=?", (sid,)).delete()
mw.M('domain').where("pid=?", (sid,)).delete()
mw.M('domain').where("name=?", (webname,)).delete()
# binding domain delete # binding domain delete
binding_list = mw.M('binding').field( binding_list = mw.M('binding').field(
@@ -2605,6 +2635,8 @@ location ^~ {from} {\n\
mw.M('binding').where("pid=?", (sid,)).delete() mw.M('binding').where("pid=?", (sid,)).delete()
mw.restartWeb() mw.restartWeb()
self.runHook('site_cb', 'delete')
return mw.returnJson(True, '站点删除成功!') return mw.returnJson(True, '站点删除成功!')
def setEndDate(self, sid, edate): def setEndDate(self, sid, edate):
+27
View File
@@ -166,6 +166,33 @@ class system_api:
except: except:
return False return False
def getEnvInfoApi(self, get=None):
serverInfo = {}
serverInfo['status'] = True
sdir = mw.getServerDir()
serverInfo['webserver'] = '未安装'
if os.path.exists(sdir + '/openresty/nginx/sbin/nginx'):
serverInfo['webserver'] = 'OpenResty'
serverInfo['php'] = []
phpversions = ['52', '53', '54', '55', '56', '70', '71',
'72', '73', '74', '80', '81', '82', '83', '84']
phpPath = sdir + '/php/'
for pv in phpversions:
if not os.path.exists(phpPath + pv + '/bin/php'):
continue
serverInfo['php'].append(pv)
serverInfo['mysql'] = False
if os.path.exists(sdir + '/mysql/bin/mysql'):
serverInfo['mysql'] = True
import psutil
try:
diskInfo = psutil.disk_usage('/www')
except:
diskInfo = psutil.disk_usage('/')
serverInfo['disk'] = diskInfo[2]
return mw.returnJson(True, 'ok', serverInfo)
def getPanelInfo(self, get=None): def getPanelInfo(self, get=None):
# 取面板配置 # 取面板配置
address = mw.GetLocalIp() address = mw.GetLocalIp()
+3
View File
@@ -65,6 +65,9 @@ class ORM:
def setCharset(self, charset): def setCharset(self, charset):
self.__DB_CHARSET = charset self.__DB_CHARSET = charset
def setHost(self, host):
self.__DB_HOST = host
def setPort(self, port): def setPort(self, port):
self.__DB_PORT = port self.__DB_PORT = port
+5 -1
View File
@@ -33,7 +33,11 @@ if [ ! -d $WEB_PATH ];then
mkdir -p $WEB_PATH mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
else else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH if [ -f $GIT_PROJECT_DIR/exclude.list ];then
rsync -vauP --delete --exclude-from="$GIT_PROJECT_DIR/exclude.list" $GIT_PROJECT_DIR/ $WEB_PATH
else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
fi
fi fi
sysName=`uname` sysName=`uname`
+1 -1
View File
@@ -8,7 +8,7 @@
"uninstall_pre_inspection":true, "uninstall_pre_inspection":true,
"checks": "server/mariadb", "checks": "server/mariadb",
"path": "server/mariadb", "path": "server/mariadb",
"versions":["10.6","10.7","10.8","10.9"], "versions":["10.6","10.7","10.8","10.9","10.11","11.0"],
"shell":"install.sh", "shell":"install.sh",
"checks":"server/mariadb", "checks":"server/mariadb",
"path":"server/mariadb", "path":"server/mariadb",
+1 -1
View File
@@ -1185,7 +1185,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.11.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+1 -1
View File
@@ -13,7 +13,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.6.9 MY_VER=10.6.12
Install_app() Install_app()
{ {
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.7.4 MY_VER=10.7.8
Install_app() Install_app()
{ {
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.8.5 MY_VER=10.8.7
Install_app() Install_app()
{ {
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb mariadbDir=${serverPath}/source/mariadb
MY_VER=10.9.2 MY_VER=10.9.5
Install_app() Install_app()
{ {
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.0.1
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+6 -6
View File
@@ -228,11 +228,11 @@ label.checkbox_label span {
</div> </div>
<div class="mtb20"> <div class="mtb20">
<span class="panel_setp_span">接收数据的面板地址</span> <span class="panel_setp_span">接收数据的面板地址</span>
<input type="text" class="bt-input-text" name="psync_url" value="" placeholder="接收数据面板地址,如: http://127.0.0.1:8888"> <input type="text" class="bt-input-text" name="sync_url" value="" placeholder="接收数据面板地址,如: http://127.0.0.1:8888">
</div> </div>
<div class="mtb20"> <div class="mtb20">
<span class="panel_setp_span">接收数据的面板API</span> <span class="panel_setp_span">接收数据的面板API</span>
<input type="text" class="bt-input-text" name="psync_token" value="" placeholder="接收数据面板API密钥" /> <input type="text" class="bt-input-text" name="sync_token" value="" placeholder="接收数据面板API密钥" />
<a href="#" target="_blank" class="btlink ml5">获取API秘钥</a> <a href="#" target="_blank" class="btlink ml5">获取API秘钥</a>
</div> </div>
<div class="mtb20"> <div class="mtb20">
@@ -243,8 +243,7 @@ label.checkbox_label span {
<button class="btn btn-success infoNext">下一步</button> <button class="btn btn-success infoNext">下一步</button>
</div> </div>
</div> </div>
<div class="pa15 psync_path" style="margin:0 50px"> <div class="pa15 psync_path" style="margin:0 50px;"></div>
</div>
<div class="pa15 psync_data" style="text-align: left;"> <div class="pa15 psync_data" style="text-align: left;">
<div class="checkbox_conten"> <div class="checkbox_conten">
<div class="checkbox_data"> <div class="checkbox_data">
@@ -253,7 +252,7 @@ label.checkbox_label span {
<input type="checkbox" id="sites_All" checked> <input type="checkbox" id="sites_All" checked>
<span>网站</span> <span>网站</span>
</label> </label>
<ul></ul> <ul id="sites_li"></ul>
</div> </div>
</div> </div>
<div class="checkbox_data"> <div class="checkbox_data">
@@ -262,7 +261,7 @@ label.checkbox_label span {
<input type="checkbox" id="db_All" checked> <input type="checkbox" id="db_All" checked>
<span>数据库</span> <span>数据库</span>
</label> </label>
<ul></ul> <ul id="db_li"></ul>
</div> </div>
</div> </div>
</div> </div>
@@ -286,6 +285,7 @@ label.checkbox_label span {
<script type="text/javascript"> <script type="text/javascript">
resetPluginWinWidth(700); resetPluginWinWidth(700);
resetPluginWinWidth(700);
$.getScript( "/plugins/file?name=migration_api&f=js/app.js", function(){ $.getScript( "/plugins/file?name=migration_api&f=js/app.js", function(){
initStep(); initStep();
}); });
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"sort": 7, "sort": 7,
"ps": "[<span style='color:red;'>潜龙勿用</span>]一键迁移,仅网站数据和MySQL数据", "ps": "[<span style='color:red;'>潜龙勿用</span>]一键迁移,仅网站数据和MySQL数据(仅支持源码安装软件)",
"name": "migration_api", "name": "migration_api",
"title": "一键迁移API", "title": "一键迁移API",
"shell": "install.sh", "shell": "install.sh",
+246 -22
View File
@@ -1,4 +1,24 @@
function maPost(method,args,callback){
function maPostNoMsg(method,args,callback){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
$.post('/plugins/run', {name:'migration_api', func:method, args:_args}, 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 maPost(method,args,callback, msg = '正在获取...'){
var _args = null; var _args = null;
if (typeof(args) == 'string'){ if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args)); _args = JSON.stringify(toArrayObject(args));
@@ -6,7 +26,7 @@ function maPost(method,args,callback){
_args = JSON.stringify(args); _args = JSON.stringify(args);
} }
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); var loadT = layer.msg(msg, { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'migration_api', func:method, args:_args}, function(data) { $.post('/plugins/run', {name:'migration_api', func:method, args:_args}, function(data) {
layer.close(loadT); layer.close(loadT);
if (!data.status){ if (!data.status){
@@ -30,6 +50,7 @@ function maAsyncPost(method,args){
return syncPost('/plugins/run', {name:'migration_api', func:method, args:_args}); return syncPost('/plugins/run', {name:'migration_api', func:method, args:_args});
} }
function maPostCallbak(method, args, callback){ function maPostCallbak(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
@@ -58,43 +79,246 @@ function maPostCallbak(method, args, callback){
} }
function initStep1(){ function selectProgress(val){
maPost('step_one',{}, function(rdata){ $('.step_head li').removeClass('active');
console.log(rdata); $('.step_head li').each(function(){
var v = $(this).find('span').text();
if (val == v){
$(this).addClass('active');
}
}); });
} }
function initStep1(){
var url = $('input[name="sync_url"]').val();
var token = $('input[name="sync_token"]').val();
maPost('step_one',{url:url,token:token}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
if (rdata.status){
initStep2();
}
},{ icon: rdata.status ? 1 : 2 });
},'API校验中...');
}
function initStep2(){ function initStep2(){
maPost('step_one',{}, function(rdata){ maPost('step_two',{}, function(rdata){
console.log(rdata); var rdata = $.parseJSON(rdata.data);
}); showMsg(rdata.msg,function(){
if (rdata.status){
selectProgress(2);
$('.psync_info').hide();
var info = rdata.data;
var body = '<div class="divtable">\
<table class="table table-hover">\
<thead>\
<tr><th style="border-right:1px solid #ddd">服务</th><th>当前服务器</th><th>远程服务器</th></tr>\
</thead>\
<tbody>\
<tr>\
<td style="border-right:1px solid #ddd">网站服务</td>\
<td>'+info['local']['webserver']+'</td>\
<td>'+info['remote']['webserver']+'</td>\
</tr>\
<tr>\
<td style="border-right:1px solid #ddd">安装MySQL</td>\
<td>'+(info['local']['mysql']?'是':'否')+'</td>\
<td>'+(info['remote']['mysql']?'是':'否')+'</td>\
</tr>\
<tr>\
<td style="border-right:1px solid #ddd">安装PHP</td>\
<td>'+(info['local']['php'].join('/'))+'</td>\
<td>'+(info['remote']['php'].join('/')) +'</td>\
</tr>\
<tr>\
<td style="border-right:1px solid #ddd">可用磁盘</td>\
<td>'+info['local']['disk']+'</td>\
<td>'+info['remote']['disk'][0]['size'][0]+'</td>\
</tr>\
</tbody>\
</table>\
</div>';
body += '<div class="line mtb20" style="text-align: left;">\
<button class="btn btn-default btn-sm mr20 pathTestting">重新检测</button>\
<button class="btn btn-default btn-sm mr20 pathBcak">上一步</button>\
<button class="btn btn-success btn-sm psync-next pathNext">下一步</button>\
</div>';
$('.psync_path').html(body);
$('.psync_path').show();
}
},{ icon: rdata.status ? 1 : 2 });
},'检测环境中...');
} }
function initStep3(){ function initStep3(){
maPost('step_one',{}, function(rdata){ maPost('step_three',{}, function(rdata){
console.log(rdata); var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
if (rdata.status){
selectProgress(3);
var pdata = rdata.data;
var site_li = '';
for (var i = 0; i < pdata.sites.length; i++) {
site_li+='<li>\
<label>\
<input type="checkbox" data-id="'+i+'" id="sites_'+pdata.sites[i]['name']+'" value="'+pdata.sites[i]['name']+'" name="sites" checked="">\
<span title="'+pdata.sites[i]['name']+'">'+pdata.sites[i]['name']+'</span>\
</label>\
</li>';
}
$('#sites_li').html(site_li);
var db_li = '';
for (var i = 0; i < pdata.databases.length; i++) {
db_li+='<li>\
<label>\
<input type="checkbox" data-id="'+i+'" id="sites_'+pdata.databases[i]['name']+'" value="'+pdata.databases[i]['name']+'" name="databases" checked="">\
<span title="'+pdata.databases[i]['name']+'">'+pdata.databases[i]['name']+'</span>\
</label>\
</li>';
}
$('#db_li').html(db_li);
$('.psync_path').hide();
$('.psync_data').show();
}
},{ icon: rdata.status ? 1 : 2 });
});
}
function renderMigrationProgress(){
maPostNoMsg('get_speed',{}, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log('speed:',rdata.data);
if (rdata.status){
if (rdata['data']['action'] == 'True'){
var end = '<div class="line">\
<div class="success text-center" style="padding: 10px 0 15px;">\
<p>数据迁移完成,请务必检查数据完整性!</p>\
<p style="font-size: 14px;margin-top:2px;color: #939292;">传输大小: '+toSize(rdata['data']['total_size'])+',耗时: '+rdata['data']['total_time']+',平均速度: '+toSize(rdata['data']['speed'])+'/s</p>\
<p class="mtb15">\
<button class="btn btn-success btn-sm mr5 okBtn">确定完成</button>\
<a class="btn btn-default btn-sm" style="margin-left: 10px;" target="_blank" href="/files/download?filename='+rdata['data']['log_file']+'">迁移日志</a>\
</p>\
</div>\
</div>';
$('.psync_migrate').html(end);
} else{
$('.psync_migrate .action').text(rdata['data']['action']);
$('.psync_migrate .done').text(rdata['data']['done']);
$('.psync_migrate pre').text(rdata['data']['log']);
var p = (rdata['data']['all_speed']/rdata['data']['all_total'])*100;
if (p>100){
p = 100;
}
$('.psync_migrate .progress_info_bar').width(p+'%');
$('.psync_migrate .progress_info').text(p+'%');
renderMigrationProgress();
}
} else{
layer.msg(rdata.msg,{icon:1});
}
}); });
} }
function initStep4(){ function initStep4(){
maPost('step_one',{}, function(rdata){ var site_checked = '';
console.log(rdata); $('input[name="sites"]:checked').each(function(){
site_checked += $(this).val()+',';
});
var databases_checked = '';
$('input[name="databases"]:checked').each(function(){
databases_checked+=$(this).val()+',';
});
maPost('step_four',{sites:site_checked,databases:databases_checked}, function(rdata){
var rdata = $.parseJSON(rdata.data);
selectProgress(4);
var progress = '<div style="margin: 0 40px;">\
<div class="line">\
<div style="text-align:left"><span class="action">--</span>\
<span style="margin-left: 20px;" class="done">当前: --</span><img src="/static/img/ing.gif"><a style="position: absolute;right: 40px;" class="btlink psync_close" onclick="migrate.close();">[取消]</a></div>\
<div class="bt-progress" style="border-radius:0;height:20px;line-height:19px">\
<div class="bt-progress-bar progress_info_bar" style="border-radius: 0px; height: 20px; width: 0%;">\
<span class="bt-progress-text progress_info"></span></div>\
</div>\
</div>\
</div>\
<pre style="height: 222px;text-align: left;margin:5px 38px 0;font-size: 12px;line-height: 20px;padding: 10px;background-color: #333;color: #fff;"></pre>\
</div>';
$('.psync_data').hide();
$('.psync_migrate').html(progress);
$('.psync_migrate').show();
renderMigrationProgress();
}); });
} }
function initStep(){ function initStep(){
console.log($('.infoNext')); maPost('get_conf',{}, function(rdata){
var rdata = $.parseJSON(rdata.data);
$('input[name="sync_url"]').val(rdata.data['url']);
$('input[name="sync_token"]').val(rdata.data['token']);
});
$('.infoNext').click(function(){ $('.infoNext').click(function(){
var step = $('.step_head .active span').text(); initStep1();
// console.log(step); });
// initStep1();
switch(step){ // 重新检测按钮
case '1':initStep1();break; $('.psync_path').on('click', '.pathTestting', function () {
case '2':initStep2();break; initStep2();
case '3':initStep3();break; });
case '4':initStep4();break;
} $('.psync_path').on('click', '.pathBcak', function(){
$('.psync_path').hide();
$('.psync_info').show();
selectProgress(1);
});
$('.psync_path').on('click', '.pathNext', function(){
initStep3();
});
$('.psync_data').on('click', '.dataBack', function(){
$('.psync_data').hide();
$('.psync_path').show();
selectProgress(2);
});
$('.psync_data').on('click', '.dataMigrate', function(){
initStep4();
});
$('#sites_All').on('click',function(){
var ch = $(this).prop('checked');
$('#sites_li input').prop('checked',ch);
});
$('#db_All').on('click',function(){
var ch = $(this).prop('checked');
$('#db_li input').prop('checked',ch);
});
$('.psync_migrate').on('click', '.okBtn', function(){
$('.psync_migrate').hide();
$('.psync_info').show();
selectProgress(1);
}); });
} }
+1
View File
@@ -65,6 +65,7 @@ binlog-ignore-db = performance_schema
#slave #slave
log-slave-updates log-slave-updates
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1
View File
@@ -62,6 +62,7 @@ binlog-ignore-db = performance_schema
#slave #slave
log_replica_updates log_replica_updates
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+2 -1
View File
@@ -2474,7 +2474,8 @@ def doFullSyncUser(version=''):
if not os.path.exists(bak_file): if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \ dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
mw.execShell(dump_sql_data) mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40}) writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+1 -1
View File
@@ -1208,7 +1208,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+1
View File
@@ -66,6 +66,7 @@ binlog-ignore-db = performance_schema
#slave #slave
log-slave-updates log-slave-updates
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1
View File
@@ -62,6 +62,7 @@ binlog-ignore-db = performance_schema
#slave #slave
log_replica_updates log_replica_updates
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+2 -1
View File
@@ -2434,7 +2434,8 @@ def doFullSyncUser(version=''):
if not os.path.exists(bak_file): if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \ dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
mw.execShell(dump_sql_data) mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40}) writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+1 -1
View File
@@ -1208,7 +1208,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+1
View File
@@ -70,6 +70,7 @@ log-slave-updates = 1
# Prevent replication from starting automatically with MySQL # Prevent replication from starting automatically with MySQL
#skip-slave-start = 1 #skip-slave-start = 1
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1
View File
@@ -72,6 +72,7 @@ log-slave-updates = 1
# Prevent replication from starting automatically with MySQL # Prevent replication from starting automatically with MySQL
#skip-slave-start = 1 #skip-slave-start = 1
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1
View File
@@ -73,6 +73,7 @@ binlog-ignore-db = performance_schema
# Prevent replication from starting automatically with MySQL # Prevent replication from starting automatically with MySQL
#skip-slave-start = 1 #skip-slave-start = 1
#replicate-do-db #replicate-do-db
slave_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1
View File
@@ -71,6 +71,7 @@ log_replica_updates = 1
# Prevent replication from starting automatically with MySQL # Prevent replication from starting automatically with MySQL
#skip_replica_start = 1 #skip_replica_start = 1
#replicate-do-db #replicate-do-db
replica_skip_errors=1062
replicate-ignore-db = information_schema replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema replicate-ignore-db = performance_schema
replicate-ignore-db = mysql replicate-ignore-db = mysql
+1 -1
View File
@@ -16,7 +16,7 @@
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p> <p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div> </div>
<div class="bt-w-con pd15"> <div class="bt-w-con pd15">
<div class="soft-man-con" style="height: 530px; overflow: auto;"></div> <div class="soft-man-con"></div>
</div> </div>
</div> </div>
+68 -13
View File
@@ -48,19 +48,20 @@ def getInitDFile():
def getArgs(): def getArgs():
args = sys.argv[2:] args = sys.argv[2:]
tmp = {} tmp = {}
args_len = len(args) args_len = len(args)
if args_len == 1: if args_len == 1:
t = args[0].strip('{').strip('}') t = args[0].strip('{').strip('}')
t = t.split(':') if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1] tmp[t[0]] = t[1]
elif args_len > 1: elif args_len > 1:
for i in range(len(args)): for i in range(len(args)):
t = args[i].split(':') t = args[i].split(':', 1)
tmp[t[0]] = t[1] tmp[t[0]] = t[1]
return tmp return tmp
@@ -842,12 +843,29 @@ def setDbBackup():
return data[1] return data[1]
scDir = mw.getRunDir() + '/scripts/backup.py' scDir = mw.getRunDir() + '/scripts/backup.py'
cmd = 'python3 ' + scDir + ' database ' + args['name'] + ' 3' cmd = 'python3 ' + scDir + ' database ' + args['name'] + ' 3'
os.system(cmd) os.system(cmd)
return mw.returnJson(True, 'ok') return mw.returnJson(True, 'ok')
# 数据库密码处理
def myPass(act, root):
conf_file = getConf()
mw.execShell("sed -i '/user=root/d' {}".format(conf_file))
mw.execShell("sed -i '/password=/d' {}".format(conf_file))
if act:
mycnf = mw.readFile(conf_file)
src_dump = "[mysqldump]\n"
sub_dump = src_dump + "user=root\npassword=\"{}\"\n".format(root)
if not mycnf:
return False
mycnf = mycnf.replace(src_dump, sub_dump)
if len(mycnf) > 100:
mw.writeFile(conf_file, mycnf)
return True
return True
def importDbExternal(): def importDbExternal():
args = getArgs() args = getArgs()
data = checkArgs(args, ['file', 'name']) data = checkArgs(args, ['file', 'name'])
@@ -902,11 +920,16 @@ def importDbExternal():
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root') pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile() sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd my_cnf = getConf()
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql
myPass(True, pwd)
mysql_cmd = getServerDir() + '/bin/mysql --defaults-file=' + my_cnf + \
' -uroot -p\"' + pwd + '\" -f ' + name + ' < ' + import_sql
# print(mysql_cmd)
rdata = mw.execShell(mysql_cmd) rdata = mw.execShell(mysql_cmd)
myPass(False, pwd)
# print(rdata)
if ext != 'sql': if ext != 'sql':
os.remove(import_sql) os.remove(import_sql)
@@ -2371,6 +2394,25 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version) return initSlaveStatusSyncUser(version)
def makeSyncUsercmd(u, version=''):
mode = recognizeDbMode()
sql = ''
ip = u['ip']
port = u['port']
username = u['user']
password = u['pass']
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
username + "', MASTER_PASSWORD='" + \
password + "', MASTER_AUTO_POSITION=1"
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
username + "', SOURCE_PASSWORD='" + \
password + "', MASTER_AUTO_POSITION=1"
return sql
def initSlaveStatusSyncUser(version=''): def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user') conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find() data = conn.field('ip,port,user,pass,mode,cmd').find()
@@ -2393,8 +2435,19 @@ def initSlaveStatusSyncUser(version=''):
if local_mode != mode_name: if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!') return mw.returnJson(False, '同步模式不一致!')
t = db.query(u['cmd']) if u['cmd'] == '' and local_mode == 'gtid':
# print(t) sql = makeSyncUsercmd(u, version)
# print(sql)
t = db.query(sql)
else:
if u['cmd'] == '':
return mw.returnJson(False, '经典模式下,必须手写同步命令!')
# print(u['cmd'])
t = db.query(u['cmd'])
isError = isSqlError(t)
if isError:
return isError
db.query("start slave user='{}' password='{}';".format( db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass'])) u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!') return mw.returnJson(True, '初始化成功!')
@@ -2612,8 +2665,10 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20}) writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file): if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \ dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data) mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40}) writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+1 -1
View File
@@ -1208,7 +1208,7 @@ function myLogs(){
<span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\ <span class="f14 c6 mr20">二进制日志 </span><span class="f14 c6 mr20">' + toSize(rdata.msg) + '</span>\
'+line_status+'\ '+line_status+'\
<p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\ <p class="f14 c6 mtb10" style="border-top:#ddd 1px solid; padding:10px 0">错误日志<button class="btn btn-default btn-clear btn-xs" style="float:right;" >清理日志</button></p>\
<textarea readonly style="margin: 0px;width: 100%;height: 440px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\ <textarea readonly style="margin: 0px;width: 100%;height: 438px;background-color: #333;color:#fff; padding:0 5px" id="error_log"></textarea>\
</p>'; </p>';
$(".soft-man-con").html(limitCon); $(".soft-man-con").html(limitCon);
+13 -1
View File
@@ -1,4 +1,16 @@
{ {
"hook":[
{
"tag":"site_cb",
"site_cb": {
"title":"网站统计",
"name":"op_waf",
"add":{"func":"reload"},
"update":{"func":"reload"},
"delete":{"func":"reload"}
}
}
],
"title":"OP防火墙", "title":"OP防火墙",
"tip":"soft", "tip":"soft",
"name":"op_waf", "name":"op_waf",
@@ -12,5 +24,5 @@
"home":"https://github.com/loveshell/ngx_lua_waf", "home":"https://github.com/loveshell/ngx_lua_waf",
"date":"2019-04-21", "date":"2019-04-21",
"pid": "1", "pid": "1",
"versions": ["0.2.5"] "versions": ["0.2.6"]
} }
+10 -1
View File
@@ -344,13 +344,22 @@ local function waf_cc_increase()
local make_uri = "/"..make_uri_str local make_uri = "/"..make_uri_str
if params['uri_request_args']['token'] then if params['uri_request_args']['token'] then
ngx.header.content_type = "application/json"
local args_token = params['uri_request_args']['token'] local args_token = params['uri_request_args']['token']
if args_token == make_token then if args_token == make_token then
ngx.shared.waf_limit:set(cache_token, 1, config['safe_verify']['time']) ngx.shared.waf_limit:set(cache_token, 1, tonumber(config['safe_verify']['time']))
local data = get_return_state(0, "ok") local data = get_return_state(0, "ok")
ngx.say(json.encode(data)) ngx.say(json.encode(data))
ngx.exit(200) ngx.exit(200)
end end
-- C:D("debug[args]:"..tostring(params['uri_request_args']['debug']))
-- if params['uri_request_args']['debug'] == 'ok' then
-- ngx.header.content_type = "application/json"
-- local data = get_return_state(0, "ok")
-- ngx.say(json.encode(data))
-- ngx.exit(200)
-- end
end end
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str) local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
+2 -2
View File
@@ -204,8 +204,8 @@ def initDreplace():
mw.writeFile(file_bin, content) mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin) mw.execShell('chmod +x ' + file_bin)
# config replace # config replace
confReplace() confReplace()
# systemd # systemd
# /usr/lib/systemd/system # /usr/lib/systemd/system
+1 -1
View File
@@ -59,11 +59,11 @@ Install_openresty()
mkdir -p ${openrestyDir} mkdir -p ${openrestyDir}
echo '正在安装脚本文件...' > $install_tmp echo '正在安装脚本文件...' > $install_tmp
# wget -O openresty-1.21.4.1.tar.gz https://openresty.org/download/openresty-1.21.4.1.tar.gz
if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then
wget -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://openresty.org/download/openresty-${VERSION}.tar.gz wget -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://openresty.org/download/openresty-${VERSION}.tar.gz
fi fi
cd ${openrestyDir} && tar -zxvf openresty-${VERSION}.tar.gz cd ${openrestyDir} && tar -zxvf openresty-${VERSION}.tar.gz
# --with-openssl=$serverPath/source/lib/openssl-1.0.2q # --with-openssl=$serverPath/source/lib/openssl-1.0.2q
+1
View File
@@ -17,6 +17,7 @@
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
resetPluginWinHeight(500);
$.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js", function(){ $.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js", function(){
pluginService('phpmyadmin'); pluginService('phpmyadmin');
}); });
+2 -1
View File
@@ -47,6 +47,7 @@ Install_phpmyadmin()
mkdir -p ${serverPath}/phpmyadmin mkdir -p ${serverPath}/phpmyadmin
mkdir -p ${serverPath}/source/phpmyadmin mkdir -p ${serverPath}/source/phpmyadmin
echo "${1}" > ${serverPath}/phpmyadmin/version.pl
VER=$1 VER=$1
@@ -67,7 +68,7 @@ Install_phpmyadmin()
cd $serverPath/phpmyadmin/ && mv $FDIR phpmyadmin cd $serverPath/phpmyadmin/ && mv $FDIR phpmyadmin
echo "${1}" > ${serverPath}/phpmyadmin/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp
cd ${rootPath} && python3 ${rootPath}/plugins/phpmyadmin/index.py start cd ${rootPath} && python3 ${rootPath}/plugins/phpmyadmin/index.py start
-1
View File
@@ -26,7 +26,6 @@ AutoRename no
AnonymousCantUpload no AnonymousCantUpload no
MaxDiskUsage 99 MaxDiskUsage 99
CustomerProof yes CustomerProof yes
PassivePortRange 48000 50000
PIDFile {$SERVER_PATH}/pureftp/etc/pure-ftpd.pid PIDFile {$SERVER_PATH}/pureftp/etc/pure-ftpd.pid
PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb
+5
View File
@@ -9,6 +9,11 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
sysName=`uname` sysName=`uname`
echo "use system: ${sysName}" echo "use system: ${sysName}"
+4 -3
View File
@@ -214,7 +214,8 @@ def initdStatus():
if mw.isAppleSystem(): if mw.isAppleSystem():
return "Apple Computer does not support" return "Apple Computer does not support"
shell_cmd = 'systemctl status redis | grep loaded | grep "enabled;"' shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd) data = mw.execShell(shell_cmd)
if data[0] == '': if data[0] == '':
return 'fail' return 'fail'
@@ -225,7 +226,7 @@ def initdInstall():
if mw.isAppleSystem(): if mw.isAppleSystem():
return "Apple Computer does not support" return "Apple Computer does not support"
mw.execShell('systemctl enable redis') mw.execShell('systemctl enable ' + getPluginName())
return 'ok' return 'ok'
@@ -233,7 +234,7 @@ def initdUinstall():
if mw.isAppleSystem(): if mw.isAppleSystem():
return "Apple Computer does not support" return "Apple Computer does not support"
mw.execShell('systemctl disable redis') mw.execShell('systemctl disable ' + getPluginName())
return 'ok' return 'ok'
+2 -13
View File
@@ -1,14 +1,3 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function redisPost(method, version, args,callback){ function redisPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
@@ -18,7 +7,7 @@ function redisPost(method, version, args,callback){
req_data['version'] = version; req_data['version'] = version;
if (typeof(args) == 'string'){ if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args)); req_data['args'] = JSON.stringify(toArrayObject(args));
} else { } else {
req_data['args'] = JSON.stringify(args); req_data['args'] = JSON.stringify(args);
} }
@@ -46,7 +35,7 @@ function redisPostCallbak(method, version, args,callback){
args['version'] = version; args['version'] = version;
if (typeof(args) == 'string'){ if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args)); req_data['args'] = JSON.stringify(toArrayObject(args));
} else { } else {
req_data['args'] = JSON.stringify(args); req_data['args'] = JSON.stringify(args);
} }
+4
View File
@@ -16,6 +16,10 @@ bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl` OSNAME=`cat ${rootPath}/data/osname.pl`
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
if id www &> /dev/null ;then if id www &> /dev/null ;then
echo "www uid is `id -u www`" echo "www uid is `id -u www`"
echo "www shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `" echo "www shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
+127
View File
@@ -0,0 +1,127 @@
#
# Discuz Sphinx Config File
#
indexer
{
mem_limit = 32M
write_buffer = 64M
}
searchd
{
listen = 9312
listen = 9306:mysql41
log = {$SERVER_APP}/index/searchd.log
query_log = {$SERVER_APP}/index/query.log
read_timeout = 5
max_children = 0
pid_file = {$SERVER_APP}/index/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
#workers = threads # for RT to work
binlog_path = {$SERVER_APP}/index/binlog
}
source pre_forum_thread
{
type = mysql
sql_host = 127.0.0.1
sql_user = bbs
sql_pass = bbs
sql_db = bbs
sql_port = 3306
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO bbs_common_sphinxcounter SELECT 1, MAX(tid) FROM bbs_forum_thread
sql_query = SELECT t.tid as id,t.tid,t.subject,t.digest,t.displayorder,t.authorid,t.lastpost,t.special \
FROM bbs_forum_thread AS t WHERE t.tid>=$start AND t.tid<=$end
sql_query_range = SELECT (SELECT MIN(tid) FROM bbs_forum_thread),maxid FROM bbs_common_sphinxcounter WHERE indexid=1
sql_range_step = 5000
sql_attr_uint = tid
sql_attr_uint = digest
sql_attr_uint = displayorder
sql_attr_uint = authorid
sql_attr_uint = special
sql_attr_timestamp =lastpost
}
index pre_forum_thread
{
source = pre_forum_thread
path = {$SERVER_APP}/index/db/pre_forum_thread/index
min_word_len = 2
html_strip = 1
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
}
# threads_minute
source pre_forum_thread_minute : pre_forum_thread
{
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_range = SELECT maxid-1,(SELECT MAX(tid) FROM bbs_forum_thread) FROM bbs_common_sphinxcounter WHERE indexid=1
}
# threads_minute
index pre_forum_thread_minute : pre_forum_thread
{
source = pre_forum_thread_minute
path = {$SERVER_APP}/index/db/pre_forum_thread/pre_forum_thread_minute
}
#posts
source pre_forum_post : pre_forum_thread
{
type = mysql
sql_query_pre =
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO bbs_common_sphinxcounter SELECT 2, MAX(pid) FROM bbs_forum_post
sql_query = SELECT p.pid AS id,p.tid,p.subject,p.message,t.digest,t.displayorder,t.authorid,t.lastpost,t.special \
FROM bbs_forum_post AS p LEFT JOIN bbs_forum_thread AS t USING(tid) where p.pid >=$start and p.pid <=$end \
AND p.first=1
sql_query_range = SELECT (SELECT MIN(pid) FROM bbs_forum_post),maxid FROM bbs_common_sphinxcounter WHERE indexid=2
sql_range_step = 5000
sql_attr_uint = tid
sql_attr_uint = digest
sql_attr_uint= displayorder
sql_attr_uint = authorid
sql_attr_uint = special
sql_attr_timestamp = lastpost
}
#posts
index pre_forum_post
{
source = pre_forum_post
path = {$SERVER_APP}/index/db/pre_forum_thread/pre_forum_post
min_word_len = 2
html_strip = 1
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
}
#pre_forum_post_minute
source pre_forum_post_minute : pre_forum_post
{
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_range = SELECT maxid-1,(SELECT MAX(pid) FROM bbs_forum_post) FROM bbs_common_sphinxcounter WHERE indexid=2
}
#pre_forum_post_minute
index pre_forum_post_minute : pre_forum_post
{
source = pre_forum_thread
path = {$SERVER_APP}/index/db/pre_forum_thread/pre_forum_post_minute
}
+1 -1
View File
@@ -23,7 +23,7 @@
.code span {display: block;margin-left: 15px;margin-bottom: 0;} .code span {display: block;margin-left: 15px;margin-bottom: 0;}
</style> </style>
<script type="text/javascript"> <script type="text/javascript">
resetPluginWinWidth(800); resetPluginWinWidth(850);
$.getScript( "/plugins/file?name=supervisor&f=js/supervisor.js", function(){ $.getScript( "/plugins/file?name=supervisor&f=js/supervisor.js", function(){
pluginService('supervisor'); pluginService('supervisor');
}); });
+28 -3
View File
@@ -220,7 +220,8 @@ def getSupList():
infos = fr.readlines() infos = fr.readlines()
for line in infos: for line in infos:
if "command=" in line.strip(): if "command=" in line.strip():
d["command"] = line.strip().split('=')[1] # d["command"] = line.strip().split('=')[1]
d["command"] = "子配置查看"
if "user=" in line.strip(): if "user=" in line.strip():
d["user"] = line.strip().split('=')[1] d["user"] = line.strip().split('=')[1]
if "priority=" in line.strip(): if "priority=" in line.strip():
@@ -329,6 +330,27 @@ def startJob():
return mw.returnJson(True, action + '[' + name + ']成功!') return mw.returnJson(True, action + '[' + name + ']成功!')
def restartJob():
args = getArgs()
data = checkArgs(args, ['name', 'status'])
if not data[0]:
return data[1]
supCtl = 'supervisorctl -c ' + getServerDir() + "/supervisor.conf"
name = args['name']
status = args['status']
cmd = supCtl + " stop " + name
data = mw.execShell(cmd)
cmd = supCtl + " start " + name
data = mw.execShell(cmd)
if data[1] != '':
return mw.returnJson(False, '[' + name + ']重启失败!')
return mw.returnJson(True, '[' + name + ']重启成功!')
def delJob(): def delJob():
args = getArgs() args = getArgs()
data = checkArgs(args, ['name']) data = checkArgs(args, ['name'])
@@ -440,8 +462,9 @@ def configTpl():
pathFile = os.listdir(path) pathFile = os.listdir(path)
tmp = [] tmp = []
for one in pathFile: for one in pathFile:
file = path + '/' + one if one.endswith(".ini"):
tmp.append(file) file = path + '/' + one
tmp.append(file)
return mw.getJson(tmp) return mw.getJson(tmp)
@@ -567,6 +590,8 @@ if __name__ == "__main__":
print(addJob()) print(addJob())
elif func == 'start_job': elif func == 'start_job':
print(startJob()) print(startJob())
elif func == 'restart_job':
print(restartJob())
elif func == 'del_job': elif func == 'del_job':
print(delJob()) print(delJob())
elif func == 'update_job': elif func == 'update_job':
+11
View File
@@ -70,6 +70,7 @@ function supList(page, search){
list += '<td style="text-align:right">\ list += '<td style="text-align:right">\
<a href="javascript:;" class="btlink" onclick="startOrStop(\''+rdata.data[i]['program']+'\',\''+sup_status+'\')" title="启动|停止">'+sup_status_desc+'</a> | ' + <a href="javascript:;" class="btlink" onclick="startOrStop(\''+rdata.data[i]['program']+'\',\''+sup_status+'\')" title="启动|停止">'+sup_status_desc+'</a> | ' +
'<a href="javascript:;" class="btlink" onclick="restartJob(\''+rdata.data[i]['program']+'\',\''+sup_status+'\')" title="重启">重启</a> | ' +
'<a href="javascript:;" class="btlink" onclick="updateJob(\''+rdata.data[i]['program']+'\')">修改</a> | ' + '<a href="javascript:;" class="btlink" onclick="updateJob(\''+rdata.data[i]['program']+'\')">修改</a> | ' +
'<a href="javascript:;" class="btlink" onclick="delJob(\''+rdata.data[i]['program']+'\')" title="删除">删除</a>' + '<a href="javascript:;" class="btlink" onclick="delJob(\''+rdata.data[i]['program']+'\')" title="删除">删除</a>' +
'</td>'; '</td>';
@@ -128,6 +129,16 @@ function startOrStop(name,status){
}); });
} }
function restartJob(name,status){
myPost('restart_job',{'name':name,'status':status}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
setTimeout(function(){
supList(1,10);
},2000);
});
}
function updateJob(name){ function updateJob(name){
myPost('get_job_info',{'name':name},function(data){ myPost('get_job_info',{'name':name},function(data){
var rdata = $.parseJSON(data.data); var rdata = $.parseJSON(data.data);
Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

+26
View File
@@ -0,0 +1,26 @@
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('tgbot');">服务</p>
<p onclick="pluginInitD('tgbot');">自启动</p>
<p onclick="botConf();">Bot配置</p>
<p onclick="botExtList();">扩展列表</p>
<p onclick="pluginLogs('tgbot','','run_log');">日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<style>
.conf_p span{
width: 70px;
}
</style>
<script type="text/javascript">
resetPluginWinHeight(350);
$.getScript( "/plugins/file?name=tgbot&f=js/tgbot.js", function(){
pluginService('tgbot');
});
</script>
+367
View File
@@ -0,0 +1,367 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import base64
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'tgbot'
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 getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeConf(data):
cfg_path = getServerDir() + "/data.cfg"
mw.writeFile(cfg_path, json.dumps(data))
return True
def getExtCfg():
cfg_path = getServerDir() + "/extend.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeExtCfg(data):
cfg_path = getServerDir() + "/extend.cfg"
return mw.writeFile(cfg_path, json.dumps(data))
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':')
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def status():
data = mw.execShell(
"ps -ef|grep tgbot |grep -v grep | grep -v mdserver-web | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
file_tpl = getInitDTpl()
service_path = mw.getServerDir()
app_path = service_path + '/' + getPluginName()
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 = content.replace('{$SERVER_PATH}', service_path + '/mdserver-web')
content = content.replace('{$APP_PATH}', app_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/tgbot.service'
systemServiceTpl = getPluginDir() + '/init.d/tgbot.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('{$APP_PATH}', app_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def tbOp(method):
file = initDreplace()
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell(file + ' ' + method)
# print(data)
if data[1] == '':
return 'ok'
return 'ok'
def start():
return tbOp('start')
def stop():
return tbOp('stop')
def restart():
status = tbOp('restart')
return status
def reload():
tgbot_tpl = getPluginDir() + '/startup/tgbot.py'
tgbot_dst = getServerDir() + '/tgbot.py'
content = mw.readFile(tgbot_tpl)
mw.writeFile(tgbot_dst, content)
ext_src = getPluginDir() + '/startup/extend'
ext_dst = getServerDir()
mw.execShell('cp -rf ' + ext_src + ' ' + ext_dst)
return tbOp('restart')
def initdStatus():
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl enable ' + getPluginName())
return 'ok'
def initdUinstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable ' + getPluginName())
return 'ok'
def getBotConf():
data = getConfigData()
if 'bot' in data:
return mw.returnJson(True, 'ok', data['bot'])
return mw.returnJson(False, 'ok', {})
def setBotConf():
args = getArgs()
data_args = checkArgs(args, ['app_token'])
if not data_args[0]:
return data_args[1]
data = getConfigData()
args['app_token'] = base64.b64decode(args['app_token']).decode('ascii')
data['bot'] = args
writeConf(data)
return mw.returnJson(True, '保存成功!', [])
def installPreInspection():
i = sys.version_info
if i[0] < 3 or i[1] < 7:
return "telebot在python小于3.7无法正常使用"
return 'ok'
def uninstallPreInspection():
stop()
return "请手动删除<br/> rm -rf {}".format(getServerDir())
def getExtCfgByName(name):
elist = getExtCfg()
for x in elist:
if x['name'] == name:
return x
return None
def botExtList():
args = getArgs()
data_args = checkArgs(args, ['p'])
if not data_args[0]:
return data_args[1]
ext_path = getServerDir() + '/extend'
if not os.path.exists(ext_path):
return mw.returnJson(False, 'ok', [])
elist_source = os.listdir(ext_path)
elist = []
for e in elist_source:
if e.endswith('py'):
elist.append(e)
page = int(args['p'])
page_size = 5
make_ext_list = []
for ex in elist:
tmp = {}
tmp['name'] = ex
edata = getExtCfgByName(ex)
if edata:
tmp['status'] = edata['status']
else:
tmp['status'] = 'stop'
tmp['tag'] = ex.split('_')[0]
make_ext_list.append(tmp)
writeExtCfg(make_ext_list)
dlist_sum = len(make_ext_list)
page_start = int((page - 1) * page_size)
page_end = page_start + page_size
if page_end >= dlist_sum:
ret_data = make_ext_list[page_start:]
else:
ret_data = make_ext_list[page_start:page_end]
data = {}
data['data'] = ret_data
data['args'] = args
data['list'] = mw.getPage(
{'count': dlist_sum, 'p': page, 'row': page_size, 'tojs': 'botExtListP'})
return mw.returnJson(True, 'ok', data)
def setExtStatus():
args = getArgs()
data_args = checkArgs(args, ['name', 'status'])
if not data_args[0]:
return data_args[1]
elist = getExtCfg()
name = args['name']
status = args['status']
for x in range(len(elist)):
if elist[x]['name'] == name:
elist[x]['status'] = status
break
writeExtCfg(elist)
action = '开启'
if status == 'stop':
action = '关闭'
return mw.returnJson(True, action + '[' + name + ']扩展成功')
def runLog():
p = getServerDir() + '/task.log'
return p
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 == 'install_pre_inspection':
print(installPreInspection())
elif func == 'uninstall_pre_inspection':
print(uninstallPreInspection())
elif func == 'get_bot_conf':
print(getBotConf())
elif func == 'set_bot_conf':
print(setBotConf())
elif func == 'bot_ext_list':
print(botExtList())
elif func == 'set_ext_status':
print(setExtStatus())
elif func == 'run_log':
print(runLog())
else:
print('error')
+20
View File
@@ -0,0 +1,20 @@
{
"sort": 7,
"ps": "简单Telegram机器人",
"name": "tgbot",
"title": "tgbot",
"shell": "install.sh",
"versions":["1.0"],
"tip": "soft",
"checks": "server/tgbot",
"path": "server/tgbot",
"install_pre_inspection":true,
"uninstall_pre_inspection":true,
"display": 1,
"author": "midokos",
"date": "2023-03-06",
"home": "https://core.telegram.org/bots/api",
"depend_doc1":"https://github.com/eternnoir/pyTelegramBotAPI",
"type": 0,
"pid": "5"
}
+14
View File
@@ -0,0 +1,14 @@
[Unit]
Description=Tgbot Service
After=network.target
[Service]
Type=forking
ExecStart={$APP_PATH}/init.d/tgbot start
ExecStop={$APP_PATH}/init.d/tgbot stop
ExecReload={$APP_PATH}/init.d/tgbot reload
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
+85
View File
@@ -0,0 +1,85 @@
#!/bin/sh
# chkconfig: 2345 55 25
# description: Tgbot Service
### BEGIN INIT INFO
# Provides: Tgbot
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts Tgbot
# Description: starts the MDW-Web
### END INIT INFO
# Simple Tgbot init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export LANG=en_US.UTF-8
mw_path={$SERVER_PATH}
PATH=$PATH:$mw_path/bin
if [ -f $mw_path/bin/activate ];then
source $mw_path/bin/activate
fi
tg_start(){
isStart=`ps -ef|grep 'tgbot.py' |grep -v grep | awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "starting tgbot... \c"
cd $mw_path
python3 {$APP_PATH}/tgbot.py >> {$APP_PATH}/task.log &
isStart=""
while [[ "$isStart" == "" ]];
do
echo -e ".\c"
sleep 0.5
isStart=`ps -ef|grep 'tgbot.py' |grep -v grep | awk '{print $2}'`
let n+=1
if [ $n -gt 20 ];then
break;
fi
done
if [ "$isStart" == '' ];then
echo -e "\033[31mfailed\033[0m"
echo -e "\033[31mError: tgbot service startup failed.\033[0m"
return;
fi
echo -e "\033[32mdone\033[0m"
else
echo "starting tgbot...(pid $(echo $isStart)) already running"
fi
}
tg_stop(){
echo -e "stopping tgbot ... \c";
arr=`ps aux|grep 'tgbot.py'|grep -v grep|awk '{print $2}'`
for p in ${arr[@]}
do
kill -9 $p > /dev/null 2>&1
done
echo -e "\033[32mdone\033[0m"
}
case "$1" in
start)
tg_start
;;
stop)
tg_stop
;;
restart|reload)
tg_stop
sleep 0.3
tg_start
;;
*)
echo "Please use start or stop as first argument"
;;
esac
+59
View File
@@ -0,0 +1,59 @@
#!/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=$2
# pip3 install ccxt
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
pip3 install pyTelegramBotAPI
pip3 install telebot
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/tgbot
echo "${VERSION}" > $serverPath/tgbot/version.pl
cp -rf ${rootPath}/plugins/tgbot/startup/* $serverPath/tgbot
cd ${rootPath} && python3 ${rootPath}/plugins/tgbot/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/tgbot/index.py initd_install
echo '安装完成' > $install_tmp
}
Uninstall_App()
{
if [ -f /usr/lib/systemd/system/tgbot.service ];then
systemctl stop tgbot
systemctl disable tgbot
rm -rf /usr/lib/systemd/system/tgbot.service
systemctl daemon-reload
fi
if [ -f $serverPath/tgbot/initd/tgbot ];then
$serverPath/tgbot/initd/tgbot stop
fi
rm -rf $serverPath/tgbot
echo "Uninstall_redis" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+148
View File
@@ -0,0 +1,148 @@
function appPost(method, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'tgbot';
req_data['func'] = method;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', req_data, function(data) {
layer.close(loadT);
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function appPostCallbak(method, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'tgbot';
req_data['func'] = method;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function botConf(){
appPost('get_bot_conf','',function(data){
var rdata = $.parseJSON(data.data);
var app_token = 'app_token';
if(rdata['status']){
db_data = rdata['data'];
app_token = db_data['app_token'];
}
var mlist = '';
mlist += '<p><span>app_token</span><input style="width: 250px;" class="bt-input-text mr5" name="app_token" value="'+app_token+'" type="text"><font>必填写</font></p>'
var option = '<style>.conf_p p{margin-bottom: 2px}</style>\
<div class="conf_p" style="margin-bottom:0">\
' + mlist + '\
<div style="margin-top:10px; padding-right:15px" class="text-right">\
<button class="btn btn-success btn-sm" onclick="submitBotConf()">保存</button>\
</div>\
</div>';
$(".soft-man-con").html(option);
});
}
function submitBotConf(){
var pull_data = {};
pull_data['app_token'] = base64_encode($('input[name="app_token"]').val());
appPost('set_bot_conf',pull_data,function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata['msg'],{icon:rdata['status']?1:2,time:2000,shade: [0.3, '#000']});
});
}
function botExtList(){
var body = '<div class="divtable mtb10">\
<table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">\
<thead>\
<tr>\
<th width="20">脚本</th>\
<th width="120">类型</th>\
<th width="10">状态</th>\
</tr>\
</thead>\
<tbody id="ext_list"></tbody>\
</table>\
<div class="dataTables_paginate paging_bootstrap pagination">\
<ul id="ext_list_page" class="page"></ul>\
</div>\
</div>';
$('.soft-man-con').html(body);
botExtListP(1);
}
function setBotExtStatus(name,status){
appPost('set_ext_status',{'name':name,'status':status}, function(rdata){
var rdata = $.parseJSON(rdata.data);
layer.msg(rdata['msg'],);
showMsg(rdata['msg'], function(){
botExtListP(1);
},{icon:rdata['status']?1:2,shade: [0.3, '#000']},2000);
});
}
function botExtListP(p=1){
appPost('bot_ext_list',{'p':p}, function(rdata){
// console.log(rdata);
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
var tBody = '';
if (!rdata.status && rdata.data.length == 0 ){
var tBody = '<tr><td colspan="4"><div style="text-align:center;">无数据</div></td></tr>';
} else{
var ldata = rdata.data.data;
for (var i = 0; i < ldata.length; i++) {
tBody += '<tr data-name="'+ldata[i]['name']+'">'
tBody += '<td>'+ldata[i]['name']+'</td>';
tBody += '<td>'+ldata[i]['tag']+'</td>';
if (ldata[i]['status'] == 'start'){
tBody += '<td><span style="color:#20a53a;cursor: pointer;" class="ext_status glyphicon glyphicon-play"></span></td>';
} else{
tBody += '<td><span style="color:red;cursor: pointer;" class="ext_status glyphicon glyphicon-pause"></span></td>';
}
tBody +='<tr>';
}
}
$('#ext_list').html(tBody);
$('#ext_list_page').html(rdata.data.list);
$('#ext_list .ext_status').click(function(){
var name = $(this).parent().parent().data('name');
var status = 'stop';
if ($(this).hasClass('glyphicon-pause')){
status = 'start';
}
setBotExtStatus(name,status);
});
});
}
+69
View File
@@ -0,0 +1,69 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import base64
import threading
sys.path.append(os.getcwd() + "/class/core")
import mw
import telebot
from telebot import types
from telebot.util import quick_markup
# 广告推送实例
chat_id = -1001578009023
# chat_id = 5568699210
def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|start
lock_file = mw.getServerDir() + '/tgbot/lock.json'
if not os.path.exists(lock_file):
mw.writeFile(lock_file, '{}')
lock_data = json.loads(mw.readFile(lock_file))
if tag in lock_data:
diff_time = time.time() - lock_data[tag]['do_time']
if diff_time >= trigger_time:
lock_data[tag]['do_time'] = time.time()
else:
return False, 0, 0
else:
lock_data[tag] = {'do_time': time.time()}
mw.writeFile(lock_file, json.dumps(lock_data))
# 信号只在一个周期内执行一次|end
keyboard = [
[
types.InlineKeyboardButton(
text="赞助联系ME", url='tg://user?id=5568699210')
],
[
types.InlineKeyboardButton(
text="论坛", url='https://bbs.midoks.me'),
types.InlineKeyboardButton(
text="搜索", url='https://bbs.midoks.me/search.php')
]
]
markup = types.InlineKeyboardMarkup(keyboard)
image_file = mw.getPluginDir() + '/tgbot/static/image/ad.png'
telebot_image = telebot.types.InputFile(image_file)
msg = bot.send_photo(chat_id, telebot_image, reply_markup=markup)
# print(msg.message_id)
time.sleep(5 * 60)
del_msg = bot.delete_message(chat_id=chat_id, message_id=msg.message_id)
# print(del_msg)
def run(bot):
send_msg(bot, 'ad', 6 * 60 * 60)
+1
View File
@@ -0,0 +1 @@
push_*.py 识别为推送插件
+205
View File
@@ -0,0 +1,205 @@
import sys
import io
import os
import time
import re
import json
import base64
import threading
sys.path.append(os.getcwd() + "/class/core")
import mw
import telebot
from telebot import types
from telebot.util import quick_markup
def isThisCmd(cmd, msg):
clen = len(cmd)
msg_len = len(msg)
if msg_len < clen:
return False
check_msg = msg[0:clen]
if cmd == check_msg:
return True
return False
def getReadCmd(cmd, msg):
clen = len(cmd)
msg_len = len(msg)
real_msg = msg[clen:]
return real_msg
def getFaqKw(cmd):
matchObj = re.match(r'寻找【(.*?)】问题如下', cmd, re.M | re.I)
data = matchObj.groups()
if len(data) > 0:
return True, data[0]
return False, ''
def searchHttpPage(kw='', p=1, size=1):
import urllib
kw = kw.strip()
kw = urllib.parse.quote_plus(kw)
api = 'https://bbs.midoks.me/plugin.php?id=external_api&f=bbs_search&q=' + kw + \
'&size=' + str(size) + '&p=' + str(p)
# print('url', api)
data = mw.httpGet(api)
# print(data)
data = json.loads(data)
# print(data)
if data['code'] > -1:
alist = data['data']['list']
r = []
for x in alist:
tmp = {}
tmp['tid'] = x['tid']
tmp['subject'] = x['subject']
tmp['url'] = 'https://bbs.midoks.me/thread-' + \
x['tid'] + '-1-1.html'
r.append(tmp)
data['data']['list'] = r
return data
def searchFaq(bot, message, cmd_text):
# cmd_text = 'mw'
data = searchHttpPage(cmd_text, 1, 5)
if data['code'] == 0 and len(data['data']['list']) > 0:
keyboard = []
dlist = data['data']['list']
for x in dlist:
keyboard.append([types.InlineKeyboardButton(
text=x['subject'], url=x['url'])])
keyboard.append([
types.InlineKeyboardButton(
text="下一页", callback_data='bbs_next_page_2'),
types.InlineKeyboardButton(
text="第" + str(data['data']['p']) + "页,共" + str(data['data']['page_num']) + "页", callback_data='bbs_page_total')
])
keyboard.append([types.InlineKeyboardButton(
text="关闭消息", callback_data='bbs_search_close')])
# print(keyboard)
markup = types.InlineKeyboardMarkup(keyboard)
bot.send_message(message.chat.id, "寻找【" +
cmd_text.strip() + "】问题如下:", reply_markup=markup)
else:
keyboard = [
[
types.InlineKeyboardButton(
text="论坛", url='https://bbs.midoks.me'),
types.InlineKeyboardButton(
text="搜索", url='https://bbs.midoks.me/search.php')
],
[
types.InlineKeyboardButton(
text="关闭消息", callback_data='bbs_search_close')
]
]
markup = types.InlineKeyboardMarkup(keyboard)
bot.send_message(
message.chat.id, "未找到合适内容,请在官方论坛[bbs.midoks.me]提问!", reply_markup=markup)
return True
def searchDebug(bot, message, cmd_text):
searchFaq(bot, message, cmd_text)
return True
def answer_callback_query(bot, call):
keyword = call.data
if keyword == 'bbs_search_close':
bot.delete_message(chat_id=call.message.chat.id,
message_id=call.message.message_id)
return
is_bbs_page = False
p = 1
if keyword.startswith('bbs_next_page'):
is_bbs_page = True
p = keyword.replace('bbs_next_page_', '')
if keyword.startswith('bbs_pre_page'):
is_bbs_page = True
p = keyword.replace('bbs_pre_page_', '')
# print("p", p)
if is_bbs_page:
is_match, cmd_text = getFaqKw(call.message.text)
if not is_match:
bot.edit_message_text(
chat_id=call.message.chat.id, message_id=call.message.message_id, text="出现错误!")
return
data = searchHttpPage(cmd_text, int(p), 5)
dlist = data['data']['list']
# print(data)
keyboard = []
for x in dlist:
keyboard.append([types.InlineKeyboardButton(
text=x['subject'], url=x['url'])])
page_nav = []
if int(data['data']['p']) > 1:
page_nav.append(types.InlineKeyboardButton(
text="上一页", callback_data='bbs_pre_page_' + str(int(p) - 1)))
if data['data']['page_num'] != data['data']['p']:
page_nav.append(types.InlineKeyboardButton(
text="下一页", callback_data='bbs_next_page_' + str(int(p) + 1)))
page_nav.append(types.InlineKeyboardButton(
text="第" + str(data['data']['p']) + "页,共" + str(data['data']['page_num']) + "页", callback_data='bbs_page_total'))
keyboard.append(page_nav)
keyboard.append([types.InlineKeyboardButton(
text="关闭消息", callback_data='bbs_search_close')])
markup = types.InlineKeyboardMarkup(keyboard)
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
text=call.message.text, reply_markup=markup)
def run(bot, message):
text_body = message.text
# print(text_body)
if isThisCmd('/faq:', text_body):
cmd_text = getReadCmd('/faq:', text_body)
return searchFaq(bot, message, cmd_text)
# if isThisCmd('/debug', text_body):
# cmd_text = getReadCmd('/debug', text_body)
# return searchDebug(bot, message, cmd_text)
if text_body.find('?') > -1 or text_body.find('?') > -1:
return_msg = "你似乎在寻找【" + text_body + "】答案:\n"
return_msg += "/faq:开始寻找你的问题\n"
bot.reply_to(message, return_msg)
return bot
if __name__ == "__main__":
# print(isThisCmd('/?:', '/?:如何在安装面板'))
# print(getReadCmd('/?:', '/?:如何在安装面板'))
# print(searchHttpPage('mw'))
print(getFaqKw('寻找【mw】问题如下:'))
+173
View File
@@ -0,0 +1,173 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import base64
import threading
sys.path.append(os.getcwd() + "/class/core")
import mw
import telebot
def getPluginName():
return 'tgbot'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
sys.path.append(getServerDir() + "/extend")
def getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeConf(data):
cfg_path = getServerDir() + "/data.cfg"
mw.writeFile(cfg_path, json.dumps(data))
return True
def getExtCfg():
cfg_path = getServerDir() + "/extend.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def getStartExtCfgByTag(tag='push'):
# 获取开启的扩展
elist = getExtCfg()
rlist = []
for x in elist:
if x['tag'] == tag and x['status'] == 'start':
rlist.append(x)
return rlist
def writeLog(log_str):
if __name__ == "__main__":
print(log_str)
now = mw.getDateFromNow()
log_file = getServerDir() + '/task.log'
mw.writeFileLog(now + ':' + log_str, log_file, limit_size=5 * 1024)
return True
# start tgbot
cfg = getConfigData()
while True:
cfg = getConfigData()
if 'bot' in cfg and 'app_token' in cfg['bot']:
if cfg['bot']['app_token'] != '' and cfg['bot']['app_token'] != 'app_token':
break
writeLog('等待输入配置,填写app_token')
time.sleep(3)
bot = telebot.TeleBot(cfg['bot']['app_token'])
bot.delete_my_commands(scope=None, language_code=None)
bot.set_my_commands(
commands=[
telebot.types.BotCommand("start", "查看帮助信息"),
telebot.types.BotCommand("faq", "查看bbs帖子主题【不要忘记:冒号】"),
],
)
# @bot.message_handler(commands=['start', 'help'])
# def hanle_start_help(message):
# bot.reply_to(message, "hello world")
# @bot.message_handler(commands=['mw_echo'])
# def hanle_mw_echo(message):
# bot.reply_to(message, message.text)
@bot.message_handler(commands=['chat_id'])
def hanle_get_chat_id(message):
bot.reply_to(message, message.chat.id)
@bot.message_handler(func=lambda message: True)
def all_message(message):
rlist = getStartExtCfgByTag('receive')
for r in rlist:
try:
script = r['name'].split('.')[0]
__import__(script).run(bot, message)
except Exception as e:
writeLog('-----all_message error start -------')
writeLog(mw.getTracebackInfo())
writeLog('-----all_message error end -------')
@bot.callback_query_handler(func=lambda call: True)
def callback_query_handler(call):
rlist = getStartExtCfgByTag('receive')
for r in rlist:
try:
script = r['name'].split('.')[0]
__import__(script).answer_callback_query(bot, call)
except Exception as e:
writeLog('-----callback_query_handler error start -------')
writeLog(mw.getTracebackInfo())
writeLog('-----callback_query_handler error end -------')
def runBotPushTask():
plist = getStartExtCfgByTag('push')
for p in plist:
try:
script = p['name'].split('.')[0]
__import__(script).run(bot)
except Exception as e:
writeLog('-----runBotPushTask error start -------')
writeLog(mw.getTracebackInfo())
writeLog('-----runBotPushTask error end -------')
def botPush():
while True:
runBotPushTask()
time.sleep(1)
def setDaemon(t):
if sys.version_info.major == 3 and sys.version_info.minor >= 10:
t.daemon = True
else:
t.setDaemon(True)
if __name__ == "__main__":
# 机器人推送任务
botPushTask = threading.Thread(target=botPush)
# print(botPushTask)
# botPushTask = setDaemon(botPushTask)
botPushTask.start()
writeLog('启动成功')
bot.polling()
# asyncio.run(bot.polling())
Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

+19 -18
View File
@@ -25,7 +25,7 @@ class App():
self.__host_dir = self.getServerDir() + '/host' self.__host_dir = self.getServerDir() + '/host'
if not os.path.exists(self.__host_dir): if not os.path.exists(self.__host_dir):
os.makedirs(self.__host_dir) mw.execShell('mkdir -p ' + self.__host_dir)
def getPluginName(self): def getPluginName(self):
return 'webssh' return 'webssh'
@@ -145,24 +145,25 @@ class App():
def get_server_list(self): def get_server_list(self):
host_list = [] host_list = []
for name in os.listdir(self.__host_dir): if os.path.exists(self.__host_dir):
info_file = self.__host_dir + '/' + name + '/info.json' for name in os.listdir(self.__host_dir):
if not os.path.exists(info_file): info_file = self.__host_dir + '/' + name + '/info.json'
continue if not os.path.exists(info_file):
try: continue
info_tmp = self.getSshInfo(info_file) try:
host_info = {} info_tmp = self.getSshInfo(info_file)
host_info['host'] = name host_info = {}
host_info['port'] = info_tmp['port'] host_info['host'] = name
host_info['ps'] = info_tmp['ps'] host_info['port'] = info_tmp['port']
# host_info['sort'] = int(info_tmp['sort']) host_info['ps'] = info_tmp['ps']
except Exception as e: # host_info['sort'] = int(info_tmp['sort'])
print(e) except Exception as e:
# if os.path.exists(info_file): print(e)
# os.remove(info_file) # if os.path.exists(info_file):
# continue # os.remove(info_file)
# continue
host_list.append(host_info) host_list.append(host_info)
host_list = sorted(host_list, key=lambda x: x['host'], reverse=False) host_list = sorted(host_list, key=lambda x: x['host'], reverse=False)
return mw.returnJson(True, 'ok!', host_list) return mw.returnJson(True, 'ok!', host_list)
+8
View File
@@ -9,6 +9,14 @@
"css_path":"menu/index.css", "css_path":"menu/index.css",
"js_path":"js/webssh.js" "js_path":"js/webssh.js"
} }
},
{
"tag":"global_static",
"global_static": {
"title":"终端管理",
"name":"webssh",
"css_path":"menu/ico.css"
}
} }
], ],
"id":3, "id":3,
+10
View File
@@ -0,0 +1,10 @@
/* menu start */
.menu .menu_plugin_webssh {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMBJREFUeNpiYKAQMM6cOVMASBuQozk9Pf0AC5AuAOJ6cgwAWt7IhMQvRKIfAPEEYgxhQWL3o9EFpBgwAeifQhKdD7YI5oWPUMEEmAQR4COyATBwAIgdgIacB2IFYkxhQouWB0BsCA3E86QGIsxvDSBXgGIDSxr5ALTgAk4XADWAQt4fiB2BChcAaQVoGoHheLwuAGqagBz/UNsciQ4DEgE/zAUfQM4DOt+eRANAYTMRZADIrxfIdMUFSnMzA0CAAQD0hjqnYxWD2gAAAABJRU5ErkJggg==");
}
.menu .current .menu_plugin_webssh:hover {
background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQXAJ6ipUFITySRPIiMkDFRQuXm5jJKQy1kQCGeOzBXQSl3PiWLPVhfZSxrQCpxP9na2yeEPTREQ8LExmRqb5OXm/Hx8TU9RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMyQjYwMTU3OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMyQjYwMTU4OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzJCNjAxNTU5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzJCNjAxNTY5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFMgAXACwAAAAAEAAQAAAFU6AljmRpBVOqrqtFVXAsy9Q7VMMDzHHN/5UawGQC1CiWg4IoOiINAoGB6BxBENSjyIE4oFKMprYhIFgYkvTQpWWOqm6RcVBI2+/2AuXL6k8CcSYhACH5BAUyABcALAcACQAFAAIAAAUIYJSMBLGcSggAIfkEBTIAFwAsBwAJAAUAAgAABQhgMI0MI51ACAAh+QQFMgAXACwHAAkABQACAAAFCGCUjASxnEoIADs=");
}
/* menu end */
-11
View File
@@ -1,15 +1,4 @@
/* menu start */
.menu .menu_plugin_webssh {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMBJREFUeNpiYKAQMM6cOVMASBuQozk9Pf0AC5AuAOJ6cgwAWt7IhMQvRKIfAPEEYgxhQWL3o9EFpBgwAeifQhKdD7YI5oWPUMEEmAQR4COyATBwAIgdgIacB2IFYkxhQouWB0BsCA3E86QGIsxvDSBXgGIDSxr5ALTgAk4XADWAQt4fiB2BChcAaQVoGoHheLwuAGqagBz/UNsciQ4DEgE/zAUfQM4DOt+eRANAYTMRZADIrxfIdMUFSnMzA0CAAQD0hjqnYxWD2gAAAABJRU5ErkJggg==");
}
.menu .current .menu_plugin_webssh:hover {
background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQXAJ6ipUFITySRPIiMkDFRQuXm5jJKQy1kQCGeOzBXQSl3PiWLPVhfZSxrQCpxP9na2yeEPTREQ8LExmRqb5OXm/Hx8TU9RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMyQjYwMTU3OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMyQjYwMTU4OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzJCNjAxNTU5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzJCNjAxNTY5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFMgAXACwAAAAAEAAQAAAFU6AljmRpBVOqrqtFVXAsy9Q7VMMDzHHN/5UawGQC1CiWg4IoOiINAoGB6BxBENSjyIE4oFKMprYhIFgYkvTQpWWOqm6RcVBI2+/2AuXL6k8CcSYhACH5BAUyABcALAcACQAFAAIAAAUIYJSMBLGcSggAIfkEBTIAFwAsBwAJAAUAAgAABQhgMI0MI51ACAAh+QQFMgAXACwHAAkABQACAAAFCGCUjASxnEoIADs=");
}
/* menu end */
.xterm{ .xterm{
position: inherit; position: inherit;
} }
+1
View File
@@ -27,6 +27,7 @@
"gif", "gif",
"jpg", "jpg",
"css", "css",
"svg",
"js", "js",
"ico", "ico",
"woff2" "woff2"
+5 -4
View File
@@ -191,8 +191,10 @@ def pSqliteDb(dbname='web_logs', site_name='unset', name="logs"):
conn = mw.M(dbname).dbPos(db_dir, name) conn = mw.M(dbname).dbPos(db_dir, name)
conn.execute("PRAGMA synchronous = 0") conn.execute("PRAGMA synchronous = 0")
conn.execute("PRAGMA page_size = 4096") conn.execute("PRAGMA cache_size = 8000")
conn.execute("PRAGMA page_size = 32768")
conn.execute("PRAGMA journal_mode = wal") conn.execute("PRAGMA journal_mode = wal")
conn.execute("PRAGMA journal_size_limit = 1073741824")
return conn return conn
@@ -263,6 +265,8 @@ def initDreplace():
loadLuaSiteFile() loadLuaSiteFile()
loadDebugLogFile() loadDebugLogFile()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + getServerDir())
return 'ok' return 'ok'
@@ -277,9 +281,6 @@ def start():
import tool_task import tool_task
tool_task.createBgTask() tool_task.createBgTask()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + getServerDir())
# issues:326 # issues:326
luaRestart() luaRestart()
return 'ok' return 'ok'
+14 -2
View File
@@ -1,10 +1,22 @@
{ {
"sort": 7, "hook":[
{
"tag":"site_cb",
"site_cb": {
"title":"网站统计",
"name":"webstats",
"add":{"func":"reload"},
"update":{"func":"reload"},
"delete":{"func":"reload"}
}
}
],
"sort": "7",
"ps": "网站统计报表", "ps": "网站统计报表",
"name": "webstats", "name": "webstats",
"title": "网站统计", "title": "网站统计",
"shell": "install.sh", "shell": "install.sh",
"versions":["0.2.4"], "versions":["0.2.5"],
"tip": "soft", "tip": "soft",
"install_pre_inspection":true, "install_pre_inspection":true,
"checks": "server/webstats", "checks": "server/webstats",
+50 -22
View File
@@ -210,8 +210,6 @@ function _M.get_http_origin(self)
if not headers then return data end if not headers then return data end
local req_method = ngx.req.get_method() local req_method = ngx.req.get_method()
if req_method ~='GET' then if req_method ~='GET' then
-- API disabled in the context of log_by_lua*
-- ngx.req.read_body()
-- proxy_pass, fastcgi_pass, uwsgi_pass, and scgi_pass -- proxy_pass, fastcgi_pass, uwsgi_pass, and scgi_pass
data = ngx.var.request_body data = ngx.var.request_body
@@ -219,9 +217,11 @@ function _M.get_http_origin(self)
data = ngx.req.get_body_data() data = ngx.req.get_body_data()
end end
if not data then -- API disabled in the context of log_by_lua
data = ngx.req.get_post_args(1000000) -- if not data then
end -- ngx.req.read_body()
-- data = ngx.req.get_post_args(1000000)
-- end
if "string" == type(data) then if "string" == type(data) then
headers["payload"] = data headers["payload"] = data
@@ -239,6 +239,7 @@ function _M.cronPre(self)
local time_key = self:get_store_key() local time_key = self:get_store_key()
local time_key_next = self:get_store_key_with_time(ngx.time()+3600) local time_key_next = self:get_store_key_with_time(ngx.time()+3600)
for site_k, site_v in ipairs(sites) do for site_k, site_v in ipairs(sites) do
local input_sn = site_v["name"] local input_sn = site_v["name"]
@@ -250,16 +251,24 @@ function _M.cronPre(self)
'spider_stat' 'spider_stat'
} }
local v1 = true
local v2 = true
for _,ws_v in pairs(wc_stat) do for _,ws_v in pairs(wc_stat) do
self:_update_stat_pre(db, ws_v, time_key) v1 = self:_update_stat_pre(db, ws_v, time_key)
self:_update_stat_pre(db, ws_v, time_key_next) v2 = self:_update_stat_pre(db, ws_v, time_key_next)
end end
if db and db:isopen() then if db and db:isopen() then
db:execute([[COMMIT]]) db:execute([[COMMIT]])
db:close() db:close()
end end
if not v1 or not v2 then
return false
end
end end
return true
end end
-- 后台任务 -- 后台任务
@@ -273,7 +282,17 @@ function _M.cron(self)
return true return true
end end
self:cronPre() -- self:D("dedebide:cron task is busy!")
local ready_ok = self:cronPre()
if not ready_ok then
self:D("cron task is busy!")
return true
end
local cron_key = 'cron_every_1s'
if self:is_working(cron_key) then
return true
end
ngx.update_time() ngx.update_time()
local begin = ngx.now() local begin = ngx.now()
@@ -316,17 +335,13 @@ function _M.cron(self)
end end
end end
local cron_key = 'cron_every_1s'
if self:is_working(cron_key) then
return true
end
self:lock_working(cron_key) self:lock_working(cron_key)
-- 每秒100条 -- 每秒100条
for i=1,llen do for i=1,llen do
local data, _ = ngx.shared.mw_total:lpop(total_key) local data, _ = ngx.shared.mw_total:lpop(total_key)
if not data then if not data then
self:unlock_working(cron_key)
break break
end end
@@ -338,10 +353,17 @@ function _M.cron(self)
local db = dbs[input_sn] local db = dbs[input_sn]
local stat_fields_is = stat_fields[input_sn] local stat_fields_is = stat_fields[input_sn]
if not db then if not db then
ngx.shared.mw_total:rpush(total_key, data)
self:unlock_working(cron_key)
break break
end end
self:store_logs_line(db, stmts[input_sn]["web_logs"], input_sn, info) local insert_ok = self:store_logs_line(db, stmts[input_sn]["web_logs"], input_sn, info)
if not insert_ok then
ngx.shared.mw_total:rpush(total_key, data)
self:unlock_working(cron_key)
break
end
local excluded = info["log_kv"]['excluded'] local excluded = info["log_kv"]['excluded']
local stat_tmp_fields = info['stat_fields'] local stat_tmp_fields = info['stat_fields']
@@ -514,10 +536,8 @@ function _M.store_logs_line(self, db, stmt, input_sn, info)
local request_headers = logline["request_headers"] local request_headers = logline["request_headers"]
local excluded = logline["excluded"] local excluded = logline["excluded"]
-- self:D("json:"..json.encode(logline))
local time_key = logline["time_key"] local time_key = logline["time_key"]
if not excluded then if not excluded then
stmt:bind_names { stmt:bind_names {
time=time, time=time,
ip=ip, ip=ip,
@@ -539,13 +559,15 @@ function _M.store_logs_line(self, db, stmt, input_sn, info)
local res, err = stmt:step() local res, err = stmt:step()
if tostring(res) == "5" then if tostring(res) == "5" then
self:D("step res:"..tostring(res) ..",step err:"..tostring(err)) -- self:D("json:"..json.encode(logline))
self:D("the step database connection is busy, so it will be stored later.") -- self:D("the step database connection is busy, so it will be stored later | step res:"..tostring(res) ..",step err:"..tostring(err))
if stmt then
stmt:reset()
end
return false return false
end end
stmt:reset() stmt:reset()
end end
return true return true
end end
@@ -653,9 +675,14 @@ end
function _M._update_stat_pre(self, db, stat_table, key) function _M._update_stat_pre(self, db, stat_table, key)
local local_sql = string.format("INSERT INTO %s(time) SELECT :time WHERE NOT EXISTS(SELECT time FROM %s WHERE time=:time);", stat_table, stat_table) local local_sql = string.format("INSERT INTO %s(time) SELECT :time WHERE NOT EXISTS(SELECT time FROM %s WHERE time=:time);", stat_table, stat_table)
local update_stat_stmt = db:prepare(local_sql) local update_stat_stmt = db:prepare(local_sql)
update_stat_stmt:bind_names{time=key}
update_stat_stmt:step() if update_stat_stmt then
update_stat_stmt:finalize() update_stat_stmt:bind_names{time=key}
update_stat_stmt:step()
update_stat_stmt:finalize()
return true
end
return false
end end
function _M.update_stat_quick(self, db, stat_table, key,columns) function _M.update_stat_quick(self, db, stat_table, key,columns)
@@ -1084,6 +1111,7 @@ end
function _M.get_client_ip(self) function _M.get_client_ip(self)
local client_ip = "unknown" local client_ip = "unknown"
local cdn = auto_config['cdn'] local cdn = auto_config['cdn']
local request_header = ngx.req.get_headers()
if cdn == true then if cdn == true then
for _,v in ipairs(auto_config['cdn_headers']) do for _,v in ipairs(auto_config['cdn_headers']) do
if request_header[v] ~= nil and request_header[v] ~= "" then if request_header[v] ~= nil and request_header[v] ~= "" then
+1
View File
@@ -134,6 +134,7 @@ log_by_lua_block {
local function exclude_url() local function exclude_url()
if not ngx.var.uri then return false end if not ngx.var.uri then return false end
if not ngx.var.request_uri then return false end
if not auto_config['exclude_url'] then return false end if not auto_config['exclude_url'] then return false end
local the_uri = string.sub(ngx.var.request_uri, 2) local the_uri = string.sub(ngx.var.request_uri, 2)
local url_conf = auto_config["exclude_url"] local url_conf = auto_config["exclude_url"]
+6
View File
@@ -85,6 +85,7 @@ def migrateSiteHotLogs(site_name, query_date):
import shutil import shutil
print("coping {} to {} ...".format(hot_db, hot_db_tmp)) print("coping {} to {} ...".format(hot_db, hot_db_tmp))
mw.writeFile(migrating_flag, "yes") mw.writeFile(migrating_flag, "yes")
time.sleep(3)
shutil.copy(hot_db, hot_db_tmp) shutil.copy(hot_db, hot_db_tmp)
if not os.path.exists(hot_db_tmp): if not os.path.exists(hot_db_tmp):
return mw.returnMsg(False, "migrating fail, copy tmp file!") return mw.returnMsg(False, "migrating fail, copy tmp file!")
@@ -182,6 +183,11 @@ def migrateSiteHotLogs(site_name, query_date):
os.remove(hot_db_tmp) os.remove(hot_db_tmp)
print("{} logs migrate ok.".format(site_name)) print("{} logs migrate ok.".format(site_name))
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + getServerDir())
mw.opWeb('restart')
return mw.returnMsg(True, "{} logs migrate ok".format(site_name)) return mw.returnMsg(True, "{} logs migrate ok".format(site_name))
+2
View File
@@ -29,3 +29,5 @@ flask-caching>=1.10.1
bcrypt==3.1.3 bcrypt==3.1.3
PyMySQL==1.0.2 PyMySQL==1.0.2
whitenoise==5.3.0 whitenoise==5.3.0
pyTelegramBotAPI
telebot
+10 -10
View File
@@ -1,12 +1,12 @@
location / { location / {
rewrite "^/list-([0-9]+)\.html$" /plus/list.php?tid=$1 last; rewrite ^/list-([0-9]+)\.html$ /plus/list.php?tid=$1 last;
rewrite "^/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$" /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last; rewrite ^/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last;
rewrite "^/view-([0-9]+)-1\.html$" /plus/view.php?arcID=$1 last; rewrite ^/view-([0-9]+)-1\.html$ /plus/view.php?arcID=$1 last;
rewrite "^/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last; rewrite ^/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last;
rewrite "^/plus/list-([0-9]+)\.html$" /plus/list.php?tid=$1 last; rewrite ^/plus/list-([0-9]+)\.html$ /plus/list.php?tid=$1 last;
rewrite "^/plus/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$" /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last; rewrite ^/plus/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last;
rewrite "^/plus/view-([0-9]+)-1\.html$" /plus/view.php?arcID=$1 last; rewrite ^/plus/view-([0-9]+)-1\.html$ /plus/view.php?arcID=$1 last;
rewrite "^/plus/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last; rewrite ^/plus/view-([0-9]+)-([0-9]+)\.html$ /plus/view.php?aid=$1&pageno=$2 last;
rewrite "^/tags.html$" /tags.php last; rewrite ^/tags.html$ /tags.php last;
rewrite "^/tag-([0-9]+)-([0-9]+)\.html$" /tags.php?/$1/$2/ last; rewrite ^/tag-([0-9]+)-([0-9]+)\.html$ /tags.php?/$1/$2/ last;
} }
-7
View File
@@ -1,7 +0,0 @@
location / {
rewrite ^/archiver/((fid|tid)-[\w\-]+\.html)$ /archiver/index.php?$1 last;
rewrite ^/forum-([0-9]+)-([0-9]+)\.html$ /forumdisplay.php?fid=$1&page=$2 last;
rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /viewthread.php?tid=$1&extra=page%3D$3&page=$2 last;
rewrite ^/space-(username|uid)-(.+)\.html$ /space.php?$1=$2 last;
rewrite ^/tag-(.+)\.html$ /tag.php?name=$1 last;
}
+5 -1
View File
@@ -9,6 +9,10 @@ location / {
rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last;
rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last;
if (!-e $request_filename) { if (!-e $request_filename) {
return 404; rewrite ^(.*)$ /index.php last;
} }
#if (!-e $request_filename) {
# return 404;
#}
} }
+1 -1
View File
@@ -9,6 +9,6 @@ location /bbs/ {
rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last;
rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last;
if (!-e $request_filename) { if (!-e $request_filename) {
return 404; rewrite ^(.*)$ /index.php last;
} }
} }
+1 -1
View File
@@ -9,7 +9,7 @@ location / {
rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last;
rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last;
if (!-e $request_filename) { if (!-e $request_filename) {
return 404; rewrite ^(.*)$ /index.php last;
} }
} }
+8 -7
View File
@@ -179,7 +179,6 @@ def requestCheck():
def isLogined(): def isLogined():
# print('isLogined', session)
if 'login' in session and 'username' in session and session['login'] == True: if 'login' in session and 'username' in session and session['login'] == True:
userInfo = mw.M('users').where( userInfo = mw.M('users').where(
"id=?", (1,)).field('id,username,password').find() "id=?", (1,)).field('id,username,password').find()
@@ -445,7 +444,6 @@ def login_temp_user(token):
@app.route('/api/<reqClass>/<reqAction>', methods=['POST', 'GET']) @app.route('/api/<reqClass>/<reqAction>', methods=['POST', 'GET'])
def api(reqClass=None, reqAction=None, reqData=None): def api(reqClass=None, reqAction=None, reqData=None):
comReturn = common.local() comReturn = common.local()
if comReturn: if comReturn:
return comReturn return comReturn
@@ -458,15 +456,18 @@ def api(reqClass=None, reqAction=None, reqData=None):
request_time = request.form.get('request_time', '') request_time = request.form.get('request_time', '')
request_token = request.form.get('request_token', '') request_token = request.form.get('request_token', '')
request_ip = request.remote_addr request_ip = request.remote_addr
request_ip = request_ip.replace('::ffff:', '')
token_md5 = mw.md5(str(request_time) + mw.md5(data['token_crypt'])) # print(request_time, request_token)
if not mw.inArray(data['limit_addr'], request_ip):
return mw.returnJson(False, 'IP校验失败,您的访问IP为[' + request_ip + ']')
local_token = mw.deCrypt(data['token'], data['token_crypt'])
token_md5 = mw.md5(str(request_time) + mw.md5(local_token))
if not (token_md5 == request_token): if not (token_md5 == request_token):
return mw.returnJson(False, '密钥错误') return mw.returnJson(False, '密钥错误')
if not mw.inArray(data['limit_addr'], request_ip):
return mw.returnJson(False, '非法请求')
if reqClass == None: if reqClass == None:
return mw.returnJson(False, '请指定请求方法类') return mw.returnJson(False, '请指定请求方法类')
@@ -477,7 +478,7 @@ def api(reqClass=None, reqAction=None, reqData=None):
'plugins_api', 'system_api', 'site_api', 'task_api') 'plugins_api', 'system_api', 'site_api', 'task_api')
className = reqClass + '_api' className = reqClass + '_api'
if not className in classFile: if not className in classFile:
return "external api request error" return mw.returnJson(False, 'external api request error')
eval_str = "__import__('" + className + "')." + className + '()' eval_str = "__import__('" + className + "')." + className + '()'
newInstance = eval(eval_str) newInstance = eval(eval_str)
+110 -3
View File
@@ -354,6 +354,78 @@ function setPanelSSL(){
}); });
} }
function setNotifyApi(tag, obj){
var enable = $(obj).prop("checked");
console.log(tag,obj,enable);
$.post('/config/set_notify_enable', {'tag':tag, 'enable':enable},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){}
} ,{icon:rdata.status?1:2}, 1000);
},'json');
}
function getTgbot(){
var loadT = layer.msg('正在获取TgBot信息...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/get_notify',{},function(data){
layer.close(loadT);
var app_token = '';
var chat_id = '';
if (data.status){
if (typeof(data['data']['tgbot']) !='undefined'){
app_token = data['data']['tgbot']['data']['app_token'];
chat_id = data['data']['tgbot']['data']['chat_id'];
}
}
layer.open({
type: 1,
area: "500px",
title: '配置TgBot配置',
closeBtn: 1,
shift: 5,
btn:["确定","关闭","验证"],
shadeClose: false,
content: "<div class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>APP_TOKEN</span>\
<div class='info-r'><input class='bt-input-text' type='text' name='app_token' value='"+app_token+"' style='width:100%'/></div>\
</div>\
<div class='line'>\
<span class='tname'>CHAT_ID</span>\
<div class='info-r'><input class='bt-input-text' type='text' name='chat_id' value='"+chat_id+"' style='width:100%' /></div>\
</div>\
</div>",
yes:function(index){
var pdata = {};
pdata['app_token'] = $('input[name="app_token"]').val();
pdata['chat_id'] = $('input[name="chat_id"]').val();
$.post('/config/set_notify',{'tag':'tgbot', 'data':JSON.stringify(pdata)},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){
layer.close(index);
}
},{icon:rdata.status?1:2},2000);
});
},
btn3:function(index){
var pdata = {};
pdata['app_token'] = $('input[name="app_token"]').val();
pdata['chat_id'] = $('input[name="chat_id"]').val();
$.post('/config/set_notify_test',{'tag':'tgbot', 'data':JSON.stringify(pdata)},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){
layer.close(index);
}
},{icon:rdata.status?1:2},2000);
});
return false;
}
});
});
}
function getPanelSSL(){ function getPanelSSL(){
var loadT = layer.msg('正在获取证书信息...',{icon:16,time:0,shade: [0.3, '#000']}); var loadT = layer.msg('正在获取证书信息...',{icon:16,time:0,shade: [0.3, '#000']});
@@ -364,11 +436,21 @@ function getPanelSSL(){
var cert_data = ''; var cert_data = '';
if (cert['info']){ if (cert['info']){
cert_data = "<div class='ssl_state_info'><div class='state_info_flex'>\ cert_data = "<div class='ssl_state_info'><div class='state_info_flex'>\
<div class='state_item'><span>证书品牌:</span><span class='ellipsis_text ssl_issue'>"+cert['info']['issuer']+"</span></div>\ <div class='state_item'><span>证书品牌:</span>\
<div class='state_item'><span>到期时间:</span><span class='btlink ssl_endtime'>剩余"+cert['info']['endtime']+"天到期</span></div>\ <span class='ellipsis_text ssl_issue'>"+cert['info']['issuer']+"</span></div>\
<div class='state_item'><span>到期时间:</span>\
<span class='btlink ssl_endtime'>剩余"+cert['info']['endtime']+"天到期</span></div>\
</div>\ </div>\
<div class='state_info_flex'>\ <div class='state_info_flex'>\
<div class='state_item'><span>认证域名:</span><span class='ellipsis_text ssl_subject'>"+cert['info']['subject']+"</span></div>\ <div class='state_item'><span>认证域名:</span>\
<span class='ellipsis_text ssl_subject'>"+cert['info']['subject']+"</span></div>\
<div class='state_item'>\
<span>强制HTTPS:</span>\
<span class='switch'>\
<input class='btswitch btswitch-ios' id='toHttps' type='checkbox' "+cert['is_https']+">\
<label class='btswitch-btn set_panel_http_to_https' for='toHttps'></label>\
</span>\
</div>\
</div></div>"; </div></div>";
} }
@@ -385,6 +467,7 @@ function getPanelSSL(){
</div>\ </div>\
<div class="ssl-btn pull-left mtb15" style="width:100%">\ <div class="ssl-btn pull-left mtb15" style="width:100%">\
<button class="btn btn-success btn-sm save-panel-ssl">保存</button>\ <button class="btn btn-success btn-sm save-panel-ssl">保存</button>\
<button class="btn btn-success btn-sm del-panel-ssl">删除</button>\
<button class="btn btn-success btn-sm apply-lets-ssl">申请Lets证书</button>\ <button class="btn btn-success btn-sm apply-lets-ssl">申请Lets证书</button>\
</div>\ </div>\
</div>\ </div>\
@@ -419,6 +502,30 @@ function getPanelSSL(){
},'json'); },'json');
}); });
//删除SSL
$('.del-panel-ssl').click(function(){
var loadT = layer.msg('正在删除SSL...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/del_panel_ssl',data,function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
});
// 设置面板SSL的Http
$('.set_panel_http_to_https').click(function(){
var https = $('#toHttps').prop('checked');
$.post('/config/set_panel_http_to_https',{'https':https},function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
});
//申请Lets证书 //申请Lets证书
$('.apply-lets-ssl').click(function(){ $('.apply-lets-ssl').click(function(){
showSpeedWindow('正在申请...', 'site.get_let_logs', function(layers,index){ showSpeedWindow('正在申请...', 'site.get_let_logs', function(layers,index){
+1 -1
View File
@@ -1110,7 +1110,7 @@ function reName(type, fileName) {
</div>', </div>',
success:function(){ success:function(){
$("#newFileName").focus().keyup(function(e){ $("#newFileName").focus().keyup(function(e){
if(e.keyCode == 13) $("#ReNameBtn").click(); if(e.keyCode == 13) $(".layui-layer-btn0").click();
}); });
}, },
yes:function(){ yes:function(){
+227 -70
View File
@@ -515,29 +515,24 @@ function openPath(a) {
window.location.href = "/files/" window.location.href = "/files/"
} }
function onlineEditFile(k, f) { function onlineEditFile(k, f, callback) {
if(k != 0) { if(k != 0) {
var l = $("#PathPlace input").val(); var l = $("#PathPlace input").val();
var h = encodeURIComponent($("#textBody").val()); var h = encodeURIComponent($("#textBody").val());
var a = $("select[name=encoding]").val(); var a = $("select[name=encoding]").val();
var loadT = layer.msg(lan.bt.save_file, { var loadT = layer.msg('正在保存,请稍候...', {icon: 16,time: 0});
icon: 16, $.post("/files/save_body", "data=" + h + "&path=" + encodeURIComponent(f) + "&encoding=" + a, function(data) {
time: 0
});
$.post("/files/save_body", "data=" + h + "&path=" + encodeURIComponent(f) + "&encoding=" + a, function(m) {
if(k == 1) { if(k == 1) {
layer.close(loadT); layer.close(loadT);
} }
layer.msg(m.msg, { layer.msg(data.msg, {icon: data.status ? 1 : 2});
icon: m.status ? 1 : 2 if (data.status && typeof(callback) == 'function'){
}); callback(k, f);
}
},'json'); },'json');
return return
} }
var e = layer.msg(lan.bt.read_file, { var e = layer.msg('正在读取文件,请稍候...', {icon: 16,time: 0});
icon: 16,
time: 0
});
var g = f.split("."); var g = f.split(".");
var b = g[g.length - 1]; var b = g[g.length - 1];
var d; var d;
@@ -595,15 +590,12 @@ function onlineEditFile(k, f) {
default: default:
var j = { var j = {
name: "htmlmixed", name: "htmlmixed",
scriptTypes: [{ scriptTypes: [
matches: /\/x-handlebars-template|\/x-mustache/i, {matches: /\/x-handlebars-template|\/x-mustache/i,mode: null},
mode: null {matches: /(text|application)\/(x-)?vb(a|script)/i,mode: "vbscript"}
}, { ]
matches: /(text|application)\/(x-)?vb(a|script)/i,
mode: "vbscript"
}]
}; };
d = j d = j;
} }
$.post("/files/get_body", "path=" + encodeURIComponent(f), function(s) { $.post("/files/get_body", "path=" + encodeURIComponent(f), function(s) {
if(s.status === false){ if(s.status === false){
@@ -619,51 +611,57 @@ function onlineEditFile(k, f) {
m = s.data.encoding == u[p] ? "selected" : ""; m = s.data.encoding == u[p] ? "selected" : "";
n += '<option value="' + u[p] + '" ' + m + ">" + u[p] + "</option>"; n += '<option value="' + u[p] + '" ' + m + ">" + u[p] + "</option>";
} }
var code_mirror = null;
var r = layer.open({ var r = layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 1, closeBtn: 1,
area: ["90%", "90%"], area: ["90%", "90%"],
title: lan.bt.edit_title+"[" + f + "]", btn:['保存','关闭'],
content: '<form class="bt-form pd20 pb70">\ title: "在线编辑[" + f + "]",
content: '<form class="bt-form pd20">\
<div class="line">\ <div class="line">\
<p style="color:red;margin-bottom:10px">' + lan.bt.edit_ps + '\ <p style="color:red;margin-bottom:10px">提示:Ctrl+F 搜索关键字,Ctrl+G 查找下一个,Ctrl+S 保存,Ctrl+Shift+R 查找替换!\
<select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select>\ <select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select>\
</p>\ </p>\
<textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" />\ <textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" />\
</div>\ </div>\
<div class="bt-form-submit-btn" style="position:absolute; bottom:0; width:100%">\ </form>',
<button type="button" class="btn btn-danger btn-sm btn-editor-close">'+lan.public.close+'</button>\ success:function(){
<button id="OnlineEditFileBtn" type="button" class="btn btn-success btn-sm">'+lan.public.save+'</button>\ $("#textBody").text(s.data.data);
</div>\ var q = $(window).height() * 0.9;
</form>' $("#textBody").height(q - 160);
}); code_mirror = CodeMirror.fromTextArea(document.getElementById("textBody"), {
$("#textBody").text(s.data.data); extraKeys: {
var q = $(window).height() * 0.9; "Ctrl-F": "findPersistent",
$("#textBody").height(q - 160); "Ctrl-H": "replaceAll",
var t = CodeMirror.fromTextArea(document.getElementById("textBody"), { "Ctrl-S": function() {
extraKeys: { $("#textBody").text(code_mirror.getValue());
"Ctrl-F": "findPersistent", onlineEditFile(2, f,callback);
"Ctrl-H": "replaceAll", },
"Ctrl-S": function() { "Cmd-S":function() {
$("#textBody").text(t.getValue()); $("#textBody").text(code_mirror.getValue());
onlineEditFile(2, f) onlineEditFile(2, f,callback);
} },
},
mode: d,
lineNumbers: true,
matchBrackets: true,
matchtags: true,
autoMatchParens: true
});
code_mirror.focus();
code_mirror.setSize("auto", q - 150);
$(window).resize(function(){
var q = $(window).height() * 0.9;
code_mirror.setSize("auto", q - 150);
});
}, },
mode: d, yes:function(){
lineNumbers: true, $("#textBody").text(code_mirror.getValue());
matchBrackets: true, onlineEditFile(1, f,callback);
matchtags: true, }
autoMatchParens: true
});
t.focus();
t.setSize("auto", q - 150);
$("#OnlineEditFileBtn").click(function() {
$("#textBody").text(t.getValue());
onlineEditFile(1, f);
});
$(".btn-editor-close").click(function() {
layer.close(r);
}); });
},'json'); },'json');
} }
@@ -1133,18 +1131,21 @@ function bindPanel(a,type,ip,btid,url,user,pw){
<li><font style='color:red'>注意,开启广告拦截会导致无法快捷登录。</font></li></ul>\ <li><font style='color:red'>注意,开启广告拦截会导致无法快捷登录。</font></li></ul>\
</div>\ </div>\
<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm' onclick=\"layer.closeAll()\">关闭</button> "+btn+"</div>\ <div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm' onclick=\"layer.closeAll()\">关闭</button> "+btn+"</div>\
</div>" </div>",
});
$("#btaddress").on("input",function(){ success:function(){
var str =$(this).val(); $("#btaddress").on("input",function(){
var isip = /([\w-]+\.){2,6}\w+/; var str =$(this).val();
var iptext = str.match(isip); var isip = /([\w-]+\.){2,6}\w+/;
if(iptext) $("#bttitle").val(iptext[0]); var iptext = str.match(isip);
}).blur(function(){ if(iptext) $("#bttitle").val(iptext[0]);
var str =$(this).val(); }).blur(function(){
var isip = /([\w-]+\.){2,6}\w+/; var str =$(this).val();
var iptext = str.match(isip); var isip = /([\w-]+\.){2,6}\w+/;
if(iptext) $("#bttitle").val(iptext[0]); var iptext = str.match(isip);
if(iptext) $("#bttitle").val(iptext[0]);
});
}
}); });
} }
//删除快捷登录 //删除快捷登录
@@ -1769,6 +1770,159 @@ function entitiesDecode(text) {
return text; return text;
} }
// base64.js
// base64加密
function base64_encode(str) {
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var out, i, len;
var c1, c2, c3;
len = str.length;
i = 0;
out = "";
while(i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
out += base64EncodeChars.charAt(c3 & 0x3F);
}
return out;
}
// base64解密
function base64_decode(str) {
var base64DecodeChars = new Array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
var c1, c2, c3, c4;
var i, len, out;
len = str.length;
i = 0;
out = "";
while(i < len) {
/* c1 */
do {
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
} while(i < len && c1 == -1);
if(c1 == -1)
break;
/* c2 */
do {
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
} while(i < len && c2 == -1);
if(c2 == -1)
break;
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
/* c3 */
do {
c3 = str.charCodeAt(i++) & 0xff;
if(c3 == 61)
return out;
c3 = base64DecodeChars[c3];
} while(i < len && c3 == -1);
if(c3 == -1)
break;
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
/* c4 */
do {
c4 = str.charCodeAt(i++) & 0xff;
if(c4 == 61)
return out;
c4 = base64DecodeChars[c4];
} while(i < len && c4 == -1);
if(c4 == -1)
break;
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
}
return out;
}
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for(i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
function utf8to16(str) {
var out, i, len, c;
var char2, char3;
out = "";
len = str.length;
i = 0;
while(i < len) {
c = str.charCodeAt(i++);
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += str.charAt(i-1);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = str.charCodeAt(i++);
char3 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
function pluginService(_name, version){ function pluginService(_name, version){
var data = {name:_name, func:'status'} var data = {name:_name, func:'status'}
@@ -2120,6 +2274,8 @@ function pluginOpInitD(a, _version, b) {
} }
function pluginLogs(_name, version, func, line){ function pluginLogs(_name, version, func, line){
var _this = this;
if ( typeof(version) == 'undefined' ){ if ( typeof(version) == 'undefined' ){
version = ''; version = '';
} }
@@ -2160,9 +2316,10 @@ function pluginLogs(_name, version, func, line){
if(rdata.data == '') { if(rdata.data == '') {
rdata.data = '当前没有日志!'; rdata.data = '当前没有日志!';
} }
var ebody = '<div class="soft-man-con">\
<textarea readonly="" style="margin: 0px;width: 100%;height: 520px;background-color: #333;color:#fff; padding:0 5px" id="info_log">'+rdata.data+'</textarea>\
</div>'; var h = parseInt($('.bt-w-menu').css('height')) - 40;
var ebody = '<textarea readonly="" style="margin: 0px;height: '+h+'px;width: 100%;background-color: #333;color:#fff; padding:0 5px" id="info_log">'+rdata.data+'</textarea>';
$(".soft-man-con").html(ebody); $(".soft-man-con").html(ebody);
var ob = document.getElementById('info_log'); var ob = document.getElementById('info_log');
ob.scrollTop = ob.scrollHeight; ob.scrollTop = ob.scrollHeight;
Vendored Executable → Regular
+45 -29
View File
File diff suppressed because one or more lines are too long
+15 -1
View File
@@ -102,7 +102,6 @@
</div> </div>
<div class="title c6 plr15"><h3 class="f16">安全</h3></div> <div class="title c6 plr15"><h3 class="f16">安全</h3></div>
<div class="setting-con pd15"> <div class="setting-con pd15">
<p class="mtb15"> <p class="mtb15">
@@ -148,6 +147,21 @@
<span class="set-info c7">为非管理员临时提供面板访问权限</span> <span class="set-info c7">为非管理员临时提供面板访问权限</span>
</p> </p>
</div> </div>
<div class="title c6 plr15"><h3 class="f16">通知</h3></div>
<div class="setting-con pd15">
<p class="mtb15">
<span class="set-tit text-right" title="TelegramBot" style="float: left;">TG机器人通知</span>
<input id="cfg_tgbot" name="cfg_tgbot" onclick="setNotifyApi('tgbot',this)" class="btswitch btswitch-ios" type="checkbox" {{data['notify_tgbot_enable']}}>
<label class="btswitch-btn ml5" for="cfg_tgbot" style="float: left;margin-top:4px;"></label>
<button ype="button" class="btn btn-default btn-xs panel_api_btn" style="vertical-align: middle; margin-left: 10px" onclick="getTgbot();">TelegramBot配置</button>
<span class="set-info c7">Telegram Bot机器人通知【<b style="color:red;">国内可能无法使用</b>】</span>
</p>
</div>
</div> </div>
</div> </div>
</div> </div>
-1
View File
@@ -146,7 +146,6 @@
</div> </div>
</div> </div>
</div> </div>
<script src="/static/js/echarts.min.js?v={{config.version}}"></script>
<script src="/static/app/control.js?v={{config.version}}"></script> <script src="/static/app/control.js?v={{config.version}}"></script>
{% endblock %} {% endblock %}
+47 -30
View File
@@ -2,35 +2,42 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<title>{{data['title']}}</title> <title>{{data['title']}}</title>
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
<link href="/static/bootstrap-3.3.5/css/bootstrap.min.css?v={{config.version}}" rel="stylesheet"> <link href="/static/bootstrap-3.3.5/css/bootstrap.min.css?v={{config.version}}" rel="stylesheet">
<link href="/static/css/site.css?v={{config.version}}" rel="stylesheet"> <link href="/static/css/site.css?v={{config.version}}" rel="stylesheet">
<link href="/static/codemirror/lib/codemirror.css?v={{config.version}}" rel="stylesheet"> <link href="/static/codemirror/lib/codemirror.css?v={{config.version}}" rel="stylesheet">
<script src="/static/language/Simplified_Chinese/lan.js?v={{config.version}}"></script> <script src="/static/language/Simplified_Chinese/lan.js?v={{config.version}}"></script>
<!--[if lte IE 9]> <!--[if lte IE 9]>
<script src="/static/js/requestAnimationFrame.js"></script> <script src="/static/js/requestAnimationFrame.js"></script>
<![endif]--> <![endif]-->
<!-- 统计一下用户量,让我的开发更有激情 --> <!-- 统计一下用户量,让我的开发更有激情 -->
<!-- Google tag (gtag.js) --> <!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD"></script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);} function gtag(){dataLayer.push(arguments);}
gtag('js', new Date()); gtag('js', new Date());
gtag('config', 'G-FC74BB2RGD'); gtag('config', 'G-FC74BB2RGD');
</script> </script>
{% for menu in data['hook_menu'] %} {% for menu in data['hook_menu'] %}
{% if menu['js_path'] %} {% if menu['css_path'] and data['hook_tag'] == menu['name'] %}
<!-- 加载插件css --> <!-- 加载插件css -->
<link href="/plugins/file?name={{menu['name']}}&v={{config.version}}&f={{menu['css_path']}}" rel="stylesheet" /> <link href="/plugins/file?name={{menu['name']}}&v={{config.version}}&f={{menu['css_path']}}" rel="stylesheet" />
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<!-- 全局静态HOOK -->
{% for menu in data['hook_global_static'] %}
{% if menu['css_path'] %}
<link href="/plugins/file?name={{menu['name']}}&v={{config.version}}&f={{menu['css_path']}}" rel="stylesheet" />
{% endif %}
{% endfor %}
</head> </head>
<body> <body>
@@ -83,11 +90,15 @@
{% block content %}{% endblock %} {% block content %}{% endblock %}
<div class="footer bgw">mdserver-web &copy;2018-∞ Linux面板 (<a class="btlink" target="_blank" href="//github.com/midoks/mdserver-web">源码</a>) <span style="margin-left:5px;">/</span> <div class="footer bgw">mdserver-web &copy;2018-∞ Linux面板 (<a class="btlink" target="_blank" href="//github.com/midoks/mdserver-web">源码</a>) <span style="margin-left:5px;">/</span>
<a class="btlink" style="margin-left:5px;" href="//github.com/midoks/mdserver-web/wiki" target="_blank">WIKI</a><span style="margin-left:5px;">/</span> <a class="btlink" target="_blank" style="margin-left:5px;" href="//github.com/midoks/mdserver-web/wiki">WIKI</a><span style="margin-left:5px;">/</span>
<a class='btlink panel_ad_list_mode' style="margin-left:5px;">AD</a> <a class='btlink panel_ad_list_mode' style="margin-left:5px;">AD</a>
<span style="margin-left:5px;">/</span>
<a class='btlink' target="_blank" href="https://bbs.midoks.me" style="margin-left:5px;">交流论坛</a>
<span style="margin-left:5px;">/</span>
<a class='btlink' target="_blank" href="https://t.me/mdserver_web" style="margin-left:5px;">TG吹水群</a>
</div>
</div> </div>
</div> </div>
</div>
</body> </body>
<script type="text/javascript"> <script type="text/javascript">
@@ -158,8 +169,14 @@ if (thisPath.indexOf('?')>-1){
<script src="/static/laydate/laydate.js?v={{config.version}}"></script> <script src="/static/laydate/laydate.js?v={{config.version}}"></script>
{% for menu in data['hook_menu'] %} {% for menu in data['hook_menu'] %}
{% if menu['js_path'] and data['hook_tag'] == menu['name'] %}
<script src="/plugins/file?name={{menu['name']}}&f={{menu['js_path']}}&v={{config.version}}"></script>
{% endif %}
{% endfor %}
<!-- 全局静态HOOK -->
{% for menu in data['hook_global_static'] %}
{% if menu['js_path'] %} {% if menu['js_path'] %}
<!-- 加载插件js -->
<script src="/plugins/file?name={{menu['name']}}&f={{menu['js_path']}}&v={{config.version}}"></script> <script src="/plugins/file?name={{menu['name']}}&f={{menu['js_path']}}&v={{config.version}}"></script>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
+29 -15
View File
@@ -5,6 +5,7 @@
import sys import sys
import os import os
import re
if sys.platform != 'darwin': if sys.platform != 'darwin':
os.chdir('/www/server/mdserver-web') os.chdir('/www/server/mdserver-web')
@@ -50,7 +51,6 @@ class backupTools:
mw.execShell(cmd) mw.execShell(cmd)
endDate = time.strftime('%Y/%m/%d %X', time.localtime()) endDate = time.strftime('%Y/%m/%d %X', time.localtime())
print(filename) print(filename)
if not os.path.exists(filename): if not os.path.exists(filename):
log = "网站[" + name + "]备份失败!" log = "网站[" + name + "]备份失败!"
@@ -83,6 +83,27 @@ class backupTools:
if num < 1: if num < 1:
break break
def getConf(self, mtype='mysql'):
path = mw.getServerDir() + '/' + mtype + '/etc/my.cnf'
return path
# 数据库密码处理
def mypass(self, act, root):
conf_file = self.getConf('mysql')
mw.execShell("sed -i '/user=root/d' {}".format(conf_file))
mw.execShell("sed -i '/password=/d' {}".format(conf_file))
if act:
mycnf = mw.readFile(conf_file)
src_dump = "[mysqldump]\n"
sub_dump = src_dump + "user=root\npassword=\"{}\"\n".format(root)
if not mycnf:
return False
mycnf = mycnf.replace(src_dump, sub_dump)
if len(mycnf) > 100:
mw.writeFile(conf_file, mycnf)
return True
return True
def backupDatabase(self, name, count): def backupDatabase(self, name, count):
db_path = mw.getServerDir() + '/mysql' db_path = mw.getServerDir() + '/mysql'
db_name = 'mysql' db_name = 'mysql'
@@ -104,17 +125,11 @@ class backupTools:
filename = backup_path + "/db_" + name + "_" + \ filename = backup_path + "/db_" + name + "_" + \
time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz" time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz"
import re
mysql_root = mw.M('config').dbPos(db_path, db_name).where( mysql_root = mw.M('config').dbPos(db_path, db_name).where(
"id=?", (1,)).getField('mysql_root') "id=?", (1,)).getField('mysql_root')
mycnf = mw.readFile(db_path + '/etc/my.cnf') my_cnf = self.getConf('mysql')
rep = "\[mysqldump\]\nuser=root" self.mypass(True, mysql_root)
sea = "[mysqldump]\n"
subStr = sea + "user=root\npassword=" + mysql_root + "\n"
mycnf = mycnf.replace(sea, subStr)
if len(mycnf) > 100:
mw.writeFile(db_path + '/etc/my.cnf', mycnf)
# mw.execShell(db_path + "/bin/mysqldump --opt --default-character-set=utf8 " + # mw.execShell(db_path + "/bin/mysqldump --opt --default-character-set=utf8 " +
# name + " | gzip > " + filename) # name + " | gzip > " + filename)
@@ -125,8 +140,10 @@ class backupTools:
# mw.execShell(db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " + # mw.execShell(db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " +
# name + " | gzip > " + filename) # name + " | gzip > " + filename)
mw.execShell(db_path + "/bin/mysqldump --force --opt --default-character-set=utf8 " + cmd = db_path + "/bin/mysqldump --defaults-file=" + my_cnf + " --force --opt --default-character-set=utf8 " + \
name + " | gzip > " + filename) name + " | gzip > " + filename
# print(cmd)
mw.execShell(cmd)
if not os.path.exists(filename): if not os.path.exists(filename):
endDate = time.strftime('%Y/%m/%d %X', time.localtime()) endDate = time.strftime('%Y/%m/%d %X', time.localtime())
@@ -136,10 +153,7 @@ class backupTools:
"----------------------------------------------------------------------------") "----------------------------------------------------------------------------")
return return
mycnf = mw.readFile(db_path + '/etc/my.cnf') self.mypass(False, mysql_root)
mycnf = mycnf.replace(subStr, sea)
if len(mycnf) > 100:
mw.writeFile(db_path + '/etc/my.cnf', mycnf)
endDate = time.strftime('%Y/%m/%d %X', time.localtime()) endDate = time.strftime('%Y/%m/%d %X', time.localtime())
outTime = time.time() - startTime outTime = time.time() - startTime
+24 -12
View File
@@ -196,32 +196,44 @@ error_logs()
mw_update() mw_update()
{ {
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"") LOCAL_ADDR=common
if [ ! -z "$cn" ];then ping -c 1 github.com > /dev/null 2>&1
curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh | bash if [ "$?" != "0" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "common" ];then
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash
else else
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install.sh | bash
fi fi
} }
mw_update_dev() mw_update_dev()
{ {
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"") LOCAL_ADDR=common
if [ ! -z "$cn" ];then ping -c 1 github.com > /dev/null 2>&1
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash if [ "$?" != "0" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "common" ];then
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
else else
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash
fi fi
cd /www/server/mdserver-web cd /www/server/mdserver-web
} }
mw_mirror() mw_mirror()
{ {
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"") LOCAL_ADDR=common
if [ ! -z "$cn" ];then ping -c 1 github.com > /dev/null 2>&1
bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) if [ "$?" != "0" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "common" ];then
bash <(curl --insecure -sSL https://raw.githubusercontent.com/midoks/change-linux-mirrors/main/change-mirrors.sh)
else else
bash <(curl -sSL https://raw.githubusercontent.com/midoks/change-linux-mirrors/main/change-mirrors.sh) bash <(curl --insecure -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)
fi fi
cd /www/server/mdserver-web cd /www/server/mdserver-web
} }
+29 -11
View File
@@ -56,6 +56,16 @@ else
fi fi
# cn=$(curl --insecure -fsSL -m 10 https://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
if [ $OSNAME != "macos" ];then if [ $OSNAME != "macos" ];then
if id www &> /dev/null ;then if id www &> /dev/null ;then
echo "" echo ""
@@ -71,14 +81,11 @@ if [ $OSNAME != "macos" ];then
mkdir -p /www/backup/site mkdir -p /www/backup/site
# https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh # https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -d /www/server/mdserver-web ];then if [ ! -d /www/server/mdserver-web ];then
if [ ! -z "$cn" ];then if [ "$LOCAL_ADDR" != "common" ];then
curl -sSLo /tmp/master.zip https://gitee.com/midoks/mdserver-web/repository/archive/master.zip curl --insecure -sSLo /tmp/master.zip https://gitee.com/midoks/mdserver-web/repository/archive/master.zip
else else
curl -sSLo /tmp/master.zip https://codeload.github.com/midoks/mdserver-web/zip/master curl --insecure -sSLo /tmp/master.zip https://codeload.github.com/midoks/mdserver-web/zip/master
fi fi
cd /tmp && unzip /tmp/master.zip cd /tmp && unzip /tmp/master.zip
@@ -89,8 +96,8 @@ if [ $OSNAME != "macos" ];then
# install acme.sh # install acme.sh
if [ ! -d /root/.acme.sh ];then if [ ! -d /root/.acme.sh ];then
if [ ! -z "$cn" ];then if [ "$LOCAL_ADDR" != "common" ];then
curl -sSL -o /tmp/acme.tar.gz https://ghproxy.com/github.com/acmesh-official/acme.sh/archive/master.tar.gz curl --insecure -sSLo /tmp/acme.tar.gz https://gitee.com/neilpang/acme.sh/repository/archive/master.tar.gz
tar xvzf /tmp/acme.tar.gz -C /tmp tar xvzf /tmp/acme.tar.gz -C /tmp
cd /tmp/acme.sh-master cd /tmp/acme.sh-master
bash acme.sh install bash acme.sh install
@@ -103,10 +110,21 @@ if [ $OSNAME != "macos" ];then
fi fi
fi fi
echo "use system version: ${OSNAME}" echo "use system version: ${OSNAME}"
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh if [ "${OSNAME}" == "macos" ];then
if [ "$LOCAL_ADDR" != "common" ];then
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/install/macos.sh | bash
else
curl --insecure -fsSL ${HTTP_PREFIX}https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install/macos.sh | bash
fi
else
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh
fi
if [ "${OSNAME}" == "macos" ];then
echo "macos end"
exit 0
fi
cd /www/server/mdserver-web && bash cli.sh start cd /www/server/mdserver-web && bash cli.sh start
isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'` isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'`
+18 -18
View File
@@ -46,31 +46,31 @@ apt install -y wget curl lsof unzip tar cron expect locate
apt install -y python3-pip python3-dev python3-venv apt install -y python3-pip python3-dev python3-venv
# if [ -f /usr/sbin/ufw ];then if [ -f /usr/sbin/ufw ];then
# if [ "$SSH_PORT" != "" ];then # look
# ufw allow $SSH_PORT/tcp # ufw status
# else ufw enable
# ufw allow 22/tcp if [ "$SSH_PORT" != "" ];then
# fi ufw allow $SSH_PORT/tcp
else
ufw allow 22/tcp
fi
# ufw allow 80/tcp ufw allow 80/tcp
# ufw allow 443/tcp ufw allow 443/tcp
# ufw allow 888/tcp ufw allow 888/tcp
# fi fi
# if [ -f /usr/sbin/ufw ];then if [ ! -f /usr/sbin/ufw ];then
# ufw disable
# fi
if [ ! -f /usr/sbin/firewalld ];then
# look # look
# firewall-cmd --list-all # firewall-cmd --list-all
# apt remove -y firewalld
apt install -y firewalld apt install -y firewalld
systemctl enable firewalld systemctl enable firewalld
#取消服务锁定 #取消服务锁定
systemctl unmask firewalld systemctl unmask firewalld
systemctl start firewalld
if [ "$SSH_PORT" != "" ];then if [ "$SSH_PORT" != "" ];then
firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp
@@ -81,13 +81,13 @@ if [ ! -f /usr/sbin/firewalld ];then
firewall-cmd --permanent --zone=public --add-port=443/tcp firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --permanent --zone=public --add-port=888/tcp firewall-cmd --permanent --zone=public --add-port=888/tcp
systemctl start firewalld
# fix:debian10 firewalld faq # fix:debian10 firewalld faq
# https://kawsing.gitbook.io/opensystem/andoid-shou-ji/untitled/fang-huo-qiang#debian-10-firewalld-0.6.3-error-commandfailed-usrsbinip6tablesrestorewn-failed-ip6tablesrestore-v1.8 # https://kawsing.gitbook.io/opensystem/andoid-shou-ji/untitled/fang-huo-qiang#debian-10-firewalld-0.6.3-error-commandfailed-usrsbinip6tablesrestorewn-failed-ip6tablesrestore-v1.8
sed -i 's#IndividualCalls=no#IndividualCalls=yes#g' /etc/firewalld/firewalld.conf sed -i 's#IndividualCalls=no#IndividualCalls=yes#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload firewall-cmd --reload
#安装时不开启
systemctl stop firewalld
fi fi
#fix zlib1g-dev fail #fix zlib1g-dev fail
-4
View File
@@ -36,8 +36,6 @@ if [ ! -d $DEV/server/lib ]; then
cd $DEV/server/mdserver-web/scripts && bash lib.sh cd $DEV/server/mdserver-web/scripts && bash lib.sh
fi fi
pip3 install mysqlclient
chmod 755 $DEV/server/mdserver-web/data chmod 755 $DEV/server/mdserver-web/data
if [ -f $DEV/server/mdserver-web/bin/activate ];then if [ -f $DEV/server/mdserver-web/bin/activate ];then
cd $DEV/server/mdserver-web && python3 -m venv $DEV/server/mdserver-web cd $DEV/server/mdserver-web && python3 -m venv $DEV/server/mdserver-web
@@ -47,8 +45,6 @@ else
cd $DEV/server/mdserver-web && pip3 install -r $DEV/server/mdserver-web/requirements.txt cd $DEV/server/mdserver-web && pip3 install -r $DEV/server/mdserver-web/requirements.txt
fi fi
pip3 install mysqlclient
cd $DEV/server/mdserver-web && ./cli.sh start cd $DEV/server/mdserver-web && ./cli.sh start
cd $DEV/server/mdserver-web && ./cli.sh stop cd $DEV/server/mdserver-web && ./cli.sh stop
+5 -5
View File
@@ -84,9 +84,6 @@ if [ ! -f /usr/sbin/firewalld ];then
systemctl unmask firewalld systemctl unmask firewalld
systemctl start firewalld systemctl start firewalld
sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload
# look # look
# firewall-cmd --list-all # firewall-cmd --list-all
@@ -102,7 +99,7 @@ if [ ! -f /usr/sbin/firewalld ];then
# firewall-cmd --permanent --zone=public --add-port=3306/tcp # firewall-cmd --permanent --zone=public --add-port=3306/tcp
# firewall-cmd --permanent --zone=public --add-port=30000-40000/tcp # firewall-cmd --permanent --zone=public --add-port=30000-40000/tcp
# sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload firewall-cmd --reload
#安装时不开启 #安装时不开启
@@ -134,11 +131,14 @@ if [ $VERSION_ID -ge 8 ];then
gmp-devel kernel-devel libXpm-devel libaio-devel libcap libcurl libcurl-devel libevent libevent-devel \ gmp-devel kernel-devel libXpm-devel libaio-devel libcap libcurl libcurl-devel libevent libevent-devel \
libicu-devel libidn libidn-devel libmcrypt libmcrypt-devel libmemcached libmemcached-devel \ libicu-devel libidn libidn-devel libmcrypt libmcrypt-devel libmemcached libmemcached-devel \
libpng libpng-devel libstdc++.so.6 libtirpc libtirpc-devel libtool libtool-libs libwebp libwebp-devel \ libpng libpng-devel libstdc++.so.6 libtirpc libtirpc-devel libtool libtool-libs libwebp libwebp-devel \
libxml2 libxml2-devel libxslt libxslt-devel lsof make mysql-devel ncurses ncurses-devel net-tools \ libxml2 libxml2-devel libxslt libxslt-devel libarchive lsof make mysql-devel ncurses ncurses-devel net-tools \
oniguruma oniguruma-devel patch pcre pcre-devel perl perl-Data-Dumper perl-devel procps psmisc python3-devel \ oniguruma oniguruma-devel patch pcre pcre-devel perl perl-Data-Dumper perl-devel procps psmisc python3-devel \
readline-devel rpcgen sqlite-devel tar unzip vim-minimal wget zip zlib zlib-devel ; readline-devel rpcgen sqlite-devel tar unzip vim-minimal wget zip zlib zlib-devel ;
do do
dnf $REPOS install -y $rpms; dnf $REPOS install -y $rpms;
if [ "$?" != "0" ];then
dnf install -y $rpms;
fi
done done
else else
# CentOS 7 # CentOS 7
+20 -24
View File
@@ -27,31 +27,26 @@ localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'` SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
echo "SSH PORT:${SSH_PORT}" echo "SSH PORT:${SSH_PORT}"
# if [ -f /usr/sbin/ufw ];then if [ -f /usr/sbin/ufw ];then
# look
# ufw status
ufw enable
# # look if [ "$SSH_PORT" != "" ];then
# # ufw status ufw allow $SSH_PORT/tcp
# ufw enable else
ufw allow 22/tcp
fi
# if [ "$SSH_PORT" != "" ];then ufw allow 80/tcp
# ufw allow $SSH_PORT/tcp ufw allow 443/tcp
# else ufw allow 888/tcp
# ufw allow 22/tcp fi
# fi
# ufw allow 80/tcp if [ ! -f /usr/sbin/ufw ];then
# ufw allow 443/tcp
# ufw allow 888/tcp
# fi
# if [ -f /usr/sbin/ufw ];then
# ufw disable
# fi
if [ ! -f /usr/sbin/firewalld ];then
apt install -y firewalld apt install -y firewalld
systemctl enable firewalld systemctl enable firewalld
systemctl start firewalld
if [ "$SSH_PORT" != "" ];then if [ "$SSH_PORT" != "" ];then
firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp firewall-cmd --permanent --zone=public --add-port=${SSH_PORT}/tcp
@@ -63,17 +58,18 @@ if [ ! -f /usr/sbin/firewalld ];then
firewall-cmd --permanent --zone=public --add-port=443/tcp firewall-cmd --permanent --zone=public --add-port=443/tcp
firewall-cmd --permanent --zone=public --add-port=888/tcp firewall-cmd --permanent --zone=public --add-port=888/tcp
systemctl start firewalld
# fix:debian10 firewalld faq # fix:debian10 firewalld faq
# https://kawsing.gitbook.io/opensystem/andoid-shou-ji/untitled/fang-huo-qiang#debian-10-firewalld-0.6.3-error-commandfailed-usrsbinip6tablesrestorewn-failed-ip6tablesrestore-v1.8 # https://kawsing.gitbook.io/opensystem/andoid-shou-ji/untitled/fang-huo-qiang#debian-10-firewalld-0.6.3-error-commandfailed-usrsbinip6tablesrestorewn-failed-ip6tablesrestore-v1.8
sed -i 's#IndividualCalls=no#IndividualCalls=yes#g' /etc/firewalld/firewalld.conf sed -i 's#IndividualCalls=no#IndividualCalls=yes#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload firewall-cmd --reload
# #安装时不开启
# systemctl stop firewalld
fi fi
#安装时不开启
systemctl stop firewalld
apt install -y devscripts apt install -y devscripts
apt install -y net-tools apt install -y net-tools
apt install -y python3-dev apt install -y python3-dev
+40 -5
View File
@@ -5,7 +5,7 @@ export PATH
is64bit=`getconf LONG_BIT` is64bit=`getconf LONG_BIT`
echo -e "您正在安装的是\033[31mmdserver-web测试版\033[0m,非开发测试用途请使用正式版 install.sh !" echo -e "您正在安装的是\033[31mmdserver-web测试版\033[0m,非开发测试用途请使用正式版 install.sh !"
echo -e "You are installing\033[31mmdserver-web dev version\033[0m, normally use install.sh for production.\n" echo -e "You are installing\033[31m mdserver-web dev version\033[0m, normally use install.sh for production.\n"
sleep 1 sleep 1
{ {
@@ -60,6 +60,20 @@ else
fi fi
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
# cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
# HTTP_PREFIX="https://"
# if [ ! -z "$cn" ];then
# HTTP_PREFIX="https://ghproxy.com/"
# fi
if [ $OSNAME != "macos" ];then if [ $OSNAME != "macos" ];then
mkdir -p /www/server mkdir -p /www/server
mkdir -p /www/wwwroot mkdir -p /www/wwwroot
@@ -68,7 +82,13 @@ if [ $OSNAME != "macos" ];then
mkdir -p /www/backup/site mkdir -p /www/backup/site
if [ ! -d /www/server/mdserver-web ];then if [ ! -d /www/server/mdserver-web ];then
curl -sSLo /tmp/dev.zip https://github.com/midoks/mdserver-web/archive/refs/heads/dev.zip
if [ "$LOCAL_ADDR" == "common" ];then
curl --insecure -sSLo /tmp/dev.zip ${HTTP_PREFIX}github.com/midoks/mdserver-web/archive/refs/heads/dev.zip
else
curl --insecure -sSLo /tmp/dev.zip https://gitee.com/midoks/mdserver-web/repository/archive/dev.zip
fi
cd /tmp && unzip /tmp/dev.zip cd /tmp && unzip /tmp/dev.zip
mv -f /tmp/mdserver-web-dev /www/server/mdserver-web mv -f /tmp/mdserver-web-dev /www/server/mdserver-web
rm -rf /tmp/dev.zip rm -rf /tmp/dev.zip
@@ -77,8 +97,9 @@ if [ $OSNAME != "macos" ];then
# install acme.sh # install acme.sh
if [ ! -d /root/.acme.sh ];then if [ ! -d /root/.acme.sh ];then
if [ ! -z "$cn" ];then if [ "$LOCAL_ADDR" != "common" ];then
curl -sSL -o /tmp/acme.tar.gz https://ghproxy.com/github.com/acmesh-official/acme.sh/archive/master.tar.gz # curl -sSL -o /tmp/acme.tar.gz ${HTTP_PREFIX}github.com/acmesh-official/acme.sh/archive/master.tar.gz
curl --insecure -sSLo /tmp/acme.tar.gz https://gitee.com/neilpang/acme.sh/repository/archive/master.tar.gz
tar xvzf /tmp/acme.tar.gz -C /tmp tar xvzf /tmp/acme.tar.gz -C /tmp
cd /tmp/acme.sh-master cd /tmp/acme.sh-master
bash acme.sh install bash acme.sh install
@@ -92,7 +113,21 @@ if [ $OSNAME != "macos" ];then
fi fi
echo "use system version: ${OSNAME}" echo "use system version: ${OSNAME}"
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh
if [ "${OSNAME}" == "macos" ];then
if [ "$LOCAL_ADDR" != "common" ];then
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/install/macos.sh | bash
else
curl --insecure -fsSL ${HTTP_PREFIX}https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install/macos.sh | bash
fi
else
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh
fi
if [ "${OSNAME}" == "macos" ];then
echo "macos end"
exit 0
fi
cd /www/server/mdserver-web && bash cli.sh start cd /www/server/mdserver-web && bash cli.sh start
isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'` isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'`

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