Compare commits

..
982 Commits
Author SHA1 Message Date
Mr Chen 4efe740504 Merge pull request #522 from midoks/dev
0.16.3
2024-02-06 22:53:11 +08:00
Mr Chen bde0ed59ad Update README.md 2024-02-06 22:52:15 +08:00
Mr Chen 19c855790f Update config_api.py 2024-02-06 22:51:47 +08:00
Mr Chen 4a90f1b8b0 Update app.js 2024-02-06 22:45:25 +08:00
Mr Chen f83bdffed8 update 2024-02-06 22:44:52 +08:00
Mr Chen 087cb4fc37 Update app.js 2024-02-06 22:16:09 +08:00
Mr Chen 66bcd15502 update 2024-02-06 22:14:17 +08:00
Mr Chen 29e3dedbe9 update 2024-02-06 22:11:02 +08:00
Mr Chen f10160c239 update 2024-02-06 22:06:26 +08:00
Mr Chen 376d09a955 up 2024-02-06 21:31:20 +08:00
Mr Chen 9076a3a11a Update app.js 2024-02-06 21:27:05 +08:00
Mr Chen 57719990d5 Update app.js 2024-02-06 21:20:07 +08:00
Mr Chen 7073d66662 Update app.js 2024-02-06 21:18:33 +08:00
Mr Chen 1983d02107 up 2024-02-06 21:17:24 +08:00
Mr Chen b4acb2942f update 2024-02-06 19:49:15 +08:00
Mr Chen c94a662235 Update index.html 2024-02-06 18:25:47 +08:00
Mr Chen 1d61026dd3 Update index.html 2024-02-06 18:25:28 +08:00
Mr Chen 48a55e279e Update nosql_mongodb.py 2024-02-06 18:06:45 +08:00
Mr Chen 55e9313711 update 2024-02-06 18:00:20 +08:00
Mr Chen 5ab59c3b75 update 2024-02-06 04:34:41 +08:00
Mr Chen 9c045b8e85 update 2024-02-06 04:10:13 +08:00
Mr Chen 65e87fec1a up 2024-02-06 03:52:36 +08:00
Mr Chen dc8f508ac5 update 2024-02-06 03:14:20 +08:00
Mr Chen ce0c2fb9ea Update index.py 2024-02-05 00:22:00 +08:00
Mr Chen d7e70aa701 Update index.py 2024-02-05 00:17:44 +08:00
Mr Chen ceacaaf7ae Update index.py 2024-02-04 18:12:33 +08:00
Mr Chen 36ad902250 Update tool_migrate.py 2024-02-04 15:30:05 +08:00
Mr Chen 7a871d3e16 Update tool_migrate.py 2024-02-04 15:29:31 +08:00
Mr Chen f36ba4a351 Update tool_migrate.py 2024-02-04 15:27:50 +08:00
Mr Chen 5093265a24 Update index.html 2024-02-04 02:38:03 +08:00
Mr Chen 9c4347f692 del rockmongo 2024-02-03 23:30:52 +08:00
Mr Chen cb882ab7a1 Update requirements.txt 2024-02-03 20:36:40 +08:00
Mr Chen 0d5fd1b423 Update README.md 2024-02-03 18:46:13 +08:00
Mr Chen e694635088 Update README.md 2024-02-03 18:45:59 +08:00
Mr Chen 3386ae2064 Update app.js 2024-02-03 16:11:00 +08:00
Mr Chen bbaced5976 Update app.js 2024-02-03 15:51:33 +08:00
Mr Chen c0d5c5c0e6 Update app.js 2024-02-03 15:50:38 +08:00
Mr Chen f9f7de48ef Update app.js 2024-02-03 15:43:26 +08:00
Mr Chen 5555eab5c0 Update stats.js 2024-02-03 15:40:35 +08:00
Mr Chen 654737cbd2 Update setting.js 2024-02-03 15:34:38 +08:00
Mr Chen 04568df3df update 2024-02-03 04:44:06 +08:00
Mr Chen b1e8839ace update_dev 2024-02-03 04:09:00 +08:00
Mr Chen 80c6f91206 update 2024-02-02 06:16:28 +08:00
Mr Chen 315b8e0e48 Update index.html 2024-02-01 22:18:18 +08:00
Mr Chen ed295d5456 up 2024-02-01 22:08:45 +08:00
Mr Chen eb38d81674 Update config_api.py 2024-02-01 15:06:39 +08:00
Mr Chen 0bc3b42819 del phpredisadmin 2024-02-01 05:19:10 +08:00
Mr Chen 8a640981d2 数据管理插件 2024-02-01 05:09:56 +08:00
Mr Chen 7b94a61b65 update 2024-01-29 19:25:05 +08:00
Mr Chen e24151f332 Update public.js 2024-01-27 15:45:05 +08:00
Mr Chen dc43953c05 Update public.js 2024-01-27 15:44:52 +08:00
Mr Chen 160ff6a4a7 update 2024-01-26 03:03:07 +08:00
Mr Chen a218ba05d2 Update app_start.php 2024-01-25 15:38:32 +08:00
Mr Chen 65cb4941af Update index.py 2024-01-25 15:11:18 +08:00
Mr Chen 53a12e7c4b Update site.js 2024-01-24 19:25:29 +08:00
Mr Chen 6db8a906ff Update task.py 2024-01-23 23:41:06 +08:00
Mr Chen fc6c86e3ce Update info.json 2024-01-23 03:02:04 +08:00
Mr Chen f5989c881d Update info.json 2024-01-23 03:00:50 +08:00
Mr Chen b4946a87ee Update index.py 2024-01-23 02:43:58 +08:00
Mr Chen 562e153371 Update site.css 2024-01-23 02:01:13 +08:00
Mr Chen 63ea0cc129 Update requirements.txt 2024-01-23 00:16:03 +08:00
Mr Chen 8eacae7c6a Update .gitignore 2024-01-22 23:46:30 +08:00
Mr Chen 3e48c3871a Update task.py 2024-01-22 23:46:15 +08:00
Mr Chen 22df4cb5b1 Update task.py 2024-01-22 23:41:02 +08:00
Mr Chen 2d5d954586 Create ico.png 2024-01-22 16:48:14 +08:00
Mr Chen 63ce3805ee Update index.py 2024-01-22 00:23:55 +08:00
Mr Chen 3fe4918b55 update 2024-01-22 00:16:25 +08:00
Mr Chen 24cc733e45 Update mongodb.conf 2024-01-21 23:30:52 +08:00
Mr Chen 1ebb9e1ff3 Update mongodb.conf 2024-01-21 22:15:08 +08:00
Mr Chen 9769f2c190 Update config_api.py 2024-01-21 16:34:28 +08:00
Mr Chen de91e4545b update 2024-01-21 16:01:10 +08:00
Mr Chen 8d3c87a25e Update opcache.sh 2024-01-21 15:54:00 +08:00
Mr Chen 660e393cf1 Update install.sh 2024-01-21 13:47:35 +08:00
Mr Chen fa5f2d6de5 Update config.js 2024-01-21 02:35:15 +08:00
Mr Chen f27406d343 Update config.js 2024-01-21 02:32:37 +08:00
Mr Chen 488577af68 update 2024-01-21 02:23:18 +08:00
Mr Chen 0f7b462b43 Update task.py 2024-01-21 01:47:41 +08:00
Mr Chen 998f1ceae5 Update task.py 2024-01-21 01:44:17 +08:00
Mr Chen 2a9bec3fb8 Update README.md 2024-01-21 01:29:08 +08:00
Mr Chen 5c301296df 站点页优化 2024-01-21 01:27:09 +08:00
Mr Chen 45b0e94132 update 2024-01-20 18:32:35 +08:00
Mr Chen 06be751d1a update 2024-01-20 18:25:31 +08:00
Mr Chen f939b03a0b Update update_dev.sh 2024-01-20 18:22:35 +08:00
Mr Chen 3339406f37 Update compatibility.md 2024-01-20 13:57:24 +08:00
Mr Chen f32d07ccc9 Update nginx.conf 2024-01-20 13:09:40 +08:00
Mr Chen ab8f1623bf update 2024-01-20 02:31:29 +08:00
Mr Chen d467d73230 Update backup.conf 2024-01-20 02:30:52 +08:00
Mr Chen 4b0dd7d3fb Update php.js 2024-01-20 01:49:35 +08:00
Mr Chen 91d243f8b1 Update install.sh 2024-01-20 01:37:57 +08:00
Mr Chen d682882d25 Update install.sh 2024-01-20 01:37:07 +08:00
Mr Chen 0b3745c933 Update README.md 2024-01-20 01:29:45 +08:00
Mr Chen 935c3012f9 Update README.md 2024-01-20 01:08:45 +08:00
Mr Chen a191548a83 Update enable-php-upstream.conf 2024-01-19 22:06:48 +08:00
Mr Chen 9a01d61e1e Update enable-php.conf 2024-01-19 22:06:35 +08:00
Mr Chen 7524798385 php配置改造 2024-01-19 21:21:36 +08:00
Mr Chen 86e3796524 Update logs_api.py 2024-01-18 13:23:22 +08:00
Mr Chen 37d68f5ff8 Update logs_api.py 2024-01-17 21:19:48 +08:00
Mr Chen 647e3904d2 Create enable-php-upstream.conf 2024-01-17 04:22:34 +08:00
Mr Chen c5abb3eea1 Update index.html 2024-01-17 03:20:48 +08:00
Mr Chen 65c94c64ae Update README.md 2024-01-17 02:47:12 +08:00
Mr Chen dbc132951b PHP-FPM设置多个应用池 2024-01-17 02:44:17 +08:00
Mr Chen 440ba49e7b Create backup.conf 2024-01-17 00:07:45 +08:00
Mr Chen 6a0f78b1a0 Update index.html 2024-01-17 00:07:30 +08:00
Mr Chen a69ff3e373 php更新加密校验 2024-01-16 01:18:27 +08:00
Mr Chen 770d37e575 Update config_api.py 2024-01-15 19:58:33 +08:00
Mr Chen e725ad90ca Update config.js 2024-01-15 19:56:57 +08:00
Mr Chen bf5d8f7f27 Update commit.tpl 2024-01-15 17:14:46 +08:00
Mr Chen 9bc72b23d6 Update commit.tpl 2024-01-15 17:13:52 +08:00
Mr Chen 3ac3350240 Update install.sh 2024-01-14 22:38:40 +08:00
Mr Chen c1d04b0a16 Update index.py 2024-01-14 22:35:48 +08:00
Mr Chen 1962cece21 Update index.py 2024-01-14 22:33:00 +08:00
Mr Chen 0d24b8aebd update 2024-01-14 22:29:28 +08:00
Mr Chen de50de0a75 Update index.py 2024-01-14 22:16:35 +08:00
Mr Chen 190fc88d4f Update index.py 2024-01-10 22:23:44 +08:00
Mr Chen 727a7872a7 Update index.py 2024-01-10 14:52:19 +08:00
Mr Chen d408d56826 Update README.md 2024-01-10 14:14:17 +08:00
Mr Chen 1cccd63edc update 2024-01-10 12:57:43 +08:00
Mr Chen cc50816286 Update config.html 2024-01-10 00:55:53 +08:00
Mr Chen 04426c7a67 Update README.md 2024-01-10 00:40:27 +08:00
Mr Chen 3979820eae 时区 2024-01-10 00:19:09 +08:00
Mr Chen 3a850a31a1 Update config_api.py 2024-01-10 00:05:52 +08:00
Mr Chen 6f5487b487 Update requirements.txt 2024-01-10 00:03:59 +08:00
Mr Chen d09a96ec84 时区设置 2024-01-10 00:02:04 +08:00
Mr Chen dcc4e14e7b Update gd.sh 2024-01-09 19:48:29 +08:00
Mr Chen e947b8db4e Update gd_old.sh 2024-01-09 19:47:51 +08:00
Mr Chen 158a66ab62 update 2024-01-09 19:06:34 +08:00
Mr Chen df596fc673 Update tools.py 2024-01-09 01:57:28 +08:00
Mr Chen 707fd668d5 update 2024-01-09 01:56:25 +08:00
Mr Chen b96c4c00e3 Update common.py 2024-01-09 01:12:13 +08:00
Mr Chen bc6cf72cfe up 2024-01-07 19:16:24 +08:00
Mr Chen 48dacb4c27 Update php.js 2024-01-07 04:14:03 +08:00
Mr Chen 78c9abbde2 update 2024-01-07 04:12:33 +08:00
Mr Chen d8d772c6dc Create trace.sh 2024-01-07 03:16:18 +08:00
Mr Chen 33e114ffdd Update php.js 2024-01-07 03:11:18 +08:00
Mr Chen 552b63d329 update 2024-01-07 03:08:41 +08:00
Mr Chen 36637260a7 Update index_php_apt.py 2024-01-07 03:06:45 +08:00
Mr Chen 53fbb5039b Update index_php_apt.py 2024-01-07 02:58:50 +08:00
Mr Chen 74152af289 Update index_php_apt.py 2024-01-07 02:56:30 +08:00
Mr Chen 5bf4401fb0 Update index_php_apt.py 2024-01-07 02:51:56 +08:00
Mr Chen 12117a3b27 Update index_php_apt.py 2024-01-07 02:47:58 +08:00
Mr Chen d726f1bb15 Update php.js 2024-01-07 02:43:33 +08:00
Mr Chen a2b316b4d2 update 2024-01-07 02:40:56 +08:00
Mr Chen 0d48e5250a Update php.js 2024-01-07 02:35:21 +08:00
Mr Chen d3cd606432 Update php.js 2024-01-07 02:35:14 +08:00
Mr Chen 600435f23c update 2024-01-07 02:34:33 +08:00
Mr Chen b4831d64b9 php界面优化 2024-01-07 02:32:04 +08:00
Mr Chen 6638967636 Create script.sh 2024-01-07 02:05:19 +08:00
Mr Chen ead409a58c Update linux.conf 2024-01-07 01:32:15 +08:00
Mr Chen 971da145cb Update linux.conf 2024-01-07 01:21:59 +08:00
Mr Chen 055d440484 up 2024-01-04 19:54:50 +08:00
Mr Chen 97e2d131b4 update 2024-01-01 19:26:19 +08:00
Mr Chen e2784d2d55 Update .gitignore 2024-01-01 02:18:10 +08:00
Mr Chen 6b697ae3be Update opcache.sh 2023-12-31 02:15:07 +08:00
Mr Chen 207fa1d15e Update index.py 2023-12-30 19:58:54 +08:00
Mr Chen 454e399d3d Update phpmongoadmin.conf 2023-12-30 19:32:39 +08:00
Mr Chen 6ea8f20a9d php mongo admin 2023-12-30 19:32:17 +08:00
Mr Chen 9dc3496c27 update 2023-12-30 04:30:21 +08:00
Mr Chen b523b84609 Update info.json 2023-12-30 04:19:03 +08:00
Mr Chen e443b88ad9 phpredisadmin 2023-12-30 04:12:15 +08:00
Mr Chen 480ae78579 Update redis.conf 2023-12-30 03:32:23 +08:00
Mr Chen fb31e3ca15 Update index.py 2023-12-30 03:31:39 +08:00
Mr Chen 53fdaed5c3 Update install.sh 2023-12-30 03:21:20 +08:00
Mr Chen 37f6f2b6bc update 2023-12-30 03:21:13 +08:00
Mr Chen d1028bcc41 Update install.sh 2023-12-30 02:43:43 +08:00
Mr Chen 72e7800b50 AD调整 2023-12-30 00:04:39 +08:00
Mr Chen bb717d2963 update 2023-12-28 19:07:05 +08:00
Mr Chen 16787aebd0 Update stats.js 2023-12-28 03:34:53 +08:00
Mr Chen d769822731 Update stats.js 2023-12-28 03:32:48 +08:00
Mr Chen b6073ba8d3 Update maccms.conf 2023-12-28 00:47:18 +08:00
Mr Chen 8d50f75f18 php 升级 2023-12-27 20:46:10 +08:00
Mr Chen 8077b4cb13 Update gtid.cnf 2023-12-25 19:58:20 +08:00
Mr Chen 7a9f1ebf5e Create orm.py 2023-12-25 19:56:48 +08:00
Mr Chen 21f5670a85 Update index.py 2023-12-23 00:41:00 +08:00
Mr Chen dbd0664c72 Merge pull request #519 from midoks/dev
mysql-apt/mysql-yum 功能增强
2023-12-22 23:25:00 +08:00
Mr Chen f9e53164d9 Update README.md 2023-12-22 23:23:24 +08:00
Mr Chen 62e0321126 Update index.py 2023-12-22 23:10:47 +08:00
Mr Chen 51b82ecbbb Update index.py 2023-12-22 23:09:32 +08:00
Mr Chen 0229f50fef Update install.sh 2023-12-22 23:04:53 +08:00
Mr Chen be176001ea Update index.py 2023-12-22 22:50:33 +08:00
Mr Chen 3bea21bb94 update 2023-12-22 22:48:14 +08:00
Mr Chen 4b3104c849 Update index.py 2023-12-22 22:32:59 +08:00
Mr Chen 0cbb1ad02e Update index.py 2023-12-22 22:28:50 +08:00
Mr Chen 221f114dd4 Update index.py 2023-12-22 22:28:17 +08:00
Mr Chen 5a5c2f3e33 update 2023-12-22 22:20:03 +08:00
Mr Chen 69de62f8c3 Update index.py 2023-12-22 22:12:41 +08:00
Mr Chen af7698e157 update 2023-12-22 22:02:46 +08:00
Mr Chen f0af84f940 Update index.py 2023-12-22 21:54:05 +08:00
Mr Chen 4802dde50a update 2023-12-22 21:52:31 +08:00
Mr Chen fcbf7be2b6 update 2023-12-22 21:45:06 +08:00
Mr Chen f77484df84 update 2023-12-22 21:42:06 +08:00
Mr Chen 64ccba7595 Update index.py 2023-12-22 21:37:57 +08:00
Mr Chen b1935372a1 Update index.py 2023-12-22 21:37:37 +08:00
Mr Chen 03c9afed4a Create index_mysql_apt.py 2023-12-22 21:35:09 +08:00
Mr Chen 4e63c82e93 update 2023-12-22 21:32:20 +08:00
Mr Chen 6fa2fde791 Update index_mysql_apt.py 2023-12-22 21:23:28 +08:00
Mr Chen 98353df1ee Update index.py 2023-12-22 21:20:26 +08:00
Mr Chen 50978741aa Update index.py 2023-12-22 21:14:59 +08:00
Mr Chen d4431f11be Update index.py 2023-12-22 21:09:08 +08:00
Mr Chen 3faad62dd8 update 2023-12-22 20:58:23 +08:00
Mr Chen 6d2550e607 update 2023-12-22 20:31:23 +08:00
Mr Chen f835e4d6a1 Merge branch 'master' into dev 2023-12-22 15:53:37 +08:00
Mr Chen e33bdc5b7d Merge pull request #518 from midoks/dev
mariadb功能增强
2023-12-22 15:33:30 +08:00
Mr Chen 1e6fe01819 Update index.py 2023-12-22 15:21:12 +08:00
Mr Chen c522738df5 Update mysql.js 2023-12-22 15:20:37 +08:00
Mr Chen 5a8be9de7c Update mariadb.js 2023-12-22 15:19:44 +08:00
Mr Chen fd9c860d9b Update index.py 2023-12-22 15:11:12 +08:00
Mr Chen 306a6d450f Update index.py 2023-12-22 15:04:56 +08:00
Mr Chen 79fd1d7157 Update install.sh 2023-12-22 14:55:58 +08:00
Mr Chen 9276e811c2 update 2023-12-22 14:50:50 +08:00
Mr Chen d1493ca13f Update index.py 2023-12-22 05:27:01 +08:00
Mr Chen 13c605d58a Update index.py 2023-12-22 05:26:16 +08:00
Mr Chen 36d19f2250 up 2023-12-22 05:21:59 +08:00
Mr Chen 8f229c99be Update index.py 2023-12-22 05:05:48 +08:00
Mr Chen 72b16e9540 update 2023-12-22 04:59:19 +08:00
Mr Chen dbe2a1f0df Update index.py 2023-12-22 04:56:05 +08:00
Mr Chen 4c3f8c095f Update index.py 2023-12-22 04:55:30 +08:00
Mr Chen 589933dc33 Update index.py 2023-12-22 04:53:05 +08:00
Mr Chen de36f41182 Update index.py 2023-12-22 04:51:07 +08:00
Mr Chen 8e1b4881c4 Update index.py 2023-12-22 04:22:10 +08:00
Mr Chen 692872ecd6 Update index.py 2023-12-22 04:14:58 +08:00
Mr Chen d422a640d5 Update index.py 2023-12-22 03:48:35 +08:00
Mr Chen 46d293613e Update index.py 2023-12-22 03:46:26 +08:00
Mr Chen b775625890 Update index.py 2023-12-22 03:25:54 +08:00
Mr Chen eb2bb595de Update index.py 2023-12-22 03:10:31 +08:00
Mr Chen 0ddc3bf762 Update index.py 2023-12-22 03:05:50 +08:00
Mr Chen e45604f211 update 2023-12-22 02:49:13 +08:00
Mr Chen 4f22d9ae70 update 2023-12-22 02:39:43 +08:00
Mr Chen 732363ec41 Update index.py 2023-12-22 01:26:16 +08:00
Mr Chen bc688aa93f update 2023-12-22 01:23:47 +08:00
Mr Chen 56ed68b888 mariadb 二进制查看 2023-12-22 01:17:45 +08:00
Mr Chen 90539a5049 Update index.py 2023-12-22 01:08:36 +08:00
Mr Chen df15100272 Update mariadb.js 2023-12-22 01:04:20 +08:00
Mr Chen 4bfec3ac06 Update index.py 2023-12-22 01:01:46 +08:00
Mr Chen 3a80a27970 Update mysql.js 2023-12-22 00:56:02 +08:00
Mr Chen 09e79aff63 Update index.py 2023-12-22 00:55:18 +08:00
Mr Chen 41a36a6fd3 Update index.py 2023-12-22 00:52:15 +08:00
Mr Chen fc0974dc91 mysql修复功能-敏感功能优化 2023-12-22 00:34:23 +08:00
Mr Chen 4942c92b33 Update index.py 2023-12-22 00:24:08 +08:00
Mr Chen e173c2e51a mysql修复功能-敏感功能优化 2023-12-22 00:18:41 +08:00
Mr Chen daddf317e2 Update info.json 2023-12-21 19:07:32 +08:00
Mr Chen 7e919050b2 Create my8.2.cnf 2023-12-21 19:01:03 +08:00
Mr Chen af9d050536 update 2023-12-21 18:59:32 +08:00
Mr Chen a9e6acd407 Update phplib.conf 2023-12-21 18:57:03 +08:00
Mr Chen 180e67dde9 Update info.json 2023-12-21 18:11:37 +08:00
Mr Chen f8451fadba Create install.sh 2023-12-21 18:10:49 +08:00
Mr Chen 558bfcb1ee 调整 2023-12-20 01:15:06 +08:00
Mr Chen 6a27e69ee7 Update config_api.py 2023-12-19 23:34:11 +08:00
Mr Chen b5d28b4ef2 流量显示优化 2023-12-19 23:31:18 +08:00
Mr Chen 8f80336901 Update index.py 2023-12-18 22:18:54 +08:00
Mr Chen 0a78dda06c update 2023-12-18 22:13:03 +08:00
Mr Chen b6c3020705 Update index.py 2023-12-18 21:42:56 +08:00
Mr Chen ed70d4faa3 Update index.py 2023-12-18 21:41:26 +08:00
Mr Chen 46e4f55105 Merge pull request #517 from midoks/dev
mongodb优化
2023-12-17 13:52:23 +08:00
Mr Chen 235f0b6d66 Update mongodb.conf 2023-12-17 13:47:30 +08:00
Mr Chen 633066088d Update index.py 2023-12-17 13:32:39 +08:00
Mr Chen 48f223f4f9 Update index.html 2023-12-16 20:59:29 +08:00
Mr Chen 709a91dcec Update mongodb.js 2023-12-16 17:06:22 +08:00
Mr Chen 2592291b49 update 2023-12-16 17:01:49 +08:00
Mr Chen 502893194e mongo状态 2023-12-16 16:30:34 +08:00
Mr Chen 8976e97ea5 Update mongodb.conf 2023-12-16 15:25:18 +08:00
Mr Chen 22cb5f3bc2 Update config.js 2023-12-15 18:36:20 +08:00
Mr Chen 0888b89ea7 Update config.js 2023-12-15 18:36:14 +08:00
Mr Chen 738e69562e Update config.js 2023-12-15 18:35:54 +08:00
Mr Chen 511b62d911 Merge pull request #516 from midoks/dev
mysql8.2及密码生成加强
2023-12-15 14:49:43 +08:00
Mr Chen d748674b49 Update public.js 2023-12-15 14:48:54 +08:00
Mr Chen 828372f16f Update public.js 2023-12-15 14:47:52 +08:00
Mr Chen a349b2bc81 Update install.sh 2023-12-14 14:00:31 +08:00
Mr Chen 4f3fe2af54 Update index.py 2023-12-14 13:59:08 +08:00
Mr Chen 4670811fd6 Create my8.2.cnf 2023-12-14 13:33:04 +08:00
Mr Chen e1fb85859a Update install.sh 2023-12-14 01:01:21 +08:00
Mr Chen c0fc1148eb Update install.sh 2023-12-14 01:01:01 +08:00
Mr Chen 50052e7650 Update install.sh 2023-12-14 00:58:02 +08:00
Mr Chen 8053f9b593 Update install.sh 2023-12-14 00:30:58 +08:00
Mr Chen 1a5cdca70d Update mysql.js 2023-12-14 00:22:27 +08:00
Mr Chen 341690d234 Update mysql.js 2023-12-14 00:20:24 +08:00
Mr Chen d76654b853 Update mysql.js 2023-12-14 00:17:37 +08:00
Mr Chen 0ef35e1474 Update mysql.js 2023-12-14 00:12:56 +08:00
Mr Chen 9ea52e452a mysql识别登录加密规则 2023-12-14 00:04:48 +08:00
Mr Chen 5e39e1a463 Update my8.0.cnf 2023-12-13 23:54:39 +08:00
Mr Chen 36421ae254 update 2023-12-13 23:51:18 +08:00
Mr Chen a34f025a36 Update index.py 2023-12-13 23:33:25 +08:00
Mr Chen 7be4f9ea98 Update index.py 2023-12-13 23:32:59 +08:00
Mr Chen 2dc93bf490 Update my8.0.cnf 2023-12-13 23:27:18 +08:00
Mr Chen 73fb46fcc0 Merge pull request #515 from midoks/dev
mongodb配置优化
2023-12-12 14:54:49 +08:00
Mr Chen f4ea1dc544 Update index.py 2023-12-12 14:51:47 +08:00
Mr Chen d17cc990fe Update index.py 2023-12-12 14:44:39 +08:00
Mr Chen 8edd40393b Update index.py 2023-12-12 14:44:23 +08:00
Mr Chen 98e653710c Update index.py 2023-12-12 14:43:49 +08:00
Mr Chen 3eb6937778 Update layout.html 2023-12-12 13:22:31 +08:00
Mr Chen 974eaf3583 Merge branch 'master' into dev 2023-12-11 23:32:27 +08:00
Mr Chen dadcc2df6d Merge pull request #514 from midoks/dev
部分更新
2023-12-11 23:32:14 +08:00
Mr Chen 639d5413e5 up 2023-12-11 23:20:34 +08:00
Mr Chen 1d114d9db7 Update cmd.md 2023-12-09 15:59:36 +08:00
Mr Chen dfa669a032 Update cmd.md 2023-12-09 15:58:57 +08:00
Mr Chen bf370685b3 Update install.sh 2023-12-07 13:27:46 +08:00
Mr Chen 8f9bdde0a1 Update info.json 2023-12-06 21:10:32 +08:00
Mr Chen dbbc32258a Create install.sh 2023-12-06 21:09:56 +08:00
Mr Chen bf79e3028a Merge pull request #513 from midoks/dev
地址更新
2023-12-05 13:08:47 +08:00
Mr Chen 0650858824 update 2023-12-05 13:07:56 +08:00
Mr Chen 83f736d5b2 Update install.sh 2023-12-05 13:06:59 +08:00
Mr Chen bafee3782a Merge pull request #512 from midoks/dev
地址更新
2023-12-04 16:24:36 +08:00
Mr Chen 1aff003ba3 Update mw.tpl 2023-12-04 16:23:54 +08:00
Mr Chen 30e779686a Merge pull request #511 from midoks/dev
域名更改
2023-12-04 13:19:24 +08:00
Mr Chen 15eccc72f3 Update README.md 2023-12-04 13:18:46 +08:00
Mr Chen f69691fac7 Update plugins_api.py 2023-12-04 00:13:41 +08:00
Mr Chen 1ffcb9ca7d 站点-优化提示 2023-12-04 00:10:03 +08:00
Mr Chen 75514f8e5c update 2023-12-03 03:15:13 +08:00
Mr Chen 098be84816 Update push_bbs_ntid.py 2023-12-03 03:14:19 +08:00
Mr Chen 8752e394a3 Update mw.py 2023-12-03 01:23:18 +08:00
Mr Chen 0350f3ecbb Update mw.py 2023-12-03 01:17:50 +08:00
Mr Chen 3c855afc43 Merge pull request #510 from midoks/dev
简单更新
2023-12-03 00:31:34 +08:00
Mr Chen 0c8ec2132f Update README.md 2023-12-03 00:30:43 +08:00
Mr Chen e3deac06b4 Update README.md 2023-12-03 00:30:09 +08:00
Mr Chen b92dbea2c8 update 2023-12-01 12:09:20 +08:00
Mr Chen 4da6738909 Merge pull request #509 from midoks/dev
换自建域名
2023-12-01 11:44:12 +08:00
Mr Chen 1665256627 换自建域名 2023-12-01 11:43:31 +08:00
Mr Chen d49ebe9fa8 Update index.py 2023-11-29 00:35:51 +08:00
Mr Chen 6dbdf26d80 Update index.py 2023-11-28 17:33:02 +08:00
Mr Chen 114ed15c02 Update supervisor.service 2023-11-28 12:49:56 +08:00
Mr Chen 315eb82a89 Update index.py 2023-11-28 12:46:23 +08:00
Mr Chen f4ef03304d Update install.sh 2023-11-28 12:28:04 +08:00
Mr Chen 9877d04979 查看日志优化 2023-11-25 22:09:17 +08:00
Mr Chen e6f379db9d Merge pull request #507 from midoks/dev
php83正式版发布
2023-11-24 17:01:00 +08:00
Mr Chen ecad324fc6 Update install.sh 2023-11-24 16:27:45 +08:00
Mr Chen ed13ee1645 Update install.sh 2023-11-24 16:26:33 +08:00
Mr Chen 603c436f4e Update commit.tpl 2023-11-23 19:33:01 +08:00
Mr Chen d917c23fda Update webstats_common.lua 2023-11-21 22:17:01 +08:00
Mr Chen a0c4273280 Update webstats_common.lua 2023-11-21 21:59:24 +08:00
Mr Chen 8e71d0a306 Update webstats_common.lua 2023-11-21 19:08:39 +08:00
Mr Chen 01dfb6f248 Merge pull request #506 from midoks/dev
命令行开启ipv6支持
2023-11-21 00:44:34 +08:00
Mr Chen 4ab1d14ffe update 2023-11-21 00:43:38 +08:00
Mr Chen 665fe41014 Update tool_migrate.py 2023-11-20 23:51:12 +08:00
Mr Chen ddba4f3abe Update tool_migrate.py 2023-11-20 23:43:18 +08:00
Mr Chen 1f65f80bef Update webstats_common.lua 2023-11-20 23:40:07 +08:00
Mr Chen 8dd9f707a6 命令行开启ip支持 2023-11-20 20:57:53 +08:00
Mr Chen 14437611c8 Merge pull request #505 from midoks/dev
增加php扩展
2023-11-20 01:01:13 +08:00
Mr Chen bfe857ee59 Update install.sh 2023-11-19 22:00:53 +08:00
Mr Chen 01efa67bf1 Merge branch 'master' of https://github.com/midoks/mdserver-web 2023-11-19 21:38:07 +08:00
Mr Chen 3b3356d5c6 update 2023-11-19 21:37:41 +08:00
Mr Chen 6dbfd385fb Update readline.sh 2023-11-19 21:34:35 +08:00
Mr Chen 1e9fa587f5 Update all_test.sh 2023-11-19 21:34:30 +08:00
Mr Chen fd673b76e8 Update phplib.conf 2023-11-19 21:34:07 +08:00
Mr Chen d2340872c0 Update libedit.sh 2023-11-19 21:05:46 +08:00
Mr Chen 1c14566b6c Update readline.sh 2023-11-19 21:03:49 +08:00
Mr Chen adde0086aa Create libedit.sh 2023-11-19 21:02:31 +08:00
Mr Chen b6ca99f1ef Update libiconv.sh 2023-11-19 20:50:16 +08:00
Mr Chen c920b46a13 Update readline.sh 2023-11-19 20:37:30 +08:00
Mr Chen 338e64d295 Update event.sh 2023-11-19 20:34:08 +08:00
Mr Chen f030f7a97d event 2023-11-19 20:33:19 +08:00
Mr Chen ef7da2ec96 update 2023-11-19 20:30:47 +08:00
Mr Chen 6dec09741f Update maccms.conf 2023-11-19 19:26:03 +08:00
Mr Chen 6d75a65a09 Update maccms.conf 2023-11-19 17:38:23 +08:00
Mr Chen 8eeb55d555 Update maccms.conf 2023-11-19 17:32:53 +08:00
Mr Chen f54feaa87b Update maccms.conf 2023-11-19 17:29:50 +08:00
Mr Chen b828fc2188 Update maccms.conf 2023-11-19 17:23:22 +08:00
Mr Chen e645be4285 Update maccms.conf 2023-11-19 17:18:01 +08:00
Mr Chen 05a7b8818e Update maccms.conf 2023-11-19 17:10:53 +08:00
Mr Chen 391b313a65 Update maccms.conf 2023-11-19 17:06:13 +08:00
Mr Chen df7bff4a72 Update maccms.conf 2023-11-19 17:04:10 +08:00
Mr Chen 2eefd7d3fa Update maccms.conf 2023-11-19 16:58:15 +08:00
Mr Chen 130e4cf546 Update maccms.conf 2023-11-19 16:55:05 +08:00
Mr Chen 096dfa6b96 Create maccms.conf 2023-11-19 16:54:36 +08:00
Mr Chen 77361259c3 Update install.sh 2023-11-19 16:10:22 +08:00
Mr Chen cf00bd3d98 Merge pull request #504 from midoks/dev
0.16.2
2023-11-18 22:55:14 +08:00
Mr Chen ad3f42059d Update config_api.py 2023-11-18 22:54:08 +08:00
Mr Chen 9a1d3f5e15 Update README.md 2023-11-18 22:53:06 +08:00
Mr Chen f2246cf8ba Update index.py 2023-11-18 20:46:11 +08:00
Mr Chen 81aabd3910 Update index.py 2023-11-18 20:44:51 +08:00
Mr Chen 235b1dc5e4 Update install.sh 2023-11-18 20:43:39 +08:00
Mr Chen ad007b07a5 Update haproxy.conf 2023-11-18 20:40:54 +08:00
Mr Chen 53cc020108 Update install.sh 2023-11-18 20:36:34 +08:00
Mr Chen 71d63f3d68 Update install.sh 2023-11-18 20:34:44 +08:00
Mr Chen 917b3f6099 Update default.tpl 2023-11-18 20:29:49 +08:00
Mr Chen 36341f66f1 Update haproxy.conf 2023-11-18 20:29:32 +08:00
Mr Chen 2a16e1d262 安装优化 2023-11-18 20:28:17 +08:00
Mr Chen d27db369dc Update public.js 2023-11-18 20:16:03 +08:00
Mr Chen 6619ae0bc5 haproxy 配置检查 2023-11-18 20:13:39 +08:00
Mr Chen da1646eaed Update info.json 2023-11-18 19:37:14 +08:00
Mr Chen bf88621629 Create keepalived.lvs.nat.master.conf 2023-11-18 18:07:19 +08:00
Mr Chen 7497c4608a Update install.sh 2023-11-18 17:34:15 +08:00
Mr Chen b0ee844b84 Update lvs.js 2023-11-18 17:32:43 +08:00
Mr Chen 3efa46ce70 Update lvs.js 2023-11-18 17:32:29 +08:00
Mr Chen aaaef570a4 Update default.tpl 2023-11-18 17:28:51 +08:00
Mr Chen 53c651724a update 2023-11-18 17:28:11 +08:00
Mr Chen dd8c97f4b8 update 2023-11-18 17:17:55 +08:00
Mr Chen b4e1a5947e Update install.sh 2023-11-18 17:14:49 +08:00
Mr Chen 784056d465 Update install.sh 2023-11-18 17:10:47 +08:00
Mr Chen b1fbdf8d60 Update mw.tpl 2023-11-18 17:08:59 +08:00
Mr Chen f9459089a4 Update mw.tpl 2023-11-18 17:08:46 +08:00
Mr Chen 36c3967e38 Update push_notice_msg.py 2023-11-18 16:25:31 +08:00
Mr Chen c7ba5fa2d9 Update push_ad.py 2023-11-18 16:25:07 +08:00
Mr Chen 5f2f6d15ed Update linux.conf 2023-11-18 16:20:49 +08:00
Mr Chen 5e3c81d785 update 2023-11-18 15:54:40 +08:00
Mr Chen 76560bc4fd Update info.json 2023-11-18 15:27:34 +08:00
Mr Chen e84a104584 Update webstats_common.lua 2023-11-18 12:45:29 +08:00
Mr Chen afe7175941 Update webstats_common.lua 2023-11-18 04:32:35 +08:00
Mr Chen 4b7c821a91 Update index.py 2023-11-18 03:39:53 +08:00
Mr Chen 1941479092 Update index.py 2023-11-18 03:37:41 +08:00
Mr Chen bfcfc2015a Update index.py 2023-11-18 03:36:13 +08:00
Mr Chen 8a5daeb327 网站统计-加入耗时搜索 2023-11-18 03:32:39 +08:00
Mr Chen 66049068aa Update webstats_common.lua 2023-11-18 02:40:03 +08:00
Mr Chen e2d680cb2a 修复反向代理代过来的数据 2023-11-18 02:36:18 +08:00
Mr Chen 719eec4b98 Update install.sh 2023-11-18 01:51:25 +08:00
Mr Chen 9ea859f94c Update install.sh 2023-11-18 01:51:11 +08:00
Mr Chen 0bdd384f46 Update install.sh 2023-11-18 01:50:21 +08:00
Mr Chen c3d20f358c Update install.sh 2023-11-18 01:04:50 +08:00
Mr Chen 7a6454e126 Update requirements.txt 2023-11-18 00:50:33 +08:00
Mr Chen d683069fef Update info.json 2023-11-17 23:45:41 +08:00
Mr Chen 5e7e7af1a7 update 2023-11-17 23:35:23 +08:00
Mr Chen 5894323eec Update README.md 2023-11-17 23:12:54 +08:00
Mr Chen 1cd4996527 Update linux.conf 2023-11-17 20:58:46 +08:00
Mr Chen 78786a92e9 Update linux.conf 2023-11-17 20:57:41 +08:00
Mr Chen 67d5d3fac5 Update linux.conf 2023-11-17 20:57:26 +08:00
Mr Chen 5caf8f52bc Update index.html 2023-11-17 19:16:58 +08:00
Mr Chen b838caea8b update 2023-11-17 18:56:07 +08:00
Mr Chen 57d4ef5fc9 Update index.py 2023-11-17 18:52:05 +08:00
Mr Chen ca3d8cccc9 Update install.sh 2023-11-17 18:33:39 +08:00
Mr Chen c56aa2efa3 Update install.sh 2023-11-17 18:33:21 +08:00
Mr Chen f41ef634bf Update install.sh 2023-11-17 18:30:41 +08:00
Mr Chen 80e3a73fa4 Update install.sh 2023-11-17 17:54:08 +08:00
Mr Chen c4788c03f9 update 2023-11-17 17:49:42 +08:00
Mr Chen 501012b4e6 初始化lvs插件 2023-11-17 17:40:58 +08:00
Mr Chen e7b927bdef Update keepalived.mysql.note.conf 2023-11-16 20:26:45 +08:00
Mr Chen 9c818b0a5d Update keepalived.conf 2023-11-16 20:03:23 +08:00
Mr Chen 8faf553e1d Update chk.sh 2023-11-16 19:55:18 +08:00
Mr Chen e22f296e38 Update chk.sh 2023-11-16 19:45:43 +08:00
Mr Chen b3deeb5a39 Update config_api.py 2023-11-16 19:39:24 +08:00
Mr Chen 2ddb4e9ef8 Update chk.sh 2023-11-16 19:34:58 +08:00
Mr Chen 74b1d424b9 Update chk_mysql.sh 2023-11-16 19:34:32 +08:00
Mr Chen cd13d0bbe7 update 2023-11-16 19:30:43 +08:00
Mr Chen 5dc97276c1 keepalived 脚本模板 2023-11-16 19:16:14 +08:00
Mr Chen 9da7f04379 Update keepalived.mysql.conf 2023-11-16 18:03:09 +08:00
Mr Chen 0bee208795 update 2023-11-16 18:02:34 +08:00
Mr Chen af660daa30 update 2023-11-16 18:00:53 +08:00
Mr Chen 71a2b43c06 Update mw.tpl 2023-11-16 17:49:21 +08:00
Mr Chen ad644c3cf9 Update chk_mysql.sh 2023-11-16 17:19:35 +08:00
Mr Chen e676790250 update 2023-11-16 17:11:49 +08:00
Mr Chen 135b307a98 update 2023-11-16 16:11:17 +08:00
Mr Chen c95c760aef Update index.py 2023-11-16 16:06:15 +08:00
Mr Chen 60125e6bbb Update keepalived.mysql.note.conf 2023-11-16 16:03:30 +08:00
Mr Chen fbef641839 update 2023-11-16 15:29:21 +08:00
Mr Chen 37431a76b6 update 2023-11-16 03:07:51 +08:00
Mr Chen 49cfeb7a39 mysql config 2023-11-16 00:34:03 +08:00
Mr Chen faf433b77d Update install.sh 2023-11-15 19:58:21 +08:00
Mr Chen d0b70841c2 Update install.sh 2023-11-15 19:58:03 +08:00
Mr Chen bf8a820343 Update install.sh 2023-11-15 19:21:27 +08:00
Mr Chen ae1e2cd972 php-fpm状态展示说明 2023-11-15 16:44:20 +08:00
Mr Chen 46da6c0dd0 php性能调整优化 2023-11-14 01:52:02 +08:00
Mr Chen 1e827944ab update 2023-11-14 01:41:51 +08:00
Mr Chen 09bbd5280d update 2023-11-12 13:15:23 +08:00
Mr Chen 01a887efad sync_binlog
默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。

如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。但是binlog虽然是顺序IO,但是设置sync_binlog=1,多个事务同时提交,同样很大的影响MySQL和IO性能。虽然可以通过group commit的补丁缓解,但是刷新的频率过高对IO的影响也非常大。对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多
2023-11-12 13:12:58 +08:00
Mr Chen aa236bac0b up 2023-11-12 12:45:44 +08:00
Mr Chen bcc1ae3b8f ad 改动 2023-11-12 12:22:34 +08:00
Mr Chen 1acc9a4b76 Update index.py 2023-11-11 16:13:11 +08:00
Mr Chen e1b57621d5 Update index.py 2023-11-11 16:12:46 +08:00
Mr Chen 0f9bd8d387 Update install.sh 2023-11-11 03:17:10 +08:00
Mr Chen 24eb4fe994 没成功,不管了 2023-11-11 01:14:06 +08:00
Mr Chen 7799d3436a php56 ,55 mac m2 ok 2023-11-11 00:47:32 +08:00
Mr Chen f3f1aaa041 php 70 mac m2 ok 2023-11-11 00:32:20 +08:00
Mr Chen d7d907945a php 71 mac m2 ok 2023-11-11 00:28:10 +08:00
Mr Chen 6961ff7996 Update install.sh 2023-11-10 23:34:57 +08:00
Mr Chen 27047cb169 php 54 mac m2 编译 2023-11-10 23:34:08 +08:00
Mr Chen 25f3b5b18d Create pcre.sh 2023-11-10 23:29:36 +08:00
Mr Chen a9efe0f808 update 2023-11-10 21:51:50 +08:00
Mr Chen 847a40e743 Update install.sh 2023-11-10 21:42:05 +08:00
Mr Chen 9f59f479a2 update 2023-11-10 20:18:15 +08:00
Mr Chen c8b955f282 update 2023-11-10 20:03:04 +08:00
Mr Chen b4cee43517 Update macos.sh 2023-11-10 19:29:17 +08:00
Mr Chen a33c1261b3 更好的重启 2023-11-10 19:20:23 +08:00
Mr Chen 8fd3476126 up 2023-11-10 19:06:31 +08:00
Mr Chen 664852c26f update 2023-11-10 18:47:32 +08:00
Mr Chen b356ad5a43 Update index.py 2023-11-10 05:05:49 +08:00
Mr Chen ce96f54aa7 update 2023-11-10 05:01:06 +08:00
Mr Chen 028bfe13ab Update macos.sh 2023-11-10 02:45:21 +08:00
Mr Chen 93061a1138 Update macos.sh 2023-11-10 02:26:40 +08:00
Mr Chen 66f0b8691c 群集创建说明 2023-11-10 01:45:27 +08:00
Mr Chen 22ac89bc2c 集群节点暂时 2023-11-10 00:13:32 +08:00
Mr Chen 4edf9c1bb7 Update redis.tpl 2023-11-09 22:52:59 +08:00
Mr Chen 8169f89ddb Update redis.js 2023-11-09 22:31:47 +08:00
Mr Chen 8c82641cb0 Update index.py 2023-11-09 22:26:48 +08:00
Mr Chen 5e5606a586 Update redis.js 2023-11-09 22:26:24 +08:00
Mr Chen d4d0538996 集群状态 2023-11-09 22:18:37 +08:00
Mr Chen d03c630b48 Update index.py 2023-11-09 21:40:09 +08:00
Mr Chen 698b5c2623 up 2023-11-09 21:00:42 +08:00
Mr Chen c9817cb1c6 Create redis_simple.conf 2023-11-09 21:00:23 +08:00
Mr Chen 76d2acac76 Update redis.js 2023-11-09 20:54:53 +08:00
Mr Chen feb58ca3ad Update redis.js 2023-11-09 20:50:51 +08:00
Mr Chen 2748d248b4 Update redis.js 2023-11-09 20:49:13 +08:00
Mr Chen e008de3d2c redis集群配置 2023-11-09 20:45:00 +08:00
Mr Chen 57c9ca8e78 Update redis.js 2023-11-09 19:43:27 +08:00
Mr Chen db90443239 Update redis.js 2023-11-09 19:41:42 +08:00
Mr Chen 883ce06c1c Update redis.js 2023-11-09 19:26:50 +08:00
Mr Chen 9c9b0b9ae5 redis 复制状态 2023-11-09 15:08:45 +08:00
Mr Chen dd8341867f Update install.sh 2023-11-09 13:11:20 +08:00
Mr Chen 15e6ca97e1 redis 主从配置识别 2023-11-09 03:33:07 +08:00
Mr Chen 1996cb03ce 兼容新版mac 2023-11-09 01:32:59 +08:00
Mr Chen 7d0834397d Update haproxy.conf 2023-11-08 17:58:46 +08:00
Mr Chen 54055f2174 Update install.sh 2023-11-08 16:47:30 +08:00
Mr Chen 33c77f0e90 Update mw.tpl 2023-11-08 16:19:49 +08:00
Mr Chen 7d4c4a9ef9 mac优化 2023-11-08 15:55:53 +08:00
Mr Chen fbe211b3ec update 2023-11-08 15:28:52 +08:00
Mr Chen 53e98bd5fe Update macos.sh 2023-11-08 12:12:16 +08:00
Mr Chen 8a7be7e61c mac 不判断root 2023-11-08 11:59:28 +08:00
Mr Chen 4aad9f90db mac 不判断root 2023-11-08 11:58:50 +08:00
Mr Chen 29de642a1a Merge pull request #503 from midoks/dev
mysql binlog日志查看功能及同步12306错误,尝试修复功能。
2023-11-08 02:14:07 +08:00
midoks e73533b611 Update mysql.js 2023-11-08 02:04:14 +08:00
midoks 89e5d57926 Update index.py 2023-11-08 01:58:45 +08:00
midoks 283d3c5f1f Update index.py 2023-11-08 01:57:27 +08:00
midoks 69cde4ebc3 Update index_mysql.py 2023-11-08 01:56:55 +08:00
midoks e5a9f2c197 Update index_mysql.py 2023-11-08 01:52:49 +08:00
midoks b3f495efb8 Update index.py 2023-11-08 01:49:44 +08:00
midoks c0310a2628 binlog日志功能基本OK 2023-11-08 01:44:17 +08:00
midoks 496e94ad54 Update mysql.js 2023-11-08 01:16:55 +08:00
midoks beb00d46e0 update 2023-11-08 01:15:28 +08:00
midoks 9e123f067b update 2023-11-08 01:12:02 +08:00
midoks aba594caf2 update 2023-11-08 01:00:29 +08:00
midoks f67be6d59f update 2023-11-08 00:49:01 +08:00
midoks bb5240dc43 Update ubuntu.sh 2023-11-07 19:42:02 +08:00
midoks e24bf5313c Update debian.sh 2023-11-07 19:41:29 +08:00
midoks f17a986461 mysql 同步1236错误-修复方案 2023-11-07 18:55:44 +08:00
midoks 2c31318a5c Update index.py 2023-11-07 18:06:09 +08:00
midoks 7c4231d9c0 Update debian.sh 2023-11-07 16:36:16 +08:00
midoks 462f7b78ec Update tool_task.py 2023-11-07 12:17:04 +08:00
midoks 83466e927e update 2023-11-06 18:29:20 +08:00
midoks d8123d9350 Update install.sh 2023-11-05 19:57:14 +08:00
Mr Chen 23c3b553e9 Merge pull request #501 from midoks/dev
php扩展ioncube修复。
2023-11-05 19:32:05 +08:00
midoks 9c2129e638 Update phplib.conf 2023-11-05 19:05:40 +08:00
midoks a29b2ac731 Update phplib.conf 2023-11-05 19:05:08 +08:00
midoks 944040cc03 Update ioncube.sh 2023-11-05 19:00:58 +08:00
midoks 9d9615acc9 Update ioncube.sh 2023-11-05 18:59:15 +08:00
midoks e3f42c8f67 Update ioncube.sh 2023-11-05 18:48:10 +08:00
Mr Chen 6e9dbe4bd5 Merge pull request #500 from midoks/dev
安装减小体积3 && php扩展-yaml
2023-11-03 19:24:09 +08:00
midoks e71329485a yaml依赖 2023-11-03 19:21:50 +08:00
midoks 5d0e24f0d5 php yaml 2023-11-03 19:14:24 +08:00
midoks 78263f6a06 Create yaml.sh 2023-11-03 19:10:52 +08:00
midoks ce70fdc784 Update mw.py 2023-11-01 23:21:45 +08:00
midoks 184610acb9 Update all_test.sh 2023-11-01 02:36:32 +08:00
midoks 1b668d546f 优化 2023-11-01 02:35:36 +08:00
midoks b7df4f57ad update 2023-11-01 02:27:42 +08:00
midoks 817e7607e5 update 2023-11-01 02:16:44 +08:00
midoks d36df7b24c Update gd.sh 2023-11-01 02:15:37 +08:00
Mr Chen e63a643c7b Merge pull request #499 from midoks/dev
安装结束后解压源码删除  2
2023-11-01 02:03:38 +08:00
midoks 0cfd2fc971 update 2023-11-01 01:47:45 +08:00
midoks 9b3383dd0e update 2023-11-01 01:43:05 +08:00
midoks 9b266ffd7d Update yaf.sh 2023-11-01 01:41:19 +08:00
midoks 345a5be488 Update swoole.sh 2023-11-01 01:41:00 +08:00
midoks 0a178f196a up 2023-11-01 00:43:52 +08:00
midoks 8abc166dd2 update 2023-10-31 22:09:22 +08:00
Mr Chen a3e0fe817b Merge pull request #498 from midoks/dev
安装结束后解压源码删除
2023-10-31 21:15:30 +08:00
midoks 7ab4572bdd update 2023-10-31 21:01:21 +08:00
midoks 165f6ee323 update ad 2023-10-31 14:57:25 +08:00
midoks e565390d5b ad 2023-10-31 14:43:06 +08:00
Mr Chen 7502fb7e08 Merge pull request #497 from midoks/dev
暂时不删除php源码。
2023-10-31 03:15:20 +08:00
midoks 026f191de2 update 2023-10-31 03:13:13 +08:00
midoks 6d7b58e65c Update ubuntu.sh 2023-10-31 02:34:54 +08:00
Mr Chen 6953140238 Merge pull request #496 from midoks/dev
php73-gd优化及部分安装删除源码,节省安装体积。
2023-10-31 02:33:22 +08:00
midoks 97963a67aa Update install.sh 2023-10-31 02:29:05 +08:00
midoks 1112e31a5f update 2023-10-31 02:21:57 +08:00
midoks 5358191adf Update install.sh 2023-10-31 02:17:16 +08:00
midoks 4f52e4a520 Update php5.ini 2023-10-31 02:13:14 +08:00
midoks abcabeb2a1 update 2023-10-31 02:08:29 +08:00
midoks c592086d29 u p d da te 2023-10-31 02:00:05 +08:00
midoks f93dd8ebec Update www.conf 2023-10-31 01:59:12 +08:00
midoks 92283d1cfc Update icu.sh 2023-10-31 01:45:41 +08:00
midoks f29b15dd60 update 2023-10-31 01:37:21 +08:00
midoks 84f2d212f4 mongodb 安装后删除文件 2023-10-31 01:34:24 +08:00
midoks 5fb00f7108 Update centos.sh 2023-10-31 01:25:45 +08:00
midoks fcea7a0610 update 2023-10-31 01:25:11 +08:00
midoks f9b364c435 Update debian.sh 2023-10-31 01:14:35 +08:00
midoks e9743ce97e Update centos.sh 2023-10-31 01:13:06 +08:00
midoks 8c2475192b update 2023-10-31 01:05:23 +08:00
midoks 35c279d93a update 2023-10-31 00:59:03 +08:00
midoks 7c5a7fe822 Update install.sh 2023-10-31 00:53:35 +08:00
midoks 09ee8a0c61 Update install.sh 2023-10-31 00:52:48 +08:00
midoks 7bda3c0cd6 安装后,可以删除就删除 2023-10-31 00:50:25 +08:00
midoks d8a5fcab90 Update imagemagick.sh 2023-10-31 00:42:57 +08:00
midoks 1d8bc48a9b Update imagemagick.sh 2023-10-31 00:36:50 +08:00
midoks 2d39f431c5 Update all_test.sh 2023-10-31 00:29:33 +08:00
midoks b78cbb3c39 Update stats.js 2023-10-31 00:06:49 +08:00
midoks d55450e0c9 Update icu.sh 2023-10-30 23:47:23 +08:00
midoks 7cc10a9bdb update 2023-10-30 23:25:33 +08:00
midoks fdebeab6b2 Update phplib.conf 2023-10-30 23:21:58 +08:00
midoks fdc1a93e51 Update install.sh 2023-10-30 23:21:40 +08:00
midoks e9978642c8 Update phplib.conf 2023-10-30 23:14:44 +08:00
midoks 823c6f1f79 update 2023-10-30 23:08:02 +08:00
Mr Chen 7bbb49a459 Merge pull request #495 from midoks/dev
php73-gd优化
2023-10-30 23:01:55 +08:00
midoks 2bbbe3f17f update 2023-10-30 22:55:00 +08:00
midoks 9e8d036ee7 Update debian.sh 2023-10-30 22:43:18 +08:00
midoks 7ee6e491e8 Update install.sh 2023-10-30 20:02:49 +08:00
Mr Chen 10ffa66dd8 Merge pull request #494 from midoks/dev
Gogs/Gitea优化
2023-10-30 17:54:17 +08:00
midoks 85d2f2f702 Update stats.js 2023-10-30 16:34:39 +08:00
midoks 0917ec52de Update index.py 2023-10-30 16:12:53 +08:00
midoks da872c1d92 Update index.py 2023-10-30 16:10:42 +08:00
midoks 91919426f4 Update index.py 2023-10-30 16:06:20 +08:00
midoks 7f7196c55e Update index.py 2023-10-30 16:03:37 +08:00
midoks cb86245a35 Update index.py 2023-10-30 16:02:58 +08:00
midoks a319c43d54 Update index.py 2023-10-30 15:55:27 +08:00
midoks d07faf396e Update index.py 2023-10-30 15:49:56 +08:00
midoks fc718ff727 Update index.html 2023-10-30 15:47:11 +08:00
midoks bacac94186 Update index.py 2023-10-30 15:40:25 +08:00
midoks c925e09ea6 Update index.py 2023-10-30 15:38:42 +08:00
midoks 2de9b736f5 Update gitea.js 2023-10-30 15:36:05 +08:00
midoks 24d3aeabb0 gitea update 2023-10-30 15:34:37 +08:00
midoks 3a33a4c758 Update index.py 2023-10-30 15:04:58 +08:00
midoks 109f562f06 update 2023-10-30 14:47:54 +08:00
midoks f74702cbad Update gogs.js 2023-10-30 14:21:33 +08:00
midoks be9365e4e6 Update gogs.js 2023-10-30 14:11:18 +08:00
midoks 6a61e66c05 Update index.html 2023-10-30 14:07:57 +08:00
midoks 42d07c1cec update 2023-10-30 14:02:10 +08:00
midoks 3886dab6b5 Update index.py 2023-10-30 13:55:42 +08:00
midoks d17ebf1e9c Update index.py 2023-10-30 13:31:18 +08:00
midoks a6644cc706 优化 2023-10-30 01:48:26 +08:00
midoks 43071db317 gogs 基本改造结束 2023-10-30 01:43:35 +08:00
midoks e5c53323a5 gogs 项目管理细化 2023-10-30 01:00:54 +08:00
midoks d08ba45f5f update 2023-10-30 00:25:45 +08:00
midoks eba73c71bc update 2023-10-29 23:50:32 +08:00
midoks fe63f684f3 Update index.py 2023-10-29 14:35:09 +08:00
midoks f19ef94dca update 2023-10-29 14:34:16 +08:00
midoks 685aa7868d update 2023-10-29 14:26:46 +08:00
midoks 2e927da78c update 2023-10-29 03:23:17 +08:00
midoks 4391a3ccd7 Delete .gitignore 2023-10-29 02:01:47 +08:00
midoks 27041ee0e0 Update keepalived.backup.conf 2023-10-29 01:29:24 +08:00
midoks e09085a64c update 2023-10-29 00:48:28 +08:00
midoks 8216000f35 update 2023-10-28 22:47:34 +08:00
midoks 36d59c6c67 Update push_notice_msg.py 2023-10-28 22:41:03 +08:00
midoks 363f97119c update 2023-10-28 22:35:21 +08:00
midoks f86980b805 update 2023-10-28 22:34:14 +08:00
midoks 805b804a10 Update keepalived.conf 2023-10-28 20:02:02 +08:00
midoks 2f22cdb36e Update keepalived.conf 2023-10-28 18:51:24 +08:00
midoks 7254b9b862 update 2023-10-28 18:50:52 +08:00
midoks ad9ab2d7af Update index.html 2023-10-28 18:44:38 +08:00
midoks c8c4a0dbbe Update index.py 2023-10-28 18:43:15 +08:00
midoks f425fb1ea2 Update init.lua 2023-10-28 13:32:45 +08:00
midoks 970c6dbe54 Update init.lua 2023-10-28 13:32:27 +08:00
midoks 3f529ac798 Update index.py 2023-10-24 16:42:04 +08:00
midoks 4be2f60b5b Update index.py 2023-10-24 16:41:25 +08:00
midoks 305b9ca7cf Update install.sh 2023-10-24 16:38:16 +08:00
midoks fdf0c4e02f update 2023-10-24 16:35:58 +08:00
midoks 52dc2210a4 Update keepalived.conf 2023-10-24 16:13:55 +08:00
midoks 579b118495 Update install.sh 2023-10-24 15:46:34 +08:00
midoks 0fac1b026b Update keepalived.conf 2023-10-24 15:25:36 +08:00
midoks a0c891ed92 Update keepalived.conf 2023-10-24 15:25:08 +08:00
midoks 98f3ad52dd Update keepalived.conf 2023-10-24 15:24:36 +08:00
midoks ada1aeac05 Update keepalived.conf 2023-10-24 15:23:26 +08:00
midoks 272d71ed97 update 2023-10-24 15:23:05 +08:00
midoks 1a69d55da1 Update push_notice_msg.py 2023-10-23 19:04:55 +08:00
midoks 8a4174a8a4 Update index_php.py 2023-10-23 17:42:34 +08:00
midoks 7d58ba316d Update index_php.py 2023-10-23 17:42:15 +08:00
midoks d4af727e5a Update index_php.py 2023-10-23 17:41:34 +08:00
midoks 3a8c93b595 update 2023-10-23 17:37:44 +08:00
midoks 25fe2e79bb Update keepalived.js 2023-10-23 16:33:50 +08:00
midoks 84ebfc4254 Update info.json 2023-10-23 16:31:34 +08:00
midoks 2bdba8aa8d Update index.html 2023-10-23 16:25:27 +08:00
midoks 60be806398 Update index.html 2023-10-23 16:25:14 +08:00
midoks b919de1fd6 Update index.html 2023-10-23 16:24:00 +08:00
midoks 087dcc7f40 Update index.html 2023-10-23 16:22:13 +08:00
midoks be2cfa4407 Update index.py 2023-10-23 16:19:42 +08:00
midoks e86707d752 Update index.py 2023-10-23 16:19:17 +08:00
midoks b31c49ac11 update 2023-10-23 16:15:33 +08:00
midoks d013595431 Update index.py 2023-10-23 16:05:42 +08:00
midoks 9e9dad7325 update 2023-10-23 16:03:10 +08:00
midoks 1f52d69410 Update keepalived.tpl 2023-10-23 15:52:03 +08:00
midoks 5a221d9cb3 update 2023-10-22 22:53:42 +08:00
midoks 4abd1df942 Update index.py 2023-10-22 18:12:32 +08:00
midoks ee84266acb Update index.py 2023-10-22 17:55:02 +08:00
midoks 4fadf4c275 Update keepalived.tpl 2023-10-22 17:52:42 +08:00
midoks 89b5a762d1 Update install.sh 2023-10-22 17:48:42 +08:00
midoks 759e1432f8 keepalived debug 2023-10-22 17:45:39 +08:00
midoks d3e9fbb5db update 2023-10-22 17:18:39 +08:00
midoks e3c60de0e7 Update stats.js 2023-10-21 17:42:01 +08:00
Mr Chen 1cd7667f7b Merge pull request #492 from midoks/dev
centos8 mongodb安装优化
2023-10-21 16:30:53 +08:00
midoks d0ac8bd70c Update files.html 2023-10-21 16:29:36 +08:00
midoks 89e20482a0 Update mongodb.service.tpl 2023-10-21 16:23:02 +08:00
midoks 9036d88fab 首页软件列表优化 2023-10-21 16:10:27 +08:00
Mr Chen 919ca8ed83 Merge pull request #491 from midoks/dev
网站统计-增加查询条件
2023-10-21 15:02:38 +08:00
midoks e41055443e Update stats.js 2023-10-21 14:53:59 +08:00
midoks ad15bb303f 网站统计-增加查询条件 2023-10-21 14:41:45 +08:00
Mr Chen a6e0af5672 Merge pull request #490 from midoks/dev
centos8-php-memcached扩展安装优化
2023-10-20 22:59:02 +08:00
midoks dbd3c86970 Update rhel.sh 2023-10-20 22:46:03 +08:00
midoks 7659e654a9 Update all_test.sh 2023-10-20 22:39:48 +08:00
midoks 32c74fd85d Update memcached.sh 2023-10-20 22:32:56 +08:00
midoks 383fd3b068 Update libmemcached.sh 2023-10-20 22:27:10 +08:00
midoks d8aed860a7 Update libmemcached.sh 2023-10-20 22:23:18 +08:00
midoks 68a8751137 Update libmemcached.sh 2023-10-20 22:23:07 +08:00
midoks bb0f0ced62 Update libmemcached.sh 2023-10-20 22:22:17 +08:00
midoks 04ce9541a2 Update libmemcached.sh 2023-10-20 22:18:20 +08:00
midoks 2be2565736 Update memcached.sh 2023-10-20 21:59:08 +08:00
Mr Chen b5776f903f Merge pull request #489 from midoks/dev
php argon2 安装优化
2023-10-20 13:44:37 +08:00
midoks 5052ea11b0 php argon2 安装优化 2023-10-20 13:42:08 +08:00
midoks a578eeef01 Update rhel.sh 2023-10-20 13:15:44 +08:00
midoks d1dcbcb0d6 Update libmemcached.sh 2023-10-20 02:47:22 +08:00
midoks 0916e96448 Update libmemcached.sh 2023-10-20 02:26:06 +08:00
midoks 7616acccb9 Update memcached.sh 2023-10-20 02:22:16 +08:00
midoks 2499c296e7 Update rhel.sh 2023-10-20 01:56:20 +08:00
midoks ceb41fef68 Update index.py 2023-10-20 01:40:38 +08:00
midoks aaaefdb996 Update libsodium.sh 2023-10-20 00:49:46 +08:00
midoks 0bef98d83e Update mongodb.service.tpl 2023-10-19 22:10:18 +08:00
Mr Chen a21ac3fa6c Merge pull request #487 from midoks/dev
mongodb安装优化
2023-10-19 00:37:08 +08:00
midoks de9fdd6e87 Update mongodb.service.tpl 2023-10-19 00:33:23 +08:00
midoks 6991a3ecfc Update index.py 2023-10-19 00:32:06 +08:00
midoks 863b42800b 优化 2023-10-19 00:28:31 +08:00
midoks 3bf83a6202 Update install.sh 2023-10-19 00:07:10 +08:00
midoks ee6e6f8286 Update index.py 2023-10-19 00:05:57 +08:00
midoks 7370ef9816 Update index.py 2023-10-19 00:04:38 +08:00
midoks 8572b93ed0 debian 安装mongodb的bug 2023-10-18 23:51:43 +08:00
Mr Chen 337ba1fa1e Merge pull request #486 from midoks/dev
版本升级
2023-10-18 23:35:15 +08:00
midoks 1ad11de98e 版本升级 2023-10-18 23:34:18 +08:00
midoks a9aaf268fc Update install.sh 2023-10-18 23:31:50 +08:00
midoks d618f36f89 Update install.sh 2023-10-18 23:28:25 +08:00
midoks 929ead12bc Update install.sh 2023-10-18 23:28:06 +08:00
midoks 89991b8417 Update install.sh 2023-10-18 23:24:12 +08:00
midoks af8f9fb1a9 Update index.py 2023-10-18 23:21:49 +08:00
midoks 4a09695343 Update index.py 2023-10-18 23:19:41 +08:00
midoks 5aead0ad7c Update index.py 2023-10-18 23:19:33 +08:00
midoks 8324a89edb Update install.sh 2023-10-18 23:17:21 +08:00
midoks de6ed476fb Update install.sh 2023-10-18 23:13:38 +08:00
midoks 9342e31faf Update install.sh 2023-10-18 23:01:50 +08:00
midoks 061c2d86eb Update install.sh 2023-10-18 22:57:34 +08:00
midoks 1937a6344e php升级版本 2023-10-18 22:54:59 +08:00
midoks 5e91ac8fe9 Update install.sh 2023-10-18 22:49:26 +08:00
midoks ff32ab721f Update info.json 2023-10-18 22:46:10 +08:00
Mr Chen 8d213a2444 Merge pull request #485 from midoks/dev
系统加固提醒
2023-10-18 16:58:08 +08:00
midoks ca10177754 Update crontab_api.py 2023-10-18 16:53:59 +08:00
Mr Chen 7cbabaa04b Merge pull request #484 from midoks/dev
OP防火墙-地区限制优化
2023-10-18 03:15:25 +08:00
midoks 805bd0a3ad Update install.sh 2023-10-18 03:13:46 +08:00
midoks cf003d9f62 Update index.py 2023-10-18 03:12:48 +08:00
midoks 2e22b7307c OP防火墙优化 2023-10-18 03:06:59 +08:00
midoks 4d346dd6c8 Update config.json 2023-10-18 02:28:11 +08:00
midoks 35a7025530 Update init.lua 2023-10-18 02:20:23 +08:00
midoks 9ad51c81d8 Update install.sh 2023-10-18 02:13:44 +08:00
midoks 30da2fe60d Update install.sh 2023-10-18 02:11:16 +08:00
midoks b16ca19ca8 update 2023-10-18 02:02:44 +08:00
Mr Chen 986687b829 Merge pull request #483 from midoks/dev
增加清空python库文件
2023-10-18 01:23:45 +08:00
midoks 0cec515297 Update gd.sh 2023-10-18 01:08:25 +08:00
midoks e54ea53017 Update gd.sh 2023-10-18 01:07:46 +08:00
midoks 755901b4ca Update mw.tpl 2023-10-17 17:23:03 +08:00
midoks 90d0d3ba72 Update mw.tpl 2023-10-17 17:22:20 +08:00
midoks f65a8a24e0 Update init_cmd.py 2023-10-14 02:24:45 +08:00
Mr Chen 2c7d50e3bc Merge pull request #482 from midoks/dev
删除部分AD
2023-10-14 02:21:58 +08:00
midoks 91a71a1eb3 update 2023-10-14 02:21:06 +08:00
Mr Chen 875acda8a5 Merge pull request #481 from midoks/dev
各种小细节的优化
2023-10-14 02:05:59 +08:00
midoks 52e138ae56 Update __init__.py 2023-10-14 02:02:41 +08:00
midoks a769623a24 Merge branch 'master' into dev 2023-10-14 01:56:22 +08:00
midoks d7a4e1d4be Merge branch 'master' into dev 2023-10-14 01:54:58 +08:00
Mr Chen 057e152845 Merge pull request #480 from tsymq-live/master
Update __init__.py
2023-10-14 01:53:40 +08:00
tsymq-live f80ac8e9f0 Update __init__.py
解决gogs webhook 验证失败的问题

需要带上参数post=1来强制使用post
2023-10-14 00:24:11 +08:00
midoks aceb26e309 Update README.md 2023-10-13 21:32:28 +08:00
midoks 1d078a63ca Update index.py 2023-10-13 16:37:23 +08:00
midoks f0ba3d58d6 Update redis.js 2023-10-13 00:52:49 +08:00
midoks 14f2fad644 Update redis.js 2023-10-12 19:43:40 +08:00
midoks 58f0cd69b7 Update files_api.py 2023-10-12 01:47:21 +08:00
midoks 9326138c6e Update files_api.py 2023-10-12 01:46:55 +08:00
midoks ceffb49d61 Update files_api.py 2023-10-12 01:46:32 +08:00
midoks a4e2b2d8b4 Update files_api.py 2023-10-12 01:46:01 +08:00
midoks 1ba42fdc4b Update site_api.py 2023-10-12 01:44:00 +08:00
midoks b0ab2e28cb Update site_api.py 2023-10-12 01:43:09 +08:00
midoks 2471784d1f Update waf_common.lua 2023-10-11 14:48:22 +08:00
Mr Chen 78049fa34f Merge pull request #477 from midoks/dev
php安装的下载文件,md5校验
2023-10-11 02:37:40 +08:00
midoks 09c25924fe php安装的下载文件,md5校验 2023-10-11 02:36:03 +08:00
midoks e8e2487f27 Update install.sh 2023-10-11 02:16:27 +08:00
midoks cf930aeca1 Merge branch 'master' into dev 2023-10-10 23:34:39 +08:00
midoks e6d380c321 Merge branch 'master' into dev 2023-10-10 23:34:11 +08:00
Mr Chen 065b6430f2 Merge pull request #475 from 0honus0/master
修改flask版本过高造成的启动失败
2023-10-10 23:32:44 +08:00
Mr Chen e1c03474eb Merge branch 'master' into master 2023-10-10 23:32:36 +08:00
Mr Chen 3aef5f7bbf Merge pull request #476 from midoks/dev
解决python flask 最新版本影响大部分安装
2023-10-10 23:31:15 +08:00
midoks cebeb7fe90 Update requirements.txt 2023-10-10 23:28:38 +08:00
midoks c5d8166a2a Update mw.tpl 2023-10-10 23:22:46 +08:00
midoks ff30de33ab Update cmd.md 2023-10-10 23:22:02 +08:00
midoks 7700eb92ec Update mw.tpl 2023-10-10 23:21:09 +08:00
midoks 0c8f84e81f Update requirements.txt 2023-10-10 23:18:45 +08:00
midoks 245d026726 Update README.md 2023-10-10 23:13:13 +08:00
midoks 1ac8bf51f2 Update README.md 2023-10-10 23:11:42 +08:00
midoks 248e6b1e0e update 2023-10-10 23:06:27 +08:00
midoks 6ff5d4128b Update README.md 2023-10-10 22:52:25 +08:00
0honus0 82e39f6be4 修改flask版本过高造成的启动失败 2023-10-10 22:39:32 +08:00
Mr Chen 780dfb08a3 Merge pull request #474 from midoks/dev
debian11  python3.9 flask默认安装太高问题解决。
2023-10-10 13:30:53 +08:00
midoks dd586576a7 Create r3.9.txt 2023-10-10 13:26:29 +08:00
Mr Chen c77efccd19 Merge pull request #473 from midoks/dev
mysql初始安装优化
2023-10-09 20:33:52 +08:00
midoks 962b0fa9c5 mysql 优化 2023-10-09 20:32:35 +08:00
midoks 5532dcd968 Update index.py 2023-10-09 18:43:48 +08:00
midoks ce2d060c94 Update .gitignore 2023-10-09 11:40:44 +08:00
Mr Chen 3c388ada21 Merge pull request #471 from midoks/dev
快捷命令说明
2023-10-08 02:03:11 +08:00
midoks c81ddebcd4 Update cmd.md 2023-10-08 02:02:10 +08:00
midoks 9ff01c3cfb Update cmd.md 2023-10-08 02:01:50 +08:00
midoks 6a981e1e8f Update cmd.md 2023-10-08 01:56:51 +08:00
midoks 3643d63a90 Update cmd.md 2023-10-08 01:55:41 +08:00
Mr Chen 8560880944 Merge pull request #470 from midoks/dev
Update mw.tpl
2023-10-08 01:52:55 +08:00
midoks 4210bb87a9 Update mw.tpl 2023-10-08 01:51:52 +08:00
Mr Chen 6473d68421 Merge pull request #469 from midoks/dev
增加命令 mw db 快捷登录数据库
2023-10-08 01:50:17 +08:00
midoks 009b599831 Update mw.tpl 2023-10-08 01:47:35 +08:00
midoks 1c4536980c Update mw.tpl 2023-10-08 00:48:00 +08:00
midoks 9b62a46312 update 2023-10-08 00:46:55 +08:00
midoks bb100b6bf2 Update mw.tpl 2023-10-08 00:42:54 +08:00
midoks 81fba581bd Update mw.tpl 2023-10-08 00:32:21 +08:00
midoks 36cc799c1a Update mw.tpl 2023-10-08 00:31:19 +08:00
midoks 6d64401e22 update 2023-10-08 00:30:35 +08:00
midoks 8e81f423f9 Update mw.tpl 2023-10-08 00:26:47 +08:00
midoks ea4677b2c4 update 2023-10-08 00:26:34 +08:00
midoks 774cf403f1 Update push_ad.py 2023-10-06 17:05:54 +08:00
midoks 3e3e53e58b Update mw.tpl 2023-10-04 21:34:23 +08:00
Mr Chen e0678c8b4c Merge pull request #466 from midoks/dev
gogs同步模板优化
2023-10-04 16:32:13 +08:00
midoks c0bdf2659f Update commit.tpl 2023-10-04 15:57:23 +08:00
midoks ae3cc4bd0b Update commit.tpl 2023-10-04 15:53:59 +08:00
midoks 0f8c9ee740 Update commit.tpl 2023-10-04 15:33:03 +08:00
midoks 4bc4ff5eda Update gogs.js 2023-10-04 15:31:49 +08:00
midoks 7568bd10d8 Update gogs.js 2023-10-04 15:16:38 +08:00
midoks 28410d2bf5 Update gogs.js 2023-10-04 15:16:17 +08:00
midoks c56246a9d7 Update index.py 2023-10-04 15:13:17 +08:00
midoks 5770c6d3c5 Update gogs.js 2023-10-04 15:10:18 +08:00
midoks b9fed0b6e9 Update gogs.js 2023-10-04 14:55:35 +08:00
midoks 899e58500e Update gogs.js 2023-10-04 14:54:40 +08:00
Mr Chen c6a8841a91 Merge pull request #465 from midoks/dev
细节优化2
2023-10-01 23:53:31 +08:00
midoks 40e8393c43 Update mw.tpl 2023-10-01 23:52:41 +08:00
midoks ec3d29fc2b Update install.sh 2023-10-01 21:12:00 +08:00
midoks fba632c393 update 2023-10-01 20:34:27 +08:00
Mr Chen 5dec539d40 Merge pull request #464 from midoks/dev
细节优化
2023-10-01 14:33:43 +08:00
midoks 0119e72771 Update mw.tpl 2023-10-01 14:07:48 +08:00
Mr Chen c1ffb36642 Merge pull request #463 from midoks/dev
增加mosquitto插件
2023-09-30 15:22:52 +08:00
midoks 29d8779233 update
* 增加mosquitto插件。
* redis负载状态读取优化。
2023-09-30 15:21:41 +08:00
midoks 6e9a26c331 Update README.md 2023-09-30 01:39:09 +08:00
midoks e2a491ab97 Update index.py 2023-09-30 01:36:56 +08:00
midoks f1fb16366c Update php.service.tpl 2023-09-30 01:16:49 +08:00
midoks 29ffc62b7c Update index.py 2023-09-30 01:12:02 +08:00
midoks f0d8f12f89 Update README.md 2023-09-29 23:58:37 +08:00
midoks ef36d8729e Update mosquitto.tpl 2023-09-29 23:57:30 +08:00
midoks 28bf685e73 update 2023-09-29 23:45:20 +08:00
midoks 3f424668a7 Update install.sh 2023-09-29 23:39:00 +08:00
midoks dfa53c4c4c Update install.sh 2023-09-29 23:38:13 +08:00
midoks 0b712c7242 Update install.sh 2023-09-29 23:33:59 +08:00
midoks 101792a081 Update mosquitto.js 2023-09-29 23:31:25 +08:00
midoks 0055fa98fa update 2023-09-29 23:23:42 +08:00
midoks 52a8cc6946 Update mosquitto.service.tpl 2023-09-29 23:19:56 +08:00
midoks 3da1ff214f Update mosquitto.service.tpl 2023-09-29 23:16:58 +08:00
midoks ed509e2d8d Update index.py 2023-09-29 23:15:47 +08:00
midoks 5dfc0f7ebb Update index.py 2023-09-29 23:13:41 +08:00
midoks 1129d5753a update 2023-09-29 23:13:07 +08:00
midoks 0c48e0fcbb Update mosquitto.service.tpl 2023-09-29 23:11:02 +08:00
midoks 6a28e72273 Update index.py 2023-09-29 23:02:57 +08:00
midoks 82fc1a3609 Update index.py 2023-09-29 23:01:03 +08:00
midoks 73ff1c664e Update index.py 2023-09-29 22:59:39 +08:00
midoks 9093d4bc3f Update index.py 2023-09-29 22:59:03 +08:00
midoks d50936349c Update index.py 2023-09-29 22:58:20 +08:00
midoks 20d85d0bd7 Update index.py 2023-09-29 22:56:56 +08:00
midoks fc904c9a5d update 2023-09-29 22:54:14 +08:00
midoks 59e616919f mosquitto 初始化 2023-09-29 22:48:38 +08:00
midoks 3447c1e48f Update php.service.tpl 2023-09-29 21:35:31 +08:00
midoks d7c6879d2f Update php.service.tpl 2023-09-29 21:14:49 +08:00
midoks c0240836f7 Update php.service.tpl 2023-09-29 19:53:58 +08:00
midoks 99c6c26859 Update push_ad.py 2023-09-29 14:24:14 +08:00
midoks 7b0e65de42 update 2023-09-28 19:35:39 +08:00
Mr Chen 29c737121b Merge pull request #462 from midoks/dev
网站统计-其他爬虫识别优化
2023-09-27 18:41:19 +08:00
midoks 318d123015 Update webstats_common.lua 2023-09-27 18:36:24 +08:00
midoks 093f8b14f8 Update webstats_common.lua 2023-09-27 18:27:20 +08:00
midoks 2f48df6013 update 2023-09-27 15:22:44 +08:00
Mr Chen 7f42ee741c Merge pull request #461 from midoks/dev
防火墙支持tcp/udp模式
2023-09-26 22:17:36 +08:00
midoks abfb92eaa5 Update README.md 2023-09-26 22:16:32 +08:00
midoks 3f8a822d5e Update index.py 2023-09-26 21:39:32 +08:00
midoks f9bec73252 Update firewall_api.py 2023-09-26 21:35:01 +08:00
midoks a9530b0630 Update firewall_api.py 2023-09-26 21:34:38 +08:00
midoks 33fe1095d7 Update firewall_api.py 2023-09-26 21:32:17 +08:00
midoks ae5a947898 Update index.py 2023-09-26 21:27:03 +08:00
midoks b1128cbddb update 2023-09-26 21:21:42 +08:00
midoks ead8de6e0f update 2023-09-26 20:32:00 +08:00
midoks caf3924b09 Update config_api.py 2023-09-26 20:25:21 +08:00
midoks 526caf0497 Update firewall_api.py 2023-09-26 20:25:03 +08:00
midoks c20dc4af94 Update firewall.js 2023-09-26 20:20:01 +08:00
midoks be500c898e Update firewall_api.py 2023-09-26 20:13:28 +08:00
midoks d2ccea3520 Update firewall_api.py 2023-09-26 20:10:50 +08:00
midoks 051f992e91 Update firewall_api.py 2023-09-26 20:09:41 +08:00
midoks af6b96d18b update 2023-09-26 20:07:11 +08:00
midoks 996786a7b7 update_dev 2023-09-26 19:02:31 +08:00
midoks 42bedca172 调整 - phpMyAdmin默认端口2 2023-09-26 18:00:47 +08:00
midoks 51e3d26492 调整 - phpMyAdmin默认端口 2023-09-26 17:58:38 +08:00
midoks 5ff6ee2763 Update default.sql 2023-09-26 17:49:07 +08:00
midoks 64f0ff8ad9 Update default.sql 2023-09-26 17:39:44 +08:00
midoks 7a6f4323d2 Update default.sql 2023-09-26 17:39:17 +08:00
Mr Chen f927914ff1 Merge pull request #460 from midoks/dev
python gevent 调整
2023-09-26 15:39:01 +08:00
midoks 02ad9c95ee Update requirements.txt 2023-09-26 15:32:59 +08:00
midoks 4d9c102e8b up 2023-09-26 15:28:53 +08:00
midoks ebb53ada1d Update requirements.txt 2023-09-26 15:28:30 +08:00
Mr Chen 87f4307655 Merge pull request #458 from midoks/dev
SSH禁止密码登陆优化
2023-09-25 04:11:56 +08:00
midoks 21cf48b08b Update README.md 2023-09-25 04:11:11 +08:00
midoks dd6d9cf09a Update firewall_api.py 2023-09-25 04:07:47 +08:00
midoks e0e889bbff Update firewall_api.py 2023-09-25 04:01:31 +08:00
midoks 18b36b08a7 Update firewall_api.py 2023-09-25 03:54:37 +08:00
midoks 1389280a70 Update firewall_api.py 2023-09-25 03:54:22 +08:00
midoks 8bc9500b23 Update firewall_api.py 2023-09-25 03:52:54 +08:00
midoks 49a358ccfa Update system_api.py 2023-09-24 00:12:29 +08:00
midoks c9bf5f59f4 Update system_api.py 2023-09-24 00:11:20 +08:00
midoks 577e5f3512 Update system_api.py 2023-09-24 00:06:20 +08:00
Mr Chen 343b815823 Merge pull request #457 from midoks/dev
网站统计安装优化
2023-09-17 23:24:42 +08:00
midoks 3819e2f470 Update install.sh 2023-09-17 23:22:56 +08:00
midoks 0e5f762919 update 2023-09-15 13:28:19 +08:00
midoks e9eab63e99 update 2023-09-15 13:24:19 +08:00
midoks be43b537cc Update install.sh 2023-09-15 13:23:28 +08:00
midoks 6b85710504 Update install_dev.sh 2023-09-15 13:21:53 +08:00
Mr Chen c2d89a91ab Merge pull request #456 from midoks/dev
支持rar解压。
2023-09-15 01:08:21 +08:00
midoks 682f8309c4 支持rar解压 2023-09-15 01:07:29 +08:00
midoks 586302b575 Update config_api.py 2023-09-15 00:59:50 +08:00
midoks 4af7183dbd Update config_api.py 2023-09-15 00:43:01 +08:00
midoks a488f106ca Update files_api.py 2023-09-15 00:37:23 +08:00
midoks f05de84dc2 Update files_api.py 2023-09-15 00:13:05 +08:00
midoks fe4c95276d Update files_api.py 2023-09-15 00:08:13 +08:00
midoks abc6e8f597 支持rar 2023-09-15 00:01:37 +08:00
Mr Chen 0fc03c81db Merge pull request #455 from midoks/dev
unrar&&rar准备
2023-09-14 15:14:39 +08:00
midoks 8a6dbf22c0 加入rar,unrar 2023-09-14 14:21:31 +08:00
midoks 8c18023f64 update 2023-09-14 00:17:01 +08:00
midoks fd521eff3f ad 2023-09-14 00:05:29 +08:00
Mr Chen 55f8e3fd72 Merge pull request #454 from midoks/dev
延长检查时间
2023-09-13 23:18:12 +08:00
midoks 1a26224b6f 延长检查时间 2023-09-13 23:17:16 +08:00
Mr Chen f9ab290d07 Merge pull request #453 from midoks/dev
php83显示&&redis安装优化
2023-09-12 17:22:16 +08:00
midoks 70a30412a5 Update install.sh 2023-09-12 17:00:11 +08:00
midoks ed63341750 Update site_api.py 2023-09-12 16:52:10 +08:00
midoks 81fea53bc7 Update push_notice_msg.py 2023-09-12 16:12:46 +08:00
Mr Chen eab194f5d1 Merge pull request #452 from midoks/dev
update
2023-09-11 13:12:42 +08:00
midoks 0b5299dbe0 update 2023-09-11 13:12:08 +08:00
Mr Chen e5f399e700 Merge pull request #451 from midoks/dev
安装时默认监控开启2
2023-09-11 12:43:57 +08:00
midoks f7ee3a9aed Update common.py 2023-09-11 12:42:27 +08:00
midoks aa60d52662 Update __init__.py 2023-09-11 12:39:16 +08:00
Mr Chen 9249ed7896 Merge pull request #450 from midoks/dev
安装时默认监控开启
2023-09-11 12:25:09 +08:00
midoks a470b3c53c Update common.py 2023-09-11 12:24:27 +08:00
midoks 0851e95fb2 Update common.py 2023-09-11 12:17:08 +08:00
Mr Chen b6f7334f5e Merge pull request #449 from midoks/dev
0.16.1
2023-09-11 11:52:37 +08:00
midoks 27b77f8570 Update push_notice_msg.py 2023-09-10 23:18:13 +08:00
midoks 3d888961bc Update zip.sh 2023-09-10 22:02:43 +08:00
midoks 5edc4fb713 Update install.sh 2023-09-10 21:33:37 +08:00
midoks 214954b298 Update install.sh 2023-09-10 21:29:29 +08:00
midoks 13b0b2752e Update info.json 2023-09-10 21:23:27 +08:00
midoks a2918e651f Update common.py 2023-09-10 14:26:00 +08:00
midoks 55dd1d7d5a update 2023-09-10 14:06:41 +08:00
midoks df50eceeed update 2023-09-10 14:06:19 +08:00
midoks e1de6dd514 Update install_dev.sh 2023-09-10 14:04:13 +08:00
midoks 08328bbb86 Update install_dev.sh 2023-09-10 14:03:53 +08:00
midoks 6abc5b365b Update README.md 2023-09-10 12:37:34 +08:00
midoks 6cc1279729 update 2023-09-10 12:36:23 +08:00
midoks aeafaa2832 update 2023-09-10 12:25:51 +08:00
midoks e74a511763 Update euler.sh 2023-09-10 12:25:01 +08:00
midoks f86159eeac Update README.md 2023-09-10 12:20:02 +08:00
midoks 8097164475 支持华为欧拉系统 2023-09-10 12:19:14 +08:00
midoks 4ebb44e4c0 Update info.json 2023-09-09 22:32:52 +08:00
midoks 584f93461a update 2023-09-09 12:13:16 +08:00
midoks e21f0a53e5 Update update_dev.sh 2023-09-09 11:57:34 +08:00
midoks 1d31a0eae0 Update update.sh 2023-09-09 11:57:15 +08:00
midoks ded33ed6b4 update 2023-09-09 11:55:40 +08:00
midoks b703758d0e update 2023-09-09 11:37:18 +08:00
midoks 33493ac03c up 2023-09-09 11:35:08 +08:00
midoks 74e63c5bbd Update install.sh 2023-09-09 11:33:38 +08:00
midoks f2d34e5551 Update lib.sh 2023-09-09 11:32:02 +08:00
midoks 89c529f44c Update install_dev.sh 2023-09-09 11:28:53 +08:00
midoks 56b728601b MySQL/MYSQL-YUM/MySQL-APT添加重置master功能。
mysql主从同步数据过期时,可使用此命令
2023-09-07 21:17:56 +08:00
midoks bf1d2daeaa Update push_notice_msg.py 2023-09-07 20:37:46 +08:00
midoks cac45b3732 update 2023-09-07 13:36:54 +08:00
midoks ee498b7094 Update install.sh 2023-09-07 13:04:30 +08:00
midoks 385113fe4d Update push_notice_msg.py 2023-09-07 12:58:53 +08:00
midoks 5dbfc5bd51 Update README.md 2023-09-06 19:34:09 +08:00
midoks b76e0f606a Update install.sh 2023-09-06 19:24:25 +08:00
midoks 047702f26d Update debian.sh 2023-09-06 17:48:40 +08:00
midoks eb219caada Update config_api.py 2023-09-04 18:45:49 +08:00
midoks 78b2046f19 Update README.md 2023-09-04 18:45:10 +08:00
Mr Chen 5fe85730e6 Merge pull request #447 from midoks/dev
0.16.1-提前版,合并不release.
2023-09-04 18:44:41 +08:00
midoks adb72ef33b Update config_api.py 2023-09-04 18:40:39 +08:00
midoks d9c8a46031 Update install.sh 2023-09-04 18:35:12 +08:00
midoks 24f520bdc9 Update install.sh 2023-09-04 18:30:40 +08:00
midoks 7492756997 Update install.sh 2023-09-04 18:23:08 +08:00
midoks 616af16635 Update install.sh 2023-09-04 18:15:53 +08:00
midoks 916d39e205 Update install.sh 2023-09-04 18:15:21 +08:00
midoks 017958b6b0 Update install.sh 2023-09-04 18:07:52 +08:00
midoks d403c4c4ad Update opensuse.sh 2023-09-04 17:43:28 +08:00
midoks 9f1481db07 Update mw_api.py 2023-09-04 13:16:42 +08:00
midoks 47e0ec5fae update 2023-09-04 13:14:08 +08:00
midoks a2377d960e 给防盗链增加禁止空来源 2023-09-04 12:47:12 +08:00
midoks 60f1ce2575 update 2023-09-03 00:16:01 +08:00
midoks 0e368f7157 Update index.py 2023-09-03 00:01:20 +08:00
midoks 3cf5c5b190 Update gdriveclient.py 2023-09-02 23:45:33 +08:00
midoks 4ed07beca3 Update gdriveclient.py 2023-09-02 23:43:30 +08:00
midoks cee9619883 update 2023-09-02 23:30:02 +08:00
midoks 5db4a96fc9 Update install.sh 2023-09-02 23:17:38 +08:00
midoks 2e6b7bf5cd Update install.sh 2023-09-02 23:15:52 +08:00
midoks f404caa763 Update install.sh 2023-09-02 22:59:37 +08:00
midoks 062a518492 gdrive云备份开始测试 2023-09-02 22:47:01 +08:00
midoks 0310cab3ae Update msonedrive.js 2023-09-02 21:06:30 +08:00
midoks 4a0b8df57f Update index.html 2023-09-01 16:28:44 +08:00
430 changed files with 25521 additions and 2229 deletions
+2 -2
View File
@@ -110,7 +110,6 @@ tmp/*
*.zip
logs/*
data/*.db
data/control.conf
data/iplist.txt
data/json/index.json
data/json/config.json
@@ -159,11 +158,11 @@ data/unauthorized_status.pl
plugins/vip_*
plugins/own_*
plugins/my_*
plugins/op_auth
plugins/l2tp
plugins/openlitespeed
plugins/tamper_proof
plugins/cryptocurrency_trade
plugins/gdrive
plugins/mtproxy
plugins/zimg
plugins/bk_demo
@@ -172,6 +171,7 @@ plugins/fastdfs
plugins/v2ray
plugins/frp
plugins/file_search
plugins/proxysql
debug.out
+29 -24
View File
@@ -10,7 +10,7 @@
简单的Linux面板,感谢BT.CN写出如此好的web管理软件。我一看到,就知道这是我一直想要的页面化管理方式。
复制了后台管理界面,按照自己想要的方式写了一版。
![EulerOS](https://img.shields.io/badge/LINUX-EulerOS-blue?style=for-the-badge&logo=EulerOS)
![Debian](https://img.shields.io/badge/LINUX-Debian-blue?style=for-the-badge&logo=Debian)
![Ubuntu](https://img.shields.io/badge/LINUX-Ubuntu-blue?style=for-the-badge&logo=Ubuntu)
![Fedora](https://img.shields.io/badge/LINUX-Fedora-blue?style=for-the-badge&logo=Fedora)
@@ -29,7 +29,7 @@
基本上可以使用,后续会继续优化!欢迎提供意见!
- 吹水组 - https://t.me/mdserver_web
- 交流论坛 - https://bbs.midoks.me
- 交流论坛 - https://bbs.midoks.icu
```
如果出现问题,最好私给我面板信息。不要让我猜。如果不提供,不要提出问题,自行解决。 — 座右铭
@@ -37,12 +37,12 @@ Talk is cheap, show me the code. -- linus
```
- [兼容性测试报告](/compatibility.md)
- [常用命令说明](/cmd.md)
- [常用命令说明](/cmd.md) [ mw default ]
### 主要插件介绍
* OpenResty - 轻量级,占有内存少,并发能力强。
* PHP[53-82] - PHP是世界上最好的编程语言。
* PHP[53-83] - PHP是世界上最好的编程语言。
* MySQL - 一种关系数据库管理系统。
* MariaDB - 是MySQL的一个重要分支。
* MySQL[APT/YUM] - 一种关系数据库管理系统。
@@ -66,6 +66,10 @@ Talk is cheap, show me the code. -- linus
- 插件地址 - https://github.com/mw-plugin
- 开发文档 - https://github.com/midoks/mdserver-web/wiki/插件开发
## 其他插件
- OP鉴权 - https://github.com/mw-plugin/op_auth
# Note
@@ -74,13 +78,19 @@ phpMyAdmin[4.4.15]支持MySQL[5.5-5.7]
phpMyAdmin[5.2.0]支持MySQL[8.0]
PHP[53-72]支持phpMyAdmin[4.4.15]
PHP[72-82]支持phpMyAdmin[5.2.0]
PHP[72-83]支持phpMyAdmin[5.2.0]
```
# 郑重声明
不卖、不会监控(统计使用除外)、更不会注入病毒,大家使用方便(望大家不吝捐赠)。
- https://www.youtube.com/watch?v=2taa5K-Jmmw
# 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.pw/)
- [鲲鹏vpn,免费试用,解锁流媒体和chatGPT](https://down.xbjc888.top/?agent_code=github)
# AD - VPS推荐 - 🙏
@@ -92,28 +102,23 @@ PHP[72-82]支持phpMyAdmin[5.2.0]
# Docker
- 由[DDSRem](https://github.com/DDSRem)开发维护。
- https://hub.docker.com/r/ddsderek/mw
- 由[DDS-Derek](https://github.com/DDS-Derek)开发维护。
- https://github.com/DDS-Derek/mdserver-web-Docker
```
docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:443 -p 888:888 ddsderek/mw-server:latest
```
### 版本更新 0.16.0
### 版本更新 0.16.3
yum install -y libargon2-devel
apt install -y libargon2-dev
OP防火墙 - 重载即可
* 增加PHP83。
* 面板日志单独为一页并加入日志审计功能。
* 修复webssh服务器读取问题。
* 站点批量删除修复。
* OP防火墙-修复`自动强制验证`关闭不生效。
* 新增OneDrive备份插件。
* FTP备份优化。
* 面板配置-可以配置时区。
* PHP(GD)扩展安装优化。
* PHP界面功能调整。
* PHP-FPM设置多个应用池(提高高并发稳定性)。
* MySQL(apt/yum)调整优化。
* 网站类型优化。
* 增加数据管理插件。
### JSDelivr安装地址
@@ -141,7 +146,7 @@ wget --no-check-certificate -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/m
```
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/install.sh | bash
curl --insecure -fsSL https://code.midoks.me/midoks/mdserver-web/raw/branch/master/scripts/install.sh | bash
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/master/scripts/install.sh | bash
```
- 直接更新
@@ -178,8 +183,8 @@ wget --no-check-certificate -O uninstall.sh https://raw.githubusercontent.com/mi
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh | bash
curl --insecure -fsSL https://code.midoks.me/midoks/mdserver-web/raw/branch/dev/scripts/install_dev.sh | bash
curl --insecure -fsSL https://code.midoks.me/midoks/mdserver-web/raw/branch/dev/scripts/update_dev.sh | bash
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/install_dev.sh | bash
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/dev/scripts/update_dev.sh | bash
```
### 捐赠地址 USDT(TRC20)
+5
View File
@@ -123,6 +123,11 @@ class cert_api:
return True
def createCertCron(self):
if mw.isAppleSystem():
print('在Macos上不支持创建证书自动续签任务!')
return ''
# 创建证书自动续签任务
try:
import crontab_api
+2 -12
View File
@@ -33,10 +33,10 @@ from flask import redirect
def init():
initDB()
initDBSshPort()
initUserInfo()
initInitD()
initInitTask()
return True
def local():
@@ -63,17 +63,6 @@ def initDB():
print(str(ex))
def initDBSshPort():
# SSH端口必须放开
import firewall_api
cmd_data = mw.execShell(
"cat /etc/ssh/sshd_config | grep '^Port \d*' | tail -1")
ssh_port = cmd_data[0].replace("Port ", '').strip()
if ssh_port == '':
ssh_port = '22'
firewall_api.firewall_api().addAcceptPortArgs(ssh_port, 'SSH远程管理服务', 'port')
def doContentReplace(src, dst):
content = mw.readFile(src)
content = content.replace("{$SERVER_PATH}", mw.getRunDir())
@@ -149,6 +138,7 @@ def initUserInfo():
data = mw.M('users').where('id=?', (1,)).getField('password')
if data == '21232f297a57a5a743894a0e4a801fc3':
pwd = mw.getRandomString(8).lower()
file_pw = mw.getRunDir() + '/data/default.pl'
mw.writeFile(file_pw, pwd)
+17 -1
View File
@@ -20,6 +20,7 @@ import mw
import re
import json
import pwd
import pytz
from flask import session
from flask import request
@@ -27,7 +28,7 @@ from flask import request
class config_api:
__version = '0.16.0'
__version = '0.16.3'
__api_addr = 'data/api.json'
def __init__(self):
@@ -911,6 +912,21 @@ class config_api:
data['status_code_msg'] = "默认-安全入口错误提示"
return data
def getTimezoneListApi(self):
# 获取时区列表
# pytz.all_timezones | 所有
# pytz.common_timezones
return pytz.all_timezones
def setTimezoneApi(self):
# 设置时区列表
timezone = request.form.get('timezone', '').strip()
cmd = 'timedatectl set-timezone "'+timezone+'"'
mw.execShell(cmd)
return mw.returnJson(True, '设置成功!')
def get(self):
data = {}
+3
View File
@@ -283,6 +283,9 @@ class crontab_api:
return mw.returnJson(is_check_pass, msg)
addData = self.add(params)
if type(addData) == str:
return addData
if addData > 0:
return mw.returnJson(True, '添加成功')
return mw.returnJson(False, '添加失败')
+56 -6
View File
@@ -87,6 +87,12 @@ class files_api:
path = request.form.get('path', '')
return self.unzip(sfile, dfile, stype, path)
def uncompressApi(self):
sfile = request.form.get('sfile', '')
dfile = request.form.get('dfile', '')
path = request.form.get('path', '')
return self.uncompress(sfile, dfile, path)
# 移动文件或目录
def mvFileApi(self):
sfile = request.form.get('sfile', '')
@@ -801,7 +807,7 @@ class files_api:
if path.find("web_conf") > 0:
mw.restartWeb()
mw.writeLog('文件管理', '文件保存成功', (path,))
mw.writeLog('文件管理', '文件[{1}]保存成功', (path,))
return mw.returnJson(True, '文件保存成功')
except Exception as ex:
return mw.returnJson(False, '文件保存错误:' + str(ex))
@@ -825,15 +831,59 @@ class files_api:
mw.execShell("cd '" + path + "' && tar -zcvf '" +
dfile + "' " + sfiles + " > " + tmps + " 2>&1")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件压缩成功!', (sfile, dfile))
mw.writeLog("文件管理", '文件[{1}]压缩[{2}]成功!', (sfile, dfile))
return mw.returnJson(True, '文件压缩成功!')
except:
return mw.returnJson(False, '文件压缩失败!')
def unzip(self, sfile, dfile, stype, path):
def uncompress(self, sfile, dfile, path):
if not os.path.exists(sfile):
return mw.returnMsg(False, '指定文件不存在!')
return mw.returnJson(False, '指定文件不存在!')
filename = os.path.basename(sfile)
extension = os.path.splitext(filename)[-1]
extension = extension.strip('.')
tar_gz = 'tar.gz'
tar_gz_len = len(tar_gz)
suffix_gz = sfile[-tar_gz_len:]
if suffix_gz == tar_gz:
extension = suffix_gz
if not extension in ['tar.gz', 'gz', 'zip', 'rar']:
return mw.returnJson(False, '现在仅支持gz,zip,rar格式解压!')
if mw.isAppleSystem() and extension == 'rar':
return mw.returnJson(False, 'macosx暂时不支持rar格式解压')
try:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
if extension == 'zip':
cmd = "cd " + path + " && unzip -o -d '" + dfile + \
"' '" + sfile + "' > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if extension == 'tar.gz':
cmd = "cd " + path + " && tar -zxvf " + sfile + \
" -C " + dfile + " > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if extension == 'gz':
cmd = "cd " + path + " && gunzip -k " + sfile + " > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if extension == 'rar':
cmd = "cd " + path + " && unrar x " + sfile + \
" " + dfile + " > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if os.path.exists(dfile):
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件[{1}]解压[{2}]成功!', (sfile, dfile))
return mw.returnJson(True, '文件解压成功!')
except Exception as e:
return mw.returnJson(False, '文件解压失败!:' + str(e))
def unzip(self, sfile, dfile, stype, path):
if not os.path.exists(sfile):
return mw.returnJson(False, '指定文件不存在!')
try:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
@@ -850,7 +900,7 @@ class files_api:
" -C " + dfile + " > " + tmps + " 2>&1 &")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件解压成功!', (sfile, dfile))
mw.writeLog("文件管理", '文件[{1}]解压[{2}]成功!', (sfile, dfile))
return mw.returnJson(True, '文件解压成功!')
except:
return mw.returnJson(False, '文件解压失败!')
+98 -37
View File
@@ -84,12 +84,13 @@ class firewall_api:
port = request.form.get('port', '').strip()
ps = request.form.get('ps', '').strip()
stype = request.form.get('type', '').strip()
protocol = request.form.get('protocol', '').strip()
data = self.addAcceptPortArgs(port, ps, stype)
data = self.addAcceptPortArgs(port, ps, stype, protocol)
return mw.getJson(data)
# 添加放行端口
def addAcceptPortArgs(self, port, ps, stype):
def addAcceptPortArgs(self, port, ps, stype, protocol='tcp'):
import re
import time
@@ -103,12 +104,13 @@ class firewall_api:
if mw.M('firewall').where("port=?", (port,)).count() > 0:
return mw.returnData(False, '您要放行的端口已存在,无需重复放行!')
msg = mw.getInfo('放行端口[{1}]成功', (port,))
msg = mw.getInfo('放行端口[{1}][{2}]成功', (port, protocol,))
mw.writeLog("防火墙管理", msg)
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
mw.M('firewall').add('port,ps,addtime', (port, ps, addtime))
mw.M('firewall').add('port,protocol,ps,addtime',
(port, protocol, ps, addtime))
self.addAcceptPort(port)
self.addAcceptPort(port, protocol)
self.firewallReload()
return mw.returnData(True, '添加放行(' + port + ')端口成功!')
@@ -139,32 +141,64 @@ class firewall_api:
self.firewallReload()
return mw.returnJson(True, '删除成功!')
# 删除放行端口
def delAcceptPortApi(self):
port = request.form.get('port', '').strip()
sid = request.form.get('id', '').strip()
mw_port = mw.readFile('data/port.pl')
try:
if(port == mw_port):
return mw.returnJson(False, '失败,不能删除当前面板端口!')
if self.__isUfw:
def delAcceptPortArgs(self, port, protocol='tcp'):
if self.__isUfw:
if protocol == 'tcp':
mw.execShell('ufw delete allow ' + port + '/tcp')
elif self.__isFirewalld:
port = port.replace(':', '-')
if protocol == 'udp':
mw.execShell('ufw delete allow ' + port + '/udp')
if protocol == 'tcp/udp':
mw.execShell('ufw delete allow ' + port + '/tcp')
mw.execShell('ufw delete allow ' + port + '/udp')
elif self.__isFirewalld:
port = port.replace(':', '-')
if protocol == 'tcp':
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
if protocol == 'udp':
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
if protocol == 'tcp/udp':
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
elif self.__isIptables:
elif self.__isIptables:
if protocol == 'tcp':
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
else:
pass
msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
mw.writeLog("防火墙管理", msg)
if protocol == 'udp':
mw.execShell(
'iptables -D INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT')
if protocol == 'tcp/udp':
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
mw.execShell(
'iptables -D INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT')
else:
pass
mw.M('firewall').where("port=?", (port,)).delete()
msg = mw.getInfo('删除防火墙放行端口[{1}][{2}]成功!', (port, protocol,))
mw.writeLog("防火墙管理", msg)
self.firewallReload()
return True
# 删除放行端口
def delAcceptPortApi(self):
port = request.form.get('port', '').strip()
protocol = request.form.get('protocol', 'tcp').strip()
sid = request.form.get('id', '').strip()
mw_port = mw.readFile('data/port.pl')
if(port == mw_port):
return mw.returnJson(False, '失败,不能删除当前面板端口!')
try:
self.delAcceptPortArgs(port, protocol)
mw.M('firewall').where("id=?", (sid,)).delete()
self.firewallReload()
return mw.returnJson(True, '删除成功!')
except Exception as e:
return mw.returnJson(False, '删除失败!:' + str(e))
@@ -214,16 +248,13 @@ class firewall_api:
data['pass_prohibit_status'] = False
# 密码登陆配置检查
pass_rep = "#PasswordAuthentication\s+(\w*)\s*\n"
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if pass_status:
data['pass_prohibit_status'] = True
if not data['pass_prohibit_status']:
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if pass_status and pass_status.groups(0)[0].strip() == 'no':
data['pass_prohibit_status'] = True
else:
data['pass_prohibit_status'] = True
data['port'] = port
data['status'] = status
@@ -299,11 +330,17 @@ class firewall_api:
conf = mw.readFile(file)
if status == '1':
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if not pass_status:
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication yes\n", conf)
if status == '1':
rep = "PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication yes\n", conf)
else:
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
rep = "PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication no\n", conf)
mw.writeFile(file, conf)
mw.execShell("systemctl restart sshd.service")
@@ -389,7 +426,7 @@ class firewall_api:
start = (page - 1) * limit
_list = mw.M('firewall').field('id,port,ps,addtime').limit(
_list = mw.M('firewall').field('id,port,protocol,ps,addtime').limit(
str(start) + ',' + str(limit)).order('id desc').select()
data = {}
data['data'] = _list
@@ -403,16 +440,40 @@ class firewall_api:
data['page'] = mw.getPage(_page)
return mw.getJson(data)
def addAcceptPort(self, port):
def addAcceptPort(self, port, protocol='tcp'):
if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp')
if protocol == 'tcp':
mw.execShell('ufw allow ' + port + '/tcp')
if protocol == 'udp':
mw.execShell('ufw allow ' + port + '/udp')
if protocol == 'tcp/udp':
mw.execShell('ufw allow ' + port + '/tcp')
mw.execShell('ufw allow ' + port + '/udp')
elif self.__isFirewalld:
port = port.replace(':', '-')
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
if protocol == 'tcp':
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
if protocol == 'udp':
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/udp'
mw.execShell(cmd)
if protocol == 'tcp/udp':
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/udp'
mw.execShell(cmd)
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
if protocol == 'tcp':
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
if protocol == 'udp':
cmd = 'iptables -I INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
if protocol == 'tcp/udp':
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
cmd = 'iptables -I INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
else:
pass
return True
+3 -1
View File
@@ -77,7 +77,9 @@ class logs_api:
if log_name in ['dmesg'] or log_name.find('dmesg') == 0:
return '内核缓冲区日志'
if log_name in ['syslog'] or log_name.find('syslog') == 0:
return '系统警告/错误日志'
return '系统日志'
if log_name in ['rsyncd.log']:
return '远程同步日志'
if log_name in ['btmp']:
return '失败的登录记录'
if log_name in ['utmp', 'wtmp']:
+21 -3
View File
@@ -394,6 +394,9 @@ def getPageObject(args, result='1,2,3,4,5,8'):
if 'tojs' in args:
info['return_js'] = args['tojs']
if 'args_tpl' in args:
info['args_tpl'] = args['args_tpl']
return (page.GetPage(info, result), page)
@@ -425,13 +428,13 @@ def getFileMd5(filename):
def getRandomString(length):
# 取随机字符串
str = ''
rnd_str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
chrlen = len(chars) - 1
random = Random()
for i in range(length):
str += chars[random.randint(0, chrlen)]
return str
rnd_str += chars[random.randint(0, chrlen)]
return rnd_str
def getUniqueId():
@@ -905,7 +908,22 @@ def aesDecrypt_Crypto(data, key, vi):
text_decrypted = text_decrypted.decode('utf8').rstrip() # 去掉补位的右侧空格
return text_decrypted
def encodeImage(imgsrc, newsrc):
# 图片加密
import struct
old_fp = open(imgsrc, 'rb')
imgFile = old_fp.read()
old_fp.close()
new_fp = open(newsrc,"wb")
for x in imgFile:
value = x ^ 86
value = hex(value)
s = struct.pack('B',int(value,16))
new_fp.write(s)
new_fp.close()
return True
def buildSoftLink(src, dst, force=False):
'''
建立软连接
+14 -6
View File
@@ -39,6 +39,7 @@ class Page():
__RTURN_JS = False # 是否返回JS回调
__START_NUM = None # 起始行
__END_NUM = None # 结束行
__ARGS_TPL = ''
def __init__(self):
if False:
@@ -51,12 +52,19 @@ class Page():
self.__FO = tmp['FO']
self.__LINE = tmp['LINE']
def getPageNum(self, num):
return str(num) + self.__ARGS_TPL
def GetPage(self, pageInfo, limit='1,2,3,4,5,6,7,8'):
# 取分页信息
# @param pageInfo 传入分页参数字典
# @param limit 返回系列
self.__RTURN_JS = pageInfo['return_js']
self.__COUNT_ROW = pageInfo['count']
if 'args_tpl' in pageInfo:
self.__ARGS_TPL = pageInfo['args_tpl']
self.ROW = pageInfo['row']
self.__C_PAGE = self.__GetCpage(pageInfo['p'])
self.__START_NUM = self.__StartRow()
@@ -111,7 +119,7 @@ class Page():
str(self.__COUNT_PAGE) + "'>" + str(self.__END) + "</a>"
else:
endStr = "<a class='Pend' onclick='" + self.__RTURN_JS + \
"(" + str(self.__COUNT_PAGE) + ")'>" + \
"(" + self.getPageNum(self.__COUNT_PAGE) + ")'>" + \
str(self.__END) + "</a>"
return endStr
@@ -126,7 +134,7 @@ class Page():
str(self.__C_PAGE + 1) + "'>" + str(self.__NEXT) + "</a>"
else:
nextStr = "<a class='Pnext' onclick='" + self.__RTURN_JS + \
"(" + str(self.__C_PAGE + 1) + ")'>" + \
"(" + self.getPageNum(self.__C_PAGE + 1) + ")'>" + \
str(self.__NEXT) + "</a>"
return nextStr
@@ -151,7 +159,7 @@ class Page():
"p=" + str(page) + "'>" + str(page) + "</a>"
else:
pages += "<a class='Pnum' onclick='" + self.__RTURN_JS + \
"(" + str(page) + ")'>" + str(page) + "</a>"
"(" + self.getPageNum(page) + ")'>" + str(page) + "</a>"
# 当前页
if self.__C_PAGE > 0:
@@ -174,7 +182,7 @@ class Page():
"p=" + str(page) + "'>" + str(page) + "</a>"
else:
pages += "<a class='Pnum' onclick='" + self.__RTURN_JS + \
"(" + str(page) + ")'>" + str(page) + "</a>"
"(" + self.getPageNum(page) + ")'>" + str(page) + "</a>"
return pages
@@ -189,7 +197,7 @@ class Page():
str(self.__C_PAGE - 1) + "'>" + str(self.__PREV) + "</a>"
else:
startStr = "<a class='Ppren' onclick='" + self.__RTURN_JS + \
"(" + str(self.__C_PAGE - 1) + ")'>" + \
"(" + self.getPageNum(self.__C_PAGE - 1) + ")'>" + \
str(self.__PREV) + "</a>"
return startStr
@@ -204,7 +212,7 @@ class Page():
self.__URI + "p=1'>" + str(self.__START) + "</a>"
else:
startStr = "<a class='Pstart' onclick='" + \
self.__RTURN_JS + "(1)'>" + str(self.__START) + "</a>"
self.__RTURN_JS + "("+self.getPageNum(1)+")'>" + str(self.__START) + "</a>"
return startStr
def __GetCpage(self, p):
+52 -21
View File
@@ -52,6 +52,7 @@ class plugins_api:
__plugin_dir = 'plugins'
__type = 'data/json/type.json'
__index = 'data/json/index.json'
__index_data = None
setupPath = None
def __init__(self):
@@ -60,6 +61,14 @@ class plugins_api:
self.__type = mw.getRunDir() + '/data/json/type.json'
self.__index = mw.getRunDir() + '/data/json/index.json'
self.initIndexData()
def initIndexData(self):
if not os.path.exists(self.__index):
mw.writeFile(self.__index, '[]')
self.__index_data = json.loads(mw.readFile(self.__index))
##### ----- start ----- ###
def listApi(self):
sType = request.args.get('type', '0')
@@ -139,7 +148,7 @@ class plugins_api:
def initApi(self):
plugin_names = {
'openresty': '1.21.4.2',
'openresty': '1.21.4.3',
'php': '56',
'swap': '1.1',
'mysql': '5.7',
@@ -615,20 +624,37 @@ class plugins_api:
return plugins_info
def checkDisplayIndex(self, name, version):
if not os.path.exists(self.__index):
mw.writeFile(self.__index, '[]')
def checkIndexList(self, name, version):
indexList = self.__index_data
for i in indexList:
nv = i.split('-')
if nv[0] == name:
return True
return False
indexList = json.loads(mw.readFile(self.__index))
if type(version) == list:
for index in range(len(version)):
vname = name + '-' + version[index]
def checkDisplayIndex(self, name, version, coexist):
# if not os.path.exists(self.__index):
# mw.writeFile(self.__index, '[]')
# indexList = json.loads(mw.readFile(self.__index))
indexList = self.__index_data
if coexist:
if type(version) == list:
for index in range(len(version)):
vname = name + '-' + version[index]
if vname in indexList:
return True
else:
vname = name + '-' + version
if vname in indexList:
return True
else:
vname = name + '-' + version
if vname in indexList:
return True
if type(version) == list:
for index in range(len(version)):
return self.checkIndexList(name, version)
else:
return self.checkIndexList(name, version)
return False
def getVersion(self, path):
@@ -695,7 +721,7 @@ class plugins_api:
pInfo['task'] = self.checkSetupTask(
pInfo['name'], info['versions'], coexist)
pInfo['display'] = self.checkDisplayIndex(
info['name'], pInfo['versions'])
info['name'], pInfo['versions'], coexist)
pInfo['setup'] = os.path.exists(pInfo['install_checks'])
@@ -800,10 +826,10 @@ class plugins_api:
continue
path = self.__plugin_dir + '/' + dirinfo
if os.path.isdir(path):
json_file = path + '/info.json'
if os.path.exists(json_file):
info_file = path + '/info.json'
if os.path.exists(info_file):
try:
data = json.loads(mw.readFile(json_file))
data = json.loads(mw.readFile(info_file))
# 判断是否搜索
if kw != '' and not self.searchKey(data, kw):
continue
@@ -976,19 +1002,24 @@ class plugins_api:
plugin_name = '-'.join(tmpArr)
plugin_ver = tmp[tmp_len - 1]
json_file = self.__plugin_dir + '/' + plugin_name + '/info.json'
if os.path.exists(json_file):
content = mw.readFile(json_file)
read_json_file = self.__plugin_dir + '/' + plugin_name + '/info.json'
if os.path.exists(read_json_file):
content = mw.readFile(read_json_file)
try:
data = json.loads(content)
data = self.makeList(data)
for index in range(len(data)):
if data[index]['versions'] == plugin_ver or plugin_ver in data[index]['versions']:
if data[index]['coexist']:
if data[index]['versions'] == plugin_ver or plugin_ver in data[index]['versions']:
data[index]['display'] = True
plist.append(data[index])
continue
else:
data[index]['display'] = True
plist.append(data[index])
continue
except Exception as e:
print('getIndexList:', e)
print('getIndexList:', mw.getTracebackInfo())
# 使用gevent模式时,无法使用多进程
# plist = self.checkStatusMProcess(plist)
+68 -21
View File
@@ -105,7 +105,7 @@ class site_api:
start = (int(p) - 1) * (int(limit))
siteM = mw.M('sites').field('id,name,path,status,ps,addtime,edate')
siteM = siteC = mw.M('sites').field('id,name,path,status,ps,addtime,edate,type_id')
sql_where = ''
if search != '':
@@ -113,30 +113,37 @@ class site_api:
if type_id != '' and int(type_id) >= 0 and search != '':
sql_where = sql_where + " and type_id=" + type_id + ""
elif type_id != '' and int(type_id) >= 0:
if type_id != '' and int(type_id) >= 0:
sql_where = " type_id=" + type_id
if sql_where != '':
siteM.where(sql_where)
_list = siteM.limit((str(start)) + ',' +
limit).order('id desc').select()
_list = siteM.limit((str(start)) + ',' +limit).order('id desc').select()
if _list != None:
for i in range(len(_list)):
_list[i]['backup_count'] = mw.M('backup').where(
"pid=? AND type=?", (_list[i]['id'], 0)).count()
_list[i]['backup_count'] = mw.M('backup').where("pid=? AND type=?", (_list[i]['id'], 0)).count()
_ret = {}
_ret['data'] = _list
count = siteM.count()
if sql_where != '':
count = siteC.where(sql_where).count()
else:
count = siteC.count()
_page = {}
_page['count'] = count
_page['tojs'] = 'getWeb'
_page['p'] = p
_page['row'] = limit
page_args_tpl = ''
page_args_tpl += ','+type_id+''
if search != '':
page_args_tpl += ',"'+search+'"'
_page['args_tpl'] = page_args_tpl
_ret['page'] = mw.getPage(_page)
return mw.getJson(_ret)
@@ -973,6 +980,9 @@ class site_api:
siteInfo = mw.M('sites').where(
'name=?', (siteName,)).field('id,name,path').find()
path = self.getSitePath(siteName)
if path == '':
return mw.returnJson(False, '【'+siteName+'】配置文件,异常!')
srcPath = siteInfo['path']
# 检测acme是否安装
@@ -1149,8 +1159,9 @@ class site_api:
domains = request.form.get('domains', '')
status = request.form.get('status', '')
name = request.form.get('name', '')
none = request.form.get('none', '')
sid = request.form.get('id', '')
return self.setSecurity(sid, name, fix, domains, status)
return self.setSecurity(sid, name, fix, domains, status, none)
def getLogsApi(self):
siteName = request.form.get('siteName', '')
@@ -2200,7 +2211,10 @@ location ^~ {from} {\n\
if os.path.exists(file):
conf = mw.readFile(file)
rep = '\s*root\s*(.+);'
path = re.search(rep, conf).groups()[0]
find_cnf = re.search(rep, conf)
if not find_cnf:
return ''
path = find_cnf.groups()[0]
return path
return ''
@@ -2299,9 +2313,15 @@ location ^~ {from} {\n\
def getSitePhpVersion(self, siteName):
conf = mw.readFile(self.getHostConf(siteName))
rep = "enable-php-(.*)\.conf"
tmp = re.search(rep, conf).groups()
find_php_cnf = re.search(rep, conf)
def_pver = '00'
if find_php_cnf:
tmp = find_php_cnf.groups()
def_pver = tmp[0]
data = {}
data['phpversion'] = tmp[0]
data['phpversion'] = def_pver
return mw.getJson(data)
def getIndex(self, sid):
@@ -2430,9 +2450,28 @@ location ^~ {from} {\n\
tmp = re.search(rep, conf).group()
data['fix'] = re.search(
"\(.+\)\$", tmp).group().replace('(', '').replace(')$', '').replace('|', ',')
data['domains'] = ','.join(re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp).groups()[0].split())
data['status'] = True
data['status'] = False
data['none'] = False
valid_referers = re.search(
"valid_referers\s+(.+);\n", tmp)
valid_referers_none = re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp)
if valid_referers or valid_referers_none:
data['status'] = True
if valid_referers_none:
domain_t = valid_referers_none.groups()[0].split()
data['domains'] = ','.join(domain_t)
data['none'] = True
elif valid_referers:
domain_t = valid_referers.groups()[0].split()
data['domains'] = ','.join(domain_t)
data['none'] = False
# print(data)
else:
data['fix'] = 'jpg,jpeg,gif,png,js,css'
domains = mw.M('domain').where(
@@ -2442,19 +2481,27 @@ location ^~ {from} {\n\
tmp.append(domain['name'])
data['domains'] = ','.join(tmp)
data['status'] = False
data['none'] = False
return mw.getJson(data)
def setSecurity(self, sid, name, fix, domains, status):
def setSecurity(self, sid, name, fix, domains, status, none=''):
if len(fix) < 2:
return mw.returnJson(False, 'URL后缀不能为空!')
file = self.getHostConf(name)
if os.path.exists(file):
conf = mw.readFile(file)
if conf.find('SECURITY-START') != -1:
if status == 'false':
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
mw.writeLog('网站管理', '站点[' + name + ']已关闭防盗链设置!')
else:
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
valid_referers = domains.strip().replace(',', ' ')
if none == 'true':
valid_referers = 'none blocked ' + valid_referers
pre_path = self.setupPath + "/php/conf"
re_path = "include\s+" + pre_path + "/enable-php-"
rconf = '''#SECURITY-START 防盗链配置
@@ -2462,13 +2509,13 @@ location ^~ {from} {\n\
{
expires 30d;
access_log /dev/null;
valid_referers none blocked %s;
valid_referers %s;
if ($invalid_referer){
return 404;
}
}
#SECURITY-END
include %s/enable-php-''' % (fix.strip().replace(',', '|'), domains.strip().replace(',', ' '), pre_path)
include %s/enable-php-''' % (fix.strip().replace(',', '|'), valid_referers, pre_path)
conf = re.sub(re_path, rconf, conf)
mw.writeLog('网站管理', '站点[' + name + ']已开启防盗链!')
mw.writeFile(file, conf)
@@ -2477,7 +2524,7 @@ location ^~ {from} {\n\
def getPhpVersion(self):
phpVersions = ('00', '52', '53', '54', '55',
'56', '70', '71', '72', '73', '74', '80', '81', '82')
'56', '70', '71', '72', '73', '74', '80', '81', '82', '83')
data = []
for val in phpVersions:
tmp = {}
@@ -2760,7 +2807,7 @@ location ^~ {from} {\n\
self.saveCert(keyPath, certPath)
msg = mw.getInfo('网站[{}]开启SSL成功!', siteName)
msg = mw.getInfo('网站[{1}]开启SSL成功!', (siteName,))
mw.writeLog('网站管理', msg)
mw.restartWeb()
+25 -8
View File
@@ -273,17 +273,34 @@ class system_api:
title = mw.readFile(titlePl).strip()
return title
def getSystemDeviceTemperature(self):
if not hasattr(psutil, "sensors_temperatures"):
return False, "platform not supported"
temps = psutil.sensors_temperatures()
if not temps:
return False, "can't read any temperature"
for name, entries in temps.items():
for entry in entries:
return True, entry.label
# print("%-20s %s °C (high = %s °C, critical = %s °C)" % (
# entry.label or name, entry.current, entry.high,
# entry.critical))
return False, ""
def getSystemVersion(self):
#
# 取操作系统版本
current_os = mw.getOs()
# sys_temper = self.getSystemDeviceTemperature()
# print(sys_temper)
# mac
if current_os == 'darwin':
data = mw.execShell('sw_vers')[0]
data_list = data.strip().split("\n")
mac_version = ''
for x in data_list:
mac_version += x.split("\t")[1] + ' '
xlist = x.split("\t")
mac_version += xlist[len(xlist)-1] + ' '
arch_ver = mw.execShell("arch")
return mac_version + " (" + arch_ver[0].strip() + ")"
@@ -350,15 +367,15 @@ class system_api:
mem = psutil.virtual_memory()
if mw.getOs() == 'darwin':
memInfo = {
'memTotal': mem.total / 1024 / 1024
'memTotal': mem.total,
}
memInfo['memRealUsed'] = memInfo['memTotal'] * (mem.percent / 100)
else:
memInfo = {
'memTotal': mem.total / 1024 / 1024,
'memFree': mem.free / 1024 / 1024,
'memBuffers': mem.buffers / 1024 / 1024,
'memCached': mem.cached / 1024 / 1024
'memTotal': mem.total,
'memFree': mem.free,
'memBuffers': mem.buffers,
'memCached': mem.cached
}
memInfo['memRealUsed'] = memInfo['memTotal'] - \
@@ -542,9 +559,9 @@ class system_api:
networkInfo['upTotal'] = networkIo[0]
networkInfo['downTotal'] = networkIo[1]
networkInfo['up'] = round(float(
networkIo[0] - session['up']) / 1024 / (ntime - session['otime']), 2)
networkIo[0] - session['up']) / (ntime - session['otime']), 2)
networkInfo['down'] = round(
float(networkIo[1] - session['down']) / 1024 / (ntime - session['otime']), 2)
float(networkIo[1] - session['down']) / (ntime - session['otime']), 2)
networkInfo['downPackets'] = networkIo[3]
networkInfo['upPackets'] = networkIo[2]
+1 -1
View File
@@ -20,7 +20,7 @@ import requests
class vip_api:
api_url = 'https://wo.midoks.me/api/wp-json/vip'
api_url = 'https://wo.midoks.icu/api/wp-json/vip'
def __init__(self):
pass
+5 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
DIR=$(cd "$(dirname "$0")"; pwd)
MDIR=$(dirname "$DIR")
@@ -46,6 +46,10 @@ mw_start(){
mw_start_debug(){
if [ ! -f $DIR/logs/task.log ];then
echo '' > $DIR/logs/task.log
fi
python3 task.py >> $DIR/logs/task.log 2>&1 &
port=7200
if [ -f /www/server/mdserver-web/data/port.pl ];then
+12 -1
View File
@@ -4,7 +4,18 @@
- 面板相关命令
```
/etc/init.d/mw default
/etc/init.d/mw default | 显示登录信息
/etc/init.d/mw db | 快捷连接数据库
----------------------------------------
mw open | 开启面板
mw close | 关闭面板
mw debug | 开发测试
mw venv | 进入虚拟环境
mw mirror | 切换镜像
mw install_app | 快捷安装常用软件
mw update | 更新到正式
mw update_dev | 更新到开发
service mw [start|stop|reload|restart|status]
```
+18 -18
View File
@@ -29,24 +29,24 @@ cd /www/server/mdserver-web/plugins/php/versions && bash all_test.sh
| 系统名称 |PHP53 |PHP54 |PHP55 |PHP56 |PHP70 |PHP71 |PHP72 |PHP73 |PHP74 |PHP80 |PHP81 |PHP82 |
| ----------------- |-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
| CentOS 7.9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 8.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 8 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 9 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 10.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 11.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 12 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 18.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 20.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 22.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Fedora 31 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Fedora 32 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| AlmaLinux 9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| RockyLinux 8.6 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Arch Linux |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| openSUSE 15.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| 系统名称 |PHP53 |PHP54 |PHP55 |PHP56 |PHP70 |PHP71 |PHP72 |PHP73 |PHP74 |PHP80 |PHP81 |PHP82 |PHP83 |
| ----------------- |-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
| CentOS 7.9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 8.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 8 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| CentOS 9 Stream |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 10.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 11.3 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Debian 12 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 18.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 20.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Ubuntu 22.04 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Fedora 31 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Fedora 32 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| AlmaLinux 9 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| RockyLinux 8.6 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| Arch Linux |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
| openSUSE 15.4 |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |✅ |
+1
View File
@@ -0,0 +1 @@
30
+7 -5
View File
@@ -40,14 +40,16 @@ CREATE TABLE IF NOT EXISTS `crontab` (
CREATE TABLE IF NOT EXISTS `firewall` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`port` TEXT,
`protocol` TEXT DEFAULT 'tcp',
`ps` TEXT,
`addtime` TEXT
);
INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES
(1, '80', '网站默认端口', '0000-00-00 00:00:00'),
(2, '443', 'HTTPS', '0000-00-00 00:00:00'),
(3, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
ALTER TABLE `firewall` ADD COLUMN `protocol` TEXT DEFAULT 'tcp';
INSERT INTO `firewall` (`id`, `port`, `protocol`, `ps`, `addtime`) VALUES
(1, '80', 'tcp','网站默认端口', '0000-00-00 00:00:00'),
(2, '443', 'tcp', 'HTTPS', '0000-00-00 00:00:00');
@@ -55,7 +57,7 @@ CREATE TABLE IF NOT EXISTS `logs` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`type` TEXT,
`log` TEXT,
`uid` TEXT,
`uid` INTEGER DEFAULT '1',
`addtime` TEXT
);
ALTER TABLE `logs` ADD COLUMN `uid` INTEGER DEFAULT '1';
+2 -2
View File
@@ -52,8 +52,8 @@ def createBgTask():
removeBgTask()
args = {
"period": "day",
"hour": "2",
"minute": "30",
"hour": "0",
"minute": "15",
}
createBgTaskByName(getPluginName(), args)
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+25
View File
@@ -0,0 +1,25 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('data_query');">服务</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(300);
resetPluginWinWidth(380);
pluginService('data_query', $('.plugin_version').attr('version'));
</script>
+97
View File
@@ -0,0 +1,97 @@
# coding:utf-8
import sys
import io
import os
import time
import re
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'data_query'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
def getArgs():
args = sys.argv[3:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':')
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def status():
return 'start'
def appOp(method):
return 'ok'
def start():
return appOp('start')
def stop():
return appOp('stop')
def restart():
status = appOp('restart')
return status
def reload():
return appOp('reload')
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
else:
print('error')
+36
View File
@@ -0,0 +1,36 @@
{
"hook":[
{
"tag":"menu",
"menu": {
"title":"数据管理",
"name":"data_query",
"path":"static/html/index.html",
"css_path":"static/css/data.css",
"js_path":"static/js/app.js"
}
},
{
"tag":"global_static",
"global_static": {
"title":"数据管理",
"name":"data_query",
"css_path":"static/css/ico.css"
}
}
],
"sort": 7,
"ps": "数据简单管理(memcached,redis,mongodb)",
"name": "data_query",
"title": "数据管理",
"shell": "install.sh",
"versions":"1.0",
"tip": "soft",
"checks": "server/data_query",
"path": "server/data_query",
"display": 1,
"author": "midoks",
"date": "2024-01-22",
"type": 0,
"pid": "2"
}
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/data_query
echo "${VERSION}" > $serverPath/data_query/version.pl
echo '安装完成'
}
Uninstall_App()
{
rm -rf $serverPath/data_query
echo "卸载成功"
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+253
View File
@@ -0,0 +1,253 @@
# coding:utf-8
# https://pypi.org/project/pymemcache/
# https://pymemcache.readthedocs.io/en/latest/getting_started.html#using-a-client-pool
import sys
import io
import os
import time
import re
import json
import pymemcache
sys.path.append(os.getcwd() + "/class/core")
import mw
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class nosqlMemcached():
__DB_PASS = None
__DB_USER = None
__DB_PORT = 11211
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_LOCAL = None
def __init__(self):
self.__config = self.get_options(None)
def conn(self):
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
mem_path = "{}/memcached".format(mw.getServerDir())
if not os.path.exists(mem_path): return False
if not self.__DB_LOCAL:
self.__DB_PORT = int(self.__config['port'])
try:
self.__DB_CONN = pymemcache.client.base.PooledClient((self.__DB_HOST,self.__DB_PORT), max_pool_size=4)
return self.__DB_CONN
except pymemcache.exceptions.MemcacheError:
return False
except Exception:
self.__DB_ERR = mw.getTracebackInfo()
return False
# 获取配置项
def get_options(self, get=None):
result = {}
mem_content = mw.readFile("{}/memcached/memcached.env".format(mw.getServerDir()))
if not mem_content: return False
keys = ["bind", "PORT"]
rep = 'PORT\s*=\s*(.*)'
port_re = re.search(rep, mem_content)
if port_re:
result['port'] = int(port_re.groups()[0].strip())
else:
result['port'] = 11211
return result
def set_host(self, host, port, prefix=''):
self.__DB_HOST = host
self.__DB_PORT = int(port)
self.__DB_PREFIX = prefix
self.__DB_LOCAL = 1
return self
@singleton
class nosqlMemcachedCtr():
def __init__(self):
pass
def getInstanceBySid(self, sid = 0):
instance = nosqlMemcached()
return instance
def getItems(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
result = {}
m_items = mem_instance.stats('items')
item_no = []
for i in m_items:
item_match = b'items:(\d*?):number'
item_match_re = re.search(item_match, i)
if item_match_re:
v = item_match_re.groups()[0].strip()
v_str = v.decode()
if not v_str in item_no:
item_no.append(v_str)
if len(item_no) == 0:
item_no = [0]
result['items'] = item_no
return mw.returnData(True,'ok', result)
def getKeyList(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
p = 1
size = 10
if 'p' in args:
p = args['p']
if 'size' in args:
size = args['size']
item_id = args['item_id']
if item_id == '0':
return mw.returnData(False,'ok')
m_items = mem_instance.stats('items')
item_key = 'items:%s:number' % item_id
item_key_b = item_key.encode("utf-8")
m_items_v = m_items[item_key_b]
start = (p-1)*size
end = start+size
if end > m_items_v:
end = m_items_v
all_key = mem_instance.stats('cachedump', str(item_id) , str(0))
# print(all_key)
all_key_list = []
cur_time_t = time.time()
for k in all_key:
t = {}
t['k'] = k.decode("utf-8")
v = all_key[k].decode("utf-8")
v = v.strip('[').strip(']').split(';')
t['s'] = v[0]
cur_time = v[1].strip().split(' ')[0]
if int(cur_time) != 0 :
t['t'] = int(cur_time) - int(cur_time_t)
else:
t['t'] = 0
all_key_list.append(t)
# print(len(all_key_list))
# print(start,end)
return_all_key = all_key_list[start:end]
for x in range(len(return_all_key)):
v = mem_instance.get(return_all_key[x]['k'])
return_all_key[x]['v'] = v.decode('utf-8')
result = {}
result['list'] = return_all_key
result['p'] = p
page_args = {}
page_args['count'] = len(all_key_list)
page_args['tojs'] = 'memcachedGetKeyList'
page_args['p'] = p
page_args['row'] = size
result['page'] = mw.getPage(page_args)
return mw.returnData(True,'ok', result)
def delVal(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
key = args['key']
mem_instance.delete(key)
return mw.returnData(True,'删除成功!')
def setKv(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
key = args['key']
val = args['val']
endtime = args['endtime']
mem_instance.set(key, val, int(endtime))
return mw.returnData(True,'设置成功!')
def clear(self, args):
sid = args['sid']
mem_instance = self.getInstanceBySid(sid).conn()
if mem_instance is False:
return mw.returnData(False,'无法链接')
mem_instance.flush_all()
return mw.returnData(True,'清空成功!')
# ---------------------------------- run ----------------------------------
# 获取 memcached 列表
def get_items(args):
t = nosqlMemcachedCtr()
return t.getItems(args)
def get_key_list(args):
t = nosqlMemcachedCtr()
return t.getKeyList(args)
def del_val(args):
t = nosqlMemcachedCtr()
return t.delVal(args)
def set_kv(args):
t = nosqlMemcachedCtr()
return t.setKv(args)
def clear(args):
t = nosqlMemcachedCtr()
return t.clear(args)
# 测试
def test(args):
sid = args['sid']
t = nosqlMemcachedCtr()
print(t.get_options())
print("test")
return 'ok'
# ---------------------------------- run ----------------------------------
+254
View File
@@ -0,0 +1,254 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import pymongo
import json
from bson.objectid import ObjectId
from bson.json_util import dumps
sys.path.append(os.getcwd() + "/class/core")
import mw
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class nosqlMongodb():
__DB_PASS = None
__DB_USER = None
__DB_PORT = 6379
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_LOCAL = None
def __init__(self):
self.__config = self.get_options(None)
def mgdb_conn(self):
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
mgdb_path = "{}/mongodb".format(mw.getServerDir())
if not os.path.exists(mgdb_path): return False
if not self.__DB_LOCAL:
self.__DB_PORT = int(self.__config['port'])
# print(self.__DB_HOST,self.__DB_PORT, self.__DB_PASS)
try:
self.__DB_CONN = pymongo.MongoClient(host=self.__DB_HOST, port=self.__DB_PORT, maxPoolSize=10)
self.__DB_CONN.admin.command('ping')
return self.__DB_CONN
except pymongo.errors.ConnectionFailure:
return False
except Exception:
self.__DB_ERR = mw.get_error_info()
return False
# 获取配置项
def get_options(self, get=None):
result = {}
mgdb_content = mw.readFile("{}/mongodb/mongodb.conf".format(mw.getServerDir()))
if not mgdb_content: return False
keys = ["bind_ip", "port"]
result['host'] = '127.0.0.1'
rep = 'port\s*=\s*(.*)'
ip_re = re.search(rep, mgdb_content)
if ip_re:
result['port'] = int(ip_re.groups()[0].strip())
else:
result['port'] = 27017
return result
def set_host(self, host, port, name, username, password, prefix=''):
self.__DB_HOST = host
self.__DB_PORT = int(port)
self.__DB_NAME = name
if self.__DB_NAME: self.__DB_NAME = str(self.__DB_NAME)
self.__DB_USER = str(username)
self._USER = str(username)
self.__DB_PASS = str(password)
self.__DB_PREFIX = prefix
self.__DB_LOCAL = 1
return self
@singleton
class nosqlMongodbCtr():
def __init__(self):
pass
def getInstanceBySid(self, sid = 0):
instance = nosqlMongodb()
return instance
def getDbList(self, args):
sid = args['sid']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
result = {}
doc_list = mgdb_instance.list_database_names()
rlist = []
for x in doc_list:
if not x in ['admin', 'config', 'local']:
rlist.append(x)
result['list'] = rlist
return mw.returnData(True,'ok', result)
def getCollectionsList(self, args):
sid = args['sid']
name = args['name']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
result = {}
collections = mgdb_instance[name].list_collection_names()
result['collections'] = collections
return mw.returnData(True,'ok', result)
def getDataList(self, args):
sid = args['sid']
db = args['db']
collection = args['collection']
p = 1
size = 10
if 'p' in args:
p = args['p']
if 'size' in args:
size = args['size']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
db_instance = mgdb_instance[db]
collection_instance = db_instance[collection]
start_index = (p - 1) * size
end_index = p * size
args_where = args['where']
where = {}
if 'field' in args_where:
mg_field = args_where['field']
if mg_field == '_id':
mg_value = ObjectId(args_where['value'])
where[mg_field] = mg_value
else:
mg_value = args_where['value']
where[mg_field] = re.compile(mg_value)
# print(where)
result = collection_instance.find(where).skip(start_index).limit(size).sort({'_id':-1})
count = collection_instance.count_documents(where)
d = []
for document in result:
d.append(document)
doc_str_json = dumps(d)
result = json.loads(doc_str_json)
page_args = {}
page_args['count'] = count
page_args['tojs'] = 'mongodbDataList'
page_args['p'] = p
page_args['row'] = size
rdata = {}
rdata['page'] = mw.getPage(page_args)
rdata['list'] = result
rdata['count'] = count
rdata['soso_field'] = ''
if 'field' in args_where:
rdata['soso_field'] = args_where['field']
return mw.returnData(True,'ok', rdata)
def delById(self,args):
sid = args['sid']
db = args['db']
collection = args['collection']
mgdb_instance = self.getInstanceBySid(sid).mgdb_conn()
if mgdb_instance is False:
return mw.returnData(False,'无法链接')
db_instance = mgdb_instance[db]
collection_instance = db_instance[collection]
_id = args['_id']
result = collection_instance.delete_one({"_id": ObjectId(_id)})
return mw.returnData(True,'文档删除【%d】个成功!' % result.deleted_count)
# ---------------------------------- run ----------------------------------
# 获取 mongodb databases 列表
def get_db_list(args):
t = nosqlMongodbCtr()
return t.getDbList(args)
# 获取 mongodb collections 列表
def get_collections_list(args):
t = nosqlMongodbCtr()
return t.getCollectionsList(args)
def get_data_list(args):
t = nosqlMongodbCtr()
return t.getDataList(args)
def set_kv(args):
t = nosqlMongodbCtr()
return t.setKv(args)
def del_val(args):
t = nosqlMongodbCtr()
return t.delVal(args)
def batch_del_val(args):
t = nosqlMongodbCtr()
return t.batchDelVal(args)
def clear_flushdb(args):
t = nosqlMongodbCtr()
return t.clearFlushDB(args)
def del_by_id(args):
t = nosqlMongodbCtr()
return t.delById(args)
# 测试
def test(args):
sid = args['sid']
t = nosqlMongodbCtr()
print(t.get_options())
print("test")
return 'ok'
+347
View File
@@ -0,0 +1,347 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import redis
sys.path.append(os.getcwd() + "/class/core")
import mw
# def getPluginName():
# return 'data_query'
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class nosqlRedis():
__DB_PASS = None
__DB_USER = None
__DB_PORT = 6379
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_LOCAL = None
def __init__(self):
self.__config = self.get_options(None)
def redis_conn(self, db_idx=0):
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
redis_path = "{}/redis".format(mw.getServerDir())
if not os.path.exists(redis_path): return False
if not self.__DB_LOCAL:
self.__DB_PASS = self.__config['requirepass']
self.__DB_PORT = int(self.__config['port'])
# print(self.__DB_HOST,self.__DB_PORT, self.__DB_PASS)
try:
redis_pool = redis.ConnectionPool(host=self.__DB_HOST, port=self.__DB_PORT, password=self.__DB_PASS, db=db_idx, socket_timeout=3)
self.__DB_CONN = redis.Redis(connection_pool=redis_pool)
self.__DB_CONN.ping()
return self.__DB_CONN
except redis.exceptions.ConnectionError:
return False
except Exception:
self.__DB_ERR = mw.getTracebackInfo()
return False
# 获取配置项
def get_options(self, get=None):
result = {}
redis_conf = mw.readFile("{}/redis/redis.conf".format(mw.getServerDir()))
if not redis_conf: return False
keys = ["bind", "port", "timeout", "maxclients", "databases", "requirepass", "maxmemory"]
for k in keys:
v = ""
rep = "\n%s\s+(.+)" % k
group = re.search(rep, redis_conf)
if not group:
if k == "maxmemory":
v = "0"
if k == "maxclients":
v = "10000"
if k == "requirepass":
v = ""
else:
if k == "maxmemory":
v = int(group.group(1).strip("mb"))
else:
v = group.group(1)
result[k] = v
return result
def set_host(self, host, port, name, username, password, prefix=''):
self.__DB_HOST = host
self.__DB_PORT = int(port)
self.__DB_NAME = name
if self.__DB_NAME: self.__DB_NAME = str(self.__DB_NAME)
self.__DB_USER = str(username)
self._USER = str(username)
self.__DB_PASS = str(password)
self.__DB_PREFIX = prefix
self.__DB_LOCAL = 1
return self
@singleton
class nosqlRedisCtr():
def __init__(self):
pass
def getInstanceBySid(self, sid = 0):
instance = nosqlRedis()
return instance
def getList(self, args):
sid = args['sid']
redis_instance = self.getInstanceBySid(sid).redis_conn(0)
if redis_instance is False:
return mw.returnData(False,'无法链接')
redis_info = redis_instance.info()
is_cluster = redis_info.get("cluster_enabled", 0)
if is_cluster != 0:
return mw.returnData(False, "当前不支持连接redis集群!")
db_num = 16
if sid != 0:
db_num = 1000
result = []
for x in range(0, db_num):
data = {}
data['id'] = x
data['name'] = 'DB{}'.format(x)
try:
redis_instance = self.getInstanceBySid(sid).redis_conn(x)
data['keynum'] = redis_instance.dbsize()
result.append(data)
except:
break
return mw.returnData(True,'ok', result)
def getDbKeyList(self, args):
p = 1
size = 10
if not 'sid' in args:
return mw.returnData(False, "缺少参数!sid")
if 'p' in args:
p = args['p']
if p < 1:
p = 1
if p > 10:
p = 10
if 'size' in args:
size = args['size']
sid = args['sid']
idx = args['idx']
search = '*'
if 'search' in args and args['search'] != '':
search = args['search']
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
total = redis_instance.dbsize()
if search != '*':
keylist = redis_instance.keys(search)
total = len(keylist)
else:
keys = redis_instance.scan(cursor=0, match="{}".format(search), count=p*size)
keylist = keys[1]
slist = keylist[(p - 1) * size:p*size]
items = []
for key in slist:
item = {}
try:
item['name'] = key.decode()
except Exception as e:
item['name'] = str(key)
item['endtime'] = redis_instance.ttl(key)
item['type'] = redis_instance.type(key).decode()
if item['type'] == 'string':
try:
item['val'] = redis_instance.get(key).decode()
except Exception as e:
item['val'] = str(redis_instance.get(key))
elif item['type'] == 'hash':
if redis_instance.hlen(key) > 500:
item['val'] = "数据量过大无法显示!共 {} 条".format(redis_instance.hlen(key))
else:
item['val'] = str(redis_instance.hgetall(key))
elif item['type'] == 'list':
if redis_instance.llen(key) > 500:
item['val'] = "数据量过大无法显示!共 {} 条".format(redis_instance.llen(key))
else:
item['val'] = str(redis_instance.lrange(key, 0, -1))
elif item['type'] == 'set':
if redis_instance.scard(key) > 500:
item['val'] = "数据量过大无法显示!共 {} 条".format(redis_instance.scard(key))
else:
item['val'] = str(redis_instance.smembers(key))
elif item['type'] == 'zset':
if redis_instance.zcard(key) > 500:
item['val'] = "数据量过大无法显示!共 {} 条".format(redis_instance.zcard(key))
else:
item['val'] = str(redis_instance.zrange(key, 0, -1, withscores=True))
else:
item['val'] = ''
try:
item['len'] = redis_instance.strlen(key)
except:
item['len'] = len(item['val'])
items.append(item)
page_args = {}
page_args['count'] = total
page_args['tojs'] = 'redisGetKeyList'
page_args['p'] = p
page_args['row'] = size
rdata = {}
rdata['page'] = mw.getPage(page_args)
rdata['data'] = items
return mw.returnData(True,'ok',rdata)
def setKv(self,args):
if not 'name' in args:
return mw.returnData(False, "缺少参数!name")
if not 'val' in args:
return mw.returnData(False, "缺少参数!val")
if not 'idx' in args:
return mw.returnData(False, "缺少参数!idx")
sid = args['sid']
idx = args['idx']
name = args["name"]
val = args["val"]
endtime = args["endtime"]
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
return mw.returnData(False,'从库不能写操作!')
if endtime != '0':
redis_instance.set(name, val, int(endtime))
else:
redis_instance.set(name, val)
return mw.returnData(True,'操作成功')
def delVal(self, args):
sid = args['sid']
idx = args['idx']
name = args["name"]
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
return mw.returnData(False,'从库不能删除操作!')
redis_instance.delete(name)
return mw.returnData(True,'操作成功')
def batchDelVal(self, args):
sid = args['sid']
idx = args['idx']
keys = args["keys"]
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
return mw.returnData(False,'从库不能删除操作!')
for k in keys:
redis_instance.delete(k)
return mw.returnData(True,'操作成功')
def clearFlushDB(self, args):
sid = args['sid']
idxs = args['idxs']
for idx in idxs:
redis_instance = self.getInstanceBySid(sid).redis_conn(idx)
redis_info = redis_instance.info()
if redis_info['role'] == 'slave':
return mw.returnData(False,'从库不能清空操作!')
redis_instance.flushdb()
return mw.returnData(True,'操作成功')
# ---------------------------------- run ----------------------------------
# 获取 redis databases 列表
def get_list(args):
t = nosqlRedisCtr()
return t.getList(args)
# 获取 redis key 列表
def get_dbkey_list(args):
t = nosqlRedisCtr()
return t.getDbKeyList(args)
def set_kv(args):
t = nosqlRedisCtr()
return t.setKv(args)
def del_val(args):
t = nosqlRedisCtr()
return t.delVal(args)
def batch_del_val(args):
t = nosqlRedisCtr()
return t.batchDelVal(args)
def clear_flushdb(args):
t = nosqlRedisCtr()
return t.clearFlushDB(args)
# 测试
def test(args):
sid = args['sid']
t = nosqlRedis()
print(t.get_options())
print("test")
return 'ok'
# ---------------------------------- run ----------------------------------
+296
View File
@@ -0,0 +1,296 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import pymongo
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class nosqlMySQL():
__DB_PASS = None
__DB_USER = None
__DB_PORT = 3306
__DB_HOST = '127.0.0.1'
__DB_CONN = None
__DB_ERR = None
__DB_SOCKET = None
__DB_LOCAL = None
def __init__(self):
self.__config = self.get_options(None)
def conn(self):
if self.__DB_HOST in ['127.0.0.1', 'localhost']:
my_path = "{}/mysql".format(mw.getServerDir())
if not os.path.exists(my_path): return False
if not self.__DB_LOCAL:
# print(self.__config)
self.__DB_PORT = int(self.__config['port'])
self.__DB_USER = self.__config['username']
self.__DB_PASS = self.__config['password']
self.__DB_SOCKET = self.__config['socket']
try:
db = mw.getMyORM()
db.setPort(self.__DB_PORT)
db.setPwd(self.__DB_PASS)
db.setUser(self.__DB_USER)
if self.__DB_SOCKET != '':
db.setSocket(self.__DB_SOCKET)
return db
except Exception:
self.__DB_ERR = mw.get_error_info()
return False
def sqliteDb(self,dbname='databases'):
my_root_path = mw.getServerDir() +'/mysql'
name = 'mysql'
conn = mw.M(dbname).dbPos(my_root_path, name)
return conn
# 获取配置项
def get_options(self, get=None):
result = {}
my_cnf_path = "{}/mysql/etc/my.cnf".format(mw.getServerDir())
my_content = mw.readFile(my_cnf_path)
if not my_content: return False
mysql_pass = self.sqliteDb('config').where('id=?', (1,)).getField('mysql_root')
result['password'] = mysql_pass
result['username'] = 'root'
keys = ["bind_ip", "port"]
result['host'] = '127.0.0.1'
rep = 'port\s*=\s*(.*)'
port_re = re.search(rep, my_content)
if port_re:
result['port'] = int(port_re.groups()[0].strip())
else:
result['port'] = 3306
socket_rep = 'socket\s*=\s*(.*)'
socket_re = re.search(socket_rep, my_content)
if socket_re:
result['socket'] = socket_re.groups()[0].strip()
else:
result['socket'] = ''
return result
def set_host(self, host, port, name, username, password, prefix=''):
self.__DB_HOST = host
self.__DB_PORT = int(port)
self.__DB_NAME = name
if self.__DB_NAME: self.__DB_NAME = str(self.__DB_NAME)
self.__DB_USER = str(username)
self._USER = str(username)
self.__DB_PASS = str(password)
self.__DB_PREFIX = prefix
self.__DB_LOCAL = 1
return self
@singleton
class nosqlMySQLCtr():
def __init__(self):
pass
def getInstanceBySid(self, sid = 0):
instance = nosqlMySQL()
return instance
def getDbList(self, args):
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
result = {}
db_list = my_instance.query('show databases')
rlist = []
for x in db_list:
if not x['Database'] in ['information_schema', 'mysql', 'performance_schema','sys']:
rlist.append(x['Database'])
result['list'] = rlist
return mw.returnData(True,'ok', result)
def getTableList(self, args):
sid = args['sid']
db = args['db']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
sql = "select * from information_schema.tables where table_schema = '"+db+"'"
table_list = my_instance.query(sql)
# print(table_list)
rlist = []
for x in table_list:
# print(x['TABLE_NAME'])
rlist.append(x['TABLE_NAME'])
result = {}
result['list'] = rlist
return mw.returnData(True,'ok', result)
def getDataList(self, args):
sid = args['sid']
db = args['db']
table = args['table']
p = 1
size = 10
if 'p' in args:
p = args['p']
if 'size' in args:
size = args['size']
start_index = (p - 1) * size
args_where = {}
where_sql = ''
if 'where' in args:
args_where = args['where']
if 'field' in args_where:
if args_where['field'] == 'id' or args_where['field'].find('id')>-1:
where_sql = ' where '+args_where['field'] + " = '"+args_where['value']+"' "
else:
where_sql = ' where '+args_where['field'] + " like '%"+args_where['value']+"%' "
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
my_instance.setDbName(db)
sql = 'select count(*) as num from ' + table + where_sql
# print(sql)
count_result = my_instance.query(sql)
count = count_result[0]['num']
sql = 'select * from ' + table + where_sql + ' limit '+str(start_index)+',10';
# print(sql)
result = my_instance.query(sql)
# print(result)
page_args = {}
page_args['count'] = count
page_args['tojs'] = 'mysqlGetDataList'
page_args['p'] = p
page_args['row'] = size
rdata = {}
rdata['page'] = mw.getPage(page_args)
rdata['list'] = result
rdata['count'] = count
rdata['soso_field'] = ''
if 'field' in args_where:
rdata['soso_field'] = args_where['field']
return mw.returnData(True,'ok', rdata)
def showProcessList(self,args):
sql = 'show processlist';
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
result = my_instance.query(sql)
rdata = {}
rdata['list'] = result
return mw.returnData(True,'ok', rdata)
def showStatusList(self,args):
sql = 'show status';
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
result = my_instance.query(sql)
rdata = {}
rdata['list'] = result
return mw.returnData(True,'ok', rdata)
def showStatsList(self, args):
sql = "show status like 'Com_%'";
sid = args['sid']
my_instance = self.getInstanceBySid(sid).conn()
if my_instance is False:
return mw.returnData(False,'无法链接')
result = my_instance.query(sql)
rdata = {}
rdata['list'] = result
return mw.returnData(True,'ok', rdata)
# ---------------------------------- run ----------------------------------
# 获取 mysql 列表
def get_db_list(args):
t = nosqlMySQLCtr()
return t.getDbList(args)
# 获取 mysql 列表
def get_table_list(args):
t = nosqlMySQLCtr()
return t.getTableList(args)
def get_data_list(args):
t = nosqlMySQLCtr()
return t.getDataList(args)
def get_proccess_list(args):
t = nosqlMySQLCtr()
return t.showProcessList(args)
def get_status_list(args):
t = nosqlMySQLCtr()
return t.showStatusList(args)
def get_stats_list(args):
t = nosqlMySQLCtr()
return t.showStatsList(args)
# 测试
def test(args):
sid = args['sid']
t = nosqlMySQLCtr()
print(t.get_options())
print("test")
return 'ok'
+48
View File
@@ -0,0 +1,48 @@
.main-content .safe {
position: relative;
}
.mask_layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgb(255 255 255 / 60%);
z-index: 9998;
}
.mask_layer .prompt_description {
width: 350px;
height: 60px;
line-height: 60px;
text-align: center;
position: absolute;
left: 50%;
top: 50%;
margin-top: -25px;
margin-left: -175px;
background: #fff;
box-shadow: 1px 1px 50px rgb(0 0 0 / 30%);
border: 1px solid #eee;
border-radius: 2px;
font-size: 13px;
}
#mongodb_search xm-select {
min-height: 30px;
line-height: 30px;
}
#mongodb_search xm-select .xm-label .xm-label-block{
height: 20px;
line-height: 20px;
}
#mongodb td:last-child, th:last-child {
width: 44px;
position:sticky;
right:0; /* 首行永远固定在左侧 */
z-index:1;
background-color:white;
}
+11
View File
@@ -0,0 +1,11 @@
/* menu start */
.menu .current .menu_plugin_data_query:hover {
background-image: url("/plugins/file?name=data_query&f=ico.png");
}
.menu .menu_plugin_data_query {
background-image: url("/plugins/file?name=data_query&f=ico.png");
}
/* menu end */
+294
View File
@@ -0,0 +1,294 @@
<div class="main-content" style="min-height: 389px;">
<div class="container-fluid" style="padding-bottom: 50px;">
<div id="cutTab" class="pos-box bgw mtb15" style="height:45px">
<div class="tab-list">
<div class="tabs-item active" data-name="redis">Redis</div>
<div class="tabs-item" data-name="mongodb">Mongodb</div>
<div class="tabs-item" data-name="memcached">Memcached</div>
<div class="tabs-item" data-name="mysql">MySQL</div>
</div>
</div>
<div class="bgw mtb15 pd15 tab-view-box firewall-tab-view safe" style="overflow: hidden;">
<div class="mask_layer" style="display:none;">
<div class="prompt_description">当前未安装本地服务器,<a class="btlink install_server" href="/soft">点击安装</a></div>
</div>
<!-- mysql start -->
<!-- show w-full -->
<div class="tab-con hide" id="mysql" style="padding: 0px;">
<div class="col-md-12" style="padding: 0px;overflow: hidden;">
<div class="tootls_group tootls_top">
<div class="pull-left">
<div class="server_list" style="float:left;">
<select name="sid" class="bt-input-text c5 mr5">
<option value="0">本地服务器</option>
</select>
</div>
<div class="mysql_db_list" style="float:left;">
<select name="mysql_db" class="bt-input-text c5 mr5">
<option value="0">数据库空</option>
</select>
</div>
<div class="mysql_table_list" style="float:left;">
<select name="mysql_table" class="bt-input-text c5 mr5">
<option value="0">数据表空</option>
</select>
</div>
<div class="field" style="float:left;">
<select name="mysql_field_key" class="bt-input-text c5 mr5" style="width:80px;">
<option value="0">无字段</option>
</select>
</div>
<div class="value" style="float:left;">
<input name="mysql_field_value" type="text" class="bt-input-text" placeholder="请输入查找内容">
</div>
<button type="button" class="mysql_find btn btn-success btn-sm mr5 ml5" style="float:right;">
<span>查找</span>
</button>
</div>
</div>
<div style="position: relative;">
<div id="mysql_table" class="mysql_table divtable mtb10">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th><span>编号</span></th>
<th><span>操作类型</span></th>
<th><span>详情</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="mysql_list_page page">
<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>
</div>
</div>
<div class="col-md-12" style="padding-left: 3px;">
<div id="mysql_list_tab" style="padding-top:0px;">
<div class="tab-nav">
<span data-name="proccess" class="on">进程</span>
<span data-name="status" class="">状态</span>
<span data-name="stats" class="">统计</span>
</div>
</div>
<div style="position: relative;">
<div id="mysql_ot_table" class="divtable">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th><span>编号</span></th>
<th><span>操作类型</span></th>
<th><span>详情</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- mysql end -->
<!-- mongodb start -->
<!-- show w-full -->
<div class="tab-con hide" id="mongodb" style="padding: 0px;">
<div class="tootls_group tootls_top">
<div class="pull-left">
<div class="field" style="float:left;">
<select name="mongodb_field_key" class="bt-input-text c5 mr5" style="width:80px;">
<option value="0">无字段</option>
</select>
</div>
<div class="value" style="float:left;">
<input name="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>
<div class="pull-right" style="padding-top: 5px;">
<div class="server_list" style="float:left;">
<select name="sid" class="bt-input-text c5 mr5">
<option value="0">本地服务器</option>
</select>
</div>
<div class="db_list" style="float:left;">
<select name="db" class="bt-input-text c5 mr5">
<option value="0">空</option>
</select>
</div>
<div class="search" id="mongodb_search"></div>
</div>
</div>
<div style="position: relative;">
<div id="mongodb_table" class="mongodb_table divtable mtb10">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th><span>编号</span></th>
<th><span>操作类型</span></th>
<th><span>详情</span></th>
<th style="text-align:right;"><span>操作</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="mongodb_list_page page">
<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>
</div>
</div>
<!-- mongodb end -->
<!-- redis start -->
<div class="tab-con show w-full" id="redis" style="padding: 0px;">
<div id="redis_ctr" style="position: relative;">
<div class="tootls_group tootls_top">
<div class="pull-left">
<button id="redis_add_key" type="button" class="refresh btn btn-success btn-sm mr5">
<span>添加key</span>
</button>
<button id="redis_clear_all" type="button" class="clear btn btn-default btn-sm mr5" style="border-right: 1px solid #ccc;padding-right: 20px;">
<span>清空数据库</span>
</button>
</div>
</div>
<div id="redis_list_tab" style="padding-top:10px;">
<div class="tab-nav">
<!-- <span data-id="0" class="on">DB0(0)</span> -->
</div>
</div>
<div class="tootls_group tootls_top">
<div class="pull-left"></div>
<div class="pull-right" style="padding-top: 5px;">
<div class="search">
<input id="redis_ksearch" type="text" class="search_input" placeholder="请输入键名称">
<span id="redis_ksearch_span" class="glyphicon glyphicon-search" aria-hidden="true"></span>
</div>
</div>
</div>
<div class="divtable mtb10 redis_table_content">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th width="30"><input type="checkbox" onclick="checkSelect();"></th>
<th><span>键</span></th>
<th><span>值</span></th>
<th><span>数据类型</span></th>
<th><span>数据长度</span></th>
<th><span>有效期</span></th>
<th style="text-align:right;"><span>操作</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="tootls_group tootls_bottom">
<div class="pull-left">
<button id="redis_batch_del" type="button" class="btn btn-sm set_batch_option bt-disabled btn-default">批量删除</button>
</div>
<div class="pull-right">
<div class="page redis_list_page">
<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>
</div>
</div>
</div>
</div>
<!-- redis end -->
<!-- memcached start -->
<div class="tab-con hide" id="memcached" style="padding: 0px;">
<div id="memcached_ctr" style="position: relative;">
<div class="tootls_group tootls_top">
<div class="pull-left">
<button id="memcached_add_key" type="button" class="refresh btn btn-success btn-sm mr5">
<span>添加key</span>
</button>
<button id="memcached_clear_all" type="button" class="clear btn btn-default btn-sm mr5" style="border-right: 1px solid #ccc;padding-right: 20px;">
<span>清空</span>
</button>
</div>
<div class="pull-right" style="padding-top: 5px;">
<div class="item_list" style="float:left;">
<select name="item" class="bt-input-text c5 mr5">
<option value="0">空</option>
</select>
</div>
<div class="search">
<input id="memcached_ksearch" type="text" class="search_input" placeholder="请输入键名称">
<span id="memcached_ksearch_span" class="glyphicon glyphicon-search" aria-hidden="true"></span>
</div>
</div>
</div>
<div class="divtable mtb10 memcached_table_content">
<table class="table table-hover">
<thead style="position: relative;z-index: 1;">
<tr>
<th width="30"><input type="checkbox" onclick="checkSelect();"></th>
<th><span>键</span></th>
<th><span>值</span></th>
<th><span>数据长度</span></th>
<th><span>有效期</span></th>
<th style="text-align:right;"><span>操作</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="tootls_group tootls_bottom">
<div class="pull-left">
<button id="memcached_batch_del" type="button" class="btn btn-sm set_batch_option bt-disabled btn-default">批量删除</button>
</div>
<div class="pull-right">
<div class="page memcached_list_page">
<div><span class="Pcurrent">0</span><span class="Pcount">共0条</span></div>
</div>
</div>
</div>
</div>
<!-- memcached end -->
</div>
</div>
</div>
+1281
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -15,5 +15,5 @@
"home": "https://docker.io",
"doc1":"https://docker-py.readthedocs.io/",
"type": 0,
"pid": "2"
"pid": "4"
}
+365
View File
@@ -0,0 +1,365 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import io
sys.path.append(os.getcwd() + "/class/core")
import mw
# -----------------------------
import google.oauth2.credentials
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.http import MediaFileUpload
from googleapiclient.http import MediaIoBaseDownload
class gdriveclient():
__plugin_dir = ''
__server_dir = ''
__credentials = "/root/credentials.json"
__backup_dir_name = "backup"
__creds = None
__exclude = ""
__scpos = ['https://www.googleapis.com/auth/drive.file']
_title = 'Google Drive'
_name = 'Google Drive'
__debug = False
_DEFAULT_AUTH_PROMPT_MESSAGE = (
'Please visit this URL to authorize this application: {url}')
"""str: The message to display when prompting the user for
authorization."""
_DEFAULT_AUTH_CODE_MESSAGE = (
'Enter the authorization code: ')
"""str: The message to display when prompting the user for the
authorization code. Used only by the console strategy."""
_DEFAULT_WEB_SUCCESS_MESSAGE = (
'The authentication flow has completed, you may close this window.')
def __init__(self, plugin_dir, server_dir):
self.__plugin_dir = plugin_dir
self.__server_dir = server_dir
self.set_creds()
# self.get_exclode()
def setDebug(self, d=False):
self.__debug = d
def D(self, msg=''):
if self.__debug:
print(msg)
# 检查gdrive连接
def _check_connect(self):
try:
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
results.get('files', [])
except:
return False
return True
# 设置creds
def set_creds(self):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
tmp_data = json.load(token)['credentials']
self.__creds = google.oauth2.credentials.Credentials(
tmp_data['token'],
tmp_data['refresh_token'],
tmp_data['id_token'],
tmp_data['token_uri'],
tmp_data['client_id'],
tmp_data['client_secret'],
tmp_data['scopes'])
# if not self._check_connect():
# return False
# else:
# return True
def get_sign_in_url(self):
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
self.__plugin_dir + '/credentials.json',
scopes=self.__scpos)
# flow.redirect_uri = 'https://drive.aapanel.com'
flow.redirect_uri = 'https://drive.aapanel.com'
auth_url, state = flow.authorization_url(
access_type='offline',
prompt='consent',
include_granted_scopes='false')
return auth_url, state
def set_auth_url(self, url):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
return mw.returnJson(True, "验证成功")
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
self.__plugin_dir + '/credentials.json',
scopes=self.__scpos,
state=url.split('state=')[1].split('&code=')[0])
# flow.redirect_uri = 'https://localhost'
flow.redirect_uri = 'https://drive.aapanel.com'
flow.fetch_token(authorization_response=url)
credentials = flow.credentials
credentials_data = {}
credentials_data['credentials'] = {
'token': credentials.token,
'id_token': credentials.id_token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes}
with open(token_file, 'w') as token:
json.dump(credentials_data, token)
if not self.set_creds():
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
# 获取token
def get_token(self, get):
token_file = self.__server_dir + '/token.json'
import requests
try:
respone = requests.get("https://www.google.com", timeout=2)
except:
return mw.returnJson(False, "连接谷歌失败")
if respone.status_code != 200:
return mw.returnJson(False, "连接谷歌失败")
if not self.set_creds():
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
if not os.path.exists(token_file):
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
# 获取auth_url
def get_auth_url(self, get):
self.get_sign_in_url()
if os.path.exists("/tmp/auth_url"):
return mw.readFile("/tmp/auth_url")
# 检查连接
def check_connect(self, get):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
self.set_creds()
else:
self.D("Failed to get Google token, please verify before use")
return mw.returnJson(True, "Failed to get Google token, please verify before use")
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
try:
results.get('files', [])
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
except:
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
def _get_filename(self, filename):
l = filename.split("/")
return l[-1]
def _create_folder_cycle(self, filepath):
l = filepath.split("/")
fid_list = []
for i in l:
if not i:
continue
fid = self.__get_folder_id(i)
if fid:
fid_list.append(fid)
continue
if not fid_list:
fid_list.append("")
fid_list.append(self.create_folder(i, fid_list[-1]))
return fid_list[-1]
def build_object_name(self, data_type, file_name):
"""根据数据类型构建对象存储名称
:param data_type:
:param file_name:
:return:
"""
import re
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
if not prefix_dict.get(data_type):
print("data_type 类型错误!!!")
exit(1)
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\."
sub_search = re.search(file_regx.lower(), file_name)
sub_path_name = ""
if sub_search:
sub_path_name = sub_search.groups()[0]
sub_path_name += '/'
# 构建OS存储路径
object_name = self.__backup_dir_name + \
'/{}/{}'.format(data_type, sub_path_name)
if object_name[:1] == "/":
object_name = object_name[1:]
return object_name
# 上传文件
def upload_file(self, filename, data_type=None):
"""
get.filename 上传后的文件名
get.filepath 上传文件路径
被面板新版计划任务调用时
get表示file_name
:param get:
:return:
"""
# filename = filename
filepath = self.build_object_name(data_type, filename)
_filename = self._get_filename(filename)
self.D(filepath)
self.D(filename)
parents = self._create_folder_cycle(filepath)
self.D(parents)
drive_service = build('drive', 'v3', credentials=self.__creds)
file_metadata = {'name': _filename, 'parents': [parents]}
media = MediaFileUpload(filename, resumable=True)
file = drive_service.files().create(
body=file_metadata, media_body=media, fields='id').execute()
self.D('Upload Success ,File ID: %s' % file.get('id'))
return True
def _get_file_id(self, filename):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}'".format(
filename), fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
return []
else:
for item in items:
return item["id"]
def delete_file(self, filename=None, data_type=None):
file_id = self._get_file_id(filename)
self.delete_file_by_id(file_id)
return True
def delete_file_by_id(self, file_id):
self.D("delete id:{}".format(file_id))
try:
drive_service = build('drive', 'v3', credentials=self.__creds)
drive_service.files().delete(fileId=file_id).execute()
return True
except Exception as e:
return False
# 创建目录
def create_folder(self, folder_name, parents=""):
self.D(self.__creds)
self.D("folder_name: {}".format(folder_name))
self.D("parents: {}".format(parents))
service = build('drive', 'v3', credentials=self.__creds)
file_metadata = {
'name': folder_name,
'mimeType': 'application/vnd.google-apps.folder'
}
if parents:
file_metadata['parents'] = [parents]
folder = service.files().create(body=file_metadata, fields='id').execute()
self.D('Create Folder ID: %s' % folder.get('id'))
return folder.get('id')
def get_rootdir_id(self, folder_name='backup'):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(folder_name),
fields="nextPageToken, files(id, name,size,parents,webViewLink)").execute()
items = results.get('files', [])
if len(items) == 0:
self.create_folder(folder_name)
return self.get_rootdir_id(folder_name)
return items[0]['parents'][0]
# 获取目录id
def __get_folder_id(self, floder_name):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(floder_name),
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
return []
else:
for item in items:
return item["id"]
def get_res_info(self, rid):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().get(fileId='{}'.format(rid)).execute()
return results
def get_id_list(self, driveId=''):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, driveId="{}".format(driveId),
fields="nextPageToken, files(id, name,size,parents)").execute()
items = results.get('files', [])
return items
def get_list(self, dir_id='', next_page_token=''):
if dir_id == '':
dir_id = self.get_rootdir_id(self.__backup_dir_name)
service = build('drive', 'v3', credentials=self.__creds)
cmd_query = "trashed=false and '{}' in parents".format(dir_id)
results = service.files().list(pageSize=10, q=cmd_query, orderBy='folder asc',
fields="nextPageToken, files(id, name,size,createdTime,parents,webViewLink)").execute()
items = results.get('files', [])
nextPageToken = results.get('nextPageToken', [])
# print(items)
# print(nextPageToken)
return items
def get_exclode(self, exclude=[]):
if not exclude:
tmp_exclude = os.getenv('MW_EXCLUDE')
if tmp_exclude:
exclude = tmp_exclude.split(',')
if not exclude:
return ""
for ex in exclude:
self.__exclude += " --exclude=\"" + ex + "\""
self.__exclude += " "
return self.__exclude
def download_file(self, filename):
file_id = self._get_file_id(filename)
service = build('drive', 'v3', credentials=self.__creds)
request = service.files().get_media(fileId=file_id)
with open('/tmp/{}'.format(filename), 'wb') as fh:
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print("Download %d%%." % int(status.progress() * 100))
+13
View File
@@ -0,0 +1,13 @@
{
"web": {
"client_id": "226011946234-d3e1vashgag64utjedu1ljt9u39ncrpq.apps.googleusercontent.com",
"project_id": "light-willow-341609",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "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",
"redirect_uris": [
"https://drive.aapanel.com"
]
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"web": {
"client_id": "540181629246-1horo9i4htamdbhiqar9rcbq33bqe2ob.apps.googleusercontent.com",
"project_id": "plated-inn-369901",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "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",
"redirect_uris": ["https://drive.aapanel.com"]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

+310
View File
@@ -0,0 +1,310 @@
<style>
.upyunCon {
height: 428px;
}
.up-place {
height: 62px;
border-bottom: 1px solid #ddd;
}
.up-place .btn {
border-radius: 0;
}
.up-place .place-input {
background-color: #f3f3f3;
border: 1px solid #ccc;
height: 30px;
line-height: 28px;
overflow: hidden;
margin: 1px 0 0 -1px;
width: 340px;
}
.place-input ul {
display: inline-block;
position: relative;
width: auto;
}
.place-input ul li {
background: url("/static/img/ico/ico-ltr.png") no-repeat right center;
float: left;
padding-left: 10px;
padding-right: 18px;
}
.place-input ul li a {
height: 28px;
cursor: pointer;
display: inline-block;
}
.upyunlist {
height: 516px;
overflow: auto;
}
.up-bottom {
background-color: #fafafa;
border-top: 1px solid #eee;
bottom: 0;
position: absolute;
width: 100%;
}
.up-use {
line-height: 50px
}
.list-list .cursor span {
line-height: 30px;
}
.btn-title {
margin-top: 1px
}
.tip {
font-size: 10px;
font-style: oblique;
color: green;
}
</style>
<div class="upyunCon">
<div class="up-place pd15">
<button id="backBtn" class="btn btn-default btn-sm glyphicon glyphicon-arrow-left pull-left" title="后退"></button>
<input id="myPath" type="hidden" value="">
<input id="curPath" type="hidden" value="">
<div class="place-input pull-left">
<div style="width:1400px;height:28px"><ul></ul></div>
</div>
<button class="refreshBtn btn btn-default btn-sm glyphicon glyphicon-refresh pull-left mr20" title="刷新" style="margin-left:-1px;"></button>
<button class="btn btn-default btn-sm pull-right btn-title" onclick="authApi()">授权</button>
<button class="btn btn-default btn-sm pull-right mr20 btn-title" onclick="createDir()">新建文件夹</button>
</div>
<div class="upyunlist pd15">
<div class="divtable" style="margin-bottom:15px">
<table class="table table-hover">
<thead><tr><th>名称</th><th>大小</th><th>更新时间</th><th class="text-right">操作</th></tr></thead>
<tbody class="list-list"></tbody>
</table>
</div>
</div>
</div>
<style type="text/css">
.check_api {
padding: 20px;
}
.up-place {
height: 62px;
border-bottom: 1px solid #ddd;
}
.up-place .btn {
border-radius: 0;
}
.up-place .place-input {
background-color: #f3f3f3;
border: 1px solid #ccc;
height: 30px;
line-height: 28px;
overflow: hidden;
margin: 1px 0 0 -1px;
width: 340px;
}
.place-input ul {
display: inline-block;
position: relative;
width: auto;
}
.place-input ul li {
background: url("/static/img/ico/ico-ltr.png") no-repeat right center;
float: left;
padding-left: 10px;
padding-right: 18px;
}
.place-input ul li a {
height: 28px;
cursor: pointer;
display: inline-block;
}
.upyunlist {
height: 546px;
overflow: auto;
}
.up-bottom {
background-color: #fafafa;
border-top: 1px solid #eee;
bottom: 0;
position: absolute;
width: 100%;
}
.up-use {
line-height: 50px
}
.list-list .cursor span {
line-height: 30px;
}
.btn-title {
margin-top: 1px
}
.step_item{
clear: both;
}
.step_item .serial_box{
display: inline-block;
clear: both;
}
.step_item .serial{
width: 70px;
height: 30px;
line-height: 30px;
text-align: center;
display: inline-block;
float: left;
}
.step_item .serial span{
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 28px;
font-size: 11px;
border-radius: 50%;
color: #20a53a;
border: 2px solid #20a53a;
}
.step_item .serial_title{
margin-bottom: 10px;
font-size: 15px;
line-height: 30px;
color: #666;
}
.step_two_url{
display: inline-block;
overflow: hidden;
width: 380px;
/*text-overflow: ellipsis;*/
white-space: nowrap;
height: 35px;
line-height: 35px;
margin-right: 15px;
border-radius: 2px;
padding: 0 10px;
float: left;
width:360px;
padding-right: 35px;
}
.btn_btlink{
display: inline-block;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
border: 1px solid #20a53a;
color: #fff;
background-color: #20a53a;
margin-right:10px;
}
.btn_btlink:hover{
color: #fff;
background-color: #10952a;
border-color: #398439;
}
.btn_btlink a:visited{
color: #fff;
background-color: #10952a;
border-color: #398439;
}
.view_video{
margin-bottom: 10px;
}
.view_video ul li{
line-height: 20px;
font-size: 13px;
}
.setp_one i{
position: absolute;
top: 8px;
left: 25px;
width: 30px;
height: 30px;
}
.google_drive{
width:465px;
height:100px;
margin-bottom:10px;
}
</style>
<script type="text/html" id="check_api">
<div class="check_api">
<div class="step_two">
<div class="step_item">
<div class="serial"><span>1</span></div>
<div class="serial_box">
<div class="serial_title">阅读简易操作教程:如何获取Google Drive授权?</div>
<div class="serial_conter">
<div class="view_video">
<ul>
<li>1. 点击下面第<div class="serial" style="float: none;width: 45px;"><span>2</span></div>步中的 打开授权链接。<li>
<li>2. 在新窗口页面上登录Google Drive账号。阅读授权权限,并同意。<li>
<li>3. 页面跳转后,将浏览器的地址栏地址复制到第<div class="serial" style="float: none;width: 45px;"><span>3</span></div>步的文本框中。<li>
<li>4. 点击 获取授权,随即完成授权。<li>
</ul>
</div>
<hr/>
</div>
</div>
</div>
<div class="step_item pb15">
<div class="serial"><span>2</span></div>
<div class="serial_box">
<div class="serial_title">操作1:👇打开授权链接,根据网页提示对插件进行授权。</div>
<div class="serial_conter step_two" style="width: 500px;">
<input class="bt-input-text mr5 step_two_url" type="text" disabled>
<span class="ico-copy mr10" data-copy="" style="vertical-align: middle;cursor: pointer;margin-left: -37px;margin-right: 20px;"></span>
<a href="" class="btn_btlink open_btlink" target="_blank" style="padding: 7px 10px;">打开授权链接</a>
</div>
</div>
</div>
<div class="step_item">
<div class="serial"><span>3</span></div>
<div class="serial_box">
<div class="serial_title">操作2:复制回浏览器跳转后的地址:</div>
<div class="serial_conter">
<textarea row="3" placeholder="验证URL地址" class="bt-input-text google_drive" style="resize: none;"/></br>
<button type="button" class="btn btn-success btn-sm set_auth_btn">获取授权</button>
</div>
</div>
</div>
</div>
</div>
</script>
<script type="text/javascript" src="/plugins/file?name=gdrive&f=js/gdrive.js"></script>
<script type="text/javascript">
$.getScript( "/plugins/file?name=gdrive&f=js/gdrive.js", function(){
gdList('');
});
</script>
+338
View File
@@ -0,0 +1,338 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
# print(sys.platform)
if sys.platform != "darwin":
os.chdir("/www/server/mdserver-web")
sys.path.append(os.getcwd() + "/class/core")
import mw
import db
_ver = sys.version_info
is_py2 = (_ver[0] == 2)
is_py3 = (_ver[0] == 3)
DEBUG = False
if is_py2:
reload(sys)
sys.setdefaultencoding('utf-8')
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'gdrive'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def in_array(name, arr=[]):
for x in arr:
if name == x:
return True
return False
sys.path.append(getPluginDir() + "/class")
from gdriveclient import gdriveclient
gd = gdriveclient(getPluginDir(), getServerDir())
gd.setDebug(False)
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':', 1)
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def status():
return 'start'
def isAuthApi():
cfg = getServerDir() + "/token.json"
if os.path.exists(cfg):
return True
return False
def getConf():
if not isAuthApi():
sign_in_url, state = gd.get_sign_in_url()
return mw.returnJson(False, "未授权!", {'auth_url': sign_in_url})
return mw.returnJson(True, "OK")
def setAuthUrl():
args = getArgs()
data = checkArgs(args, ['url'])
if not data[0]:
return data[1]
url = args['url']
try:
if url.startswith("http://"):
url = url.replace("http://", "https://")
token = gd.set_auth_url(url)
# gd.store_token(token)
# gd.store_user()
return mw.returnJson(True, "授权成功!")
except Exception as e:
return mw.returnJson(False, "授权失败2!:" + str(e))
return mw.returnJson(False, "授权失败!:" + str(e))
def clearAuth():
token = getServerDir() + "/token.json"
if os.path.exists(token):
os.remove(token)
return mw.returnJson(True, "清空授权成功!")
def getList():
if not isAuthApi():
return mw.returnJson(False, "未配置,请点击`授权`", [])
args = getArgs()
data = checkArgs(args, ['file_id'])
if not data[0]:
return data[1]
try:
flist = gd.get_list(args['file_id'])
return mw.returnJson(True, "ok", flist)
except Exception as e:
return mw.returnJson(False, str(e), [])
def createDir():
if not isAuthApi():
return mw.returnJson(False, "未配置,请点击`授权`", [])
args = getArgs()
data = checkArgs(args, ['parents', 'name'])
if not data[0]:
return data[1]
isok = gd.create_folder(args['name'], args['parents'])
if isok:
return mw.returnJson(True, "创建成功")
return mw.returnJson(False, "创建失败")
def deleteDir():
args = getArgs()
data = checkArgs(args, ['dir_name', 'path'])
if not data[0]:
return data[1]
isok = gd.delete_file_by_id(args['dir_name'])
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "文件不为空,删除失败!")
def deleteFile():
args = getArgs()
data = checkArgs(args, ['path', 'filename'])
if not data[0]:
return data[1]
isok = gd.delete_file(args['filename'])
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "删除失败")
def findPathName(path, filename):
f = os.scandir(path)
l = []
for ff in f:
t = {}
if ff.name.find(filename) > -1:
t['filename'] = path + '/' + ff.name
l.append(t)
return l
def backupAllFunc(stype):
if not isAuthApi():
mw.echoInfo("未授权API,无法使用!!!")
return ''
os.chdir(mw.getRunDir())
backup_dir = mw.getBackupDir()
run_dir = mw.getRunDir()
stype = sys.argv[1]
name = sys.argv[2]
num = sys.argv[3]
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
backups = []
sql = db.Sql()
# print("stype:", stype)
# 提前获取-清理多余备份
if stype == 'site':
pid = sql.table('sites').where('name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('0', pid)).field('id,filename').select()
if stype == 'database':
db_path = mw.getServerDir() + '/mysql'
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
if stype == 'path':
backup_path = backup_dir + '/path'
_name = 'path_{}'.format(os.path.basename(name))
backups = findPathName(backup_path, _name)
# 其他类型关系性数据库(mysql类的)
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
db_path = mw.getServerDir() + '/' + plugin_name
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
args = stype + " " + name + " " + num
cmd = 'python3 ' + run_dir + '/scripts/backup.py ' + args
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
args = "database " + name + " " + num
cmd = 'python3 ' + run_dir + '/plugins/' + \
plugin_name + '/scripts/backup.py ' + args
if stype == 'path':
name = os.path.basename(name)
# print("cmd:", cmd)
os.system(cmd)
# 开始执行上传信息.
if stype.find('database_') > -1:
bk_name = 'database'
plugin_name = stype.replace('database_', '')
bk_prefix = plugin_name + '/db'
stype = 'database'
else:
bk_prefix = prefix_dict[stype]
bk_name = stype
find_path = backup_dir + '/' + bk_name + '/' + bk_prefix + '_' + name
find_new_file = "ls " + find_path + \
"_* | grep '.gz' | cut -d \ -f 1 | awk 'END {print}'"
# print(find_new_file)
filename = mw.execShell(find_new_file)[0].strip()
if filename == "":
mw.echoInfo("not find upload file!")
return False
mw.echoInfo("准备上传文件 {}".format(filename))
mw.echoStart('开始上传')
# gd.setDebug(False)
gd.upload_file(filename, stype)
mw.echoEnd('上传成功')
# print(backups)
backups = sorted(backups, key=lambda x: x['filename'], reverse=False)
mw.echoStart('开始删除远程备份')
num = int(num)
sep = len(backups) - num
if sep > -1:
for backup in backups:
fn = os.path.basename(backup['filename'])
gd.delete_file(fn, stype)
mw.echoInfo("---已清理远程过期备份文件:" + fn)
sep -= 1
if sep < 0:
break
mw.echoEnd('结束删除远程备份')
return ''
def installPreInspection():
return 'ok'
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'install_pre_inspection':
print(installPreInspection())
elif func == 'conf':
print(getConf())
elif func == 'set_auth_url':
print(setAuthUrl())
elif func == 'clear_auth':
print(clearAuth())
elif func == "get_list":
print(getList())
elif func == "create_dir":
print(createDir())
elif func == "delete_dir":
print(deleteDir())
elif func == 'delete_file':
print(deleteFile())
elif in_array(func, ['site', 'database', 'path']) or func.find('database_') > -1:
print(backupAllFunc(func))
else:
print('error')
+19
View File
@@ -0,0 +1,19 @@
{
"hook":["backup"],
"id":998,
"title":"谷歌云网盘",
"tip":"lib",
"name":"gdrive",
"type":"扩展",
"ps":"备份你的数据到谷歌云网盘",
"versions":"2.0",
"shell":"install.sh",
"checks": "server/gdrive",
"path":"server/gdrive",
"author":"google",
"home":"https://drive.google.com/",
"api_doc":"https://developers.google.com/drive/api/guides/about-sdk?hl=zh_CN",
"api_doc2":"https://developers.google.cn/drive/api/reference/rest/v3/comments/list?hl=zh-cn",
"date":"2022-06-26",
"pid":"5"
}
+87
View File
@@ -0,0 +1,87 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# cd /www/server/mdserver-web/plugins/gdrive && /bin/bash install.sh install 2.0
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
PATH=$PATH:${rootPath}/bin
export PATH
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
VERSION=$2
Install_App()
{
tmp_ping=`ping -c 1 google.com 2>&1`
echo $tmp_ping
if [ $? -eq 0 ];then
tmp=`python -V 2>&1|awk '{print $2}'`
pVersion=${tmp:0:3}
which pip
if [ "$?" -eq "0" ];then
tmp=$(pip list|grep google-api-python-client|awk '{print $2}')
if [ "$tmp" != '2.39.0' ];then
pip install --upgrade google-api-python-client
# pip uninstall google-api-python-client -y
pip install -I google-api-python-client==2.39.0 -i https://pypi.Python.org/simple
fi
tmp=$(pip list|grep google-auth-httplib2|awk '{print $2}')
if [ "$tmp" != '0.1.0' ];then
pip uninstall google-auth-httplib2 -y
pip install -I google-auth-httplib2==0.1.0 -i https://pypi.Python.org/simple
fi
tmp=$(pip list|grep google-auth-oauthlib|awk '{print $2}')
if [ "$tmp" != '0.5.0' ];then
# pip uninstall google-auth-oauthlib -y
pip install -I google-auth-oauthlib==0.5.0 -i https://pypi.Python.org/simple
fi
tmp=$(pip list|grep -E '^httplib2'|awk '{print $2}')
if [ "$tmp" != '0.18.1' ];then
# pip uninstall httplib2 -y
pip install -I httplib2==0.18.1 -i https://pypi.Python.org/simple
fi
else
pip install -I pyOpenSSL
pip install -I google-api-python-client==2.39.0 google-auth-httplib2==0.1.0 google-auth-oauthlib==0.5.0 -i https://pypi.Python.org/simple
pip install -I httplib2==0.18.1 -i https://pypi.Python.org/simple
fi
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/gdrive
echo "${VERSION}" > $serverPath/gdrive/version.pl
echo '安装完成' > $install_tmp
else
echo '服务器连接不上谷歌云!安装失败!' > $install_tmp
exit 1
fi
}
Uninstall_App()
{
rm -rf $serverPath/gdrive
echo '卸载完成' > $install_tmp
}
action=$1
type=$2
echo $action $type
if [ "${action}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+260
View File
@@ -0,0 +1,260 @@
function gdPost(method,args,callback){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'gdrive', func:method, args:_args}, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function createDir(){
layer.open({
type: 1,
area: "400px",
title: "创建目录",
closeBtn: 1,
shift: 5,
shadeClose: false,
btn: ['确定','取消'],
content:'<div class="bingfa bt-form c6" style="padding-bottom: 10px;">\
<p>\
<span class="span_tit">目录名称:</span>\
<input style="width: 200px;" type="text" name="newPath" value="">\
</p>\
</div>',
success:function(){
$("input[name='newPath']").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(index,layero){
var name = $("input[name='newPath']").val();
if(name == ''){
layer.msg('目录名称不能为空!',{icon:2});
return;
}
var parents = $("#myPath").val();
var cur_file_id = $('#curPath').val();
if (cur_file_id!=''){
parents = cur_file_id;
}
var dirname = name;
var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']});
gdPost('create_dir', {parents:parents,name:dirname}, function(data){
layer.close(loadT);
var rdata = $.parseJSON(data.data);
if(rdata.status) {
showMsg(rdata.msg, function(){
layer.close(index);
var file_id = $('#myPath').val();
if (cur_file_id!=''){
file_id = cur_file_id;
}
gdList(file_id);
} ,{icon:1}, 2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
});
}
});
}
//设置API
function authApi(){
gdPost('conf', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
// console.log(rdata.data.auth_url);
var apicon = '';
if (rdata.status){
var html = '';
html += '<button id="clear_auth" onclick="clearAuth();" class="btn btn-default btn-sm">清空配置</button>';
var loadOpen = layer.open({
type: 1,
title: '已授权',
area: '240px',
content:'<div class="change-default pd20">'+html+'</div>',
success: function(){
$('#clear_auth').click(function(){
gdPost('clear_auth', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
layer.close(loadOpen);
gdList('');
},{icon:rdata.status?1:2},2000);
});
});
}
});
return true;
} else{
apicon = '<div class="new_form">'+$("#check_api").html()+'</div>';
}
var layer_auth = layer.open({
type: 1,
area: "620px",
title: "Google Drive 授权",
closeBtn: 1,
shift: 5,
shadeClose: false,
content:apicon,
success:function(layero,index){
// console.log(layero,index);
if (!rdata.status){
$('.check_api .step_two_url').val(rdata.data['auth_url']);
$('.check_api .open_btlink').attr('href',rdata.data['auth_url']);
$('.check_api .ico-copy').click(function(){
copyPass(rdata.data['auth_url']);
});
$('.check_api .set_auth_btn').click(function(){
var url = $('.check_api .google_drive').val();
if ( url == ''){
layer.msg("验证URL不能为空",{icon:2});
return;
}
// console.log(url);
gdPost('set_auth_url', {url:url}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var show_time = 2000;
if (!rdata.status){
show_time = 10000;
}
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(layer_auth);
gdList('');
}
},{icon:rdata.status?1:2},show_time);
});
});
}
}
});
});
}
//计算当前目录偏移
function upPathLeft(){
var UlWidth = $(".place-input ul").width();
var SpanPathWidth = $(".place-input").width() - 20;
var Ml = UlWidth - SpanPathWidth;
if(UlWidth > SpanPathWidth ){
$(".place-input ul").css("left",-Ml)
}
else{
$(".place-input ul").css("left",0)
}
}
function getGDTime(a) {
return new Date(a).format("yyyy/MM/dd hh:mm:ss")
}
function gdList(file_id){
$('#curPath').val(file_id);
gdPost('get_list', {file_id:file_id}, function(rdata){
var rdata = $.parseJSON(rdata.data);
console.log(rdata);
if(rdata.status === false){
showMsg(rdata.msg,function(){
authApi();
},{icon:2},2000);
return;
}
var mlist = rdata.data;
var listBody = '';
var listFiles = '';
for(var i=0;i<mlist.length;i++){
if(mlist[i].size == null){
listFiles += '<tr><td class="cursor" onclick="gdList(\''+(mlist[i].id).replace('//','/')+'\')"><span class="ico ico-folder"></span>\<span>'+mlist[i].name+'</span></td>\
<td>-</td>\
<td>-</td>\
<td class="text-right"><a class="btlink" onclick="deleteFile(\''+mlist[i].id+'\', true)">删除</a></td></tr>'
}else{
listFiles += '<tr><td class="cursor"><span class="ico ico-file"></span><span>'+mlist[i].name+'</span></td>\
<td>'+toSize(mlist[i].size)+'</td>\
<td>'+getGDTime(mlist[i].createdTime)+'</td>\
<td class="text-right"><a target="_blank" href="'+mlist[i].webViewLink+'" class="btlink">下载</a> | <a class="btlink" onclick="deleteFile(\''+mlist[i].name+'\', false)">删除</a></td></tr>'
}
}
listBody += listFiles;
var pathLi = '<li><a title="根目录" onclick="gdList(\'\')">根目录</a></li>';
if (mlist.length>0){
$('#myPath').val(mlist[0]['parents'][0]);
}
$(".upyunCon .place-input ul").html(pathLi);
$(".upyunlist .list-list").html(listBody);
$('#backBtn').unbind().click(function() {
gdList('');
});
$('.upyunCon .refreshBtn').unbind().click(function(){
var file_id = $('#myPath').val();
gdList(file_id);
});
});
}
//删除文件
function deleteFile(name, is_dir){
if (is_dir === false){
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
var filename = name;
gdPost('delete_file', {filename:filename,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
var file_id = $('#myPath').val();
gdList(file_id);
},{icon:rdata.status?1:2},2000);
});
});
} else {
safeMessage('删除文件夹','删除后将无法恢复,真的要删除文件资源['+name+']吗?',function(){
var path = $("#myPath").val();
gdPost('delete_dir', {dir_name:name,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
var file_id = $('#myPath').val();
gdList(file_id);
},{icon:rdata.status?1:2},2000);
});
});
}
}
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/python
# coding: utf-8
# python3 plugins/gdrive/t/test.py
# https://console.cloud.google.com/apis/credentials/consent?project=plated-inn-369901
# https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=226011946234-d3e1vashgag64utjedu1ljt9u39ncrpq.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdrive.aapanel.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=I2da4aZUwqgmikrgrqAwwSjyoEHVs1&access_type=offline&prompt=consent&include_granted_scopes=false
# https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/08125e6b-6502-4ac9-9548-ad682f00848d/objectId/62b1d655-9828-47ed-be99-65eb18c3a929/isMSAApp~/false/defaultBlade/Overview/appSignInAudience/AzureADandPersonalMicrosoftAccount/servicePrincipalCreated~/true
# 0WA8Q~sZkZFZKv50ryP4ux~.fpVtbHw7BuTZmbQB
# client_id:d9878fac-8526-4ff6-8036-e1c92dd9dd80
# 08125e6b-6502-4ac9-9548-ad682f00848d
# /drive/v2internal/files?openDrive=false&reason=102&syncType=0&errorRecovery=false&q=trashed = false and '1-z6gUXseXmlxmntvkLzOe_tYFT5tdhM9' in parents&fields=kind,nextPageToken,items(kind,modifiedDate,hasVisitorPermissions,containsUnsubscribedChildren,modifiedByMeDate,lastViewedByMeDate,alternateLink,fileSize,owners(kind,permissionId,emailAddressFromAccount,id),lastModifyingUser(kind,permissionId,emailAddressFromAccount,id),customerId,ancestorHasAugmentedPermissions,hasThumbnail,thumbnailVersion,title,id,resourceKey,abuseIsAppealable,abuseNoticeReason,shared,accessRequestsCount,sharedWithMeDate,userPermission(role),explicitlyTrashed,mimeType,quotaBytesUsed,copyable,subscribed,folderColor,hasChildFolders,fileExtension,primarySyncParentId,sharingUser(kind,permissionId,emailAddressFromAccount,id),flaggedForAbuse,folderFeatures,spaces,sourceAppId,recency,recencyReason,version,actionItems,teamDriveId,hasAugmentedPermissions,createdDate,primaryDomainName,organizationDisplayName,passivelySubscribed,trashingUser(kind,permissionId,emailAddressFromAccount,id),trashedDate,parents(id),capabilities(canMoveItemIntoTeamDrive,canUntrash,canModifyContentRestriction,canMoveItemWithinTeamDrive,canMoveItemOutOfTeamDrive,canDeleteChildren,canTrashChildren,canRequestApproval,canReadCategoryMetadata,canEditCategoryMetadata,canAddMyDriveParent,canRemoveMyDriveParent,canShareChildFiles,canShareChildFolders,canRead,canMoveItemWithinDrive,canMoveChildrenWithinDrive,canAddFolderFromAnotherDrive,canChangeSecurityUpdateEnabled,canBlockOwner,canReportSpamOrAbuse,canCopy,canDownload,canEdit,canAddChildren,canDelete,canRemoveChildren,canShare,canTrash,canRename,canReadTeamDrive,canMoveTeamDriveItem),contentRestrictions(readOnly),approvalMetadata(approvalVersion,approvalSummaries,hasIncomingApproval),shortcutDetails(targetId,targetMimeType,targetLookupStatus,targetFile,canRequestAccessToTarget),spamMetadata(markedAsSpamDate,inSpamView),labels(starred,trashed,restricted,viewed)),incompleteSearch&appDataFilter=NO_APP_DATA&spaces=drive&maxResults=200&supportsTeamDrives=true&includeItemsFromAllDrives=true&corpora=default&orderBy=folder,title_natural asc&retryCount=0&key=AIzaSyD_InbmSFufIEps5UAt2NmB_3LvBH3Sz_8 HTTP/1.1
# http://localhost/?code=M.C106_BAY.2.3e12c859-6107-0c5b-9ef4-14b3fb8269ba&state=JzHdzHXmA7x6zl7Be6cJ6uOlf9Bg69
# python3 /www/mdserver-web/plugins/gdrive/index.py site bbs.midoks.icu 3
# python3 /www/mdserver-web/plugins/gdrive/index.py database t1 3
# python3 /www/server/mdserver-web/plugins/msonedrive/index.py path
# /Users/midoks/Desktop/dev/python 3
import sys
import io
import os
import time
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
def getPluginName():
return 'gdrive'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
# print(getPluginDir())
sys.path.append(getPluginDir() + "/class")
from gdriveclient import gdriveclient
gd = gdriveclient(getPluginDir(), getServerDir())
gd.setDebug(True)
# sign_in_url, state = gd.get_sign_in_url()
# print(sign_in_url)
# url = 'https://localhost/?state=GH2YZ1VeytzVB1BqJJpQZIBk2GGAub&code=4/0Adeu5BXnD2dQvXx8Sg0WPn1XiMpihcRBNaG1yaFKIo86gUiG7q65KU1MaNCxrj_f2bjkwQ&scope=https://www.googleapis.com/auth/drive.file'
# t = gd.set_auth_url(url)
# print(t)
# def set_auth_url(url):
# try:
# if url.startswith("http://"):
# url = url.replace("http://", "https://")
# token = msodc.get_token_from_authorized_url(
# authorized_url=url)
# msodc.store_token(token)
# msodc.store_user()
# return mw.returnJson(True, "授权成功!")
# except Exception as e:
# print(e)
# return mw.returnJson(False, "授权失败2!:" + str(e))
# return mw.returnJson(False, "授权失败!:" + str(e))
# url = 'http://localhost/?code=M.C106_BAY.2.310112f3-a158-c400-9667-d158cbd1de6c&state=jEJz0ucR9bpZYD9PGxp2GgRDotrzO6'
# token = set_auth_url(url)
# print(token)
# token = msodc.get_token()
# print("token:", token)
# t = gd.get_list('')
# print(t)
# t = gd.get_id_list('1u7LjXGj1KoN-ltAdTRaib7IZJpsEnPdz')
# print(t)
# t = gd.create_folder('backup_demo')
# print(t)
# t = msodc.delete_object('backup')
# print(t)
# t = gd.upload_file('web_t1.cn_20230830_134549.tar.gz', 'site')
# print(t)
# print(gd.error_msg)
# /Users/midoks/Desktop/mwdev/server/mdserver-web/paramiko.log
# backup/site/paramiko.log
# |-正在上传到 backup/site/paramiko.log...
# True
t = gd.upload_file(
'db_zzzvps_20230830_210727.sql.gz', 'datebase')
print(t)
+5 -1
View File
@@ -8,6 +8,10 @@ GIT_SDIR="{$CODE_DIR}"
GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}"
GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
if [ ! -d $GIT_USER_DIR ];then
mkdir -p $GIT_USER_DIR
chown -R www:www $GIT_USER_DIR
fi
git config --global credential.helper store
git config --global pull.rebase false
@@ -34,7 +38,7 @@ if [ ! -d $WEB_PATH ];then
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
else
if [ -f $GIT_PROJECT_DIR/exclude.list ];then
rsync -vauP --delete --exclude-from="$GIT_PROJECT_DIR/exclude.list" $GIT_PROJECT_DIR/ $WEB_PATH
rsync -vauP --exclude-from="$GIT_PROJECT_DIR/exclude.list" $GIT_PROJECT_DIR/ $WEB_PATH
else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
fi
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
H_DIR={$HOOK_DIR}
HL_DIR={$HOOK_LOGS_DIR}
SH_LIST=`cd ${H_DIR} && ls | grep ".sh$"`
for sh_f in $SH_LIST; do
ABS_FILE=${H_DIR}/${sh_f}
ABS_LOGS=${HL_DIR}/${sh_f}.log
echo "sh ${ABS_FILE} 2>${ABS_LOGS}"
sh -x ${ABS_FILE} 2>${ABS_LOGS}
done
+10 -1
View File
@@ -1,13 +1,21 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('gitea');">服务</p>
<p onclick="pluginInitD('gitea');">自启动</p>
<!-- <p onclick="pluginConfig('gitea',null, 'init_conf');">启动配置</p> -->
<p onclick="gogsEdit();">手动编辑</p>
<p onclick="pluginConfig('gitea',null, 'conf');">配置文件</p>
<p onclick="gogsSetConfig();">配置修改</p>
<p onclick="giteaUserList();">用户列表</p>
<p onclick="giteaRepoList();">项目列表</p>
<!-- <p onclick="pluginLogs('gitea',null,'run_log');">运行日志</p> -->
<!-- <p onclick="pluginLogs('gitea',null,'post_receive_log');" title="提交post-receive日志">提交日志</p> -->
<p onclick="giteaRead();">使用说明</p>
@@ -18,6 +26,7 @@
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(530);
$.getScript( "/plugins/file?name=gitea&f=js/gitea.js",function(){
pluginService('gitea');
});
+402 -19
View File
@@ -453,6 +453,13 @@ def submitGogsConf():
return mw.returnJson(True, '设置成功')
def gogsEditTpl():
data = {}
data['post_receive'] = getPluginDir() + '/hook/post-receive.tpl'
data['commit'] = getPluginDir() + '/hook/commit.tpl'
return mw.getJson(data)
def userList():
conf = getConf()
@@ -473,7 +480,66 @@ def userList():
page = int(args['page'])
page_size = int(args['page_size'])
tojs = args['tojs']
search = ''
if 'search' in args:
search = args['search']
user_where1 = ''
user_where2 = ''
if search != '':
user_where1 = ' where name like "%' + search + '%"'
user_where2 = ' where name like "%' + search + '%"'
data = {}
data['root_url'] = getRootUrl()
start = (page - 1) * page_size
list_count = pQuery('select count(id) as num from user' + user_where1)
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user ' + user_where2 + ' order by id desc limit ' + str(start) + ',' + str(page_size))
data['list'] = mw.getPage({'count': count, 'p': page,
'row': page_size, 'tojs': 'gogsUserList'})
data['page'] = page
data['page_size'] = page_size
data['page_count'] = int(math.ceil(count / page_size))
data['data'] = list_data
return mw.returnJson(True, 'OK', data)
def checkRepoListIsHasScript(data):
path = getRootPath()
for x in range(len(data)):
name = data[x]['name'] + '/' + data[x]['repo'] + '.git'
path_tmp = path + '/' + name + '/custom_hooks/commit'
if os.path.exists(path_tmp):
data[x]['has_hook'] = True
else:
data[x]['has_hook'] = False
return data
def repoList():
conf = getConf()
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
conf = getDbConfValue()
gtype = getGiteaDbType(conf)
if gtype != 'mysql':
return mw.returnJson(False, "仅支持mysql数据操作!")
import math
args = getArgs()
data = checkArgs(args, ['page', 'page_size'])
if not data[0]:
return data[1]
page = int(args['page'])
page_size = int(args['page_size'])
search = ''
if 'search' in args:
search = args['search']
@@ -482,14 +548,25 @@ def userList():
data['root_url'] = getRootUrl()
start = (page - 1) * page_size
list_count = pQuery('select count(id) as num from user')
repo_where1 = ''
repo_where2 = ''
if search != '':
repo_where1 = ' where name like "%' + search + '%"'
repo_where2 = ' where r.name like "%' + search + '%"'
start = (page - 1) * page_size
list_count = pQuery(
'select count(id) as num from repository' + repo_where1)
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size))
data['list'] = mw.getPage(
{'count': count, 'p': page, 'row': page_size, 'tojs': tojs})
sql = 'select r.id,r.owner_id,r.name as repo, u.name from repository r left join user u on r.owner_id=u.id ' + repo_where2 + ' order by r.id desc limit ' + \
str(start) + ',' + str(page_size)
# print(sql)
list_data = pQuery(sql)
# print(list_data)
list_data = checkRepoListIsHasScript(list_data)
data['list'] = mw.getPage({'count': count, 'p': page,
'row': page_size, 'tojs': 'gogsRepoListPage'})
data['page'] = page
data['page_size'] = page_size
data['page_count'] = int(math.ceil(count / page_size))
@@ -586,11 +663,9 @@ def projectScriptEdit():
def projectScriptLoad():
args = getArgs()
if not 'user' in args:
return mw.returnJson(True, 'username missing')
if not 'name' in args:
return mw.returnJson(True, 'project name missing')
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
@@ -670,11 +745,299 @@ def projectScriptDebug():
return mw.getJson(data)
def gogsEdit():
data = {}
data['post_receive'] = getPluginDir() + '/hook/post-receive.tpl'
data['commit'] = getPluginDir() + '/hook/commit.tpl'
return mw.getJson(data)
def projectScriptRun():
args = getArgs()
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
path = getRootPath() + '/' + user + '/' + name
commit_sh = path + '/custom_hooks/commit'
commit_log = path + '/custom_hooks/sh.log'
script_run = 'sh -x ' + commit_sh + ' 2>' + commit_log
if not os.path.exists(commit_sh):
return mw.returnJson(False, '脚本文件不存在!')
mw.execShell(script_run)
mw.execShell('chown -R www:www ' + commit_log)
return mw.returnJson(True, '脚本文件执行成功,观察日志!')
def projectScriptSelf():
args = getArgs()
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
mw.execShell("chown -R www:www " + self_path)
self_logs_path = custom_hooks + '/self_logs'
if not os.path.exists(self_logs_path):
os.mkdir(self_logs_path)
mw.execShell("chown -R www:www " + self_logs_path)
self_hook_file = custom_hooks + '/self_hook.sh'
self_hook_exist = False
if os.path.exists(self_hook_file):
self_hook_exist = True
dlist = []
if os.path.exists(self_path):
for filename in os.listdir(self_path):
tmp = {}
filePath = self_path + '/' + filename
if os.path.isfile(filePath):
tmp['path'] = filePath
tmp['name'] = os.path.basename(filePath)
tmp['is_hidden'] = False
if tmp['name'].endswith('.txt'):
tmp['is_hidden'] = True
dlist.append(tmp)
dlist_sum = len(dlist)
# print(dlist)
rdata = {}
rdata['data'] = dlist
rdata['self_hook'] = self_hook_exist
rdata['list'] = mw.getPage(
{'count': dlist_sum, 'p': 1, 'row': 100, 'tojs': 'self_page'})
return mw.returnJson(True, 'ok', rdata)
def projectScriptSelf_Create():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
self_path = path = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
abs_file = self_path + '/' + file + '.sh'
if os.path.exists(abs_file):
return mw.returnJson(False, '脚本已经存在!')
mw.writeFile(abs_file, "#!/bin/bash\necho `date +'%Y-%m-%d %H:%M:%S'`\n")
mw.execShell('chown -R www:www ' + abs_file)
rdata = {}
rdata['abs_file'] = abs_file
return mw.returnJson(True, '创建文件成功!', rdata)
def projectScriptSelf_Del():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
abs_file = self_path + '/' + file
# print(abs_file)
if not os.path.exists(abs_file):
return mw.returnJson(False, '脚本已经删除!')
os.remove(abs_file)
# 日志也删除
log_file = custom_hooks + '/self_logs/' + file + '.log'
if os.path.exists(log_file):
os.remove(log_file)
return mw.returnJson(True, '脚本删除成功!')
def projectScriptSelf_Logs():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
self_path = path = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks/self_logs'
if not os.path.exists(self_path):
os.mkdir(self_path)
logs_file = self_path + '/' + file + '.log'
if os.path.exists(logs_file):
rdata = {}
rdata['path'] = logs_file
return mw.returnJson(True, 'ok', rdata)
return mw.returnJson(False, '日志不存在!')
def projectScriptSelf_Run():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self/' + file
self_logs_path = custom_hooks + '/self_logs/' + file + '.log'
shell = "sh -x " + self_path + " 2>" + self_logs_path + ' &'
mw.execShell(shell)
mw.execShell("chown -R www:www " + self_logs_path)
return mw.returnJson(True, '执行成功!')
def projectScriptSelf_Rename():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'o_file', 'n_file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
o_file = args['o_file']
n_file = args['n_file']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
o_file_abs = self_path + '/' + o_file + '.sh'
if not os.path.exists(o_file_abs):
return mw.returnJson(False, '原文件已经不存在了!')
n_file_abs = self_path + '/' + n_file + '.sh'
os.rename(o_file_abs, n_file_abs)
# 日志也删除
log_file = custom_hooks + '/self_logs/' + o_file + '.sh.log'
if os.path.exists(log_file):
os.remove(log_file)
return mw.returnJson(True, '重命名成功!')
def projectScriptSelf_Enable():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'enable'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
enable = args['enable']
custom_path = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
# 替换commit配置
commit_path = custom_path + '/commit'
note = '#Gogs Script Don`t Remove and Change'
self_file = custom_path + '/self_hook.sh'
self_hook_tpl = getPluginDir() + '/hook/self_hook.tpl'
if enable == '1':
content = mw.readFile(self_hook_tpl)
content = content.replace('{$HOOK_DIR}', custom_path + '/self')
content = content.replace(
'{$HOOK_LOGS_DIR}', custom_path + '/self_logs')
mw.writeFile(self_file, content)
mw.execShell("chmod 777 " + self_file)
mw.execShell("chown -R www:www " + self_file)
commit_content = mw.readFile(commit_path)
commit_content += "\n\n" + "bash " + self_file + " " + note
mw.writeFile(commit_path, commit_content)
return mw.returnJson(True, '开启成功!')
else:
commit_content = mw.readFile(commit_path)
rep = ".*" + note
commit_content = re.sub(rep, '', commit_content, re.M)
commit_content = commit_content.strip()
mw.writeFile(commit_path, commit_content)
if os.path.exists(self_file):
os.remove(self_file)
return mw.returnJson(True, '关闭成功!')
def projectScriptSelf_Status():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file', 'status'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
status = args['status']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
# 日志也删除
log_file = custom_hooks + '/self_logs/' + file + '.log'
if os.path.exists(log_file):
os.remove(log_file)
if status == '1':
file_abs = self_path + '/' + file
file_text_abs = self_path + '/' + file + '.txt'
os.rename(file_abs, file_text_abs)
return mw.returnJson(True, '开始禁用成功!')
else:
file_abs = self_path + '/' + file.strip('.txt')
file_text_abs = self_path + '/' + file
os.rename(file_text_abs, file_abs)
return mw.returnJson(True, '开始使用成功!')
return mw.returnJson(True, '禁用成功!')
def getRsaPublic():
@@ -745,8 +1108,12 @@ if __name__ == "__main__":
print(getGogsConf())
elif func == 'submit_gogs_conf':
print(submitGogsConf())
elif func == 'gogs_edit_tpl':
print(gogsEditTpl())
elif func == 'user_list':
print(userList())
elif func == 'repo_list':
print(repoList())
elif func == 'user_project_list':
print(userProjectList())
elif func == 'project_script_edit':
@@ -757,8 +1124,24 @@ if __name__ == "__main__":
print(projectScriptUnload())
elif func == 'project_script_debug':
print(projectScriptDebug())
elif func == 'gogs_edit':
print(gogsEdit())
elif func == 'project_script_run':
print(projectScriptRun())
elif func == 'project_script_self':
print(projectScriptSelf())
elif func == 'project_script_self_create':
print(projectScriptSelf_Create())
elif func == 'project_script_self_del':
print(projectScriptSelf_Del())
elif func == 'project_script_self_logs':
print(projectScriptSelf_Logs())
elif func == 'project_script_self_run':
print(projectScriptSelf_Run())
elif func == 'project_script_self_rename':
print(projectScriptSelf_Rename())
elif func == 'project_script_self_enable':
print(projectScriptSelf_Enable())
elif func == 'project_script_self_status':
print(projectScriptSelf_Status())
elif func == 'get_rsa_public':
print(getRsaPublic())
elif func == 'get_total_statistics':
+414 -10
View File
@@ -118,6 +118,7 @@ function gogsEdit(){
}
function giteaUserList(page, search) {
var _data = {};
@@ -130,7 +131,6 @@ function giteaUserList(page, search) {
if(typeof(search) != 'undefined'){
_data['search'] = search;
}
_data['tojs'] = 'giteaUserList';
gogsPost('user_list', _data, function(data){
@@ -140,7 +140,7 @@ function giteaUserList(page, search) {
return;
}
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找用户名" id="find_user" style="height: 28px; border-radius: 3px;width: 435px;">';
content += '<button class="btn btn-success btn-sm" onclick="userFind();">查找</button></div>';
content += '<button class="btn btn-success btn-sm find_user" >查找</button></div>';
content += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
content += '<thead><tr>';
@@ -154,24 +154,31 @@ function giteaUserList(page, search) {
ulist = rdata['data']['data'];
for (i in ulist){
email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
var email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
var user_url = rdata['data']['root_url'] + ulist[i]["name"];
content += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td>'+ulist[i]["name"]+'</td>'+
'<td>'+email+'</td>'+
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i]["name"]+'\')">项目管理</a></td>'+
'<td><a class="btlink" target="_blank" href="'+user_url+'">项目管理</a></td>'+
'</tr>';
}
content += '</tbody>';
content += '</table></div>';
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
var page_html = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page_html += rdata['data']['list'];
page_html += '</div></ul></div>';
content += page;
content += page_html;
$(".soft-man-con").html(content);
$('.find_user').click(function(){
var name = $('#find_user').val();
giteaUserList(page, name);
});
});
}
@@ -336,6 +343,403 @@ function projectScriptDebug(user,name,index){
});
}
function gogsRepoListPage(page, search){
var _data = {};
if (typeof(page) =='undefined'){
var page = 1;
}
_data['page'] = page;
_data['page_size'] = 10;
if(typeof(search) != 'undefined'){
_data['search'] = search;
}
gogsPost('repo_list', _data, function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var ulist = rdata['data']['data'];
var body = ''
for (i in ulist){
// console.log(ulist[i]);
var option = '';
if(ulist[i]['has_hook']){
option += '<a class="btlink unload" data-index="'+i+'">卸载脚本</a>' + ' | ';
option += '<a class="btlink load" data-index="'+i+'">重载</a>' + ' | ';
option += '<a class="btlink edit" data-index="'+i+'">编辑</a>' + ' | ';
option += '<a class="btlink debug" data-index="'+i+'">日志</a>' + ' | ';
option += '<a class="btlink run" data-index="'+i+'">手动</a>' + ' | ';
option += '<a class="btlink scripts" data-index="'+i+'" onclick="projectScriptSelf(\''+ulist[i]["name"]+'\',\''+ulist[i]["repo"]+'\')" >自定义</a>';
} else{
option += '<a data-index="'+i+'" class="btlink load">加载脚本</a>';
}
body += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td class="overflow_hide" style="width:70px;">' + ulist[i]["name"]+'</td>'+
'<td class="overflow_hide" style="width:70px;display: inline-block;">' + ulist[i]["repo"]+'</td>'+
'<td>' +
'<a class="btlink" target="_blank" href="'+rdata['data']['root_url']+ulist[i]["name"]+'/'+ulist[i]["repo"]+'">源码</a>' + ' | ' +
option +
'</td>' +
'</tr>';
}
$('#repo_list tbody').html(body);
$('#repo_list_page').html(rdata['data']['list']);
$('.find_repo').click(function(){
var find_repo = $('#find_repo').val();
gogsRepoListPage(page, find_repo);
});
$('#repo_list .load').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_load', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
gogsRepoListPage(page, search);
}, 2000);
});
});
$('#repo_list .unload').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_unload', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
gogsRepoListPage(page, search);
}, 2000);
});
});
$('#repo_list .edit').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_edit', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['data']['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
});
$('#repo_list .debug').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_debug', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
});
$('#repo_list .run').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_run', {'user':user,'name':name}, function(data){
var data = $.parseJSON(data.data);
layer.msg(data.msg,{icon:data.status?1:2,time:2000,shade: [0.3, '#000']});
});
});
//---------
});
}
function giteaRepoList() {
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找项目" id="find_repo" style="height: 28px; border-radius: 3px;width: 435px;">';
content += '<button class="btn btn-success btn-sm find_repo">查找</button></div>';
content += '<div id="repo_list" class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
content += '<thead><tr>';
content += '<th style="width:50px;">序号</th>';
content += '<th style="width:80px;">用户/组织</th>';
content += '<th style="width:80px;">项目名</th>';
content += '<th>操作</th>';
content += '</tr></thead>';
content += '<tbody></tbody>';
content += '</table></div>';
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="repo_list_page" class="page"></ul></div>';
content += page;
$(".soft-man-con").html(content);
gogsRepoListPage(1);
}
function projectScriptSelfRender(user, name){
gogsPost('project_script_self', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
var data = rdata['data']['data'];
if (rdata['data']['self_hook']){
$('#open_script').prop('checked',true);
}
var body = '';
if(data.length == 0 ){
body += '<tr><td colspan="3" style="text-align:center;">无脚本数据</td></tr>';
} else{
for (var i = 0; i < data.length; i++) {
var b_status = '<a class="btlink status" data-index="'+i+'" target="_blank">已使用</a>';
if (data[i]["is_hidden"]){
b_status = '<a class="btlink status" data-index="'+i+'" target="_blank">已隐藏</a>';
}
body += '<tr>'+
'<td>' + data[i]["name"]+'</td>'+
'<td>' + b_status + '</td>'+
'<td>' +
'<a class="btlink del" data-index="'+i+'" target="_blank">删除</a>' + ' | ' +
'<a class="btlink edit" data-index="'+i+'" target="_blank">编辑</a>' + ' | ' +
'<a class="btlink logs" data-index="'+i+'" target="_blank">日志</a>' + ' | ' +
'<a class="btlink run" data-index="'+i+'" target="_blank">手动</a>' + ' | ' +
'<a class="btlink rename" data-index="'+i+'" target="_blank">重命名</a>' +
'</td></tr>';
}
}
$('#gogs_self_table tbody').html(body);
$('#gogs_self_table .page').html(rdata['data']['list']);
$('#gogs_self_table .status').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
var status = '1';
if (data[i]["is_hidden"]){
status = '0';
}
gogsPost('project_script_self_status', {'user':user,'name':name,'file':file, status:status}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
projectScriptSelfRender(user, name);
},{icon:data.code?2:1,time:2000,shade: [0.3, '#000']},2000);
});
});
$('#gogs_self_table .del').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
gogsPost('project_script_self_del', {'user':user,'name':name,'file':file}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
projectScriptSelfRender(user, name);
},{icon:data.code?2:1,time:2000,shade: [0.3, '#000']},2000);
});
});
$('#gogs_self_table .edit').click(function(){
var i = $(this).data('index');
var path = data[i]["path"];
onlineEditFile(0,path);
});
$('#gogs_self_table .logs').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
gogsPost('project_script_self_logs', {'user':user,'name':name,'file':file}, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
if (rdata['status']){
onlineEditFile(0, rdata['data']['path']);
} else {
layer.msg(rdata.msg,{icon:data.status?2:1,time:2000,shade: [0.3, '#000']});
}
});
});
$('#gogs_self_table .run').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
if (data[i]["is_hidden"]){
layer.msg("已经禁用,不能执行!",{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
gogsPost('project_script_self_run', {'user':user,'name':name,'file':file}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg,{icon:data.status?1:2,time:2000,shade: [0.3, '#000']});
});
});
$('#gogs_self_table .rename').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
if (data[i]["is_hidden"]){
layer.msg("已经禁用,不能执行!",{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
file = file.split('.sh')[0];
layer.open({
type: 1,
shift: 5,
closeBtn: 1,
area: '320px',
title: '重命名',
btn:['设置','关闭'],
content: '<div class="bt-form pd20">\
<div class="line">\
<input type="text" class="bt-input-text" name="Name" id="newFileName" value="'+file+'" placeholder="文件名" style="width:100%" />\
</div>\
</div>',
success:function(){
$("#newFileName").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(){
var n_file = $("#newFileName").val();
var o_file = file;
gogsPost('project_script_self_rename', {'user':user,'name':name,'o_file':o_file,'n_file':n_file}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
$(".layui-layer-btn1").click();
projectScriptSelfRender(user, name);
},{icon:data.code?2:1,time:2000,shade: [0.3, '#000']},2000);
});
}
});
//-----
});
//------
});
}
//新建文件
function createScriptFile(type, user, name, file) {
if (type == 1) {
gogsPost('project_script_self_create', {'user':user,'name':name,'file': file }, function(data){
var rdata = $.parseJSON(data.data);
if(!rdata['status']){
layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
showMsg(rdata.msg, function(){
$(".layui-layer-btn1").click();
onlineEditFile(0,rdata['data']['abs_file']);
projectScriptSelfRender(user, name);
}, {icon:1,shade: [0.3, '#000']},2000);
});
return;
}
layer.open({
type: 1,
shift: 5,
closeBtn: 1,
area: '320px',
title: '新建自定义脚本',
btn:['新建','关闭'],
content: '<div class="bt-form pd20">\
<div class="line">\
<input type="text" class="bt-input-text" name="Name" id="newFileName" value="" placeholder="文件名" style="width:100%" />\
</div>\
</div>',
success:function(){
$("#newFileName").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(){
var file = $("#newFileName").val();;
createScriptFile(1, user, name, file);
}
});
}
function projectScriptSelf(user, name){
layer.open({
type: 1,
title: '项目('+user+'/'+name+')自定义脚本',
area: '500px',
content:"<div class='bt-form pd15'>\
<button id='create_script' class='btn btn-success btn-sm' type='button' style='margin-right: 5px;''>添加脚本</button>\
<div style='float:right;'>\
<span style='line-height: 23px;'>开启自定义脚本</span>\
<input class='btswitch btswitch-ios' id='open_script' type='checkbox'>\
<label id='script_hook_enable' class='btswitch-btn' for='open_script' style='display: inline-flex;line-height:38px;margin-left: 4px;float: right;'></label>\
</div>\
<div id='gogs_self_table' class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th style='width:100px;'>脚本文件名</th><th>状态</th><th>操作</th></tr></thead>\
<tbody></tbody>\
</table>\
<div class='dataTables_paginate paging_bootstrap pagination' style='margin-top:0px;'>\
<ul class='page'><div class='gogs_page'></div></ul>\
</div>\
</div>\
</div>",
success:function(){
projectScriptSelfRender(user, name);
$('#create_script').click(function(){
createScriptFile(0, user, name);
});
$('#script_hook_enable').click(function(){
var enable = $('#open_script').prop('checked');
var enable_option = '0';
if (!enable){
enable_option = '1';
}
gogsPost('project_script_self_enable', {'user':user,'name':name,'enable':enable_option}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
projectScriptSelfRender(user, name);
},{icon:data.status?1:2,shade: [0.3, '#000']},2000);
});
});
}
});
}
function getRsaPublic(){
gogsPost('get_rsa_public', {}, function(data){
var rdata = $.parseJSON(data.data);
@@ -361,8 +765,8 @@ function giteaRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>默认使用MySQL,第一个启动加载各种配置,并修改成正确的数据库配置</li>';
readme += '<li>邮件端口使用456,gogs仅支持使用STARTTLS的SMTP协议</li>';
readme += '<li>如果使用项目中脚本本地同步,<a target="_blank" href="https://github.com/midoks/mdserver-web/wiki/%E6%8F%92%E4%BB%B6%E7%AE%A1%E7%90%86%5Bgogs%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%5D#%E5%90%AF%E5%8A%A8gogs%E5%90%8E%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BD%BF%E7%94%A8hook%E8%84%9A%E6%9C%AC%E5%90%8C%E6%AD%A5%E4%BB%A3%E7%A0%81%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AFssh%E7%AB%AF%E5%8F%A3">点击查看</></li>';
readme += '<li>邮件端口使用456,gitea仅支持使用STARTTLS的SMTP协议</li>';
readme += '<li>项目【加载脚本】后,会自动同步到wwwroot目录下</li>';
readme += '<li><a href="#" onclick="getRsaPublic();">点击查看本机公钥</></li>';
readme += '</ul>';
+16 -3
View File
@@ -10,14 +10,19 @@ GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
git config --global credential.helper store
git config --global pull.rebase false
# echo $GIT_PROJECT_DIR
if [ ! -d $GIT_PROJECT_DIR ];then
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
git clone $GITADDR
git clone $GITADDR --branch main
if [ "$?" != "0" ];then
git clone $GITADDR
fi
fi
unset GIT_DIR
cd $GIT_PROJECT_DIR && git pull
# func 2
@@ -26,9 +31,17 @@ cd $GIT_PROJECT_DIR && git pull
#更新的目的地址
WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT}
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
if [ ! -d $WEB_PATH ];then
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
else
if [ -f $GIT_PROJECT_DIR/exclude.list ];then
rsync -vauP --delete --exclude-from="$GIT_PROJECT_DIR/exclude.list" $GIT_PROJECT_DIR/ $WEB_PATH
else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
fi
fi
sysName=`uname`
if [ $sysName == 'Darwin' ]; then
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
H_DIR={$HOOK_DIR}
HL_DIR={$HOOK_LOGS_DIR}
SH_LIST=`cd ${H_DIR} && ls | grep ".sh$"`
for sh_f in $SH_LIST; do
ABS_FILE=${H_DIR}/${sh_f}
ABS_LOGS=${HL_DIR}/${sh_f}.log
echo "sh ${ABS_FILE} 2>${ABS_LOGS}"
sh -x ${ABS_FILE} 2>${ABS_LOGS}
done
+14 -3
View File
@@ -1,13 +1,22 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('gogs');">服务</p>
<p onclick="pluginInitD('gogs');">自启动</p>
<!-- <p onclick="pluginConfig('gogs',null, 'init_conf');">启动配置</p> -->
<p onclick="gogsEdit();">手动编辑</p>
<p onclick="gogsEditTpl();">手动编辑</p>
<p onclick="pluginConfig('gogs',null, 'conf');">配置文件</p>
<p onclick="gogsSetConfig();">配置修改</p>
<p onclick="gogsUserList();">用户列表</p>
<p onclick="gogsRepoList();">项目列表</p>
<p onclick="pluginLogs('gogs',null,'run_log');">运行日志</p>
<p onclick="pluginLogs('gogs',null,'post_receive_log');" title="提交post-receive日志">提交日志</p>
<p onclick="gogsRead();">使用说明</p>
@@ -18,6 +27,8 @@
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=gogs&f=js/gogs.js");
pluginService('gogs');
resetPluginWinHeight(530);
$.getScript( "/plugins/file?name=gogs&f=js/gogs.js",function(){
pluginService('gogs');
});
</script>
+394 -12
View File
@@ -456,6 +456,13 @@ def submitGogsConf():
return mw.returnJson(True, '设置成功')
def gogsEditTpl():
data = {}
data['post_receive'] = getPluginDir() + '/hook/post-receive.tpl'
data['commit'] = getPluginDir() + '/hook/commit.tpl'
return mw.getJson(data)
def userList():
conf = getConf()
@@ -470,6 +477,66 @@ def userList():
import math
args = getArgs()
data = checkArgs(args, ['page', 'page_size'])
if not data[0]:
return data[1]
page = int(args['page'])
page_size = int(args['page_size'])
search = ''
if 'search' in args:
search = args['search']
user_where1 = ''
user_where2 = ''
if search != '':
user_where1 = ' where name like "%' + search + '%"'
user_where2 = ' where name like "%' + search + '%"'
data = {}
data['root_url'] = getRootUrl()
start = (page - 1) * page_size
list_count = pQuery('select count(id) as num from user' + user_where1)
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user ' + user_where2 + ' order by id desc limit ' + str(start) + ',' + str(page_size))
data['list'] = mw.getPage({'count': count, 'p': page,
'row': page_size, 'tojs': 'gogsUserList'})
data['page'] = page
data['page_size'] = page_size
data['page_count'] = int(math.ceil(count / page_size))
data['data'] = list_data
return mw.returnJson(True, 'OK', data)
def checkRepoListIsHasScript(data):
path = getRootPath()
for x in range(len(data)):
name = data[x]['name'] + '/' + data[x]['repo'] + '.git'
path_tmp = path + '/' + name + '/custom_hooks/post-receive'
if os.path.exists(path_tmp):
data[x]['has_hook'] = True
else:
data[x]['has_hook'] = False
return data
def repoList():
conf = getConf()
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
conf = getDbConfValue()
gtype = getGogsDbType(conf)
if gtype != 'mysql':
return mw.returnJson(False, "仅支持mysql数据操作!")
import math
args = getArgs()
data = checkArgs(args, ['page', 'page_size'])
if not data[0]:
return data[1]
@@ -484,13 +551,25 @@ def userList():
data['root_url'] = getRootUrl()
repo_where1 = ''
repo_where2 = ''
if search != '':
repo_where1 = ' where name like "%' + search + '%"'
repo_where2 = ' where r.name like "%' + search + '%"'
start = (page - 1) * page_size
list_count = pQuery('select count(id) as num from user')
list_count = pQuery(
'select count(id) as num from repository' + repo_where1)
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size))
sql = 'select r.id,r.owner_id,r.name as repo, u.name from repository r left join user u on r.owner_id=u.id ' + repo_where2 + ' order by r.id desc limit ' + \
str(start) + ',' + str(page_size)
# print(sql)
list_data = pQuery(sql)
# print(list_data)
list_data = checkRepoListIsHasScript(list_data)
data['list'] = mw.getPage({'count': count, 'p': page,
'row': page_size, 'tojs': 'gogsUserList'})
'row': page_size, 'tojs': 'gogsRepoListPage'})
data['page'] = page
data['page_size'] = page_size
data['page_count'] = int(math.ceil(count / page_size))
@@ -561,7 +640,7 @@ def userProjectList():
data['data'] = ret_data
data['args'] = args
data['list'] = mw.getPage(
{'count': dlist_sum, 'p': page, 'row': page_size, 'tojs': 'userProjectList'})
{'count': dlist_sum, 'p': page, 'row': page_size, 'tojs': 'userProjectListPage'})
return mw.returnJson(True, 'OK', data)
@@ -668,11 +747,294 @@ def projectScriptDebug():
return mw.getJson(data)
def gogsEdit():
data = {}
data['post_receive'] = getPluginDir() + '/hook/post-receive.tpl'
data['commit'] = getPluginDir() + '/hook/commit.tpl'
return mw.getJson(data)
def projectScriptRun():
args = getArgs()
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
path = getRootPath() + '/' + user + '/' + name
commit_sh = path + '/custom_hooks/commit'
commit_log = path + '/custom_hooks/sh.log'
script_run = 'sh -x ' + commit_sh + ' 2>' + commit_log
if not os.path.exists(commit_sh):
return mw.returnJson(False, '脚本文件不存在!')
mw.execShell(script_run)
return mw.returnJson(True, '脚本文件执行成功,观察日志!')
def projectScriptSelf():
args = getArgs()
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
self_logs_path = custom_hooks + '/self_logs'
if not os.path.exists(self_logs_path):
os.mkdir(self_logs_path)
self_hook_file = custom_hooks + '/self_hook.sh'
self_hook_exist = False
if os.path.exists(self_hook_file):
self_hook_exist = True
dlist = []
if os.path.exists(self_path):
for filename in os.listdir(self_path):
tmp = {}
filePath = self_path + '/' + filename
if os.path.isfile(filePath):
tmp['path'] = filePath
tmp['name'] = os.path.basename(filePath)
tmp['is_hidden'] = False
if tmp['name'].endswith('.txt'):
tmp['is_hidden'] = True
dlist.append(tmp)
dlist_sum = len(dlist)
# print(dlist)
rdata = {}
rdata['data'] = dlist
rdata['self_hook'] = self_hook_exist
rdata['list'] = mw.getPage(
{'count': dlist_sum, 'p': 1, 'row': 100, 'tojs': 'self_page'})
return mw.returnJson(True, 'ok', rdata)
def projectScriptSelf_Create():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
self_path = path = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
abs_file = self_path + '/' + file + '.sh'
if os.path.exists(abs_file):
return mw.returnJson(False, '脚本已经存在!')
mw.writeFile(abs_file, "#!/bin/bash\necho `date +'%Y-%m-%d %H:%M:%S'`\n")
rdata = {}
rdata['abs_file'] = abs_file
return mw.returnJson(True, '创建文件成功!', rdata)
def projectScriptSelf_Del():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
abs_file = self_path + '/' + file
# print(abs_file)
if not os.path.exists(abs_file):
return mw.returnJson(False, '脚本已经删除!')
os.remove(abs_file)
# 日志也删除
log_file = custom_hooks + '/self_logs/' + file + '.log'
if os.path.exists(log_file):
os.remove(log_file)
return mw.returnJson(True, '脚本删除成功!')
def projectScriptSelf_Logs():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
self_path = path = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks/self_logs'
if not os.path.exists(self_path):
os.mkdir(self_path)
logs_file = self_path + '/' + file + '.log'
if os.path.exists(logs_file):
rdata = {}
rdata['path'] = logs_file
return mw.returnJson(True, 'ok', rdata)
return mw.returnJson(False, '日志不存在!')
def projectScriptSelf_Run():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self/' + file
self_logs_path = custom_hooks + '/self_logs/' + file + '.log'
shell = "sh -x " + self_path + " 2>" + self_logs_path + ' &'
mw.execShell(shell)
return mw.returnJson(True, '执行成功!')
def projectScriptSelf_Rename():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'o_file', 'n_file'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
o_file = args['o_file']
n_file = args['n_file']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
o_file_abs = self_path + '/' + o_file + '.sh'
if not os.path.exists(o_file_abs):
return mw.returnJson(False, '原文件已经不存在了!')
n_file_abs = self_path + '/' + n_file + '.sh'
os.rename(o_file_abs, n_file_abs)
# 日志也删除
log_file = custom_hooks + '/self_logs/' + o_file + '.sh.log'
if os.path.exists(log_file):
os.remove(log_file)
return mw.returnJson(True, '重命名成功!')
def projectScriptSelf_Enable():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'enable'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
enable = args['enable']
custom_path = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
# 替换commit配置
commit_path = custom_path + '/commit'
note = '#Gogs Script Don`t Remove and Change'
self_file = custom_path + '/self_hook.sh'
self_hook_tpl = getPluginDir() + '/hook/self_hook.tpl'
if enable == '1':
content = mw.readFile(self_hook_tpl)
content = content.replace('{$HOOK_DIR}', custom_path + '/self')
content = content.replace(
'{$HOOK_LOGS_DIR}', custom_path + '/self_logs')
mw.writeFile(self_file, content)
mw.execShell("chmod 777 " + self_file)
commit_content = mw.readFile(commit_path)
commit_content += "\n\n" + "bash " + self_file + " " + note
mw.writeFile(commit_path, commit_content)
return mw.returnJson(True, '开启成功!')
else:
commit_content = mw.readFile(commit_path)
rep = ".*" + note
commit_content = re.sub(rep, '', commit_content, re.M)
commit_content = commit_content.strip()
mw.writeFile(commit_path, commit_content)
if os.path.exists(self_file):
os.remove(self_file)
return mw.returnJson(True, '关闭成功!')
def projectScriptSelf_Status():
args = getArgs()
data = checkArgs(args, ['user', 'name', 'file', 'status'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
file = args['file']
status = args['status']
custom_hooks = getRootPath() + '/' + user + '/' + \
name + '/custom_hooks'
self_path = custom_hooks + '/self'
if not os.path.exists(self_path):
os.mkdir(self_path)
# 日志也删除
log_file = custom_hooks + '/self_logs/' + file + '.log'
if os.path.exists(log_file):
os.remove(log_file)
if status == '1':
file_abs = self_path + '/' + file
file_text_abs = self_path + '/' + file + '.txt'
os.rename(file_abs, file_text_abs)
return mw.returnJson(True, '开始禁用成功!')
else:
file_abs = self_path + '/' + file.strip('.txt')
file_text_abs = self_path + '/' + file
os.rename(file_text_abs, file_abs)
return mw.returnJson(True, '开始使用成功!')
return mw.returnJson(True, '禁用成功!')
def getRsaPublic():
@@ -732,8 +1094,12 @@ if __name__ == "__main__":
print(getGogsConf())
elif func == 'submit_gogs_conf':
print(submitGogsConf())
elif func == 'gogs_edit_tpl':
print(gogsEditTpl())
elif func == 'user_list':
print(userList())
elif func == 'repo_list':
print(repoList())
elif func == 'user_project_list':
print(userProjectList())
elif func == 'project_script_edit':
@@ -744,8 +1110,24 @@ if __name__ == "__main__":
print(projectScriptUnload())
elif func == 'project_script_debug':
print(projectScriptDebug())
elif func == 'gogs_edit':
print(gogsEdit())
elif func == 'project_script_run':
print(projectScriptRun())
elif func == 'project_script_self':
print(projectScriptSelf())
elif func == 'project_script_self_create':
print(projectScriptSelf_Create())
elif func == 'project_script_self_del':
print(projectScriptSelf_Del())
elif func == 'project_script_self_logs':
print(projectScriptSelf_Logs())
elif func == 'project_script_self_run':
print(projectScriptSelf_Run())
elif func == 'project_script_self_rename':
print(projectScriptSelf_Rename())
elif func == 'project_script_self_enable':
print(projectScriptSelf_Enable())
elif func == 'project_script_self_status':
print(projectScriptSelf_Status())
elif func == 'get_rsa_public':
print(getRsaPublic())
elif func == 'get_total_statistics':
+1 -1
View File
@@ -2,7 +2,7 @@
"ps": "Gogs是一款极易搭建的自助Git服务",
"name": "gogs",
"title": "Gogs",
"versions": ["0.11.86","0.12.9"],
"versions": ["0.11.86","0.12.9","0.13.0"],
"tip": "soft",
"checks": "server/gogs",
"path":"server/gogs",
+4
View File
@@ -9,6 +9,10 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
GOGS_DOWNLOAD='https://dl.gogs.io'
+482 -45
View File
@@ -1,19 +1,8 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function gogsPost(method,args,callback, title){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(str2Obj(args));
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
@@ -113,9 +102,8 @@ function submitGogsConf() {
});
}
function gogsEdit(){
gogsPost('gogs_edit',{} , function(data){
function gogsEditTpl(){
gogsPost('gogs_edit_tpl',{} , function(data){
// console.log(data);
var rdata = $.parseJSON(data.data);
var edit = '<p class="status">通用的手动编辑:</p>';
@@ -149,7 +137,7 @@ function gogsUserList(page, search) {
return;
}
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找用户名" id="find_user" style="height: 28px; border-radius: 3px;width: 435px;">';
content += '<button class="btn btn-success btn-sm" onclick="userFind();">查找</button></div>';
content += '<button class="btn btn-success btn-sm find_user" >查找</button></div>';
content += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
content += '<thead><tr>';
@@ -163,28 +151,84 @@ function gogsUserList(page, search) {
ulist = rdata['data']['data'];
for (i in ulist){
email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
var email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
var user_url = rdata['data']['root_url'] + ulist[i]["name"];
content += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td>'+ulist[i]["name"]+'</td>'+
'<td>'+email+'</td>'+
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i]["name"]+'\')">项目管理</a></td>'+
'<td><a class="btlink" target="_blank" href="'+user_url+'">项目管理</a></td>'+
'</tr>';
}
content += '</tbody>';
content += '</table></div>';
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
var page_html = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page_html += rdata['data']['list'];
page_html += '</div></ul></div>';
content += page;
content += page_html;
$(".soft-man-con").html(content);
$('.find_user').click(function(){
var name = $('#find_user').val();
gogsUserList(page, name);
});
});
}
function userProjectList(user, search){
layer.open({
type: 1,
title: '用户('+user+')项目列表',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div>\
<div id='gogs_table' class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th>项目</th><th>操作</th></tr></thead>\
<tbody></tbody>\
</table>\
<div class='dataTables_paginate paging_bootstrap pagination' style='margin-top:0px;'>\
<ul class='page'><div class='gogs_page'></div></ul>\
</div>\
</div>\
</div>\
</div>",
success:function(){
userProjectListPage(user,search);
}
});
}
function userProjectList2(user, search){
layer.open({
type: 1,
title: '用户('+user+')项目列表',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div>\
<div id='gogs_table' class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th>项目</th><th>操作</th></tr></thead>\
<tbody></tbody>\
</table>\
<div class='dataTables_paginate paging_bootstrap pagination' style='margin-top:0px;'>\
<ul class='page'><div class='gogs_page'></div></ul>\
</div>\
</div>\
</div>\
</div>",
success:function(){
userProjectListPage(user,search);
}
});
}
function userProjectListPage(user, search){
var req = {};
if (!isNaN(user)){
req['page'] = user;
@@ -200,8 +244,7 @@ function userProjectList(user, search){
if(typeof(search) != 'undefined'){
req['search'] = search;
}
$('.layui-layer-close1').click();
gogsPost('user_project_list', req, function(data){
var rdata = [];
try {
@@ -218,7 +261,8 @@ function userProjectList(user, search){
var project_list = rdata['data']['data'];
for (i in project_list) {
var name = project_list[i]['name'];
list += '<tr><td>'+name+'</td>\
list += '<tr>\
<td>'+name+'</td>\
<td>\
<a class="btlink" target="_blank" href="'+rdata['data']['root_url']+user+'/'+name+'">源码</a> | \
<a class="btlink" onclick="projectScript(\''+user+'\',\''+name+'\','+project_list[i]['has_hook']+');">脚本</a>\
@@ -226,28 +270,180 @@ function userProjectList(user, search){
</tr>';
}
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
$('#gogs_table tbody').html(list);
var loadOpen = layer.open({
type: 1,
title: '用户('+user+')项目列表',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div>\
<div class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th>项目</th><th>操作</th></tr></thead>\
<tbody>" + list + "</tbody>\
</table>" +
page +
"</div></div></div>"
});
var page = rdata['data']['list'];
$('#gogs_table .gogs_page').html(page);
});
}
function gogsRepoListPage(page, search){
var _data = {};
if (typeof(page) =='undefined'){
var page = 1;
}
_data['page'] = page;
_data['page_size'] = 10;
if(typeof(search) != 'undefined'){
_data['search'] = search;
}
gogsPost('repo_list', _data, function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var ulist = rdata['data']['data'];
var body = ''
for (i in ulist){
// console.log(ulist[i]);
var option = '';
if(ulist[i]['has_hook']){
option += '<a class="btlink unload" data-index="'+i+'">卸载脚本</a>' + ' | ';
option += '<a class="btlink load" data-index="'+i+'">重载</a>' + ' | ';
option += '<a class="btlink edit" data-index="'+i+'">编辑</a>' + ' | ';
option += '<a class="btlink debug" data-index="'+i+'">日志</a>' + ' | ';
option += '<a class="btlink run" data-index="'+i+'">手动</a>' + ' | ';
option += '<a class="btlink scripts" data-index="'+i+'" onclick="projectScriptSelf(\''+ulist[i]["name"]+'\',\''+ulist[i]["repo"]+'\')" >自定义</a>';
} else{
option += '<a data-index="'+i+'" class="btlink load">加载脚本</a>';
}
body += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td class="overflow_hide" style="width:70px;">' + ulist[i]["name"]+'</td>'+
'<td class="overflow_hide" style="width:70px;display: inline-block;">' + ulist[i]["repo"]+'</td>'+
'<td>' +
'<a class="btlink" target="_blank" href="'+rdata['data']['root_url']+ulist[i]["name"]+'/'+ulist[i]["repo"]+'">源码</a>' + ' | ' +
option +
'</td>' +
'</tr>';
}
$('#repo_list tbody').html(body);
$('#repo_list_page').html(rdata['data']['list']);
$('.find_repo').click(function(){
var find_repo = $('#find_repo').val();
gogsRepoListPage(page, find_repo);
});
$('#repo_list .load').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_load', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
gogsRepoListPage(page, search);
}, 2000);
});
});
$('#repo_list .unload').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_unload', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
gogsRepoListPage(page, search);
}, 2000);
});
});
$('#repo_list .edit').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_edit', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['data']['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
});
$('#repo_list .debug').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_debug', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
});
$('#repo_list .run').click(function(){
var i = $(this).data('index');
var user = ulist[i]["name"];
var name = ulist[i]["repo"];
gogsPost('project_script_run', {'user':user,'name':name}, function(data){
var data = $.parseJSON(data.data);
layer.msg(data.msg,{icon:data.status?1:2,time:2000,shade: [0.3, '#000']});
});
});
//---------
});
}
function gogsRepoList() {
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找项目" id="find_repo" style="height: 28px; border-radius: 3px;width: 435px;">';
content += '<button class="btn btn-success btn-sm find_repo" >查找</button></div>';
content += '<div id="repo_list" class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
content += '<thead><tr>';
content += '<th style="width:50px;">序号</th>';
content += '<th style="width:80px;">用户/组织</th>';
content += '<th style="width:80px;">项目名</th>';
content += '<th>操作</th>';
content += '</tr></thead>';
content += '<tbody></tbody>';
content += '</table></div>';
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="repo_list_page" class="page"></ul></div>';
content += page;
$(".soft-man-con").html(content);
gogsRepoListPage(1);
}
function projectScript(user, name,has_hook){
// console.log(user,name,has_hook);
var html = '';
@@ -288,7 +484,7 @@ function projectScriptLoad(user,name){
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
userProjectList(1);
gogsRepoListPage(1);
}, 2000);
});
}
@@ -302,11 +498,18 @@ function projectScriptUnload(user,name){
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
userProjectList(1);
gogsRepoListPage(1);
}, 2000);
});
}
function projectScriptRun(user, name){
gogsPost('project_script_run', {'user':user,'name':name}, function(data){
var data = $.parseJSON(data.data);
layer.msg(data.msg,{icon:data.code?2:1,time:2000,shade: [0.3, '#000']});
});
}
function projectScriptDebug(user,name){
gogsPost('project_script_debug', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
@@ -318,6 +521,240 @@ function projectScriptDebug(user,name){
});
}
function projectScriptSelfRender(user, name){
gogsPost('project_script_self', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
var data = rdata['data']['data'];
if (rdata['data']['self_hook']){
$('#open_script').prop('checked',true);
}
var body = '';
if(data.length == 0 ){
body += '<tr><td colspan="3" style="text-align:center;">无脚本数据</td></tr>';
} else{
for (var i = 0; i < data.length; i++) {
var b_status = '<a class="btlink status" data-index="'+i+'" target="_blank">已使用</a>';
if (data[i]["is_hidden"]){
b_status = '<a class="btlink status" data-index="'+i+'" target="_blank">已隐藏</a>';
}
body += '<tr>'+
'<td>' + data[i]["name"]+'</td>'+
'<td>' + b_status + '</td>'+
'<td>' +
'<a class="btlink del" data-index="'+i+'" target="_blank">删除</a>' + ' | ' +
'<a class="btlink edit" data-index="'+i+'" target="_blank">编辑</a>' + ' | ' +
'<a class="btlink logs" data-index="'+i+'" target="_blank">日志</a>' + ' | ' +
'<a class="btlink run" data-index="'+i+'" target="_blank">手动</a>' + ' | ' +
'<a class="btlink rename" data-index="'+i+'" target="_blank">重命名</a>' +
'</td></tr>';
}
}
$('#gogs_self_table tbody').html(body);
$('#gogs_self_table .page').html(rdata['data']['list']);
$('#gogs_self_table .status').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
var status = '1';
if (data[i]["is_hidden"]){
status = '0';
}
gogsPost('project_script_self_status', {'user':user,'name':name,'file':file, status:status}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
projectScriptSelfRender(user, name);
},{icon:data.code?2:1,time:2000,shade: [0.3, '#000']},2000);
});
});
$('#gogs_self_table .del').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
gogsPost('project_script_self_del', {'user':user,'name':name,'file':file}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
projectScriptSelfRender(user, name);
},{icon:data.code?2:1,time:2000,shade: [0.3, '#000']},2000);
});
});
$('#gogs_self_table .edit').click(function(){
var i = $(this).data('index');
var path = data[i]["path"];
onlineEditFile(0,path);
});
$('#gogs_self_table .logs').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
gogsPost('project_script_self_logs', {'user':user,'name':name,'file':file}, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
if (rdata['status']){
onlineEditFile(0, rdata['data']['path']);
} else {
layer.msg(rdata.msg,{icon:data.status?2:1,time:2000,shade: [0.3, '#000']});
}
});
});
$('#gogs_self_table .run').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
if (data[i]["is_hidden"]){
layer.msg("已经禁用,不能执行!",{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
gogsPost('project_script_self_run', {'user':user,'name':name,'file':file}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg,{icon:data.status?1:2,time:2000,shade: [0.3, '#000']});
});
});
$('#gogs_self_table .rename').click(function(){
var i = $(this).data('index');
var file = data[i]["name"];
if (data[i]["is_hidden"]){
layer.msg("已经禁用,不能执行!",{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
file = file.split('.sh')[0];
layer.open({
type: 1,
shift: 5,
closeBtn: 1,
area: '320px',
title: '重命名',
btn:['设置','关闭'],
content: '<div class="bt-form pd20">\
<div class="line">\
<input type="text" class="bt-input-text" name="Name" id="newFileName" value="'+file+'" placeholder="文件名" style="width:100%" />\
</div>\
</div>',
success:function(){
$("#newFileName").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(){
var n_file = $("#newFileName").val();
var o_file = file;
gogsPost('project_script_self_rename', {'user':user,'name':name,'o_file':o_file,'n_file':n_file}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
$(".layui-layer-btn1").click();
projectScriptSelfRender(user, name);
},{icon:data.code?2:1,time:2000,shade: [0.3, '#000']},2000);
});
}
});
//-----
});
//------
});
}
//新建文件
function createScriptFile(type, user, name, file) {
if (type == 1) {
gogsPost('project_script_self_create', {'user':user,'name':name,'file': file }, function(data){
var rdata = $.parseJSON(data.data);
if(!rdata['status']){
layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
showMsg(rdata.msg, function(){
$(".layui-layer-btn1").click();
onlineEditFile(0,rdata['data']['abs_file']);
projectScriptSelfRender(user, name);
}, {icon:1,shade: [0.3, '#000']},2000);
});
return;
}
layer.open({
type: 1,
shift: 5,
closeBtn: 1,
area: '320px',
title: '新建自定义脚本',
btn:['新建','关闭'],
content: '<div class="bt-form pd20">\
<div class="line">\
<input type="text" class="bt-input-text" name="Name" id="newFileName" value="" placeholder="文件名" style="width:100%" />\
</div>\
</div>',
success:function(){
$("#newFileName").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(){
var file = $("#newFileName").val();;
createScriptFile(1, user, name, file);
}
});
}
function projectScriptSelf(user, name){
layer.open({
type: 1,
title: '项目('+user+'/'+name+')自定义脚本',
area: '500px',
content:"<div class='bt-form pd15'>\
<button id='create_script' class='btn btn-success btn-sm' type='button' style='margin-right: 5px;''>添加脚本</button>\
<div style='float:right;'>\
<span style='line-height: 23px;'>开启自定义脚本</span>\
<input class='btswitch btswitch-ios' id='open_script' type='checkbox'>\
<label id='script_hook_enable' class='btswitch-btn' for='open_script' style='display: inline-flex;line-height:38px;margin-left: 4px;float: right;'></label>\
</div>\
<div id='gogs_self_table' class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th style='width:100px;'>脚本文件名</th><th>状态</th><th>操作</th></tr></thead>\
<tbody></tbody>\
</table>\
<div class='dataTables_paginate paging_bootstrap pagination' style='margin-top:0px;'>\
<ul class='page'><div class='gogs_page'></div></ul>\
</div>\
</div>\
</div>",
success:function(){
projectScriptSelfRender(user, name);
$('#create_script').click(function(){
createScriptFile(0, user, name);
});
$('#script_hook_enable').click(function(){
var enable = $('#open_script').prop('checked');
var enable_option = '0';
if (!enable){
enable_option = '1';
}
gogsPost('project_script_self_enable', {'user':user,'name':name,'enable':enable_option}, function(data){
var data = $.parseJSON(data.data);
showMsg(data.msg ,function(){
projectScriptSelfRender(user, name);
},{icon:data.status?1:2,shade: [0.3, '#000']},2000);
});
});
}
});
}
function getRsaPublic(){
gogsPost('get_rsa_public', {}, function(data){
var rdata = $.parseJSON(data.data);
@@ -344,7 +781,7 @@ function gogsRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>默认使用MySQL,第一个启动加载各种配置,并修改成正确的数据库配置</li>';
readme += '<li>邮件端口使用456,gogs仅支持使用STARTTLS的SMTP协议</li>';
readme += '<li>如果使用项目中脚本本地同步,<a target="_blank" href="https://github.com/midoks/mdserver-web/wiki/%E6%8F%92%E4%BB%B6%E7%AE%A1%E7%90%86%5Bgogs%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%5D#%E5%90%AF%E5%8A%A8gogs%E5%90%8E%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BD%BF%E7%94%A8hook%E8%84%9A%E6%9C%AC%E5%90%8C%E6%AD%A5%E4%BB%A3%E7%A0%81%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AFssh%E7%AB%AF%E5%8F%A3">点击查看</></li>';
readme += '<li>项目【加载脚本】后,会自动同步到wwwroot目录下</li>';
readme += '<li><a href="#" onclick="getRsaPublic();">点击查看本机公钥</></li>';
readme += '</ul>';
+5 -3
View File
@@ -1,12 +1,12 @@
global
daemon
#一般情况下,可关闭
log 127.0.0.1 local0
pidfile /tmp/haproxy.pid
maxconn 4000
user haproxy
group haproxy
defaults
mode http
log global
@@ -20,6 +20,7 @@ listen stats
mode http
bind *:10800
stats enable
stats refresh 10
stats uri /haproxy
stats realm Haproxy\ Statistics
stats auth admin:admin
@@ -28,10 +29,11 @@ frontend http-in
bind *:1080
default_backend servers
option forwardfor
option httpclose
#option httpclose
option http-keep-alive
backend servers
balance roundrobin
server web1 0.0.0.0:9090 check
server web1 0.0.0.0:9090 check inter 2000 rise 2 fall 5
+11 -15
View File
@@ -97,6 +97,8 @@ def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$HA_USER}', mw.getRandomString(8))
content = content.replace('{$HA_PWD}', mw.getRandomString(10))
content = content.replace('{$SERVER_APP}', service_path + '/haproxy')
return content
@@ -150,6 +152,13 @@ def initDreplace():
def haOp(method):
file = initDreplace()
# check config
sdir = getServerDir()
cmd_check = sdir+'/sbin/haproxy -c -f ' + sdir + '/haproxy.conf'
chk_data = mw.execShell(cmd_check)
if chk_data[1]!= '':
return chk_data[1]
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' haproxy')
if data[1] == '':
@@ -206,19 +215,8 @@ def initdUinstall():
def runLog():
path = getConf()
content = mw.readFile(path)
rep = 'log\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
def getPort():
path = getConf()
content = mw.readFile(path)
rep = 'listen\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
path = getServerDir() + "/haproxy.log"
return path
if __name__ == "__main__":
@@ -247,7 +245,5 @@ if __name__ == "__main__":
print(readConfigTpl())
elif func == 'run_log':
print(runLog())
elif func == 'query_log':
print(queryLog())
else:
print('error')
+5 -3
View File
@@ -1,6 +1,8 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# for mac
export PATH=$PATH:/opt/homebrew/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
@@ -23,12 +25,12 @@ else
fi
if [ "${2}" == "" ];then
echo '缺少安装脚本...' > $install_tmp
echo '缺少安装脚本...'
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
echo '缺少安装脚本2...' > $install_tmp
echo '缺少安装脚本2...'
exit 0
fi
+1 -1
View File
@@ -10,7 +10,7 @@ function spPostMin(method, args, callback){
$.post('/plugins/run', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
layer.msg(data.msg,{icon:0,time:10000,shade: [0.3, '#000']});
return;
}
+37
View File
@@ -0,0 +1,37 @@
global
daemon
pidfile /tmp/haproxy.pid
maxconn 4000
user haproxy
group haproxy
defaults
mode http
log global
option httplog
timeout connect 10s
timeout client 15s
timeout server 15s
listen stats
mode http
bind *:10800
stats enable
stats refresh 10
stats uri /haproxy
stats realm Haproxy\ Statistics
stats auth {$HA_USER}:{$HA_PWD}
frontend http-in
bind *:1080
default_backend servers
option forwardfor
option http-keep-alive
backend servers
balance roundrobin
server web1 0.0.0.0:9090 check inter 2000 rise 2 fall 5
+39 -4
View File
@@ -20,12 +20,26 @@ VERSION=2.6.4
MIN_VERSION=2.6
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
echo '正在安装Haproxy软件...'
mkdir -p $serverPath/haproxy
APP_DIR=${serverPath}/source/haproxy
mkdir -p $APP_DIR
LOCAL_ADDR=common
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ] || [ "$?" == "0" ] ;then
LOCAL_ADDR=cn
fi
if [ "${LOCAL_ADDR}" == "cn" ];then
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
wget -O ${APP_DIR}/haproxy-${VERSION}.tar.gz https://dl.midoks.icu/soft/haproxy/haproxy-${VERSION}.tar.gz
fi
fi
if [ ! -f ${APP_DIR}/haproxy-${VERSION}.tar.gz ];then
if [ $sysName == 'Darwin' ]; then
@@ -49,7 +63,28 @@ Install_App()
fi
echo $MIN_VERSION > $serverPath/haproxy/version.pl
echo 'Install_HA' > $install_tmp
echo '安装Haproxy成功' > $install_tmp
#Haproxy日志配置
if [ -f /etc/rsyslog.conf ];then
find_ha=`cat /etc/rsyslog.conf | grep haproxy`
if [ "$find_ha" != "" ];then
echo $find_ha
else
echo "---------------------------------------------"
echo "" > ${serverPath}/haproxy/haproxy.log
echo "local0.* ${serverPath}/haproxy/haproxy.log" >> /etc/rsyslog.conf
systemctl restart syslog
echo "syslog默认的haproxy配置"
echo "local0.* ${serverPath}/haproxy/haproxy.log >> /etc/rsyslog.conf"
echo "---------------------------------------------"
fi
fi
#删除解压源码
if [ -d ${APP_DIR}/haproxy-${VERSION} ];then
rm -rf ${APP_DIR}/haproxy-${VERSION}
fi
}
Uninstall_App()
@@ -59,7 +94,7 @@ Uninstall_App()
fi
rm -rf $serverPath/haproxy
echo "Uninstall_HA" > $install_tmp
echo "卸载Haproxy成功"
}
action=$1
+32
View File
@@ -0,0 +1,32 @@
! Configuration File for keepalived
global_defs {
router_id MYSQL_MHA
}
vrrp_script chk_mysql_port {
script "{$SERVER_PATH}/keepalived/scripts/chk.sh mysql"
interval 2
weight –5
fall 2
rise 1
}
vrrp_instance VI_MYSQL {
state MASTER
interface {$ETH_XX}
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.10
}
track_script {
chk_mysql_port
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

+22
View File
@@ -0,0 +1,22 @@
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('keepalived');">服务</p>
<p onclick="pluginInitD('keepalived');">自启动</p>
<!-- <p onclick="pluginConfig('keepalived');">配置修改</p> -->
<p onclick="pluginConfigTpl('keepalived',$('.plugin_version').attr('version'));">配置修改</p>
<p onclick="pluginConfigListTpl('keepalived',$('.plugin_version').attr('version'),'config_scripts_tpl','read_config_tpl');">脚本模板</p>
<p onclick="pluginLogs('keepalived','','run_log');">日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(530);
$.getScript( "/plugins/file?name=keepalived&f=js/keepalived.js", function(){
pluginService('keepalived', $('.plugin_version').attr('version'));
});
</script>
+353
View File
@@ -0,0 +1,353 @@
# coding:utf-8
import sys
import io
import os
import time
import re
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'keepalived'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
current_os = mw.getOs()
if current_os == 'darwin':
return '/tmp/' + getPluginName()
if current_os.startswith('freebsd'):
return '/etc/rc.d/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getConf():
path = getServerDir() + "/etc/keepalived/keepalived.conf"
return path
def getConfTpl():
path = getPluginDir() + "/config/keepalived.conf"
return path
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
def getArgs():
args = sys.argv[3:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':')
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def configTpl():
path = getPluginDir() + '/tpl'
pathFile = os.listdir(path)
tmp = []
for one in pathFile:
file = path + '/' + one
tmp.append(file)
return mw.getJson(tmp)
def readConfigTpl():
args = getArgs()
data = checkArgs(args, ['file'])
if not data[0]:
return data[1]
content = mw.readFile(args['file'])
content = contentReplace(content)
return mw.returnJson(True, 'ok', content)
def defaultScriptsTpl():
path = getServerDir() + "/scripts/chk.sh"
return path
def configScriptsTpl():
path = getServerDir() + '/scripts'
pathFile = os.listdir(path)
tmp = []
for one in pathFile:
file = path + '/' + one
tmp.append(file)
return mw.getJson(tmp)
def status():
data = mw.execShell(
"ps aux|grep keepalived |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def contentReplace(content):
service_path = os.path.dirname(os.getcwd())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$PLUGIN_PATH}', getPluginDir())
# 网络接口
ethx = mw.execShell("route -n | grep ^0.0.0.0 | awk '{print $8}'")
if ethx[1]!='':
# 未找到
content = content.replace('{$ETH_XX}', 'eth1')
else:
# 已找到
content = content.replace('{$ETH_XX}', ethx[0])
return content
def copyScripts():
# 复制检查脚本
src_scripts_path = getPluginDir() + '/scripts'
dst_scripts_path = getServerDir() + '/scripts'
if not os.path.exists(dst_scripts_path):
mw.execShell('mkdir -p ' + dst_scripts_path)
olist = os.listdir(src_scripts_path)
for o in range(len(olist)):
src_file = src_scripts_path+'/'+olist[o]
dst_file = dst_scripts_path+'/'+olist[o]
content = mw.readFile(src_file)
content = contentReplace(content)
mw.writeFile(dst_file, content)
cmd = 'chmod +x ' + dst_file
mw.execShell(cmd)
return True
return False
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/' + getPluginName()
# initd replace
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = contentReplace(content)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# log
dataLog = getServerDir() + '/data'
if not os.path.exists(dataLog):
mw.execShell('chmod +x ' + file_bin)
# config replace
dst_conf = getServerDir() + '/etc/keepalived/keepalived.conf'
dst_conf_init = getServerDir() + '/init.pl'
if not os.path.exists(dst_conf_init):
content = mw.readFile(getConfTpl())
content = contentReplace(content)
mw.writeFile(dst_conf, content)
mw.writeFile(dst_conf_init, 'ok')
# 复制检查脚本
copyScripts()
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/' + getPluginName() + '.service'
if os.path.exists(systemDir) and not os.path.exists(systemService):
systemServiceTpl = getPluginDir() + '/init.d/' + getPluginName() + '.service.tpl'
service_path = mw.getServerDir()
content = mw.readFile(systemServiceTpl)
content = contentReplace(content)
mw.writeFile(systemService, content)
mw.execShell('systemctl daemon-reload')
return file_bin
def kpOp(method):
file = initDreplace()
current_os = mw.getOs()
if current_os == "darwin":
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
if current_os.startswith("freebsd"):
data = mw.execShell('service ' + getPluginName() + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return data[1]
def start():
return kpOp('start')
def stop():
return kpOp('stop')
def restart():
status = kpOp('restart')
log_file = runLog()
mw.execShell("echo '' > " + log_file)
return status
def reload():
return kpOp('reload')
def getPort():
conf = getServerDir() + '/keepalived.conf'
content = mw.readFile(conf)
rep = "^(" + 'port' + ')\s*([.0-9A-Za-z_& ~]+)'
tmp = re.search(rep, content, re.M)
if tmp:
return tmp.groups()[1]
return '6379'
def initdStatus():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
# freebsd initd install
if current_os.startswith('freebsd'):
import shutil
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="YES"')
return 'ok'
mw.execShell('systemctl enable ' + getPluginName())
return 'ok'
def initdUinstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="NO"')
return 'ok'
mw.execShell('systemctl disable ' + getPluginName())
return 'ok'
def runLog():
return getServerDir() + '/' + getPluginName() + '.log'
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'run_info':
print(runInfo())
elif func == 'conf':
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'config_tpl':
print(configTpl())
elif func == 'default_scripts_tpl':
print(defaultScriptsTpl())
elif func == 'config_scripts_tpl':
print(configScriptsTpl())
elif func == 'read_config_tpl':
print(readConfigTpl())
else:
print('error')
+17
View File
@@ -0,0 +1,17 @@
{
"sort": 7,
"ps": "[<span style='color:red;'>内网</span>]优秀的高可用软件",
"name": "keepalived",
"title": "keepalived",
"shell": "install.sh",
"versions":["2.2.8"],
"tip": "soft",
"checks": "server/keepalived",
"path": "server/keepalived",
"display": 1,
"author": "keepalived",
"date": "2023-10-22",
"home": "https://keepalived.org/download.html",
"type": "soft",
"pid": "4"
}
@@ -0,0 +1,13 @@
[Unit]
Description=Redis In-Memory Data Store
After=network.target
[Service]
Type=forking
ExecStart={$SERVER_PATH}/keepalived/sbin/keepalived -D
ExecReload=/bin/kill -USR1 $MAINPID
Restart=on-failure
StandardOutput={$SERVER_PATH}/keepalived/keepalived.log
[Install]
WantedBy=multi-user.target
+78
View File
@@ -0,0 +1,78 @@
#!/bin/sh
#
# Startup script for the Keepalived daemon
#
# processname: keepalived
# pidfile: /var/run/keepalived.pid
# config: /etc/keepalived/keepalived.conf
# chkconfig: - 21 79
# description: Start and stop Keepalived
# Source function library
if [ -f /etc/rc.d/init.d/functions ];then
. /etc/rc.d/init.d/functions
fi
SYS_KP_FILE={$SERVER_PATH}/keepalived/etc/sysconfig/keepalived
# Source configuration file (we set KEEPALIVED_OPTIONS there)
if [ -f $SYS_KP_FILE ];then
. $SYS_KP_FILE
fi
RETVAL=0
prog="keepalived"
start() {
echo -n $"Starting $prog: "
{$SERVER_PATH}/keepalived/sbin/keepalived ${KEEPALIVED_OPTIONS}
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
}
stop() {
echo -n $"Stopping $prog: "
pkill keepalived
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
}
reload() {
echo -n $"Reloading $prog: "
pkill keepalived -1
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;
condrestart)
if [ -f /var/lock/subsys/$prog ]; then
stop
start
fi
;;
status)
status keepalived
RETVAL=$?
;;
*)
echo "Usage: $0 {start|stop|reload|restart|condrestart|status}"
RETVAL=1
esac
exit $RETVAL
+100
View File
@@ -0,0 +1,100 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# for mac
export PATH=$PATH:/opt/homebrew/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/keepalived && bash install.sh install 2.2.8
# cd /www/server/mdserver-web/plugins/keepalived && bash install.sh install 2.2.8
# /www/server/keepalived/init.d/keepalived start
# systemctl status keepalived
# systemctl restart keepalived
# ifconfig
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
Install_App()
{
echo '正在安装keepalived脚本文件...'
mkdir -p $serverPath/source/keepalived
if [ ! -f $serverPath/source/keepalived/keepalived-${VERSION}.tar.gz ];then
wget -O $serverPath/source/keepalived/keepalived-${VERSION}.tar.gz https://keepalived.org/software/keepalived-${VERSION}.tar.gz
fi
#检测文件是否损坏.
md5_file_ok=8c26f75a8767e5341d82696e1e717115
if [ -f $serverPath/source/keepalived/keepalived-${VERSION}.tar.gz ];then
md5_file=`md5sum $serverPath/source/keepalived/keepalived-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_file}" != "${md5_file_ok}" ]; then
echo "keepalived-${version} 下载文件不完整,重新安装"
rm -rf $serverPath/source/keepalived/keepalived-${VERSION}.tar.gz
fi
fi
echo $serverPath/keepalived/keepalived-${VERSION}
if [ -d $serverPath/keepalived/keepalived-${VERSION} ];then
cd $serverPath/keepalived/keepalived-${VERSION}
else
cd $serverPath/source/keepalived && tar -zxvf keepalived-${VERSION}.tar.gz
cd $serverPath/keepalived/keepalived-${VERSION}
fi
cd $serverPath/source/keepalived/keepalived-${VERSION}
./configure --prefix=$serverPath/keepalived && make && make install
# for test
# mkdir -p $serverPath/keepalived
if [ -d $serverPath/keepalived ];then
echo "${VERSION}" > $serverPath/keepalived/version.pl
echo 'keepalived安装完成'
cd ${rootPath} && python3 ${rootPath}/plugins/keepalived/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/keepalived/index.py initd_install
fi
if [ -d $serverPath/source/keepalived/keepalived-${VERSION} ];then
rm -rf $serverPath/source/keepalived/keepalived-${VERSION}
fi
}
Uninstall_App()
{
if [ -f /usr/lib/systemd/system/keepalived.service ];then
systemctl stop keepalived
systemctl disable keepalived
rm -rf /usr/lib/systemd/system/keepalived.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/keepalived.service ];then
systemctl stop keepalived
systemctl disable keepalived
rm -rf /lib/systemd/system/keepalived.service
systemctl daemon-reload
fi
if [ -f $serverPath/keepalived/initd/keepalived ];then
$serverPath/keepalived/initd/keepalived stop
fi
rm -rf $serverPath/keepalived
echo "keepalived卸载完成"
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+143
View File
@@ -0,0 +1,143 @@
function kpPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'keepalived';
req_data['func'] = method;
req_data['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', req_data, function(data) {
layer.close(loadT);
if (!data.status){
//错误展示10S
layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function kpPostCallbak(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'keepalived';
req_data['func'] = method;
args['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
//redis负载状态 start
function redisStatus(version) {
redisPost('run_info',version, {},function(data){
var rdata = $.parseJSON(data.data);
// if (!rdata.status){
// layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
// return;
// }
hit = (parseInt(rdata.keyspace_hits) / (parseInt(rdata.keyspace_hits) + parseInt(rdata.keyspace_misses)) * 100).toFixed(2);
var con = '<div class="divtable">\
<table class="table table-hover table-bordered" style="width: 490px;">\
<thead><th>字段</th><th>当前值</th><th>说明</th></thead>\
<tbody>\
<tr><th>uptime_in_days</th><td>' + rdata.uptime_in_days + '</td><td>已运行天数</td></tr>\
<tr><th>tcp_port</th><td>' + rdata.tcp_port + '</td><td>当前监听端口</td></tr>\
<tr><th>connected_clients</th><td>' + rdata.connected_clients + '</td><td>连接的客户端数量</td></tr>\
<tr><th>used_memory_rss</th><td>' + toSize(rdata.used_memory_rss) + '</td><td>Redis当前占用的系统内存总量</td></tr>\
<tr><th>used_memory</th><td>' + toSize(rdata.used_memory) + '</td><td>Redis当前已分配的内存总量</td></tr>\
<tr><th>used_memory_peak</th><td>' + toSize(rdata.used_memory_peak) + '</td><td>Redis历史分配内存的峰值</td></tr>\
<tr><th>mem_fragmentation_ratio</th><td>' + rdata.mem_fragmentation_ratio + '%</td><td>内存碎片比率</td></tr>\
<tr><th>total_connections_received</th><td>' + rdata.total_connections_received + '</td><td>运行以来连接过的客户端的总数量</td></tr>\
<tr><th>total_commands_processed</th><td>' + rdata.total_commands_processed + '</td><td>运行以来执行过的命令的总数量</td></tr>\
<tr><th>instantaneous_ops_per_sec</th><td>' + rdata.instantaneous_ops_per_sec + '</td><td>服务器每秒钟执行的命令数量</td></tr>\
<tr><th>keyspace_hits</th><td>' + rdata.keyspace_hits + '</td><td>查找数据库键成功的次数</td></tr>\
<tr><th>keyspace_misses</th><td>' + rdata.keyspace_misses + '</td><td>查找数据库键失败的次数</td></tr>\
<tr><th>hit</th><td>' + hit + '%</td><td>查找数据库键命中率</td></tr>\
<tr><th>latest_fork_usec</th><td>' + rdata.latest_fork_usec + '</td><td>最近一次 fork() 操作耗费的微秒数</td></tr>\
<tbody>\
</table></div>';
$(".soft-man-con").html(con);
});
}
//redis负载状态 end
//配置修改
function getRedisConfig(version) {
redisPost('get_redis_conf', version,'',function(data){
// console.log(data);
var rdata = $.parseJSON(data.data);
// console.log(rdata);
var mlist = '';
for (var i = 0; i < rdata.length; i++) {
var w = '70'
if (rdata[i].name == 'error_reporting') w = '250';
var ibody = '<input style="width: ' + w + 'px;" class="bt-input-text mr5" name="' + rdata[i].name + '" value="' + rdata[i].value + '" type="text" >';
switch (rdata[i].type) {
case 0:
var selected_1 = (rdata[i].value == 1) ? 'selected' : '';
var selected_0 = (rdata[i].value == 0) ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;"><option value="1" ' + selected_1 + '>开启</option><option value="0" ' + selected_0 + '>关闭</option></select>'
break;
case 1:
var selected_1 = (rdata[i].value == 'On') ? 'selected' : '';
var selected_0 = (rdata[i].value == 'Off') ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;"><option value="On" ' + selected_1 + '>开启</option><option value="Off" ' + selected_0 + '>关闭</option></select>'
break;
}
mlist += '<p><span>' + rdata[i].name + '</span>' + ibody + ', <font>' + rdata[i].ps + '</font></p>'
}
var con = '<style>.conf_p p{margin-bottom: 2px}</style><div class="conf_p" style="margin-bottom:0">' + mlist + '\
<div style="margin-top:10px; padding-right:15px" class="text-right"><button class="btn btn-success btn-sm mr5" onclick="getRedisConfig(\'' + version + '\')">刷新</button>\
<button class="btn btn-success btn-sm" onclick="submitConf(\'' + version + '\')">保存</button></div>\
</div>'
$(".soft-man-con").html(con);
});
}
//提交配置
function submitConf(version) {
var data = {
version: version,
bind: $("input[name='bind']").val(),
'port': $("input[name='port']").val(),
'timeout': $("input[name='timeout']").val(),
maxclients: $("input[name='maxclients']").val(),
databases: $("input[name='databases']").val(),
requirepass: $("input[name='requirepass']").val(),
maxmemory: $("input[name='maxmemory']").val(),
};
redisPost('submit_redis_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
# 计划任务,恢复后,可自动拉起keepalived
# bash {$SERVER_PATH}/keepalived/scripts/chk.sh mysql
cd {$SERVER_PATH}/keepalived
# check script bash
curPath=`pwd`
rootPath=$(dirname "$curPath")
SOFT=$1
if [ "$SOFT" == "mysql" ];then
bash ${rootPath}/keepalived/scripts/chk_mysql.sh > ${rootPath}/keepalived/keepalived.log
else
echo "you should use [chk.sh mysql] exp ."
fi
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
# 计划任务,恢复后,可自动拉起keepalived
# bash {$SERVER_PATH}/keepalived/scripts/chk_mysql.sh
counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
data_time=`date +'%Y-%m-%d %H:%M:%S'`
if [ "${counter}" -eq "0" ]; then
echo "${data_time}: start check mysql status, mysql is down, stop keepalive ..."
systemctl stop keepalived
echo "${data_time}: start check mysql end !!!"
fi
# 恢复后,自动拉起
# systemctl start keepalived
if [ "${counter}" -gt "0" ]; then
echo "${data_time}: start check mysql status, mysql is up, start keepalive"
keepalived_status=`which systemctl && systemctl status keepalived | grep Active | grep inactive`
if [ "$keepalived_status" != "" ];then
systemctl start keepalived
fi
echo "${data_time}: start check mysql end !!!"
fi
@@ -0,0 +1,46 @@
# keepalived for lvs-nat
# 未测试通过
global_defs {
router_id HA_LVS
}
vrrp_sync_group HA_LVS_NAT {
group {
HA_LVS_NAT
}
}
vrrp_instance HA_LVS_NAT {
state MASTER
interface bond1
virtual_router_id 222
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.212.100/25 dev bond1
}
}
virtual_server 192.168.212.100 80 {
delay_loop 6
lb_algo rr
lb_kind NAT
protocol TCP
real_server 192.168.212.129 80 {
weight 100
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 15000
}
}
}
@@ -0,0 +1,32 @@
! Configuration File for keepalived
global_defs {
router_id MYSQL_MHA
}
vrrp_script chk_mysql_port {
script "{$SERVER_PATH}/scripts/chk.sh mysql"
interval 2
weight –5
fall 2
rise 1
}
vrrp_instance VI_MYSQL {
state 这里所有节点定义为BACKUP
interface {$ETH_XX}
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.10
}
track_script {
chk_mysql_port
}
}
@@ -0,0 +1,32 @@
! Configuration File for keepalived
global_defs {
router_id MYSQL_MHA
}
vrrp_script chk_mysql_port {
script "{$SERVER_PATH}/scripts/chk.sh mysql"
interval 2
weight –5
fall 2
rise 1
}
vrrp_instance VI_MYSQL {
state MASTER
interface {$ETH_XX}
virtual_router_id 51
priority 101
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.10
}
track_script {
chk_mysql_port
}
}
@@ -0,0 +1,49 @@
! Configuration File for keepalived
global_defs {
# 路由标识,主从保持一致
router_id MYSQL_MHA
}
#检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
vrrp_script chk_mysql_port {
# 这里通过脚本监测
script "{$SERVER_PATH}/scripts/chk.sh mysql"
# 脚本执行间隔,每2s检测一次
interval 2
# 脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
weight –5
# 检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
fall 2
# 检测1次成功就算成功。但不修改优先级
rise 1
}
vrrp_instance VI_1 {
# 这里所有节点定义为BACKUP/MASTER
state BACKUP
# 指定虚拟ip的网卡(可能需要手动查看)
# route -n | grep ^0.0.0.0 | awk '{print $8}'
interface {$ETH_XX}
# 路由器标识,MASTER和BACKUP必须是一致的
virtual_router_id 51
# 定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级
priority 99
# 通知间隔秒数(心跳频率)
advert_int 1
# 不抢占模式,在优先级高的机器上设置即可,优先级低的机器可不设置
nopreempt
# 认证信息配置,主从服务器保持一致
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
# 虚拟IP(VIP) | 根据情况设置
192.168.10.10
}
track_script {
chk_mysql_port
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

+19
View File
@@ -0,0 +1,19 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('lvs');">服务</p>
<p onclick="pluginInitD('lvs');">自启动</p>
<p onclick="pluginConfig('lvs');">配置修改</p>
<!-- <p onclick="pluginLogs('lvs','','run_log',30);">运行日志</p> -->
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(480);
$.getScript( "/plugins/file?name=lvs&f=js/lvs.js", function(){
pluginService('lvs');
});
</script>
+180
View File
@@ -0,0 +1,180 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import string
import subprocess
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'lvs'
def getIpvsadm():
return 'ipvsadm'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def getConf():
path = '/etc/default/ipvsadm'
return path
def status():
data = mw.execShell("which ipvsadm")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/' + getPluginName()
# initd replace
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = contentReplace(content)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
return file_bin
def haOp(method):
return 'ok'
def start():
return haOp('start')
def stop():
return haOp('stop')
def restart():
return haOp('restart')
def reload():
return haOp('reload')
def initdStatus():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
mw.execShell('systemctl enable ' + getIpvsadm())
return 'ok'
def initdUinstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
mw.execShell('systemctl disable ' + getIpvsadm())
return 'ok'
def runLog():
path = getConf()
content = mw.readFile(path)
rep = 'log\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'conf':
print(getConf())
else:
print('error')
+18
View File
@@ -0,0 +1,18 @@
{
"sort": 7,
"ps": "[<span style='color:red;'>内网</span>]LVS超强负载均衡,通过ipvsadm管理[<span style='color:red;'>暂时不可用</span>]",
"name": "lvs",
"title": "LVS",
"shell": "install.sh",
"versions":["1.0"],
"updates":["1.0"],
"tip": "soft",
"checks": "server/lvs",
"path": "server/lvs",
"display": 1,
"author": "midoks",
"date": "2023-11-17",
"home": "http://www.linuxvirtualserver.org/",
"type": 0,
"pid": "4"
}
+83
View File
@@ -0,0 +1,83 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH=$PATH:/opt/homebrew/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
sys_os=`uname`
VERSION=1.6.22
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/lvs && bash install.sh install 1.0
# cd /www/server/mdserver-web/plugins/lvs && bash install.sh install 1.0
Install_LVS(){
mkdir -p $serverPath/source
which ipvsadm
if [ "$?" == "0" ];then
echo '已安装LVS!!'
exit 0
fi
echo '正在安装LVS...'
# 检测平台命令
which apt
if [ "$?" == "0" ];then
apt install -y ipvsadm
fi
which yum
if [ "$?" == "0" ];then
yum install -y ipvsadm
fi
which ipvsadm
if [ "$?" == "0" ];then
echo '正在安装LVS成功!'
mkdir -p $serverPath/lvs
ipv_version=`ipvsadm -v | awk '{print $2}'`
if [ "$ipv_version" != "" ];then
echo "$ipv_version" > $serverPath/lvs/version.pl
else
echo '1.0' > $serverPath/lvs/version.pl
fi
cd ${rootPath} && python3 ${rootPath}/plugins/lvs/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/lvs/index.py initd_install
else
echo '正在安装LVS失败!'
fi
}
Uninstall_LVS()
{
# 检测平台命令
which apt
if [ "$?" == "0" ];then
apt remove -y ipvsadm
fi
which yum
if [ "$?" == "0" ];then
yum uninstall -y ipvsadm
fi
echo "卸载LVS完成"
if [ -d $serverPath/lvs ];then
rm -rf $serverPath/lvs
fi
}
action=$1
if [ "${1}" == 'install' ];then
Install_LVS
else
Uninstall_LVS
fi
+53
View File
@@ -0,0 +1,53 @@
function lvsPostMin(method, args, callback){
var req_data = {};
req_data['name'] = 'lvs';
req_data['func'] = method;
if (typeof(args) != 'undefined' && args!=''){
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function lvsPost(method, args, callback, msg = '正在获取...'){
var loadT = layer.msg(msg, { icon: 16, time: 0, shade: 0.3 });
lvsPostMin(method,args,function(data){
layer.close(loadT);
if(typeof(callback) == 'function'){
callback(data);
}
});
}
function secToTime(s) {
var t;
if(s > -1){
var hour = Math.floor(s/3600);
var min = Math.floor(s/60) % 60;
var sec = s % 60;
if(hour < 10) {
t = '0'+ hour + ":";
} else {
t = hour + ":";
}
if(min < 10){t += "0";}
t += min + ":";
if(sec < 10){t += "0";}
t += sec.toFixed(2);
}
return t;
}
+20
View File
@@ -0,0 +1,20 @@
debian
# 查看网卡
ls /sys/class/net/
ifconfig ens256 172.16.204.100 netmask 255.255.255.255 broadcast 192.168.212.100 up
route add -host 172.16.204.100 dev ens256
ipvsadm -A -t 172.16.204.100:80 -s rr
ipvsadm -a -t 172.16.204.100:80 -r 172.16.204.129:80 -m
# 清空LVS规则
ipvsadm -C
# 查看LVS
ipvsadm -L -n
+1
View File
@@ -12,6 +12,7 @@
<p onclick="myPerfOpt();">性能优化</p>
<p onclick="myLogs();">日志</p>
<p onclick="pluginLogs('mariadb',$('.plugin_version').attr('version'),'show_log');">慢日志</p>
<p onclick="myBinLogs();">BINLOG</p>
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
+211 -35
View File
@@ -90,6 +90,12 @@ def getDataDir():
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getLogBinName():
file = getConf()
content = mw.readFile(file)
rep = 'log-bin\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getPidFile():
file = getConf()
@@ -294,6 +300,53 @@ def binLog():
mw.writeFile(conf, con)
return mw.returnJson(True, '设置成功!')
def binLogList():
args = getArgs()
data = checkArgs(args, ['page', 'page_size', 'tojs'])
if not data[0]:
return data[1]
page = int(args['page'])
page_size = int(args['page_size'])
data_dir = getDataDir()
log_bin_name = getLogBinName()
alist = os.listdir(data_dir)
log_bin_l = []
for x in range(len(alist)):
f = alist[x]
t = {}
if f.startswith(log_bin_name) and not f.endswith('.index'):
abspath = data_dir + '/' + f
t['name'] = f
t['size'] = os.path.getsize(abspath)
t['time'] = mw.getDataFromInt(os.path.getctime(abspath))
log_bin_l.append(t)
log_bin_l = sorted(log_bin_l, key=lambda x: x['time'], reverse=True)
# print(log_bin_l)
# print(data_dir, log_bin_name)
count = len(log_bin_l)
page_start = (page - 1) * page_size
page_end = page_start + page_size
if page_end > count:
page_end = count
data = {}
page_args = {}
page_args['count'] = count
page_args['p'] = page
page_args['row'] = page_size
page_args['tojs'] = args['tojs']
data['page'] = mw.getPage(page_args)
data['data'] = log_bin_l[page_start:page_end]
return mw.getJson(data)
def cleanBinLog():
db = pMysqlDb()
@@ -302,21 +355,6 @@ def cleanBinLog():
return mw.returnJson(True, '清理BINLOG成功!')
def setSkipGrantTables(v):
'''
设置是否密码验证
'''
conf = getConf()
con = mw.readFile(conf)
if v:
if con.find('#skip-grant-tables') != -1:
con = con.replace('#skip-grant-tables', 'skip-grant-tables')
else:
con = con.replace('skip-grant-tables', '#skip-grant-tables')
mw.writeFile(conf, con)
return True
def getErrorLog():
args = getArgs()
path = getDataDir()
@@ -402,6 +440,8 @@ def initMariaDbPwd():
pwd + ' -e "drop database test";'
mw.execShell(drop_test_db)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
if hostname != 'localhost':
@@ -412,8 +452,6 @@ def initMariaDbPwd():
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
return True
@@ -579,7 +617,7 @@ def setMyPort():
restart()
return mw.returnJson(True, '编辑成功!')
# python3 plugins/mariadb/index.py run_info {}
def runInfo(version):
if status(version) == 'stop':
@@ -755,6 +793,13 @@ def importDbBackup():
return mw.returnJson(True, 'ok')
def rootPwd():
return pSqliteDb('config').where(
'id=?', (1,)).getField('mysql_root')
# python3 plugins/mariadb/index.py import_db_external {"file":"xx.sql","name":"demo1"}
# python3 plugins/mariadb/index.py import_db_external {"file":"db_demo1_20231221_203614 2.sql","name":"demo1"}
def importDbExternal():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
@@ -801,6 +846,9 @@ def importDbExternal():
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文件')
@@ -808,12 +856,14 @@ def importDbExternal():
sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd
mysql_cmd = getServerDir() + '/bin/mariadb -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql
mysql_cmd = getServerDir() + '/bin/mariadb -S ' + sock + ' -uroot -p"' + \
pwd + '" ' + name + ' < "' + import_sql+'"'
# print(mysql_cmd)
os.system(mysql_cmd)
os.remove(import_sql)
if ext != 'sql':
os.remove(import_sql)
return mw.returnJson(True, 'ok')
@@ -977,7 +1027,7 @@ def syncGetDatabases():
host = user["Host"]
break
ps = mw.getMsg('INPUT_PS')
ps = vdb_name
if vdb_name == 'test':
ps = mw.getMsg('DATABASE_TEST')
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
@@ -1049,12 +1099,21 @@ def setRootPwd(version=''):
if not data[0]:
return data[1]
#强制修改
force = 0
if 'force' in args and args['force'] == '1':
force = 1
password = args['password']
try:
pdb = pMysqlDb('mysql')
result = pdb.query("show databases")
isError = isSqlError(result)
if isError != None:
if force == 1:
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (password,))
return mw.returnJson(True, '【强制修改】数据库root密码修改成功(不意为成功连接数据)!')
return isError
cmd = "ALTER USER 'root'@'localhost' IDENTIFIED BY '" + password + "';"
@@ -1064,7 +1123,12 @@ def setRootPwd(version=''):
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (password,))
orm = pMysqlDb()
orm.execute("flush privileges")
return mw.returnJson(True, '数据库root密码修改成功!')
msg = ''
if force == 1:
msg = ',无须强制!'
return mw.returnJson(True, '数据库root密码修改成功!' + msg)
except Exception as ex:
return mw.returnJson(False, '修改错误:' + str(ex))
@@ -1271,16 +1335,58 @@ def setDbAccess():
psdb.where('username=?', (name,)).save('accept,rw', (access, 'rw',))
return mw.returnJson(True, '设置成功!')
def openSkipGrantTables():
mycnf = getConf()
content = mw.readFile(mycnf)
content = content.replace('#skip-grant-tables','skip-grant-tables')
mw.writeFile(mycnf, content)
return True
def closeSkipGrantTables():
mycnf = getConf()
content = mw.readFile(mycnf)
content = content.replace('skip-grant-tables','#skip-grant-tables')
mw.writeFile(mycnf, content)
return True
def resetDbRootPwd(version):
serverdir = getServerDir()
myconf = serverdir + "/etc/my.cnf"
pwd = mw.getRandomString(16)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
db_option = "-S " + serverdir + "/mysql.sock"
cmd_pass = serverdir + '/bin/mariadb ' + db_option + ' -uroot -e'
cmd_pass = cmd_pass + \
"\"flush privileges;use mysql;grant all privileges on *.* to 'root'@'localhost' identified by '" + pwd + "';"
cmd_pass = cmd_pass + "flush privileges;\""
data = mw.execShell(cmd_pass)
# print(data)
return True
def fixDbAccess(version):
pdb = pMysqlDb()
mdb_ddir = getDataDir()
if not os.path.exists(mdb_ddir):
return mw.returnJson(False, '数据目录不存在,尝试重启重建!')
try:
pdb = pMysqlDb()
psdb = pSqliteDb('databases')
data = pdb.query('show databases')
isError = isSqlError(data)
if isError != None:
# 重置密码
appCMD(version, 'stop')
mw.execShell("rm -rf " + getServerDir() + "/data")
openSkipGrantTables()
appCMD(version, 'start')
time.sleep(3)
resetDbRootPwd(version)
appCMD(version, 'stop')
closeSkipGrantTables()
appCMD(version, 'start')
return mw.returnJson(True, '修复成功!')
return mw.returnJson(True, '正常无需修复!')
@@ -1583,6 +1689,13 @@ def setDbMasterAccess():
psdb.where('username=?', (username,)).save('accept', (access,))
return mw.returnJson(True, '设置成功!')
def resetMaster(version=''):
pdb = pMysqlDb()
r = pdb.execute('reset master')
isError = isSqlError(r)
if isError != None:
return isError
return mw.returnJson(True, '重置成功!')
def getMasterDbList(version=''):
args = getArgs()
@@ -1894,8 +2007,7 @@ def getMasterRepSlaveUserCmd(version):
if mode == "gtid":
sql = "CHANGE MASTER " + connection_name + "TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', " + "MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_USE_GTID=no,MASTER_CONNECT_RETRY=10;"
clist[0]['password'] + "',MASTER_USE_GTID=no,MASTER_CONNECT_RETRY=10;"
else:
sql = "CHANGE MASTER " + connection_name + "TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
@@ -2181,6 +2293,58 @@ def getSlaveList(version=''):
data['data'] = dlist
return mw.getJson(data)
def trySlaveSyncBugfix(version=''):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动', [])
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode != 'sync-user':
return mw.returnJson(False, '仅支持【同步账户】模式')
conn = pSqliteDb('slave_sync_user')
slave_sync_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_sync_data) < 1:
return mw.returnJson(False, '需要先添加【同步用户】配置!')
# print(slave_sync_data)
# 本地从库
sdb = pMysqlDb()
gtid_purged = ''
for i in range(len(slave_sync_data)):
port = slave_sync_data[i]['port']
password = slave_sync_data[i]['pass']
host = slave_sync_data[i]['ip']
user = slave_sync_data[i]['user']
# print(port, password, host)
mdb = mw.getMyORM()
mdb.setHost(host)
mdb.setPort(port)
mdb.setUser(user)
mdb.setPwd(password)
mdb.setSocket('')
# var_gtid = mdb.query('show VARIABLES like "%gtid_purged%"')
var_gtid = mdb.query('select @@global.gtid_current_pos as Value')
#print(var_gtid)
if len(var_gtid) > 0:
gtid_purged += var_gtid[0]['Value'] + ','
gtid_purged = gtid_purged.strip(',')
sql = "set @@global.gtid_slave_pos='" + gtid_purged + "'"
sdb.query('stop all slaves')
# print(sql)
sdb.query(sql)
sdb.query('start all slaves')
return mw.returnJson(True, '修复成功!')
def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
@@ -2221,7 +2385,7 @@ def parseSlaveSyncCmd(cmd):
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
# python3 plugins/mariadb/index.py init_slave_status {}
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
@@ -2262,7 +2426,7 @@ def initSlaveStatusSyncUser(version=''):
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
return mw.returnJson(False, base_t + '->CMD同步命令不合规范:'+str(e))
pdb.query(cmd_sql)
@@ -2447,8 +2611,7 @@ def fullSync(version=''):
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
'/index.py do_full_sync {"db":"' + args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
@@ -2470,6 +2633,7 @@ def fullSync(version=''):
return json.dumps({'code': 0, 'msg': '点击开始,开始同步!', 'progress': 0})
# python3 plugins/mariadb/index.py do_full_sync {"db":"demo1","sign":"","beigin":"1"}
def doFullSync(version=''):
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
@@ -2507,13 +2671,16 @@ def doFullSyncUser(version=''):
ip = data['ip']
bak_file = '/tmp/tmp.sql'
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 10})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file
# https://mariadb.com/kb/zh-cn/mariadb-dump/
dump_sql_data = getServerDir() + "/bin/mariadb-dump -f --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p'" + apass + "' " + sync_db + ">" + bak_file
print(dump_sql_data)
mw.execShell(dump_sql_data)
@@ -2521,8 +2688,9 @@ def doFullSyncUser(version=''):
if os.path.exists(bak_file):
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db + ' < ' + bak_file
my_import_cmd = getServerDir() + '/bin/mariadb -S ' + sock + " -uroot -p'" + pwd + \
"' " + sync_db + '<' + bak_file
print(my_import_cmd)
mw.execShell(my_import_cmd)
pinfo = parseSlaveSyncCmd(data['cmd'])
@@ -2724,6 +2892,8 @@ if __name__ == "__main__":
print(getConf())
elif func == 'bin_log':
print(binLog())
elif func == 'binlog_list':
print(binLogList())
elif func == 'clean_bin_log':
print(cleanBinLog())
elif func == 'error_log':
@@ -2740,6 +2910,8 @@ if __name__ == "__main__":
print(setMyPort())
elif func == 'init_pwd':
print(initMysqlPwd())
elif func == 'root_pwd':
print(rootPwd())
elif func == 'get_db_list':
print(getDbList())
elif func == 'set_db_backup':
@@ -2790,6 +2962,8 @@ if __name__ == "__main__":
print(getDbrunMode(version))
elif func == 'set_dbrun_mode':
print(setDbrunMode(version))
elif func == 'reset_master':
print(resetMaster(version))
elif func == 'get_masterdb_list':
print(getMasterDbList(version))
elif func == 'get_master_status':
@@ -2814,6 +2988,8 @@ if __name__ == "__main__":
print(getMasterRepSlaveUserCmd(version))
elif func == 'get_slave_list':
print(getSlaveList(version))
elif func == 'try_slave_sync_bugfix':
print(trySlaveSyncBugfix(version))
elif func == 'get_slave_sync_cmd':
print(getSlaveSyncCmd(version))
elif func == 'get_slave_ssh_list':
+186
View File
@@ -0,0 +1,186 @@
# 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
if mw.isAppleSystem():
cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
info = mw.execShell(cmd)
p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
sys.path.append(p)
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'mariadb'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getConf():
path = getServerDir() + '/etc/my.cnf'
return path
def getDataDir():
file = getConf()
content = mw.readFile(file)
rep = 'datadir\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getRelayLogName():
file = getConf()
content = mw.readFile(file)
rep = 'relay-log\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getLogBinName():
file = getConf()
content = mw.readFile(file)
rep = 'log-bin\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def binLogListLook(args):
file = args['file']
line = args['line']
data_dir = getDataDir()
my_bin = getServerDir() + '/bin'
my_binlog_cmd = my_bin + '/mysqlbinlog'
cmd = my_binlog_cmd + ' --no-defaults ' + \
data_dir + '/' + file + '|tail -' + str(line)
data = mw.execShell(cmd)
rdata = {}
rdata['cmd'] = cmd
rdata['data'] = data[0]
return rdata
def binLogListLookDecode(args):
file = args['file']
line = args['line']
data_dir = getDataDir()
my_bin = getServerDir() + '/bin'
my_binlog_cmd = my_bin + '/mysqlbinlog'
cmd = my_binlog_cmd + ' --no-defaults --base64-output=decode-rows -vvvv ' + \
data_dir + '/' + file + '|tail -' + str(line)
data = mw.execShell(cmd)
rdata = {}
rdata['cmd'] = cmd
rdata['data'] = data[0]
return rdata
def binLogListTraceRelay(args):
rdata = {}
file = args['file']
line = args['line']
relay_name = getRelayLogName()
data_dir = getDataDir()
alist = os.listdir(data_dir)
relay_list = []
for x in range(len(alist)):
f = alist[x]
t = {}
if f.startswith(relay_name) and not f.endswith('.index'):
relay_list.append(f)
relay_list = sorted(relay_list, reverse=True)
if len(relay_list) == 0:
rdata['cmd'] = ''
rdata['data'] = '无Relay日志'
return rdata
file = relay_list[0]
my_bin = getServerDir() + '/bin'
my_binlog_cmd = my_bin + '/mysqlbinlog'
cmd = my_binlog_cmd + ' --no-defaults --base64-output=decode-rows -vvvv ' + \
data_dir + '/' + file + '|tail -' + str(line)
data = mw.execShell(cmd)
rdata['cmd'] = cmd
rdata['data'] = data[0]
return rdata
def binLogListTraceBinLog(args):
rdata = {}
file = args['file']
line = args['line']
data_dir = getDataDir()
log_bin_name = getLogBinName()
alist = os.listdir(data_dir)
log_bin_l = []
for x in range(len(alist)):
f = alist[x]
t = {}
if f.startswith(log_bin_name) and not f.endswith('.index'):
log_bin_l.append(f)
if len(log_bin_l) == 0:
rdata['cmd'] = ''
rdata['data'] = '无BINLOG'
return rdata
log_bin_l = sorted(log_bin_l, reverse=True)
file = log_bin_l[0]
my_bin = getServerDir() + '/bin'
my_binlog_cmd = my_bin + '/mysqlbinlog'
cmd = my_binlog_cmd + ' --no-defaults --base64-output=decode-rows -vvvv ' + \
data_dir + '/' + file + '|tail -' + str(line)
data = mw.execShell(cmd)
rdata['cmd'] = cmd
rdata['data'] = data[0]
return rdata
+1 -1
View File
@@ -8,7 +8,7 @@
"uninstall_pre_inspection":true,
"checks": "server/mariadb",
"path": "server/mariadb",
"versions":["10.6","10.7","10.8","10.9","10.11","11.0"],
"versions":["10.6","10.7","10.8","10.9","10.11","11.0","11.1","11.2","11.3"],
"shell":"install.sh",
"checks":"server/mariadb",
"path":"server/mariadb",
+1 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
curPath=`pwd`
+269 -10
View File
@@ -58,6 +58,62 @@ function myAsyncPost(method,args){
return syncPost('/plugins/run', {name:'mysql', func:method, args:_args});
}
function myPostCallbak(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'mariadb';
req_data['func'] = method;
req_data['script']='index_mariadb';
args['version'] = version;
if (typeof(args) == 'string' && args == ''){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function myPostCallbakN(method, version, args,callback){
var req_data = {};
req_data['name'] = 'mariadb';
req_data['func'] = method;
req_data['script']='index_mariadb';
args['version'] = version;
if (typeof(args) == 'string' && args == ''){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function runInfo(){
myPost('run_info','',function(data){
@@ -83,7 +139,7 @@ function runInfo(){
<tr><th>活动/峰值连接数</th><td>' + rdata.Threads_running + '/' + rdata.Max_used_connections + '</td><td colspan="2">若值过大,增加max_connections</td></tr>\
<tr><th>线程缓存命中率</th><td>' + ((1 - rdata.Threads_created / rdata.Connections) * 100).toFixed(2) + '%</td><td colspan="2">若过低,增加thread_cache_size</td></tr>\
<tr><th>索引命中率</th><td>' + ((1 - rdata.Key_reads / rdata.Key_read_requests) * 100).toFixed(2) + '%</td><td colspan="2">若过低,增加key_buffer_size</td></tr>\
<tr><th>Innodb索引命中率</th><td>' + ((1 - rdata.Innodb_buffer_pool_reads / rdata.Innodb_buffer_pool_read_requests) * 100).toFixed(2) + '%</td><td colspan="2">若过低,增加innodb_buffer_pool_size</td></tr>\
<tr><th>Innodb索引命中率</th><td>' + (rdata.Innodb_buffer_pool_read_requests / (rdata.Innodb_buffer_pool_read_requests+rdata.Innodb_buffer_pool_reads)).toFixed(2) + '%</td><td colspan="2">若过低,增加innodb_buffer_pool_size</td></tr>\
<tr><th>查询缓存命中率</th><td>' + cache_size + '</td><td colspan="2">' + lan.soft.mysql_status_ps5 + '</td></tr>\
<tr><th>创建临时表到磁盘</th><td>' + ((rdata.Created_tmp_disk_tables / rdata.Created_tmp_tables) * 100).toFixed(2) + '%</td><td colspan="2">若过大,尝试增加tmp_table_size</td></tr>\
<tr><th>已打开的表</th><td>' + rdata.Open_tables + '</td><td colspan="2">若过大,增加table_cache_size</td></tr>\
@@ -438,13 +494,24 @@ function syncToDatabase(type){
}
function setRootPwd(type, pwd){
if (type==1){
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
},{icon: rdata.status ? 1 : 2});
});
return;
}
var index = layer.open({
type: 1,
area: '500px',
title: '修改数据库密码',
closeBtn: 1,
shift: 5,
btn:["提交","关闭"],
btn:["提交", "关闭", "复制ROOT密码", "强制修改"],
shadeClose: true,
content: "<form class='bt-form pd20' id='mod_pwd'>\
<div class='line'>\
@@ -454,16 +521,36 @@ function setRootPwd(type, pwd){
</div>\
</div>\
</form>",
yes:function(index,layero){
yes:function(layerIndex){
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
layer.close(layerIndex);
dbList();
layer.close(index);
},{icon: rdata.status ? 1 : 2});
});
return;
},
btn3:function(){
var password = $("#MyPassword").val();
copyText(password);
return false;
},
btn4:function(layerIndex){
layer.confirm('强制修改,是为了在重建时使用,确定强制?', {
btn: ['确定', '取消']
}, function(index, layero){
layer.close(index);
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password,force:'1'}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
layer.close(layerIndex);
dbList();
},{icon: rdata.status ? 1 : 2});
});
});
return false;
}
});
}
@@ -1160,6 +1247,146 @@ function dbList(page, search){
});
}
function myBinRollingLogs(_name, func, _args, line){
var file_line = 100;
if ( typeof(line) != 'undefined' ){
file_line = line;
}
var reqTimer = null;
function requestLogs(func,file,line){
myPostCallbakN(func,'',{'file':file,"line":line}, function(rdata){
var data = rdata.data.data;
var cmd = rdata.data.cmd;
if(data == '') {
data = '当前没有日志!';
}
$('#my_rolling_cmd').html(cmd);
$('#my_rolling_copy').click(function(){
copyText(cmd);
});
var ebody = '<textarea readonly="readonly" style="margin: 0px;width: 100%;height: 570px;background-color: #333;color:#fff; padding:0 5px" id="roll_info_log">'+data+'</textarea>';
$("#my_rolling_logs").html(ebody);
var ob = document.getElementById('roll_info_log');
ob.scrollTop = ob.scrollHeight;
});
}
layer.open({
type: 1,
title: _name + '日志',
area: ['800px','700px'],
end: function(){
if (reqTimer){
clearInterval(reqTimer);
}
},
content:'<div class="change-default" style="padding:0px 20px 0px;">\
<div class="divtable mtb10">\
<table class="table table-hover"><tr>\
<td id="my_rolling_cmd">cmd</td>\
<td id="my_rolling_copy" style="width:35px;"><span class="ico-copy cursor btcopy" title="复制密码"></span></td>\
<tr>\
</table>\
</div>\
</div>\
<div class="change-default" style="padding:0px 20px 0px;" id="my_rolling_logs">\
<textarea readonly="readonly" style="margin: 0px;width: 100%;height: 570px;background-color: #333;color:#fff; padding:0 5px" id="roll_info_log"></textarea>\
</div>',
success:function(){
var fileName = _args['file'];
requestLogs(func,fileName,file_line);
reqTimer = setInterval(function(){
requestLogs(func,fileName,file_line);
},1000);
}
});
}
function myBinLogsRender(page){
var _data = {};
if (typeof(page) =='undefined'){
var page = 1;
}
_data['page'] = page;
_data['page_size'] = 10;
_data['tojs'] = 'myBinLogsRender';
myPost('binlog_list', _data, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
var list = '';
for(i in rdata.data){
list += '<tr>';
list += '<td>' + rdata.data[i]['name'] +'</td>';
list += '<td>' + toSize(rdata.data[i]['size'])+'</td>';
list += '<td>' + rdata.data[i]['time'] +'</td>';
list += '<td style="text-align:right">';
list += '<a href="javascript:;" data-index="'+i+'" class="btlink look" class="btlink">查看</a> | ';
list += '<a href="javascript:;" data-index="'+i+'" class="btlink look_decode" class="btlink">解码查看</a>';
list += '</td></tr>';
}
if (rdata.data.length ==0){
list = '<tr><td colspan="4">无数据</td</tr>';
}
$("#binlog_list tbody").html(list);
$('#binlog_page').html(rdata.page);
$('#binlog_list .look').click(function(){
var i = $(this).data('index');
var file = rdata.data[i]['name'];
myBinRollingLogs('查看BINLOG','binLogListLook',{'file':file },100);
});
$('#binlog_list .look_decode').click(function(){
var i = $(this).data('index');
var file = rdata.data[i]['name'];
myBinRollingLogs('查看解码BINLOG','binLogListLookDecode',{'file':file },100);
});
});
}
function myBinLogs(){
var con = '<div class="safe bgw">\
<button class="btn btn-success btn-sm relay_trace" type="button" style="margin-right: 5px;">中继日志跟踪</button>\
<button class="btn btn-default btn-sm binlog_trace" type="button" style="margin-right: 5px;">最新BINLOG日志跟踪</button>\
<div id="binlog_list" class="divtable mtb10">\
<div class="tablescroll">\
<table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr>\
<th>文件名称</th>\
<th>大小</th>\
<th>时间</th>\
<th style="text-align:right;">操作</th>\
</tr></thead>\
<tbody></tbody></table>\
</div>\
<div id="binlog_page" class="dataTables_paginate paging_bootstrap page"></div>\
</div>\
</div>';
$(".soft-man-con").html(con);
myBinLogsRender(1);
$('.soft-man-con .relay_trace').click(function(){
myBinRollingLogs('中继日志跟踪','binLogListTraceRelay',{'file':''},100);
});
$('.soft-man-con .binlog_trace').click(function(){
myBinRollingLogs('最新BINLOG日志跟踪','binLogListTraceBinLog',{'file':''},100);
});
}
function myLogs(){
@@ -1603,6 +1830,14 @@ function setDbMasterAccess(username){
});
}
function resetMaster(){
myPost('reset_master', '', function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
},{icon: rdata.status ? 1 : 2});
},'正在执行重置master命令[reset master]');
}
function getMasterRepSlaveList(){
var _data = {};
if (typeof(page) =='undefined'){
@@ -2329,11 +2564,16 @@ function masterOrSlaveConf(version=''){
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
var btn_list = ['复制错误',"取消"];
if (info['Last_IO_Error'].search(/1236/i)>0){
btn_list = ['复制错误',"取消","尝试修复"];
}
layer.open({
type: 1,
title: '同步异常信息',
area: ['600px','300px'],
btn:['复制错误',"取消"],
btn:btn_list,
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
@@ -2348,10 +2588,20 @@ function masterOrSlaveConf(version=''){
</div>\
</form>",
success:function(){
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
},
yes:function(){
if (info['Last_IO_Error'] != ''){
@@ -2368,6 +2618,14 @@ function masterOrSlaveConf(version=''){
copyText(info['Slave_SQL_Running_State']);
return;
}
},
btn3:function(){
myPost('try_slave_sync_bugfix', {}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg, function(){
masterOrSlaveConf();
},{ icon: rdata.status ? 1 : 5 },2000);
});
}
});
});
@@ -2437,6 +2695,7 @@ function masterOrSlaveConf(version=''){
<p class="conf_p">\
<span class="f14 c6 mr20">Master[主]配置</span><span class="f14 c6 mr20"></span>\
<button class="btn '+(!rdata.status ? 'btn-danger' : 'btn-success')+' btn-xs btn-master">'+(!rdata.status ? '未开启' : '已开启') +'</button>\
<button class="btn btn-success btn-xs" onclick="resetMaster()">重置</button>\
</p>\
<hr/>\
<!-- master list -->\
+7 -6
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.11.2
MY_VER=10.11.6
Install_app()
{
@@ -102,16 +102,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+7 -6
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# https://mariadb.org/download/?t=mariadb
@@ -13,7 +13,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.6.12
MY_VER=10.6.16
Install_app()
{
@@ -105,16 +105,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.6' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -92,16 +92,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.7' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -92,16 +92,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.8' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+7 -6
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.9.5
MY_VER=10.9.8
Install_app()
{
@@ -102,16 +102,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.9' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+9 -7
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.0.1
MY_VER=11.0.4
Install_app()
{
@@ -100,17 +100,19 @@ Install_app()
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '11.0' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.1.3
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '11.1' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.2.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '11.2' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.3.1
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '11.3' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi

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