Compare commits

...
385 Commits
Author SHA1 Message Date
Mr Chen dcae829a1c Merge pull request #577 from midoks/dev
0.16.9
2024-05-22 22:12:39 +08:00
Mr Chen de4e134be8 0.16.9
- mysql同步优化,享受丝滑般感觉。
- 网站统计 - 实时-可调节1-10s。
- 网站统计 - 加入大小条件。
- Sphinx优化。
2024-05-22 22:12:03 +08:00
Mr Chen ba96e62126 Update cmd.md 2024-05-22 22:11:07 +08:00
Mr Chen 990fb06567 Update .gitignore 2024-05-22 22:02:17 +08:00
Mr Chen 71c1034d12 Update .gitignore 2024-05-22 22:01:37 +08:00
Mr Chen 6582cbc09d update 2024-05-22 22:01:09 +08:00
Mr Chen 52bad278cc Update README.md 2024-05-22 19:48:12 +08:00
Mr Chen e023490002 网站统计加入大小条件 2024-05-22 19:44:25 +08:00
Mr Chen c1a7443597 Update r3.6.txt 2024-05-22 11:46:40 +08:00
Mr Chen 3f57e7da07 update 2024-05-22 11:45:51 +08:00
Mr Chen 0461bf3225 Update sphinx_make.py 2024-05-22 11:37:47 +08:00
Mr Chen ac0a503aa7 Update push_notice_msg.py 2024-05-22 10:57:45 +08:00
Mr Chen 706e9e98e7 Update redis.tpl 2024-05-22 10:50:08 +08:00
Mr Chen d9e878d607 Update redis_cluster.conf 2024-05-22 10:45:57 +08:00
Mr Chen ceb5f21814 Update redis_slave.conf 2024-05-22 10:44:45 +08:00
Mr Chen c8e689433b mw update_dev 2024-05-22 10:44:21 +08:00
Mr Chen f2171aa159 Update mw.tpl 2024-05-22 03:29:46 +08:00
Mr Chen 6eccdd510e update 2024-05-22 03:29:01 +08:00
Mr Chen c9a00809a4 Update redis_slave.conf 2024-05-22 02:57:42 +08:00
Mr Chen 9f1d8e43e6 Update redis_slave.conf 2024-05-22 02:54:26 +08:00
Mr Chen e8eda79a1a Update redis.conf 2024-05-22 02:54:06 +08:00
Mr Chen f25847d31d Update tidb.yaml 2024-05-22 02:53:27 +08:00
Mr Chen bda7dfa518 Update redis_slave.conf 2024-05-22 02:53:06 +08:00
Mr Chen 4115c29fe9 Update redis_slave.conf 2024-05-22 02:46:09 +08:00
Mr Chen f73e378fd6 Update index.py 2024-05-21 23:41:56 +08:00
Mr Chen aa9ab55fec Update sphinx_make.py 2024-05-21 23:39:19 +08:00
Mr Chen da5c44a747 Update sphinx_make.py 2024-05-21 23:39:04 +08:00
Mr Chen ee55c998ba Update sphinx_make.py 2024-05-21 23:28:55 +08:00
Mr Chen 2e75a56502 Update sphinx_make.py 2024-05-21 23:26:15 +08:00
Mr Chen a66279ba37 Update sphinx_make.py 2024-05-21 23:23:33 +08:00
Mr Chen 78bbae1f53 Update sphinx_make.py 2024-05-21 23:21:20 +08:00
Mr Chen a87def4325 Update sphinx_make.py 2024-05-21 22:29:32 +08:00
Mr Chen b84ac2daf1 Update sphinx_make.py 2024-05-21 20:58:22 +08:00
Mr Chen 7c9bf99669 Update sphinx_make.py 2024-05-21 20:56:38 +08:00
Mr Chen 599f6ecc51 Update sphinx_make.py 2024-05-21 20:42:38 +08:00
Mr Chen 47a17fbc46 Update sphinx_make.py 2024-05-21 20:40:31 +08:00
Mr Chen 80fa0ea62d Update sphinx_make.py 2024-05-21 20:40:15 +08:00
Mr Chen 83c78609a4 Update sphinx_make.py 2024-05-21 20:35:50 +08:00
Mr Chen 298d4b7981 Update sphinx_make.py 2024-05-21 20:33:22 +08:00
Mr Chen dc6f4e03e7 Update sphinx_make.py 2024-05-21 20:27:55 +08:00
Mr Chen 8b0b2b2d72 Update sphinx.js 2024-05-21 20:00:29 +08:00
Mr Chen d4087ce7f0 Update sphinx_make.py 2024-05-21 19:59:23 +08:00
Mr Chen f92df461ba Update sphinx_make.py 2024-05-21 19:58:43 +08:00
Mr Chen 9e015bc08c Update sphinx_make.py 2024-05-21 19:55:36 +08:00
Mr Chen 4bffd9a22d update 2024-05-21 19:43:25 +08:00
Mr Chen e2ef42fbbc Update sphinx.js 2024-05-21 19:23:30 +08:00
Mr Chen f10e05b7ee update 2024-05-21 19:20:07 +08:00
Mr Chen c15288cf09 update 2024-05-21 17:12:39 +08:00
Mr Chen 2461307d64 update 2024-05-21 16:57:05 +08:00
Mr Chen 95ec87346d update 2024-05-21 16:07:59 +08:00
Mr Chen f99c5b5fc4 update 2024-05-21 16:04:02 +08:00
Mr Chen adfd3bef2d Update app.js 2024-05-21 15:58:32 +08:00
Mr Chen c11631c0c3 Update index.html 2024-05-21 14:42:11 +08:00
Mr Chen 4f87725101 Update redis_slave.conf 2024-05-21 14:22:40 +08:00
Mr Chen 3a6695bb0d Update redis.conf 2024-05-21 14:22:02 +08:00
Mr Chen dd3bcced66 Update redis_slave.conf 2024-05-21 14:21:57 +08:00
Mr Chen 81a163f744 Update site.css 2024-05-21 03:08:08 +08:00
Mr Chen 19dd36fa8b Update sphinx_make.py 2024-05-21 00:22:03 +08:00
Mr Chen 9dcb028158 Update sphinx_make.py 2024-05-21 00:15:26 +08:00
Mr Chen 1ce841eac9 Update sphinx_make.py 2024-05-21 00:12:15 +08:00
Mr Chen c99311dad9 update 2024-05-21 00:07:48 +08:00
Mr Chen d7dd126a48 Update sphinx_make.py 2024-05-20 23:50:06 +08:00
Mr Chen ec8ab6bc45 Update sphinx_make.py 2024-05-20 23:48:03 +08:00
Mr Chen d5b87f450d Update sphinx_make.py 2024-05-20 23:46:23 +08:00
Mr Chen 0016f85132 Update sphinx_make.py 2024-05-20 23:18:48 +08:00
Mr Chen 32a6b36297 Update tools.py 2024-05-20 22:31:11 +08:00
Mr Chen 8da60ffc6b Update tools.py 2024-05-20 22:20:32 +08:00
Mr Chen 64d65a5cac Update sphinx_make.py 2024-05-20 20:14:48 +08:00
Mr Chen cf5b986d2e update 2024-05-20 14:11:27 +08:00
Mr Chen e1d0fc49bb Update install.sh 2024-05-20 00:34:08 +08:00
Mr Chen 68187ee7dd update 2024-05-20 00:21:09 +08:00
Mr Chen 9f7a7c5e59 Update rhel.sh 2024-05-20 00:10:44 +08:00
Mr Chen 90b14d59b0 Update install.sh 2024-05-19 23:51:32 +08:00
Mr Chen e8d1ea0a38 Update install.sh 2024-05-19 23:51:11 +08:00
Mr Chen edf8a5534a Update install.sh 2024-05-19 23:48:06 +08:00
Mr Chen 87bceced80 update 2024-05-19 23:18:48 +08:00
Mr Chen db3350e85c Update install.sh 2024-05-19 23:03:59 +08:00
Mr Chen 56b3aae0c7 Update install.sh 2024-05-19 22:22:52 +08:00
Mr Chen 01d5b75d90 Update install.sh 2024-05-19 22:15:43 +08:00
Mr Chen cbf3a15bf0 update 2024-05-19 22:06:47 +08:00
Mr Chen 2f0f6eaed6 Update install.sh 2024-05-19 21:54:20 +08:00
Mr Chen f0fcec44ff Update install.sh 2024-05-19 21:46:52 +08:00
Mr Chen fcfdfe822a up 2024-05-19 21:36:25 +08:00
Mr Chen d8e08812f9 update 2024-05-19 19:49:15 +08:00
Mr Chen d0ba142933 Update sphinx_make.py 2024-05-19 18:42:43 +08:00
Mr Chen b4e130c664 Update sphinx_make.py 2024-05-19 18:25:51 +08:00
Mr Chen 7503907f34 Update sphinx_make.py 2024-05-19 18:22:13 +08:00
Mr Chen 390df93477 Update sphinx_make.py 2024-05-19 18:20:55 +08:00
Mr Chen abcf6250e3 Update sphinx_make.py 2024-05-19 18:20:10 +08:00
Mr Chen 70370fcb0b Update sphinx_make.py 2024-05-19 18:19:57 +08:00
Mr Chen 57e7021be2 Update sphinx_make.py 2024-05-19 18:10:54 +08:00
Mr Chen 45b7abd0fb Update sphinx_make.py 2024-05-19 17:58:50 +08:00
Mr Chen a6d96bb4d8 Update sphinx_make.py 2024-05-19 17:57:27 +08:00
Mr Chen 2742ecfc67 Update sphinx_make.py 2024-05-19 17:49:08 +08:00
Mr Chen 60747c2f04 Update sphinx_make.py 2024-05-19 17:47:51 +08:00
Mr Chen 2b019a704a Update sphinx_make.py 2024-05-19 17:47:27 +08:00
Mr Chen 7e049a381b Update sphinx_make.py 2024-05-19 17:45:39 +08:00
Mr Chen 2f4cf46bcf Update sphinx_make.py 2024-05-19 17:45:27 +08:00
Mr Chen 706ee146b5 Update sphinx_make.py 2024-05-19 17:43:52 +08:00
Mr Chen 79b4d09d50 Update index.py 2024-05-19 17:37:47 +08:00
Mr Chen 2f0797daab Update sphinx_make.py 2024-05-19 17:34:37 +08:00
Mr Chen 8e47c73f5c Update sphinx_make.py 2024-05-19 17:27:22 +08:00
Mr Chen c90d752ae7 update 2024-05-19 17:21:19 +08:00
Mr Chen 7c96bbe72f Update sphinx_make.py 2024-05-19 16:56:27 +08:00
Mr Chen 53134b7ecc Update sphinx_make.py 2024-05-19 16:36:14 +08:00
Mr Chen bf859f7c7c Update sphinx_make.py 2024-05-19 16:29:16 +08:00
Mr Chen 0046d02ddf update 2024-05-19 16:24:33 +08:00
Mr Chen 5a0e7a3b60 update 2024-05-19 15:09:25 +08:00
Mr Chen a74ca20d0e up 2024-05-19 14:58:14 +08:00
Mr Chen 41109af522 Update install.sh 2024-05-19 11:27:13 +08:00
Mr Chen b3b23994eb Update sphinx.js 2024-05-19 02:40:11 +08:00
Mr Chen 02f3a147aa Update index.py 2024-05-19 02:36:34 +08:00
Mr Chen 10edf675f5 Update config_api.py 2024-05-19 02:35:24 +08:00
Mr Chen b07b6f0c94 update 2024-05-19 02:35:03 +08:00
Mr Chen 002639936e update 2024-05-19 01:32:31 +08:00
Mr Chen aac516c8f8 Update stats.js 2024-05-19 00:56:35 +08:00
Mr Chen efd07f6de2 网站统计 - 实时请求 可选择 2024-05-19 00:51:35 +08:00
Mr Chen fa17782573 Update index.py 2024-05-18 14:15:57 +08:00
Mr Chen 9ee3aebc8c Update index.py 2024-05-18 14:02:17 +08:00
Mr Chen b778c8cdeb Update index.py 2024-05-18 13:57:34 +08:00
Mr Chen 1d1e6b1d5b Update index.py 2024-05-18 12:49:46 +08:00
Mr Chen 70012ea7ee Update index.py 2024-05-18 11:56:56 +08:00
Mr Chen 0897fd9370 Update index.py 2024-05-18 11:51:51 +08:00
Mr Chen 477b8b38fd Update index.py 2024-05-18 10:58:10 +08:00
Mr Chen e805910b1b Update index.py 2024-05-18 10:54:06 +08:00
Mr Chen 2f9903753f Update index.py 2024-05-18 02:57:32 +08:00
Mr Chen 53cd6377bb Update stats.js 2024-05-18 00:57:55 +08:00
Mr Chen 56cf0271b8 Update index.py 2024-05-17 18:26:51 +08:00
Mr Chen 4fefb0efb2 Update index.py 2024-05-17 18:26:18 +08:00
Mr Chen 222b8bc4de Update index.py 2024-05-17 17:58:50 +08:00
Mr Chen dc0e6fe78a Update index.py 2024-05-17 17:57:14 +08:00
Mr Chen 22a21025af Update index.py 2024-05-17 17:56:11 +08:00
Mr Chen 7cd102c40f Update index.py 2024-05-17 17:55:47 +08:00
Mr Chen 5cd7a65737 Update index.py 2024-05-17 17:48:40 +08:00
Mr Chen c370486845 Update mysql.js 2024-05-17 16:59:08 +08:00
Mr Chen cb9857edf2 update 2024-05-17 16:51:10 +08:00
Mr Chen 8fb3410366 Update mysql.js 2024-05-17 16:26:55 +08:00
Mr Chen 659ef259b7 Update index.py 2024-05-17 15:44:33 +08:00
Mr Chen 9d89a92b78 Update mysql.js 2024-05-17 15:33:48 +08:00
Mr Chen 139f353034 update 2024-05-17 14:09:57 +08:00
Mr Chen 908b1cf684 Update backup.py 2024-05-17 14:05:25 +08:00
Mr Chen 07dc74c283 update 2024-05-17 13:56:47 +08:00
Mr Chen 61e136fb39 Update backup.py 2024-05-17 13:54:59 +08:00
Mr Chen 030e05b2cf Update index.py 2024-05-17 13:52:19 +08:00
Mr Chen 24750cfdb2 Update config_api.py 2024-05-17 13:35:26 +08:00
Mr Chen 975a69fce8 Update layout.html 2024-05-17 13:35:13 +08:00
Mr Chen 5f42f37ee2 Update mysql.sql 2024-05-17 05:24:48 +08:00
Mr Chen 9925daa363 Update index.py 2024-05-17 05:08:45 +08:00
Mr Chen 2572bde607 Update index.py 2024-05-17 05:05:06 +08:00
Mr Chen 572207105c Update index.py 2024-05-17 05:04:18 +08:00
Mr Chen 2b8804e960 同步问题 2024-05-17 05:01:39 +08:00
Mr Chen 310409c52b Update mw.tpl 2024-05-17 04:06:01 +08:00
Mr Chen 01e95fa6fb Update index.py 2024-05-17 03:36:27 +08:00
Mr Chen 848021a639 Update index.py 2024-05-17 03:27:20 +08:00
Mr Chen a679c0e90c Update index.py 2024-05-17 03:26:37 +08:00
Mr Chen 8d9eb6302c Update index.py 2024-05-17 03:20:29 +08:00
Mr Chen f6663ad370 Update index.py 2024-05-17 03:18:59 +08:00
Mr Chen 9964745e46 Update index.py 2024-05-17 01:49:11 +08:00
Mr Chen b570a4552a Update index.py 2024-05-17 01:48:00 +08:00
Mr Chen cd2655a6f9 Update index.py 2024-05-17 01:47:40 +08:00
Mr Chen 608b40a110 Update index.py 2024-05-17 01:46:17 +08:00
Mr Chen a65d42ed2e Update index.py 2024-05-17 01:43:57 +08:00
Mr Chen b0d8d4bef8 Update index.py 2024-05-17 01:43:19 +08:00
Mr Chen d9f657c236 Update index.py 2024-05-17 01:42:05 +08:00
Mr Chen de02bcd800 Update index.py 2024-05-17 01:39:46 +08:00
Mr Chen 1f8dbe1a5f Update index.py 2024-05-17 01:37:54 +08:00
Mr Chen 8f4949cf8d Update index.py 2024-05-17 01:35:43 +08:00
Mr Chen 6128186a2c Update index.py 2024-05-17 01:26:35 +08:00
Mr Chen 7f707f9aac Update index.py 2024-05-17 01:08:13 +08:00
Mr Chen 56c1cd88ee Update config_api.py 2024-05-17 01:02:36 +08:00
Mr Chen 5d0b8b1877 Update layout.html 2024-05-17 01:01:48 +08:00
Mr Chen e944c9fbc5 Update layout.html 2024-05-17 01:01:16 +08:00
Mr Chen 8cab94e26c Update config_api.py 2024-05-17 00:45:56 +08:00
Mr Chen edb26fd11c update 2024-05-17 00:44:52 +08:00
Mr Chen cfd3a07046 Update mysql.js 2024-05-17 00:32:27 +08:00
Mr Chen 8d4ffc431a Update index.py 2024-05-17 00:21:37 +08:00
Mr Chen 22b97ab255 updatae 2024-05-17 00:21:06 +08:00
Mr Chen 8cfc5c5344 Update stats.js 2024-05-16 21:09:10 +08:00
Mr Chen 01c9633a1b Update index.py 2024-05-16 20:32:22 +08:00
Mr Chen 160634d3d4 Update index.py 2024-05-16 20:09:21 +08:00
Mr Chen 59b4ec32a6 Update index.py 2024-05-16 19:58:22 +08:00
Mr Chen 08a2295cdc Update index.py 2024-05-16 19:57:51 +08:00
Mr Chen fb7dbd69e5 Update index.py 2024-05-16 19:43:55 +08:00
Mr Chen c212a30536 Update index.py 2024-05-16 19:42:04 +08:00
Mr Chen 7a7acd3a4d Update index.py 2024-05-16 19:39:45 +08:00
Mr Chen f5edd83164 Update index.py 2024-05-16 19:04:38 +08:00
Mr Chen 8ea3ac1a3c Update index.py 2024-05-16 19:04:21 +08:00
Mr Chen d241ceea3e Update index.py 2024-05-16 18:55:07 +08:00
Mr Chen 6b3f50374a Update index.py 2024-05-16 18:32:59 +08:00
Mr Chen b3ceb03365 Update index.py 2024-05-16 18:25:20 +08:00
Mr Chen 87b26a14df Update mysql.js 2024-05-16 18:25:02 +08:00
Mr Chen 9046a09c0a Update mysql.js 2024-05-16 18:18:22 +08:00
Mr Chen 8bbfdbbf66 Update index.py 2024-05-16 17:57:46 +08:00
Mr Chen fa2d5c690c Update index.py 2024-05-16 17:46:25 +08:00
Mr Chen 681dfc96cb update 2024-05-16 16:33:19 +08:00
Mr Chen 362f5eb427 Update index.py 2024-05-16 16:28:07 +08:00
Mr Chen b033bd1c73 Update index.py 2024-05-16 16:17:04 +08:00
Mr Chen ea94fa21d5 Update index.py 2024-05-16 16:14:51 +08:00
Mr Chen 36c1541179 Update index.py 2024-05-16 16:13:05 +08:00
Mr Chen d5864db956 update 2024-05-15 23:56:52 +08:00
Mr Chen 00008b657c Update index.py 2024-05-15 21:11:29 +08:00
Mr Chen 3abed25d71 Update index.py 2024-05-15 20:52:58 +08:00
Mr Chen 862ea95a77 Update index.py 2024-05-15 20:22:58 +08:00
Mr Chen 63d624d084 Update index.py 2024-05-15 20:11:59 +08:00
Mr Chen c580076307 Update index.py 2024-05-15 20:01:59 +08:00
Mr Chen 3fada81661 Update index.py 2024-05-15 20:00:36 +08:00
Mr Chen a3bd0c6bda Update index.py 2024-05-15 20:00:19 +08:00
Mr Chen 454b036908 Update index.py 2024-05-15 20:00:01 +08:00
Mr Chen 1af9b1ddaa Update index.py 2024-05-15 19:59:35 +08:00
Mr Chen 5818fb46f1 Update mysql.js 2024-05-15 19:36:15 +08:00
Mr Chen 1069fd5252 Update index.py 2024-05-15 19:33:53 +08:00
Mr Chen 76229b6651 Update index.py 2024-05-15 19:31:30 +08:00
Mr Chen 4c9e717559 Update index.py 2024-05-15 19:30:04 +08:00
Mr Chen 9ae61517a4 Update index.py 2024-05-15 19:20:02 +08:00
Mr Chen 952a173535 Update index.py 2024-05-15 19:11:28 +08:00
Mr Chen 5b9b03a153 Update index.py 2024-05-15 19:09:01 +08:00
Mr Chen 9475dbecfe Update index.py 2024-05-15 18:56:38 +08:00
Mr Chen 5a64835969 Update index.py 2024-05-15 18:56:00 +08:00
Mr Chen 8685f21ad9 Update index.py 2024-05-15 18:50:52 +08:00
Mr Chen 500ccff90b update 2024-05-15 17:48:41 +08:00
Mr Chen 85adb449c2 Update index.py 2024-05-15 17:38:49 +08:00
Mr Chen aa6748c09d Update index.py 2024-05-15 17:32:11 +08:00
Mr Chen 05992b5f82 Update index.py 2024-05-15 17:31:49 +08:00
Mr Chen 1a48e880d0 update 2024-05-15 17:29:02 +08:00
Mr Chen 1da749aea9 Update index.py 2024-05-15 14:45:23 +08:00
Mr Chen bf121ee6f8 Update index.py 2024-05-15 14:41:19 +08:00
Mr Chen 6b6e1f415f Update index.py 2024-05-15 14:40:33 +08:00
Mr Chen 5535d56304 Update index.py 2024-05-15 14:30:56 +08:00
Mr Chen bbc0dee2b6 Update index.py 2024-05-15 14:28:23 +08:00
Mr Chen 1da8f6bbb6 update 2024-05-15 14:21:43 +08:00
Mr Chen de15101a76 Update orm.py 2024-05-15 14:06:17 +08:00
Mr Chen ee99d14df3 Update index.py 2024-05-15 14:03:41 +08:00
Mr Chen 7bff08b3e5 Update index.py 2024-05-15 14:02:10 +08:00
Mr Chen faca0b183e update 2024-05-15 13:59:59 +08:00
Mr Chen 700b9a7c61 Update index.py 2024-05-15 13:53:30 +08:00
Mr Chen 53952d267e Update index.py 2024-05-15 13:42:57 +08:00
Mr Chen ff52646fd2 Update index.py 2024-05-15 13:40:00 +08:00
Mr Chen 1dcd4520f1 Update index.py 2024-05-15 13:37:23 +08:00
Mr Chen 21d86f0583 Update index.py 2024-05-15 13:33:08 +08:00
Mr Chen 3e95e3aaf2 Update index.py 2024-05-15 13:28:46 +08:00
Mr Chen 29c7367906 Update index.py 2024-05-15 13:01:44 +08:00
Mr Chen fc1e23f12d Update index.py 2024-05-15 12:31:52 +08:00
Mr Chen ae4af02909 Update index.py 2024-05-15 12:27:54 +08:00
Mr Chen 6b8716ae59 Update index.py 2024-05-15 12:07:57 +08:00
Mr Chen 661faf8503 Update index.py 2024-05-15 11:57:58 +08:00
Mr Chen d0881ff3eb Update index.py 2024-05-15 06:04:24 +08:00
Mr Chen b708d4821a Update index.py 2024-05-15 05:59:39 +08:00
Mr Chen 2f18bf5fb2 Update index.py 2024-05-15 05:50:25 +08:00
Mr Chen 2079076638 Update index.py 2024-05-15 05:42:44 +08:00
Mr Chen 6ec2e4f29f Update index.py 2024-05-15 05:41:51 +08:00
Mr Chen a07ed61305 Update index.py 2024-05-15 05:38:59 +08:00
Mr Chen 8031ea2c45 Update index.py 2024-05-15 05:35:14 +08:00
Mr Chen 24d3fc18d6 Update index.py 2024-05-15 05:05:29 +08:00
Mr Chen 4b200765aa Update index.py 2024-05-15 05:02:01 +08:00
Mr Chen 994ee32fbf Update index.py 2024-05-15 05:00:03 +08:00
Mr Chen c6a742a932 Update index.py 2024-05-15 04:57:51 +08:00
Mr Chen 478e03bca1 Update index.py 2024-05-15 04:42:42 +08:00
Mr Chen f4cff7bcf7 Update index.py 2024-05-15 04:35:52 +08:00
Mr Chen ff7d2f358e Update index.py 2024-05-15 04:35:12 +08:00
Mr Chen e114b07d7d Update index.py 2024-05-15 04:30:04 +08:00
Mr Chen 272b13b29c Update index.py 2024-05-15 04:24:13 +08:00
Mr Chen 8d875fe589 Update index.py 2024-05-15 04:23:17 +08:00
Mr Chen e85e6a7299 update 2024-05-15 04:22:14 +08:00
Mr Chen e8a3f8b014 Update orm.py 2024-05-15 04:16:49 +08:00
Mr Chen 585cd8b532 update_dev 2024-05-15 04:06:15 +08:00
Mr Chen c89ee89061 Update index.py 2024-05-15 01:20:42 +08:00
Mr Chen ea7310502f Update index.py 2024-05-15 01:19:02 +08:00
Mr Chen 507b34797d Update backup.py 2024-05-15 01:18:56 +08:00
Mr Chen 7baecfc4a0 Update README.md 2024-05-14 23:57:17 +08:00
Mr Chen 8a1b64a524 Update index.py 2024-05-14 23:21:44 +08:00
Mr Chen 89052225f9 Update index.py 2024-05-14 23:20:55 +08:00
Mr Chen b4c0030baa Update index.py 2024-05-14 23:20:26 +08:00
Mr Chen 342dfe407c Create README.md 2024-05-14 22:36:37 +08:00
Mr Chen f9020d3c7f Update index.py 2024-05-14 22:24:08 +08:00
Mr Chen d9eb331f32 Update index.py 2024-05-14 22:23:24 +08:00
Mr Chen bc9b5ab511 Update install.sh 2024-05-14 21:48:55 +08:00
Mr Chen b71e3196b8 Update index.py 2024-05-14 21:38:07 +08:00
Mr Chen 69b8c609aa Update index.py 2024-05-14 21:36:07 +08:00
Mr Chen b1ff41350c Update index.py 2024-05-14 21:02:24 +08:00
Mr Chen ddc9defe51 Update index.py 2024-05-14 20:59:46 +08:00
Mr Chen 2942e47630 Update backup.py 2024-05-14 20:58:49 +08:00
Mr Chen b825ed9c76 Update index.py 2024-05-14 20:56:01 +08:00
Mr Chen 5d2dd11163 Update index.py 2024-05-14 20:54:47 +08:00
Mr Chen 253de5e70f Update index.py 2024-05-14 20:11:59 +08:00
Mr Chen a1e900f5c9 Update index.py 2024-05-14 19:25:18 +08:00
Mr Chen cf44889c74 Update index.py 2024-05-14 19:25:00 +08:00
Mr Chen abd48636ab Update index.py 2024-05-14 19:03:17 +08:00
Mr Chen cc0cdd62b8 Update index.py 2024-05-14 16:24:33 +08:00
Mr Chen 0b95db3bd5 Update index.py 2024-05-14 16:13:06 +08:00
Mr Chen d473f0769f Update mongodb.js 2024-05-14 16:11:23 +08:00
Mr Chen dd498c2cfc update 2024-05-14 14:12:21 +08:00
Mr Chen 77b4d0452a Update mongodb.sh 2024-05-13 23:18:00 +08:00
Mr Chen 924e1ddbec Update layout.html 2024-05-13 22:35:10 +08:00
Mr Chen 3213cee5f8 Update mongodb.sh 2024-05-13 20:50:45 +08:00
Mr Chen 9fbf09f2ef Create tidb_debug.yaml 2024-05-13 10:41:00 +08:00
Mr Chen fd3e074cc3 Update install.sh 2024-05-13 03:18:02 +08:00
Mr Chen 574007da2c Update stats.js 2024-05-13 02:47:13 +08:00
Mr Chen ec6c1b2024 Update nginx.conf 2024-05-12 16:09:36 +08:00
Mr Chen 0dd6f47b2a Update index.py 2024-05-12 15:59:19 +08:00
Mr Chen 968827480e Update install.sh 2024-05-12 14:42:07 +08:00
Mr Chen 4bce8bb56d Update index.py 2024-05-12 14:35:53 +08:00
Mr Chen 00fa001c91 update 2024-05-12 14:27:36 +08:00
Mr Chen 2f65839b9a Update index.py 2024-05-12 14:17:49 +08:00
Mr Chen c0aa4bcc1e Update mongodb.js 2024-05-12 14:10:52 +08:00
Mr Chen 4bb345abc4 update 2024-05-12 14:06:56 +08:00
Mr Chen 3d552379bc update 2024-05-12 12:55:14 +08:00
Mr Chen 2de399b70f Update index.py 2024-05-12 12:46:41 +08:00
Mr Chen 7952570b45 update 2024-05-12 10:58:12 +08:00
Mr Chen 00269662bf Create tidb.yaml 2024-05-12 01:25:10 +08:00
Mr Chen fb6dbde4c9 Update config_api.py 2024-05-12 01:18:49 +08:00
Mr Chen 66a9ca2a5a Update files.js 2024-05-12 01:18:32 +08:00
Mr Chen 2e9561dd86 Update files_api.py 2024-05-12 01:10:04 +08:00
Mr Chen 47ff1e4458 Update r3.7.txt 2024-05-12 00:28:20 +08:00
Mr Chen 9f49595bad Update r3.6.txt 2024-05-12 00:28:08 +08:00
Mr Chen 3e6f4f32d5 Update install.sh 2024-05-11 23:42:26 +08:00
Mr Chen ae69d58ee8 Update install.sh 2024-05-11 23:40:45 +08:00
Mr Chen 1788054cc4 Update install.sh 2024-05-11 22:14:51 +08:00
Mr Chen 20b20d3cce Update index.py 2024-05-11 22:13:53 +08:00
Mr Chen 3fc3d90b6f Update install.sh 2024-05-11 22:09:57 +08:00
Mr Chen cef6db80a2 Update install.sh 2024-05-11 22:08:06 +08:00
Mr Chen 59aab80eab Update install.sh 2024-05-11 22:03:56 +08:00
Mr Chen 53c2c71d3e Update install.sh 2024-05-11 21:56:24 +08:00
Mr Chen d9d814202a Update install.sh 2024-05-11 21:51:40 +08:00
Mr Chen 941dbecfa2 Update index.py 2024-05-11 21:48:05 +08:00
Mr Chen cb7228c681 Update index.py 2024-05-11 21:47:55 +08:00
Mr Chen 7ac1cb2944 Update index.py 2024-05-11 21:47:46 +08:00
Mr Chen 0262d29218 Update install.sh 2024-05-11 21:46:48 +08:00
Mr Chen 5a955c2a33 tidb插件init 2024-05-11 20:21:07 +08:00
Mr Chen dd25ebe1e9 Merge pull request #574 from midoks/dev
修复
2024-05-11 13:54:29 +08:00
Mr Chen e92151c9c5 Update site_api.py 2024-05-11 13:52:52 +08:00
Mr Chen 16cc3eab40 Update site_api.py 2024-05-11 13:52:39 +08:00
Mr Chen 87138fc41f Merge pull request #573 from midoks/dev
迁移加入版本判断
2024-05-11 12:38:52 +08:00
Mr Chen 0787bff959 Update index.py 2024-05-11 12:36:57 +08:00
Mr Chen 8fc6855936 Merge pull request #572 from midoks/dev
mysql 不锁表导出
2024-05-11 12:13:27 +08:00
Mr Chen 43f21b4d58 Update backup.py 2024-05-11 12:06:59 +08:00
Mr Chen 56e75bc4cf Update backup.py 2024-05-11 11:59:38 +08:00
Mr Chen 10190201c7 Update backup.py 2024-05-11 11:46:49 +08:00
Mr Chen 3db2aa0034 Merge pull request #571 from midoks/dev
Update site_api.py
2024-05-11 11:08:09 +08:00
Mr Chen 9fa93b5c84 Update site_api.py 2024-05-11 11:07:23 +08:00
Mr Chen fe3e9eec35 Merge pull request #570 from midoks/dev
调优
2024-05-10 17:40:28 +08:00
Mr Chen 86a3922d4f Update index.html 2024-05-10 17:38:48 +08:00
Mr Chen aa50658245 update 2024-05-10 17:36:06 +08:00
Mr Chen 8cd78d7dea Update index.js 2024-05-10 17:25:19 +08:00
Mr Chen f33bfa214f Merge pull request #569 from midoks/dev
Update README.md
2024-05-10 16:26:26 +08:00
Mr Chen e231c38f1d Update README.md 2024-05-10 16:25:20 +08:00
Mr Chen a6a3cf7882 Merge pull request #568 from midoks/dev
0.16.8
2024-05-10 15:34:21 +08:00
Mr Chen a1afe5e846 0.16.8
- 首页对网络/磁盘IO进行更细致的展示。
2024-05-10 15:30:49 +08:00
Mr Chen 594e8c4b2b update 2024-05-10 14:36:38 +08:00
Mr Chen cc015bad61 update 2024-05-10 14:35:51 +08:00
Mr Chen bc9461dea6 update 2024-05-10 13:32:46 +08:00
Mr Chen 0a25598c15 Update config_api.py 2024-05-10 12:14:05 +08:00
Mr Chen 7a9a8a08b6 Update index.js 2024-05-10 12:13:51 +08:00
Mr Chen 8eb728defa index加入io统计展示 2024-05-10 12:04:21 +08:00
Mr Chen 7f8ffbf178 Update site.css 2024-05-10 04:36:43 +08:00
Mr Chen cb0027e903 Update system_api.py 2024-05-10 04:23:48 +08:00
Mr Chen e0ebdd922d Update site.css 2024-05-10 02:16:49 +08:00
Mr Chen d6f43a86c9 Update system_api.py 2024-05-10 02:16:39 +08:00
Mr Chen dfe7becdb1 Update system_api.py 2024-05-09 23:43:16 +08:00
Mr Chen 57f4162cb8 Update mongodb.js 2024-05-09 01:08:14 +08:00
Mr Chen a9ce4f2e23 Update mongodb.js 2024-05-09 01:05:03 +08:00
Mr Chen b501d62d91 Update mongodb.js 2024-05-09 01:03:41 +08:00
Mr Chen 45ffba1559 Merge pull request #567 from midoks/dev
mysql手动导入大文件sql
2024-05-08 17:02:59 +08:00
Mr Chen 28d0fbe106 手动导入大文件sql 2024-05-08 17:01:58 +08:00
Mr Chen eeb8fee3b3 Merge pull request #566 from midoks/dev
日志清理-改成每隔7天
2024-05-08 12:59:59 +08:00
Mr Chen 0e1fbdcfb9 update 2024-05-08 12:58:55 +08:00
Mr Chen df2744816b Merge pull request #565 from midoks/dev
php更新和安装脚本加入pv命令
2024-05-08 12:34:20 +08:00
Mr Chen 862c09778a Update euler.sh 2024-05-08 12:32:52 +08:00
Mr Chen 8f9a1888ff update 2024-05-08 12:32:37 +08:00
Mr Chen 66351dc3a7 update 2024-05-08 12:28:50 +08:00
Mr Chen 55c4709c93 Merge pull request #564 from midoks/dev
日志清理优化
2024-05-08 01:33:02 +08:00
Mr Chen e27ae42270 Update index.py 2024-05-08 01:27:23 +08:00
Mr Chen 70805de98e Update index.py 2024-05-08 01:26:43 +08:00
Mr Chen c0e09e43a2 Update index.py 2024-05-08 01:25:58 +08:00
Mr Chen b69a32c81f Update index.py 2024-05-08 01:20:29 +08:00
Mr Chen 2431833cce Update index.py 2024-05-08 01:19:53 +08:00
Mr Chen a85d8ec429 Update index.html 2024-05-08 01:15:59 +08:00
Mr Chen ce5a6edeea Update tool_task.py 2024-05-08 01:13:34 +08:00
Mr Chen aa195dea2c Update tool_task.py 2024-05-08 00:52:51 +08:00
Mr Chen 840a3c5911 Update layout.html 2024-05-08 00:27:09 +08:00
Mr Chen ca87ab78b3 Update layout.html 2024-05-08 00:11:04 +08:00
Mr Chen d9fc411168 Update layout.html 2024-05-08 00:00:37 +08:00
Mr Chen e468ab16eb Merge pull request #563 from midoks/dev
细节优化
2024-05-07 20:26:43 +08:00
Mr Chen c545062d07 Update index.py 2024-05-07 20:24:05 +08:00
Mr Chen e620fd67e3 Merge pull request #562 from midoks/dev
mongodb删除保护
2024-05-07 20:18:53 +08:00
Mr Chen aa9a412e9a mongodb删除保护 2024-05-07 20:18:23 +08:00
76 changed files with 3304 additions and 495 deletions
+1
View File
@@ -173,6 +173,7 @@ plugins/v2ray
plugins/frp
plugins/file_search
plugins/proxysql
plugins/tidb
debug.out
+6 -3
View File
@@ -18,7 +18,7 @@
[![Wiki](https://img.shields.io/badge/MW-Wiki-red?style=for-the-badge&logo=wiki)](https://github.com/midoks/mdserver-web/wiki)
[![](https://data.jsdelivr.com/v1/package/gh/midoks/mdserver-web/badge?style=for-the-badge)](https://www.jsdelivr.com/package/gh/midoks/mdserver-web)
[![jsdelivr](https://data.jsdelivr.com/v1/package/gh/midoks/mdserver-web/badge)](https://www.jsdelivr.com/package/gh/midoks/mdserver-web)
* SSH终端工具
* 面板收藏功能
@@ -110,9 +110,12 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.16.7
### 版本更新 0.16.9
- mongodb副本设置/备份/认证。
- mysql同步优化,享受丝滑般感觉。
- 网站统计 - 实时-可调节1-10s。
- 网站统计 - 加入大小条件。
- Sphinx优化。
### JSDelivr安装地址
+1 -1
View File
@@ -28,7 +28,7 @@ from flask import request
class config_api:
__version = '0.16.7'
__version = '0.16.9'
__api_addr = 'data/api.json'
# 统一默认配置文件
+15
View File
@@ -121,6 +121,7 @@ class files_api:
def fileAccessApi(self):
filename = request.form.get('filename', '')
data = self.getAccess(filename)
data['sys_users'] = self.getSysUserList()
return mw.getJson(data)
def setFileAccessApi(self):
@@ -933,6 +934,20 @@ class files_api:
data['chown'] = 'www'
return data
def getSysUserList(self):
pwd_file = '/etc/passwd'
if os.path.exists(pwd_file):
content = mw.readFile(pwd_file)
clist = content.split('\n')
sys_users = []
for line in clist:
if line.find(":")<0:
continue
lines = line.split(":",1)
sys_users.append(lines[0])
return sys_users
return ['root','mysql','www']
# 计算文件数量
def getCount(self, path, search):
i = 0
+2 -1
View File
@@ -79,10 +79,11 @@ def getRootDir():
def getPluginDir():
return getRunDir() + '/plugins'
def getPanelDataDir():
return getRunDir() + '/data'
def getMWLogs():
return getRunDir() + '/logs'
def getPanelTmp():
return getRunDir() + '/tmp'
+17 -6
View File
@@ -1960,6 +1960,19 @@ class site_api:
proxy_site_path) if os.path.exists(proxy_site_path) else ""
data = json.loads(data_content) if data_content != "" else []
proxy_action = 'add'
if _id == "":
_id = mw.md5("{}".format(_name))
else:
proxy_action = 'edit'
if proxy_action == "add":
for item in data:
if item["name"] == _name:
return mw.returnJson(False, "名称重复!!")
if item["from"] == _from:
return mw.returnJson(False, "代理目录已存在!!")
tpl = "#PROXY-START\n\
location ^~ {from} {\n\
proxy_pass {to};\n\
@@ -2016,15 +2029,9 @@ location ^~ {from} {\n\
else:
tpl = tpl.replace("{proxy_cache}", tpl_proxy_nocache, 999)
proxy_action = 'add'
if _id == "":
_id = mw.md5("{}".format(_name))
else:
proxy_action = 'edit'
conf_proxy = "{}/{}.conf".format(self.getProxyPath(_siteName), _id)
conf_bk = "{}/{}.conf.txt".format(self.getProxyPath(_siteName), _id)
mw.writeFile(conf_proxy, tpl)
rule_test = mw.checkWebConfig()
@@ -2655,6 +2662,10 @@ location ^~ {from} {\n\
mw.writeFile(rewrite_file, '')
def add(self, webname, port, ps, path, version):
site_root_dir = mw.getWwwDir()
if site_root_dir == path.rstrip('/'):
return mw.returnJson(False, '不要以网站根目录创建站点!')
siteMenu = json.loads(webname)
self.siteName = self.toPunycode(
siteMenu['domain'].strip().split(':')[0]).strip()
+168 -25
View File
@@ -44,10 +44,11 @@ def mw_async(f):
class system_api:
setupPath = None
pids = None
cache = {}
def __init__(self):
self.setupPath = mw.getServerDir()
##### ----- start ----- ###
def networkApi(self):
data = self.getNetWork()
@@ -254,8 +255,7 @@ class system_api:
data['load_average'] = self.GetLoadAverage(get)
data['title'] = self.GetTitle()
data['network'] = self.GetNetWorkApi(get)
data['panel_status'] = not os.path.exists(
'/www/server/mdserver-web/data/close.pl')
data['panel_status'] = not os.path.exists('/www/server/mdserver-web/data/close.pl')
import firewalls
ssh_info = firewalls.firewalls().GetSshInfo(None)
data['enable_ssh_status'] = ssh_info['status']
@@ -488,7 +488,7 @@ class system_api:
shutil.rmtree(filename)
else:
os.remove(filename)
print('mail clear ok')
# print('mail clear ok')
num += 1
total += size
count += num
@@ -547,38 +547,181 @@ class system_api:
def getNetWork(self):
# 取网络流量信息
try:
# 取网络流量信息
networkIo = self.psutilNetIoCounters()
if not "otime" in session:
session['up'] = networkIo[0]
session['down'] = networkIo[1]
session['otime'] = time.time()
ntime = time.time()
networkInfo = {}
networkInfo['upTotal'] = networkIo[0]
networkInfo['downTotal'] = networkIo[1]
networkInfo['up'] = round(float(
networkIo[0] - session['up']) / (ntime - session['otime']), 2)
networkInfo['down'] = round(
float(networkIo[1] - session['down']) / (ntime - session['otime']), 2)
networkInfo['downPackets'] = networkIo[3]
networkInfo['upPackets'] = networkIo[2]
# 取网络流量信息
# networkIo = self.psutilNetIoCounters()
# if not "otime" in session:
# session['up'] = networkIo[0]
# session['down'] = networkIo[1]
# session['otime'] = time.time()
# print networkIo[1], session['down'], ntime, session['otime']
session['up'] = networkIo[0]
session['down'] = networkIo[1]
session['otime'] = time.time()
# ntime = time.time()
# print("source",ntime - session['otime'])
# networkInfo['upTotal'] = networkIo[0]
# networkInfo['downTotal'] = networkIo[1]
# networkInfo['up'] = round(float(
# networkIo[0] - session['up']) / (ntime - session['otime']), 2)
# networkInfo['down'] = round(
# float(networkIo[1] - session['down']) / (ntime - session['otime']), 2)
# networkInfo['downPackets'] = networkIo[3]
# networkInfo['upPackets'] = networkIo[2]
# # print networkIo[1], session['down'], ntime, session['otime']
# session['up'] = networkIo[0]
# session['down'] = networkIo[1]
# session['otime'] = time.time()
networkInfo['cpu'] = self.getCpuInfo()
networkInfo['load'] = self.getLoadAverage()
networkInfo['mem'] = self.getMemInfo()
networkInfo['iostat'] = self.getDiskIostat()
networkInfo['network'] = self.getNetWorkIostat()
return networkInfo
except Exception as e:
print("getNetWork error:", e)
print(mw.getTracebackInfo())
return None
def getNetWorkIostat(self):
netInfo = {}
netInfo['ALL'] = {}
netInfo['ALL']['up'] = 0
netInfo['ALL']['down'] = 0
netInfo['ALL']['upTotal'] = 0
netInfo['ALL']['downTotal'] = 0
netInfo['ALL']['upPackets'] = 0
netInfo['ALL']['downPackets'] = 0
mtime = time.time()
iokey = 'netstat'
netio = None
if iokey in self.cache:
netio = self.cache[iokey]
if not netio:
netio = {}
netio['info'] = None
netio['all_io'] = None
netio['time'] = mtime
stime = mtime - netio['time']
if not stime: stime = 1
# print("new:",stime)
netio_group = psutil.net_io_counters(pernic=True).keys()
netio_cache = netio['info']
allio_cache = netio['all_io']
if not netio_cache:
netio_cache = {}
netio_group_t = {}
for name in netio_group:
netInfo[name] = {}
io_data = psutil.net_io_counters(pernic=True).get(name)
if not name in netio_cache:
netio_cache[name] = io_data
netio_group_t[name] = io_data
netInfo[name]['up'] = round(float((io_data[0] - netio_cache[name][0]) / stime), 2)
netInfo[name]['down'] = round(float((io_data[1] - netio_cache[name][1])/ stime), 2)
netInfo[name]['upTotal'] = io_data[0]
netInfo[name]['downTotal'] = io_data[1]
netInfo[name]['upPackets'] = io_data[2]
netInfo[name]['downPackets'] = io_data[3]
all_io = psutil.net_io_counters()[:4]
if not allio_cache:
allio_cache = all_io
netInfo['ALL']['up'] = round(float((all_io[0] - allio_cache[0]) /stime), 2)
netInfo['ALL']['down'] = round(float((all_io[1] - allio_cache[1]) /stime), 2)
netInfo['ALL']['upTotal'] = all_io[0]
netInfo['ALL']['downTotal'] = all_io[1]
netInfo['ALL']['upPackets'] = all_io[2]
netInfo['ALL']['downPackets'] = all_io[3]
self.cache[iokey] = {'info':netio_group_t,'all_io':all_io,'time':mtime}
return netInfo
def getDiskIostat(self):
iokey = 'iostat'
diskInfo = {}
diskInfo['ALL'] = {}
diskInfo['ALL']['read_count'] = 0
diskInfo['ALL']['write_count'] = 0
diskInfo['ALL']['read_bytes'] = 0
diskInfo['ALL']['write_bytes'] = 0
diskInfo['ALL']['read_time'] = 0
diskInfo['ALL']['write_time'] = 0
diskInfo['ALL']['read_merged_count'] = 0
diskInfo['ALL']['write_merged_count'] = 0
try:
diskio = None
if iokey in self.cache:
diskio = self.cache[iokey]
mtime = int(time.time())
if not diskio:
diskio = {}
diskio['info'] = None
diskio['time'] = mtime
diskio_cache = diskio['info']
stime = mtime - diskio['time']
if not stime: stime = 1
diskio_group = psutil.disk_io_counters(perdisk=True)
if not diskio_cache:
diskio_cache = diskio_group
for disk_name in diskio_group.keys():
diskInfo[disk_name] = {}
# print('disk_name',disk_name)
# print(diskio_group[disk_name].write_time , diskio_cache[disk_name].write_time)
# print(diskio_group[disk_name].write_count , diskio_cache[disk_name].write_count)
diskInfo[disk_name]['read_count'] = int((diskio_group[disk_name].read_count - diskio_cache[disk_name].read_count) / stime)
diskInfo[disk_name]['write_count'] = int((diskio_group[disk_name].write_count - diskio_cache[disk_name].write_count) / stime)
diskInfo[disk_name]['read_bytes'] = int((diskio_group[disk_name].read_bytes - diskio_cache[disk_name].read_bytes) / stime)
diskInfo[disk_name]['write_bytes'] = int((diskio_group[disk_name].write_bytes - diskio_cache[disk_name].write_bytes) / stime)
diskInfo[disk_name]['read_time'] = int((diskio_group[disk_name].read_time - diskio_cache[disk_name].read_time) / stime)
diskInfo[disk_name]['write_time'] = int((diskio_group[disk_name].write_time - diskio_cache[disk_name].write_time) / stime)
if 'read_merged_count' in diskio_group[disk_name] and 'read_merged_count' in diskio_cache[disk_name]:
diskInfo[disk_name]['read_merged_count'] = int((diskio_group[disk_name].read_merged_count - diskio_cache[disk_name].read_merged_count) / stime)
if 'write_merged_count' in diskio_group[disk_name] and 'write_merged_count' in diskio_cache[disk_name]:
diskInfo[disk_name]['write_merged_count'] = int((diskio_group[disk_name].write_merged_count - diskio_cache[disk_name].write_merged_count) / stime)
diskInfo['ALL']['read_count'] += diskInfo[disk_name]['read_count']
diskInfo['ALL']['write_count'] += diskInfo[disk_name]['write_count']
diskInfo['ALL']['read_bytes'] += diskInfo[disk_name]['read_bytes']
diskInfo['ALL']['write_bytes'] += diskInfo[disk_name]['write_bytes']
if diskInfo['ALL']['read_time'] < diskInfo[disk_name]['read_time']:
diskInfo['ALL']['read_time'] = diskInfo[disk_name]['read_time']
if diskInfo['ALL']['write_time'] < diskInfo[disk_name]['write_time']:
diskInfo['ALL']['write_time'] = diskInfo[disk_name]['write_time']
if 'read_merged_count' in diskInfo[disk_name] and 'read_merged_count' in diskInfo[disk_name]:
diskInfo['ALL']['read_merged_count'] += diskInfo[disk_name]['read_merged_count']
if 'write_merged_count' in diskInfo[disk_name] and 'write_merged_count' in diskInfo[disk_name]:
diskInfo['ALL']['write_merged_count'] += diskInfo[disk_name]['write_merged_count']
self.cache[iokey] = {'info':diskio_group,'time':mtime}
except Exception as e:
# print(mw.getTracebackInfo())
pass
return diskInfo
def getNetWorkIoData(self, start, end):
# 取指定时间段的网络Io
data = mw.M('network').dbfile('system').where("addtime>=? AND addtime<=?", (start, end)).field(
+29 -5
View File
@@ -17,37 +17,50 @@ class ORM:
__DB_CUR = None
__DB_ERR = None
__DB_CNF = '/etc/my.cnf'
__DB_TIMEOUT=1
__DB_SOCKET = '/www/server/mysql/mysql.sock'
__DB_CHARSET = "utf8"
def __Conn(self):
# print(self.__DB_HOST, self.__DB_USER)
'''连接数据库'''
try:
if os.path.exists(self.__DB_SOCKET):
if self.__DB_HOST != 'localhost':
try:
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
database=self.__DB_NAME,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT,
cursorclass=pymysql.cursors.DictCursor)
except Exception as e:
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
database=self.__DB_NAME,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT,
cursorclass=pymysql.cursors.DictCursor)
elif os.path.exists(self.__DB_SOCKET):
try:
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
database=self.__DB_NAME,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT,
unix_socket=self.__DB_SOCKET, cursorclass=pymysql.cursors.DictCursor)
except Exception as e:
self.__DB_HOST = '127.0.0.1'
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
database=self.__DB_NAME,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT,
unix_socket=self.__DB_SOCKET, cursorclass=pymysql.cursors.DictCursor)
else:
try:
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
database=self.__DB_NAME,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT,
cursorclass=pymysql.cursors.DictCursor)
except Exception as e:
self.__DB_HOST = '127.0.0.1'
self.__DB_CONN = pymysql.connect(host=self.__DB_HOST, user=self.__DB_USER, passwd=self.__DB_PASS,
database=self.__DB_NAME,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=1,
port=int(self.__DB_PORT), charset=self.__DB_CHARSET, connect_timeout=self.__DB_TIMEOUT,
cursorclass=pymysql.cursors.DictCursor)
self.__DB_CUR = self.__DB_CONN.cursor()
@@ -80,6 +93,10 @@ class ORM:
def getPwd(self):
return self.__DB_PASS
def setTimeout(self, timeout = 1):
self.__DB_TIMEOUT = timeout
return True
def setDbName(self, name):
self.__DB_NAME = name
@@ -95,6 +112,13 @@ class ORM:
except Exception as ex:
return ex
def ping(self):
try:
self.__DB_CONN.ping()
except Exception as e:
print(e)
return True
def query(self, sql):
# 执行SQL语句返回数据集
if not self.__Conn():
+2 -1
View File
@@ -5,7 +5,8 @@
```
/etc/init.d/mw default | 显示登录信息
/etc/init.d/mw db | 快捷连接数据库
/etc/init.d/mw db | 快捷连接MySQL
/etc/init.d/mw redis | 快捷连接Redis
----------------------------------------
mw open | 开启面板
mw close | 关闭面板
+1 -1
View File
@@ -17,7 +17,7 @@ pluginService('clean');
function pRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>启动后,加入到计划中[2:30]执行。</li>';
readme += '<li>启动后,加入到计划任务每隔7天[0:15]执行。</li>';
readme += '<li>【*】代表要删除。</li>';
readme += '<li>添加/删除清除日志,可在`配置修改`中添加/删除。</li>';
readme += '<li>如果是目录,会寻找【.log】后缀的文件清空。</li>';
+21 -1
View File
@@ -99,7 +99,27 @@ def initConf():
"/var/log/secure",
"/var/log/lastlog",
"/var/log/cron",
"/www/server/cron"
"/www/server/rsyncd",
"/www/server/sphinx/index",
"/www/server/mongodb/logs",
"/www/server/php/53/var/log",
"/www/server/php/54/var/log",
"/www/server/php/55/var/log",
"/www/server/php/56/var/log",
"/www/server/php/70/var/log",
"/www/server/php/71/var/log",
"/www/server/php/72/var/log",
"/www/server/php/73/var/log",
"/www/server/php/74/var/log",
"/www/server/php/80/var/log",
"/www/server/php/81/var/log",
"/www/server/php/82/var/log",
"/www/server/php/83/var/log",
"/www/server/php/84/var/log",
"/www/server/openresty/nginx/logs",
"/www/server/phpmyadmin",
"/www/server/redis/data",
"/www/server/cron",
]
for i in clogcom:
if os.path.exists(i):
+30 -57
View File
@@ -37,57 +37,36 @@ def getConfigData():
return json.loads(mw.readFile(getTaskConf()))
except:
pass
return []
def getConfigTpl():
tpl = {
"name": "",
return {
"task_id": -1,
"period": "day-n",
"where1": "7",
"hour": "0",
"minute": "15",
}
return tpl
def createBgTask():
removeBgTask()
args = {
"period": "day",
"hour": "0",
"minute": "15",
}
createBgTaskByName(getPluginName(), args)
createBgTaskByName(getPluginName())
def createBgTaskByName(name, args):
cfg = getConfigTpl()
def createBgTaskByName(name):
args = getConfigData()
_name = "[勿删]日志清理[" + name + "]"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
if "task_id" in args and args["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
"id=?", (args["task_id"],)).find()
if res and res["id"] == args["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
api = crontab_api.crontab_api()
period = args['period']
_hour = ''
_minute = ''
_where1 = ''
_type_day = "day"
if period == 'day':
_type_day = 'day'
_hour = args['hour']
_minute = args['minute']
elif period == 'minute-n':
_type_day = 'minute-n'
_where1 = args['minute-n']
_minute = ''
mw_dir = mw.getRunDir()
cmd = '''
mw_dir=%s
@@ -105,11 +84,11 @@ logs_file=$plugin_path/${rname}.log
params = {
'name': _name,
'type': _type_day,
'type': args['period'],
'week': "",
'where1': _where1,
'hour': _hour,
'minute': _minute,
'where1': args['where1'],
'hour': args['hour'],
'minute': args['minute'],
'save': "",
'backup_to': "",
'stype': "toShell",
@@ -120,30 +99,24 @@ logs_file=$plugin_path/${rname}.log
task_id = api.add(params)
if task_id > 0:
cfg["task_id"] = task_id
cfg["name"] = name
_dd = getConfigData()
_dd.append(cfg)
mw.writeFile(getTaskConf(), json.dumps(_dd))
args["task_id"] = task_id
args["name"] = name
mw.writeFile(getTaskConf(), json.dumps(args))
def removeBgTask():
cfg_list = getConfigData()
for x in range(len(cfg_list)):
cfg = cfg_list[x]
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
cfg_list[x] = cfg
mw.writeFile(getTaskConf(), '[]')
return True
cfg = getConfigData()
if "task_id" in cfg and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
mw.writeFile(getTaskConf(), json.loads(cfg))
return True
return False
+10
View File
@@ -5,6 +5,16 @@
white-space: nowrap;
vertical-align: middle;
}
#select_db xm-select{
min-height: 30px;
line-height: 30px;
}
#select_db xm-select *{
font-size: 12px;
}
</style>
<div class="bt-form">
+10 -3
View File
@@ -123,9 +123,16 @@
<input name="mongodb_field_value" type="text" class="bt-input-text" placeholder="请输入查找内容">
</div>
<button type="button" class="mongodb_find btn btn-success btn-sm mr5 ml5" style="float:right;">
<span>查找</span>
</button>
<div style="float:right;">
<button type="button" class="mongodb_find btn btn-success btn-sm mr5 ml5" >
<span>查找</span>
</button>
<button type="button" class="mongodb_refresh btn btn-success btn-sm mr5 ml5">
<span>刷新</span>
</button>
</div>
</div>
<div class="pull-right" style="padding-top: 5px;">
+5 -1
View File
@@ -738,6 +738,10 @@ function mongodbInitField(f, data){
}
mongodbDataList(1);
});
$('#mongodb .mongodb_refresh').unbind('click').click(function(){
mongodbDataList(1);
});
}
var mogodb_db_list;
@@ -1252,7 +1256,7 @@ function redisBatchClear(){
xm_db_list = xmSelect.render({
el: '#select_db',
repeat: true,
repeat: false,
toolbar: {show: true},
data: idx_db,
});
+1
View File
@@ -63,6 +63,7 @@
<p onclick="mongoStatus();">负载状态</p>
<p onclick="mongoReplStatus();">复制状态</p>
<p onclick="pluginLogs('mongodb','','run_log');">日志</p>
<p onclick="mgdbReadme();">相关说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con" style="height:455px;overflow: auto;"></div>
+35 -13
View File
@@ -18,7 +18,6 @@ if mw.isAppleSystem():
# /usr/lib/systemd/system/mongod.service
# /var/lib/mongo
# python3 /www/server/mdserver-web/plugins/mongodb/index.py repl_init
# python3 /www/server/mdserver-web/plugins/mongodb/index.py run_repl_info
@@ -107,6 +106,9 @@ def getConfIp():
data = getConfigData()
return data['net']['bindIp']
def getConfLocalIp():
return '127.0.0.1'
def getConfPort():
data = getConfigData()
return data['net']['port']
@@ -186,7 +188,7 @@ def mongdbClientS():
import pymongo
port = getConfPort()
auth = getConfAuth()
ip = getConfIp()
ip = getConfLocalIp()
mg_root = pSqliteDb('config').where('id=?', (1,)).getField('mg_root')
if auth == 'disabled':
@@ -200,7 +202,7 @@ def mongdbClient():
import pymongo
port = getConfPort()
auth = getConfAuth()
ip = getConfIp()
ip = getConfLocalIp()
mg_root = pSqliteDb('config').where('id=?', (1,)).getField('mg_root')
# print(ip,port,auth,mg_root)
if auth == 'disabled':
@@ -488,15 +490,14 @@ def runDocInfo():
def runReplInfo():
client = mongdbClient()
db = client.admin
result = {}
try:
serverStatus = db.command('serverStatus')
except Exception as e:
return mw.returnJson(False, str(e))
d = getConfigData()
result = {}
if 'replSetName' in d['replication']:
if 'replication' in d and 'replSetName' in d['replication']:
result['repl_name'] = d['replication']['replSetName']
result['status'] = '无'
@@ -518,7 +519,22 @@ def runReplInfo():
hosts = mw.getDefault(repl,'hosts', '')
result['hosts'] = ','.join(hosts)
result['members'] = []
try:
members_list = []
replStatus = db.command('replSetGetStatus')
if 'members' in replStatus:
members = replStatus['members']
for m in members:
t = {}
t['name'] = m['name']
t['stateStr'] = m['stateStr']
t['uptime'] = m['uptime']
members_list.append(t)
result['members'] = members_list
except Exception as e:
pass
return mw.returnJson(True, 'OK', result)
def getDbList():
@@ -602,7 +618,7 @@ def addDb():
username = data_name
client[data_name].chat.insert_one({})
client[data_name].zchat.insert_one({})
user_roles = [{'role': 'dbOwner', 'db': data_name}, {'role': 'userAdmin', 'db': data_name}]
if auth_status:
# db.command("dropUser", username)
@@ -787,7 +803,7 @@ def toDbBase(find):
data_name = find['name']
db = client[data_name]
db.chat.insert_one({})
db.zchat.insert_one({})
user_roles = [{'role': 'dbOwner', 'db': data_name}, {'role': 'userAdmin', 'db': data_name}]
try:
db_admin.command("createUser", find['username'], pwd=find['password'], roles=user_roles)
@@ -1011,10 +1027,6 @@ def replSetNode():
add_node = args['node'].strip()
idx = int(args['idx'])
priority = -1
if 'priority' in args:
priority = args['priority'].strip()
@@ -1505,6 +1517,14 @@ def installPreInspection(version):
return '暂时仅支持{}'.format(','.join(supportOs))
return 'ok'
def uninstallPreInspection(version):
stop()
import plugins_api
plugins_api.plugins_api().removeIndex(getPluginName(), version)
return "请手动删除MongoDB[{}]<br/> rm -rf {}".format(version, getServerDir())
if __name__ == "__main__":
func = sys.argv[1]
@@ -1524,6 +1544,8 @@ if __name__ == "__main__":
print(reload())
elif func == 'install_pre_inspection':
print(installPreInspection(version))
elif func == 'uninstall_pre_inspection':
print(uninstallPreInspection(version))
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
+1
View File
@@ -6,6 +6,7 @@
"title": "MongoDB",
"shell": "install.sh",
"install_pre_inspection":true,
"uninstall_pre_inspection":true,
"versions":["4.4","5.0","6.0","7.0"],
"tip": "soft",
"checks": "server/mongodb",
+79 -60
View File
@@ -154,11 +154,17 @@ function mongoReplStatus() {
} else{
tbody += '<tr><th>状态</th><td>' + rdata.status + '</td><td>主/从</td></tr>\
<tr><th>同步文档</th><td>' + rdata.setName + '</td><td>文档名</td></tr>\
<tr><th>hosts</th><td><span class="overflow_hide" style="width:260px;" title="'+rdata.hosts+'">' + rdata.hosts + '</span></td><td>服务器所有节点</td></tr>\
<tr><th>hosts</th><td><span class="overflow_hide" style="width:300px;word-wrap: break-word;white-space:pre-wrap;" title="'+rdata.hosts+'">' + rdata.hosts + '</span></td><td>服务器所有节点</td></tr>\
<tr><th>primary</th><td>' + rdata.primary + '</td><td>主节点</td></tr>\
<tr><th>me</th><td>' + rdata.me + '</td><td>本机</td></tr>';
}
var tbody_members = '';
var member_list = rdata['members'];
for (var i = 0; i < member_list.length; i++) {
tbody_members += '<tr><th>'+member_list[i]['name']+'</th><td>' + member_list[i]['stateStr'] + '</td><td>'+member_list[i]['uptime']+'</td></tr>';
}
// console.log(rdata);
var repl_on = 'btn-danger';
var repl_on_title = '未开启';
@@ -176,9 +182,14 @@ function mongoReplStatus() {
con += '<div class="divtable">\
<table class="table table-hover table-bordered" style="width: 660px;">\
<thead><th>字段</th><th>当前值</th><th>说明</th></thead>\
<tbody>\
'+tbody+'\
<tbody>\
<tbody>'+tbody+'<tbody>\
</table>\
</div>';
con += '<div class="divtable" style="margin-top:5px;">\
<table class="table table-hover table-bordered" style="width: 660px;">\
<thead><th>IP</th><th>状态</th><th>在线</th></thead>\
<tbody>'+tbody_members+'<tbody>\
</table>\
</div>';
@@ -188,67 +199,66 @@ function mongoReplStatus() {
//设置副本名称
function mongoReplCfgReplSetName(){
mgPost('run_doc_info', '', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
// <select class='bt-input-text mr5' name='replSetName' style='width:100px'><option value=''></option></select>
layer.open({
type: 1,
area: '300px',
title: '设置副本名称',
closeBtn: 1,
shift: 5,
shadeClose: false,
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='mod_pwd'>\
<div class='line'>\
<span class='tname'>同步副本名称</span>\
<div class='info-r'>\
<input class='bt-input-text mr5' name='replSetName' style='width:100px' />\
</div>\
</div>\
</form>",
layer.open({
type: 1,
area: '300px',
title: '设置副本名称',
closeBtn: 1,
shift: 5,
shadeClose: false,
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='mod_pwd'>\
<div class='line'>\
<span class='tname'>同步副本</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='replSetName' style='width:100px'>\
<option value=''></option>\
</select>\
</div>\
</div>\
</form>",
success: function(){
// // console.log(rdata);
// var rlist = rdata['dbs'];
// var dbs = [];
// var selectHtml = '';
// for (var i = 0; i < rlist.length; i++) {
// // console.log(rlist[i]['db']);
// var dbname = rlist[i]['db'];
success: function(){
// console.log(rdata);
var rlist = rdata['dbs'];
var dbs = [];
var selectHtml = '';
for (var i = 0; i < rlist.length; i++) {
// console.log(rlist[i]['db']);
var dbname = rlist[i]['db'];
// if (['admin','local','config'].includes(dbname)){
// } else {
// dbs.push(dbname);
// }
// }
if (['admin','local','config'].includes(dbname)){
} else {
dbs.push(dbname);
}
}
// if (dbs.length == 0 ){
// selectHtml += "<option value=''>无</option>";
// }
if (dbs.length == 0 ){
selectHtml += "<option value=''>无</option>";
}
// for (index in dbs) {
// selectHtml += "<option value='"+dbs[index]+"'>"+dbs[index]+"</option>";
// }
for (index in dbs) {
selectHtml += "<option value='"+dbs[index]+"'>"+dbs[index]+"</option>";
}
$('select[name="replSetName"]').html(selectHtml);
},
yes:function(index){
var data = {};
data['name'] = $('select[name=replSetName]').val();
mgPost('repl_set_name', '',data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata['status']){
layer.close(index);
mongoReplCfgInit();
}
},{icon: rdata.status ? 1 : 2});
});
}
});
// $('select[name="replSetName"]').html(selectHtml);
},
yes:function(index){
var data = {};
data['name'] = $('input[name=replSetName]').val();
if (data['name'] == ''){
layer.msg("副本名称不能为空");
return;
}
mgPost('repl_set_name', '',data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata['status']){
layer.close(index);
mongoReplCfgInit();
}
},{icon: rdata.status ? 1 : 2});
});
}
});
}
@@ -1193,3 +1203,12 @@ function importDbExternal(file,name){
});
}
function mgdbReadme(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>认证同步说明</li>';
readme += '<li>root/用户,配置Key完全一致才能同步。</li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
}
+1 -1
View File
@@ -63,7 +63,7 @@ class backupTools:
if len(mycnf) > 100:
mw.writeFile(db_path + '/etc/my.cnf', mycnf)
cmd = db_path + "/bin/usr/bin/mysqldump --defaults-file=" + my_conf_path + " --single-transaction --quick --default-character-set=utf8 " + \
cmd = db_path + "/bin/usr/bin/mysqldump --defaults-file=" + my_conf_path + " --single-transaction -q --default-character-set=utf8 " + \
name + " | gzip > " + filename
mw.execShell(cmd)
+1 -1
View File
@@ -65,7 +65,7 @@ class backupTools:
if len(content) > 100:
mw.writeFile(my_cnf, content)
cmd = db_path + "/bin/usr/bin/mysqldump --defaults-file=" + my_cnf + " --single-transaction --quick --default-character-set=utf8 " + \
cmd = db_path + "/bin/usr/bin/mysqldump --defaults-file=" + my_cnf + " --single-transaction -q --default-character-set=utf8 " + \
name + " | gzip > " + filename
mw.execShell(cmd)
+27
View File
@@ -0,0 +1,27 @@
```
show global variables like '%gtid%';
show global variables like 'server_uuid';
```
```
# 不锁表,需要删除原来数据表
# tables = db.query('show tables from `%s`' % sync_db_import)
# table_key = "Tables_in_" + sync_db_import
# for tname in tables:
# drop_db_cmd = 'drop table if exists '+sync_db_import+'.'+tname[table_key]
# # print(drop_db_cmd)
# db.query(drop_db_cmd)
```
```
# 修改同步位置
# master_info = sync_mdb.query('show master status')
# slave_info = db.query('show slave status')
# if len(master_info)>0:
# channel_name = slave_info[0]['Channel_Name']
# change_cmd = "CHANGE MASTER TO MASTER_LOG_FILE='"+master_info[0]['File']+"', MASTER_LOG_POS="+str(master_info[0]['Position'])+" for channel '"+channel_name+"';"
# print(change_cmd)
# r = db.execute(change_cmd)
# print(r)
```
+2
View File
@@ -50,7 +50,9 @@ CREATE TABLE IF NOT EXISTS `slave_sync_user` (
`pass` TEXT,
`mode` TEXT,
`cmd` TEXT,
`db` TEXT,
`addtime` TEXT
);
ALTER TABLE `slave_sync_user` ADD COLUMN `db` TEXT DEFAULT '';
+633 -56
View File
@@ -63,12 +63,12 @@ def getArgs():
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
t = t.split(':',1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':', 1)
t = args[i].split(':',1)
tmp[t[0]] = t[1]
return tmp
@@ -745,7 +745,7 @@ def getMyDbPos():
return tmp.groups()[0].strip()
def setMyDbPos():
def setMyDbPos(version):
args = getArgs()
data = checkArgs(args, ['datadir'])
if not data[0]:
@@ -760,7 +760,7 @@ def setMyDbPos():
mw.execShell('mkdir -p ' + t_datadir)
# mw.execShell('/etc/init.d/mysqld stop')
stop()
stop(version)
mw.execShell('cp -rf ' + s_datadir + '/* ' + t_datadir + '/')
mw.execShell('chown -R mysql mysql ' + t_datadir)
mw.execShell('chmod -R 755 ' + t_datadir)
@@ -774,7 +774,7 @@ def setMyDbPos():
mycnf = mycnf.replace(s_datadir, t_datadir)
mw.writeFile(myfile, mycnf)
start()
start(version)
result = mw.execShell(
'ps aux|grep mysqld| grep -v grep|grep -v python')
@@ -784,7 +784,7 @@ def setMyDbPos():
else:
mw.execShell('pkill -9 mysqld')
mw.writeFile(myfile, mw.readFile(path + '/etc/my_backup.cnf'))
start()
start(version)
return mw.returnJson(False, '文件迁移失败!')
@@ -1070,6 +1070,81 @@ def importDbExternal():
return mw.returnJson(True, 'ok')
def importDbExternalProgress():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
cmd = 'cd '+mw.getServerDir()+'/mdserver-web && source bin/activate && '
cmd += 'python3 '+mw.getServerDir()+'/mdserver-web/plugins/mysql/index.py import_db_external_progress_bar {"file":"'+file+'","name":"'+name+'"}'
return mw.returnJson(True, 'ok',cmd)
def importDbExternalProgressBar():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
import_dir = mw.getRootDir() + '/backup/import/'
file_path = import_dir + file
if not os.path.exists(file_path):
return mw.returnJson(False, '文件突然消失?')
exts = ['sql', 'gz', 'zip']
ext = mw.getFileSuffix(file)
if ext not in exts:
return mw.returnJson(False, '导入数据库格式不对!')
tmp = file.split('/')
tmpFile = tmp[len(tmp) - 1]
tmpFile = tmpFile.replace('.sql.' + ext, '.sql')
tmpFile = tmpFile.replace('.' + ext, '.sql')
tmpFile = tmpFile.replace('tar.', '')
# print(tmpFile)
import_sql = ""
if file.find("sql.gz") > -1:
cmd = 'cd ' + import_dir + ' && gzip -dc ' + \
file + " > " + import_dir + tmpFile
info = mw.execShell(cmd)
if info[1] == "":
import_sql = import_dir + tmpFile
if file.find(".zip") > -1:
cmd = 'cd ' + import_dir + ' && unzip -o ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if file.find("tar.gz") > -1:
cmd = 'cd ' + import_dir + ' && tar -zxvf ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if file.find(".sql") > -1 and file.find(".sql.gz") == -1:
import_sql = import_dir + file
if import_sql == "":
return mw.returnJson(False, '未找SQL文件')
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_cnf = getConf()
mysql_cmd = getServerDir() + '/bin/mysql --defaults-file=' + my_cnf + \
' -uroot -p"' + pwd + '" -f ' + name
mysql_cmd_progress_bar = "pv -t -p " + import_sql + '|'+ mysql_cmd
print(mysql_cmd_progress_bar)
rdata = os.system(mysql_cmd_progress_bar)
return ""
def importDbBackup():
args = getArgs()
@@ -1107,6 +1182,53 @@ def importDbBackup():
return mw.returnJson(True, 'ok')
def importDbBackupProgress():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
cmd = 'cd '+mw.getServerDir()+'/mdserver-web && source bin/activate && '
cmd += 'python3 '+mw.getServerDir()+'/mdserver-web/plugins/mysql/index.py import_db_backup_progress_bar {"file":"'+file+'","name":"'+name+'"}'
return mw.returnJson(True, 'ok',cmd)
return mw.returnJson(True, 'ok')
def importDbBackupProgressBar():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
file_path = mw.getRootDir() + '/backup/database/' + file
file_path_sql = mw.getRootDir() + '/backup/database/' + file.replace('.gz', '')
if not os.path.exists(file_path_sql):
cmd = 'cd ' + mw.getRootDir() + '/backup/database && gzip -d ' + file
mw.execShell(cmd)
local_mode = recognizeDbMode()
if local_mode == 'gtid':
pdb = pMysqlDb()
pdb.execute('reset master')
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p"' + pwd + \
'" ' + name
mysql_cmd_progress_bar = "pv -t -p " + file_path_sql + '|'+ mysql_cmd
print(mysql_cmd_progress_bar)
rdata = os.system(mysql_cmd_progress_bar)
return ''
def deleteDbBackup():
args = getArgs()
data = checkArgs(args, ['filename', 'path'])
@@ -2227,7 +2349,7 @@ def addMasterRepSlaveUser(version=''):
if isError != None:
return isError
sql_select = "grant select,lock tables,PROCESS on *.* to " + username + "@'%';"
sql_select = "grant select,reload,REPLICATION CLIENT,PROCESS on *.* to " + username + "@'%';"
pdb.execute(sql_select)
pdb.execute('FLUSH PRIVILEGES;')
@@ -2272,29 +2394,31 @@ def getMasterRepSlaveUserCmd(version):
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
mdb8 = ['8.0','8.1','8.2','8.3','8.4']
sql = ''
if not mw.inArray(mdb8,version):
base_sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "'"
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
sql += base_sql +';'
sql += "<br/><hr/>"
# sql += base_sql + ", MASTER_AUTO_POSITION=1" + channel_name
sql += base_sql + channel_name
sql += "<br/><hr/>"
sql += base_sql + "', MASTER_LOG_FILE='" + mstatus[0]["File"] + "',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
else:
base_sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
clist[0]['password']+"'"
sql += base_sql +';'
sql += "<br/><hr/>"
# sql += base_sql + ", MASTER_AUTO_POSITION=1" + channel_name
sql += base_sql + channel_name
sql += "<br/><hr/>"
sql += base_sql + "', SOURCE_LOG_FILE='" + mstatus[0]["File"] + "',SOURCE_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2647,6 +2771,7 @@ def initSlaveStatus(version=''):
return mw.returnJson(False, 'MySQL未启动', [])
mode_file = getSyncModeFile()
# print(mode_file)
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
@@ -2720,7 +2845,7 @@ def initSlaveStatusSyncUser(version=''):
if slave_t['mode'] == '1':
mode_name = 'gtid'
# print(local_mode, mode_name)
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
@@ -2734,8 +2859,9 @@ def initSlaveStatusSyncUser(version=''):
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
# print(u['cmd'])
# print(cmd_sql)
t = pdb.query(cmd_sql)
# print(t)
isError = isSqlError(t)
if isError:
return isError
@@ -2850,18 +2976,21 @@ def setSlaveStatus(version=''):
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
def deleteSlaveFunc(sign = ''):
db = pMysqlDb()
if 'sign' in args:
sign = args['sign']
if sign != '':
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
def deleteSlave(version=''):
args = getArgs()
sign = ''
if 'sign' in args:
sign = args['sign']
deleteSlaveFunc(sign)
return mw.returnJson(True, '删除成功!')
@@ -2896,6 +3025,293 @@ def dumpMysqlData(version=''):
return 'fail'
############### --- 重要 数据补足同步 ---- ###########
def getSyncMysqlDB(dbname,sign = ''):
conn = pSqliteDb('slave_sync_user')
if sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where('ip=?', (sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
ip = data['ip']
# 远程数据
sync_db = mw.getMyORM()
# MySQLdb |
sync_db.setPort(port)
sync_db.setHost(ip)
sync_db.setUser(user)
sync_db.setPwd(apass)
sync_db.setDbName(dbname)
sync_db.setTimeout(60)
return sync_db
def syncDatabaseRepairTempFile():
tmp_log = mw.getMWLogs()+ '/mysql-check.log'
return tmp_log
def syncDatabaseRepairLog(version=''):
import subprocess
args = getArgs()
data = checkArgs(args, ['db','sign','op'])
if not data[0]:
return data[1]
sync_args_db = args['db']
sync_args_sign = args['sign']
op = args['op']
tmp_log = syncDatabaseRepairTempFile()
cmd = 'cd '+mw.getServerDir()+'/mdserver-web && source bin/activate && python3 plugins/mysql/index.py sync_database_repair {"db":"'+sync_args_db+'","sign":"'+sync_args_sign+'"}'
# print(cmd)
if op == 'get':
log = mw.getLastLine(tmp_log, 15)
return mw.returnJson(True, log)
if op == 'cmd':
return mw.returnJson(True, 'ok', cmd)
if op == 'do':
os.system(' echo "开始执行" > '+ tmp_log)
subprocess.Popen(cmd +' >> '+ tmp_log +' &')
# time.sleep(10)
# mw.execShell('rm -rf '+tmp_log)
return mw.returnJson(True, 'ok')
return mw.returnJson(False, '无效请求!')
def syncDatabaseRepair(version=''):
time_stats_s = time.time()
tmp_log = syncDatabaseRepairTempFile()
from pymysql.converters import escape_string
args = getArgs()
data = checkArgs(args, ['db','sign'])
if not data[0]:
return data[1]
sync_args_db = args['db']
sync_args_sign = args['sign']
# 本地数据
local_db = pMysqlDb()
# 远程数据
sync_db = getSyncMysqlDB(sync_args_db,sync_args_sign)
tables = local_db.query('show tables from `%s`' % sync_args_db)
table_key = "Tables_in_" + sync_args_db
inconsistent_table = []
tmp_dir = '/tmp/sync_db_repair'
mw.execShell('mkdir -p '+tmp_dir)
for tb in tables:
table_name = sync_args_db+'.'+tb[table_key]
table_check_file = tmp_dir+'/'+table_name+'.txt'
if os.path.exists(table_check_file):
# print(table_name+', 已检查OK')
continue
primary_key_sql = "SHOW INDEX FROM "+table_name+" WHERE Key_name = 'PRIMARY';";
primary_key_data = local_db.query(primary_key_sql)
# print(primary_key_sql,primary_key_data)
pkey_name = '*'
if len(primary_key_data) == 1:
pkey_name = primary_key_data[0]['Column_name']
# print(pkey_name)
if pkey_name != '*' :
# 智能校验(由于服务器同步可能会慢,比较总数总是对不上)
cmd_local_newpk_sql = 'select ' + pkey_name + ' from ' + table_name + " order by " + pkey_name + " desc limit 1"
cmd_local_newpk_data = local_db.query(cmd_local_newpk_sql)
# print(cmd_local_newpk_data)
if len(cmd_local_newpk_data) == 1:
# 比较总数
cmd_count_sql = 'select count('+pkey_name+') as num from '+table_name + ' where '+pkey_name + ' <= '+ str(cmd_local_newpk_data[0][pkey_name])
local_count_data = local_db.query(cmd_count_sql)
sync_count_data = sync_db.query(cmd_count_sql)
if local_count_data != sync_count_data:
print(cmd_count_sql)
print("all data compare: ",local_count_data, sync_count_data)
else:
print(table_name+' smart compare check ok.')
mw.writeFile(tmp_log, table_name+' smart compare check ok.\n','a+')
mw.execShell("echo 'ok' > "+table_check_file)
continue
# 比较总数
cmd_count_sql = 'select count('+pkey_name+') as num from '+table_name
local_count_data = local_db.query(cmd_count_sql)
sync_count_data = sync_db.query(cmd_count_sql)
if local_count_data != sync_count_data:
print("all data compare: ",local_count_data, sync_count_data)
inconsistent_table.append(table_name)
diff = sync_count_data[0]['num'] - local_count_data[0]['num']
print(table_name+', need sync. diff,'+str(diff))
mw.writeFile(tmp_log, table_name+', need sync. diff,'+str(diff)+'\n','a+')
else:
print(table_name+' check ok.')
mw.writeFile(tmp_log, table_name+' check ok.\n','a+')
mw.execShell("echo 'ok' > "+table_check_file)
# inconsistent_table = ['xx.xx']
# 数据对齐
for table_name in inconsistent_table:
is_break = False
while not is_break:
local_db.ping()
# 远程数据
sync_db.ping()
print("check table:"+table_name)
mw.writeFile(tmp_log, "check table:"+table_name+'\n','a+')
table_name_pos = 0
table_name_pos_file = tmp_dir+'/'+table_name+'.pos.txt'
primary_key_sql = "SHOW INDEX FROM "+table_name+" WHERE Key_name = 'PRIMARY';";
primary_key_data = local_db.query(primary_key_sql)
pkey_name = primary_key_data[0]['Column_name']
if os.path.exists(table_name_pos_file):
table_name_pos = mw.readFile(table_name_pos_file)
data_select_sql = 'select * from '+table_name + ' where '+pkey_name+' > '+str(table_name_pos)+' limit 10000'
print(data_select_sql)
local_select_data = local_db.query(data_select_sql)
time_s = time.time()
sync_select_data = sync_db.query(data_select_sql)
print(f'sync query cos:{time.time() - time_s:.4f}s')
mw.writeFile(tmp_log, f'sync query cos:{time.time() - time_s:.4f}s\n','a+')
# print(local_select_data)
# print(sync_select_data)
# print(len(local_select_data))
# print(len(sync_select_data))
print('pos:',str(table_name_pos),'local compare sync,',local_select_data == sync_select_data)
cmd_count_sql = 'select count('+pkey_name+') as num from '+table_name
local_count_data = local_db.query(cmd_count_sql)
time_s = time.time()
sync_count_data = sync_db.query(cmd_count_sql)
print(f'sync count data cos:{time.time() - time_s:.4f}s')
print(local_count_data,sync_count_data)
# 数据同步有延迟,相等即任务数据补足完成
if local_count_data[0]['num'] == sync_count_data[0]['num']:
is_break = True
break
diff = sync_count_data[0]['num'] - local_count_data[0]['num']
print("diff," + str(diff)+' line data!')
if local_select_data == sync_select_data:
data_count = len(local_select_data)
if data_count == 0:
# mw.writeFile(table_name_pos_file, '0')
print(table_name+",data is equal ok..")
is_break = True
break
# print(table_name,data_count)
pos = local_select_data[data_count-1][pkey_name]
print('pos',pos)
progress = pos/sync_count_data[0]['num']
print('progress,%.2f' % progress+'%')
mw.writeFile(table_name_pos_file, str(pos))
else:
sync_select_data_len = len(sync_select_data)
skip_idx = 0
# 主库PK -> 查询本地 | 保证一致
if sync_select_data_len > 0:
for idx in range(sync_select_data_len):
sync_idx_data = sync_select_data[idx]
local_idx_data = None
if idx in local_select_data:
local_idx_data = local_select_data[idx]
if sync_select_data[idx] == local_idx_data:
skip_idx = idx
pos = local_select_data[idx][pkey_name]
mw.writeFile(table_name_pos_file, str(pos))
# print(insert_data)
local_inquery_sql = 'select * from ' + table_name+ ' where ' +pkey_name+' = '+ str(sync_idx_data[pkey_name])
# print(local_inquery_sql)
ldata = local_db.query(local_inquery_sql)
# print('ldata:',ldata)
if len(ldata) == 0:
print("id:"+ str(sync_idx_data[pkey_name])+ " no exists, insert")
insert_sql = 'insert into ' + table_name
field_str = ''
value_str = ''
for field in sync_idx_data:
field_str += '`'+field+'`,'
value_str += '\''+escape_string(str(sync_idx_data[field]))+'\','
field_str = '(' +field_str.strip(',')+')'
value_str = '(' +value_str.strip(',')+')'
insert_sql = insert_sql+' '+field_str+' values'+value_str+';'
print(insert_sql)
r = local_db.execute(insert_sql)
print(r)
else:
# print('compare sync->local:',sync_idx_data == ldata[0] )
if ldata[0] == sync_idx_data:
continue
print("id:"+ str(sync_idx_data[pkey_name])+ " data is not equal, update")
update_sql = 'update ' + table_name
field_str = ''
value_str = ''
for field in sync_idx_data:
if field == pkey_name:
continue
field_str += '`'+field+'`=\''+escape_string(str(sync_idx_data[field]))+'\','
field_str = field_str.strip(',')
update_sql = update_sql+' set '+field_str+' where '+pkey_name+'=\''+str(sync_idx_data[pkey_name])+'\';'
print(update_sql)
r = local_db.execute(update_sql)
print(r)
# 本地PK -> 查询主库 | 保证一致
# local_select_data_len = len(local_select_data)
# if local_select_data_len > 0:
# for idx in range(local_select_data_len):
# if idx < skip_idx:
# continue
# local_idx_data = local_select_data[idx]
# print('local idx check', idx, skip_idx)
# local_inquery_sql = 'select * from ' + table_name+ ' where ' +pkey_name+' = '+ str(local_idx_data[pkey_name])
# print(local_inquery_sql)
# sdata = sync_db.query(local_inquery_sql)
# sdata_len = len(sdata)
# print('sdata:',sdata,sdata_len)
# if sdata_len == 0:
# delete_sql = 'delete from ' + table_name + ' where ' +pkey_name+' = '+ str(local_idx_data[pkey_name])
# print(delete_sql)
# r = local_db.execute(delete_sql)
# print(r)
# break
if is_break:
print("break all")
break
time.sleep(3)
print(f'data check cos:{time.time() - time_stats_s:.4f}s')
print("data supplementation completed")
mw.execShell('rm -rf '+tmp_dir)
return 'ok'
############### --- 重要 同步---- ###########
def asyncTmpfile():
@@ -2906,7 +3322,20 @@ def asyncTmpfile():
def writeDbSyncStatus(data):
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
return True
def fullSyncCmd():
time_all_s = time.time()
args = getArgs()
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
db = args['db']
sign = args['sign']
cmd = 'cd '+mw.getServerDir()+'/mdserver-web && source bin/activate && python3 plugins/mysql/index.py do_full_sync {"db":"'+db+'","sign":"'+sign+'"}'
return mw.returnJson(True,'ok',cmd)
def doFullSync(version=''):
mode_file = getSyncModeFile()
@@ -2920,7 +3349,53 @@ def doFullSync(version=''):
return doFullSyncUser(version)
def isSimpleSyncCmd(sql):
new_sql = sql.lower()
if new_sql.find('master_auto_position') > 0:
return False
return True
def getChannelNameForCmd(cmd):
cmd = cmd.lower()
cmd_arr = cmd.split('channel')
if len(cmd_arr) == 2:
cmd_channel_info = cmd_arr[1]
channel_name = cmd_channel_info.strip()
channel_name = channel_name.strip(';')
channel_name = channel_name.strip("'")
return channel_name
return ''
def doFullSyncUserImportContentForChannel(file, channel_name):
# print(file, channel_name)
content = mw.readFile(file)
content = content.replace('STOP SLAVE;', "STOP SLAVE for channel '{}';".format(channel_name))
content = content.replace('START SLAVE;', "START SLAVE for channel '{}';".format(channel_name))
find_head = "CHANGE MASTER TO "
find_re = find_head+"(.*?);"
find_r = re.search(find_re, content, re.I|re.M)
if find_r:
find_rg = find_r.groups()
if len(find_rg)>0:
find_str = find_head+find_rg[0]
if find_str.lower().find('channel')==-1:
content = content.replace(find_str+';', find_str+" for channel '{}';".format(channel_name))
mw.writeFile(file,content)
return True
def doFullSyncUser(version=''):
which_pv = mw.execShell('which pv')
is_exist_pv = False
if not os.path.exists(which_pv[0]):
is_exist_pv = True
time_all_s = time.time()
args = getArgs()
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
@@ -2941,6 +3416,9 @@ def doFullSyncUser(version=''):
db = pMysqlDb()
# 重置
# deleteSlaveFunc(sync_sign)
conn = pSqliteDb('slave_sync_user')
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
@@ -2948,10 +3426,15 @@ def doFullSyncUser(version=''):
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
# print(data)
user = data['user']
apass = data['pass']
port = data['port']
ip = data['ip']
cmd = data['cmd']
channel_name = getChannelNameForCmd(cmd)
sync_mdb = getSyncMysqlDB(sync_db,sync_sign)
bak_file = '/tmp/tmp.sql'
if os.path.exists(bak_file):
@@ -2965,41 +3448,111 @@ def doFullSyncUser(version=''):
time.sleep(1)
writeDbSyncStatus({'code': 1, 'msg': '正在停止从库...', 'progress': 15})
if version == '8.0':
mdb8 = ['8.0','8.1','8.2','8.3','8.4']
if mw.inArray(mdb8,version):
db.query("stop slave user='{}' password='{}';".format(user, apass))
else:
db.query("stop slave")
time.sleep(2)
time.sleep(1)
writeDbSyncStatus({'code': 2, 'msg': '远程导出数据...', 'progress': 20})
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" + \
port + " -u" + user + " -p'" + apass + \
"' --ssl-mode=DISABLED " + sync_db + " > " + bak_file
print(dump_sql_data)
mw.execShell(dump_sql_data)
# --master-data=2表示在dump过程中记录主库的binlog和pos点,并在dump文件中注释掉这一行
# --master-data=1表示在dump过程中记录主库的binlog和pos点,并在dump文件中不注释掉这一行,即恢复时会执行
# --dump-slave=2表示在dump过程中,在从库dump,mysqldump进程也要在从库执行,记录当时主库的binlog和pos点,并在dump文件中注释掉这一行
# --dump-slave=1表示在dump过程中,在从库dump,mysqldump进程也要在从库执行,记录当时主库的binlog和pos点,并在dump文件中不注释掉这一行
# --force --opt --single-transaction
# --skip-opt --create-options
# --master-data=1
find_run_dump = mw.execShell('ps -ef | grep mysqldump | grep -v grep')
if find_run_dump[0] != "":
print("正在远程导出数据中,别着急...")
writeDbSyncStatus({'code': 3.1, 'msg': '正在远程导出数据中,别着急...', 'progress': 19})
return False
time_s = time.time()
if not os.path.exists(bak_file):
if isSimpleSyncCmd(cmd):
dmp_option += " --master-data=1 --apply-slave-statements --include-master-host-port "
else:
dmp_option += ' '
dump_sql_data = getServerDir() + "/bin/mysqldump --single-transaction --default-character-set=utf8mb4 --compress -q " + dmp_option + " -h" + ip + " -P" + \
port + " -u" + user + " -p'" + apass + "' --ssl-mode=DISABLED " + sync_db + " > " + bak_file
print(dump_sql_data)
time_s = time.time()
r = mw.execShell(dump_sql_data)
print(r)
time_e = time.time()
export_cos = time_e - time_s
print("export cos:", export_cos)
writeDbSyncStatus({'code': 3, 'msg': '正在到本地导入数据中...', 'progress': 40})
writeDbSyncStatus({'code': 3, 'msg': '导出耗时:'+str(int(export_cos))+'秒,正在到本地导入数据中...', 'progress': 40})
find_run_import = mw.execShell('ps -ef | grep mysql| grep '+ bak_file +' | grep -v grep')
if find_run_import[0] != "":
print("正在导入数据中,别着急...")
writeDbSyncStatus({'code': 4.1, 'msg': '正在导入数据中,别着急...', 'progress': 39})
return False
time_s = time.time()
if os.path.exists(bak_file):
# 重置
db.execute('reset master')
# 加快导入 - 开始
# db.execute('set global innodb_flush_log_at_trx_commit = 2')
# db.execute('set global sync_binlog = 2000')
if channel_name != '':
doFullSyncUserImportContentForChannel(bak_file, channel_name)
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + " -uroot -p'" + pwd + \
"' " + sync_db_import + ' < ' + bak_file
print(my_import_cmd)
mw.execShell(my_import_cmd)
if version == '8.0':
if is_exist_pv:
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + " -uroot -p'" + pwd + "' " + sync_db_import
my_import_cmd = "pv -t -p " + bak_file + '|' + my_import_cmd
print(my_import_cmd)
os.system(my_import_cmd)
else:
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + " -uroot -p'" + pwd + "' " + sync_db_import + ' < ' + bak_file
print(my_import_cmd)
mw.execShell(my_import_cmd)
# 加快导入 - 结束
# db.execute('set global innodb_flush_log_at_trx_commit = 1')
# db.execute('set global sync_binlog = 1')
time_e = time.time()
import_cos = time_e - time_s
print("import cos:", import_cos)
writeDbSyncStatus({'code': 4, 'msg': '导入耗时:'+str(int(import_cos))+'秒', 'progress': 60})
time.sleep(3)
# print(cmd)
# r = db.query(cmd)
# print(r)
mdb8 = ['8.0','8.1','8.2','8.3','8.4']
if mw.inArray(mdb8,version):
db.query("start slave user='{}' password='{}';".format(user, apass))
else:
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
db.query("start all slaves")
time_all_e = time.time()
cos = time_all_e - time_all_s
writeDbSyncStatus({'code': 6, 'msg': '总耗时:'+str(int(cos))+'秒,从库重启完成...', 'progress': 100})
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
@@ -3130,10 +3683,13 @@ def doFullSyncSSH(version=''):
print(import_data[0])
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
mdb8 = ['8.0','8.1','8.2','8.3','8.4']
if mw.inArray(mdb8,version):
db.query("start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password']))
else:
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -3178,9 +3734,16 @@ def fullSync(version=''):
def installPreInspection(version):
import psutil
mem = psutil.virtual_memory()
memTotal = mem.total
memG = memTotal/1024/1024/1024
if memG > 2:
return 'ok'
swap_path = mw.getServerDir() + "/swap"
if not os.path.exists(swap_path):
return "为了稳定安装MySQL,先安装swap插件!"
return "内存小,为了稳定安装MySQL,先安装swap插件!"
return 'ok'
@@ -3243,7 +3806,7 @@ if __name__ == "__main__":
elif func == 'my_db_pos':
print(getMyDbPos())
elif func == 'set_db_pos':
print(setMyDbPos())
print(setMyDbPos(version))
elif func == 'my_port':
print(getMyPort())
elif func == 'set_my_port':
@@ -3258,8 +3821,16 @@ if __name__ == "__main__":
print(setDbBackup())
elif func == 'import_db_backup':
print(importDbBackup())
elif func == 'import_db_backup_progress':
print(importDbBackupProgress())
elif func == 'import_db_backup_progress_bar':
print(importDbBackupProgressBar())
elif func == 'import_db_external':
print(importDbExternal())
elif func == 'import_db_external_progress':
print(importDbExternalProgress())
elif func == 'import_db_external_progress_bar':
print(importDbExternalProgressBar())
elif func == 'delete_db_backup':
print(deleteDbBackup())
elif func == 'get_db_backup_list':
@@ -3364,7 +3935,13 @@ if __name__ == "__main__":
print(fullSync(version))
elif func == 'do_full_sync':
print(doFullSync(version))
elif func == 'full_sync_cmd':
print(fullSyncCmd())
elif func == 'dump_mysql_data':
print(dumpMysqlData(version))
elif func == 'sync_database_repair':
print(syncDatabaseRepair())
elif func == 'sync_database_repair_log':
print(syncDatabaseRepairLog())
else:
print('error')
+5 -2
View File
@@ -6,8 +6,11 @@ export PATH
# https://www.cnblogs.com/whiteY/p/17331882.html
# cd /www/server/mdserver-web/plugins/mysql && bash install.sh install 8.2
# cd /www/server/mdserver-web && source bin/activate && python3 /www/server/mdserver-web/plugins/mysql/index.py try_slave_sync_bugfix {}
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py try_slave_sync_bugfix {}
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py do_full_sync {"db":"xxx","sign":"","begin":1}
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py sync_database_repair {"db":"xxx","sign":""}
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py init_slave_status
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py install_pre_inspection
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
+177 -13
View File
@@ -929,6 +929,31 @@ function importBackup(file,name){
});
}
function importBackupProgress(file,name){
myPost('import_db_backup_progress',{file:file,name:name}, function(data){
var rdata = $.parseJSON(data.data);
layer.open({
title: "手动导入命令CMD【显示进度】",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
}
function importDbExternal(file,name){
myPost('import_db_external',{file:file,name:name}, function(data){
@@ -936,6 +961,31 @@ function importDbExternal(file,name){
});
}
function importDbExternalProgress(file,name){
myPost('import_db_external_progress',{file:file,name:name}, function(data){
var rdata = $.parseJSON(data.data);
layer.open({
title: "手动导入命令CMD【显示进度】",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
}
function setLocalImport(db_name){
//上传文件
@@ -991,6 +1041,7 @@ function setLocalImport(db_name){
<td><span> ' + file_list[i]['time'] + '</span></td>\
<td style="text-align: right;">\
<a class="btlink" onclick="importDbExternal(\'' + file_list[i]['name'] + '\',\'' +db_name+ '\')">导入</a> | \
<a class="btlink" onclick="importDbExternalProgress(\'' + file_list[i]['name'] + '\',\'' +db_name+ '\')">导入进度</a> | \
<a class="btlink del" index="'+i+'">删除</a>\
</td>\
</tr>';
@@ -1014,7 +1065,7 @@ function setLocalImport(db_name){
var layerIndex = layer.open({
type: 1,
title: "从文件导入数据",
area: ['600px', '380px'],
area: ['700px', '380px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
@@ -1060,7 +1111,7 @@ function setBackup(db_name){
var layerIndex = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
area: ['700px', '280px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
@@ -1114,6 +1165,7 @@ function setBackupReq(db_name, obj){
<td><span> ' + rdata.data[i]['time'] + '</span></td>\
<td style="text-align: right;">\
<a class="btlink" onclick="importBackup(\'' + rdata.data[i]['name'] + '\',\'' +db_name+ '\')">导入</a> | \
<a class="btlink" onclick="importBackupProgress(\'' + rdata.data[i]['name'] + '\',\'' +db_name+ '\')">导入进度</a> | \
<a class="btlink" onclick="downloadBackup(\'' + rdata.data[i]['file'] + '\')">下载</a> | \
<a class="btlink" onclick="delBackup(\'' + rdata.data[i]['name'] + '\',\'' +db_name+ '\')">删除</a>\
</td>\
@@ -1933,6 +1985,7 @@ function getFullSyncStatus(db){
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
<span data-status='init' class='btn btn-default btn-sm' id='full_sync_cmd'>手动命令</span>\
</div>\
</div>",
cancel: function(){
@@ -1951,10 +2004,36 @@ function getFullSyncStatus(db){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
$('#begin_full_sync').text("同步中");
} else {
layer.msg("正在同步中..",{icon:0});
}
});
$('#full_sync_cmd').click(function(){
myPostN('full_sync_cmd', {'db':db,'sign':''}, function(rdata){
var rdata = $.parseJSON(rdata.data);
layer.open({
title: "手动执行命令CMD",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
});
}
});
});
@@ -1970,12 +2049,91 @@ function getFullSyncStatus(db){
if (rdata['code']==6 ||rdata['code']<0){
layer.msg(rdata['msg']);
clearInterval(timeId);
$('#begin_full_sync').text("同步结束,再次同步?");
$("#begin_full_sync").attr('data-status','init');
}
});
}
}
function dataSyncVerify(db){
var reqTimer = null;
function requestLogs(layerIndex){
myPostN('sync_database_repair_log', {db:db, sign:'',op:'get'}, function(rdata){
var rdata = $.parseJSON(rdata.data);
if(!rdata.status) {
layer.close(layerIndex);
layer.msg(rdata.msg,{icon:2, time:2000});
clearInterval(reqTimer);
return;
};
if (rdata.msg == ''){
rdata.msg = '暂无数据!';
}
$("#data_verify_log").html(rdata.msg);
//滚动到最低
var ob = document.getElementById('data_verify_log');
ob.scrollTop = ob.scrollHeight;
});
}
layer.open({
type: 1,
title: '同步数据库['+db+']数据校验',
area: '500px',
btn:[ "开始","取消","手动"],
content:"<div class='bt-form'>\
"+'<pre id="data_verify_log" style="overflow: auto; border: 0px none; line-height:23px;padding: 5px; margin: 0px; white-space: pre-wrap; height: 395px; background-color: rgb(51,51,51);color:#f1f1f1;border-radius:0px;font-family:"></pre>'+"\
</div>",
cancel: function(){
if (reqTimer){
clearInterval(reqTimer);
}
},
yes:function(index,layer_index){
myPostN('sync_database_repair_log', {db:db, sign:'',op:'do'}, function(data){});
layer.msg("执行成功");
requestLogs(layer_index);
reqTimer = setInterval(function(){
requestLogs(layer_index);
},3000);
},
success:function(){
},
btn3: function(){
myPostN('sync_database_repair_log', {db:db, sign:'',op:'cmd'}, function(rdata){
var rdata = $.parseJSON(rdata.data);
layer.open({
title: "手动执行命令CMD",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
return false;
}
});
}
function addSlaveSSH(ip=''){
myPost('get_slave_ssh_by_ip', {ip:ip}, function(rdata){
@@ -2131,7 +2289,7 @@ function addSlaveSyncUser(ip=''){
var index = layer.open({
type: 1,
area: ['500px','470px'],
area: ['500px','510px'],
title: '同步账户',
closeBtn: 1,
shift: 5,
@@ -2142,6 +2300,15 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>端口</span><div class='info-r'><input name='port' class='bt-input-text mr5' type='number' style='width:330px;' value='"+port+"'></div></div>\
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>同步模式</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='mode'>\
<option value='0' "+( mode == '0' ? 'selected="selected"' : '')+">经典</option>\
<option value='1' "+( mode == '1' ? 'selected="selected"' : '')+">GTID</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
@@ -2152,6 +2319,7 @@ function addSlaveSyncUser(ip=''){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
val = val.replace(';','');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
@@ -2178,11 +2346,6 @@ function addSlaveSyncUser(ip=''){
$('input[name="port"]').val(a['MASTER_PORT']);
$('input[name="user"]').val(a['MASTER_USER']);
$('input[name="pass"]').val(a['MASTER_PASSWORD']);
console.log(a['MASTER_AUTO_POSITION'],typeof(a['MASTER_AUTO_POSITION']));
if (typeof(a['MASTER_AUTO_POSITION']) != 'undefined' ){
$('input[name="mode"]').val('1');
}
});
},
yes:function(index){
@@ -2191,7 +2354,7 @@ function addSlaveSyncUser(ip=''){
var user = $('input[name="user"]').val();
var pass = $('input[name="pass"]').val();
var cmd = $('textarea[name="cmd"]').val();
var mode = $('input[name="mode"]').val();
var mode = $('select[name="mode"]').val();
var data = {ip:ip,port:port,cmd:cmd,user:user,pass:pass,mode:mode};
myPost('add_slave_sync_user', data, function(ret_data){
@@ -2469,7 +2632,7 @@ function masterOrSlaveConf(version=''){
for(i in rdata.data){
var v = rdata.data[i];
if ('Channel_Name' in v){
if ('Channel_Name' in v && v['Channel_Name'] !=''){
isHasSign = true;
}
@@ -2640,7 +2803,8 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['name'] +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="setDbSlave(\''+rdata.data[i]['name']+'\')" title="加入|退出">'+(rdata.data[i]['slave']?'退出':'加入')+'</a> | ' +
'<a href="javascript:;" class="btlink" onclick="getFullSyncStatus(\''+rdata.data[i]['name']+'\')" title="同步">同步</a>' +
'<a href="javascript:;" class="btlink" onclick="getFullSyncStatus(\''+rdata.data[i]['name']+'\')" title="同步">同步</a> | ' +
'<a href="javascript:;" class="btlink" onclick="dataSyncVerify(\''+rdata.data[i]['name']+'\')" title="数据校验">数据校验</a>' +
'</td>';
list += '</tr>';
}
@@ -2772,10 +2936,10 @@ function masterOrSlaveConf(version=''){
getMasterDbList();
}
// if (rdata.slave_status){
if (rdata.slave_status){
getAsyncMasterDbList();
getAsyncDataList()
// }
}
});
}
getMasterStatus();
+1 -1
View File
@@ -51,7 +51,7 @@ http
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
+2 -2
View File
@@ -16,7 +16,7 @@ function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.1.27
version=8.1.28
PHP_VER=81
Install_php()
{
@@ -56,7 +56,7 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then
fi
#检测文件是否损坏.
md5_file_ok=479e65c3f05714d4aace1370e617d78e49e996ec7a7579a5be47535be61f0658
md5_file_ok=95d0b2e9466108fd750dab5c30a09e5c67f5ad2cb3b1ffb3625a038a755ad080
if [ -f $sourcePath/php/php-${version}.tar.xz ];then
md5_file=`sha256sum $sourcePath/php/php-${version}.tar.xz | awk '{print $1}'`
if [ "${md5_file}" != "${md5_file_ok}" ]; then
+2 -2
View File
@@ -16,7 +16,7 @@ function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.2.17
version=8.2.18
PHP_VER=82
Install_php()
{
@@ -57,7 +57,7 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then
fi
#检测文件是否损坏.
md5_file_ok=1cc4ef733ba58f6557db648012471f1916e5bac316303aa165535bedab08ee35
md5_file_ok=44b306fc021e56441f691da6c3108788bd9e450f293b3bc70fcd64b08dd41a50
if [ -f $sourcePath/php/php-${version}.tar.xz ];then
md5_file=`sha256sum $sourcePath/php/php-${version}.tar.xz | awk '{print $1}'`
if [ "${md5_file}" != "${md5_file_ok}" ]; then
+2 -2
View File
@@ -15,7 +15,7 @@ function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)"
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.3.4
version=8.3.6
PHP_VER=83
Install_php()
{
@@ -56,7 +56,7 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then
fi
#检测文件是否损坏.
md5_file_ok=39a337036a546e5c28aea76cf424ac172db5156bd8a8fd85252e389409a5ba63
md5_file_ok=53c8386b2123af97626d3438b3e4058e0c5914cb74b048a6676c57ac647f5eae
if [ -f $sourcePath/php/php-${version}.tar.xz ];then
md5_file=`sha256sum $sourcePath/php/php-${version}.tar.xz | awk '{print $1}'`
if [ "${md5_file}" != "${md5_file_ok}" ]; then
+4
View File
@@ -17,6 +17,10 @@ sysName=`uname`
actionType=$1
version=$2
if [ "$version" -ge '74' ];then
LIBV=1.19.0
fi
if [ "$version" == '71' ];then
LIBV=1.11.1
fi
+9 -4
View File
@@ -1,5 +1,5 @@
daemonize yes
pidfile {$SERVER_PATH}/redis/redis_6379.pid
pidfile {$SERVER_PATH}/redis/redis.pid
bind 127.0.0.1
port 6379
@@ -40,15 +40,20 @@ maxclients 10000
#maxmemory-samples 3
maxmemory 218mb
maxmemory-policy volatile-ttl
#maxmemory-policy allkeys-lru
############################## APPEND ONLY MODE ###############################
#appendonly no
# appendonly no
# appendfsync always
#appendfsync everysec
# appendfsync everysec
# appendfsync no
#no-appendfsync-on-rewrite no
# appendfilename "appendonly.aof"
# no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
+1 -1
View File
@@ -23,7 +23,7 @@ if [ "$REDISPASS" != "" ];then
fi
EXEC={$SERVER_PATH}/redis/bin/redis-server
CLIEXEC="{$SERVER_PATH}/redis/bin/redis-cli -p $REDISPORT$REDISPASS"
PIDFILE={$SERVER_PATH}/redis/redis_6379.pid
PIDFILE={$SERVER_PATH}/redis/redis.pid
echo $REDISPASS
echo $REDISPORT
+14 -9
View File
@@ -25,14 +25,16 @@ Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/source/redis
if [ ! -f $serverPath/source/redis-${VERSION}.tar.gz ];then
wget -O $serverPath/source/redis-${VERSION}.tar.gz http://download.redis.io/releases/redis-${VERSION}.tar.gz
FILE_TGZ=redis-${VERSION}.tar.gz
REDIS_DIR=$serverPath/source/redis
if [ ! -f $REDIS_DIR/${FILE_TGZ} ];then
wget -O $REDIS_DIR/${FILE_TGZ} http://download.redis.io/releases/${FILE_TGZ}
fi
cd $serverPath/source && tar -zxvf redis-${VERSION}.tar.gz
cd $REDIS_DIR && tar -zxvf ${FILE_TGZ}
CMD_MAKE=`which gmake`
if [ "$?" == "0" ];then
@@ -55,8 +57,8 @@ Install_App()
echo '安装失败!'
fi
if [ -d $serverPath/source/redis-${VERSION} ];then
rm -rf $serverPath/source/redis-${VERSION}
if [ -d ${REDIS_DIR}/redis-${VERSION} ];then
rm -rf ${REDIS_DIR}/redis-${VERSION}
fi
}
@@ -80,8 +82,11 @@ Uninstall_App()
$serverPath/redis/initd/redis stop
fi
rm -rf $serverPath/redis
echo "Uninstall_redis" > $install_tmp
if [ -d $serverPath/redis ];then
rm -rf $serverPath/redis
fi
echo "卸载redis成功"
}
action=$1
+1 -1
View File
@@ -1,5 +1,5 @@
daemonize yes
pidfile {$SERVER_PATH}/redis/redis_6379.pid
pidfile {$SERVER_PATH}/redis/redis.pid
loglevel notice
logfile {$SERVER_PATH}/redis/data/redis.log
+1 -1
View File
@@ -1,5 +1,5 @@
daemonize yes
pidfile {$SERVER_PATH}/redis/redis_6379.pid
pidfile {$SERVER_PATH}/redis/redis.pid
bind 127.0.0.1
port 6379
+11 -10
View File
@@ -1,17 +1,18 @@
daemonize yes
pidfile {$SERVER_PATH}/redis/redis_6379.pid
loglevel notice
logfile {$SERVER_PATH}/redis/data/redis.log
databases 16
timeout 0
tcp-keepalive 0
pidfile {$SERVER_PATH}/redis/redis.pid
bind 127.0.0.1
port 6379
requirepass {$REDIS_PASS}
timeout 0
tcp-keepalive 0
loglevel notice
logfile {$SERVER_PATH}/redis/data/redis.log
databases 16
################################ SNAPSHOTTING #################################
save 900 1
@@ -33,7 +34,7 @@ slave-priority 100
# 填写主库信息
#slaveof 127.0.0.1 6379
#masterauth master_pwd
#masterauth 123123
################################## SECURITY ###################################
@@ -41,7 +42,7 @@ slave-priority 100
################################### LIMITS ####################################
maxclients 10000
#maxmemory-samples 3
maxmemory 218mb
maxmemory 0mb
maxmemory-policy volatile-ttl
############################## APPEND ONLY MODE ###############################
+75
View File
@@ -0,0 +1,75 @@
daemonize yes
pidfile {$SERVER_PATH}/redis/redis.pid
loglevel notice
logfile {$SERVER_PATH}/redis/data/redis.log
databases 16
timeout 0
tcp-keepalive 0
bind 127.0.0.1
port 6379
requirepass {$REDIS_PASS}
################################ SNAPSHOTTING #################################
save ""
stop-writes-on-bgsave-error no
################################# REPLICATION #################################
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
# 填写主库信息
#slaveof 127.0.0.1 6379
#masterauth 123123
################################## SECURITY ###################################
################################### LIMITS ####################################
maxclients 10000
#maxmemory-samples 3
maxmemory 218mb
maxmemory-policy allkeys-lru
############################## APPEND ONLY MODE ###############################
################################ LUA SCRIPTING ###############################
lua-time-limit 5000
################################## SLOW LOG ###################################
slowlog-log-slower-than 10000
slowlog-max-len 128
############################### ADVANCED CONFIG ###############################
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing no
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
+486
View File
@@ -0,0 +1,486 @@
# coding:utf-8
import sys
import io
import os
import time
import subprocess
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
def getServerDir():
return mw.getServerDir() + '/mysql'
def getPluginDir():
return mw.getPluginDir() + '/mysql'
def getConf():
path = getServerDir() + '/etc/my.cnf'
return path
def getDbPort():
file = getConf()
content = mw.readFile(file)
rep = 'port\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
rep = 'socket\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def pSqliteDb(dbname='databases'):
file = getServerDir() + '/mysql.db'
name = 'mysql'
conn = mw.M(dbname).dbPos(getServerDir(), name)
return conn
def pMysqlDb():
# pymysql
db = mw.getMyORM()
db.setPort(getDbPort())
db.setSocket(getSocketFile())
# db.setCharset("utf8")
db.setPwd(pSqliteDb('config').where('id=?', (1,)).getField('mysql_root'))
return db
class sphinxMake():
pdb = None
psdb = None
pkey_name_cache = {}
delta = 'sph_counter'
ver = ''
def __init__(self):
self.pdb = pMysqlDb()
def setDeltaName(self, name):
self.delta = name
return True
def setVersion(self, ver):
self.ver = ver
def createSql(self, db):
conf = '''
CREATE TABLE IF NOT EXISTS `{$DB_NAME}`.`{$TABLE_NAME}` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`table` varchar(200) NOT NULL,
`max_id` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `table_uniq` (`table`),
KEY `table` (`table`)
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8mb4;
'''
conf = conf.replace("{$TABLE_NAME}", self.delta)
conf = conf.replace("{$DB_NAME}", db)
return conf
def eqVerField(self, field):
ver = self.ver.replace(".1",'')
if float(ver) >= 3.6:
if field == 'sql_attr_timestamp':
return 'attr_bigint'
if field == 'sql_attr_bigint':
return 'attr_bigint'
if field == 'sql_attr_float':
return 'attr_float'
if field == 'sql_field_string':
return 'field_string'
if float(ver) >= 3.3:
if field == 'sql_attr_timestamp':
return 'sql_attr_bigint'
return field
def pathVerName(self):
ver = self.ver.replace(".1",'')
# if float(ver) >= 3.6:
# return 'datadir'
return 'path'
def getTablePk(self, db, table):
key = db+'_'+table
if key in self.pkey_name_cache:
return self.pkey_name_cache[key]
# SHOW INDEX FROM bbs.bbs_ucenter_vars WHERE Key_name = 'PRIMARY'
pkey_sql = "SHOW INDEX FROM {}.{} WHERE Key_name = 'PRIMARY';".format(db,table,);
pkey_data = self.pdb.query(pkey_sql)
# print(db, table)
# print(pkey_data)
key = ''
if len(pkey_data) == 1:
pkey_name = pkey_data[0]['Column_name']
sql = "select COLUMN_NAME,DATA_TYPE from information_schema.COLUMNS where `TABLE_SCHEMA`='{}' and `TABLE_NAME` = '{}' and `COLUMN_NAME`='{}';"
sql = sql.format(db,table,pkey_name,)
# print(sql)
fields = self.pdb.query(sql)
if len(fields) == 1:
# print(fields[0]['DATA_TYPE'])
if mw.inArray(['bigint','smallint','tinyint','int','mediumint'], fields[0]['DATA_TYPE']):
key = pkey_name
return key
def getTableFieldStr(self, db, table):
sql = "select COLUMN_NAME,DATA_TYPE from information_schema.COLUMNS where `TABLE_SCHEMA`='{}' and `TABLE_NAME` = '{}';"
sql = sql.format(db,table,)
fields = self.pdb.query(sql)
field_str = ''
for x in range(len(fields)):
field_str += '`'+fields[x]['COLUMN_NAME']+'`,'
field_str = field_str.strip(',')
return field_str
def makeSphinxHeader(self):
conf = '''
indexer
{
mem_limit = 128M
}
searchd
{
listen = 9312
listen = 9306:mysql41
log = {$server_dir}/sphinx/index/searchd.log
query_log = {$server_dir}/sphinx/index/query.log
read_timeout = 5
max_children = 0
pid_file = {$server_dir}/sphinx/index/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
#workers = threads # for RT to work
binlog_path = {$server_dir}/sphinx/index/binlog
}
'''
conf = conf.replace("{$server_dir}", mw.getServerDir())
return conf
def makeSphinxDbSourceRangeSql(self, db, table):
pkey_name = self.getTablePk(db,table)
sql = "SELECT min("+pkey_name+"), max("+pkey_name+") FROM "+table
return sql
def makeSphinxDbSourceQuerySql(self, db, table):
pkey_name = self.getTablePk(db,table)
field_str = self.getTableFieldStr(db,table)
# print(field_str)
if pkey_name == 'id':
sql = "SELECT " + field_str + " FROM " + table + " where id >= $start AND id <= $end"
else:
sql = "SELECT `"+pkey_name+'` as `id`,' + field_str + " FROM " + table + " where "+pkey_name+" >= $start AND "+pkey_name+" <= $end"
return sql
def makeSphinxDbSourceDeltaRange(self, db, table):
pkey_name = self.getTablePk(db,table)
conf = "SELECT (SELECT max_id FROM `{$SPH_TABLE}` where `table`='{$TABLE_NAME}') as min, (SELECT max({$PK_NAME}) FROM {$TABLE_NAME}) as max"
conf = conf.replace("{$DB_NAME}", db)
conf = conf.replace("{$TABLE_NAME}", table)
conf = conf.replace("{$SPH_TABLE}", self.delta)
conf = conf.replace("{$PK_NAME}", pkey_name)
return conf
def makeSphinxDbSourcePost(self, db, table):
pkey_name = self.getTablePk(db,table)
conf = "sql_query_post = UPDATE {$SPH_TABLE} SET max_id=(SELECT MAX({$PK_NAME}) FROM {$TABLE_NAME}) where `table`='{$TABLE_NAME}'"
# conf = "REPLACE INTO {$SPH_TABLE} (`table`,`max_id`) VALUES ('{$TABLE_NAME}',(SELECT MAX({$PK_NAME}) FROM {$TABLE_NAME}))"
conf = conf.replace("{$DB_NAME}", db)
conf = conf.replace("{$TABLE_NAME}", table)
conf = conf.replace("{$SPH_TABLE}", self.delta)
conf = conf.replace("{$PK_NAME}", pkey_name)
return conf
def makeSphinxDbSourceDelta(self, db, table):
conf = '''
source {$DB_NAME}_{$TABLE_NAME}_delta:{$DB_NAME}_{$TABLE_NAME}
{
sql_query_pre = SET NAMES utf8
sql_query_range = {$DELTA_RANGE}
sql_query = {$DELTA_QUERY}
{$DELTA_UPDATE}
{$SPH_FIELD}
}
index {$DB_NAME}_{$TABLE_NAME}_delta:{$DB_NAME}_{$TABLE_NAME}
{
source = {$DB_NAME}_{$TABLE_NAME}_delta
{$PATH_NAME} = {$server_dir}/sphinx/index/db/{$DB_NAME}.{$TABLE_NAME}/delta
html_strip = 1
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
{$SPH_FIELD_INDEX}
}
''';
conf = conf.replace("{$server_dir}", mw.getServerDir())
conf = conf.replace("{$PATH_NAME}", self.pathVerName())
conf = conf.replace("{$DB_NAME}", db)
conf = conf.replace("{$TABLE_NAME}", table)
delta_range = self.makeSphinxDbSourceDeltaRange(db, table)
conf = conf.replace("{$DELTA_RANGE}", delta_range)
delta_query = self.makeSphinxDbSourceQuerySql(db, table)
conf = conf.replace("{$DELTA_QUERY}", delta_query)
delta_update = self.makeSphinxDbSourcePost(db, table)
conf = conf.replace("{$DELTA_UPDATE}", delta_update)
sph_field = self.makeSqlToSphinxTable(db, table)
conf = self.makeSphinxDbFieldRepalce(conf, sph_field)
return conf;
def makeSphinxDbSource(self, db, table, create_sphinx_table = False):
db_info = pSqliteDb('databases').field('username,password').where('name=?', (db,)).find()
port = getDbPort()
conf = '''
source {$DB_NAME}_{$TABLE_NAME}
{
type = mysql
sql_host = 127.0.0.1
sql_user = {$DB_USER}
sql_pass = {$DB_PASS}
sql_db = {$DB_NAME}
sql_port = {$DB_PORT}
sql_query_pre = SET NAMES utf8
{$UPDATE}
sql_query_range = {$DB_RANGE_SQL}
sql_range_step = 1000
sql_query = {$DB_QUERY_SQL}
{$SPH_FIELD}
}
index {$DB_NAME}_{$TABLE_NAME}
{
source = {$DB_NAME}_{$TABLE_NAME}
{$PATH_NAME} = {$server_dir}/sphinx/index/db/{$DB_NAME}.{$TABLE_NAME}/index
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
{$SPH_FIELD_INDEX}
}
'''
conf = conf.replace("{$server_dir}", mw.getServerDir())
conf = conf.replace("{$PATH_NAME}", self.pathVerName())
conf = conf.replace("{$DB_NAME}", db)
conf = conf.replace("{$TABLE_NAME}", table)
conf = conf.replace("{$DB_USER}", db_info['username'])
conf = conf.replace("{$DB_PASS}", db_info['password'])
conf = conf.replace("{$DB_PORT}", port)
range_sql = self.makeSphinxDbSourceRangeSql(db, table)
conf = conf.replace("{$DB_RANGE_SQL}", range_sql)
query_sql = self.makeSphinxDbSourceQuerySql(db, table)
conf = conf.replace("{$DB_QUERY_SQL}", query_sql)
sph_field = self.makeSqlToSphinxTable(db, table)
# conf = conf.replace("{$SPH_FIELD}", sph_field)
conf = self.makeSphinxDbFieldRepalce(conf, sph_field)
if create_sphinx_table:
update = self.makeSphinxDbSourcePost(db, table)
conf = conf.replace("{$UPDATE}", update)
else:
conf = conf.replace("{$UPDATE}", '')
if create_sphinx_table:
sph_sql = self.createSql(db)
self.pdb.query(sph_sql)
sql_find = "select * from {}.{} where `table`='{}'".format(db,self.delta,table)
find_data = self.pdb.query(sql_find)
if len(find_data) == 0:
insert_sql = "insert into `{}`.`{}`(`table`,`max_id`) values ('{}',{}) ".format(db,self.delta,table,0)
# print(insert_sql)
self.pdb.execute(insert_sql)
conf += self.makeSphinxDbSourceDelta(db,table)
# print(ver)
# print(conf)
return conf
def makeSphinxDbFieldRepalce(self, content, sph_field):
ver = self.ver.replace(".1",'')
ver = float(ver)
if ver >= 3.6:
content = content.replace("{$SPH_FIELD}", '')
content = content.replace("{$SPH_FIELD_INDEX}", '')
else:
content = content.replace("{$SPH_FIELD}", sph_field)
content = content.replace("{$SPH_FIELD_INDEX}", '')
return content
def makeSqlToSphinxDb(self, db, table = [], is_delta = False):
conf = ''
for tn in table:
pkey_name = self.getTablePk(db,tn)
if pkey_name == '':
continue
conf += self.makeSphinxDbSource(db, tn,is_delta)
if len(table) == 0:
tables = self.pdb.query("show tables in "+ db)
for x in range(len(tables)):
key = 'Tables_in_'+db
table_name = tables[x][key]
pkey_name = self.getTablePk(db, table_name, is_delta)
if pkey_name == '':
continue
if self.makeSqlToSphinxTableIsHaveFulltext(db, table_name):
conf += self.makeSphinxDbSource(db, table_name)
return conf
def makeSqlToSphinxTableIsHaveFulltext(self, db, table):
sql = "select COLUMN_NAME,DATA_TYPE from information_schema.COLUMNS where `TABLE_SCHEMA`='{}' and `TABLE_NAME` = '{}';"
sql = sql.format(db,table,)
cols = self.pdb.query(sql)
cols_len = len(cols)
for x in range(cols_len):
data_type = cols[x]['DATA_TYPE']
column_name = cols[x]['COLUMN_NAME']
if mw.inArray(['varchar'], data_type):
return True
if mw.inArray(['text','mediumtext','tinytext','longtext'], data_type):
return True
return False
def makeSqlToSphinxTable(self,db,table):
pkey_name = self.getTablePk(db,table)
sql = "select COLUMN_NAME,DATA_TYPE from information_schema.COLUMNS where `TABLE_SCHEMA`='{}' and `TABLE_NAME` = '{}';"
sql = sql.format(db,table,)
cols = self.pdb.query(sql)
cols_len = len(cols)
conf = ''
run_pos = 0
for x in range(cols_len):
data_type = cols[x]['DATA_TYPE']
column_name = cols[x]['COLUMN_NAME']
# print(column_name+":"+data_type)
# if mw.inArray(['tinyint'], data_type):
# conf += 'sql_attr_bool = '+ column_name + "\n"
if pkey_name == column_name:
# run_pos += 1
# conf += '\tsql_attr_bigint = '+column_name+"\n"
continue
if mw.inArray(['enum'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_attr_string')+' = '+ column_name + "\n"
continue
if mw.inArray(['decimal'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_attr_float')+' = '+ column_name + "\n"
continue
if mw.inArray(['bigint','smallint','tinyint','int','mediumint'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_attr_bigint')+' = '+ column_name + "\n"
continue
if mw.inArray(['float'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_attr_float')+' = '+ column_name + "\n"
continue
if mw.inArray(['char'], data_type):
conf += '\t'+self.eqVerField('sql_attr_string')+' = '+ column_name + "\n"
continue
if mw.inArray(['varchar'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_field_string')+' = '+ column_name + "\n"
continue
if mw.inArray(['text','mediumtext','tinytext','longtext'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_field_string')+' = '+ column_name + "\n"
continue
if mw.inArray(['datetime','date'], data_type):
run_pos += 1
conf += '\t'+self.eqVerField('sql_attr_timestamp')+' = '+ column_name + "\n"
continue
return conf
def checkDbName(self, db):
filter_db = ['information_schema','performance_schema','sys','mysql']
if db in filter_db:
return False
return True
def makeSqlToSphinx(self, db, tables = [], is_delta = False):
conf = ''
conf += self.makeSphinxHeader()
conf += self.makeSqlToSphinxDb(db, tables, is_delta)
return conf
def makeSqlToSphinxAll(self):
filter_db = ['information_schema','performance_schema','sys','mysql']
dblist = self.pdb.query('show databases')
conf = ''
conf += self.makeSphinxHeader()
# conf += makeSqlToSphinxDb(pdb, 'bbs')
for x in range(len(dblist)):
dbname = dblist[x]['Database']
if mw.inArray(filter_db, dbname):
continue
conf += self.makeSqlToSphinxDb(dbname)
return conf
+17 -3
View File
@@ -1,21 +1,35 @@
<style>
#table xm-select{
min-height: 30px;
line-height: 30px;
}
#table xm-select *{
font-size: 12px;
}
</style>
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('sphinx');">服务</p>
<p onclick="pluginInitD('sphinx');">自启动</p>
<p onclick="pluginConfigTpl('sphinx');">配置修改</p>
<p onclick="pluginConfigTpl('sphinx','', 'conf','config_tpl','read_config_tpl',tryRebuildIndex);">配置修改</p>
<p onclick="pluginLogs('sphinx','','run_log',30);">运行日志</p>
<p onclick="pluginLogs('sphinx','','query_log', 30);">查询日志</p>
<p onclick="runStatus();">运行状态</p>
<p onclick="rebuild();">重建索引</p>
<p onclick="commonFunc();">常用功能</p>
<p onclick="readme();">说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
<div class="soft-man-con" style="height:425px;overflow: auto;"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(500);
$.getScript( "/plugins/file?name=sphinx&f=js/sphinx.js", function(){
pluginService('sphinx');
});
+84 -16
View File
@@ -15,14 +15,13 @@ app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'sphinx'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
sys.path.append(getPluginDir() +"/class")
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -210,9 +209,10 @@ def reload():
def rebuild():
file = initDreplace()
subprocess.Popen(file + ' rebuild &',
stdout=subprocess.PIPE, shell=True)
# data = mw.execShell(file + ' rebuild')
cmd = file + ' rebuild'
data = mw.execShell(cmd)
if data[0].find('successfully')<0:
return data[0].replace("\n","<br/>")
return 'ok'
@@ -295,18 +295,35 @@ def sphinxConfParse():
sindex = re.findall(rep, content)
indexlen = len(sindex)
cmd = {}
if indexlen > 0:
cmd_index = []
cmd_delta = []
for x in range(indexlen):
if sindex[x].find(':') != -1:
cmd_delta.append(sindex[x])
else:
cmd_index.append(sindex[x])
cmd['cmd'] = bin_dir + '/bin/bin/indexer -c ' + bin_dir + '/sphinx.conf'
cmd['index'] = cmd_index
cmd['delta'] = cmd_delta
cmd['cmd'] = bin_dir + '/bin/bin/indexer -c ' + bin_dir + '/sphinx.conf'
cmd['index'] = []
cmd_index = []
cmd_delta = []
if indexlen > 0:
for x in range(indexlen):
name = sindex[x].strip()
if name == '':
continue
if name.find(':') != -1:
cmd_delta.append(name.strip())
else:
cmd_index.append(name.strip())
# print(cmd_index)
# print(cmd_delta)
for ci in cmd_index:
val = {}
val['index'] = ci
for cd in cmd_delta:
cd = cd.replace(" ", '')
if cd.find(":"+ci) > -1:
val['delta'] = cd.split(":")[0].strip()
break
cmd['index'].append(val)
return cmd
@@ -317,6 +334,55 @@ def sphinxCmd():
else:
return mw.returnJson(False, 'no index')
def makeDbToSphinxTest():
conf_file = getConf()
import sphinx_make
sph_make = sphinx_make.sphinxMake()
conf = sph_make.makeSqlToSphinxAll()
mw.writeFile(conf_file,conf)
print(conf)
# makeSqlToSphinxTable()
return True
def makeDbToSphinx():
args = getArgs()
check = checkArgs(args, ['db','tables','is_delta','is_cover'])
if not check[0]:
return check[1]
db = args['db']
tables = args['tables']
is_delta = args['is_delta']
is_cover = args['is_cover']
if is_cover != 'yes':
return mw.returnJson(False,'暂时仅支持覆盖!')
sph_file = getConf()
import sphinx_make
sph_make = sphinx_make.sphinxMake()
version_pl = getServerDir() + "/version.pl"
if os.path.exists(version_pl):
version = mw.readFile(version_pl).strip()
sph_make.setVersion(version)
if not sph_make.checkDbName(db):
return mw.returnJson(False,'保留数据库名称,不可用!')
is_delta_bool = False
if is_delta == 'yes':
is_delta_bool = True
if is_cover == 'yes':
tables = tables.split(',')
content = sph_make.makeSqlToSphinx(db, tables, is_delta_bool)
mw.writeFile(sph_file,content)
return mw.returnJson(True,'设置成功!')
return mw.returnJson(True,'测试中')
if __name__ == "__main__":
func = sys.argv[1]
@@ -352,5 +418,7 @@ if __name__ == "__main__":
print(runStatus())
elif func == 'sphinx_cmd':
print(sphinxCmd())
elif func == 'db_to_sphinx':
print(makeDbToSphinx())
else:
print('error')
+1 -2
View File
@@ -4,8 +4,7 @@
"name": "sphinx",
"title": "sphinx",
"shell": "install.sh",
"versions":["3.1.1"],
"updates":["3.1.1"],
"versions":["3.1.1","3.2.1","3.3.1","3.4.1","3.5.1","3.6.1","3.7.1"],
"tip": "soft",
"checks": "server/sphinx",
"path": "server/sphinx",
+1 -1
View File
@@ -33,7 +33,7 @@ start () {
}
rebuild () {
${APP_PATH}/bin/bin/indexer -c ${APP_CONF} --all --rotate &
${APP_PATH}/bin/bin/indexer -c ${APP_CONF} --all --rotate
}
+98 -22
View File
@@ -7,45 +7,108 @@ rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
sysArch=`arch`
install_tmp=${rootPath}/tmp/mw_install.pl
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/sphinx/index.py rebuild
# cd /www/server/mdserver-web/plugins/sphinx && bash install.sh install 3.6.1
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/sphinx/index.py db_to_sphinx && /www/server/sphinx/bin/bin/indexer -c /www/server/sphinx/sphinx.conf --all --rotate
# /Users/midoks/Desktop/mwdev/server/sphinx/bin/bin/indexer /Users/midoks/Desktop/mwdev/server/sphinx/sphinx.conf --all --rotate
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/sphinx/index.py sphinx_cmd
# /Users/midoks/Desktop/mwdev/server/sphinx/bin/bin/indexer /Users/midoks/Desktop/mwdev/server/sphinx/sphinx.conf --all --rotate
# cd /www/server/mdserver-web && source bin/activate && python3 plugins/sphinx/index.py start
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
OSNAME_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
# echo "bash ${rootPath}/scripts/getos.sh"
OSNAME="macos"
if [ -f ${rootPath}/data/osname.pl ];then
OSNAME=`cat ${rootPath}/data/osname.pl`
fi
if [ ${OSNAME} == "centos" ] ||
[ ${OSNAME} == "fedora" ] ||
[ ${OSNAME} == "alma" ]; then
if [ "${OSNAME}" == "centos" ] ||
[ "${OSNAME}" == "fedora" ] ||
[ "${OSNAME}" == "alma" ]; then
yum install -y postgresql-libs unixODBC
fi
# http://sphinxsearch.com/files/sphinx-3.7.1-da9f8a4-linux-amd64.tar.gz
VERSION=$2
# echo $VERSION
if [ "$VERSION" == "3.1.1" ];then
VERSION_NUM=${VERSION}-612d99f
elif [ "$VERSION" == "3.2.1" ]; then
VERSION_NUM=${VERSION}-f152e0b
elif [ "$VERSION" == "3.3.1" ]; then
VERSION_NUM=${VERSION}-b72d67b
elif [ "$VERSION" == "3.4.1" ]; then
VERSION_NUM=${VERSION}-efbcc65
elif [ "$VERSION" == "3.5.1" ]; then
VERSION_NUM=${VERSION}-82c60cb
elif [ "$VERSION" == "3.6.1" ]; then
VERSION_NUM=${VERSION}-c9dbeda
elif [ "$VERSION" == "3.7.1" ]; then
VERSION_NUM=${VERSION}-da9f8a4
fi
# echo $VERSION_NUM
VERSION=3.1.1
Install_sphinx()
{
echo '正在安装Sphinx...'
mkdir -p $serverPath/sphinx
SPHINX_DIR=${serverPath}/source/sphinx
mkdir -p $SPHINX_DIR
if [ ! -f ${SPHINX_DIR}/sphinx-${VERSION}.tar.gz ];then
if [ $sysName == 'Darwin' ]; then
wget -O ${SPHINX_DIR}/sphinx-${VERSION}.tar.gz http://sphinxsearch.com/files/sphinx-${VERSION}-612d99f-darwin-amd64.tar.gz
else
curl -sSLo ${SPHINX_DIR}/sphinx-${VERSION}.tar.gz http://sphinxsearch.com/files/sphinx-${VERSION}-612d99f-linux-amd64.tar.gz
SPH_NAME=amd64
if [ "$sysArch" == "arm64" ];then
SPH_NAME=amd64
elif [ "$sysArch" == "x86_64" ]; then
SPH_NAME=amd64
elif [ "$sysArch" == "aarch64" ]; then
SPH_NAME=aarch64
fi
if [ "$sysName" == "Darwin" ] && [ "$VERSION" == "3.7.1" ];then
SPH_NAME=aarch64
fi
SPH_SYSNAME=linux
if [ $sysName == 'Darwin' ]; then
SPH_SYSNAME=darwin
elif [ "$sysName" == "aarch64" ]; then
SPH_NAME=aarch64
elif [ "$sysName" == "freebsd" ]; then
SPH_NAME=freebsd
fi
if [ "$SPH_SYSNAME" == "linux" ];then
glibc_ver=`ldd --version | grep libc | awk -F ')' '{print $2}'|awk '{gsub(/^\s+|\s+$/, "");print}'`
if [ "$VERSION" == "3.7.1" ] && [ `echo "2.29 > $glibc_ver " | bc` -eq 1 ];then
SPH_NAME=${SPH_NAME}-glibc2.17
fi
if [ "$VERSION" == "3.6.1" ] && [ `echo "2.29 > $glibc_ver " | bc` -eq 1 ];then
SPH_NAME=${SPH_NAME}-glibc2.17
fi
fi
if [ ! -f ${SPHINX_DIR}/sphinx-${VERSION}.tar.gz ];then
curl -sSLo ${SPHINX_DIR}/sphinx-${VERSION}.tar.gz https://github.com/midoks/mdserver-web/releases/download/init/sphinx-${VERSION}.tar.gz
FILE_NAME=sphinx-${VERSION_NUM}-${SPH_SYSNAME}-${SPH_NAME}
FILE_TGZ=${FILE_NAME}.tar.gz
echo $FILE_TGZ
# curl -sSLo ${SPHINX_DIR}/${FILE_TGZ} http://sphinxsearch.com/files/${FILE_TGZ}
if [ ! -f ${SPHINX_DIR}/${FILE_TGZ} ];then
wget --no-check-certificate -O ${SPHINX_DIR}/${FILE_TGZ} http://sphinxsearch.com/files/${FILE_TGZ}
fi
cd ${SPHINX_DIR} && tar -zxvf sphinx-${VERSION}.tar.gz
cd ${SPHINX_DIR} && tar -zxvf ${FILE_TGZ}
if [ "$?" == "0" ];then
mkdir -p $SPHINX_DIR
@@ -56,7 +119,10 @@ Install_sphinx()
echo "${VERSION}" > $serverPath/sphinx/version.pl
echo '安装Sphinx完成'
cd ${rootPath} && python3 ${rootPath}/plugins/sphinx/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/sphinx/index.py initd_install
if [ $sysName != 'Darwin' ]; then
cd ${rootPath} && python3 ${rootPath}/plugins/sphinx/index.py initd_install
fi
fi
if [ -d ${SPHINX_DIR}/sphinx-${VERSION} ];then
@@ -69,8 +135,14 @@ Uninstall_sphinx()
if [ -f /usr/lib/systemd/system/sphinx.service ] || [ -f /lib/systemd/system/sphinx.service ];then
systemctl stop sphinx
systemctl disable sphinx
rm -rf /usr/lib/systemd/system/sphinx.service
rm -rf /lib/systemd/system/sphinx.service
if [ -f /usr/lib/systemd/system/sphinx.service ];then
rm -rf /usr/lib/systemd/system/sphinx.service
fi
if [ -f /lib/systemd/system/sphinx.service ];then
rm -rf /lib/systemd/system/sphinx.service
fi
systemctl daemon-reload
fi
@@ -78,8 +150,12 @@ Uninstall_sphinx()
$serverPath/sphinx/initd/sphinx stop
fi
rm -rf $serverPath/sphinx
echo "Uninstall_sphinx" > $install_tmp
if [ -d $serverPath/sphinx ];then
echo "rm -rf $serverPath/sphinx"
rm -rf $serverPath/sphinx
fi
echo "卸载sphinx成功"
}
action=$1
+201 -27
View File
@@ -20,6 +20,32 @@ function spPostMin(method, args, callback){
},'json');
}
function myPost(method, args, callback, title){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
var _title = '正在获取...';
if (typeof(title) != 'undefined'){
_title = title;
}
$.post('/plugins/run', {name:'mysql', 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 spPost(method, args, callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
spPostMin(method,args,function(data){
@@ -30,21 +56,167 @@ function spPost(method, args, callback){
});
}
function rebuild(){
var con = '<button class="btn btn-default btn-sm" onclick="rebuildIndex();">重建索引</button>';
function commonFunc(){
var con = '<button class="btn btn-default btn-sm" onclick="confirmRebuildIndex();">重建索引</button>';
con += '&nbsp;&nbsp; <button class="btn btn-default btn-sm" onclick="autoMakeConf();">自动创建配置</button>';
$(".soft-man-con").html(con);
}
function autoMakeConf(){
var xm_db_list;
var con = '<ul class="help-info-text c7">';
con += '<li style="color:red;">如果数据量比较大,第一次启动会失败!(可通过手动建立索引)</li>';
con += '<li style="color:red;">以下内容,需手动加入计划任务。</li>';
layer.open({
type: 1,
area: ['380px','350px'],
title: '自动创建配置',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:["提交","关闭"],
content: "<form class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>选择数据库</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='dbname' style='width:100%'>\
<option value=''>无</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>选择表</span>\
<div class='info-r'>\
<div id='table'></div>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>是否增量</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='is_delta' style='width:100px'>\
<option value='no'>否</option>\
<option value='yes'>是</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>是否覆盖配置</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='is_cover' style='width:100px'>\
<option value='yes'>是</option>\
<option value='no'>否</option>\
</select>\
</div>\
</div>\
<ul class='help-info-text c7'>\
<li style='color:red;'>具体配置,仍须手动修改!!!</li>'\
</ul>\
</form>\
",
success:function(l,i){
$(l).find('.layui-layer-content').css('overflow','visible');
xm_db_list = xmSelect.render({
el: '#table',
repeat: false,
toolbar: {show: true},
data: [],
});
myPost('get_db_list', {"page":1,"page_size":20}, function(data){
var rdata = $.parseJSON(data.data);
var dblist = rdata.data;
var db_html = '';
for (var i = 0; i < dblist.length; i++) {
db_html += "<option value='"+dblist[i]['name']+"'>"+dblist[i]['name']+"</option>";
}
if (dblist.length > 0){
initDbSelect(dblist[0]['name']);
}
$('select[name="dbname"]').html(db_html);
});
$('select[name="dbname"]').change(function(){
var db = $('select[name="dbname"]').val();
initDbSelect(db);
});
},
yes:function(index){
var args = {}
args['db'] = $('select[name="dbname"]').val();
args['is_delta'] = $('select[name="is_delta"]').val();
args['is_cover'] = $('select[name="is_cover"]').val();
args['tables'] = xm_db_list.getValue('value').join(',');
// console.log(args);
spPost('db_to_sphinx', args, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
confirmRebuildIndex();
}
},{icon: rdata.status ? 1 : 2}, 2000);
});
}
});
function initDbSelect(db){
if (db == ''){
return;
}
getDbInfo(db, function(rdata){
var rdata = $.parseJSON(rdata.data);
var tables = rdata.tables;
var idx_db = [];
for (var i = 0; i < tables.length; i++) {
var t = {};
t['name'] = tables[i]['table_name'];
t['value'] = tables[i]['table_name'];
idx_db.push(t);
}
xm_db_list = xmSelect.render({el: '#table', filterable: true,repeat: false,toolbar: {show: true},data: idx_db,});
});
}
function getDbInfo(db_name, callback){
myPost('get_db_info', {name:db_name}, function(data){
callback(data);
});
}
}
function rebuildIndex(){
spPost('rebuild', '', function(data){
if (data.data == 'ok'){
layer.msg('在重建中..',{icon:1,time:2000,shade: [0.3, '#000']});
layer.msg('重建成功!',{icon:1,time:2000,shade: [0.3, '#000']});
} else {
layer.msg(data.data,{icon:2,time:2000,shade: [0.3, '#000']});
layer.msg(data.data,{icon:2,time:10000,shade: [0.3, '#000']});
}
});
}
function confirmRebuildIndex(){
layer.confirm("是否重建索引?", {icon:3,closeBtn: 1} , function(){
rebuildIndex();
});
}
function tryRebuildIndex(){
layer.confirm("修改配置后,是否尝试重建索引!", {icon:3,closeBtn: 1} , function(){
rebuildIndex();
});
}
function secToTime(s) {
var t;
if(s > -1){
@@ -74,7 +246,12 @@ function runStatus(){
return;
}
var idata = rdata.data;
// console.log(idata);
var tbody = '';
for (var i in idata) {
tbody += '<tr><th>'+i+'</th><td>' + idata[i] + '</td><td colspan="2">'+i+'</td></tr>';
}
var con = '<div class="divtable"><table class="table table-hover table-bordered" style="margin-bottom:10px;background-color:#fafafa">\
<tbody>\
<tr><th>运行时间</th><td>' + secToTime(idata.uptime) + '</td><th>每秒查询</th><td>' + parseInt(parseInt(idata.queries) / parseInt(idata.uptime)) + '</td></tr>\
@@ -84,18 +261,12 @@ function runStatus(){
</tbody>\
</table>\
<table class="table table-hover table-bordered">\
<thead style="display:none;"><th></th><th></th><th></th><th></th></thead>\
<tbody>\
<tr><th>command_delete</th><td>' + idata.command_delete + '</td><td colspan="2">command_delete</td></tr>\
<tr><th>command_excerpt</th><td>' + idata.command_excerpt + '</td><td colspan="2">command_excerpt</td></tr>\
<tr><th>command_flushattrs</th><td>' + idata.command_flushattrs + '</td><td colspan="2">command_flushattrs</td></tr>\
<tr><th>command_keywords</th><td>' + idata.command_keywords + '</td><td colspan="2">command_keywords</td></tr>\
<tr><th>command_persist</th><td>' + idata.command_persist + '</td><td colspan="2">command_persist</td></tr>\
<tr><th>command_search</th><td>' + idata.command_search + '</td><td colspan="2">command_search</td></tr>\
<tr><th>command_status</th><td>' + idata.command_status + '</td><td colspan="2">command_status</td></tr>\
<tr><th>command_update</th><td>' + idata.command_update + '</td><td colspan="2">command_update</td></tr>\
<tbody>\
</table></div>';
<thead style="display:none;"><th></th><th></th><th></th><th></th></thead>\
<tbody>\
'+tbody+'\
<tbody>\
</table>\
</div>';
$(".soft-man-con").html(con);
});
@@ -110,21 +281,24 @@ function readme(){
return;
}
// console.log(rdata['data']);
var con = '<ul class="help-info-text c7">';
con += '<li style="color:red;">如果数据量比较大,第一次启动会失败!(可通过手动建立索引)</li>';
con += '<li style="color:red;">以下内容,需手动加入计划任务。</li>';
con += '<li>全量:' + rdata['data']['cmd'] + ' --all --rotate</li>';
//主索引
for (var i = 0; i < rdata['data']['index'].length; i++) {
var index_t = rdata['data']['index'][i];
con += '<li>主索引:' + rdata['data']['cmd'] + ' '+ index_t +' --rotate</li>';
}
for (var i = 0; i < rdata['data']['delta'].length; i++) {
var delta_t = rdata['data']['delta'][i];
var list = delta_t.split(':');
// console.log(list);
con += '<li>增量索引:' + rdata['data']['cmd'] + ' '+ list[0] +' --rotate</li>';
con += '<li>合并索引:' + rdata['data']['cmd'] + ' --merge '+ list[1] + ' ' + list[0] +' --rotate</li>';
var index_kv = rdata['data']['index'][i];
var index = index_kv['index'];
var delta = index_kv['delta'];
// console.log(index,delta);
con += '<li>主索引 :' + rdata['data']['cmd'] + ' '+ index +' --rotate</li>';
con += '<li>增量索引 :' + rdata['data']['cmd'] + ' '+ delta +' --rotate</li>';
con += '<li>合并索引 :' + rdata['data']['cmd'] + ' --merge '+ index + ' ' + delta +' --rotate</li>';
}
con += '</ul>';
+2 -2
View File
@@ -42,10 +42,10 @@ def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|end
# https://t.me/gjgzs2022 | 22/m | @GJ_gzs
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,5/15 | @baleite
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,7/15 | @baleite
# 综合包网/NG接口开户 | 28/m | 6m | next,10/28 | @aabbcx888
# 实名认证/过人脸🕵️‍♀️各种账号处理✅ | 30/m| next,6/30 | @nngzs
## 海外服务器 高防CDN 解决移动屏蔽 | 19/m | next,4/19 | @YYCDNFW
# 海外服务器 高防CDN 解决移动屏蔽 | 群内置顶AD| 16/m | @YYCDNFW
keyboard = [
[
types.InlineKeyboardButton(
@@ -51,11 +51,9 @@ def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|end
# https://t.me/gjgzs2022 | 22/m | @GJ_gzs
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,5/15 | @baleite
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,7/15 | @baleite
# 综合包网/NG接口开户 | 28/m | 6m | next,10/28 | @aabbcx888
# 实名认证/过人脸🕵️‍♀️各种账号处理✅ | 30/m| next,6/30 | @nngzs
## 海外服务器 高防CDN 解决移动屏蔽 | 19/m | next,4/19 | @YYCDNFW
# 群内置顶AD| 16/m | @YYCDNFW
keyboard = [
[
types.InlineKeyboardButton(
+2 -2
View File
@@ -86,13 +86,13 @@
.indicators-label {
display: inline-block;
width: 95px;
width: 88px;
height: 26px;
line-height: 26px;
cursor: pointer;
}
.indicators-label input {
.indicators-label input[type=radio] {
height: 13px;
margin: 0 5px 0 0;
vertical-align: -2px;
+13 -2
View File
@@ -654,17 +654,19 @@ def getLogsRealtimeInfo():
'''
import datetime
args = getArgs()
check = checkArgs(args, ['site', 'type'])
check = checkArgs(args, ['site', 'type','second'])
if not check[0]:
return check[1]
domain = args['site']
dtype = args['type']
second = int(args['second'])
conn = pSqliteDb('web_logs', domain)
timeInt = time.mktime(datetime.datetime.now().timetuple())
conn = conn.where("time>=?", (int(timeInt) - 10,))
conn = conn.where("time>=?", (int(timeInt) - second,))
field = 'time,body_length'
field_sum = toSumField(field.replace("time,", ""))
@@ -714,6 +716,7 @@ def getLogsList():
method = args['method']
status_code = args['status_code']
request_time = args['request_time']
request_size = args['request_size']
spider_type = args['spider_type']
query_date = args['query_date']
search_uri = args['search_uri']
@@ -752,6 +755,14 @@ def getLogsList():
if len(request_time_s) == 1:
conn = conn.andWhere("request_time>=?", (request_time,))
if request_size != "all":
request_size_s = request_size.strip().split('-')
# print(int(request_size_s[0])*1024)
if len(request_size_s) == 2:
conn = conn.andWhere("body_length>=? and body_length<?", (int(request_size_s[0])*1024,int(request_size_s[1])*1024,))
if len(request_size_s) == 1:
conn = conn.andWhere("body_length>=?", (int(request_size_s[0])*1024,))
if spider_type == "normal":
pass
elif spider_type == "only_spider":
+82 -24
View File
@@ -192,7 +192,7 @@ function wsOverviewRequest(page){
var data = rdata.data.data;
var statData = rdata.data.stat_list;
console.log(statData, data);
// console.log(statData, data);
var stat_pv = statData['pv'] == null?0:statData['pv'];
var stat_uv = statData['uv'] == null?0:statData['uv'];
@@ -383,11 +383,13 @@ function wsOverviewRequest(page){
var select_option = $('.indicators-container input:checked').parent().attr('data-name');
if (select_option != "realtime_traffic" && select_option != 'realtime_request' ){
clearInterval(ovTimer);
console.log("get_logs_realtime_info over:"+select_option);
// console.log("get_logs_realtime_info over:"+select_option);
return;
}
wsOriginPost("get_logs_realtime_info",'',{"site":args["site"], "type":select_option} , function(rdata){
var second = $('#check_realtime_second').val();
wsOriginPost("get_logs_realtime_info",'',{"site":args["site"], "type":select_option,'second':second} , function(rdata){
var rdata = $.parseJSON(rdata.data);
@@ -488,11 +490,11 @@ var html = '<div>\
<p class="ov_num">0</p>\
</div>\
<div class="overview_box">\
<p class="ov_title">实时流量<i class="tips" data-toggle="tooltip" data-placement="top" title="当前10秒内您网站的实时流量大小。包括已排除的请求。">?</i></p>\
<p class="ov_title">实时流量<i class="tips" data-toggle="tooltip" data-placement="top" title="当前X秒内您网站的实时流量大小。包括已排除的请求。">?</i></p>\
<p class="ov_num">0</p>\
</div>\
<div class="overview_box">\
<p class="ov_title">每秒请求<i class="tips" data-toggle="tooltip" data-placement="top" title="当前10秒内您网站的实时请求数量。包括已排除的请求。">?</i></p>\
<p class="ov_title"><span id="ov_title_req_second">每秒请求<span><i class="tips" data-toggle="tooltip" data-placement="top" title="当前1-10秒内您网站的实时请求数量。包括已排除的请求。">?</i></p>\
<p class="ov_num">0</p>\
</div>\
</div>\
@@ -525,7 +527,11 @@ var html = '<div>\
</div>\
<div class="indicators-label" bt-event-click="indicatorsType" data-name="realtime_request">\
<input type="radio" id="check_realtime_request" name="check_realtime_request">\
<span class="check_realtime_request" style="font-weight:normal">每秒请求</span>\
<span class="check_realtime_request" style="font-weight:normal">每X秒请求</span>\
</div>\
<div class="indicators-label" bt-event-click="indicatorsType">\
<input class="bt-input-text mr5" type="number" id="check_realtime_second" name="check_realtime_second" value="1" style="width:40px;outline:none;height:23px;border-radius:3px;">\
<span style="font-weight:normal">秒</span>\
</div>\
</div>\
</div>\
@@ -592,8 +598,34 @@ $('#search_time button').click(function(){
});
$('.indicators-container input').click(function(){
$('.indicators-container input').each(function(){
function initRealtimeTraffic(){
var check_realtime_second = $('#check_realtime_second').val();
if (check_realtime_second<1){
check_realtime_second = 1;
$('#check_realtime_second').val(check_realtime_second);
}
if (check_realtime_second>10){
check_realtime_second = 10;
$('#check_realtime_second').val(check_realtime_second);
}
var title = "每秒请求";
if (check_realtime_second > 1){
title = '每'+check_realtime_second+'秒请求'
}
$('#ov_title_req_second').text(title)
$('.check_realtime_request').text(title);
}
initRealtimeTraffic();
$('#check_realtime_second').change(function(){
initRealtimeTraffic();
});
$('.indicators-container input[type=radio]').click(function(){
$('.indicators-container input[type=radio]').each(function(){
$(this).removeAttr('checked');
});
$(this).prop({'checked':true});
@@ -2081,6 +2113,7 @@ var html = '<div>\
<option value="503">503</option>\
<option value="403">403</option>\
<option value="404">404</option>\
<option value="499">499</option>\
</select>\
<span style="margin-left:10px">时间: </span>\
<div class="input-group" style="margin-left:10px;width:350px;display: inline-table;vertical-align: top;">\
@@ -2179,6 +2212,7 @@ function wsTableLogRequest(page){
args['method'] = $('select[name="method"]').val();
args['status_code'] = $('select[name="status_code"]').val();
args['request_time'] = $('select[name="request_time"]').val();
args['request_size'] = $('select[name="request_size"]').val();
args['spider_type'] = $('select[name="spider_type"]').val();
args['referer'] = $('select[name="referer"]').val();
args['ip'] = $('input[name="ip"]').val();
@@ -2213,8 +2247,18 @@ function wsTableLogRequest(page){
"12":"其他",
}
var req_status = $('#logs_search').attr('req');
// console.log(req_status);
if (typeof(req_status) != 'undefined'){
if (req_status == 'start'){
layer.msg("正在请求中,请稍候!");
return;
}
}
$('#logs_search').attr('req','start');
wsPostCallbak('get_logs_list', '' ,args, function(rdata){
$('#logs_search').attr('req','end');
var rdata = $.parseJSON(rdata.data);
var list = '';
var data = rdata.data.data;
@@ -2267,22 +2311,6 @@ function wsTableLogRequest(page){
$('#ws_table').html(table);
$('#wsPage').html(rdata.data.page);
$('input[name="ip"]').bind('focus', function(e){
$(this).keyup(function(e){
if(e.keyCode == 13) {
wsTableLogRequest(1);
}
});
});
$('input[name="search_uri"]').bind('focus', function(e){
$(this).keyup(function(e){
if(e.keyCode == 13) {
wsTableLogRequest(1);
}
});
});
$(".tablescroll .details").click(function(){
var index = $(this).attr('data-id');
var res = data[index];
@@ -2388,6 +2416,7 @@ var html = '<div>\
<option value="500">500</option>\
<option value="502">502</option>\
<option value="503">503</option>\
<option value="499">499</option>\
<option value="404">404</option>\
<option value="301">301</option>\
<option value="302">302</option>\
@@ -2432,6 +2461,15 @@ var html = '<div>\
<option value="500-1000">500ms-1s</option>\
<option value="1000">大于1s</option>\
</select>\
<span style="margin-left:10px;">大小: </span>\
<select class="bt-input-text" name="request_size" style="margin-left:5px;">\
<option value="all">所有</option>\
<option value="0-1">0-1(kb)</option>\
<option value="1-20">1-20(kb)</option>\
<option value="20-50">20-50(kb)</option>\
<option value="50-100">50-100(kb)</option>\
<option value="100">大于100kb</option>\
</select>\
<span style="margin-left:10px;">URL过滤: </span>\
<div class="input-group" style="width:210px;display:inline-flex;">\
<input type="text" name="search_uri" class="form-control btn-group-sm" autocomplete="off" placeholder="URI搜索" style="font-size: 12px;padding: 0 10px;height:30px;">\
@@ -2444,6 +2482,22 @@ var html = '<div>\
</div>';
$(".soft-man-con").html(html);
$('input[name="ip"]').bind('focus', function(e){
$(this).keyup(function(e){
if(e.keyCode == 13) {
wsTableLogRequest(1);
}
});
});
$('input[name="search_uri"]').bind('focus', function(e){
$(this).keyup(function(e){
if(e.keyCode == 13) {
wsTableLogRequest(1);
}
});
});
//日期范围
laydate.render({
elem: '#time_choose',
@@ -2507,6 +2561,10 @@ $('select[name="request_time"]').change(function(){
wsTableLogRequest(1);
});
$('select[name="request_size"]').change(function(){
wsTableLogRequest(1);
});
$('#logs_search').click(function(){
wsTableLogRequest(1);
});
+12 -3
View File
@@ -705,7 +705,7 @@ def get_logs_list(args):
start_time = time.time()
check = checkArgs(args, ['page', 'page_size','site', 'method',
'status_code', 'spider_type', 'request_time', 'query_date', 'search_uri'])
'status_code', 'spider_type', 'request_time', 'request_size', 'query_date', 'search_uri'])
if not check[0]:
return check[1]
@@ -716,6 +716,7 @@ def get_logs_list(args):
method = args['method']
status_code = args['status_code']
request_time = args['request_time']
request_size = args['request_size']
spider_type = args['spider_type']
query_date = args['query_date']
search_uri = args['search_uri']
@@ -726,7 +727,7 @@ def get_logs_list(args):
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
conn = pSqliteDb('web_logs', domain)
field = 'time,ip,domain,server_name,method,is_spider,protocol,status_code,request_headers,ip_list,client_port,body_length,user_agent,referer,request_time,uri,body_length'
field = 'time,ip,domain,server_name,method,is_spider,protocol,status_code,request_headers,ip_list,client_port,body_length,user_agent,referer,request_time,uri'
condition = ''
conn = conn.field(field)
conn = conn.where("1=1", ())
@@ -762,6 +763,14 @@ def get_logs_list(args):
if len(request_time_s) == 1:
conn = conn.andWhere("request_time>=?", (request_time,))
if request_size != "all":
request_size_s = request_size.strip().split('-')
# print(int(request_size_s[0])*1024)
if len(request_size_s) == 2:
conn = conn.andWhere("body_length>=? and body_length<?", (int(request_size_s[0])*1024,int(request_size_s[1])*1024,))
if len(request_size_s) == 1:
conn = conn.andWhere("body_length>=?", (int(request_size_s[0])*1024,))
if spider_type == "normal":
pass
elif spider_type == "only_spider":
@@ -824,7 +833,7 @@ def getLogsErrorList():
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
conn = pSqliteDb('web_logs', domain)
field = 'time,ip,domain,server_name,method,protocol,status_code,ip_list,client_port,body_length,user_agent,referer,request_time,uri,body_length'
field = 'time,ip,domain,server_name,method,protocol,status_code,ip_list,client_port,body_length,user_agent,referer,request_time,uri'
conn = conn.field(field)
conn = conn.where("1=1", ())
+1 -1
View File
@@ -29,7 +29,7 @@ pymemcache
redis
pillow
Jinja2>=2.11.2
PyMySQL==1.0.2
PyMySQL==1.1.1
whitenoise==5.3.0
pyotp
pytz
+18 -4
View File
@@ -1592,6 +1592,22 @@ function setChmod(action,fileName){
var toExec = fileName == lan.files.all?'batch(3,1)':'setChmod(1,\''+fileName+'\')';
$.post('/files/file_access','filename='+encodeURIComponent(fileName),function(rdata){
// console.log(rdata);
var sys_users = rdata.sys_users;
var own_html = '';
var is_find_own_option = false;
for (var i = 0; i < sys_users.length; i++) {
var own = sys_users[i];
if (rdata.chown==own){
is_find_own_option = true;
own_html += '<option value="'+own+'" selected="selected">'+own+'</option>';
} else {
own_html += '<option value="'+own+'">'+own+'</option>';
}
}
if (!is_find_own_option){
own_html += '<option value="'+rdata.chown+'" selected="selected">'+rdata.chown+'</option>';
}
layer.open({
type:1,
closeBtn: 1,
@@ -1619,10 +1635,8 @@ function setChmod(action,fileName){
</fieldset>\
<div class="setchmodnum"><input class="bt-input-text" type="text" id="access" maxlength="3" value="'+rdata.chmod+'">权限,\
<span>所有者\
<select id="chown" class="bt-input-text">\
<option value="www" '+(rdata.chown=='www'?'selected="selected"':'')+'>www</option>\
<option value="mysql" '+(rdata.chown=='mysql'?'selected="selected"':'')+'>mysql</option>\
<option value="root" '+(rdata.chown=='root'?'selected="selected"':'')+'>root</option>\
<select id="chown" class="bt-input-text" style="width:100px;">\
'+own_html+'\
</select></span></div>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-danger btn-sm btn-title" onclick="layer.closeAll()">关闭</button>\
+578 -53
View File
@@ -1,35 +1,3 @@
$(function() {
$(".mem-release").hover(function() {
$(this).addClass("shine_green");
if (!($(this).hasClass("mem-action"))) {
$(this).find(".mem-re-min").hide();
$(this).find(".mask").css({ "color": "#d2edd8" });
$(this).find(".mem-re-con").css({ "display": "block" });
$(this).find(".mem-re-con").animate({ "top": "0", opacity: 1 });
$("#memory").text('内存释放');
}
}, function() {
$(this).removeClass("shine_green");
$(this).find(".mask").css({ "color": "#20a53a" });
$(this).find(".mem-re-con").css({ "top": "15px", opacity: 1, "display": "none" });
$("#memory").text(getCookie("mem-before"));
$(this).find(".mem-re-min").hide();
}).click(function() {
$(this).find(".mem-re-min").hide();
if (!($(this).hasClass("mem-action"))) {
reMemory();
var btlen = $(".mem-release").find(".mask span").text();
$(this).addClass("mem-action");
$(this).find(".mask").css({ "color": "#20a53a" });
$(this).find(".mem-re-con").animate({ "top": "-400px", opacity: 0 });
$(this).find(".pie_right .right").css({ "transform": "rotate(3deg)" });
for (var i = 0; i < btlen; i++) {
setTimeout("rocket(" + btlen + "," + i + ")", i * 30);
}
}
});
});
//获取负载
function getLoad(data) {
$("#LoadList .mask").html("<span id='Load' style='font-size:14px'>获取中..</span>");
@@ -64,7 +32,7 @@ function getLoad(data) {
}
$('#LoadList .circle').click(function() {
getNet();
// getNet();
});
$('#LoadList .mask').hover(function() {
@@ -81,8 +49,7 @@ $('#LoadList .mask').hover(function() {
function showCpuTips(rdata){
$('#cpuChart .mask').unbind();
$('#cpuChart .mask').hover(function() {
$('#cpuChart .mask').unbind().hover(function() {
var cpuText = '';
if (rdata.cpu[2].length == 1){
var cpuUse = parseFloat(rdata.cpu[2][0] == 0 ? 0 : rdata.cpu[2][0]).toFixed(1);
@@ -284,6 +251,8 @@ function getNet() {
var up, down;
$.get("/system/network", function(net) {
console.log(net);
$("#InterfaceSpeed").html(lan.index.interfacespeed + ": 1.0Gbps");
$("#upSpeed").html(toSize(net.up));
$("#downSpeed").html(toSize(net.down));
@@ -310,9 +279,9 @@ function getNet() {
},'json');
}
//网络Io
//网络IO
function netImg() {
var echartsNetImg = echarts.init(document.getElementById('netImg'));
var xData = [];
var yData = [];
var zData = [];
@@ -359,7 +328,7 @@ function netImg() {
var downNetTmp = toSize(getCookie("downNet"));
var upNetTmpSize = upNetTmp.split(' ')[0];
var downNetTmp = downNetTmp.split(' ')[0]
var downNetTmp = downNetTmp.split(' ')[0];
yData.push(upNetTmpSize);
zData.push(downNetTmp);
@@ -378,12 +347,12 @@ function netImg() {
// 指定图表的配置项和数据
var option = {
title: {
text: lan.index.interface_net,
text: "接口流量实时",
left: 'center',
textStyle: {
color: '#888888',
fontStyle: 'normal',
fontFamily: lan.index.net_font,
fontFamily: "宋体",
fontSize: 16,
}
},
@@ -474,6 +443,8 @@ function netImg() {
}
}]
};
var echartsNetImg = echarts.init(document.getElementById('netImg'));
setInterval(function() {
getNet();
addData(true);
@@ -516,8 +487,7 @@ function setImg() {
};
});
$('.diskbox .mask').unbind();
$('.diskbox .mask').hover(function() {
$('.diskbox .mask').unbind().hover(function() {
layer.closeAll('tips');
var that = this;
var conterError = $(this).attr("data");
@@ -638,7 +608,10 @@ function reBoot() {
area: '330px',
closeBtn: 1,
shadeClose: false,
content: '<div class="rebt-con"><div class="rebt-li"><a data-id="server" href="javascript:;">重启服务器</a></div><div class="rebt-li"><a data-id="panel" href="javascript:;">重启面板</a></div></div>'
content: '<div class="rebt-con">\
<div class="rebt-li"><a data-id="server" href="javascript:;">重启服务器</a></div>\
<div class="rebt-li"><a data-id="panel" href="javascript:;">重启面板</a></div>\
</div>'
});
$('.rebt-con a').click(function () {
@@ -779,17 +752,18 @@ function showDanger(num, port) {
closeBtn: 1,
shift: 5,
content: '<div class="pd20">\
<table class="f14 showDanger"><tbody>\
<tr><td class="text-right" width="150">风险类型:</td><td class="f16" style="color:red">暴力破解 <a href="https://www.bt.cn/bbs/thread-9562-1-1.html" class="btlink f14" style="margin-left:10px" target="_blank">说明</a></td></tr>\
<tr><td class="text-right">累计遭遇攻击总数:</td><td class="f16" style="color:red">' + num + ' <a href="javascript:showDangerIP();" class="btlink f14" style="margin-left:10px">详细</a><span class="c9 f12" style="margin-left:10px">(数据直接来源本服务器日志)</span></td></tr>\
<tr><td class="text-right">风险等级:</td><td class="f16" style="color:red">较高风险</td></tr>\
<tr><td class="text-right" style="vertical-align:top">风险描述:</td><td style="line-height:20px">' + atxt + '</td></tr>\
<tr><td class="text-right" style="vertical-align:top">可参考解决方案:</td><td><p style="margin-bottom:8px">方案一:修改SSH默认端口,修改SSH验证方式为数字证书,清除近期登陆日志。</p><p>方案二:购买宝塔企业运维版,一键部署安全隔离服务,高效且方便。</p></td></tr>\
</tbody></table>\
<div class="mtb20 text-center"><a href="https://www.bt.cn/admin/index.html" target="_blank" class="btn btn-success">立即部署隔离防护</a></div>\
</div>'
<table class="f14 showDanger">\
<tbody>\
<tr><td class="text-right" width="150">风险类型:</td><td class="f16" style="color:red">暴力破解 <a href="https://www.bt.cn/bbs/thread-9562-1-1.html" class="btlink f14" style="margin-left:10px" target="_blank">说明</a></td></tr>\
<tr><td class="text-right">累计遭遇攻击总数:</td><td class="f16" style="color:red">' + num + ' <a href="javascript:showDangerIP();" class="btlink f14" style="margin-left:10px">详细</a><span class="c9 f12" style="margin-left:10px">(数据直接来源本服务器日志)</span></td></tr>\
<tr><td class="text-right">风险等级:</td><td class="f16" style="color:red">较高风险</td></tr>\
<tr><td class="text-right" style="vertical-align:top">风险描述:</td><td style="line-height:20px">' + atxt + '</td></tr>\
<tr><td class="text-right" style="vertical-align:top">可参考解决方案:</td><td><p style="margin-bottom:8px">方案一:修改SSH默认端口,修改SSH验证方式为数字证书,清除近期登陆日志。</p><p>方案二:购买宝塔企业运维版,一键部署安全隔离服务,高效且方便。</p></td></tr>\
</tbody>\
</table>\
</div>'
});
$(".showDanger td").css("padding", "8px")
$(".showDanger td").css("padding", "8px");
}
function pluginInit(){
@@ -913,3 +887,554 @@ function loadKeyDataCount(){
call(pname);
}
}
$(function() {
$(".mem-release").hover(function() {
$(this).addClass("shine_green");
if (!($(this).hasClass("mem-action"))) {
$(this).find(".mem-re-min").hide();
$(this).find(".mask").css({ "color": "#d2edd8" });
$(this).find(".mem-re-con").css({ "display": "block" });
$(this).find(".mem-re-con").animate({ "top": "0", opacity: 1 });
$("#memory").text('内存释放');
}
}, function() {
$(this).removeClass("shine_green");
$(this).find(".mask").css({ "color": "#20a53a" });
$(this).find(".mem-re-con").css({ "top": "15px", opacity: 1, "display": "none" });
$("#memory").text(getCookie("mem-before"));
$(this).find(".mem-re-min").hide();
}).click(function() {
$(this).find(".mem-re-min").hide();
if (!($(this).hasClass("mem-action"))) {
reMemory();
var btlen = $(".mem-release").find(".mask span").text();
$(this).addClass("mem-action");
$(this).find(".mask").css({ "color": "#20a53a" });
$(this).find(".mem-re-con").animate({ "top": "-400px", opacity: 0 });
$(this).find(".pie_right .right").css({ "transform": "rotate(3deg)" });
for (var i = 0; i < btlen; i++) {
setTimeout("rocket(" + btlen + "," + i + ")", i * 30);
}
}
});
$("select[name='network-io'],select[name='disk-io']").change(function () {
var key = $(this).val(), type = $(this).attr('name');
if (type == 'network-io') {
if (key == 'ALL') {
key = '';
}
setCookie('network_io_key', key);
} else {
if (key == 'ALL') {
key = '';
}
setCookie('disk_io_key', key);
}
});
$('.tabs-nav span').click(function () {
var indexs = $(this).index();
$(this).addClass('active').siblings().removeClass('active');
$('.tabs-content .tabs-item:eq(' + indexs + ')').addClass('tabs-active').siblings().removeClass('tabs-active');
$('.tabs-down select:eq(' + indexs + ')').removeClass('hide').siblings().addClass('hide');
switch (indexs) {
case 0:
index.net.table.resize();
break;
case 1:
index.iostat.table.resize();
break;
}
})
});
var index = {
common:{
ts:function (m) { return m < 10 ? '0' + m : m },
format:function (sjc) {
var time = new Date(sjc);
var h = time.getHours();
var mm = time.getMinutes();
var s = time.getSeconds();
return h+ ':' + mm + ':' +s;
},
getTime:function () {
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
if (minute < 10) {
minute = "0" + minute;
}
if (second < 10) {
second = "0" + second;
}
var nowdate = hour + ":" + minute + ":" + second;
return nowdate;
},
},
net: {
table: null,
data: {
xData: [],
yData: [],
zData: []
},
default_unit : 'KB/s',
init_select : false,
init: function(){
for (var i = 8; i >= 0; i--) {
var time = (new Date()).getTime();
index.net.data.xData.push(index.common.format(time - (i * 3 * 1000)));
index.net.data.yData.push(0);
index.net.data.zData.push(0);
}
index.net.table = echarts.init(document.getElementById('netImg'));
var option = index.net.defaultOption();
index.net.table.setOption(option);
window.addEventListener("resize", function () {
index.net.table.resize();
});
},
render:function(){
index.net.table.setOption({
yAxis: {
name: '单位 '+ index.net.default_unit,
splitLine: { lineStyle: { color: "#eee" } },
axisLine: { lineStyle: { color: "#666" } }
},
xAxis: {
data: index.net.data.xData
},
series: [{
name: lan.index.net_up,
data: index.net.data.yData
}, {
name: lan.index.net_down,
data: index.net.data.zData
}]
});
},
defaultOption:function(){
var option = {
title: {
text: "",
left: 'center',
textStyle: {
color: '#888888',
fontStyle: 'normal',
fontFamily: "宋体",
fontSize: 16,
}
},
tooltip: {
trigger: 'axis'
},
legend: {
data: [lan.index.net_up, lan.index.net_down],
bottom: '2%'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: index.net.data.xData,
axisLine: {
lineStyle: {
color: "#666"
}
}
},
yAxis: {
name: '单位 '+ index.net.default_unit,
splitLine: {
lineStyle: { color: "#eee" }
},
axisLine: {
lineStyle: { color: "#666" }
}
},
series: [{
name: '上行',
type: 'line',
data: index.net.data.yData,
smooth: true,
showSymbol: false,
symbol: 'circle',
symbolSize: 6,
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(255, 140, 0,0.5)'
}, {
offset: 1,
color: 'rgba(255, 140, 0,0.8)'
}], false)
}
},
itemStyle: {
normal: {
color: '#f7b851'
}
},
lineStyle: {
normal: {
width: 1
}
}
},
{
name: '下行',
type: 'line',
data: index.net.data.zData,
smooth: true,
showSymbol: false,
symbol: 'circle',
symbolSize: 6,
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(30, 144, 255,0.5)',
}, {
offset: 1,
color: 'rgba(30, 144, 255,0.8)',
}], false)
}
},
itemStyle: {
normal: {
color: '#52a9ff',
}
},
lineStyle: {
normal: {
width: 1,
}
}
}]
};
return option;
},
add: function (up, down) {
var _net = this;
var limit = 8;
var d = new Date()
if (_net.data.xData.length >= limit) _net.data.xData.splice(0, 1);
if (_net.data.yData.length >= limit) _net.data.yData.splice(0, 1);
if (_net.data.zData.length >= limit) _net.data.zData.splice(0, 1);
var upTmpSize = toSize(up).split(' ')[0];
var downTmpSize = toSize(down).split(' ')[0];
var tmp = up;
if (down>up){
tmp = down;
}
index.net.default_unit = toSize(tmp).split(' ')[1] + '/s';
_net.data.zData.push(downTmpSize);
_net.data.yData.push(upTmpSize);
_net.data.xData.push(d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds());
},
renderSelect:function(net){
// console.log(net);
if (!index.net.init_select){
var option = '';
var network = net.network;
var network_io_key = getCookie('network_io_key');
for (var name in network) {
if (name == 'ALL'){
option += '<option value="'+name+'">全部</option>';
} else if (network_io_key == name){
option += '<option value="'+name+'" selected>'+name+'</option>';
} else {
option += '<option value="'+name+'">'+name+'</option>';
}
}
$('select[name="network-io"]').html(option);
index.net.init_select = true;
}
}
},
iostat:{
table: null,
data: {
xData: [],
yData: [],
zData: [],
tipsData: []
},
init_select:false,
default_unit : 'MB/s',
init:function(){
for (var i = 8; i >= 0; i--) {
var time = (new Date()).getTime();
index.iostat.data.xData.push(index.common.format(time - (i * 3 * 1000)));
index.iostat.data.yData.push(0);
index.iostat.data.zData.push(0);
index.iostat.data.tipsData.push({});
}
index.iostat.table = echarts.init(document.getElementById('ioStat'));
var option = index.iostat.defaultOption();
index.iostat.table.setOption(option);
window.addEventListener("resize", function () {
index.iostat.table.resize();
});
},
render:function(){
index.iostat.table.setOption({
tooltip: {
trigger: 'axis',
formatter :function (config) {
var _config = config, _tips = "时间:" + _config[0].axisValue + "<br />", options = {
read_bytes: '读取字节数',
read_count: '读取次数 ',
read_merged_count: '合并读取次数',
read_time: '读取延迟',
write_bytes: '写入字节数',
write_count: '写入次数',
write_merged_count: '合并写入次数',
write_time: '写入延迟',
}, data = index.iostat.data.tipsData[config[0].dataIndex], list = ['read_count', 'write_count', 'read_merged_count', 'write_merged_count', 'read_time', 'write_time',];
for (var i = 0; i < config.length; i++) {
if (typeof config[i].data == "undefined") {
return false;
}
_tips += '<span style="display: inline-block;width: 10px;height: 10px;border-radius: 50%;background: ' + config[i].color + ';"></span>&nbsp;&nbsp;<span>' + config[i].seriesName + ':' + config[i].data + ' MB/s' + '</span><br />'
}
$.each(list, function (index, item) {
if (typeof data[item] != 'undefined'){
_tips += '<span style="display: inline-block;width: 10px;height: 10px;"></span>&nbsp;&nbsp;<span style="' + (item.indexOf('time') > -1 ? ('color:' + ((data[item] > 100 && data[item] < 1000) ? '#ff9900' : (data[item] >= 1000 ? 'red' : '#20a53a'))) : '') + '">' + options[item] + ':' + data[item] + (item.indexOf('time') > -1 ? ' ms' : ' 次/秒') + '</span><br />';
}
})
return _tips;
}
},
yAxis: {
name: '单位 '+ index.iostat.default_unit,
splitLine: { lineStyle: { color: "#eee" } },
axisLine: { lineStyle: { color: "#666" } }
},
xAxis: {
data: index.iostat.data.xData
},
series: [{
name: "读取",
data: index.iostat.data.yData
}, {
name: "写入",
data: index.iostat.data.zData
}]
});
},
defaultOption:function(){
var option = {
title: {
text: "",
left: 'center',
textStyle: {
color: '#888888',
fontStyle: 'normal',
fontFamily: "宋体",
fontSize: 16,
}
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ["读取", "写入"],
bottom: '2%'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: index.iostat.data.xData,
axisLine: {
lineStyle: {
color: "#666"
}
}
},
yAxis: {
name: '单位 '+ index.iostat.default_unit,
splitLine: {
lineStyle: { color: "#eee" }
},
axisLine: {
lineStyle: { color: "#666" }
}
},
series: [{
name: '读取',
type: 'line',
data: index.iostat.data.yData,
smooth: true,
showSymbol: false,
symbol: 'circle',
areaStyle: {
normal: {
color: 'rgb(255, 70, 131)'
}
},
itemStyle: {
normal: {
color: 'rgb(255, 70, 131)'
}
},
lineStyle: {
normal: {
width: 1,
}
}
},
{
name: '写入',
type: 'line',
data: index.iostat.data.zData,
smooth: true,
showSymbol: false,
symbol: 'circle',
symbolSize: 6,
areaStyle: {
normal: {
color: 'rgba(46, 165, 186, .7)'
}
},
itemStyle: {
normal: {
color: 'rgba(46, 165, 186, .7)'
}
},
lineStyle: {
normal: {
width: 1,
}
}
}]
};
return option;
},
renderSelect:function(data){
if (!index.iostat.init_select){
var option = '';
var iostat = data.iostat;
var disk_io_key = getCookie('disk_io_key');
for (var name in iostat) {
if (name == 'ALL'){
option += '<option value="'+name+'">全部</option>';
} else if (disk_io_key == name){
option += '<option value="'+name+'" selected>'+name+'</option>';
} else {
option += '<option value="'+name+'">'+name+'</option>';
}
}
$('select[name="disk-io"]').html(option);
index.iostat.init_select = true;
}
},
add: function (read, write, data) {
var _iostat = this;
var limit = 8;
var d = new Date()
if (_iostat.data.xData.length >= limit) _iostat.data.xData.splice(0, 1);
if (_iostat.data.yData.length >= limit) _iostat.data.yData.splice(0, 1);
if (_iostat.data.zData.length >= limit) _iostat.data.zData.splice(0, 1);
if (_iostat.data.tipsData.length >= limit) _iostat.data.tipsData.splice(0, 1);
var readTmpSize = toSizeMB(read).split(' ')[0];
var writeTmpSize = toSizeMB(write).split(' ')[0];
_iostat.data.zData.push(writeTmpSize);
_iostat.data.yData.push(readTmpSize);
_iostat.data.tipsData.push(data);
_iostat.data.xData.push(d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds());
},
},
getData:function(){
$.get("/system/network", function(net) {
//网络IO
var network_io_key = getCookie('network_io_key');
var network_data = net.network;
var network_select = network_data['ALL'];
if (network_io_key && network_io_key != ''){
network_select = network_data[network_io_key];
}
index.net.add(network_select.up,network_select.down);
index.net.render();
index.net.renderSelect(net);
$("#upSpeed").html(toSize(network_select.up));
$("#downSpeed").html(toSize(network_select.down));
$("#downAll").html(toSize(network_select.downTotal));
$("#downAll").attr('title','数据包:' + network_select.downPackets)
$("#upAll").html(toSize(network_select.upTotal));
$("#upAll").attr('title','数据包:' + network_select.upPackets)
//磁盘IO
var disk_io_key = getCookie('disk_io_key');
var iostat_data = net.iostat;
var iostat_select = iostat_data['ALL'];
if (disk_io_key && disk_io_key != ''){
iostat_select = iostat_data[disk_io_key];
}
index.iostat.add(iostat_select.read_bytes,iostat_select.write_bytes, iostat_select);
index.iostat.render();
index.iostat.renderSelect(net);
$("#readBytes").html(toSize(iostat_select.read_bytes));
$("#writeBytes").html(toSize(iostat_select.write_bytes));
$("#diskIops").html(iostat_select.read_count+":"+iostat_select.write_count+ " 次");
$("#diskTime").html(iostat_select.read_time+":"+iostat_select.write_time +" ms");
$("#core").html(net.cpu[1] + " " + lan.index.cpu_core);
$("#state").html(net.cpu[0]);
setcolor(net.cpu[0], "#state", 30, 70, 90);
//负载
getLoad(net.load);
//内存
setMemImg(net.mem);
//绑定hover事件
setImg();
showCpuTips(net);
},'json');
},
task:function(){
// index.getData();
setInterval(function() {
index.getData();
}, 3000);
},
init: function(){
index.net.init();
index.iostat.init();
index.task();
}
}
+25 -8
View File
@@ -16,6 +16,17 @@ function toSize(a) {
}
}
function toSizeMB(a) {
var d = [" KB", " MB"];
var e = 1024;
var i = 0;
for(var b = 0; b < d.length; b++) {
a /= e;
i = b;
}
return a.toFixed(2) + d[i]
}
function toTrim(x) {
return x.replace(/^\s+|\s+$/gm,'');
}
@@ -2244,7 +2255,7 @@ function pluginConfig(_name, version, func){
//配置修改模版 --- start
function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_func){
function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_func, save_callback_func){
if ( typeof(version) == 'undefined' ){
version = '';
}
@@ -2270,7 +2281,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_
<textarea class="bt-input-text" style="height: 320px; line-height:18px;" id="textBody"></textarea>\
<button id="onlineEditFileBtn" class="btn btn-success btn-sm" style="margin-top:10px;">保存</button>\
<ul class="help-info-text c7 ptb15">\
<li>此处为'+ _name + version +'主配置文件,若您不了解配置规则,请勿随意修改。</li>\
<li>此处为【'+ _name + version +'】主配置文件,若您不了解配置规则,请勿随意修改。</li>\
</ul>';
$(".soft-man-con").html(con);
@@ -2310,7 +2321,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_
"Ctrl-H": "replaceAll",
"Ctrl-S": function() {
$("#textBody").text(editor.getValue());
pluginConfigSave(fileName);
pluginConfigSave(fileName,save_callback_func);
}
},
lineNumbers: true,
@@ -2321,7 +2332,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_
$("#onlineEditFileBtn").unbind('click');
$("#onlineEditFileBtn").click(function(){
$("#textBody").text(editor.getValue());
pluginConfigSave(fileName);
pluginConfigSave(fileName, save_callback_func);
});
},'json');
}
@@ -2350,7 +2361,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_
"Ctrl-H": "replaceAll",
"Ctrl-S": function() {
$("#textBody").text(editor.getValue());
pluginConfigSave(fileName);
pluginConfigSave(fileName,save_callback_func);
}
},
lineNumbers: true,
@@ -2360,7 +2371,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_
$(".CodeMirror-scroll").css({"height":"300px","margin":0,"padding":0});
$("#onlineEditFileBtn").click(function(){
$("#textBody").text(editor.getValue());
pluginConfigSave(fileName);
pluginConfigSave(fileName,save_callback_func);
});
},'json');
},'json');
@@ -2487,13 +2498,19 @@ function pluginConfigListTpl(_name, version, config_tpl_func, read_config_tpl_fu
//配置保存
function pluginConfigSave(fileName) {
function pluginConfigSave(fileName, callback) {
var data = encodeURIComponent($("#textBody").val());
var encoding = 'utf-8';
var loadT = layer.msg('保存中...', {icon: 16,time: 0});
$.post('/files/save_body', 'data=' + data + '&path=' + fileName + '&encoding=' + encoding, function(rdata) {
layer.close(loadT);
layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2});
showMsg(rdata.msg, function(){
if ( rdata.status && typeof(callback) == 'function'){
callback();
}
},{icon: rdata.status ? 1 : 2});
},'json');
}
+108 -1
View File
@@ -9,7 +9,8 @@ input,
textarea,
select {
font-size: 100%;
font-family: inherit
font-family: inherit;
outline: none;
}
body,
@@ -5096,4 +5097,110 @@ select[disabled]{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.title.tabs-nav {
padding: 0;
position: relative;
}
.title.tabs-nav span {
display: inline-block;
height: 50px;
min-width: 100px;
padding: 0 20px;
line-height: 50px;
font-size: 15px;
cursor: pointer;
position: relative;
text-align: center;
}
.title.tabs-nav span.active {
color: #20a53a;
background: #20a53a08;
}
.title.tabs-nav select {
position: absolute;
right: 5px;
top: 50%;
margin-top: -12px;
}
select[name="network-io"], select[name="disk-io"] {
font-size: 13px;
height: 24px;
line-height: 24px;
padding: 2px;
border-radius: 0;
border-color: #ececec;
}
.tabs-content .tabs-item {
display: none;
height: 100%;
width: 100%;
background-color: #fff;
}
.tabs-content .tabs-active.tabs-item {
display: inline-block;
}
.bw-info {
height: 80px;
}
.bw-info>div {
float: left;
padding-top: 35px;
text-align: center;
}
.bw-info>div p {
margin-bottom: 7px;
}
.bw-info>div a {
font-size: 14px;
color: #666;
}
.bw-info .ico-down,
.bw-info .ico-up,
.bw-info .ico-write,
.bw-info .ico-read {
width: 10px;
height: 10px;
display: inline-block;
margin-right: 3px;
border-radius: 5px;
}
.bw-info .ico-down {
background-color: #52a9ff;
}
.bw-info .ico-up {
background-color: #f7b851;
}
.bw-info .ico-write {
background-color: #6CC0CF;
}
.bw-info .ico-read {
background-color: #FF4683;
}
.bw-info ul li {
height: 56px;
line-height: 56px;
}
.bw-info ul li.bi-line {
border-bottom: #ddd solid 1px;
}
+40 -10
View File
@@ -99,15 +99,45 @@
<div class="col-xs-12 col-sm-12 col-md-6 pull-left pd0">
<div class="pl7">
<div class="bgw" style="height:491px">
<div class="title c6 f16 plr15">流量</div>
<div class="bw-info">
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-up"></span>上行</p><a id="upSpeed">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-down"></span>下行</p><a id="downSpeed">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9">总发送</p><a id="upAll">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9">总接收</p><a id="downAll">0</a></div>
<div class="bgw radius4" style="height:491px">
<div class="title c6 f16 plr15 tabs-nav">
<div class="tab-list">
<span class="tabs-item active">流量</span>
<span class="tabs-item">磁盘IO</span>
</div>
<div class="tabs-down">
<select class="bt-input-text" name="network-io" style="font-size: 12px;">
<option value="ALL">全部</option>
</select>
<select class="bt-input-text hide" name="disk-io" style="font-size: 12px;">
<option value="ALL">全部</option>
</select>
</div>
</div>
<div id="netImg" style="width:100%;height:330px;"></div>
<div class="tabs-content">
<div class="tabs-active radius4 tabs-item">
<div class="bw-info">
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-up"></span>上行</p><a id="upSpeed">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-down"></span>下行</p><a id="downSpeed">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9">总发送</p><a id="upAll">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9">总接收</p><a id="downAll">0</a></div>
</div>
<div id="netImg" style="width:100%;height:330px;"></div>
</div>
<div class="radius4 tabs-item">
<div class="bw-info">
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-read"></span>读取</p><a id="readBytes">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9"><span class="ico-write"></span>写入</p><a id="writeBytes">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9">每秒读写</p><a id="diskIops">0</a></div>
<div class="col-sm-6 col-md-3"><p class="c9">读写IO延迟</p><a id="diskTime" style="color: rgb(32, 165, 58);">0</a></div>
</div>
<div id="ioStat" style="width:100%;height:330px;"></div>
</div>
</div>
</div>
</div>
</div>
@@ -119,8 +149,8 @@
<script type="text/javascript" src="/static/app/index.js?v={{config.version}}"></script>
<script type="text/javascript">
netImg();
setImg();
index.init();
pluginInit();
//加载关键数据总数
loadKeyDataCount();
+26 -9
View File
@@ -14,15 +14,6 @@
<!--[if lte IE 9]>
<script src="/static/js/requestAnimationFrame.js"></script>
<![endif]-->
<!-- 统计一下用户量,让我的开发更有激情 -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-FC74BB2RGD');
</script>
{% for menu in data['hook_menu'] %}
@@ -188,4 +179,30 @@ if (thisPath.indexOf('?')>-1){
{% endif %}
{% endfor %}
<!-- 统计一下用户量,让我的开发更有激情 -->
<script type="text/javascript">
$(document).ready(function(){
setTimeout(function(){
$.getScript('https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD', function(){
console.log("load google ad!");
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-FC74BB2RGD');
});
},3000);
});
</script>
<!-- Google tag (gtag.js) -->
<!-- <script async src="https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-FC74BB2RGD');
</script> -->
</html>
+23 -4
View File
@@ -87,6 +87,18 @@ class backupTools:
path = mw.getServerDir() + '/' + mtype + '/etc/my.cnf'
return path
def recognizeDbMode(self, mtype='mysql'):
conf = self.getConf(mtype)
con = mw.readFile(conf)
rep = r"!include %s/(.*)?\.cnf" % (mw.getServerDir() +'/'+ mtype +"/etc/mode",)
mode = 'none'
try:
data = re.findall(rep, con, re.M)
mode = data[0]
except Exception as e:
pass
return mode
# 数据库密码处理
def mypass(self, act, root):
conf_file = self.getConf('mysql')
@@ -134,13 +146,20 @@ class backupTools:
# mw.execShell(db_path + "/bin/mysqldump --opt --default-character-set=utf8 " +
# name + " | gzip > " + filename)
# mw.execShell(db_path + "/bin/mysqldump --skip-lock-tables --default-character-set=utf8 " +
# name + " | gzip > " + filename)
# mw.execShell(db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " +
# name + " | gzip > " + filename)
cmd = db_path + "/bin/mysqldump --defaults-file=" + my_cnf + " --force --opt --default-character-set=utf8 " + \
# 开启一致性事务 会lock表
# cmd = db_path + "/bin/mysqldump --defaults-file=" + my_cnf + " --force --opt --default-character-set=utf8 " + \
# name + " | gzip > " + filename
option = ''
mode = self.recognizeDbMode('mysql')
if mode == 'gtid':
option = ' --set-gtid-purged=off '
# skip-opt 不会lock表
# --skip-opt --create-options
cmd = db_path + "/bin/mysqldump --defaults-file=" + my_cnf +" " + option +" --single-transaction -q --default-character-set=utf8mb4 " + \
name + " | gzip > " + filename
# print(cmd)
mw.execShell(cmd)
+30 -9
View File
@@ -258,7 +258,7 @@ mw_mirror()
else
bash <(curl --insecure -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)
fi
cd /www/server/mdserver-web
cd ${ROOT_PATH}/mdserver-web
}
mw_install_app()
@@ -297,8 +297,8 @@ mw_debug(){
port=$(cat $mw_path/data/port.pl)
fi
if [ -d /www/server/mdserver-web ];then
cd /www/server/mdserver-web
if [ -d ${ROOT_PATH}/mdserver-web ];then
cd ${ROOT_PATH}/mdserver-web
fi
gunicorn -b :$port -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 app:app
}
@@ -373,7 +373,8 @@ mw_connect_mysql(){
INPUT_KEY=${SOURCE_LIST_KEY[$INPUT]}
CHOICE_DB=${DB_TYPE[$INPUT_KEY]}
echo "login to ${CHOICE_DB}:"
pwd=$(cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/${CHOICE_DB}/index.py root_pwd)
pwd=$(cd ${ROOT_PATH}/mdserver-web && python3 ${ROOT_PATH}/mdserver-web/plugins/${CHOICE_DB}/index.py root_pwd)
if [ "$CHOICE_DB" == "mysql" ];then
${ROOT_PATH}/mysql/bin/mysql -uroot -p"${pwd}"
fi
@@ -392,15 +393,34 @@ mw_connect_mysql(){
}
mw_redis(){
CONF="${ROOT_PATH}/redis/redis.conf"
if [ ! -f "$CONF" ]; then
echo -e "not install redis!"
exit 1
fi
REDISPORT=$(cat $CONF |grep port|grep -v '#'|awk '{print $2}')
REDISPASS=$(cat $CONF |grep requirepass|grep -v '#'|awk '{print $2}')
if [ "$REDISPASS" != "" ];then
REDISPASS=" -a $REDISPASS"
fi
CLIEXEC="${ROOT_PATH}/redis/bin/redis-cli -p $REDISPORT$REDISPASS"
echo $CLIEXEC
${CLIEXEC}
}
mw_venv(){
cd /www/server/mdserver-web && source bin/activate
cd ${ROOT_PATH}/mdserver-web && source bin/activate
}
mw_clean_lib(){
cd /www/server/mdserver-web && rm -rf lib
cd /www/server/mdserver-web && rm -rf lib64
cd /www/server/mdserver-web && rm -rf bin
cd /www/server/mdserver-web && rm -rf include
cd ${ROOT_PATH}/mdserver-web && rm -rf lib
cd ${ROOT_PATH}/mdserver-web && rm -rf lib64
cd ${ROOT_PATH}/mdserver-web && rm -rf bin
cd ${ROOT_PATH}/mdserver-web && rm -rf include
}
case "$1" in
@@ -428,6 +448,7 @@ case "$1" in
'debug') mw_debug;;
'mirror') mw_mirror;;
'db') mw_connect_mysql;;
'redis') mw_redis;;
'venv') mw_venv;;
'clean_lib') mw_clean_lib;;
'default')
+2
View File
@@ -14,6 +14,7 @@ dnf install -y python3-devel
dnf install -y python-devel
dnf install -y crontabs
dnf install -y mysql-devel
dnf install -y pv
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
@@ -94,6 +95,7 @@ yum install -y bison re2c cmake
yum install -y cmake3
yum install -y autoconf
yum install -y expect
yum install -y bc
yum install -y curl curl-devel
yum install -y zlib zlib-devel
+2
View File
@@ -21,6 +21,8 @@ yum install -y python-devel
yum install -y curl-devel libmcrypt libmcrypt-devel
yum install -y mysql-devel
yum install -y expect
yum install -y pv
yum install -y bc
SSH_PORT=`netstat -ntpl|grep sshd|grep -v grep | sed -n "1,1p" | awk '{print $4}' | awk -F : '{print $2}'`
if [ "$SSH_PORT" == "" ];then
+3
View File
@@ -40,6 +40,9 @@ echo y | pacman -Sy rpcsvc-proto
echo y | pacman -Sy lemon
echo y | pacman -Sy which
echo y | pacman -Sy expect
echo y | pacman -Sy pv
echo y | pacman -Sy bc
## gd start
echo y | pacman -Sy gd
+2
View File
@@ -31,6 +31,8 @@ yum install -y libmcrypt
yum install -y libmcrypt-devel
yum install -y mysql-devel
yum install -y expect
yum install -y pv
yum install -y bc
# if [ -f /usr/sbin/iptables ];then
+2
View File
@@ -56,6 +56,8 @@ apt-get update -y
apt install -y wget curl lsof unzip tar cron expect locate lrzsz
apt install -y rar
apt install -y unrar
apt install -y pv
apt install -y bc
apt install -y python3-pip python3-dev python3-venv
+2
View File
@@ -31,6 +31,8 @@ yum install -y libmcrypt
yum install -y libmcrypt-devel
yum install -y mysql-devel
yum install -y expect
yum install -y pv
yum install -y bc
# if [ -f /usr/sbin/iptables ];then
+2
View File
@@ -73,6 +73,8 @@ yum install -y epel-release
yum install -y libevent libevent-devel zip libmcrypt libmcrypt-devel
yum install -y rar unrar
yum install -y pv
yum install -y bc
yum install -y gcc libffi-devel python-devel openssl-devel
yum install -y libmcrypt libmcrypt-devel python3-devel
+2
View File
@@ -60,6 +60,8 @@ pkg install -y harfbuzz
pkg install -y libevent
pkg install -y pidof
pkg install -y pstree
pkg install -y pv
pkg install -y bc
# curl https://sh.rustup.rs -sSf | sh
pkg install -y rust
+1 -1
View File
@@ -22,7 +22,7 @@ if [ "$?" != "0" ];then
brew install mysql
fi
brew install pv
brew install libzip bzip2 gcc openssl re2c cmake
brew install librdkafka
brew install coreutils libxml2 xml2
+2
View File
@@ -28,6 +28,8 @@ zypper install -y libevent-devel
zypper install -y libtirpc-devel
zypper install -y rpcgen
zypper install -y expect
zypper install -y pv
zypper install -y bc
zypper install -y libzip libzip-devel
zypper install -y unrar rar
+2
View File
@@ -184,6 +184,7 @@ if [ "$VERSION_ID" -ge "8" ];then
oniguruma oniguruma-devel patch pcre pcre-devel perl perl-Data-Dumper perl-devel procps psmisc python3-devel \
openssl openssl-devel patchelf libargon2-devel\
ImageMagick ImageMagick-devel libyaml-devel \
pv bc\
readline-devel rpcgen sqlite-devel rar unrar tar unzip vim-minimal wget zip zlib zlib-devel;
do
# dnf --enablerepo=remi,appstream,baseos,epel,extras,powertools install -y oniguruma5php-devel
@@ -203,6 +204,7 @@ else
libwebp libwebp-devel libxml2 libxml2-devel libxslt libxslt-devel libzip libzip-devel libzstd-devel \
make mysql-devel ncurses ncurses-devel net-tools oniguruma oniguruma-devel openldap openldap-devel \
openssl openssl-devel patch pcre pcre-devel perl perl-Data-Dumper perl-devel psmisc python-devel \
pv bc\
python3-devel python3-pip re2c readline-devel rpcgen sqlite-devel tar unzip rar unrar vim-minimal vixie-cron \
wget zip zlib zlib-devel ImageMagick ImageMagick-devel libyaml-devel patchelf libargon2-devel;
do
+2
View File
@@ -15,6 +15,8 @@ sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
yum install -y wget lsof
yum install -y unrar rar
yum install -y pv
yum install -y bc
yum install -y python3-devel
yum install -y crontabs
yum install -y expect
+2 -1
View File
@@ -18,7 +18,8 @@ apt install -y python3-pip
apt install -y python3-venv
apt install -y python3-dev
apt install -y expect
apt install -y pv
apt install -y bc
apt install -y cron
+22 -1
View File
@@ -62,6 +62,7 @@ def mwcli(mw_input=0):
print("(23) 关闭IPV6支持")
print("(24) 开启防火墙SSH端口")
print("(25) 关闭二次验证")
print("(26) 查看防火墙信息")
print("(100) 开启PHP52显示")
print("(101) 关闭PHP52显示")
print("(200) 切换Linux系统软件源")
@@ -75,7 +76,12 @@ def mwcli(mw_input=0):
except:
mw_input = 0
nums = [1, 2, 3, 4, 5, 10, 11, 12, 13, 20, 21, 22, 23, 24, 25, 100, 101, 200, 201]
nums = [
1, 2, 3, 4, 5, 10, 11, 12, 13,
20, 21, 22, 23, 24, 25, 26,
100, 101,
200, 201
]
if not mw_input in nums:
print(raw_tip)
print("已取消!")
@@ -153,6 +159,21 @@ def mwcli(mw_input=0):
print("|-关闭二次验证成功!")
else:
print("|-二次验证已关闭!")
elif mw_input == 26:
cmd = 'which ufw'
run_cmd = False
find_cmd = mw.execShell(cmd)
if find_cmd[0].strip() != '':
run_cmd = True
os.system('ufw status')
cmd = 'which firewall-cmd'
find_cmd = mw.execShell(cmd)
if find_cmd[0].strip() != '':
run_cmd = True
os.system('firewall-cmd --list-all')
if not run_cmd:
mw.echoInfo("未检测到防火墙!")
elif mw_input == 100:
php_conf = 'plugins/php/info.json'
if os.path.exists(php_conf):
+2 -1
View File
@@ -35,4 +35,5 @@ whitenoise==5.3.0
pyotp
pytz
pyTelegramBotAPI
telebot
telebot
pyyaml
+2 -1
View File
@@ -1,3 +1,4 @@
urllib3==1.21.1
gevent==22.10.2
gunicorn==21.2.0
gunicorn==21.2.0
pyyaml