Compare commits

...
977 Commits
Author SHA1 Message Date
Mr Chen b76fad0b5c Merge pull request #267 from midoks/dev
0.11.0
2022-11-22 18:11:29 +08:00
midoks f357dfbd1a 0.11.0 发布 2022-11-22 18:09:38 +08:00
midoks ea56cd93c2 mysql导入优化 2022-11-22 15:17:35 +08:00
midoks cfd06d7721 Update index.py 2022-11-22 15:12:16 +08:00
midoks e3f5ddccef Update index.py 2022-11-22 15:10:33 +08:00
midoks cca3a5a899 up 2022-11-22 15:08:03 +08:00
midoks 908a1f660a up 2022-11-22 12:56:33 +08:00
midoks dfc3030900 Update index.py 2022-11-22 12:04:46 +08:00
midoks 0ab8800813 Update index.py 2022-11-22 11:39:00 +08:00
midoks 1d66f9c355 Update pg.py 2022-11-22 11:33:15 +08:00
midoks 84a8e755a8 up 2022-11-22 11:31:58 +08:00
midoks f17d4c5bef Update index.py 2022-11-22 11:28:28 +08:00
midoks 704960f7cb up 2022-11-22 11:17:58 +08:00
midoks 38e13d086c Update pg.py 2022-11-22 09:25:15 +08:00
midoks 56ff442a8d Update index.py 2022-11-22 01:17:32 +08:00
midoks 6cddfa4010 Update mw.tpl 2022-11-22 01:05:20 +08:00
midoks 2f4eb172a3 Update mw.tpl 2022-11-22 01:05:01 +08:00
midoks 6b282ce287 ip 2022-11-22 01:03:20 +08:00
midoks a597d95940 Update index.py 2022-11-22 00:37:28 +08:00
midoks 1c471abd09 Update index.py 2022-11-22 00:35:27 +08:00
midoks 495cdfeb7c up 2022-11-22 00:27:37 +08:00
midoks 798c7888b6 Update install.sh 2022-11-22 00:09:41 +08:00
midoks efc6a3dd83 Update index.py 2022-11-21 22:57:40 +08:00
midoks 724ccf507c Update index.py 2022-11-21 22:50:10 +08:00
midoks cef92e76a6 Update soft.js 2022-11-21 22:29:43 +08:00
midoks 3f5c01ac85 Update install.sh 2022-11-21 22:08:12 +08:00
midoks 3dec4cd54d Update soft.js 2022-11-21 22:02:49 +08:00
midoks 2a0dc74d3a Update soft.js 2022-11-21 21:53:30 +08:00
midoks 4f514b09c5 Update files_api.py 2022-11-21 21:19:05 +08:00
midoks 5e1fe6cff8 Update files_api.py 2022-11-21 21:15:10 +08:00
midoks 4e59c6fb5c up 2022-11-21 20:06:01 +08:00
midoks 248cb43c61 up 2022-11-21 19:58:47 +08:00
midoks 23cb934e0c Update crontab.js 2022-11-21 19:37:31 +08:00
midoks 36b837bb29 Update install.sh 2022-11-21 18:13:36 +08:00
midoks 478a3eb7f2 up 2022-11-21 15:22:03 +08:00
midoks d08c5bd511 Update index.py 2022-11-21 15:13:38 +08:00
midoks fd2f838712 up 2022-11-21 14:55:22 +08:00
midoks 5bd57b3c8b Update openssl.sh 2022-11-21 11:52:13 +08:00
midoks bfe6429bc2 up 2022-11-21 11:16:47 +08:00
midoks 2979def4dc up 2022-11-21 10:42:36 +08:00
midoks 1e603d27d2 Update index.py 2022-11-21 10:40:15 +08:00
midoks f09cdcc83a Update index.py 2022-11-21 10:18:21 +08:00
midoks b46b3346d1 Update install.sh 2022-11-21 10:01:49 +08:00
midoks b18c78b38a ip 2022-11-21 09:57:48 +08:00
midoks ac5a86b14e Update openssl.sh 2022-11-21 09:49:52 +08:00
midoks af9ce2372f Update phplib.conf 2022-11-21 09:01:18 +08:00
midoks 8bec7ccf84 up 2022-11-21 01:33:50 +08:00
midoks 3256e8dc95 up 2022-11-21 00:46:32 +08:00
midoks 6e4f671628 up 2022-11-20 20:07:50 +08:00
midoks a646cbacb5 Update firewall_api.py 2022-11-20 20:05:46 +08:00
midoks 11a4d3acf8 Update firewall_api.py 2022-11-20 20:02:39 +08:00
midoks 1e324aa695 Update firewall_api.py 2022-11-20 19:54:45 +08:00
midoks 48b57108d7 Update firewall_api.py 2022-11-20 19:52:32 +08:00
midoks 0543c0847f Update firewall_api.py 2022-11-20 19:51:15 +08:00
midoks c47758a977 Update firewall_api.py 2022-11-20 19:48:39 +08:00
midoks 4010eaceb0 Update firewall_api.py 2022-11-20 19:48:07 +08:00
midoks b988e09d33 Update firewall.js 2022-11-20 19:32:09 +08:00
midoks 1bfa8e0ac0 Update firewall_api.py 2022-11-20 19:27:28 +08:00
midoks d442324466 Update firewall_api.py 2022-11-20 19:16:32 +08:00
midoks e5ae0ecc7c Update firewall_api.py 2022-11-20 19:04:16 +08:00
midoks 642bb61a25 Update firewall_api.py 2022-11-20 19:01:07 +08:00
midoks b8de9e3d01 up 2022-11-20 19:00:28 +08:00
midoks 4cd456a76c Update firewall_api.py 2022-11-20 17:37:46 +08:00
midoks 36952614d4 Update firewall_api.py 2022-11-20 17:26:27 +08:00
midoks 0cb03f92a5 Update tools.py 2022-11-20 17:18:07 +08:00
midoks 453c17d248 Update firewall_api.py 2022-11-20 17:17:27 +08:00
midoks 46ec61d915 Update firewall_api.py 2022-11-20 17:14:43 +08:00
midoks 7577776214 up 2022-11-20 16:54:19 +08:00
midoks 376ad46fb9 Update tools.py 2022-11-20 15:06:01 +08:00
midoks 11c40cf490 Update tools.py 2022-11-20 15:04:45 +08:00
midoks 9fd85009ae Update files.js 2022-11-20 14:05:18 +08:00
midoks f456ae2a14 Update files.js 2022-11-20 14:04:13 +08:00
midoks 578fa62c84 up 2022-11-20 13:25:42 +08:00
midoks 6ef897addd Update install_dev.sh 2022-11-20 13:22:35 +08:00
midoks 690d30b73c Update common.py 2022-11-20 12:07:51 +08:00
midoks bdc1fb75b4 Update common.py 2022-11-20 12:06:51 +08:00
midoks 440fa1c535 up 2022-11-20 12:06:24 +08:00
midoks 7fd59222a9 up 2022-11-20 11:41:41 +08:00
midoks 690d959898 Update files.js 2022-11-20 11:17:05 +08:00
midoks 93cbbd6e80 Update files.js 2022-11-20 11:15:42 +08:00
midoks 4f6991aefc up 2022-11-20 11:12:21 +08:00
midoks 6f2012eb7b Update config_api.py 2022-11-20 00:32:31 +08:00
midoks bb8e43610e Update phplib.conf 2022-11-20 00:07:51 +08:00
midoks 7ad77f8338 Update sg11.sh 2022-11-20 00:04:42 +08:00
midoks c117d8e253 Update sg11.sh 2022-11-19 23:32:42 +08:00
midoks d754f6f0cd Update sg11.sh 2022-11-19 23:30:01 +08:00
midoks 00f421a56a Update sg11.sh 2022-11-19 23:22:22 +08:00
midoks b74902c1b6 Update sg11.sh 2022-11-19 23:20:06 +08:00
midoks 452210fdb2 Update sg11.sh 2022-11-19 23:19:33 +08:00
midoks b39e2e2a8c Update sg11.sh 2022-11-19 23:19:09 +08:00
midoks b61e08b2d9 Update sg11.sh 2022-11-19 23:02:16 +08:00
midoks 2d85633d86 Update sg11.sh 2022-11-19 22:18:46 +08:00
midoks 747c2a92ef Update config_api.py 2022-11-19 22:12:09 +08:00
midoks bf39b04622 Update config_api.py 2022-11-19 22:10:10 +08:00
midoks d6856498f8 Update install_dev.sh 2022-11-19 22:05:45 +08:00
midoks 99f7cf9181 basic auth test 2022-11-19 22:03:55 +08:00
midoks d5977fd9b9 up 2022-11-19 21:40:57 +08:00
midoks d8fd671eee Update index.js 2022-11-19 18:07:11 +08:00
midoks abd8fecbf2 up 2022-11-19 17:42:59 +08:00
midoks 60b25cd35b Update index.js 2022-11-19 17:16:59 +08:00
midoks 240d915913 up 2022-11-19 17:06:54 +08:00
midoks f13290c7e8 Update plugins_api.py 2022-11-19 17:01:09 +08:00
midoks f6136932f4 Update tools.py 2022-11-19 16:41:19 +08:00
midoks 6df4bbdb68 up 2022-11-19 12:33:42 +08:00
midoks dfad621845 部分配置修改 2022-11-19 12:20:01 +08:00
midoks b677b1a73b Update cert_api.py 2022-11-19 00:53:10 +08:00
midoks 39c350942e 初始安装提示 2022-11-19 00:46:08 +08:00
midoks 631475bd43 up 2022-11-18 23:15:28 +08:00
midoks 1f9e273ee0 Update mw.tpl 2022-11-18 21:40:06 +08:00
midoks 66eb3b8825 Update cert_api.py 2022-11-18 21:23:26 +08:00
midoks 29540da79c Update mw.tpl 2022-11-18 21:15:26 +08:00
midoks 864c77359f Update cert_api.py 2022-11-18 11:45:39 +08:00
midoks 1a0a02e1a6 Update cert_api.py 2022-11-18 11:14:42 +08:00
midoks 61b3223bb4 Update site_api.py 2022-11-18 11:10:00 +08:00
midoks 4b794bed26 Update cert_api.py 2022-11-18 11:07:42 +08:00
midoks 96e903596a Update cert_api.py 2022-11-18 10:53:56 +08:00
midoks eb33f376c7 Update cert_api.py 2022-11-18 10:44:22 +08:00
midoks 724c3ae02a up 2022-11-18 10:34:18 +08:00
midoks bb6f7f4e3a up 2022-11-18 10:29:25 +08:00
midoks 91e7f9917b up 2022-11-18 10:27:16 +08:00
midoks 4ea0dfe063 Update site_api.py 2022-11-17 21:22:28 +08:00
midoks ec5266f750 续签测试 2022-11-17 21:18:34 +08:00
midoks f152184808 Update requirements.txt 2022-11-17 19:48:49 +08:00
midoks 1ca051a496 Update requirements.txt 2022-11-17 19:47:57 +08:00
midoks 70a5ca1048 Update requirements.txt 2022-11-17 19:46:21 +08:00
midoks c853cc66ad Update requirements.txt 2022-11-17 19:42:43 +08:00
midoks 58d2881c8e Update requirements.txt 2022-11-17 19:39:59 +08:00
midoks a0cdb4c8c2 Update requirements.txt 2022-11-17 19:37:57 +08:00
midoks 3e3af5f11a Update requirements.txt 2022-11-17 19:34:32 +08:00
midoks b2b36208a2 Update requirements.txt 2022-11-17 19:32:13 +08:00
midoks 0fcdd3b841 up 2022-11-17 19:18:00 +08:00
midoks 3c0844d26c Update requirements.txt 2022-11-17 18:06:46 +08:00
midoks 40d4a3e963 Update site_api.py 2022-11-17 17:53:20 +08:00
midoks a61179164c Update cert_api.py 2022-11-17 17:37:09 +08:00
midoks c21c8d9322 Update site_api.py 2022-11-17 17:34:13 +08:00
midoks 3adb59188a Update site_api.py 2022-11-17 17:32:02 +08:00
midoks 806e554607 Update site_api.py 2022-11-17 17:29:41 +08:00
midoks 1a0a1e5ead Update site_api.py 2022-11-17 17:27:07 +08:00
midoks 7f6ba0cbed Update site_api.py 2022-11-17 17:22:31 +08:00
midoks f4ac70a415 Update site_api.py 2022-11-17 17:20:38 +08:00
midoks 7203c31f9b Update site_api.py 2022-11-17 17:18:05 +08:00
midoks e6ea4ff580 Update site_api.py 2022-11-17 17:13:02 +08:00
midoks dc4a4688c4 Update site_api.py 2022-11-17 17:11:27 +08:00
midoks d9c547cce5 Update site_api.py 2022-11-17 17:09:13 +08:00
midoks 0517d606c8 Update site_api.py 2022-11-17 17:07:12 +08:00
midoks 7fc4a7f899 Update site_api.py 2022-11-17 17:04:53 +08:00
midoks 9a0739b9d2 Update site_api.py 2022-11-17 17:04:40 +08:00
midoks 1f16cae6c5 Update cert_api.py 2022-11-17 17:02:33 +08:00
midoks adb8789a4f Update site_api.py 2022-11-17 17:00:27 +08:00
midoks 0cb320cb23 Update cert_api.py 2022-11-17 16:56:27 +08:00
midoks a5861ce04e up 2022-11-17 16:48:29 +08:00
midoks d4c9e9cae1 Update site.js 2022-11-17 14:36:01 +08:00
midoks 4713f13c10 up 2022-11-17 14:32:53 +08:00
midoks 595b6f9d28 Update site_api.py 2022-11-17 14:27:36 +08:00
midoks dbca385d90 Update site_api.py 2022-11-17 14:27:11 +08:00
midoks 5c56dc7b24 Update requirements.txt 2022-11-17 14:14:20 +08:00
midoks 524db0d9f5 up 2022-11-17 13:54:14 +08:00
midoks b1dbdc3000 Update site.js 2022-11-17 11:41:11 +08:00
midoks 0f0d54dd9e Update site.js 2022-11-17 11:38:49 +08:00
midoks 7c1c2fc4c2 Update site_api.py 2022-11-17 11:35:34 +08:00
midoks fcb8db8e75 Update site_api.py 2022-11-17 11:31:43 +08:00
midoks 024d0a3a52 Update mw.py 2022-11-17 11:30:31 +08:00
midoks c1d3e09c67 up 2022-11-17 11:23:57 +08:00
midoks 9d556f9991 Update site_api.py 2022-11-17 01:43:10 +08:00
midoks cc744c4ccb Update site_api.py 2022-11-17 01:34:53 +08:00
midoks 6ad12f08cf Update site_api.py 2022-11-17 01:32:37 +08:00
midoks aef9c526a6 Update config_api.py 2022-11-17 01:27:10 +08:00
midoks 669eb83893 up 2022-11-17 01:25:38 +08:00
midoks 0a8831e766 Update site_api.py 2022-11-17 01:15:17 +08:00
midoks f094179c70 Update site.js 2022-11-17 00:35:53 +08:00
midoks 0b74018e61 Update site_api.py 2022-11-17 00:30:45 +08:00
midoks 3fa7332646 Update site_api.py 2022-11-17 00:28:10 +08:00
midoks 5d2580ae01 Update site.js 2022-11-17 00:25:15 +08:00
midoks 2b02663ea4 up 2022-11-17 00:12:08 +08:00
midoks db29c0162f Update site.js 2022-11-16 23:51:57 +08:00
midoks 07f6636a54 up 2022-11-16 23:38:45 +08:00
midoks b06afe619a Update my.cnf 2022-11-16 20:58:03 +08:00
midoks 7aa69aab0d Update install.sh 2022-11-16 20:47:52 +08:00
midoks 16bbe53c6e Update install.sh 2022-11-16 20:44:00 +08:00
midoks cb3226c184 up 2022-11-16 20:37:42 +08:00
midoks 66187beabc Update install.sh 2022-11-16 20:20:41 +08:00
midoks 82fd78080c up 2022-11-16 20:13:50 +08:00
midoks a8cf8975d4 up 2022-11-16 19:58:34 +08:00
midoks b09c83b502 up 2022-11-16 19:36:15 +08:00
midoks 48be4ac07c Update install.sh 2022-11-16 19:31:11 +08:00
midoks d2ebf6d038 Update site_api.py 2022-11-16 18:22:46 +08:00
midoks 6801ea2eea Update site_api.py 2022-11-16 18:21:41 +08:00
midoks 9a9d97d482 Update site_api.py 2022-11-16 18:19:46 +08:00
midoks 25083e7dd2 Update site_api.py 2022-11-16 18:00:00 +08:00
midoks 519dc4f491 up 2022-11-16 17:57:43 +08:00
midoks bfabe34f9c Update site.js 2022-11-16 17:27:41 +08:00
midoks 23cf28133a Update site.js 2022-11-16 17:25:22 +08:00
midoks b231c321e3 Update site.js 2022-11-16 17:17:33 +08:00
midoks f71c43d057 Update site_api.py 2022-11-16 16:42:54 +08:00
midoks 0ca010245d Update config_api.py 2022-11-16 16:25:33 +08:00
midoks d1cef12341 up 2022-11-16 16:02:54 +08:00
midoks da31ad7dbe up 2022-11-16 15:59:33 +08:00
midoks ec16720858 Update cert_api.py 2022-11-16 15:01:03 +08:00
midoks 217b42eae3 自动创建Lets续期计划任务 2022-11-16 14:50:49 +08:00
midoks e33bf94a17 Update site.js 2022-11-16 01:58:07 +08:00
midoks 6d112e9d3d Update site_api.py 2022-11-16 01:54:17 +08:00
midoks 605a6f1245 Update site_api.py 2022-11-16 01:52:21 +08:00
midoks eb1213d55c Update site_api.py 2022-11-16 01:48:08 +08:00
midoks 43ee847814 Update site.js 2022-11-16 01:36:24 +08:00
midoks 03bfc3a637 Update site_api.py 2022-11-16 01:31:01 +08:00
midoks a229b322d2 Update site.js 2022-11-16 01:29:01 +08:00
midoks 15b3d44a1d Update site.js 2022-11-16 01:23:10 +08:00
midoks 520da4fabc Update site_api.py 2022-11-16 01:13:39 +08:00
midoks 1458d67d93 Update public.js 2022-11-16 01:09:33 +08:00
midoks 85077a5d2f Update site_api.py 2022-11-16 00:55:52 +08:00
midoks 1004056347 up 2022-11-16 00:51:02 +08:00
midoks 6efffdfa4f Update site_api.py 2022-11-16 00:47:04 +08:00
midoks 26f4d0b37b Update cert_api.py 2022-11-16 00:40:08 +08:00
midoks 5f8b08f100 up 2022-11-16 00:36:54 +08:00
midoks fd3fc13710 Update cert_api.py 2022-11-15 19:33:17 +08:00
midoks d55b370bb0 up 2022-11-15 18:34:19 +08:00
midoks 3424135409 Update site_api.py 2022-11-15 17:24:24 +08:00
midoks 0057c495da Update site_api.py 2022-11-15 17:17:13 +08:00
midoks 4073d863d0 Update site_api.py 2022-11-15 17:13:04 +08:00
midoks 07a8096a15 Update site_api.py 2022-11-15 17:09:15 +08:00
midoks 8fd7c9eda6 Update cert_api.py 2022-11-15 16:57:11 +08:00
midoks fd1260c71f Update cert_api.py 2022-11-15 16:53:24 +08:00
midoks e364d2e972 Update cert_api.py 2022-11-15 16:51:21 +08:00
midoks ca10fbc3b5 Update cert_api.py 2022-11-15 16:49:49 +08:00
midoks 5a660d72b7 Update site_api.py 2022-11-15 16:42:00 +08:00
midoks b5a710791d Update site_api.py 2022-11-15 16:41:37 +08:00
midoks 74357fa5ee Update cert_api.py 2022-11-15 16:04:13 +08:00
midoks c5193178a3 Update setting.py 2022-11-15 15:47:19 +08:00
midoks 49cdc7e73e Update cert_api.py 2022-11-15 15:36:04 +08:00
midoks 08ac9abb65 Update cert_api.py 2022-11-15 15:35:44 +08:00
midoks af7ffe2b26 Update cert_api.py 2022-11-15 15:33:46 +08:00
midoks 95f7dc0d3a up 2022-11-15 15:23:03 +08:00
midoks d749c80884 up 2022-11-15 12:53:58 +08:00
midoks 8a36c2ee15 up 2022-11-14 22:41:26 +08:00
midoks f9330720d6 Update cert_api.py 2022-11-14 22:30:48 +08:00
midoks e1b68eed0a Update site_api.py 2022-11-14 22:10:58 +08:00
midoks cf3e530fad Update site_api.py 2022-11-14 22:08:28 +08:00
midoks 282c1a3e70 Update site_api.py 2022-11-14 21:47:30 +08:00
midoks 0ab9b25483 up 2022-11-14 21:46:14 +08:00
midoks 6d98a704a4 Update cert_api.py 2022-11-14 21:42:12 +08:00
midoks 99afb3f5e1 up 2022-11-14 21:39:46 +08:00
midoks 081998f0de Update setting.py 2022-11-14 21:21:54 +08:00
midoks 4bee6c54be Update site.js 2022-11-14 21:12:48 +08:00
midoks 5db32760cf Update site.js 2022-11-14 21:10:45 +08:00
midoks 42e5eff80f Update site_api.py 2022-11-14 21:10:29 +08:00
midoks 94f00fe948 Update site_api.py 2022-11-14 20:48:16 +08:00
midoks 1c31f2b481 Update cert_request.py 2022-11-14 20:44:04 +08:00
midoks ff56bedbc6 Update cert_request.py 2022-11-14 20:24:26 +08:00
midoks 68798453c4 Update cert_request.py 2022-11-14 20:23:10 +08:00
midoks 280b3de46c Update cert_request.py 2022-11-14 20:21:38 +08:00
midoks 101806826c Update cert_request.py 2022-11-14 20:19:33 +08:00
midoks adb10c9f3f Update cert_request.py 2022-11-14 20:17:30 +08:00
midoks 5c547b60f6 Update cert_request.py 2022-11-14 20:15:56 +08:00
midoks 2431f22420 Update cert_request.py 2022-11-14 20:00:42 +08:00
midoks 47009b42af Update mw.tpl 2022-11-14 19:56:31 +08:00
midoks b8afbc65fb Update cert_request.py 2022-11-14 19:49:09 +08:00
midoks 5f9a3dcf21 Update setting.py 2022-11-14 19:30:48 +08:00
midoks 0082b1fb76 Update mw.tpl 2022-11-14 19:20:11 +08:00
midoks 4848f9b8f6 Update cert_request.py 2022-11-14 19:14:33 +08:00
midoks 1eb7f71567 Update cert_request.py 2022-11-14 18:33:49 +08:00
midoks 041c62edac Update site.js 2022-11-14 18:29:02 +08:00
midoks c351f5e896 Update mw.tpl 2022-11-14 18:12:09 +08:00
midoks cf24cb38ff Update public.js 2022-11-14 18:09:39 +08:00
midoks e85c88d9fd Update files_api.py 2022-11-14 18:07:25 +08:00
midoks 68c1acfb3e Update files_api.py 2022-11-14 18:07:09 +08:00
midoks 6bbc3ea73b Update files_api.py 2022-11-14 18:06:52 +08:00
midoks d2ca9b57b9 Update cert_request.py 2022-11-14 18:00:35 +08:00
midoks 3a70c92c2b Update cert_request.py 2022-11-14 17:57:09 +08:00
midoks 015869494c Update public.js 2022-11-14 17:48:30 +08:00
midoks f500d882cc Update public.js 2022-11-14 17:48:15 +08:00
midoks 3cf1204dde Update mw.tpl 2022-11-14 17:26:08 +08:00
midoks 6d8e5403c8 up 2022-11-14 17:25:21 +08:00
midoks ece7d43950 Update cert_request.py 2022-11-14 17:20:44 +08:00
midoks ecd72b98db Update cert_request.py 2022-11-14 17:14:38 +08:00
midoks e13e2c172a Update requirements.txt 2022-11-14 17:01:07 +08:00
midoks a8fa93574a Update cert_request.py 2022-11-14 16:59:57 +08:00
midoks 54cd9fa007 Update cert_request.py 2022-11-14 16:48:52 +08:00
midoks d5615ae88f Update cert_request.py 2022-11-14 16:47:26 +08:00
midoks 7ca758b2bb Update cert_request.py 2022-11-14 16:43:36 +08:00
midoks 9be9c2a4f3 up 2022-11-14 16:36:39 +08:00
midoks 5c0717d9c3 Update cert_request.py 2022-11-14 16:28:27 +08:00
midoks dd2bf1cb52 up 2022-11-14 16:26:37 +08:00
midoks 4dbadb2d5f Update site.js 2022-11-14 15:54:08 +08:00
midoks 9bc68eccf5 Update site.js 2022-11-14 15:52:23 +08:00
midoks 6272c1a879 Update site_api.py 2022-11-14 15:47:16 +08:00
midoks 49ebca2ef2 Update public.js 2022-11-14 15:45:50 +08:00
midoks 4bd6b0d770 Update public.js 2022-11-14 15:40:09 +08:00
midoks fdf140ea7d Update site_api.py 2022-11-14 15:36:21 +08:00
midoks 2bac521c56 Update cert_request.py 2022-11-14 15:28:47 +08:00
midoks 2d067b2df6 up 2022-11-14 15:21:44 +08:00
midoks 80560f3763 up 2022-11-14 13:35:22 +08:00
midoks efb148db2e Update site.js 2022-11-14 11:03:14 +08:00
midoks 7d244e0acc Update site.js 2022-11-14 01:06:02 +08:00
midoks a9a0e61729 Update site_api.py 2022-11-14 01:04:08 +08:00
midoks 445a1f3c43 Update site_api.py 2022-11-14 01:00:58 +08:00
midoks 8f50e0365b Update site_api.py 2022-11-14 01:00:48 +08:00
midoks af74b1e5f7 Update site.js 2022-11-14 00:57:24 +08:00
midoks 5ebb1c3f9b up 2022-11-14 00:54:15 +08:00
midoks 38f4b2c2b5 up 2022-11-14 00:13:57 +08:00
midoks ed4c62d620 up 2022-11-13 21:54:23 +08:00
midoks be02344c4e Update site_api.py 2022-11-13 21:29:34 +08:00
midoks 9234d452b5 Update mw.py 2022-11-13 21:28:28 +08:00
midoks 8142722652 Update site_api.py 2022-11-13 21:26:01 +08:00
midoks 0decd938e4 Update site_api.py 2022-11-13 21:12:46 +08:00
midoks e55163f244 Update site_api.py 2022-11-13 21:11:35 +08:00
midoks d103fb1879 Update site_api.py 2022-11-13 21:10:13 +08:00
midoks c37f1021d9 Update site_api.py 2022-11-13 21:09:00 +08:00
midoks 080be8368f Update site_api.py 2022-11-13 21:04:45 +08:00
midoks f7d565f33e Update site_api.py 2022-11-13 21:04:12 +08:00
midoks 2de31b28b2 Update site_api.py 2022-11-13 20:58:13 +08:00
midoks 0f72c80abf Update public.js 2022-11-13 20:55:03 +08:00
midoks 9091a26778 Update site_api.py 2022-11-13 20:42:26 +08:00
midoks a99920a651 UP 2022-11-13 20:32:43 +08:00
midoks 6b89763075 Update site.js 2022-11-13 16:30:59 +08:00
midoks 715441b972 Update site_api.py 2022-11-13 16:18:18 +08:00
midoks 102f0cadff Update mw.tpl 2022-11-13 16:14:39 +08:00
midoks 4a2cb35865 Update site.js 2022-11-13 16:12:48 +08:00
midoks 81929adba5 up 2022-11-13 16:10:44 +08:00
midoks ef13161bc7 Update debian.sh 2022-11-13 16:03:16 +08:00
midoks 93a323add5 Update site.js 2022-11-13 15:57:59 +08:00
midoks 3573517f7c Update mw.tpl 2022-11-13 15:55:28 +08:00
midoks e337f0ffd7 up 2022-11-13 15:54:12 +08:00
midoks 0a84cbec9c Update site.js 2022-11-13 15:43:26 +08:00
midoks fabc73be28 Update requirements.txt 2022-11-13 15:38:06 +08:00
midoks b7cc254407 Update cert_request.py 2022-11-13 15:35:45 +08:00
midoks 4f59d07416 up 2022-11-13 15:30:01 +08:00
midoks 9abe3ec166 up 2022-11-13 10:09:32 +08:00
midoks b2546d71a5 up 2022-11-13 09:43:33 +08:00
midoks da56e5caff Update site_api.py 2022-11-13 01:04:37 +08:00
midoks 04b35c832a Update site_api.py 2022-11-13 01:01:52 +08:00
midoks 06780dadb2 up 2022-11-13 00:39:50 +08:00
midoks bfba24c66d Update cert_request.py 2022-11-12 22:52:08 +08:00
midoks 8a518e70d5 Update cert_request.py 2022-11-12 22:43:52 +08:00
midoks 050c5efe4f Update cert_request.py 2022-11-12 22:37:56 +08:00
midoks b0534f57c8 Update cert_request.py 2022-11-12 22:35:56 +08:00
midoks b9b4c055dd Update cert_request.py 2022-11-12 22:27:42 +08:00
midoks 6a37640efb Update mw.tpl 2022-11-12 22:24:55 +08:00
midoks 4ee232a689 Update cert_request.py 2022-11-12 22:12:29 +08:00
midoks 66e5e1596d Update cert_request.py 2022-11-12 22:11:34 +08:00
midoks 0d48f3973a Update cert_request.py 2022-11-12 17:31:05 +08:00
midoks 453528e8e7 up 2022-11-12 16:11:06 +08:00
midoks 71890ca8de Update cert_request.py 2022-11-12 12:05:27 +08:00
midoks 289bca248d Update cert_request.py 2022-11-12 12:00:52 +08:00
midoks 3f22209e62 Update index.py 2022-11-12 01:10:40 +08:00
midoks 3893e24619 Update cert_request.py 2022-11-11 23:46:24 +08:00
midoks cacbca5053 Update cert_request.py 2022-11-11 23:40:48 +08:00
midoks c17f5b35d7 Update cert_request.py 2022-11-11 23:35:48 +08:00
midoks d68f61de30 Update cert_request.py 2022-11-11 23:32:21 +08:00
midoks 7caef5e104 Update cert_request.py 2022-11-11 19:35:31 +08:00
midoks 9de12c1b01 Update mw.py 2022-11-11 19:32:48 +08:00
midoks 50917e4eef Update cert_request.py 2022-11-11 19:29:51 +08:00
midoks 18b9a799b3 Update cert_request.py 2022-11-11 19:28:23 +08:00
midoks 5fbae06c00 Update cert_request.py 2022-11-11 19:23:18 +08:00
midoks a5775b16b5 Update cert_request.py 2022-11-11 19:21:14 +08:00
midoks d377286de3 up 2022-11-11 19:06:32 +08:00
midoks c35ee90068 Update path.html 2022-11-11 18:54:46 +08:00
midoks d9042d7c37 up 2022-11-11 18:52:00 +08:00
midoks 6975e9adb7 Update cert_request.py 2022-11-11 18:45:23 +08:00
midoks 3caebe4399 Merge branch 'dev' of github.com:midoks/mdserver-web into dev 2022-11-11 18:44:47 +08:00
midoks 27c5b9044b Update cert_request.py 2022-11-11 18:44:41 +08:00
Mr Chen 8f85955717 Merge pull request #259 from hang666/dev
修正拼写错误
2022-11-11 18:44:03 +08:00
midoks 87b0d087d4 Create cert_request.py 2022-11-11 18:40:57 +08:00
midoks e25eed0f97 up 2022-11-11 18:34:42 +08:00
hang666 786df5911e Update site_api.py
函数名拼写错误 0.0
2022-11-11 18:28:14 +08:00
hang666 a6c5c843db Merge pull request #1 from midoks/dev
Dev
2022-11-11 18:19:23 +08:00
midoks 3f993ffa61 Delete cert_request.py 2022-11-11 13:04:43 +08:00
midoks eae5729e35 up 2022-11-11 13:04:35 +08:00
midoks 38dce0d70a Update info.json 2022-11-11 13:02:59 +08:00
midoks f6178c3ac2 Update install_dev.sh 2022-11-11 09:32:19 +08:00
midoks 798f413d6e Update install.sh 2022-11-11 03:31:12 +08:00
midoks 5a7b2512ac Update install_dev.sh 2022-11-11 03:30:25 +08:00
midoks c177b6f7b7 Update ubuntu.sh 2022-11-11 03:21:16 +08:00
midoks 84f2c20f2a 实体字符编码 2022-11-11 02:38:31 +08:00
midoks ab338dc8a7 Update soft.js 2022-11-11 00:49:18 +08:00
midoks e00fe09851 up 2022-11-10 23:14:47 +08:00
midoks 20416e46b6 up 2022-11-10 22:51:16 +08:00
midoks 1dbf9a21f9 优化安装更新 2022-11-10 22:49:24 +08:00
midoks 37e852b411 Update common.py 2022-11-10 22:26:45 +08:00
midoks deb44571ef Update mw.service.tpl 2022-11-10 21:22:21 +08:00
midoks 1dd39b569e Update mw.service.tpl 2022-11-10 21:21:55 +08:00
midoks 0531c484ab up 2022-11-10 21:20:12 +08:00
midoks 2dd6a25890 Update mw-task.service.tpl 2022-11-10 21:12:22 +08:00
midoks d1a55ffa52 Update common.py 2022-11-10 21:03:43 +08:00
midoks 467692f586 Update common.py 2022-11-10 21:02:06 +08:00
midoks 284552c02d Update mw.py 2022-11-10 20:58:16 +08:00
midoks 6c4f69e2c7 Update common.py 2022-11-10 20:50:01 +08:00
midoks 22af57840e Update mw.py 2022-11-10 20:49:31 +08:00
midoks 212e537334 Update mw.py 2022-11-10 20:45:23 +08:00
midoks 49ae49b501 Update common.py 2022-11-10 20:40:56 +08:00
midoks 48777a5924 Create cert_request.py 2022-11-10 20:33:53 +08:00
midoks eafe6b9762 Update mw.py 2022-11-10 20:32:52 +08:00
midoks 3eedc949a1 up 2022-11-10 20:32:17 +08:00
midoks 4e53ce3a1c up 2022-11-09 11:14:45 +08:00
Mr Chen 994d2feeed Merge pull request #258 from midoks/dev
添加 mysql-yum 插件
2022-11-08 22:19:09 +08:00
midoks 4b34049c5f Update index.py 2022-11-08 22:17:31 +08:00
midoks dad3c295d4 Update index.py 2022-11-08 22:15:20 +08:00
midoks b91d680d25 Update index.py 2022-11-08 22:07:23 +08:00
midoks 942ed2b79f Update index.py 2022-11-08 22:07:08 +08:00
midoks 0dd72160f5 Update index.py 2022-11-08 20:47:00 +08:00
midoks 7fd4e7177b Update install.sh 2022-11-08 19:25:09 +08:00
midoks 6fe9302108 Update mysql5.7.service.tpl 2022-11-08 19:16:47 +08:00
midoks 50020056ca up 2022-11-08 19:08:56 +08:00
midoks aaf5ed2cf4 up 2022-11-08 19:02:23 +08:00
midoks c629a7e682 up 2022-11-08 18:51:41 +08:00
midoks 13d5d1f2be Update install.sh 2022-11-08 18:11:43 +08:00
midoks aa7ce151a9 up 2022-11-08 18:03:34 +08:00
midoks 2603d1673c Update index.py 2022-11-08 17:55:25 +08:00
midoks 2eab126986 update 2022-11-08 17:52:49 +08:00
midoks fc58c5265c Update index.py 2022-11-08 17:46:14 +08:00
midoks d9cfc41574 Update index.html 2022-11-08 17:23:48 +08:00
midoks e009615454 up 2022-11-08 17:10:38 +08:00
midoks f435919179 up 2022-11-08 17:01:11 +08:00
midoks e9a4aeacc9 Update backup.py 2022-11-08 16:36:48 +08:00
midoks 3771e0f429 Update backup.py 2022-11-08 16:35:58 +08:00
midoks 4bed9cb7b6 Update backup.py 2022-11-08 16:34:44 +08:00
midoks 759e8dce7d Update backup.py 2022-11-08 16:32:15 +08:00
midoks 20ea48c0f5 up 2022-11-08 16:07:08 +08:00
midoks 99f2fad1f3 Update index.py 2022-11-08 15:55:37 +08:00
midoks 4cb20ad907 Update install.sh 2022-11-08 15:28:57 +08:00
midoks 5e1f316898 Update install.sh 2022-11-08 15:17:23 +08:00
midoks c99cb8c859 up 2022-11-08 15:13:31 +08:00
midoks 89f2746da0 u 2022-11-08 15:06:12 +08:00
midoks eb52435ce7 Update backup.py 2022-11-08 14:51:00 +08:00
midoks 099971f768 Merge branch 'dev' of github.com:midoks/mdserver-web into dev 2022-11-08 14:40:13 +08:00
midoks 2f8d808c8f Merge branch 'master' into dev 2022-11-08 14:40:03 +08:00
Mr Chen faa8c05690 Merge pull request #257 from hang666/dev
修正获取证书内反向代理设置检测
2022-11-08 14:39:37 +08:00
midoks b3dc35abca Update index.py 2022-11-08 14:35:42 +08:00
midoks 3880d443b4 Update index.py 2022-11-08 14:26:29 +08:00
midoks 671b174034 update 2022-11-08 14:19:11 +08:00
hang666 667b3c9724 修正获取证书反向代理设置检测
之前判断PROXY-END在关闭反向代理时仍会检测到,必须删除规则。
修改后正常
2022-11-08 14:16:51 +08:00
midoks 20e7c7ae9a Update index.py 2022-11-08 14:16:19 +08:00
midoks 1a9dfb8302 Update index.py 2022-11-08 14:12:54 +08:00
midoks 5bcff64aa6 Update index.py 2022-11-08 14:09:16 +08:00
midoks 924c1aa077 Update my8.0.cnf 2022-11-08 14:07:24 +08:00
midoks 384bef1dce Update mysql.service.tpl 2022-11-08 14:03:54 +08:00
midoks dd81275439 up 2022-11-08 14:01:25 +08:00
midoks e033e783ac Update index.py 2022-11-08 13:44:48 +08:00
midoks f965a8760f Update index.py 2022-11-08 13:40:33 +08:00
midoks 4ff7d0c02c Update index.py 2022-11-08 13:38:24 +08:00
midoks 45e797024a Update index.py 2022-11-08 13:30:04 +08:00
midoks b26d8a6224 Update mysql.sql 2022-11-08 13:20:17 +08:00
midoks 86e88d88d0 Update mysql.service.tpl 2022-11-08 13:08:07 +08:00
midoks db12d96793 Update index.py 2022-11-08 13:05:16 +08:00
midoks e1e785299d Update files.js 2022-11-08 13:00:11 +08:00
midoks 37fd032ed8 Update index.py 2022-11-08 12:51:44 +08:00
midoks 85f2eb63da Update mysql-yum.js 2022-11-08 12:39:26 +08:00
midoks b2af6dbce0 Update index.py 2022-11-08 12:38:38 +08:00
midoks 25de758943 Update mysql.service.tpl 2022-11-08 12:31:00 +08:00
midoks 2b587d952e Update install.sh 2022-11-08 12:00:41 +08:00
midoks 4c6dcb7c0a up 2022-11-08 11:29:22 +08:00
midoks f9a3ac5cec Update install.sh 2022-11-08 03:11:25 +08:00
midoks 5f40286bff Update install.sh 2022-11-08 02:49:42 +08:00
midoks bcde85d24e Update install.sh 2022-11-08 02:45:13 +08:00
midoks 73c8d85f88 Update install.sh 2022-11-08 02:41:08 +08:00
midoks 3cfbf554e1 up 2022-11-08 02:26:23 +08:00
midoks 5a635fcbba Update install.sh 2022-11-08 02:25:19 +08:00
midoks c573449524 Update install.sh 2022-11-08 02:24:22 +08:00
midoks b0536b37ec Update my8.0.cnf 2022-11-08 02:21:16 +08:00
midoks 02f73e6487 Update install.sh 2022-11-08 02:11:44 +08:00
midoks 6ca64a07be Update install.sh 2022-11-08 01:14:03 +08:00
midoks 9d1e934f9a mysql-ya init 2022-11-08 00:24:15 +08:00
Mr Chen 77e154d567 Merge pull request #256 from midoks/dev
mysql-apt
2022-11-07 23:53:25 +08:00
midoks b2d78d53d1 Update index.py 2022-11-07 23:33:25 +08:00
midoks 4ca234b41f Update index.py 2022-11-07 23:11:05 +08:00
midoks 309d8291aa Update install.sh 2022-11-07 22:38:05 +08:00
midoks 5ddacf9b20 up 2022-11-07 21:50:53 +08:00
midoks d647c124e6 up 2022-11-07 21:43:11 +08:00
midoks 9c99a55a4f Update index.py 2022-11-07 20:31:52 +08:00
midoks 24a4640940 up 2022-11-07 20:31:18 +08:00
midoks b3f0358814 up 2022-11-07 20:14:40 +08:00
midoks e3fcb14efc up 2022-11-07 19:34:09 +08:00
midoks 1f643d0657 Update index.py 2022-11-07 17:56:48 +08:00
midoks d68e505ba2 up 2022-11-07 17:54:16 +08:00
midoks 3e593bb652 Update my5.7.cnf 2022-11-07 17:46:42 +08:00
midoks a917598d80 up 2022-11-07 17:38:33 +08:00
midoks 49028a1ffd Update my5.7.cnf 2022-11-07 17:21:50 +08:00
midoks c399e73800 Update index.py 2022-11-07 17:13:01 +08:00
midoks b2a18e6816 Update my5.7.cnf 2022-11-07 16:25:29 +08:00
midoks 1438715c94 Update my5.7.cnf 2022-11-07 16:03:27 +08:00
midoks 4e7165a248 Update my5.7.cnf 2022-11-07 16:00:34 +08:00
midoks 35c9ca7e4e Update index.py 2022-11-07 15:52:00 +08:00
midoks 985106d3cf Update index.py 2022-11-07 15:46:11 +08:00
midoks b7e90f81e2 Update my5.7.cnf 2022-11-07 15:41:25 +08:00
midoks 21e2b2b31b up 2022-11-07 15:40:45 +08:00
midoks 79700aa561 Update index.py 2022-11-07 15:30:07 +08:00
midoks 598909d6c8 Update install.sh 2022-11-07 14:58:07 +08:00
midoks d36db9d5b7 Update install.sh 2022-11-07 14:56:03 +08:00
midoks 77d22c459e Update install.sh 2022-11-07 14:55:29 +08:00
midoks 4cdb791ab4 up 2022-11-07 14:46:14 +08:00
midoks e7673bb428 Update index.py 2022-11-07 14:39:27 +08:00
midoks 77f98ac663 Update my8.0.cnf 2022-11-07 14:34:05 +08:00
midoks a1831e3cd6 Update index.py 2022-11-07 14:30:55 +08:00
midoks 65a364ef33 up 2022-11-07 14:29:46 +08:00
midoks 3b9d874678 Update mysql.service.tpl 2022-11-07 14:26:33 +08:00
midoks 375e657030 Update mysql.service.tpl 2022-11-07 14:24:29 +08:00
midoks 774154784d Update index.py 2022-11-07 14:17:37 +08:00
midoks 656c453f4f Update install.sh 2022-11-07 14:16:02 +08:00
midoks e4e41bced3 Update install.sh 2022-11-07 13:59:51 +08:00
midoks e5f63d876b Update install.sh 2022-11-07 13:54:47 +08:00
midoks 96f8622ac1 up 2022-11-07 13:39:44 +08:00
midoks 166d462224 up 2022-11-07 13:31:47 +08:00
midoks 502e5a1877 up 2022-11-07 13:31:27 +08:00
midoks eb8ff69598 update 2022-11-07 13:29:48 +08:00
midoks 2c9d9dd19c Update install.sh 2022-11-07 13:28:03 +08:00
midoks f117b2098d Update backup.py 2022-11-07 13:18:14 +08:00
midoks 66274be102 up 2022-11-07 13:12:01 +08:00
midoks 19b4fe375e Update backup.py 2022-11-07 12:48:07 +08:00
midoks c330a357a2 Update install.sh 2022-11-07 12:47:40 +08:00
midoks ed02d8a10b up 2022-11-07 12:39:27 +08:00
midoks c583f83448 up 2022-11-07 12:26:29 +08:00
midoks 4c459c8676 Update backup.py 2022-11-07 12:09:59 +08:00
midoks 47bb1a98d4 Update index.py 2022-11-07 12:04:31 +08:00
midoks 8e29d117c0 Update index.py 2022-11-07 12:03:26 +08:00
midoks 806ac7c032 Update backup.py 2022-11-07 12:00:48 +08:00
midoks 07fece751b Update backup.py 2022-11-07 12:00:16 +08:00
midoks ac65efde61 Update backup.py 2022-11-07 12:00:00 +08:00
midoks 0b0773851a Update index.py 2022-11-07 11:50:32 +08:00
midoks 53e6307693 Update index.py 2022-11-07 11:50:13 +08:00
midoks 89540b6256 Update phpmyadmin.js 2022-11-07 11:43:18 +08:00
midoks 834b0ea80a Update mysql.js 2022-11-07 11:41:35 +08:00
midoks 630fba02be Update mysql-apt.js 2022-11-07 11:39:55 +08:00
midoks 77657233c9 Update info.json 2022-11-07 11:33:08 +08:00
midoks 26224a37c8 Update index.py 2022-11-07 11:29:39 +08:00
midoks 70998c0d04 up 2022-11-07 11:28:08 +08:00
midoks 94dce5c01c Update mysql-apt.js 2022-11-07 11:11:49 +08:00
midoks fc344fe89a Update info.json 2022-11-07 11:06:12 +08:00
midoks cba594447a up 2022-11-07 11:02:25 +08:00
midoks 8d09ceef27 Update index.py 2022-11-07 10:57:08 +08:00
midoks b32fcd43f6 Update index.py 2022-11-07 10:55:00 +08:00
midoks 78f3151c3d Update index.py 2022-11-07 10:52:35 +08:00
midoks 31815c489b Update index.py 2022-11-07 10:48:14 +08:00
midoks a7f73e10ae Update index.py 2022-11-07 10:42:24 +08:00
midoks 3dccb2620d Update install.sh 2022-11-07 10:33:55 +08:00
midoks 248d8ad27e Update index.py 2022-11-07 10:29:37 +08:00
midoks c3be68c3fb Update index.py 2022-11-07 10:29:13 +08:00
midoks d7f8510284 Update index.py 2022-11-07 10:22:31 +08:00
midoks 6f30354c38 Update info.json 2022-11-07 10:14:52 +08:00
midoks 48b9023e67 Update info.json 2022-11-07 10:14:22 +08:00
midoks 7fa7ee6770 Update index.py 2022-11-07 10:13:30 +08:00
midoks d810165ed4 Update my8.0.cnf 2022-11-07 10:11:42 +08:00
midoks 3909a584c1 Update index.py 2022-11-07 10:09:19 +08:00
midoks 74d0db13d4 up 2022-11-07 10:02:33 +08:00
midoks c78cb88774 up 2022-11-07 09:57:29 +08:00
midoks 816cd89dd1 Update index.py 2022-11-07 09:54:49 +08:00
midoks caaa930eaa Update index.py 2022-11-07 09:52:13 +08:00
midoks 0622346852 up 2022-11-07 09:50:44 +08:00
midoks 18f320bf25 up 2022-11-07 09:45:30 +08:00
midoks 309c4cc9f4 Update my8.0.cnf 2022-11-07 09:41:23 +08:00
midoks 984615a9f7 Update index.py 2022-11-07 09:38:59 +08:00
midoks b512a7fa85 up 2022-11-07 09:28:53 +08:00
Mr Chen d72d4c8d99 Merge pull request #255 from midoks/dev
AD
2022-11-07 00:32:47 +08:00
midoks 238b46ebfd Update README.md 2022-11-07 00:30:11 +08:00
midoks 98773983da up 2022-11-06 21:57:11 +08:00
midoks 7c390e4af6 Update install.sh 2022-11-06 21:15:00 +08:00
midoks 046f77d6c2 Update info.json 2022-11-06 21:12:51 +08:00
midoks 983aecdf9f Update mysql.sql 2022-11-06 21:10:40 +08:00
midoks cc074a7c8f Update mysql-apt.js 2022-11-06 21:09:51 +08:00
midoks 076ae674ad Update index.py 2022-11-06 21:04:44 +08:00
midoks f3da1c6ce9 up 2022-11-06 20:59:32 +08:00
midoks f5d2fa8238 Update install.sh 2022-11-06 20:47:40 +08:00
midoks 60e9f8e143 再次加入到核心,测试 2022-11-06 20:32:02 +08:00
Mr Chen aefd77876a Merge pull request #254 from midoks/dev
优化requirements.txt
2022-11-06 17:39:55 +08:00
Mr Chen 25cdacc98f Merge branch 'master' into dev 2022-11-06 17:39:47 +08:00
midoks 4393605832 Update requirements.txt 2022-11-06 16:30:07 +08:00
midoks 4d88e79202 Update requirements.txt 2022-11-06 16:29:10 +08:00
midoks d9e615d265 Update install.sh 2022-11-06 10:11:08 +08:00
midoks c3b77ee645 再次优化编译安装脚本 2022-11-06 10:10:34 +08:00
midoks 891a311be2 Merge branch 'master' into dev 2022-11-06 00:10:52 +08:00
Mr Chen dd5d070bb8 Merge pull request #253 from midoks/dependabot/pip/urllib3-1.26.5
Bump urllib3 from 1.25.2 to 1.26.5
2022-11-06 00:10:18 +08:00
dependabot[bot] 1574b3a010 Bump urllib3 from 1.25.2 to 1.26.5
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.25.2 to 1.26.5.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.25.2...1.26.5)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-05 16:09:19 +00:00
Mr Chen 2d15a3fed5 Merge pull request #252 from midoks/dev
fix requirements.txt
2022-11-06 00:08:20 +08:00
midoks 8c11cfb14a Update requirements.txt 2022-11-06 00:07:01 +08:00
midoks a7b9522afa Update webstats_common.lua 2022-11-06 00:02:55 +08:00
Mr Chen d0e4e5fcae Merge pull request #251 from midoks/dev
网站统计优化
2022-11-05 23:42:56 +08:00
midoks bcbaf1d26d Update requirements.txt 2022-11-05 23:39:30 +08:00
midoks fd6160e30f Update requirements.txt 2022-11-05 23:38:34 +08:00
midoks 8bdd24daa1 Update webstats_common.lua 2022-11-05 23:37:16 +08:00
midoks ee93d2fc21 Update webstats_common.lua 2022-11-05 23:34:52 +08:00
Mr Chen 410cb7d277 Merge pull request #250 from midoks/dev
添加临时访问授权功能
2022-11-05 23:04:43 +08:00
midoks 140561ba74 Update __init__.py 2022-11-05 23:01:41 +08:00
midoks c6bd1298ea Update __init__.py 2022-11-05 23:00:53 +08:00
midoks 8058cb0068 Update __init__.py 2022-11-05 22:58:42 +08:00
midoks 16e29821cc Update __init__.py 2022-11-05 22:57:59 +08:00
midoks 116e4e0efc Update __init__.py 2022-11-05 22:49:44 +08:00
midoks cd5e6e1ec7 添加临时访问授权功能 2022-11-05 22:41:37 +08:00
midoks 4fad0b9270 Update mw.py 2022-11-05 22:18:01 +08:00
midoks 67d931b581 Update default.sql 2022-11-05 22:16:43 +08:00
midoks 996f13c5f5 Update default.sql 2022-11-05 12:31:30 +08:00
midoks f89afe5a91 Update mw.tpl 2022-11-05 01:01:13 +08:00
midoks f3061fd084 Update setting.py 2022-11-05 00:36:39 +08:00
midoks c72092f5af Update setting.py 2022-11-05 00:35:55 +08:00
Mr Chen f0ed396701 Merge pull request #248 from midoks/dev
安全入口功能优化
2022-11-05 00:19:50 +08:00
midoks 902e8a91ee 安全入口功能优化 2022-11-05 00:12:07 +08:00
midoks fb2ae13465 Update index.py 2022-11-04 23:50:32 +08:00
midoks 9da7470b4e Update index.py 2022-11-04 23:47:43 +08:00
midoks d036f23f4a Update index.py 2022-11-04 23:39:14 +08:00
midoks 64223402c4 Update phpmyadmin.js 2022-11-04 23:21:02 +08:00
midoks fecdf0660f Update index.py 2022-11-04 23:18:32 +08:00
midoks f6d1610234 Update mw.tpl 2022-11-04 23:14:34 +08:00
midoks ffaed6706c Update index.py 2022-11-04 23:02:27 +08:00
midoks d50e4196cb Update install.sh 2022-11-04 22:17:57 +08:00
midoks c77382f082 Update install.sh 2022-11-04 21:03:06 +08:00
midoks 8cafb1c86e Update setting.py 2022-11-04 21:02:47 +08:00
midoks a0d69fc68a Update install.sh 2022-11-04 20:58:26 +08:00
Mr Chen 10db90764f Merge pull request #246 from midoks/dev
脚本修复
2022-11-04 12:55:06 +08:00
midoks 5a690702cf 脚本修复 2022-11-04 12:54:07 +08:00
Mr Chen 032d4f9b57 Merge pull request #245 from midoks/dev
mysql和mariadb UI优化
2022-11-04 12:10:16 +08:00
midoks 8753f45bcb 提示优化 2022-11-04 12:04:55 +08:00
midoks 1d02896349 up 2022-11-04 11:50:57 +08:00
Mr Chen d4fb0be60b Merge pull request #244 from midoks/dev
#218
2022-11-04 00:43:42 +08:00
midoks a233d440ef mariadb修复功能OK 2022-11-04 00:38:56 +08:00
midoks e2962146cf 调整debian和ubuntu的安装 2022-11-04 00:25:47 +08:00
midoks ab2f55282d Update backup.py 2022-11-04 00:21:23 +08:00
midoks 098f0ffdd2 Update mariadb.js 2022-11-04 00:00:53 +08:00
midoks 8e544fee93 Update mariadb.js 2022-11-03 23:53:47 +08:00
midoks ea20cc6e89 mariadb加入修复功能和外部导入功能 2022-11-03 23:49:56 +08:00
midoks 176112b332 mysql加入修复功能。
密码错误时重置。这种错误一般安装时,有一个定几率出现。
2022-11-03 22:22:06 +08:00
midoks 53332e9b6b Update README.md 2022-11-03 21:12:37 +08:00
midoks 600cd80676 计算优化 2022-11-03 18:11:12 +08:00
midoks 6cd3a09584 up 2022-11-03 18:07:38 +08:00
midoks 0d3a533c11 Update install.sh 2022-11-03 18:03:56 +08:00
Mr Chen 63f9b577aa Merge pull request #243 from midoks/dev
query_cache_size优化
2022-11-03 11:52:13 +08:00
midoks 57786cb95a Update mysql.js 2022-11-03 11:51:10 +08:00
midoks 5b9bd6e0bf up 2022-11-03 11:31:24 +08:00
midoks 96c9bc38ca query_cache_size 设置优化 2022-11-03 11:25:36 +08:00
midoks 141fd8fb34 Merge branch 'master' into dev 2022-11-03 10:40:46 +08:00
Mr Chen 063f13ef69 Merge pull request #242 from msycn/dev
Update cloudfare_real_ip.conf
2022-11-03 10:22:22 +08:00
msycn 1054fd1400 update cloudfare_real_ip.conf to 2022.11
Apr 8, 2021:
104.16.0.0/12 removed from ips-v4
104.16.0.0/13 added to ips-v4
104.24.0.0/14 added to ips-v4
https://www.cloudflare.com/ips-v4
https://www.cloudflare.com/ips-v6
2022-11-02 17:15:55 -04:00
Mr Chen d795242fdd Merge pull request #241 from midoks/dev
webhook 1.0
2022-11-03 00:20:25 +08:00
midoks 8ed36c1781 webhook 1.0 2022-11-03 00:11:16 +08:00
Mr Chen b17bfb0da6 Merge pull request #240 from midoks/dev
细节优化
2022-11-02 18:53:09 +08:00
midoks 105f12cba6 Update phplib.conf 2022-11-02 18:32:09 +08:00
midoks 00b978dd70 Update apcu.sh 2022-11-02 18:24:20 +08:00
midoks fd23a4c572 phpmysqladmin保存优化 2022-11-02 18:22:21 +08:00
midoks 421c9a673c up 2022-11-02 18:04:05 +08:00
midoks 9295455628 Update phplib.conf 2022-11-02 17:40:43 +08:00
midoks 93f79a7e69 Update phplib.conf 2022-11-02 17:35:59 +08:00
midoks 7e627856d7 Update phplib.conf 2022-11-02 17:32:20 +08:00
midoks f068bf1292 写访问日志+提示 2022-11-02 16:02:41 +08:00
Mr Chen 2d495e498e Merge pull request #238 from midoks/dev
站点相关优化
2022-11-02 14:20:07 +08:00
midoks 496ef3cc36 站点相关优化
1.修复伪静态模版保存。
2.伪静态保存检测。
3.修复写入日志开关。
2022-11-02 13:48:19 +08:00
midoks 008bb49365 Update tools.py 2022-11-02 10:19:24 +08:00
midoks 2f94f9b856 Update tools.py 2022-11-02 10:19:01 +08:00
Mr Chen a2e6073858 Merge pull request #237 from midoks/dev
mariadb版本更新
2022-11-02 01:37:46 +08:00
midoks 4580f10ba7 mariadb为了稳定安装,与最新的相差2个版本 2022-11-02 01:36:52 +08:00
midoks d2974c0d79 mariadb版本更新 2022-11-02 01:31:44 +08:00
midoks ee255086ac Update install.sh 2022-11-02 01:21:37 +08:00
Mr Chen 7f1643720a Merge pull request #236 from midoks/dev
rsyncd优化
2022-11-02 01:12:14 +08:00
midoks 0b3ddd22a5 安装优化 2022-11-02 01:10:35 +08:00
midoks 4db3650b59 Update index.py 2022-11-02 01:04:18 +08:00
Mr Chen a86588ee01 Merge pull request #235 from midoks/dev
添加卸载脚本
2022-11-02 00:45:18 +08:00
midoks 72af570958 卸载脚本 2022-11-02 00:42:41 +08:00
midoks df0d980d24 Update uninstall.sh 2022-11-02 00:35:26 +08:00
midoks b06308c842 Update uninstall.sh 2022-11-02 00:31:42 +08:00
midoks e0f1a74f74 Update uninstall.sh 2022-11-02 00:31:14 +08:00
midoks 4a5f6fef6b Update uninstall.sh 2022-11-02 00:29:56 +08:00
midoks 9eaabab738 Update uninstall.sh 2022-11-02 00:25:46 +08:00
midoks 1615e7c580 Update uninstall.sh 2022-11-02 00:13:10 +08:00
midoks b2d0c4815e up 2022-11-02 00:12:56 +08:00
midoks 2ac903be9b Update uninstall.sh 2022-11-02 00:09:35 +08:00
midoks c3979d5f55 Update index.py 2022-11-01 22:25:01 +08:00
midoks 0d618b1b68 Update index.py 2022-11-01 22:01:08 +08:00
midoks d0e6954680 Update install.sh 2022-11-01 21:54:14 +08:00
midoks 57be5fd61c Update index.py 2022-11-01 21:44:35 +08:00
midoks 59987eb502 Update uninstall.sh 2022-11-01 21:28:39 +08:00
midoks 04fe781241 Update uninstall.sh 2022-11-01 21:22:42 +08:00
midoks 31fcd80877 rsyncd添加目录后统一为www权限,避免混乱 2022-11-01 21:06:32 +08:00
midoks a13c366813 Update rsyncd.js 2022-11-01 20:43:35 +08:00
midoks 6e978b668e up 2022-11-01 20:27:20 +08:00
midoks bf09f29f48 Update lib.sh 2022-11-01 20:11:46 +08:00
midoks e035330eac Update lib.sh 2022-11-01 20:11:16 +08:00
midoks 668f135b71 Update debian.sh 2022-11-01 20:00:06 +08:00
midoks e9296fbecb Update requirements.txt 2022-11-01 19:37:13 +08:00
midoks c8feecfb2a Update debian.sh 2022-11-01 18:18:27 +08:00
midoks 02bc554afb Update mw.tpl 2022-11-01 14:57:41 +08:00
midoks 9f3c7e0479 Update mw.tpl 2022-11-01 14:57:28 +08:00
midoks ad315cf37c phpmyadmin初始安装优化 2022-11-01 14:29:31 +08:00
midoks 3d807cd0c8 Update index.py 2022-11-01 14:09:49 +08:00
midoks e0ca9b4654 Update index.py 2022-11-01 13:55:50 +08:00
midoks a852cdeead Update __init__.py 2022-11-01 12:03:33 +08:00
Mr Chen 6b3c40baea Merge pull request #233 from midoks/dev
为了严格登录,验证码输入错误4次,也直接关闭。
2022-11-01 11:56:57 +08:00
midoks 852f236bb5 为了严格登录,验证码输入错误4次,也直接关闭。 2022-11-01 11:47:13 +08:00
Mr Chen 9ad2bf8bf0 Merge pull request #232 from midoks/dev
在线编辑优化-识别其他编码FIX
2022-10-31 13:13:11 +08:00
midoks 1284ddd1af 在线编辑优化-识别其他编码FIX 2022-10-31 13:12:10 +08:00
Mr Chen 412ff74f0c Merge pull request #231 from midoks/dev
修改计划任务-JS修复
2022-10-31 09:52:49 +08:00
midoks 2eceff82e8 修改计划任务-JS修复 2022-10-31 09:51:48 +08:00
Mr Chen 6b164c58e9 Merge pull request #230 from midoks/dev
计划任务-JS修复
2022-10-31 09:37:56 +08:00
midoks e9802040d9 Update pull_request_template.md 2022-10-31 09:37:20 +08:00
midoks 5dd84c12f3 Update crontab.js 2022-10-31 09:35:51 +08:00
Mr Chen b1a8c5c02f Merge pull request #228 from midoks/dev
0.10.2
2022-10-31 02:59:12 +08:00
midoks 3ed0ceed70 Update crontab.js 2022-10-31 02:57:58 +08:00
midoks 6948d503c0 Update crontab.js 2022-10-31 02:49:22 +08:00
midoks 39bca95e62 Update crontab.js 2022-10-31 02:39:12 +08:00
midoks 063bc092e6 0.10.2
* 修复上次更新的UI问题。
* `FTP存储空间` 备份数据库修复。
* 修复计划任务执行Python脚本的编码问题。
* 添加,修改计划任务参数强校验。
2022-10-31 02:30:55 +08:00
midoks aa97982f6f Update crontab_api.py 2022-10-31 00:12:45 +08:00
midoks af73ce7af8 优化 2022-10-30 23:34:18 +08:00
midoks e46ed828d9 Update index.py 2022-10-30 23:24:54 +08:00
midoks f5ec3bba3d ftp备份数据库优化 2022-10-30 22:34:18 +08:00
midoks 2f7ec60e89 Update index.html 2022-10-30 21:16:41 +08:00
midoks 5df4b9ee57 Update mw.py 2022-10-30 18:04:42 +08:00
midoks 71dbfbf5d8 登录界面统一显示设置面板名 2022-10-30 18:03:31 +08:00
Mr Chen 93fcdd2e27 Merge pull request #227 from midoks/dev
OP防火墙安装校验
2022-10-30 13:22:53 +08:00
midoks a725220577 Update info.json 2022-10-30 13:17:09 +08:00
midoks 783c4ebc60 Update firewall_api.py 2022-10-30 11:56:37 +08:00
midoks a06db0e8c3 Update firewall_api.py 2022-10-30 11:46:49 +08:00
Mr Chen d7c4dcda66 Merge pull request #226 from midoks/dev
小问题优化
2022-10-30 11:28:50 +08:00
midoks 2866e1a602 优化 2022-10-30 10:27:58 +08:00
midoks 77e4ee1053 debian首先同步时间再安装 2022-10-30 00:27:10 +08:00
Mr Chen 7589c14f81 Merge pull request #224 from midoks/dev
0.10.1
2022-10-29 23:23:23 +08:00
midoks 4344d774c1 Update config_api.py 2022-10-29 23:21:26 +08:00
midoks 4859792096 Update README.md 2022-10-29 22:00:36 +08:00
midoks e55c40e973 优化文件多选的bug 2022-10-29 21:58:29 +08:00
midoks 103beb62a4 Update files_api.py 2022-10-29 20:59:00 +08:00
midoks 76a34578ad Update index.py 2022-10-29 20:36:37 +08:00
midoks f82fdbf939 Update README.md 2022-10-29 20:19:18 +08:00
midoks 4eaf9eb36c phpmyadmin+路径随机 2022-10-29 20:12:01 +08:00
midoks 9c9f9fc42c 初始化卸载脚本 2022-10-29 16:31:59 +08:00
midoks 8301ad6f62 Update ubuntu.sh 2022-10-29 16:19:53 +08:00
midoks d42fb48749 Update mw.tpl 2022-10-29 16:13:23 +08:00
midoks fa49a3dbeb Update README.md 2022-10-29 15:24:28 +08:00
midoks dd1147c891 Update debian.sh 2022-10-29 14:39:06 +08:00
midoks 67b015a50b up 2022-10-29 13:46:16 +08:00
midoks 57831168a3 debian 9 兼容 2022-10-29 13:35:12 +08:00
midoks f6f7cabddc Update debian.sh 2022-10-29 12:18:07 +08:00
midoks dfec241c3f Update README.md 2022-10-29 11:54:58 +08:00
midoks 8a78dff571 Update ubuntu.sh 2022-10-29 11:38:27 +08:00
midoks a9486d4fbe Update ubuntu.sh 2022-10-29 11:38:08 +08:00
midoks 78d3a091cd openresty增加性能调整功能 2022-10-29 02:46:27 +08:00
midoks 314005e478 Update openresty.js 2022-10-28 19:06:27 +08:00
midoks 55fa911485 Update mysql.js 2022-10-28 17:52:43 +08:00
midoks a72046462c Update index.py 2022-10-28 17:49:30 +08:00
midoks 0b8fe15b65 Update index.py 2022-10-28 16:47:53 +08:00
midoks 34f5d12ad9 mysql 部分操作优化 2022-10-28 14:20:12 +08:00
midoks e88544d290 Update mysql.js 2022-10-28 14:08:56 +08:00
midoks a211746de7 mysql导入功能 2022-10-28 14:08:50 +08:00
midoks c417b02844 Update install.sh 2022-10-27 23:44:40 +08:00
Mr Chen 034aaedf48 Merge pull request #223 from midoks/dev
小优化
2022-10-27 15:51:03 +08:00
midoks af0ec79072 统计一下用户量,让我的开发更有激情 2022-10-27 15:44:42 +08:00
midoks 195ccf409e openresty 默认加入ipv6支持 2022-10-27 14:38:44 +08:00
Mr Chen 7cec26b8a3 Merge pull request #222 from midoks/dev
优化logo
2022-10-26 23:47:01 +08:00
midoks aacb816b11 优化logo 2022-10-26 23:40:48 +08:00
Mr Chen 411798f4bf Merge pull request #221 from midoks/dev
0.10.0
2022-10-26 23:25:55 +08:00
midoks 2179db5f8b 0.10.0 2022-10-26 23:24:33 +08:00
midoks dcced8c0fb Update crontab_api.py 2022-10-26 22:08:29 +08:00
midoks 3e0e42d8a1 优化 2022-10-26 19:41:51 +08:00
midoks e5355d3e2f Update ftp_client.py 2022-10-26 18:56:57 +08:00
midoks 0a22e25611 Update ftp_client.py 2022-10-26 18:49:05 +08:00
midoks 5f7a3e5bf6 Update index.py 2022-10-26 18:43:48 +08:00
midoks 3518548c61 backup ftp 80% 2022-10-26 17:47:40 +08:00
midoks 08c4b0845d Update crontab_api.py 2022-10-26 11:34:52 +08:00
midoks 8f5fae8e79 Update index.py 2022-10-26 02:50:11 +08:00
midoks a151db1c30 Update install.sh 2022-10-26 02:48:08 +08:00
midoks 628c69ed22 Update index.html 2022-10-26 02:48:05 +08:00
midoks 13bcbc0f3e Update soft.js 2022-10-26 02:47:57 +08:00
midoks c94838462c backup_ftp 50% 2022-10-26 02:42:10 +08:00
midoks a147ef6962 Update centos.sh 2022-10-25 22:06:32 +08:00
midoks 4ccda15933 Update ftp.js 2022-10-25 14:11:49 +08:00
midoks 01074c743d Update pure-ftpd.conf 2022-10-25 14:10:46 +08:00
midoks 0871fa1763 up 2022-10-25 13:51:24 +08:00
midoks aade0ccd98 Update install.sh 2022-10-25 12:28:57 +08:00
midoks 4aed2f91de Update ftp.js 2022-10-25 12:28:49 +08:00
midoks d49dd9f2ac Update install.sh 2022-10-25 03:37:48 +08:00
midoks cff29194f4 Revert "安装优化"
This reverts commit ecbfb2500f.
2022-10-25 03:34:00 +08:00
midoks ecbfb2500f 安装优化 2022-10-25 03:20:35 +08:00
midoks 9c43170d4b Update install.sh 2022-10-25 03:11:06 +08:00
midoks 1239a2807f up 2022-10-25 02:53:19 +08:00
midoks 1c0a130b49 up 2022-10-25 01:43:29 +08:00
midoks ffb1eb34e0 waf 0.2.3 2022-10-25 00:41:27 +08:00
midoks 82874d1f7a Update url_white.json 2022-10-24 23:42:26 +08:00
midoks 4e05f29fcd OP防火墙-0.2.3 2022-10-24 23:12:45 +08:00
midoks d5f3b0d442 初始安装 ipv6 优化 2022-10-24 21:55:44 +08:00
midoks 81eec04037 Update mw.tpl 2022-10-24 21:44:34 +08:00
midoks 5a5dc43e17 Update mw.tpl 2022-10-24 21:38:10 +08:00
midoks b4eb2b3192 Update mw.tpl 2022-10-24 21:20:04 +08:00
midoks 2d1c070e1b Update mw.tpl 2022-10-24 21:16:17 +08:00
midoks 81364fdfa3 Update common.lua 2022-10-24 21:12:41 +08:00
midoks 9d0d88d465 Update init.lua 2022-10-24 20:56:18 +08:00
midoks 7e2eef8bbf Update init.lua 2022-10-24 20:54:41 +08:00
midoks 8d1315e5be Update init.lua 2022-10-24 20:39:07 +08:00
midoks fe6a51540e Update init.lua 2022-10-24 20:38:24 +08:00
midoks 6e35683505 Update init.lua 2022-10-24 20:35:39 +08:00
midoks 713c0d1a3c up 2022-10-24 20:18:34 +08:00
midoks 8323e0ec73 up 2022-10-24 20:06:38 +08:00
midoks 6eae94658f up 2022-10-24 19:55:09 +08:00
midoks 07d173d2cf up 2022-10-24 19:11:48 +08:00
midoks 23f2b9efac Update index.py 2022-10-24 15:14:14 +08:00
midoks 9b2ab9276c Update common.lua 2022-10-24 14:53:54 +08:00
midoks 7903e1a286 Update common.lua 2022-10-24 14:53:39 +08:00
midoks 662e05511f Update common.lua 2022-10-24 14:51:58 +08:00
midoks 1f8785acbc Update init.lua 2022-10-24 14:49:20 +08:00
midoks 3eb87cf953 Update init.lua 2022-10-24 11:57:46 +08:00
midoks 124b24885e Update op_waf.js 2022-10-24 11:23:35 +08:00
midoks 2196983455 Update ip_white.json 2022-10-24 11:22:39 +08:00
midoks 80a67c4f58 Update webstats_log.lua 2022-10-24 11:10:23 +08:00
midoks ff06f7ef91 Update webstats_common.lua 2022-10-24 11:06:35 +08:00
midoks b16506c8bc #211 优化
phpmyadmin安全设置处修改端口保存后当前用修改后的端口能打开,一旦停止phpmyadmin后,再重启phpmyadmin端口又变为888,需要手工再次改变
2022-10-23 14:07:18 +08:00
midoks 2d3801dcc0 up 2022-10-23 13:49:08 +08:00
Mr Chen 9b83a2ef79 Merge pull request #216 from midoks/dev
0.9.14
2022-10-23 01:12:02 +08:00
midoks 6aefa3b7dc Update config_api.py 2022-10-23 01:11:20 +08:00
midoks 566fabbf24 Update README.md 2022-10-23 01:08:41 +08:00
midoks ea8aa5102b Update common.lua 2022-10-23 00:41:39 +08:00
midoks b8421d36ae up 2022-10-23 00:37:42 +08:00
midoks 24bd8daca0 Update install.sh 2022-10-22 22:57:04 +08:00
midoks d8047b43fa Update install.sh 2022-10-22 22:49:32 +08:00
midoks 016dde04e7 Update my8.0.cnf 2022-10-22 22:36:33 +08:00
midoks df5d86a883 Update README.md 2022-10-22 22:26:55 +08:00
midoks 84077de5d1 Update common.lua 2022-10-22 22:22:53 +08:00
midoks 04ed4b180a up 2022-10-22 21:58:35 +08:00
midoks f980dba7ed up 2022-10-22 21:36:12 +08:00
midoks f702f70f89 up 2022-10-22 20:25:46 +08:00
midoks a8e6ee052c init 2022-10-22 18:32:11 +08:00
midoks b3d0a36dcd up 2022-10-22 16:29:11 +08:00
midoks 96275303c6 Update index.py 2022-10-22 13:30:08 +08:00
midoks 0337a1bded up 2022-10-22 13:19:35 +08:00
midoks 8bd985fca9 up 2022-10-21 19:53:36 +08:00
midoks b6ef8d1625 up 2022-10-21 19:16:07 +08:00
midoks 3dc695508f up 2022-10-21 19:09:34 +08:00
midoks 0c769b02e5 Update op_waf.js 2022-10-21 17:45:30 +08:00
midoks e289037598 up 2022-10-21 17:34:38 +08:00
midoks 63e6a95553 up 2022-10-21 12:08:43 +08:00
midoks 8e1d95bf82 up 2022-10-21 01:33:35 +08:00
midoks 24fe8b6f5f up 2022-10-21 01:25:57 +08:00
midoks 3d366ee774 up 2022-10-20 23:40:28 +08:00
midoks 0428956141 up 2022-10-20 20:59:15 +08:00
midoks 37747427be up 2022-10-20 17:59:16 +08:00
midoks fb94fb8304 up 2022-10-20 16:31:30 +08:00
midoks 65d07d3934 0.2.2 2022-10-20 14:52:51 +08:00
midoks 5e6ffafeb5 Update install.sh 2022-10-20 14:10:20 +08:00
midoks 572f231fae up 2022-10-20 14:03:17 +08:00
midoks 0328dd21e7 Update webstats_common.lua 2022-10-20 13:20:54 +08:00
midoks 597d171733 Update webstats_common.lua 2022-10-20 13:10:40 +08:00
midoks 745ab9dcd0 Update webstats_common.lua 2022-10-20 12:59:26 +08:00
midoks 30323b031c Update webstats_common.lua 2022-10-20 12:58:41 +08:00
midoks f47e6a47df Update webstats_common.lua 2022-10-20 12:57:20 +08:00
midoks 0eccebd9da Update webstats_common.lua 2022-10-20 12:45:24 +08:00
midoks 0ad5e74fae Update webstats_common.lua 2022-10-20 12:38:54 +08:00
midoks 2640ba97c5 Update webstats_common.lua 2022-10-18 18:03:35 +08:00
midoks e5f440ff02 up 2022-10-18 17:41:29 +08:00
midoks 7bc9c44ec1 Update webstats_log.lua 2022-10-18 16:38:18 +08:00
midoks 9cd74db011 Update webstats_common.lua 2022-10-18 03:14:00 +08:00
midoks 5da8e5a7f6 Update webstats_common.lua 2022-10-18 03:07:12 +08:00
midoks 4da895b8df Update webstats_common.lua 2022-10-18 02:54:31 +08:00
midoks 42eca14168 Update webstats_common.lua 2022-10-18 02:13:07 +08:00
midoks 43a3dfd9bd Update webstats_common.lua 2022-10-18 01:48:18 +08:00
midoks 794eba4186 Update webstats_common.lua 2022-10-18 01:41:26 +08:00
midoks a4f533acba Update webstats_common.lua 2022-10-18 01:20:08 +08:00
midoks adb3c5250c Update webstats_common.lua 2022-10-18 01:08:05 +08:00
midoks e4226fcdd4 Update webstats_log.lua 2022-10-18 00:58:08 +08:00
midoks d3e9353589 up 2022-10-18 00:56:31 +08:00
midoks 757284cdf1 up 2022-10-17 23:48:20 +08:00
midoks 58232e10ab Update index.py 2022-10-17 23:40:44 +08:00
midoks fde211e026 Update webstats_log.lua 2022-10-17 23:30:34 +08:00
midoks c9a527e487 up 2022-10-17 23:29:57 +08:00
midoks c501efdfac up 2022-10-17 21:12:42 +08:00
midoks 80c0bbed71 Update webstats_log.lua 2022-10-17 14:54:53 +08:00
midoks 1fb3c30775 Update webstats_log.lua 2022-10-17 14:29:52 +08:00
midoks 24ab203770 Update webstats_log.lua 2022-10-17 14:08:00 +08:00
midoks bd0242db2f Update webstats_common.lua 2022-10-17 14:03:35 +08:00
midoks 42bf5edd1f Update webstats_common.lua 2022-10-17 13:45:21 +08:00
midoks 7b2a011b6a Update webstats_common.lua 2022-10-17 13:44:35 +08:00
midoks 76e01201a2 Update webstats_common.lua 2022-10-17 13:31:36 +08:00
midoks 16e45cabfc Update webstats_common.lua 2022-10-17 13:30:30 +08:00
midoks c08542ff54 Update webstats_common.lua 2022-10-17 13:23:48 +08:00
midoks 5beb76d0b7 Update webstats_common.lua 2022-10-17 13:07:22 +08:00
midoks f16a7e016e up 2022-10-17 13:06:34 +08:00
midoks eb86ac3ee6 Update webstats_common.lua 2022-10-17 12:17:37 +08:00
midoks 14c2606532 Update webstats_common.lua 2022-10-17 12:12:17 +08:00
midoks 86b8939cb8 Update webstats_common.lua 2022-10-17 12:10:15 +08:00
midoks dd28c1ef56 Update webstats_common.lua 2022-10-17 11:43:37 +08:00
midoks 6b24dfc21e Update webstats_common.lua 2022-10-17 11:36:29 +08:00
midoks dc06573125 Update webstats_common.lua 2022-10-17 03:03:32 +08:00
midoks df35e5a780 Update webstats_common.lua 2022-10-17 02:56:28 +08:00
midoks a678d851a0 Update webstats_common.lua 2022-10-17 02:49:16 +08:00
midoks 6a706651e4 Update webstats_common.lua 2022-10-17 02:45:18 +08:00
midoks 1acdfe4368 Update webstats_common.lua 2022-10-17 02:30:36 +08:00
midoks cae245efca up 2022-10-17 02:04:01 +08:00
midoks 238f1e76d8 Update webstats.conf 2022-10-17 01:09:57 +08:00
midoks f3a754d1ae Update webstats_common.lua 2022-10-17 01:06:50 +08:00
midoks 21aab0573a Update webstats_common.lua 2022-10-17 00:58:20 +08:00
midoks 011949ba85 up 2022-10-17 00:44:04 +08:00
midoks f3e7dd1cc0 Update init_worker.lua 2022-10-15 23:44:53 +08:00
midoks b49d2025eb Update install.sh 2022-10-15 23:38:12 +08:00
midoks 556b0869f2 Update config.json 2022-10-15 23:34:20 +08:00
midoks aad6deeb78 Update init_worker.lua 2022-10-15 23:28:36 +08:00
midoks 64601e42c1 up 2022-10-15 23:16:25 +08:00
midoks 6555d927ea Update common.lua 2022-10-15 21:20:40 +08:00
midoks 444ff40570 up 2022-10-15 19:13:01 +08:00
midoks 7bdcd0ac2b up 2022-10-15 17:38:42 +08:00
midoks 6e6a41e6df Update ngx_demo.sh 2022-10-15 10:03:22 +08:00
midoks feca2a6d33 aa 2022-10-15 03:23:08 +08:00
midoks 5e382e7347 Update init.lua 2022-10-15 03:16:02 +08:00
midoks abc778fb52 up 2022-10-15 02:05:29 +08:00
midoks 6b42d35cd4 up 2022-10-15 00:34:14 +08:00
midoks c74a2c9655 Update common.lua 2022-10-14 23:46:10 +08:00
midoks 01543f951a Update init.lua 2022-10-14 23:45:57 +08:00
midoks d78a5d8f27 Update init.lua 2022-10-14 23:45:43 +08:00
midoks 2a1d759cd2 Update config.json 2022-10-14 23:23:08 +08:00
midoks 43889f83f7 up 2022-10-14 21:41:25 +08:00
midoks 79a0a93959 up 2022-10-14 17:50:26 +08:00
midoks 735cf9b872 up 2022-10-14 12:41:32 +08:00
midoks e7c318e560 Update info.json 2022-10-14 12:18:09 +08:00
midoks 78d03754f6 Update install.sh 2022-10-14 12:09:19 +08:00
midoks 67cc1cac86 Update install.sh 2022-10-14 12:08:14 +08:00
midoks 77ec90980a Update install.sh 2022-10-14 12:06:57 +08:00
midoks d07b2babfd up 2022-10-14 12:05:54 +08:00
midoks 4d9ee94038 up 2022-10-14 11:36:54 +08:00
midoks 61479d5db6 Update init.lua 2022-10-13 22:23:46 +08:00
midoks 897c28034d up 2022-10-13 22:18:57 +08:00
midoks b3fef4c104 up 2022-10-13 21:29:28 +08:00
midoks 48cec8ee47 up 2022-10-13 21:05:06 +08:00
midoks 7c369ef19f up 2022-10-13 21:03:26 +08:00
midoks 1411bb1639 up 2022-10-13 20:43:46 +08:00
midoks be875d9d8c Update soft.js 2022-10-13 17:39:41 +08:00
midoks 746dc7ee4d Update soft.js 2022-10-13 17:34:44 +08:00
midoks ea7ba7d461 软件界面优化 2022-10-13 17:29:41 +08:00
midoks 48ed4156b5 Update common.lua 2022-10-13 17:06:42 +08:00
midoks ca73d0e280 Update common.lua 2022-10-13 17:01:57 +08:00
midoks 8cef43d9a7 Update info.json 2022-10-13 16:51:13 +08:00
midoks 75445774a1 test & op 2022-10-13 16:46:44 +08:00
midoks 9b29f19b96 up 2022-10-13 14:59:49 +08:00
midoks 1e6655e7f9 Update readme.md 2022-10-13 14:46:48 +08:00
midoks 363656e06c up 2022-10-13 14:46:29 +08:00
midoks a1860bc4fc up 2022-10-13 14:21:39 +08:00
midoks f8ce39bc74 up 2022-10-13 11:46:03 +08:00
midoks 969d02ef93 Update ngx_debug.sh 2022-10-13 04:35:23 +08:00
midoks a54410df6e up 2022-10-13 04:18:47 +08:00
midoks 01e388ea45 up 2022-10-13 03:12:44 +08:00
midoks ef75f22a86 Update index.py 2022-10-13 01:38:20 +08:00
midoks 97f6b232fd Update ngx_debug.sh 2022-10-13 01:36:53 +08:00
midoks 2506f5e940 Update install.sh 2022-10-13 01:10:03 +08:00
midoks dcb23ada41 Update ngx_debug.sh 2022-10-13 01:06:32 +08:00
midoks 35e1bf048c Update ngx_debug.sh 2022-10-13 00:58:47 +08:00
midoks a9e24f8eaf Update ngx_debug.sh 2022-10-13 00:58:05 +08:00
midoks 2f4ac74f52 Create ngx_debug.sh 2022-10-13 00:42:51 +08:00
midoks 522122feb6 Update common.lua 2022-10-12 20:37:56 +08:00
midoks a3c677a926 Update common.lua 2022-10-12 19:41:35 +08:00
midoks fd1c52530e Update common.lua 2022-10-12 19:35:59 +08:00
midoks 071c690583 Update linux.conf 2022-10-12 18:04:20 +08:00
midoks 67c9cd0277 up 2022-10-12 17:51:50 +08:00
midoks 61292868ad 统计变为ngx.timer.every执行 2022-10-12 17:18:51 +08:00
midoks 54b2a00b23 Update safe_js.html 2022-10-12 16:56:36 +08:00
midoks af6d377664 Update safe_js.html 2022-10-12 16:47:29 +08:00
midoks 6d55e345b0 Update common.lua 2022-10-12 16:39:55 +08:00
midoks fab4e68d8d Update common.lua 2022-10-12 15:42:48 +08:00
midoks 8864e91f21 Update install.sh 2022-10-12 15:31:42 +08:00
midoks f14ce1b66c Update info.json 2022-10-12 15:29:03 +08:00
midoks 48098efd56 Update safe_js.html 2022-10-12 15:28:09 +08:00
midoks 04eba8e33f Update init.lua 2022-10-12 15:26:38 +08:00
midoks 89cf7ffafc Update init.lua 2022-10-12 15:19:08 +08:00
midoks 47544520e8 Update init.lua 2022-10-12 15:03:51 +08:00
midoks bc1fd9a8af Update init.lua 2022-10-12 14:51:46 +08:00
midoks 27efc7ef6e Update config_api.py 2022-10-12 14:38:45 +08:00
midoks 47ead816c0 Update init.lua 2022-10-12 14:37:43 +08:00
midoks 31d36182c3 Update init.lua 2022-10-12 14:37:11 +08:00
midoks c9a58c7ea5 Update init.lua 2022-10-12 14:36:57 +08:00
midoks a6e59ae37c Update init.lua 2022-10-12 14:36:42 +08:00
midoks 328e1b0ff1 up 2022-10-12 14:30:37 +08:00
midoks f76cc5ceb8 Update init.lua 2022-10-12 13:59:30 +08:00
midoks d6c74c3f7d waf demo 3 2022-10-12 13:49:57 +08:00
midoks 4f932c36e7 up 2022-10-12 10:11:55 +08:00
midoks 0d02d0ebea Update init.lua 2022-10-12 00:53:00 +08:00
midoks 9e207ad4d3 添加 强制安全验证 功能 2022-10-12 00:38:23 +08:00
midoks f6cfe29956 Update debian.sh 2022-10-11 18:03:36 +08:00
midoks e439111761 Update mw.py 2022-10-11 17:47:48 +08:00
midoks e576d0b443 listen.backlog = 4096 设置默认 2022-10-11 17:28:07 +08:00
midoks 02e2c42225 up 2022-10-11 17:10:13 +08:00
midoks 45dec0a3d6 ip 2022-10-11 16:35:44 +08:00
midoks 28e2abc829 demo 2022-10-11 16:26:15 +08:00
midoks d59c82b7c8 Update common.lua 2022-10-11 15:46:04 +08:00
midoks 32b2158795 Update common.lua 2022-10-11 15:45:49 +08:00
midoks 5a37305c73 Update common.lua 2022-10-11 15:45:08 +08:00
midoks c043963e8e Update common.lua 2022-10-11 15:43:10 +08:00
midoks 40d755b44e up 2022-10-11 15:39:13 +08:00
midoks 00aa791205 waf debug3 2022-10-11 15:34:02 +08:00
midoks 431b3646af waf debug2 2022-10-11 15:27:08 +08:00
midoks 910aaa81de waf debug1 2022-10-11 15:22:28 +08:00
midoks 0cf35955d8 Merge branch 'master' of github.com:midoks/mdserver-web 2022-08-14 15:44:39 +08:00
271 changed files with 26180 additions and 4150 deletions
+5
View File
@@ -0,0 +1,5 @@
# These are supported funding model platforms
github: midoks
custom: https://afdian.net/a/mdserver-web
+1 -7
View File
@@ -1,9 +1,3 @@
### 合并描述
对pull请求的内容进行清晰、简洁的描述,即应该解决什么问题?
问题链接:<!--将问题链接粘贴到此处,如果不适用,请填写“不适用”->
### 清单
- [ ] 我添加了测试用例来覆盖新代码。
- 我添加了测试用例来覆盖新代码。
+2 -1
View File
@@ -145,6 +145,8 @@ data/osname.pl
data/only_netio_counters.pl
data/system.db-journal
data/hook_*.json
data/letsencrypt.json
data/basic_auth.json
plugins/l2tp
plugins/openlitespeed
@@ -156,4 +158,3 @@ plugins/mail
debug.out
+28 -11
View File
@@ -33,7 +33,7 @@
### 主要插件介绍
* OpenResty - 轻量级,占有内存少,并发能力强。
* PHP[52-81] - PHP是世界上最好的编程语言。
* PHP[53-82] - PHP是世界上最好的编程语言。
* MySQL - 一种关系数据库管理系统。
* MariaDB - 是MySQL的一个重要分支。
* MongoDB - 一种非关系NOSQL数据库管理系统。
@@ -70,6 +70,7 @@ PHP[72-81]支持phpMyAdmin[5.2.0]
# 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.la/)
- [奈飞丝 - 奈飞中国 Netflix MOD首发](https://naifeis.com/index.php#/register?code=k7P7V6Ur)
# AD - VPS推荐 - 🙏
@@ -78,7 +79,7 @@ PHP[72-81]支持phpMyAdmin[5.2.0]
| 服务商 | LOGO | 推广地址 | 优惠码 |
| ------------- |----------|-----------|-------|
| digitalvirt |[![digitalvirt](https://digitalvirt.com/templates/BlueWhite/img/logo-dark.svg)](https://digitalvirt.com/aff.php?aff=154) | https://digitalvirt.com/aff.php?aff=154 | 9SYDY7UH0U |
| 搬瓦工 |[![搬瓦工](https://bwh81.net/templates/organicbandwagon/images/logo.png)](https://bandwagonhost.com/aff.php?aff=54161) | https://bandwagonhost.com/aff.php?aff=54161 | BWH3HYATVBJW |
| 搬瓦工 |[![搬瓦工](https://bwh81.net/templates/organicbandwagon/images/logo.png)](https://bwh81.net/aff.php?aff=54161) | https://bwh81.net/aff.php?aff=54161 | BWH3HYATVBJW |
# Docker
@@ -90,15 +91,18 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.9.13
### 版本更新 0.11.0
* 优化弹框。
* 修复计划任务[日志切割]。
* 优化mysql的与phpmyadmin的连接。
* PHP添加`会话管理`功能。
* redis优化。
* 更新mysql[5.7]的安装。
* OP防火墙部分功能优化。
* 改造HTTPS升级,为lets和acme申请。
* 改造SSH管理,加入`禁止密码登陆`。
* 计划任务BUG,修改时错误提示。
* PG在debian11优化。
* PHP默认配置curl,openssl ssl配置优化。
* 初始花安装提示。
* 面板设置UI优化。
* 加入BasicAuth认证功能。
* MySQL[APT,YUM]安装检查优化。
* MySQL导入优化,对sql后缀支持。
### JSDelivr安装地址
@@ -114,6 +118,12 @@ curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/instal
curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh | bash
```
- 卸载脚本
```
wget -O uninstall.sh https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/uninstall.sh && bash uninstall.sh
```
### 备用地址
- 初始安装
@@ -129,6 +139,12 @@ curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash
```
- 卸载脚本
```
wget -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/uninstall.sh && bash uninstall.sh
```
### 通用软件安装[命令行安装]
@@ -145,9 +161,10 @@ curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/qu
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install_dev.sh | bash
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
wget -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/uninstall.sh && bash uninstall.sh
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install_dev.sh | bash
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/update_dev.sh | bash
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash
```
### 捐赠地址 USDT(TRC20)
+16 -4
View File
@@ -1,13 +1,22 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 入口文件
# ---------------------------------------------------------------------------------
# pip install profiler_online
# 性能测试
# from profiler_online import run_profiler
# run_profiler()
from gevent import monkey
monkey.patch_all()
import sys
import io
import os
@@ -17,6 +26,9 @@ from route import app, socketio
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
from gevent import monkey
monkey.patch_all()
try:
if __name__ == "__main__":
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+42 -8
View File
@@ -1,5 +1,17 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 公共操作
# ---------------------------------------------------------------------------------
import os
import sys
import time
@@ -23,6 +35,7 @@ def init():
initDB()
initUserInfo()
initInitD()
initInitTask()
def local():
@@ -58,16 +71,19 @@ def doContentReplace(src, dst):
def initInitD():
# systemctl
# 有问题
# if os.path.exists('/lib/systemd/system'):
# systemd_mw = '/lib/systemd/system/mw.service'
# systemd_mw_task = '/lib/systemd/system/mw-task.service'
# sysCfgDir = mw.systemdCfgDir()
# if os.path.exists(sysCfgDir) and mw.getOsName() == 'centos' and mw.getOsID() == '9':
# systemd_mw = sysCfgDir + '/mw.service'
# systemd_mw_task = sysCfgDir + '/mw-task.service'
# systemd_mw_tpl = mw.getRunDir() + '/scripts/init.d/mw.service.tpl'
# systemd_mw_task_tpl = mw.getRunDir() + '/scripts/init.d/mw-task.service.tpl'
# os.remove(systemd_mw)
# os.remove(systemd_mw_task)
# if os.path.exists(systemd_mw):
# os.remove(systemd_mw)
# if os.path.exists(systemd_mw_task):
# os.remove(systemd_mw_task)
# doContentReplace(systemd_mw_tpl, systemd_mw)
# doContentReplace(systemd_mw_task_tpl, systemd_mw_task)
@@ -81,24 +97,42 @@ def initInitD():
mw.execShell('chmod +x ' + script_bin)
# 在linux系统中,确保/etc/init.d存在
if not mw.isAppleSystem() and not os.path.exists("/etc/rc.d/init.d"):
mw.execShell('mkdir -p /etc/rc.d/init.d')
if not mw.isAppleSystem() and not os.path.exists("/etc/init.d"):
mw.execShell('mkdir -p /etc/init.d')
# initd
if os.path.exists("/etc/init.d"):
initd_bin = '/etc/init.d/mw'
if os.path.exists('/etc/rc.d/init.d'):
initd_bin = '/etc/rc.d/init.d/mw'
if not os.path.exists(initd_bin):
import shutil
shutil.copyfile(script_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
# 加入自启动
mw.execShell('which chkconfig && chkconfig --add mw')
if os.path.exists('/etc/init.d'):
initd_bin = '/etc/init.d/mw'
if not os.path.exists(initd_bin):
import shutil
shutil.copyfile(script_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
# 加入自启动
mw.execShell('which update-rc.d && update-rc.d -f mw defaults')
# 获取系统IPV4
mw.setHostAddr(mw.getLocalIp())
def initInitTask():
# 创建证书同步命令
import cert_api
api = cert_api.cert_api()
api.createCertCron()
def initUserInfo():
data = mw.M('users').where('id=?', (1,)).getField('password')
+210 -17
View File
@@ -1,5 +1,17 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 配置操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
@@ -15,11 +27,14 @@ from flask import request
class config_api:
__version = '0.9.13'
__version = '0.11.0'
def __init__(self):
pass
def getVersion(self):
return self.__version
##### ----- start ----- ###
# 取面板列表
@@ -107,6 +122,96 @@ class config_api:
session['username'] = name1
return mw.returnJson(True, '用户修改成功!')
def setWebnameApi(self):
webname = request.form.get('webname', '')
if webname != mw.getConfig('title'):
mw.setConfig('title', webname)
return mw.returnJson(True, '面板别名保存成功!')
def setPortApi(self):
port = request.form.get('port', '')
if port != mw.getHostPort():
import system_api
import firewall_api
if os.path.exists("/lib/systemd/system/firewalld.service"):
if not firewall_api.firewall_api().getFwStatus():
return mw.returnJson(False, 'firewalld必须先启动!')
mw.setHostPort(port)
msg = mw.getInfo('放行端口[{1}]成功', (port,))
mw.writeLog("防火墙管理", msg)
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
mw.M('firewall').add('port,ps,addtime', (port, "配置修改", addtime))
firewall_api.firewall_api().addAcceptPort(port)
firewall_api.firewall_api().firewallReload()
system_api.system_api().restartMw()
return mw.returnJson(True, '端口保存成功!')
def setIpApi(self):
host_ip = request.form.get('host_ip', '')
if host_ip != mw.getHostAddr():
mw.setHostAddr(host_ip)
return mw.returnJson(True, 'IP保存成功!')
def setWwwDirApi(self):
sites_path = request.form.get('sites_path', '')
if sites_path != mw.getWwwDir():
mw.setWwwDir(sites_path)
return mw.returnJson(True, '修改默认建站目录成功!')
def setBackupDirApi(self):
backup_path = request.form.get('backup_path', '')
if backup_path != mw.getBackupDir():
mw.setBackupDir(backup_path)
return mw.returnJson(True, '修改默认备份目录成功!')
def setBasicAuthApi(self):
basic_user = request.form.get('basic_user', '').strip()
basic_pwd = request.form.get('basic_pwd', '').strip()
basic_open = request.form.get('is_open', '').strip()
salt = '_md_salt'
path = 'data/basic_auth.json'
is_open = True
if basic_open == 'false':
if os.path.exists(path):
os.remove(path)
return mw.returnJson(True, '删除BasicAuth成功!')
if basic_user == '' or basic_pwd == '':
return mw.returnJson(True, '用户和密码不能为空!')
ba_conf = None
if os.path.exists(path):
try:
ba_conf = json.loads(public.readFile(path))
except:
os.remove(path)
if not ba_conf:
ba_conf = {
"basic_user": mw.md5(basic_user + salt),
"basic_pwd": mw.md5(basic_pwd + salt),
"open": is_open
}
else:
ba_conf['basic_user'] = mw.md5(basic_user + salt)
ba_conf['basic_pwd'] = mw.md5(basic_pwd + salt)
ba_conf['open'] = is_open
mw.writeFile(path, json.dumps(ba_conf))
os.chmod(path, 384)
mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open)
mw.restartMw()
return mw.returnJson(True, '设置成功!')
def setApi(self):
webname = request.form.get('webname', '')
port = request.form.get('port', '')
@@ -164,10 +269,12 @@ class config_api:
def setAdminPathApi(self):
admin_path = request.form.get('admin_path', '').strip()
admin_path_checks = ['/', '/close', '/login', '/do_login', '/site',
'/sites', '/download_file', '/control', '/crontab',
'/firewall', '/files', 'config', '/soft', '/system',
'/code', '/ssl', '/plugins']
admin_path_checks = ['/', '/close', '/login',
'/do_login', '/site', '/sites',
'/download_file', '/control', '/crontab',
'/firewall', '/files', 'config',
'/soft', '/system', '/code',
'/ssl', '/plugins', '/hook']
if admin_path == '':
admin_path = '/'
if admin_path != '/':
@@ -176,16 +283,18 @@ class config_api:
if admin_path in admin_path_checks:
return mw.returnJson(False, '该入口已被面板占用,请使用其它入口!')
if not re.match("^/[\w\./-_]+$", admin_path):
return mw.returnJson(False, '入口地址格式不正确,示例: /my_panel')
else:
domain = mw.readFile('data/domain.conf')
if not domain:
domain = ''
limitip = mw.readFile('data/limitip.conf')
if not limitip:
limitip = ''
if not domain.strip() and not limitip.strip():
return mw.returnJson(False, '警告,关闭安全入口等于直接暴露你的后台地址在外网,十分危险,至少开启以下一种安全方式才能关闭:<a style="color:red;"><br>1、绑定访问域名<br>2、绑定授权IP</a>')
return mw.returnJson(False, '入口地址格式不正确,示例: /mw_rand')
# else:
# domain = mw.readFile('data/bind_domain.pl')
# if not domain:
# domain = ''
# limitip = mw.readFile('data/bind_limitip.pl')
# if not limitip:
# limitip = ''
# if not domain.strip() and not limitip.strip():
# return mw.returnJson(False,
# '警告,关闭安全入口等于直接暴露你的后台地址在外网,十分危险,至少开启以下一种安全方式才能关闭:<a
# style="color:red;"><br>1、绑定访问域名<br>2、绑定授权IP</a>')
admin_path_file = 'data/admin_path.pl'
admin_path_old = '/'
@@ -302,8 +411,83 @@ class config_api:
return True
return False
def getVersion(self):
return self.__version
# 获取临时登录列表
def getTempLoginApi(self):
if 'tmp_login_expire' in session:
return mw.returnJson(False, '没有权限')
limit = request.form.get('limit', '10').strip()
p = request.form.get('p', '1').strip()
tojs = request.form.get('tojs', '').strip()
tempLoginM = mw.M('temp_login')
tempLoginM.where('state=? and expire<?',
(0, int(time.time()))).setField('state', -1)
start = (int(p) - 1) * (int(limit))
vlist = tempLoginM.limit(str(start) + ',' + str(limit)).order('id desc').field(
'id,addtime,expire,login_time,login_addr,state').select()
data = {}
data['data'] = vlist
count = tempLoginM.count()
page_args = {}
page_args['count'] = count
page_args['tojs'] = 'get_temp_login'
page_args['p'] = p
page_args['row'] = limit
data['page'] = mw.getPage(page_args)
return mw.getJson(data)
# 删除临时登录
def removeTempLoginApi(self):
if 'tmp_login_expire' in session:
return mw.returnJson(False, '没有权限')
sid = request.form.get('id', '10').strip()
if mw.M('temp_login').where('id=?', (sid,)).delete():
mw.writeLog('面板设置', '删除临时登录连接')
return mw.returnJson(True, '删除成功')
return mw.returnJson(False, '删除失败')
def setTempLoginApi(self):
if 'tmp_login_expire' in session:
return mw.returnJson(False, '没有权限')
s_time = int(time.time())
mw.M('temp_login').where(
'state=? and expire>?', (0, s_time)).delete()
token = mw.getRandomString(48)
salt = mw.getRandomString(12)
pdata = {
'token': mw.md5(token + salt),
'salt': salt,
'state': 0,
'login_time': 0,
'login_addr': '',
'expire': s_time + 3600,
'addtime': s_time
}
if not mw.M('temp_login').count():
pdata['id'] = 101
if mw.M('temp_login').insert(pdata):
mw.writeLog('面板设置', '生成临时连接,过期时间:{}'.format(
mw.formatDate(times=pdata['expire'])))
return mw.getJson({'status': True, 'msg': "临时连接已生成", 'token': token, 'expire': pdata['expire']})
return mw.returnJson(False, '连接生成失败')
def getTempLoginLogsApi(self):
if 'tmp_login_expire' in session:
return mw.returnJson(False, '没有权限')
logs_id = request.form.get('id', '').strip()
logs_id = int(logs_id)
data = mw.M('logs').where(
'uid=?', (logs_id,)).order('id desc').field(
'id,type,uid,log,addtime').select()
return mw.returnJson(False, 'ok', data)
def get(self):
@@ -341,6 +525,15 @@ class config_api:
else:
data['ssl'] = ''
basic_auth = 'data/basic_auth.json'
if os.path.exists(basic_auth):
bac = mw.readFile(basic_auth)
bac = json.loads(bac)
if bac['open']:
data['basic_auth'] = 'checked'
else:
data['basic_auth'] = ''
data['site_count'] = mw.M('sites').count()
data['username'] = mw.M('users').where(
+95 -5
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 计划任务操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
@@ -68,8 +81,8 @@ class crontab_api:
_list[i]['where_hour']), str(_list[i]['where_minute'])))
data.append(tmp)
_ret = {}
_ret['data'] = data
rdata = {}
rdata['data'] = data
count = mw.M('crontab').where('', ()).count()
_page = {}
@@ -78,9 +91,17 @@ class crontab_api:
_page['row'] = psize
_page['tojs'] = "getCronData"
_ret['list'] = mw.getPage(_page)
_ret['p'] = p
return mw.getJson(_ret)
rdata['list'] = mw.getPage(_page)
rdata['p'] = p
# backup hock
bh_file = mw.getPanelDataDir() + "/hook_backup.json"
if os.path.exists(bh_file):
hb_data = mw.readFile(bh_file)
hb_data = json.loads(hb_data)
rdata['backup_hook'] = hb_data
return mw.getJson(rdata)
# 设置计划任务状态
def setCronStatusApi(self):
@@ -107,6 +128,56 @@ class crontab_api:
'id=?', (sid,)).field(self.field).find()
return mw.getJson(data)
# 参数校验
def cronCheck(self, params):
if params['stype'] == 'site' or params['stype'] == 'database' or params['stype'] == 'logs':
if params['save'] == '':
return False, '保留份数不能为空!'
if params['type'] == 'day':
if params['hour'] == '':
return False, '小时不能为空!'
if params['minute'] == '':
return False, '分钟不能为空!'
if params['type'] == 'day-n':
if params['where1'] == '':
return False, '天不能为空!'
if params['hour'] == '':
return False, '小时不能为空!'
if params['minute'] == '':
return False, '分钟不能为空!'
if params['type'] == 'hour':
if params['minute'] == '':
return False, '分钟不能为空!'
if params['type'] == 'hour-n':
if params['where1'] == '':
return False, '小时不能为空!'
if params['minute'] == '':
return False, '分钟不能为空!'
if params['type'] == 'minute-n':
if params['where1'] == '':
return False, '分钟不能为空!'
if params['type'] == 'week':
if params['hour'] == '':
return False, '小时不能为空!'
if params['minute'] == '':
return False, '分钟不能为空!'
if params['type'] == 'month':
if params['where1'] == '':
return False, '日不能为空!'
if params['hour'] == '':
return False, '小时不能为空!'
if params['minute'] == '':
return False, '分钟不能为空!'
return True, 'OK'
def modifyCrondApi(self):
sid = request.form.get('id', '')
iname = request.form.get('name', '')
@@ -139,6 +210,11 @@ class crontab_api:
'sbody': sbody,
'urladdress': urladdress,
}
is_check_pass, msg = self.cronCheck(params)
if not is_check_pass:
return mw.returnJson(is_check_pass, msg)
cuonConfig, get, name = self.getCrondCycle(params)
cronInfo = mw.M('crontab').where(
'id=?', (sid,)).field(self.field).find()
@@ -202,6 +278,10 @@ class crontab_api:
'urladdress': urladdress,
}
is_check_pass, msg = self.cronCheck(params)
if not is_check_pass:
return mw.returnJson(is_check_pass, msg)
addData = self.add(params)
if addData > 0:
return mw.returnJson(True, '添加成功')
@@ -409,6 +489,16 @@ class crontab_api:
shell = param.sFile
else:
head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n"
source_bin_activate = '''
export LANG=en_US.UTF-8
MW_PATH=%s/bin/activate
if [ -f $MW_PATH ];then
source $MW_PATH
fi
''' % (mw.getRunDir(),)
head = head + source_bin_activate + "\n"
log = '.log'
script_dir = mw.getServerDir() + "/mdserver-web/scripts"
+49 -12
View File
@@ -1,5 +1,17 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# sqlite3操作
# ---------------------------------------------------------------------------------
import sqlite3
import os
@@ -23,7 +35,7 @@ class Sql():
def __init__(self):
self.__DB_FILE = 'data/default.db'
def __GetConn(self):
def __getConn(self):
# 取数据库对象
try:
if self.__DB_CONN == None:
@@ -100,10 +112,11 @@ class Sql():
def select(self):
# 查询数据集
self.__GetConn()
self.__getConn()
try:
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \
self.__OPT_WHERE + self.__OPT_GROUP + self.__OPT_ORDER + self.__OPT_LIMIT
# print(sql)
result = self.__DB_CONN.execute(sql, self.__OPT_PARAM)
data = result.fetchall()
# 构造字曲系列
@@ -133,7 +146,7 @@ class Sql():
def inquiry(self, input_field=''):
# 查询数据集
# 不清空查询参数
self.__GetConn()
self.__getConn()
try:
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + \
self.__OPT_WHERE + self.__OPT_GROUP + self.__OPT_ORDER + self.__OPT_LIMIT
@@ -171,6 +184,7 @@ class Sql():
def getField(self, keyName):
# 取回指定字段
result = self.field(keyName).select()
# print(result)
if len(result) == 1:
return result[0][keyName]
return result
@@ -197,7 +211,7 @@ class Sql():
def add(self, keys, param):
# 插入数据
self.__GetConn()
self.__getConn()
try:
values = ""
for key in keys.split(','):
@@ -213,6 +227,29 @@ class Sql():
except Exception as ex:
return "error: " + str(ex)
# 插入数据
def insert(self, pdata):
if not pdata:
return False
keys, param = self.__format_pdata(pdata)
return self.add(keys, param)
# 更新数据
def update(self, pdata):
if not pdata:
return False
keys, param = self.__format_pdata(pdata)
return self.save(keys, param)
# 构造数据
def __format_pdata(self, pdata):
keys = pdata.keys()
keys_str = ','.join(keys)
param = []
for k in keys:
param.append(pdata[k])
return keys_str, tuple(param)
def checkInput(self, data):
if not data:
return data
@@ -233,7 +270,7 @@ class Sql():
def addAll(self, keys, param):
# 插入数据
self.__GetConn()
self.__getConn()
try:
values = ""
for key in keys.split(','):
@@ -252,7 +289,7 @@ class Sql():
def save(self, keys, param):
# 更新数据
self.__GetConn()
self.__getConn()
try:
opt = ""
for key in keys.split(','):
@@ -277,7 +314,7 @@ class Sql():
def delete(self, id=None):
# 删除数据
self.__GetConn()
self.__getConn()
try:
if id:
self.__OPT_WHERE = " WHERE id=?"
@@ -291,7 +328,7 @@ class Sql():
return "error: " + str(ex)
def originExecute(self, sql, param=()):
self.__GetConn()
self.__getConn()
try:
result = self.__DB_CONN.execute(sql, param)
self.__DB_CONN.commit()
@@ -301,7 +338,7 @@ class Sql():
def execute(self, sql, param=()):
# 执行SQL语句返回受影响行
self.__GetConn()
self.__getConn()
# print sql, param
try:
result = self.__DB_CONN.execute(sql, param)
@@ -312,7 +349,7 @@ class Sql():
def query(self, sql, param):
# 执行SQL语句返回数据集
self.__GetConn()
self.__getConn()
try:
result = self.__DB_CONN.execute(sql, param)
# 将元组转换成列表
@@ -323,7 +360,7 @@ class Sql():
def create(self, name):
# 创建数据表
self.__GetConn()
self.__getConn()
import mw
script = mw.readFile('data/' + name + '.sql')
result = self.__DB_CONN.executescript(script)
@@ -332,7 +369,7 @@ class Sql():
def fofile(self, filename):
# 执行脚本
self.__GetConn()
self.__getConn()
import mw
script = mw.readFile(filename)
result = self.__DB_CONN.executescript(script)
+35 -17
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 文件类操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
@@ -39,7 +52,7 @@ class files_api:
data = mw.getLastLine(path, int(line))
return mw.returnJson(True, 'OK', data)
except Exception as ex:
return mw.returnJson(False, u'无法正确读取文件!' + str(ex))
return mw.returnJson(False, '无法正确读取文件!' + str(ex))
def saveBodyApi(self):
path = request.form.get('path', '')
@@ -324,7 +337,7 @@ class files_api:
if not self.checkDir(path):
return mw.returnJson(False, '敏感目录,请不要花样作死!')
os.system('which chattr && chattr -R -i ' + rPath + path)
mw.execShell('which chattr && chattr -R -i ' + rPath + path)
if os.path.isdir(rPath + path):
import shutil
shutil.rmtree(rPath + path)
@@ -343,7 +356,7 @@ class files_api:
def closeRecycleBinApi(self):
rPath = self.rPath
os.system('which chattr && chattr -R -i ' + rPath)
mw.execShell('which chattr && chattr -R -i ' + rPath)
rlist = os.listdir(rPath)
i = 0
l = len(rlist)
@@ -626,6 +639,7 @@ class files_api:
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
auth = user + ':staff'
os.system('chown -R ' + auth + ' ' + filename)
os.system('chmod -R 755 ' + filename)
@@ -652,7 +666,7 @@ class files_api:
return mw.returnJson(False, '文件不存在', (path,))
if os.path.getsize(path) > 2097152:
return mw.returnJson(False, u'不能在线编辑大于2MB的文件!')
return mw.returnJson(False, '不能在线编辑大于2MB的文件!')
fp = open(path, 'rb')
data = {}
@@ -676,8 +690,10 @@ class files_api:
data['encoding'] = 'utf-8'
if char['encoding'] == 'Big5':
data['encoding'] = 'BIG5'
if not char['encoding'] in ['GBK', 'utf-8', 'BIG5']:
if not data['encoding'] in ['GBK', 'utf-8', 'BIG5']:
data['encoding'] = 'utf-8'
try:
if sys.version_info[0] == 2:
data['data'] = srcBody.decode(
@@ -691,16 +707,17 @@ class files_api:
data['encoding']).encode('utf-8', errors='ignore')
else:
data['data'] = srcBody.decode(data['encoding'])
return mw.returnJson(True, 'OK', data)
else:
if sys.version_info[0] == 2:
data['data'] = srcBody.decode('utf-8').encode('utf-8')
else:
data['data'] = srcBody.decode('utf-8')
data['encoding'] = u'utf-8'
data['encoding'] = 'utf-8'
return mw.returnJson(True, 'OK', data)
except Exception as ex:
return mw.returnJson(False, u'文件编码不被兼容,无法正确读取文件!' + str(ex))
return mw.returnJson(False, '文件编码不被兼容,无法正确读取文件!' + str(ex))
def saveBody(self, path, data, encoding='utf-8'):
if not os.path.exists(path):
@@ -724,7 +741,7 @@ class files_api:
mw.writeLog('文件管理', '文件保存成功', (path,))
return mw.returnJson(True, '文件保存成功')
except Exception as ex:
return mw.returnJson(False, 'FILE_SAVE_ERR:' + str(ex))
return mw.returnJson(False, '文件保存错误:' + str(ex))
def zip(self, sfile, dfile, stype, path):
if sfile.find(',') == -1:
@@ -734,16 +751,16 @@ class files_api:
try:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
if stype == 'zip':
os.system("cd '" + path + "' && zip '" + dfile +
"' -r '" + sfile + "' > " + tmps + " 2>&1")
mw.execShell("cd '" + path + "' && zip '" + dfile +
"' -r '" + sfile + "' > " + tmps + " 2>&1")
else:
sfiles = ''
for sfile in sfile.split(','):
if not sfile:
continue
sfiles += " '" + sfile + "'"
os.system("cd '" + path + "' && tar -zcvf '" +
dfile + "' " + sfiles + " > " + tmps + " 2>&1")
mw.execShell("cd '" + path + "' && tar -zcvf '" +
dfile + "' " + sfiles + " > " + tmps + " 2>&1")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件压缩成功!', (sfile, dfile))
return mw.returnJson(True, '文件压缩成功!')
@@ -758,16 +775,17 @@ class files_api:
try:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
if stype == 'zip':
os.system("cd " + path + " && unzip -d '" + dfile +
"' '" + sfile + "' > " + tmps + " 2>&1 &")
mw.execShell("cd " + path + " && unzip -o -d '" + dfile +
"' '" + sfile + "' > " + tmps + " 2>&1 &")
else:
sfiles = ''
for sfile in sfile.split(','):
if not sfile:
continue
sfiles += " '" + sfile + "'"
os.system("cd " + path + " && tar -zxvf " + sfiles +
" -C " + dfile + " > " + tmps + " 2>&1 &")
mw.execShell("cd " + path + " && tar -zxvf " + sfiles +
" -C " + dfile + " > " + tmps + " 2>&1 &")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件解压成功!', (sfile, dfile))
return mw.returnJson(True, '文件解压成功!')
@@ -781,7 +799,7 @@ class files_api:
# 检查是否为.user.ini
if path.find('.user.ini') >= 0:
os.system("which chattr && chattr -i '" + path + "'")
mw.execShell("which chattr && chattr -i '" + path + "'")
try:
if os.path.exists('data/recycle_bin.pl'):
+77 -35
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 防火墙操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
@@ -165,6 +178,8 @@ class firewall_api:
return self.getLogList(int(p), int(limit), search)
def getSshInfoApi(self):
data = {}
file = '/etc/ssh/sshd_config'
conf = mw.readFile(file)
rep = "#*Port\s+([0-9]+)\s*\n"
@@ -176,39 +191,40 @@ class firewall_api:
isPing = True
else:
file = '/etc/sysctl.conf'
conf = mw.readFile(file)
sys_conf = mw.readFile(file)
rep = "#*net\.ipv4\.icmp_echo_ignore_all\s*=\s*([0-9]+)"
tmp = re.search(rep, conf).groups(0)[0]
tmp = re.search(rep, sys_conf).groups(0)[0]
if tmp == '1':
isPing = False
except:
isPing = True
import system_api
panelsys = system_api.system_api()
version = panelsys.getSystemVersion()
if os.path.exists('/usr/bin/apt-get'):
if os.path.exists('/etc/init.d/sshd'):
cmd = "service sshd status | grep -P '(dead|stop)'|grep -v grep"
status = mw.execShell(cmd)
else:
cmd = "service ssh status | grep -P '(dead|stop)'|grep -v grep"
status = mw.execShell(cmd)
else:
if version.find(' 7.') != -1:
cmd = "systemctl status sshd.service | grep 'dead'|grep -v grep"
status = mw.execShell(cmd)
else:
cmd = "/etc/init.d/sshd status | grep -e 'stopped' -e '已停'|grep -v grep"
status = mw.execShell(cmd)
if len(status[0]) > 3:
# sshd 检测
status = True
cmd = "service sshd status | grep -P '(dead|stop)'|grep -v grep"
ssh_status = mw.execShell(cmd)
if ssh_status[0] != '':
status = False
else:
status = True
data = {}
cmd = "systemctl status sshd.service | grep 'dead'|grep -v grep"
ssh_status = mw.execShell(cmd)
if ssh_status[0] != '':
status = False
data['pass_prohibit_status'] = False
# 密码登陆配置检查
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
data['port'] = port
data['status'] = status
data['ping'] = isPing
if mw.isAppleSystem():
@@ -222,7 +238,7 @@ class firewall_api:
if int(port) < 22 or int(port) > 65535:
return mw.returnJson(False, '端口范围必需在22-65535之间!')
ports = ['21', '25', '80', '443', '7200', '8080', '888', '8888']
ports = ['21', '25', '80', '443', '888']
if port in ports:
return mw.returnJson(False, '(' + port + ')' + '特殊端口不可设置!')
@@ -249,7 +265,7 @@ class firewall_api:
self.firewallReload()
# mw.M('firewall').where(
# "ps=?", ('SSH远程管理服务',)).setField('port', port)
msg = mw.getInfo('改SSH端口为[{1}]成功!', port)
msg = "改SSH端口为[{}]成功!".format(port)
mw.writeLog("防火墙管理", msg)
return mw.returnJson(True, '修改成功!')
@@ -258,24 +274,50 @@ class firewall_api:
return mw.returnJson(True, '开发机不能操作!')
status = request.form.get('status', '1').strip()
version = mw.readFile('/etc/redhat-release')
if int(status) == 1:
msg = 'SSH服务已启用'
act = 'start'
if status == "1":
msg = 'SSH服务已停用'
act = 'stop'
else:
msg = 'SSH服务已启用'
act = 'start'
if not os.path.exists('/etc/redhat-release'):
mw.execShell('service ssh ' + act)
elif version.find(' 7.') != -1:
ssh_service = mw.systemdCfgDir() + '/sshd.service'
if os.path.exists(ssh_service):
mw.execShell("systemctl " + act + " sshd.service")
else:
mw.execShell("/etc/init.d/sshd " + act)
mw.execShell('service sshd ' + act)
if os.path.exists('/etc/init.d/sshd'):
mw.execShell('/etc/init.d/sshd ' + act)
mw.writeLog("防火墙管理", msg)
return mw.returnJson(True, '操作成功!')
def setSshPassStatusApi(self):
if mw.isAppleSystem():
return mw.returnJson(True, '开发机不能操作!')
status = request.form.get('status', '1').strip()
msg = '禁止密码登陆成功'
if status == "1":
msg = '开启密码登陆成功'
file = '/etc/ssh/sshd_config'
if not os.path.exists(file):
return mw.returnJson(False, '无法设置!')
conf = mw.readFile(file)
if status == '1':
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication yes\n", conf)
else:
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication no\n", conf)
mw.writeFile(file, conf)
mw.execShell("systemctl restart sshd.service")
mw.writeLog("SSH管理", msg)
return mw.returnJson(True, msg)
def setPingApi(self):
if mw.isAppleSystem():
return mw.returnJson(True, '开发机不能操作!')
+208 -26
View File
@@ -1,4 +1,17 @@
# coding: utf-8
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 核心方法库
# ---------------------------------------------------------------------------------
import os
import sys
@@ -45,6 +58,12 @@ def execShell(cmdstring, cwd=None, timeout=None, shell=True):
return (t1, t2)
def getTracebackInfo():
import traceback
errorMsg = traceback.format_exc()
return errorMsg
def getRunDir():
return os.getcwd()
@@ -69,10 +88,6 @@ def getLogsDir():
return getRootDir() + '/wwwlogs'
def getBackupDir():
return getRootDir() + '/backup'
def getWwwDir():
file = getRunDir() + '/data/site.pl'
if os.path.exists(file):
@@ -85,11 +100,29 @@ def setWwwDir(wdir):
return writeFile(file, wdir)
def getBackupDir():
file = getRunDir() + '/data/backup.pl'
if os.path.exists(file):
return readFile(file).strip()
return getRootDir() + '/backup'
def setBackupDir(bdir):
file = getRunDir() + '/data/backup.pl'
return writeFile(file, bdir)
def getAcmeDir():
acme = '/root/.acme.sh'
if isAppleSystem():
cmd = "who | sed -n '2, 1p' |awk '{print $1}'"
user = execShell(cmd)[0].strip()
acme = '/Users/' + user + '/.acme.sh'
if not os.path.exists(acme):
acme = '/.acme.sh'
return acme
def triggerTask():
isTask = getRunDir() + '/tmp/panelTask.pl'
writeFile(isTask, 'True')
@@ -110,10 +143,36 @@ def systemdCfgDir():
return "/tmp"
def getSslCrt():
if os.path.exists('/etc/ssl/certs/ca-certificates.crt'):
return '/etc/ssl/certs/ca-certificates.crt'
if os.path.exists('/etc/pki/tls/certs/ca-bundle.crt'):
return '/etc/pki/tls/certs/ca-bundle.crt'
return ''
def getOs():
return sys.platform
def getOsName():
cmd = "cat /etc/*-release | grep PRETTY_NAME |awk -F = '{print $2}' | awk -F '\"' '{print $2}'| awk '{print $1}'"
data = execShell(cmd)
return data[0].strip().lower()
def getOsID():
cmd = "cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F '\"' '{print $2}'"
data = execShell(cmd)
return data[0].strip()
def getFileSuffix(file):
tmp = file.split('.')
ext = tmp[len(tmp) - 1]
return ext
def isAppleSystem():
if getOs() == 'darwin':
return True
@@ -161,19 +220,24 @@ def isInstalledWeb():
def restartWeb():
return opWeb("reload")
def opWeb(method):
if not isInstalledWeb():
return False
# systemd
systemd = '/lib/systemd/system/openresty.service'
if os.path.exists(systemd):
execShell('systemctl reload openresty')
execShell('systemctl ' + method + ' openresty')
return True
# initd
initd = getServerDir() + '/openresty/init.d/openresty'
if os.path.exists(initd):
execShell(initd + ' ' + 'reload')
execShell(initd + ' ' + method)
return True
return False
@@ -189,7 +253,7 @@ def checkWebConfig():
cmd = "ulimit -n 10240 && " + op_dir + \
"/sbin/nginx -t -c " + op_dir + "/conf/nginx.conf"
result = execShell(cmd)
searchStr = 'successful'
searchStr = 'test is successful'
if result[1].find(searchStr) == -1:
msg = getInfo('配置文件错误: {1}', (result[1],))
writeLog("软件管理", msg)
@@ -233,11 +297,11 @@ def getPageObject(args, result='1,2,3,4,5,8'):
return (page.GetPage(info, result), page)
def md5(str):
def md5(content):
# 生成MD5
try:
m = hashlib.md5()
m.update(str.encode("utf-8"))
m.update(content.encode("utf-8"))
return m.hexdigest()
except Exception as ex:
return False
@@ -381,32 +445,38 @@ def getDate():
return time.strftime('%Y-%m-%d %X', time.localtime())
def writeLog(type, logMsg, args=()):
def writeLog(stype, msg, args=()):
# 写日志
try:
import time
import db
import json
from flask import session
uid = 1
if 'uid' in session:
uid = session['uid']
sql = db.Sql()
mDate = time.strftime('%Y-%m-%d %X', time.localtime())
data = (type, logMsg, mDate)
result = sql.table('logs').add('type,log,addtime', data)
mdate = time.strftime('%Y-%m-%d %X', time.localtime())
wmsg = getInfo(msg, args)
data = (stype, wmsg, uid, mdate)
result = sql.table('logs').add('type,log,uid,addtime', data)
return True
except Exception as e:
pass
return False
def writeFile(filename, str):
def writeFile(filename, content, mode='w+'):
# 写文件内容
try:
fp = open(filename, 'w+')
fp.write(str)
fp = open(filename, mode)
fp.write(content)
fp.close()
return True
except Exception as e:
return False
def backFile(self, file, act=None):
def backFile(file, act=None):
"""
@name 备份配置文件
@param file 需要备份的文件
@@ -415,10 +485,12 @@ def backFile(self, file, act=None):
file_type = "_bak"
if act:
file_type = "_def"
execShell("/usr/bin/cp -p {0} {1}".format(file, file + file_type))
# print("cp -p {0} {1}".format(file, file + file_type))
execShell("cp -p {0} {1}".format(file, file + file_type))
def restoreFile(self, file, act=None):
def restoreFile(file, act=None):
"""
@name 还原配置文件
@param file 需要还原的文件
@@ -427,7 +499,62 @@ def restoreFile(self, file, act=None):
file_type = "_bak"
if act:
file_type = "_def"
execShell("/usr/bin/cp -p {1} {0}".format(file, file + file_type))
execShell("cp -p {1} {0}".format(file, file + file_type))
def enPunycode(domain):
if sys.version_info[0] == 2:
domain = domain.encode('utf8')
tmp = domain.split('.')
newdomain = ''
for dkey in tmp:
if dkey == '*':
continue
# 匹配非ascii字符
match = re.search(u"[\x80-\xff]+", dkey)
if not match:
match = re.search(u"[\u4e00-\u9fa5]+", dkey)
if not match:
newdomain += dkey + '.'
else:
if sys.version_info[0] == 2:
newdomain += 'xn--' + \
dkey.decode('utf-8').encode('punycode') + '.'
else:
newdomain += 'xn--' + \
dkey.encode('punycode').decode('utf-8') + '.'
if tmp[0] == '*':
newdomain = "*." + newdomain
return newdomain[0:-1]
def dePunycode(domain):
# punycode 转中文
tmp = domain.split('.')
newdomain = ''
for dkey in tmp:
if dkey.find('xn--') >= 0:
newdomain += dkey.replace('xn--',
'').encode('utf-8').decode('punycode') + '.'
else:
newdomain += dkey + '.'
return newdomain[0:-1]
def buildSoftLink(src, dst, force=False):
'''
建立软连接
'''
if not os.path.exists(src):
return False
if os.path.exists(dst) and force:
os.remove(dst)
if not os.path.exists(dst):
execShell('ln -sf "' + src + '" "' + dst + '"')
return True
return False
def HttpGet(url, timeout=10):
@@ -473,6 +600,11 @@ def HttpGet2(url, timeout):
import urllib.request
try:
import ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
except:
pass
req = urllib.request.urlopen(url, timeout=timeout)
result = req.read().decode('utf-8')
return result
@@ -595,12 +727,14 @@ def getLastLine(path, num, p=1):
count = start_line + num
fp = open(path, 'rb')
buf = ""
fp.seek(-1, 2)
fp.seek(0, 2)
if fp.read(1) == "\n":
fp.seek(-1, 2)
fp.seek(0, 2)
data = []
b = True
n = 0
for i in range(count):
while True:
newline_pos = str.rfind(str(buf), "\n")
@@ -669,6 +803,11 @@ def getLocalIpBack():
return '127.0.0.1'
def getClientIp():
from flask import request
return request.remote_addr.replace('::ffff:', '')
def getLocalIp():
filename = 'data/iplist.txt'
try:
@@ -704,6 +843,14 @@ def inArray(arrays, searchStr):
return False
def formatDate(format="%Y-%m-%d %H:%M:%S", times=None):
# 格式化指定时间戳
if not times:
times = int(time.time())
time_local = time.localtime(times)
return time.strftime(format, time_local)
def checkIp(ip):
# 检查是否为IPv4地址
import re
@@ -715,9 +862,44 @@ def checkIp(ip):
return False
def createLinuxUser(user, group):
execShell("groupadd {}".format(group))
execShell('useradd -s /sbin/nologin -g {} {}'.format(user, group))
return True
def setOwn(filename, user, group=None):
if isAppleSystem():
return True
# 设置用户组
if not os.path.exists(filename):
return False
from pwd import getpwnam
try:
user_info = getpwnam(user)
user = user_info.pw_uid
if group:
user_info = getpwnam(group)
group = user_info.pw_gid
except:
if user == 'www':
createLinuxUser(user)
# 如果指定用户或组不存在,则使用www
try:
user_info = getpwnam('www')
except:
createLinuxUser(user)
user_info = getpwnam('www')
user = user_info.pw_uid
group = user_info.pw_gid
os.chown(filename, user, group)
return True
def checkPort(port):
# 检查端口是否合法
ports = ['21', '25', '7200', '888']
ports = ['21', '25', '443', '888']
if port in ports:
return False
intport = int(port)
@@ -800,7 +982,7 @@ def makeConf():
file = getRunDir() + '/data/json/config.json'
if not os.path.exists(file):
c = {}
c['title'] = 'mdserver-web | linux面板'
c['title'] = '猫王面板'
c['home'] = 'http://github/midoks/mdserver-web'
c['recycle_bin'] = True
c['template'] = 'default'
+13
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 分页库操作
# ---------------------------------------------------------------------------------
import math
import string
+74 -5
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 插件操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
@@ -91,6 +104,63 @@ class plugins_api:
return mw.returnJson(True, '成功!')
return mw.returnJson(False, '失败!')
def initApi(self):
plugin_names = {
'openresty': '1.21.4.1',
'php': '56',
'swap': '1.1',
'mysql': '5.7',
'phpmyadmin': '4.4.15',
}
pn_dir = mw.getPluginDir()
pn_server_dir = mw.getServerDir()
pn_list = []
for pn in plugin_names:
info = {}
pn_json = pn_dir + '/' + pn + '/info.json'
pn_server = pn_server_dir + '/' + pn
if not os.path.exists(pn_server):
tmp = mw.readFile(pn_json)
tmp = json.loads(tmp)
info['title'] = tmp['title']
info['name'] = tmp['name']
info['versions'] = tmp['versions']
info['default_ver'] = plugin_names[pn]
pn_list.append(info)
else:
return mw.returnJson(False, 'ok')
return mw.returnJson(True, 'ok', pn_list)
def initInstallApi(self):
pn_list = request.form.get('list', '')
try:
pn_list = json.loads(pn_list)
for pn in pn_list:
name = pn['name']
version = pn['version']
infoJsonPos = self.__plugin_dir + '/' + name + '/' + 'info.json'
pluginInfo = json.loads(mw.readFile(infoJsonPos))
self.hookInstall(pluginInfo)
execstr = 'cd ' + mw.getPluginDir() + '/' + name + ' && bash ' + \
pluginInfo['shell'] + ' install ' + version
taskAdd = ('安装[' + name + '-' + version + ']',
'execshell', '0', time.strftime('%Y-%m-%d %H:%M:%S'), execstr)
mw.M('tasks').add('name,type,status,addtime, execstr', taskAdd)
os.mkdir(mw.getServerDir() + '/php')
# 任务执行相关
mw.triggerTask()
return mw.returnJson(True, '添加成功')
except Exception as e:
return mw.returnJson(False, mw.getTracebackInfo())
def installApi(self):
rundir = mw.getRunDir()
name = request.form.get('name', '')
@@ -116,17 +186,16 @@ class plugins_api:
pluginInfo = json.loads(mw.readFile(infoJsonPos))
self.hookInstall(pluginInfo)
execstr = "cd " + os.getcwd() + "/plugins/" + \
name + " && /bin/bash " + pluginInfo["shell"] \
+ " install " + version
execstr = 'cd ' + mw.getPluginDir() + '/' + name + ' && bash ' + \
pluginInfo['shell'] + ' install ' + version
if mw.isAppleSystem():
print(execstr)
taskAdd = (None, mmsg + '[' + name + '-' + version + ']',
taskAdd = (mmsg + '[' + name + '-' + version + ']',
'execshell', '0', time.strftime('%Y-%m-%d %H:%M:%S'), execstr)
mw.M('tasks').add('id,name,type,status,addtime, execstr', taskAdd)
mw.M('tasks').add('name,type,status,addtime, execstr', taskAdd)
# 任务执行相关
mw.triggerTask()
+503 -220
View File
File diff suppressed because it is too large Load Diff
+14 -1
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 系统信息操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
@@ -442,7 +455,7 @@ class system_api:
else:
os.remove(filename)
count += 1
mw.serviceReload()
mw.restartWeb()
os.system('echo > /tmp/panelBoot.pl')
return total, count
+13
View File
@@ -1,5 +1,18 @@
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 任务页操作
# ---------------------------------------------------------------------------------
import psutil
import time
import os
+12 -1
View File
@@ -1,6 +1,17 @@
#!/usr/bin/env python
# coding: utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 验证码操作
# ---------------------------------------------------------------------------------
import random
import math
+1 -1
View File
@@ -9,7 +9,7 @@ if [ -f bin/activate ];then
source bin/activate
fi
# export LC_ALL="en_US.UTF-8"
export LC_ALL="en_US.UTF-8"
mw_start_task()
+14
View File
@@ -56,8 +56,10 @@ CREATE TABLE IF NOT EXISTS `logs` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`type` TEXT,
`log` TEXT,
`uid` TEXT,
`addtime` TEXT
);
ALTER TABLE `logs` ADD COLUMN `uid` INTEGER DEFAULT '1';
CREATE TABLE IF NOT EXISTS `sites` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -109,6 +111,18 @@ CREATE TABLE IF NOT EXISTS `tasks` (
`execstr` TEXT
);
CREATE TABLE IF NOT EXISTS `temp_login` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`token` REAL,
`salt` REAL,
`state` INTEGER,
`login_time` INTEGER,
`login_addr` REAL,
`logout_time` INTEGER,
`expire` INTEGER,
`addtime` INTEGER
);
CREATE TABLE IF NOT EXISTS `panel` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`title` TEXT,
+1
View File
@@ -1,6 +1,7 @@
server
{
listen {$PORT};
listen [::]:{$PORT};
server_name {$SERVER_NAME};
index index.php index.html index.htm default.php default.htm default.html;
root {$ROOT_DIR};
+418
View File
@@ -0,0 +1,418 @@
# coding:utf-8
'''
doc: https://docs.python.org/zh-cn/3/library/ftplib.html
'''
import sys
import io
import os
import time
import re
import json
import paramiko
import ftplib
sys.path.append(os.getcwd() + "/class/core")
import mw
DEBUG = True
BLOCK_SIZE = 1024 * 1024 * 2
# BLOCK_SIZE = 50
PROGRESS_FILE_NAME = "PROGRESS_FILE_NAME"
"""
=============自定义异常===================
"""
class OsError(Exception):
"""OS端异常"""
class ObjectNotFound(OsError):
"""对象不存在时抛出的异常"""
def __init__(self, *args, **kwargs):
message = "文件对象不存在。"
super(ObjectNotFound, self).__init__(message, *args, **kwargs)
class APIError(Exception):
"""API参数错误异常"""
def __init__(self, *args, **kwargs):
_api_error_msg = 'API资料校验失败,请核实!'
super(APIError, self).__init__(_api_error_msg, *args, **kwargs)
class FtpPSClient:
_title = "FTP"
_name = "ftp"
__host = None
__port = None
__user = None
__password = None
default_port = 21
default_backup_path = "/backup/"
config_file = "cfg.json"
def __init__(self, load_config=True, timeout=10):
self.timeout = timeout
if load_config:
data = self.get_config()
self.injection_config(data)
def get_config(self):
default_config = {
"ftp_host": '',
"ftp_user": '',
"ftp_pass": '',
"backup_path": self.default_backup_path
}
cfg = mw.getServerDir() + "/backup_ftp/" + self.config_file
if os.path.exists(cfg):
data = mw.readFile(cfg)
return json.loads(data)
else:
return default_config
def injection_config(self, data):
host = data["ftp_host"].strip()
if host.find(':') == -1:
self.__port = self.default_port
self.__host = data['ftp_host'].strip()
self.__user = data['ftp_user'].strip()
self.__password = data['ftp_pass'].strip()
bp = data['backup_path'].strip()
if bp:
self.backup_path = self.getPath(bp)
else:
self.backup_path = self.getPath(self.default_backup_path)
def authorize(self):
try:
if self.timeout is not None:
ftp = ftplib.FTP(timeout=self.timeout)
else:
ftp = ftplib.FTP()
debuglevel = 0
# if DEBUG:
# debuglevel = 3
ftp.set_debuglevel(debuglevel)
# ftp.set_pasv(True)
ftp.connect(self.__host, int(self.__port))
ftp.login(self.__user, self.__password)
return ftp
except Exception as e:
raise OsError("无法连接FTP客户端,请检查配置参数是否正确!")
# 取目录路径
def getPath(self, path):
if path[-1:] != '/':
path += '/'
if path[:1] != '/':
path = '/' + path
return path.replace('//', '/')
def generateDownloadUrl(self, object_name):
return 'ftp://' + \
self.__user + ':' + \
self.__password + '@' + \
self.__host + ':' + \
"/" + object_name
def buildDirName(self, data_type, file_name):
import re
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\."
sub_search = re.search(file_regx, file_name)
sub_path_name = ""
if sub_search:
sub_path_name = sub_search.groups()[0]
sub_path_name += '/'
# 构建OS存储路径
object_name = self.backup_path + \
data_type + '/' + \
sub_path_name + \
file_name
return object_name
def uploadFile(self, filename, data_type=None, *args, **kwargs):
client = self.authorize()
local_file_name = filename
filename = os.path.abspath(filename)
dirname = os.path.dirname(filename)
temp_name = os.path.split(filename)[1]
object_name = self.buildDirName(data_type, temp_name)
upload_tmp_dir = os.path.join(dirname, ".upload_tmp")
if not os.path.exists(upload_tmp_dir):
os.mkdir(upload_tmp_dir)
print("|-正在上传文件到 {}".format(object_name))
total_bytes = os.path.getsize(filename)
object_md5_name = mw.md5(object_name)
pg_file = os.path.join(upload_tmp_dir, object_md5_name + ".pl")
block_size = BLOCK_SIZE
if kwargs.get("block_size"):
try:
block_size = float(kwargs.get("block_size"))
except:
pass
remote_file_size = None
if not os.path.exists(pg_file):
# import uuid
# uid = str(uuid.uuid1())
progress_info = {
"filename": local_file_name,
"total_bytes": total_bytes,
"uploaded_bytes": 0,
}
mw.writeFile(pg_file, json.dumps(progress_info))
else:
progress_info = json.loads(mw.readFile(pg_file))
if total_bytes == progress_info.get("total_bytes"):
# 取远程文件大小
_max_loop = 10
while _max_loop > 0:
try:
time.sleep(1)
remote_file_size = client.size(object_name)
if remote_file_size > total_bytes:
remote_file_size = None
break
except Exception as e:
if DEBUG:
print(type(e))
print(e)
_max_loop -= 1
else:
remote_file_size = None
uploaded_bytes = 0 if remote_file_size is None else remote_file_size
dir_name = os.path.split(object_name)[0]
if dir_name:
self.createDirP(dir_name)
upload_start = time.time()
try:
if total_bytes > 1024 * 1024 * 1024:
with open(local_file_name, 'rb') as file_handler:
if remote_file_size is not None:
file_handler.seek(remote_file_size)
client.voidcmd("TYPE I")
datasock = ''
esize = ''
datasock, esize = client.ntransfercmd(
"STOR " + object_name, remote_file_size)
while True:
buf = file_handler.read(block_size)
if not len(buf):
break
datasock.sendall(buf)
uploaded_bytes += len(buf)
if DEBUG:
print('\ruploading %.2f%%' %
(float(uploaded_bytes) / total_bytes * 100))
print("uploaded_bytes", uploaded_bytes)
if uploaded_bytes == total_bytes:
break
datasock.close()
if DEBUG:
print('close data handle')
try:
client.voidcmd('NOOP')
except Exception as e:
if DEBUG:
print("Send NOOP command error:")
print(e)
else:
if DEBUG:
print('keep alive cmd success')
client.voidresp()
if DEBUG:
print('No loop cmd')
else:
# 小于1G文件直接上传
file_handler = open(local_file_name, "rb")
client.storbinary('STOR %s' % object_name,
file_handler, blocksize=block_size)
file_handler.close()
except Exception as e:
print(str(e))
completed_file_size = None
_max_loop = 10
while _max_loop > 0:
try:
time.sleep(1)
completed_file_size = client.size(object_name)
break
except Exception as e:
_max_loop -= 1
if DEBUG:
print("size error:" + str(e))
# 上传完成
if completed_file_size == total_bytes:
if DEBUG:
upload_completed = time.time()
upload_diff = upload_completed - upload_start
print("文件上传成功, 耗时: {}s。".format(upload_diff))
if os.path.exists(pg_file):
os.remove(pg_file)
return True
else:
if os.path.exists(pg_file):
os.remove(pg_file)
print("文件上传后大小不一致!")
print("completed_file_size:" + str(completed_file_size))
print("total_bytes:", total_bytes)
print("object_md5_name:", object_md5_name)
print("pg_file:", pg_file)
print("filename:", filename)
print("dirname:", dirname)
print("object_name:", object_name)
return False
def createDirP(self, dir_name):
"""创建远程目录
:param dir_name: 目录名称
:return:
"""
try:
dirnames = dir_name.split('/')
ftp = self.authorize()
# ftp.cwd(get.path);
for dirname in dirnames:
if not dirname or not dirname.strip():
continue
try:
flist = ftp.nlst()
if not dirname in flist:
ftp.mkd(dirname)
except:
# print("mlsd mode.")
try:
flist = list(ftp.mlsd())[1:]
for f in flist:
if dirname == f[0]:
break
else:
ftp.mkd(dirname)
except:
return False
ftp.cwd(dirname)
return True
except:
return False
def createDir(self, path, name):
ftp = self.authorize()
path = self.getPath(path)
ftp.cwd(path)
try:
ftp.mkd(name)
ftp.close()
return True
except Exception as e:
print(str(e))
ftp.close()
return False
def deleteDir(self, path, dir_name):
try:
ftp = self.authorize()
ftp.rmd(dir_name)
return True
except ftplib.error_perm as e:
print("deleteDir:" + str(e) + ":" + dir_name)
except Exception as e:
print(e)
return False
def deleteFile(self, filename):
try:
ftp = self.authorize()
ftp.delete(filename)
return True
except Exception as e:
print(str(e))
return False
def getList(self, path="/"):
ftp = self.authorize()
path = self.getPath(path)
ftp.cwd(path)
mlsd = False
try:
files = list(ftp.mlsd())
mlsd = True
except:
try:
files = ftp.nlst(path)
mlsd = False
except:
raise RuntimeError("FTP服务器数据返回异常!")
ftp.close()
# print(files)
f_list = []
dirs = []
data = []
default_time = '1971/01/01 01:01:01'
for dt in files:
# print(dt)
if mlsd:
dt_name = dt[0]
dt_info = dt[1]
else:
if dt.find("/") >= 0:
dt = dt.split("/")[-1]
tmp = {}
tmp['name'] = dt_name
if dt_name == '.' or dt_name == '..':
continue
tmp['time'] = dt_info['modify']
try:
tmp['size'] = dt_info['size']
tmp['type'] = "File"
tmp['download'] = self.generateDownloadUrl(path + dt_name)
f_list.append(tmp)
except:
tmp['size'] = dt_info['sizd']
tmp['type'] = None
tmp['download'] = ''
dirs.append(tmp)
data = dirs + f_list
mlist = {}
mlist['path'] = path
mlist['list'] = data
return mlist
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+101
View File
@@ -0,0 +1,101 @@
<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" style="display:none;" type="text" 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="upyunApi()">帐户设置</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>
<script type="text/javascript">
$.getScript( "/plugins/file?name=backup_ftp&f=js/backup_ftp.js", function(){
osList('/');
});
</script>
+257
View File
@@ -0,0 +1,257 @@
# 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
_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 'backup_ftp'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
sys.path.append(getPluginDir() + "/class")
from ftp_client import FtpPSClient
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
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 status():
return 'start'
def getConf():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置", [])
data = mw.readFile(cfg)
data = json.loads(data)
return mw.returnJson(True, "OK", data)
def setConf():
args = getArgs()
data = checkArgs(args, ['use_sftp', 'ftp_user',
'ftp_pass', 'ftp_host', 'backup_path'])
if not data[0]:
return data[1]
cfg = getServerDir() + "/cfg.json"
values = ['ftp_user',
'ftp_pass',
'ftp_host']
for v in values:
if args[v] == '':
return mw.returnJson(False, '必填资料不能为空,请核实!', [])
if args['backup_path'] == '':
args['backup_path'] = "/backup"
try:
ftp = FtpPSClient(load_config=False)
ftp.injection_config(args)
data = ftp.getList("/")
if data:
mw.writeFile(cfg, mw.getJson(args))
return mw.returnJson(True, '设置成功', [])
except Exception as e:
return mw.returnJson(False, "FTP校验失败,请核实!\n" + str(e), [])
def getList():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置FTP,请点击`账户设置`", [])
args = getArgs()
data = checkArgs(args, ['path'])
if not data[0]:
return data[1]
try:
ftp = FtpPSClient()
flist = ftp.getList(args['path'])
return mw.returnJson(True, "ok", flist)
except Exception as e:
return mw.returnJson(False, str(e), [])
def createDir():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置FTP,请点击`账户设置`", [])
args = getArgs()
data = checkArgs(args, ['path', 'name'])
if not data[0]:
return data[1]
ftp = FtpPSClient()
isok = ftp.createDir(args['path'], args['name'])
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]
ftp = FtpPSClient()
isok = ftp.deleteDir(args['path'], 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]
ftp = FtpPSClient()
isok = ftp.deleteFile(args['path'] + "/" + args['filename'])
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "删除失败")
def backupAllFunc(stype):
os.chdir(mw.getRunDir())
name = sys.argv[2]
num = sys.argv[3]
args = stype + " " + name + " " + num
cmd = 'python3 ' + mw.getRunDir() + '/scripts/backup.py ' + args
os.system(cmd)
# 开始执行上传信息
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
find_path = mw.getBackupDir() + '/' + stype + '/' + \
prefix_dict[stype] + '_' + name
find_new_file = "ls " + find_path + \
"_* | grep '.gz' | cut -d \ -f 1 | awk 'END {print}'"
filename = mw.execShell(find_new_file)[0].strip()
if filename == "":
print("not find upload file!")
return False
ftp = FtpPSClient()
ftp.uploadFile(filename, stype)
return True
def backupSite():
# 备份站点
pass
def in_array(name, arr=[]):
for x in arr:
if name == x:
return True
return False
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_config':
print(setConf())
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']):
print(backupAllFunc(func))
else:
print('error')
+17
View File
@@ -0,0 +1,17 @@
{
"title":"FTP存储空间",
"hook":["backup"],
"tip":"soft",
"name":"backup_ftp",
"type":"运行环境",
"ps":"将网站或数据库打包备份到FTP存储空间",
"versions":["1.0"],
"install_pre_inspection":false,
"shell":"install.sh",
"checks":"server/backup_ftp",
"path": "server/backup_ftp",
"author":"midoks",
"home":"",
"date":"2022-10-23",
"pid": "4"
}
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
sys_os=`uname`
Install_App()
{
mkdir -p ${serverPath}/backup_ftp
echo "${1}" > ${serverPath}/backup_ftp/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_App()
{
rm -rf ${serverPath}/backup_ftp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App $2
else
Uninstall_App $2
fi
+258
View File
@@ -0,0 +1,258 @@
function bkfPost(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:'backup_ftp', 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 getFtpLocalTime(data){
var str = data.slice(0,4)+"/"+data.slice(4,6)+"/"+data.slice(6,8)
+ " " + data.slice(8,10)+":"+data.slice(10,12)+":"+data.slice(12,14);
return str;
}
// 自定义部分
var i = null;
//设置API
function upyunApi(){
bkfPost('conf', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var token = rdata.data;
var check_status = token.use_sftp;
var sftp_checked = check_status === "true" ? " checked=\"checked\"" : "";
if (typeof(token.ftp_host) == 'undefined'){
token.ftp_host = '';
}
if (typeof(token.ftp_user) == 'undefined'){
token.ftp_user = '';
}
if (typeof(token.ftp_pass) == 'undefined'){
token.ftp_pass = '';
}
if (typeof(token.backup_path) == 'undefined'){
token.backup_path = '';
}
var apicon = '<div class="bingfa mtb15" style="padding-bottom:0px;">\
<p>\
<span class="span_tit">使用SFTP:</span>\ <input style="width: 20px; vertical-align:middle;" type="checkbox" name="use_sftp"'+sftp_checked+'> 是否使用SFTP进行数据传输 \
</p>\
<p>\
<span class="span_tit">Host:</span>\
<input placeholder="请输入主机地址" style="width: 200px;" type="text" name="upyun_service" value="'+token.ftp_host+'"> *服务器地址,FTP默认端口21, SFTP默认端口22\
</p>\
<p>\
<span class="span_tit">用户名:</span>\
<input style="width: 200px;" type="text" name="ftp_username" value="'+token.ftp_user+'"> *指定用户名\
</p>\
<p>\
<span class="span_tit">密码:</span>\
<input style="width: 200px;" type="password" name="ftp_password" value="'+token.ftp_pass+'"> *登录密码\
</p>\
<p>\
<span class="span_tit">存储位置:</span>\
<input placeholder="请输入存储位置" style="width: 200px;" type="text" name="backup_path" value="'+token.backup_path+'"> *相对于根目录的路径,默认是/backup\
</p>\
</div>';
layer.open({
type: 1,
area: "600px",
title: "FTP/SFTP帐户设置",
closeBtn: 1,
shift: 5,
shadeClose: false,
btn: ['确定','取消'],
content:apicon,
yes:function(index,layero){
var data = {
use_sftp:$("input[name='use_sftp']").prop('checked'),
ftp_user:$("input[name='ftp_username']").val(),
ftp_pass:$("input[name='ftp_password']").val(),
ftp_host:$("input[name='upyun_service']").val(),
backup_path:$("input[name='backup_path']").val()
}
bkfPost('set_config', data, function(rdata){
var rdata = $.parseJSON(rdata.data);
if (rdata.status){
showMsg(rdata.msg,function(){
layer.close(index);
osList("/");
},{icon:1},2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
})
},
});
});
}
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 path = $("#myPath").val();
var dirname = name;
// var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']});
bkfPost('create_dir', {path:path,name:dirname}, function(data){
var rdata = $.parseJSON(data.data);
if(rdata.status) {
showMsg(rdata.msg, function(){
layer.close(index);
osList(path);
} ,{icon:1}, 2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
});
}
});
}
//删除文件
function deleteFile(name, is_dir){
if (is_dir === false){
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
var filename = name;
bkfPost('delete_file', {filename:filename,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
osList(path);
},{icon:rdata.status?1:2},2000);
});
});
} else {
safeMessage('删除文件夹','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
bkfPost('delete_dir', {dir_name:name,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
osList(path);
},{icon:rdata.status?1:2},2000);
});
});
}
}
function osList(path){
bkfPost('get_list', {path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
if(rdata.status === false){
showMsg(rdata.msg,function(){
upyunApi();
},{icon:2},2000);
return;
}
var mlist = rdata.data;
// console.log(mlist);
var listBody = ''
var listFiles = ''
for(var i=0;i<mlist.list.length;i++){
if(mlist.list[i].type == null){
listBody += '<tr><td class="cursor" onclick="osList(\''+(path+'/'+mlist.list[i].name).replace('//','/')+'\')"><span class="ico ico-folder"></span>\<span>'+mlist.list[i].name+'</span></td>\
<td>-</td>\
<td>-</td>\
<td class="text-right"><a class="btlink" onclick="deleteFile(\''+mlist.list[i].name+'\', true)">删除</a></td></tr>'
}else{
listFiles += '<tr><td class="cursor"><span class="ico ico-file"></span>\<span>'+mlist.list[i].name+'</span></td>\
<td>'+toSize(mlist.list[i].size)+'</td>\
<td>'+getFtpLocalTime(mlist.list[i].time)+'</td>\
<td class="text-right"><a target="_blank" href="'+mlist.list[i].download+'" class="btlink">下载</a> | <a class="btlink" onclick="deleteFile(\''+mlist.list[i].name+'\', false)">删除</a></td></tr>'
}
}
listBody += listFiles;
var pathLi='';
var tmp = path.split('/')
var pathname = '';
var n = 0;
for(var i=0;i<tmp.length;i++){
if(n > 0 && tmp[i] == '') continue;
var dirname = tmp[i];
if(dirname == '') {
dirname = '根目录';
n++;
}
pathname += '/' + tmp[i];
pathname = pathname.replace('//','/');
pathLi += '<li><a title="'+pathname+'" onclick="osList(\''+pathname+'\')">'+dirname+'</a></li>';
}
var um = 1;
if(tmp[tmp.length-1] == '') um = 2;
var backPath = tmp.slice(0,tmp.length-um).join('/') || '/';
$('#myPath').val(path);
$(".upyunCon .place-input ul").html(pathLi);
$(".upyunlist .list-list").html(listBody);
upPathLeft();
$('#backBtn').unbind().click(function() {
osList(backPath);
});
$('.upyunCon .refreshBtn').unbind().click(function(){
osList(path);
});
});
}
//计算当前目录偏移
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)
}
}
// $('.layui-layer-page').css('height','670px');
+1 -1
View File
@@ -17,7 +17,7 @@ pluginService('clean');
function pRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>启动后,假如到计划中[2:30]执行。</li>';
readme += '<li>启动后,加入到计划中[2:30]执行。</li>';
readme += '<li>【*】代表要删除。</li>';
readme += '<li>添加/删除清除日志,可在`配置修改`中添加/删除。</li>';
readme += '<li>如果是目录,会寻找【.log】后缀的文件清空。</li>';
+1
View File
@@ -74,6 +74,7 @@ def initConf():
content = ""
clog = [
"/var/spool/clientmqueue/*",
"/var/log/cron-*",
"/var/log/maillog-*",
"/var/log/secure-*",
+3 -1
View File
@@ -29,9 +29,11 @@ read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=1
query_cache_size = 4M
tmp_table_size = 8M
query_cache_type = 1
query_cache_size = 4M
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535
+175 -33
View File
@@ -335,6 +335,10 @@ def initMysqlData():
data = mw.execShell(cmd)
# print(data[0])
# print(data[1])
if not mw.isAppleSystem():
mw.execShell('chown -R mysql:mysql ' + serverdir + '/data')
mw.execShell('chmod -R 755 ' + serverdir + '/data')
return False
return True
@@ -359,6 +363,11 @@ def initMariaDbPwd():
print("init mariadb password fail:" + data[1])
exit(1)
# 删除空账户
drop_empty_user = serverdir + '/bin/mysql ' + db_option + '-uroot -p' + \
pwd + ' -e "use mysql;delete from user where USER=\'\'"'
mw.execShell(drop_empty_user)
# 删除测试数据库
drop_test_db = serverdir + '/bin/mysql ' + db_option + ' -uroot -p' + \
pwd + ' -e "drop database test";'
@@ -366,13 +375,14 @@ def initMariaDbPwd():
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
if hostname != 'localhost':
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
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
@@ -541,13 +551,17 @@ def setMyPort():
return mw.returnJson(True, '编辑成功!')
def runInfo():
def runInfo(version):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动', [])
db = pMysqlDb()
data = db.query('show global status')
isError = isSqlError(data)
if isError != None:
return isError
gets = ['Max_used_connections', 'Com_commit', 'Com_rollback', 'Questions', 'Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests', 'Key_reads', 'Key_read_requests', 'Key_writes',
'Key_write_requests', 'Qcache_hits', 'Qcache_inserts', 'Bytes_received', 'Bytes_sent', 'Aborted_clients', 'Aborted_connects',
'Created_tmp_disk_tables', 'Created_tmp_tables', 'Innodb_buffer_pool_pages_dirty', 'Opened_files', 'Open_tables', 'Opened_tables', 'Select_full_join',
@@ -628,7 +642,7 @@ def isSqlError(mysqlMsg):
if "2003," in mysqlMsg:
return mw.returnJson(False, "Can't connect to MySQL server on '127.0.0.1' (61)")
if "using password:" in mysqlMsg:
return mw.returnJson(False, '数据库管理密码错误!')
return mw.returnJson(False, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
@@ -712,15 +726,82 @@ def importDbBackup():
return mw.returnJson(True, 'ok')
def deleteDbBackup():
def importDbExternal():
args = getArgs()
data = checkArgs(args, ['filename'])
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
bkDir = mw.getRootDir() + '/backup/database'
file = args['file']
name = args['name']
os.remove(bkDir + '/' + args['filename'])
import_dir = mw.getRootDir() + '/backup/import/'
file_path = import_dir + file
if not os.path.exists(file_path):
return mw.returnJson(False, '文件突然消失?')
exts = ['sql', 'gz', 'zip']
tmp = file.split('.')
ext = tmp[len(tmp) - 1]
if ext not in exts:
return mw.returnJson(False, '导入数据库格式不对!')
tmp = file.split('/')
tmpFile = tmp[len(tmp) - 1]
tmpFile = tmpFile.replace('.sql.' + ext, '.sql')
tmpFile = tmpFile.replace('.' + ext, '.sql')
tmpFile = tmpFile.replace('tar.', '')
# print(tmpFile)
import_sql = ""
if file.find("sql.gz") > -1:
cmd = 'cd ' + import_dir + ' && gzip -dc ' + \
file + " > " + import_dir + tmpFile
info = mw.execShell(cmd)
if info[1] == "":
import_sql = import_dir + tmpFile
if file.find(".zip") > -1:
cmd = 'cd ' + import_dir + ' && unzip -o ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if file.find("tar.gz") > -1:
cmd = 'cd ' + import_dir + ' && tar -zxvf ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if import_sql == "":
return mw.returnJson(False, '未找SQL文件')
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql
# print(mysql_cmd)
os.system(mysql_cmd)
os.remove(import_sql)
return mw.returnJson(True, 'ok')
def deleteDbBackup():
args = getArgs()
data = checkArgs(args, ['filename', 'path'])
if not data[0]:
return data[1]
path = args['path']
full_file = ""
bkDir = mw.getRootDir() + '/backup/database'
full_file = bkDir + '/' + args['filename']
if path != "":
full_file = path + "/" + args['filename']
os.remove(full_file)
return mw.returnJson(True, 'ok')
@@ -752,6 +833,39 @@ def getDbBackupList():
return mw.returnJson(True, 'ok', rr)
def getDbBackupImportList():
bkImportDir = mw.getRootDir() + '/backup/import'
if not os.path.exists(bkImportDir):
os.mkdir(bkImportDir)
blist = os.listdir(bkImportDir)
rr = []
for x in range(0, len(blist)):
name = blist[x]
p = bkImportDir + '/' + name
data = {}
data['name'] = name
rsize = os.path.getsize(p)
data['size'] = mw.toSize(rsize)
t = os.path.getctime(p)
t = time.localtime(t)
data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', t)
rr.append(data)
data['file'] = p
rdata = {
"list": rr,
"upload_dir": bkImportDir,
}
return mw.returnJson(True, 'ok', rdata)
def getDbList():
args = getArgs()
page = 1
@@ -1083,6 +1197,10 @@ def getDbAccess():
users = pdb.query("select Host from user where User='" +
username + "' AND Host!='localhost'")
isError = isSqlError(users)
if isError != None:
return isError
if len(users) < 1:
return mw.returnJson(True, "127.0.0.1")
accs = []
@@ -1122,6 +1240,22 @@ def setDbAccess():
return mw.returnJson(True, '设置成功!')
def fixDbAccess(version):
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")
appCMD(version, 'start')
return mw.returnJson(True, '修复成功!')
return mw.returnJson(True, '正常无需修复!')
except Exception as e:
return mw.returnJson(False, '修复失败请重试!')
def setDbRw(version=''):
args = getArgs()
data = checkArgs(args, ['username', 'id', 'rw'])
@@ -1532,30 +1666,32 @@ def setDbSlave(version):
def getMasterStatus(version=''):
try:
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动,或正在启动中...!', [])
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动,或正在启动中...!', [])
conf = getConf()
content = mw.readFile(conf)
master_status = False
if content.find('#log-bin') == -1 and content.find('log-bin') > 1:
dodb = findBinlogDoDb()
if len(dodb) > 0:
master_status = True
conf = getConf()
content = mw.readFile(conf)
master_status = False
if content.find('#log-bin') == -1 and content.find('log-bin') > 1:
dodb = findBinlogDoDb()
if len(dodb) > 0:
master_status = True
data = {}
data['mode'] = recognizeDbMode()
data['status'] = master_status
data = {}
data['mode'] = recognizeDbMode()
data['status'] = master_status
db = pMysqlDb()
dlist = db.query('show slave status')
db = pMysqlDb()
dlist = db.query('show slave status')
# print(dlist[0])
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
data['slave_status'] = True
# print(dlist[0])
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
data['slave_status'] = True
return mw.returnJson(master_status, '设置成功', data)
return mw.returnJson(master_status, '设置成功', data)
except Exception as e:
return mw.returnJson(False, "数据库密码错误,在管理列表-点击【修复】!", 'pwd')
def setMasterStatus(version=''):
@@ -2200,7 +2336,7 @@ def uninstallPreInspection(version):
if __name__ == "__main__":
func = sys.argv[1]
version = "5.6"
version = "10.6"
version_pl = getServerDir() + "/version.pl"
if os.path.exists(version_pl):
version = mw.readFile(version_pl).strip()
@@ -2226,7 +2362,7 @@ if __name__ == "__main__":
elif func == 'uninstall_pre_inspection':
print(uninstallPreInspection(version))
elif func == 'run_info':
print(runInfo())
print(runInfo(version))
elif func == 'db_status':
print(myDbStatus())
elif func == 'set_db_status':
@@ -2257,10 +2393,14 @@ if __name__ == "__main__":
print(setDbBackup())
elif func == 'import_db_backup':
print(importDbBackup())
elif func == 'import_db_external':
print(importDbExternal())
elif func == 'delete_db_backup':
print(deleteDbBackup())
elif func == 'get_db_backup_list':
print(getDbBackupList())
elif func == 'get_db_backup_import_list':
print(getDbBackupImportList())
elif func == 'add_db':
print(addDb())
elif func == 'del_db':
@@ -2277,6 +2417,8 @@ if __name__ == "__main__":
print(getDbAccess())
elif func == 'set_db_access':
print(setDbAccess())
elif func == 'fix_db_access':
print(fixDbAccess(version))
elif func == 'get_db_rw':
print(setDbRw(version))
elif func == 'set_db_ps':
+1 -1
View File
@@ -7,7 +7,7 @@
"uninstall_pre_inspection":true,
"checks": "server/mariadb",
"path": "server/mariadb",
"versions":["10.6","10.7","10.8"],
"versions":["10.6","10.7","10.8","10.9"],
"shell":"install.sh",
"checks":"server/mariadb",
"path":"server/mariadb",
+244 -107
View File
@@ -1,18 +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 myPost(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);
}
@@ -40,7 +30,7 @@ function myPostN(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);
}
@@ -59,7 +49,7 @@ function myPostN(method,args,callback, title){
function myAsyncPost(method,args){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(str2Obj(args));
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
@@ -184,6 +174,11 @@ function myPerfOpt() {
//获取MySQL配置
myPost('db_status','',function(data){
var rdata = $.parseJSON(data.data);
if ( typeof(rdata.status) != 'undefined' && !rdata.status){
layer.msg(rdata.msg, {icon:2});
return;
}
// console.log(rdata);
var key_buffer_size = toSizeM(rdata.mem.key_buffer_size);
var query_cache_size = toSizeM(rdata.mem.query_cache_size);
@@ -586,7 +581,7 @@ function setDbAccess(username){
yes:function(index){
var data = $("#set_db_access").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
if(!dataObj['access']){
dataObj['access'] = dataObj['dataAccess'];
if ( dataObj['dataAccess'] == 'ip'){
@@ -611,6 +606,15 @@ function setDbAccess(username){
});
}
function fixDbAccess(username){
myPost('fix_db_access', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
dbList();
},{icon: rdata.status ? 1 : 2});
});
}
function setDbPass(id, username, password){
var index = layer.open({
@@ -651,33 +655,15 @@ function setDbPass(id, username, password){
}
function addDatabase(type){
if (type==1){
var data = $("#add_db").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
if(!dataObj['address']){
dataObj['address'] = dataObj['dataAccess'];
}
myPost('add_db', dataObj, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
dbList();
}
$('.layui-layer-close1').click();
},{icon: rdata.status ? 1 : 2},600);
});
return;
}
var index = layer.open({
layer.open({
type: 1,
skin: 'demo-class',
area: '500px',
title: '添加数据库',
closeBtn: 1,
shift: 5,
shadeClose: true,
content: "<form class='bt-form pd20 pb70' id='add_db'>\
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='add_db'>\
<div class='line'>\
<span class='tname'>数据库名</span>\
<div class='info-r'><input name='name' class='bt-input-text mr5' placeholder='新的数据库名称' type='text' style='width:65%' value=''>\
@@ -705,28 +691,39 @@ function addDatabase(type){
</div>\
</div>\
<input type='hidden' name='ps' value='' />\
<div class='bt-form-submit-btn'>\
<button id='my_mod_close' type='button' class='btn btn-danger btn-sm btn-title'>关闭</button>\
<button type='button' class='btn btn-success btn-sm btn-title' onclick=\"addDatabase(1)\" >提交</button>\
</div>\
</form>",
});
success:function(){
$("input[name='name']").keyup(function(){
var v = $(this).val();
$("input[name='db_user']").val(v);
$("input[name='ps']").val(v);
});
$("input[name='name']").keyup(function(){
var v = $(this).val();
$("input[name='db_user']").val(v);
$("input[name='ps']").val(v);
});
$('#my_mod_close').click(function(){
$('.layui-layer-close1').click();
});
$('select[name="dataAccess"]').change(function(){
var v = $(this).val();
if (v == 'ip'){
$(this).after("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
} else {
$('#dataAccess_subid').remove();
$('select[name="dataAccess"]').change(function(){
var v = $(this).val();
if (v == 'ip'){
$(this).after("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
} else {
$('#dataAccess_subid').remove();
}
});
},
yes:function(index) {
var data = $("#add_db").serialize();
data = decodeURIComponent(data);
var dataObj = toArrayObject(data);
if(!dataObj['address']){
dataObj['address'] = dataObj['dataAccess'];
}
myPost('add_db', dataObj, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
dbList();
}
},{icon: rdata.status ? 1 : 2},600);
});
}
});
}
@@ -738,7 +735,6 @@ function delDb(id, name){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
$('.layui-layer-close1').click();
},{icon: rdata.status ? 1 : 2}, 600);
});
});
@@ -860,12 +856,14 @@ function openPhpmyadmin(name,username,password){
}
}
function delBackup(filename,name){
myPost('delete_db_backup',{filename:filename},function(){
function delBackup(filename, name, path){
if(typeof(path) == "undefined"){
path = "";
}
myPost('delete_db_backup',{filename:filename,path:path},function(){
layer.msg('执行成功!');
setTimeout(function(){
$('.layui-layer-close2').click();
setBackup(name);
setBackupReq(name);
},2000);
});
}
@@ -881,9 +879,180 @@ function importBackup(file,name){
});
}
function setBackup(db_name,obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
function importDbExternal(file,name){
myPost('import_db_external',{file:file,name:name}, function(data){
layer.msg('执行成功!');
});
}
function setLocalImport(db_name){
//上传文件
function uploadDbFiles(upload_dir){
var up_db = layer.open({
type:1,
closeBtn: 1,
title:"上传导入文件["+upload_dir+']',
area: ['500px','300px'],
shadeClose:false,
content:'<div class="fileUploadDiv">\
<input type="hidden" id="input-val" value="'+upload_dir+'" />\
<input type="file" id="file_input" multiple="true" autocomplete="off" />\
<button type="button" id="opt" autocomplete="off">添加文件</button>\
<button type="button" id="up" autocomplete="off" >开始上传</button>\
<span id="totalProgress" style="position: absolute;top: 7px;right: 147px;"></span>\
<span style="float:right;margin-top: 9px;">\
<font>文件编码:</font>\
<select id="fileCodeing" >\
<option value="byte">二进制</option>\
<option value="utf-8">UTF-8</option>\
<option value="gb18030">GB2312</option>\
</select>\
</span>\
<button type="button" id="filesClose" autocomplete="off">关闭</button>\
<ul id="up_box"></ul>\
</div>',
success:function(){
$('#filesClose').click(function(){
layer.close(up_db);
});
}
});
uploadStart(function(){
getList();
layer.close(up_db);
});
}
function getList(){
myPost('get_db_backup_import_list',{}, function(data){
var rdata = $.parseJSON(data.data);
var file_list = rdata.data.list;
var upload_dir = rdata.data.upload_dir;
var tbody = '';
for (var i = 0; i < file_list.length; i++) {
tbody += '<tr>\
<td><span> ' + file_list[i]['name'] + '</span></td>\
<td><span> ' + file_list[i]['size'] + '</span></td>\
<td><span> ' + file_list[i]['time'] + '</span></td>\
<td style="text-align: right;">\
<a class="btlink" onclick="importDbExternal(\'' + file_list[i]['name'] + '\',\'' +db_name+ '\')">导入</a> | \
<a class="btlink del" index="'+i+'">删除</a>\
</td>\
</tr>';
}
$('#import_db_file_list').html(tbody);
$('input[name="upload_dir"]').val(upload_dir);
$("#import_db_file_list .del").on('click',function(){
var index = $(this).attr('index');
var filename = file_list[index]["name"];
myPost('delete_db_backup',{filename:filename,path:upload_dir},function(){
showMsg('执行成功!', function(){
getList();
},{icon:1},2000);
});
});
});
}
var layerIndex = layer.open({
type: 1,
title: "从文件导入数据",
area: ['600px', '380px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_file_upload" class="btn btn-success btn-sm" type="button">从本地上传</button>\
</div >\
<div class="divtable">\
<input type="hidden" name="upload_dir" value=""> \
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody id="import_db_file_list" class="gztr"></tbody>\
</table>\
</div>\
<ul class="help-info-text c7">\
<li>仅支持sql、zip、sql.gz、(tar.gz|gz|tgz)</li>\
<li>zip、tar.gz压缩包结构:test.zip或test.tar.gz压缩包内,必需包含test.sql</li>\
<li>若文件过大,您还可以使用SFTP工具,将数据库文件上传到/www/backup/import</li>\
</ul>\
</div>\
</div>',
success:function(index){
$('#btn_file_upload').click(function(){
var upload_dir = $('input[name="upload_dir"]').val();
uploadDbFiles(upload_dir);
});
getList();
},
});
}
function setBackup(db_name){
var layerIndex = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
<button id="btn_local_import" class="btn btn-success btn-sm" type="button">外部导入</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table id="database_table" class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="list"></tbody>\
</table>\
</div>\
</div>\
</div>',
success:function(index){
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
showMsg('执行成功!', function(){
setBackupReq(db_name);
}, {icon:1}, 2000);
});
});
$('#btn_local_import').click(function(){
setLocalImport(db_name);
});
setBackupReq(db_name);
},
});
}
function setBackupReq(db_name, obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
var rdata = $.parseJSON(data.data);
var tbody = '';
for (var i = 0; i < rdata.data.length; i++) {
@@ -898,45 +1067,7 @@ function setBackup(db_name,obj){
</td>\
</tr> ';
}
var s = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 2,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
</table>\
</div>\
</div>\
</div>'
});
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
layer.msg('执行成功!');
setTimeout(function(){
layer.close(s);
setBackup(db_name,obj);
},2000);
});
});
$('#database_table tbody').html(tbody);
});
}
@@ -970,7 +1101,7 @@ function dbList(page, search){
list += '<td><span class="c9 input-edit" onclick="setDbPs(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['name']+'\',this)" style="display: inline-block;">'+rdata.data[i]['ps']+'</span></td>';
list += '<td style="text-align:right">';
list += '<a href="javascript:;" class="btlink" class="btlink" onclick="setBackup(\''+rdata.data[i]['name']+'\',this)" title="数据库备份">'+(rdata.data[i]['is_backup']?'备份':'未备份') +'</a> | ';
list += '<a href="javascript:;" class="btlink" class="btlink" onclick="setBackup(\''+rdata.data[i]['name']+'\')" title="数据库备份">'+(rdata.data[i]['is_backup']?'备份':'未备份') +'</a> | ';
var rw = '';
var rw_change = 'all';
@@ -1006,6 +1137,7 @@ function dbList(page, search){
<button onclick="setRootPwd(0,\''+rdata.info['root_pwd']+'\')" title="设置MySQL管理员密码" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">root密码</button>\
<button onclick="openPhpmyadmin(\'\',\'root\',\''+rdata.info['root_pwd']+'\')" title="打开phpMyadmin" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">phpMyAdmin</button>\
<button onclick="setDbAccess(\'root\')" title="ROOT权限" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">ROOT权限</button>\
<button onclick="fixDbAccess(\'root\')" title="修复" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">修复</button>\
<span style="float:right"> \
<button batch="true" style="float: right;display: none;margin-left:10px;" onclick="delDbBatch();" title="删除选中项" class="btn btn-default btn-sm">删除选中</button>\
</span>\
@@ -1311,7 +1443,7 @@ function addMasterRepSlaveUser(){
yes:function(index){
var data = $("#add_master").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
if(!dataObj['address']){
dataObj['address'] = dataObj['dataAccess'];
}
@@ -1356,7 +1488,7 @@ function updateMasterRepSlaveUser(username){
$('#submit_update_master').click(function(){
var data = $("#update_master").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
myPost('update_master_rep_slave_user', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
@@ -1467,7 +1599,7 @@ function setDbMasterAccess(username){
yes:function(index){
var data = $("#set_db_access").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
if(!dataObj['access']){
dataObj['access'] = dataObj['dataAccess'];
if ( dataObj['dataAccess'] == 'ip'){
@@ -1940,9 +2072,14 @@ function masterOrSlaveConf(version=''){
function getMasterStatus(){
myPost('get_master_status', '', function(data){
var rdata = $.parseJSON(data.data);
myPost('get_master_status', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log('mode:',rdata.data);
if ( typeof(rdata.status) != 'undefined' && !rdata.status && rdata.data == 'pwd'){
layer.msg(rdata.msg, {icon:2});
return;
}
var rdata = rdata.data;
var limitCon = '\
<p class="conf_p">\
+13 -10
View File
@@ -5,6 +5,8 @@
import sys
import os
import re
import time
if sys.platform != 'darwin':
os.chdir('/www/server/mdserver-web')
@@ -19,13 +21,13 @@ sys.path.append(chdir + '/class/core')
import mw
import db
import time
class backupTools:
def backupDatabase(self, name, count):
db_path = mw.getServerDir() + '/mariadb'
db_sock = mw.getServerDir() + '/mariadb/'
db_name = 'mysql'
name = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('name')
@@ -45,26 +47,27 @@ class backupTools:
filename = backup_path + "/db_" + name + "_" + \
time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz"
import re
mysql_root = mw.M('config').dbPos(db_path, db_name).where(
"id=?", (1,)).getField('mysql_root')
mycnf = mw.readFile(db_path + '/etc/my.cnf')
my_conf_path = db_path + '/etc/my.cnf'
content = mw.readFile(my_conf_path)
rep = "\[mysqldump\]\nuser=root"
sea = "[mysqldump]\n"
subStr = sea + "user=root\npassword=" + mysql_root + "\n"
mycnf = mycnf.replace(sea, subStr)
if len(mycnf) > 100:
mw.writeFile(db_path + '/etc/my.cnf', mycnf)
content = content.replace(sea, subStr)
if len(content) > 100:
mw.writeFile(my_conf_path, content)
# mw.execShell(db_path + "/bin/mysqldump --opt --default-character-set=utf8 " +
# mw.execShell(db_path + "/bin/mysqldump --defaults-file=" + my_conf_path + " --opt --default-character-set=utf8 " +
# name + " | gzip > " + filename)
# mw.execShell(db_path + "/bin/mysqldump --skip-lock-tables --default-character-set=utf8 " +
# mw.execShell(db_path + "/bin/mysqldump --defaults-file=" + my_conf_path + " --skip-lock-tables --default-character-set=utf8 " +
# name + " | gzip > " + filename)
mw.execShell(db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " +
name + " | gzip > " + filename)
cmd = db_path + "/bin/mysqldump --defaults-file=" + my_conf_path + " --single-transaction --quick --default-character-set=utf8 " + \
name + " | gzip > " + filename
mw.execShell(cmd)
if not os.path.exists(filename):
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
+14 -11
View File
@@ -2,8 +2,7 @@
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
# https://mariadb.org/download/?t=mariadb
curPath=`pwd`
rootPath=$(dirname "$curPath")
@@ -22,8 +21,8 @@ Install_app()
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 `"
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
@@ -52,20 +51,22 @@ Install_app()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# https://mirrors.aliyun.com/mariadb/mariadb-10.8.3/source/mariadb-10.8.3.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
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
# 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
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.6.8/source/mariadb-10.6.8.tar.gz
if [ "$?" != "0" ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
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
@@ -106,12 +107,14 @@ Install_app()
echo '10.6' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
# rm -rf ${mariadbDir}/mariadb-${MY_VER}
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
+15 -10
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.7.5
MY_VER=10.7.4
Install_app()
{
@@ -22,8 +22,8 @@ Install_app()
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 `"
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
@@ -52,17 +52,20 @@ Install_app()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
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
# 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
if [ "$?" != "0" ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# https://downloads.mariadb.org/interstitial/mariadb-10.7.4/source/mariadb-10.7.4.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
@@ -91,12 +94,14 @@ Install_app()
echo '10.7' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
# rm -rf ${mariadbDir}/mariadb-${MY_VER}
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
+14 -10
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.8.4
MY_VER=10.8.5
Install_app()
{
@@ -22,8 +22,8 @@ Install_app()
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 `"
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
@@ -52,17 +52,19 @@ Install_app()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
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
# 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
if [ "$?" != "0" ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
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
@@ -92,12 +94,14 @@ Install_app()
echo '10.8' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
# rm -rf ${mariadbDir}/mariadb-${MY_VER}
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.9.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.9' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
-242
View File
@@ -1,242 +0,0 @@
# 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 'memcached'
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 getConf():
path = getServerDir() + "/init.d/memcached"
return path
def getConfTpl():
path = getPluginDir() + "/init.d/memcached.tpl"
return path
def getMemPort():
path = getConf()
content = mw.readFile(path)
rep = 'PORT\s*=\s*(\d*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
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 status():
data = mw.execShell(
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
file_tpl = getConfTpl()
service_path = mw.getServerDir()
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/memcached'
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
return file_bin
def memOp(method):
file = initDreplace()
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
def start():
return memOp('start')
def stop():
return memOp('stop')
def restart():
return memOp('restart')
def reload():
return memOp('reload')
def runInfo():
# 获取memcached状态
import telnetlib
import re
port = getMemPort()
try:
tn = telnetlib.Telnet('127.0.0.1', int(port))
tn.write(b"stats\n")
tn.write(b"quit\n")
data = tn.read_all()
if type(data) == bytes:
data = data.decode('utf-8')
data = data.replace('STAT', '').replace('END', '').split("\n")
result = {}
res = ['cmd_get', 'get_hits', 'get_misses', 'limit_maxbytes', 'curr_items', 'bytes',
'evictions', 'limit_maxbytes', 'bytes_written', 'bytes_read', 'curr_connections']
for d in data:
if len(d) < 3:
continue
t = d.split()
if not t[0] in res:
continue
result[t[0]] = int(t[1])
result['hit'] = 1
if result['get_hits'] > 0 and result['cmd_get'] > 0:
result['hit'] = float(result['get_hits']) / \
float(result['cmd_get']) * 100
conf = mw.readFile(getConf())
result['bind'] = re.search('IP=(.+)', conf).groups()[0]
result['port'] = int(re.search('PORT=(\d+)', conf).groups()[0])
result['maxconn'] = int(re.search('MAXCONN=(\d+)', conf).groups()[0])
result['cachesize'] = int(
re.search('CACHESIZE=(\d+)', conf).groups()[0])
return mw.getJson(result)
except Exception as e:
return mw.getJson({})
def saveConf():
# 设置memcached缓存大小
import re
confFile = getConf()
# print confFile
try:
args = getArgs()
content = mw.readFile(confFile)
content = re.sub('IP=.+', 'IP=' + args['ip'], content)
content = re.sub('PORT=\d+', 'PORT=' + args['port'], content)
content = re.sub('MAXCONN=\d+', 'MAXCONN=' + args['maxconn'], content)
content = re.sub('CACHESIZE=\d+', 'CACHESIZE=' +
args['cachesize'], content)
mw.writeFile(confFile, content)
restart()
return 'save ok'
except Exception as e:
pass
return 'fail'
def initdStatus():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
return 'fail'
def initdInstall():
import shutil
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
mem_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(mem_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('chkconfig --add ' + getPluginName())
return 'ok'
def initdUinstall():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('chkconfig --del ' + getPluginName())
initd_bin = getInitDFile()
os.remove(initd_bin)
return 'ok'
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 == 'conf_tpl':
print(getConfTpl())
elif func == 'save_conf':
print(saveConf())
else:
print('fail')
View File
+4
View File
@@ -0,0 +1,4 @@
[mysqld]
# SHOW GLOBAL VARIABLES LIKE '%gtid%'
gtid_mode=ON
enforce_gtid_consistency=ON
+101
View File
@@ -0,0 +1,101 @@
[client]
user = root
#password = your_password
port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
default-character-set = UTF8MB4
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
user = mysql
port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
default_storage_engine = InnoDB
language={$SERVER_APP_PATH}/bin/usr/share/mysql/english
key_buffer_size = 8M
table_open_cache = 32
sort_buffer_size = 256K
net_buffer_length = 4K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=0
character-set-server = UTF8MB4
query_cache_type = 1
query_cache_size = 8M
max_connections = 500
max_connect_errors = 100
open_files_limit = 2560
max_allowed_packet = 128M
#skip-external-locking
#skip-grant-tables
#loose-skip-innodb
#skip-networking
#skip-name-resolve
log-bin=mysql-bin
binlog_format=mixed
server-id = 1
slow_query_log=1
slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log
long_query_time=3
expire_logs_days=30
#log_queries_not_using_indexes=on
relay-log=mdserver
relay-log-index=mdserver
#master
#binlog-do-db
binlog-ignore-db = test
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
#slave
log-slave-updates
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 120
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 1
innodb_write_io_threads = 1
innodb_file_per_table=1
secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
+100
View File
@@ -0,0 +1,100 @@
[client]
user = root
#password = your_password
port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
default-character-set = UTF8MB4
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
authentication_policy=mysql_native_password
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
user = mysql
port = 33206
mysqlx_port = 33260
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
default_storage_engine = InnoDB
key_buffer_size = 8M
table_open_cache = 32
sort_buffer_size = 256K
net_buffer_length = 4K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=1
tmp_table_size = 8M
character-set-server = UTF8MB4
max_connections = 500
max_connect_errors = 100
open_files_limit = 2560
max_allowed_packet = 128M
#skip-external-locking
#skip-grant-tables
#loose-skip-innodb
#skip-networking
#skip-name-resolve
log-bin=mysql-bin
binlog_format=mixed
server-id = 1
slow_query_log=1
slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log
long_query_time=3
#log_queries_not_using_indexes=on
relay-log=mdserver
relay-log-index=mdserver
#master
#binlog-do-db
binlog-ignore-db = test
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
#slave
log_replica_updates
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_redo_log_capacity=10485760
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 120
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 1
innodb_write_io_threads = 1
innodb_file_per_table=1
binlog_expire_logs_seconds=2592000
secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
+43
View File
@@ -0,0 +1,43 @@
CREATE TABLE IF NOT EXISTS `config` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`mysql_root` TEXT
);
INSERT INTO `config` (`id`, `mysql_root`) VALUES (1, 'admin');
CREATE TABLE IF NOT EXISTS `databases` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`pid` INTEGER,
`name` TEXT,
`username` TEXT,
`password` TEXT,
`accept` TEXT,
`rw` TEXT DEFAULT 'rw',
`ps` TEXT,
`addtime` TEXT
);
-- ALTER TABLE `databases` ADD COLUMN `rw` TEXT DEFAULT 'rw';
CREATE TABLE IF NOT EXISTS `master_replication_user` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` TEXT,
`password` TEXT,
`accept` TEXT,
`ps` TEXT,
`addtime` TEXT
);
-- 从库配置主库的[ssh private key]
-- drop table `slave_id_rsa`;
CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`ip` TEXT,
`port` TEXT,
`user` TEXT,
`db_user` TEXT,
`id_rsa` TEXT,
`ps` TEXT,
`addtime` TEXT
);
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+57
View File
@@ -0,0 +1,57 @@
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<script type="text/javascript">console.log($('.plugin_version').attr('version'));</script>
<p class="bgw" onclick="pluginService('mysql-apt', $('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('mysql-apt', $('.plugin_version').attr('version'));">自启动</p>
<p onclick="pluginConfig('mysql-apt', $('.plugin_version').attr('version'));">配置文件</p>
<p onclick="myDbPos();">存储位置</p>
<p onclick="myPort();">端口</p>
<p onclick="runInfo();">当前状态</p>
<p onclick="myPerfOpt();">性能优化</p>
<p onclick="myLogs();">日志</p>
<p onclick="pluginLogs('mysql-apt',$('.plugin_version').attr('version'),'show_log');">慢日志</p>
<p onclick="dbList()">管理列表</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<style type="text/css">
.db_list{
padding: 0px 0 10px 0;
font-size: 13px;
line-height: 35px;
height: 45px;
}
.db_list a{
margin-right: 15px;
color: #555;
font-weight: 600;
}
.db_list span:nth-child(1){
display: block;
float: left;
padding-left: 15px;
background: #ececec;
border-radius: 3px;
}
#db_tools button {
margin-right: 10px;
}
#db_tools button:last-child{
margin-right: 0;
}
</style>
<script type="text/javascript">
resetPluginWinWidth(800);
$.getScript( "/plugins/file?name=mysql-apt&f=js/mysql-apt.js", function(){
pluginService('mysql-apt',$('.plugin_version').attr('version'));
});
</script>
+2522
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
{
"title":"MySQL[APT]",
"tip":"soft",
"name":"mysql-apt",
"type":"运行环境",
"ps":"[<b style='color:red;'>潜龙勿用</b>]一种关系数据库管理系统[debian,ubuntu](极速安装)",
"todo_versions":["5.7","8.0"],
"versions":["5.7","8.0"],
"shell":"install.sh",
"install_pre_inspection":true,
"checks":"server/mysql-apt",
"path":"server/mysql-apt",
"author":"mysql",
"home":"https://dev.mysql.com/downloads/mysql",
"date":"2022-06-29",
"pid": "6"
}
@@ -0,0 +1,44 @@
# Copyright (c) 2015, 2022, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# MySQL systemd service file
[Unit]
Description=MySQL Community Server
After=network.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=forking
PermissionsStartOnly=true
#ExecStartPre=/usr/share/mysql/mysql-systemd-start pre
ExecStart={$SERVER_PATH}/mysql-apt/bin/usr/sbin/mysqld --defaults-file={$SERVER_PATH}/mysql-apt/etc/my.cnf --daemonize
TimeoutSec=600
LimitNOFILE = 5000
Restart=on-failure
RestartPreventExitStatus=1
RuntimeDirectory=mysqld
RuntimeDirectoryMode=755
@@ -0,0 +1,50 @@
# Copyright (c) 2015, 2022, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# MySQL systemd service file
[Unit]
Description=MySQL Community Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=notify
#ExecStartPre=+/usr/share/mysql-8.0/mysql-systemd-start pre
ExecStart={$SERVER_PATH}/mysql-apt/bin/usr/sbin/mysqld --defaults-file={$SERVER_PATH}/mysql-apt/etc/my.cnf
TimeoutSec=0
LimitNOFILE = 10000
Restart=on-failure
RestartPreventExitStatus=1
# Always restart when mysqld exits with exit code of 16. This special exit code
# is used by mysqld for RESTART SQL.
RestartForceExitStatus=16
# Set enviroment variable MYSQLD_PARENT_PID. This is required for restart.
Environment=MYSQLD_PARENT_PID=1
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
# https://downloads.mysql.com/archives/community/
# cd /www/server/mdserver-web/plugins/mysql-apt && bash install.sh install 8.0
# cd /www/server/mdserver-web/plugins/mysql-apt && bash install.sh uninstall 8.0
# cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/mysql-apt/index.py start 8.0
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
type=$2
if [ "${2}" == "" ];then
echo '缺少安装脚本...' > $install_tmp
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
echo '缺少安装脚本2...' > $install_tmp
exit 0
fi
if [ "${action}" == "uninstall" ];then
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py stop ${type}
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py initd_uninstall ${type}
cd $curPath
if [ -f /usr/lib/systemd/system/mysql-apt.service ] || [ -f /lib/systemd/system/mysql-apt.service ];then
systemctl stop mysql-apt
systemctl disable mysql-apt
rm -rf /usr/lib/systemd/system/mysql-apt.service
rm -rf /lib/systemd/system/mysql-apt.service
systemctl daemon-reload
fi
fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ];then
# #初始化
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py start ${type}
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py initd_install ${type}
fi
+2207
View File
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
# coding: utf-8
#-----------------------------
# 网站备份工具
#-----------------------------
import sys
import os
if sys.platform != 'darwin':
os.chdir('/www/server/mdserver-web')
chdir = os.getcwd()
sys.path.append(chdir + '/class/core')
# reload(sys)
# sys.setdefaultencoding('utf-8')
import mw
import db
import time
import re
'''
DEBUG:
python3 /www/server/mdserver-web/plugins/mysql-apt/scripts/backup.py database admin 3
'''
class backupTools:
def backupDatabase(self, name, count):
db_path = mw.getServerDir() + '/mysql-apt'
db_name = 'mysql'
find_name = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('name')
startTime = time.time()
if not find_name:
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
log = "数据库[" + name + "]不存在!"
print("★[" + endDate + "] " + log)
print(
"----------------------------------------------------------------------------")
return
backup_path = mw.getRootDir() + '/backup/database'
if not os.path.exists(backup_path):
mw.execShell("mkdir -p " + backup_path)
filename = backup_path + "/db_" + name + "_" + \
time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz"
mysql_root = mw.M('config').dbPos(db_path, db_name).where(
"id=?", (1,)).getField('mysql_root')
my_conf_path = db_path + '/etc/my.cnf'
mycnf = mw.readFile(my_conf_path)
rep = "\[mysqldump\]\nuser=root"
sea = "[mysqldump]\n"
subStr = sea + "user=root\npassword=" + mysql_root + "\n"
mycnf = mycnf.replace(sea, subStr)
if len(mycnf) > 100:
mw.writeFile(db_path + '/etc/my.cnf', mycnf)
cmd = db_path + "/bin/usr/bin/mysqldump --defaults-file=" + my_conf_path + " --single-transaction --quick --default-character-set=utf8 " + \
name + " | gzip > " + filename
mw.execShell(cmd)
if not os.path.exists(filename):
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
log = "数据库[" + name + "]备份失败!"
print("★[" + endDate + "] " + log)
print(
"----------------------------------------------------------------------------")
return
mycnf = mw.readFile(db_path + '/etc/my.cnf')
mycnf = mycnf.replace(subStr, sea)
if len(mycnf) > 100:
mw.writeFile(db_path + '/etc/my.cnf', mycnf)
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
outTime = time.time() - startTime
pid = mw.M('databases').dbPos(db_path, db_name).where(
'name=?', (name,)).getField('id')
mw.M('backup').add('type,name,pid,filename,addtime,size', (1, os.path.basename(
filename), pid, filename, endDate, os.path.getsize(filename)))
log = "数据库[" + name + "]备份成功,用时[" + str(round(outTime, 2)) + "]秒"
mw.writeLog('计划任务', log)
print("★[" + endDate + "] " + log)
print("|---保留最新的[" + count + "]份备份")
print("|---文件名:" + filename)
# 清理多余备份
backups = mw.M('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
num = len(backups) - int(count)
if num > 0:
for backup in backups:
mw.execShell("rm -f " + backup['filename'])
mw.M('backup').where('id=?', (backup['id'],)).delete()
num -= 1
print("|---已清理过期备份文件:" + backup['filename'])
if num < 1:
break
def backupDatabaseAll(self, save):
db_path = mw.getServerDir() + '/mysql-apt'
db_name = 'mysql'
databases = mw.M('databases').dbPos(
db_path, db_name).field('name').select()
for database in databases:
self.backupDatabase(database['name'], save)
if __name__ == "__main__":
backup = backupTools()
type = sys.argv[1]
if type == 'database':
if sys.argv[2] == 'ALL':
backup.backupDatabaseAll(sys.argv[3])
else:
backup.backupDatabase(sys.argv[2], sys.argv[3])
+123
View File
@@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
export DEBIAN_FRONTEND=noninteractive
# https://downloads.mysql.com/archives/community/
# debug
# cd /www/server/mdserver-web/plugins/mysql-apt && bash install.sh install 8.0
# /www/server/mysql-apt/bin/usr/sbin/mysqld --defaults-file=/www/server/mysql-apt/etc/my.cnf --daemonize
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
myDir=${serverPath}/source/mysql-apt
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
MYSQL_VER=5.7.39
if [ "$OSNAME" == "debian" ];then
# mysql5.7现在仅有10的编译版
VERSION_ID="10"
fi
if [ "$OSNAME" == "ubuntu" ];then
# mysql5.7现在仅有18.04的编译版
VERSION_ID="18.04"
fi
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_amd64
APT_INSTALL()
{
########
mkdir -p $myDir
mkdir -p $serverPath/mysql-apt/bin
wget -O ${myDir}/mysql-server_${SUFFIX_NAME}.deb-bundle.tar https://cdn.mysql.com/archives/mysql-5.7/mysql-server_${SUFFIX_NAME}.deb-bundle.tar
chmod +x ${myDir}/mysql-server_${SUFFIX_NAME}.deb-bundle.tar
cd ${myDir} && tar vxf ${myDir}/mysql-server_${SUFFIX_NAME}.deb-bundle.tar
apt update -y
apt install -y libnuma1 libaio1 libmecab2
# 安装
dpkg -X mysql-common_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-client-plugins_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-client-core_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-client_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-client_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-server-core_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-server_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-server_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
# rm -rf $myDir
#######
}
APT_UNINSTALL()
{
###
rm -rf $myDir
# apt remove -y mysql-server
###
}
Install_mysql()
{
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u mysql`"
echo "mysql shell is `grep "^mysql:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
isApt=`which apt`
if [ "$isApt" != "" ];then
APT_INSTALL
fi
if [ "$?" == "0" ];then
mkdir -p $serverPath/mysql-apt
echo '5.7' > $serverPath/mysql-apt/version.pl
echo '安装完成' > $install_tmp
else
echo "暂时不支持该系统" > $install_tmp
fi
}
Uninstall_mysql()
{
isApt=`which apt`
if [ "$isApt" != "" ];then
APT_UNINSTALL
fi
rm -rf $serverPath/mysql-apt
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_mysql
else
Uninstall_mysql
fi
+116
View File
@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
export DEBIAN_FRONTEND=noninteractive
# https://downloads.mysql.com/archives/community/
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
myDir=${serverPath}/source/mysql-apt
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
# cd /www/server/mdserver-web/plugins/mysql-apt && bash install.sh install 8.0
MYSQL_VER=8.0.30
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_amd64
# /lib/systemd/system/mysql.service
# /etc/mysql/my.cnf
APT_INSTALL()
{
########
mkdir -p $myDir
mkdir -p $serverPath/mysql-apt/bin
wget -O ${myDir}/mysql-server_${SUFFIX_NAME}.deb-bundle.tar https://cdn.mysql.com/archives/mysql-8.0/mysql-server_${SUFFIX_NAME}.deb-bundle.tar
chmod +x ${myDir}/mysql-server_${SUFFIX_NAME}.deb-bundle.tar
cd ${myDir} && tar vxf ${myDir}/mysql-server_${SUFFIX_NAME}.deb-bundle.tar
apt update -y
apt install -y libnuma1 libaio1 libmecab2
# 安装
dpkg -X mysql-common_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-client-plugins_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-client-core_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-client_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-client_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-server-core_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-community-server_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
dpkg -X mysql-server_${SUFFIX_NAME}.deb $serverPath/mysql-apt/bin
# rm -rf $myDir
#######
}
APT_UNINSTALL()
{
###
rm -rf $myDir
# apt remove -y mysql-server
###
}
Install_mysql()
{
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u mysql`"
echo "mysql shell is `grep "^mysql:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
isApt=`which apt`
if [ "$isApt" != "" ];then
APT_INSTALL
fi
if [ "$?" == "0" ];then
mkdir -p $serverPath/mysql-apt
echo '8.0' > $serverPath/mysql-apt/version.pl
echo '安装完成' > $install_tmp
else
echo "暂时不支持该系统" > $install_tmp
fi
}
Uninstall_mysql()
{
isApt=`which apt`
if [ "$isApt" != "" ];then
APT_UNINSTALL
fi
rm -rf $serverPath/mysql-apt
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_mysql
else
Uninstall_mysql
fi
View File
+4
View File
@@ -0,0 +1,4 @@
[mysqld]
# SHOW GLOBAL VARIABLES LIKE '%gtid%'
gtid_mode=ON
enforce_gtid_consistency=ON
+102
View File
@@ -0,0 +1,102 @@
[client]
user = root
#password = your_password
port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
default-character-set = UTF8MB4
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
user = mysql
port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
default_storage_engine = InnoDB
language={$SERVER_APP_PATH}/bin/usr/share/mysql/english
key_buffer_size = 8M
table_open_cache = 32
sort_buffer_size = 256K
net_buffer_length = 4K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=0
tmp_table_size = 8M
character-set-server = UTF8MB4
query_cache_type = 1
query_cache_size = 8M
max_connections = 500
max_connect_errors = 100
open_files_limit = 2560
max_allowed_packet = 128M
#skip-external-locking
#skip-grant-tables
#loose-skip-innodb
#skip-networking
#skip-name-resolve
log-bin=mysql-bin
binlog_format=mixed
server-id = 1
slow_query_log=1
slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log
long_query_time=3
expire_logs_days=30
#log_queries_not_using_indexes=on
relay-log=mdserver
relay-log-index=mdserver
#master
#binlog-do-db
binlog-ignore-db = test
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
#slave
log-slave-updates
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 120
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 1
innodb_write_io_threads = 1
innodb_file_per_table=1
secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
+100
View File
@@ -0,0 +1,100 @@
[client]
user = root
#password = your_password
port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
default-character-set = UTF8MB4
[mysqld]
!include {$SERVER_APP_PATH}/etc/mode/classic.cnf
authentication_policy=mysql_native_password
pid-file = {$SERVER_APP_PATH}/data/mysql.pid
user = mysql
port = 33206
mysqlx_port = 33260
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
default_storage_engine = InnoDB
key_buffer_size = 8M
table_open_cache = 32
sort_buffer_size = 256K
net_buffer_length = 4K
read_buffer_size = 128K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=1
tmp_table_size = 8M
character-set-server = UTF8MB4
max_connections = 500
max_connect_errors = 100
open_files_limit = 2560
max_allowed_packet = 128M
#skip-external-locking
#skip-grant-tables
#loose-skip-innodb
#skip-networking
#skip-name-resolve
log-bin=mysql-bin
binlog_format=mixed
server-id = 1
slow_query_log=1
slow-query-log-file={$SERVER_APP_PATH}/data/mysql-slow.log
long_query_time=3
#log_queries_not_using_indexes=on
relay-log=mdserver
relay-log-index=mdserver
#master
#binlog-do-db
binlog-ignore-db = test
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
#slave
log_replica_updates
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_redo_log_capacity=10485760
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 120
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 1
innodb_write_io_threads = 1
innodb_file_per_table=1
binlog_expire_logs_seconds=2592000
secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
+43
View File
@@ -0,0 +1,43 @@
CREATE TABLE IF NOT EXISTS `config` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`mysql_root` TEXT
);
INSERT INTO `config` (`id`, `mysql_root`) VALUES (1, 'admin');
CREATE TABLE IF NOT EXISTS `databases` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`pid` INTEGER,
`name` TEXT,
`username` TEXT,
`password` TEXT,
`accept` TEXT,
`rw` TEXT DEFAULT 'rw',
`ps` TEXT,
`addtime` TEXT
);
-- ALTER TABLE `databases` ADD COLUMN `rw` TEXT DEFAULT 'rw';
CREATE TABLE IF NOT EXISTS `master_replication_user` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` TEXT,
`password` TEXT,
`accept` TEXT,
`ps` TEXT,
`addtime` TEXT
);
-- 从库配置主库的[ssh private key]
-- drop table `slave_id_rsa`;
CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`ip` TEXT,
`port` TEXT,
`user` TEXT,
`db_user` TEXT,
`id_rsa` TEXT,
`ps` TEXT,
`addtime` TEXT
);
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+57
View File
@@ -0,0 +1,57 @@
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<!-- <script type="text/javascript">console.log($('.plugin_version').attr('version'));</script> -->
<p class="bgw" onclick="pluginService('mysql-yum', $('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('mysql-yum', $('.plugin_version').attr('version'));">自启动</p>
<p onclick="pluginConfig('mysql-yum', $('.plugin_version').attr('version'));">配置文件</p>
<p onclick="myDbPos();">存储位置</p>
<p onclick="myPort();">端口</p>
<p onclick="runInfo();">当前状态</p>
<p onclick="myPerfOpt();">性能优化</p>
<p onclick="myLogs();">日志</p>
<p onclick="pluginLogs('mysql-yum',$('.plugin_version').attr('version'),'show_log');">慢日志</p>
<p onclick="dbList()">管理列表</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<style type="text/css">
.db_list{
padding: 0px 0 10px 0;
font-size: 13px;
line-height: 35px;
height: 45px;
}
.db_list a{
margin-right: 15px;
color: #555;
font-weight: 600;
}
.db_list span:nth-child(1){
display: block;
float: left;
padding-left: 15px;
background: #ececec;
border-radius: 3px;
}
#db_tools button {
margin-right: 10px;
}
#db_tools button:last-child{
margin-right: 0;
}
</style>
<script type="text/javascript">
resetPluginWinWidth(800);
$.getScript( "/plugins/file?name=mysql-yum&f=js/mysql-yum.js", function(){
pluginService('mysql-yum',$('.plugin_version').attr('version'));
});
</script>
+2495
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
{
"title":"MySQL[YUM]",
"tip":"soft",
"name":"mysql-yum",
"type":"运行环境",
"ps":"[<b style='color:red;'>潜龙勿用</b>]一种关系数据库管理系统[centos](极速安装)",
"todo_versions":["5.7","8.0"],
"versions":["5.7","8.0"],
"shell":"install.sh",
"install_pre_inspection":true,
"checks":"server/mysql-yum",
"path":"server/mysql-yum",
"author":"mysql",
"home":"https://dev.mysql.com/downloads/mysql",
"date":"2022-06-29",
"pid": "6"
}
@@ -0,0 +1,63 @@
# It's not recommended to modify this file in-place, because it will be
# overwritten during package upgrades. If you want to customize, the
# best way is to use systemctl edit:
#
# $ systemctl edit mysqld.service
#
# this will create file
#
# /etc/systemd/system/mysqld.service.d/override.conf
#
# which be parsed after the file mysqld.service itself is parsed.
#
# For example, if you want to increase mysql's open-files-limit to 20000
# add following when editing with command above:
#
# [Service]
# LimitNOFILE=20000
#
# Or if you require to execute pre and post scripts in the unit file as root, set
# PermissionsStartOnly=true
#
# For more info about custom unit files, see systemd.unit(5) or
# http://fedoraproject.org/wiki/Systemd#How_do_I_customize_a_unit_file.2F_add_a_custom_unit_file.3F
#
# Don't forget to reload systemd daemon after you change unit configuration:
# root> systemctl --system daemon-reload
[Unit]
Description=MySQL 5.7 database server
After=syslog.target
After=network.target
[Service]
Type=forking
User=mysql
Group=mysql
#ExecStartPre=/usr/libexec/mysql-check-socket
#ExecStartPre=/usr/libexec/mysql-prepare-db-dir %n
# Note: we set --basedir to prevent probes that might trigger SELinux alarms,
# per bug #547485
ExecStart={$SERVER_PATH}/mysql-yum/bin/usr/sbin/mysqld --defaults-file={$SERVER_PATH}/mysql-yum/etc/my.cnf --basedir={$SERVER_PATH}/mysql-yum/bin/usr --daemonize
#ExecStartPost=/usr/libexec/mysql-check-upgrade
#ExecStopPost=/usr/libexec/mysql-wait-stop
# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=300
# Place temp files in a secure directory, not /tmp
PrivateTmp=false
Restart=on-failure
RestartPreventExitStatus=1
# Sets open_files_limit
LimitNOFILE = 10000
# Set enviroment variable MYSQLD_PARENT_PID. This is required for SQL restart command.
Environment=MYSQLD_PARENT_PID=1
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,63 @@
# It's not recommended to modify this file in-place, because it will be
# overwritten during package upgrades. If you want to customize, the
# best way is to use systemctl edit:
#
# $ systemctl edit mysqld.service
#
# this will create file
#
# /etc/systemd/system/mysqld.service.d/override.conf
#
# which be parsed after the file mysqld.service itself is parsed.
#
# For example, if you want to increase mysql's open-files-limit to 20000
# add following when editing with command above:
#
# [Service]
# LimitNOFILE=20000
#
# Or if you require to execute pre and post scripts in the unit file as root, set
# PermissionsStartOnly=true
#
# For more info about custom unit files, see systemd.unit(5) or
# http://fedoraproject.org/wiki/Systemd#How_do_I_customize_a_unit_file.2F_add_a_custom_unit_file.3F
#
# Don't forget to reload systemd daemon after you change unit configuration:
# root> systemctl --system daemon-reload
[Unit]
Description=MySQL 8.0 database server
After=syslog.target
After=network.target
[Service]
Type=notify
User=mysql
Group=mysql
#ExecStartPre=/usr/libexec/mysql-check-socket
#ExecStartPre=/usr/libexec/mysql-prepare-db-dir %n
# Note: we set --basedir to prevent probes that might trigger SELinux alarms,
# per bug #547485
ExecStart={$SERVER_PATH}/mysql-yum/bin/usr/sbin/mysqld --defaults-file={$SERVER_PATH}/mysql-yum/etc/my.cnf --basedir={$SERVER_PATH}/mysql-yum/bin/usr --user=mysql
#ExecStartPost=/usr/libexec/mysql-check-upgrade
#ExecStopPost=/usr/libexec/mysql-wait-stop
# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=300
# Place temp files in a secure directory, not /tmp
PrivateTmp=false
Restart=on-failure
RestartPreventExitStatus=1
# Sets open_files_limit
LimitNOFILE = 10000
# Set enviroment variable MYSQLD_PARENT_PID. This is required for SQL restart command.
Environment=MYSQLD_PARENT_PID=1
[Install]
WantedBy=multi-user.target
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
# cd /www/server/mdserver-web/plugins/mysql-yum && bash install.sh install 8.0
# cd /www/server/mdserver-web/plugins/mysql-yum && bash install.sh uninstall 8.0
# cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/mysql-yum/index.py start 8.0
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
type=$2
if [ "${2}" == "" ];then
echo '缺少安装脚本...' > $install_tmp
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
echo '缺少安装脚本2...' > $install_tmp
exit 0
fi
if [ "${action}" == "uninstall" ];then
cd ${rootPath} && python3 plugins/mysql-yum/index.py stop ${type}
cd ${rootPath} && python3 plugins/mysql-yum/index.py initd_uninstall ${type}
cd $curPath
if [ -f /usr/lib/systemd/system/mysql-yum.service ] || [ -f /lib/systemd/system/mysql-yum.service ];then
systemctl stop mysql-yum
systemctl disable mysql-yum
rm -rf /usr/lib/systemd/system/mysql-yum.service
rm -rf /lib/systemd/system/mysql-yum.service
systemctl daemon-reload
fi
fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ];then
# #初始化
cd ${rootPath} && python3 plugins/mysql-yum/index.py start ${type}
cd ${rootPath} && python3 plugins/mysql-yum/index.py initd_install ${type}
fi
+2207
View File
File diff suppressed because it is too large Load Diff
+124
View File
@@ -0,0 +1,124 @@
# coding: utf-8
#-----------------------------
# 网站备份工具
#-----------------------------
import sys
import os
if sys.platform != 'darwin':
os.chdir('/www/server/mdserver-web')
chdir = os.getcwd()
sys.path.append(chdir + '/class/core')
# reload(sys)
# sys.setdefaultencoding('utf-8')
import mw
import db
import time
import re
'''
DEBUG:
python3 /www/server/mdserver-web/plugins/mysql-yum/scripts/backup.py database admin 3
'''
class backupTools:
def backupDatabase(self, name, count):
db_path = mw.getServerDir() + '/mysql-yum'
db_name = 'mysql'
find_name = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('name')
startTime = time.time()
if not find_name:
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
log = "数据库[" + name + "]不存在!"
print("★[" + endDate + "] " + log)
print(
"----------------------------------------------------------------------------")
return
backup_path = mw.getRootDir() + '/backup/database'
if not os.path.exists(backup_path):
mw.execShell("mkdir -p " + backup_path)
filename = backup_path + "/db_" + name + "_" + \
time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz"
mysql_root = mw.M('config').dbPos(db_path, db_name).where(
"id=?", (1,)).getField('mysql_root')
my_cnf = db_path + '/etc/my.cnf'
mw.backFile(my_cnf)
content = mw.readFile(my_cnf)
rep = "\[mysqldump\]\nuser=root"
sea = "[mysqldump]\n"
subStr = sea + "user=root\npassword=" + mysql_root + "\n"
content = content.replace(sea, subStr)
if len(content) > 100:
mw.writeFile(my_cnf, content)
cmd = db_path + "/bin/usr/bin/mysqldump --defaults-file=" + my_cnf + " --single-transaction --quick --default-character-set=utf8 " + \
name + " | gzip > " + filename
mw.execShell(cmd)
mw.restoreFile(my_cnf)
if not os.path.exists(filename):
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
log = "数据库[" + name + "]备份失败!"
print("★[" + endDate + "] " + log)
print(
"----------------------------------------------------------------------------")
return
endDate = time.strftime('%Y/%m/%d %X', time.localtime())
outTime = time.time() - startTime
pid = mw.M('databases').dbPos(db_path, db_name).where(
'name=?', (name,)).getField('id')
mw.M('backup').add('type,name,pid,filename,addtime,size', (1, os.path.basename(
filename), pid, filename, endDate, os.path.getsize(filename)))
log = "数据库[" + name + "]备份成功,用时[" + str(round(outTime, 2)) + "]秒"
mw.writeLog('计划任务', log)
print("★[" + endDate + "] " + log)
print("|---保留最新的[" + count + "]份备份")
print("|---文件名:" + filename)
# 清理多余备份
backups = mw.M('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
num = len(backups) - int(count)
if num > 0:
for backup in backups:
mw.execShell("rm -f " + backup['filename'])
mw.M('backup').where('id=?', (backup['id'],)).delete()
num -= 1
print("|---已清理过期备份文件:" + backup['filename'])
if num < 1:
break
def backupDatabaseAll(self, save):
db_path = mw.getServerDir() + '/mysql-yum'
db_name = 'mysql'
databases = mw.M('databases').dbPos(
db_path, db_name).field('name').select()
for database in databases:
self.backupDatabase(database['name'], save)
if __name__ == "__main__":
backup = backupTools()
stype = sys.argv[1]
if stype == 'database':
if sys.argv[2] == 'ALL':
backup.backupDatabaseAll(sys.argv[3])
else:
backup.backupDatabase(sys.argv[2], sys.argv[3])
+121
View File
@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# https://downloads.mysql.com/archives/community/
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
myDir=${serverPath}/source/mysql-yum
ARCH=`uname -m`
ARCH_NAME=''
case $(uname -m) in
i386) ARCH_NAME="386" ;;
i686) ARCH_NAME="386" ;;
x86_64) ARCH_NAME="amd64" ;;
arm) ARCH_NAME="arm64" ;;
esac
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
echo "VERSION_ID:${VERSION_ID}"
if [ "$OSNAME" == "centos" ] && [ "$VERSION_ID" -gt "7" ]; then
VERSION_ID=7
fi
OS_SIGN=1.el9
if [ "$OSNAME" == "centos" ];then
OS_SIGN=1.el${VERSION_ID}
elif [ "$OSNAME" == "fedora" ]; then
OS_SIGN=10.fc${VERSION_ID}
elif [ "$OSNAME" == "suse" ]; then
OS_SIGN=1.sl${VERSION_ID}
fi
MYSQL_VER=5.7.39
SUFFIX_NAME=${MYSQL_VER}-${OS_SIGN}.${ARCH}
YUM_INSTALL()
{
#######
mkdir -p $myDir
wget -O $myDir/mysql-${SUFFIX_NAME}.rpm-bundle.tar https://cdn.mysql.com/archives/mysql-5.7/mysql-${SUFFIX_NAME}.rpm-bundle.tar
cd ${myDir} && tar vxf mysql-${SUFFIX_NAME}.rpm-bundle.tar
mkdir -p ${serverPath}/mysql-yum/bin && cd ${serverPath}/mysql-yum/bin
rpm2cpio ${myDir}/mysql-community-client-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-common-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-devel-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-embedded-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-embedded-compat-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-embedded-devel-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-libs-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-libs-compat-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-server-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-test-${SUFFIX_NAME}.rpm | cpio -div
#######
}
YUM_UNINSTALL()
{
### YUM卸载 START ########
# yum -y remove mysql-server
rm -rf ${myDir}
### YUM卸载 END ########
}
Install_mysql()
{
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u mysql`"
echo "mysql shell is `grep "^mysql:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
isYum=`which yum`
if [ "$isYum" != "" ];then
YUM_INSTALL
fi
mkdir -p $serverPath/mysql-yum
echo '5.7' > $serverPath/mysql-yum/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_mysql()
{
isYum=`which yum`
if [ "$isYum" != "" ];then
YUM_UNINSTALL
fi
rm -rf $serverPath/mysql-yum
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_mysql
else
Uninstall_mysql
fi
+120
View File
@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# https://downloads.mysql.com/archives/community/
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
myDir=${serverPath}/source/mysql-yum
ARCH=`uname -m`
ARCH_NAME=''
case $(uname -m) in
i386) ARCH_NAME="386" ;;
i686) ARCH_NAME="386" ;;
x86_64) ARCH_NAME="amd64" ;;
arm) ARCH_NAME="arm64" ;;
esac
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
echo "VERSION_ID:${VERSION_ID}"
OS_SIGN=1.el9
if [ "$OSNAME" == "centos" ];then
OS_SIGN=1.el${VERSION_ID}
elif [ "$OSNAME" == "fedora" ]; then
OS_SIGN=10.fc${VERSION_ID}
elif [ "$OSNAME" == "suse" ]; then
OS_SIGN=1.sl${VERSION_ID}
fi
MYSQL_VER=8.0.30
SUFFIX_NAME=${MYSQL_VER}-${OS_SIGN}.${ARCH}
YUM_INSTALL()
{
#######
mkdir -p $myDir
wget -O $myDir/mysql-${SUFFIX_NAME}.rpm-bundle.tar https://cdn.mysql.com/archives/mysql-8.0/mysql-${SUFFIX_NAME}.rpm-bundle.tar
cd ${myDir} && tar vxf mysql-${SUFFIX_NAME}.rpm-bundle.tar
mkdir -p ${serverPath}/mysql-yum/bin && cd ${serverPath}/mysql-yum/bin
rpm2cpio ${myDir}/mysql-community-client-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-client-${SUFFIX_NAME}.x86_64.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-common-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-debuginfo-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-devel-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-embedded-compat-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-icu-data-files-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-libs-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-libs-compat-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-server-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-server-debug-${SUFFIX_NAME}.rpm | cpio -div
rpm2cpio ${myDir}/mysql-community-test-${SUFFIX_NAME}.rpm | cpio -div
#######
}
YUM_UNINSTALL()
{
### YUM卸载 START ########
# yum -y remove mysql-server
rm -rf ${myDir}
### YUM卸载 END ########
}
Install_mysql()
{
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u mysql`"
echo "mysql shell is `grep "^mysql:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
isYum=`which yum`
if [ "$isYum" != "" ];then
YUM_INSTALL
fi
mkdir -p $serverPath/mysql-yum
echo '8.0' > $serverPath/mysql-yum/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_mysql()
{
isYum=`which yum`
if [ "$isYum" != "" ];then
YUM_UNINSTALL
fi
rm -rf $serverPath/mysql-yum
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_mysql
else
Uninstall_mysql
fi
+4 -1
View File
@@ -29,9 +29,12 @@ read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=0
query_cache_size = 4M
tmp_table_size = 8M
query_cache_type = 1
query_cache_size = 4M
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535
+3 -1
View File
@@ -32,9 +32,11 @@ read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 4M
thread_cache_size = 4
lower_case_table_names=0
query_cache_size = 4M
tmp_table_size = 8M
query_cache_type = 1
query_cache_size = 4M
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535
+4
View File
@@ -22,6 +22,7 @@ server-id = {$SERVER_ID}
default_storage_engine = InnoDB
key_buffer_size = 8M
table_open_cache = 32
sort_buffer_size = 256K
@@ -34,6 +35,9 @@ lower_case_table_names=0
tmp_table_size = 8M
character-set-server = UTF8MB4
query_cache_type = 1
query_cache_size = 4M
max_connections = 500
max_connect_errors = 100
open_files_limit = 2560
+2 -1
View File
@@ -80,7 +80,8 @@ innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_log_file_size = 5M
#innodb_log_file_size = 5M
innodb_redo_log_capacity=10485760
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 120
+247 -100
View File
@@ -92,6 +92,14 @@ def getSocketFile():
return tmp.groups()[0].strip()
def getErrorLogsFile():
file = getConf()
content = mw.readFile(file)
rep = 'log-error\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getInitdTpl(version=''):
path = getPluginDir() + '/init.d/mysql' + version + '.tpl'
if not os.path.exists(path):
@@ -319,15 +327,7 @@ def setSkipGrantTables(v):
def getErrorLog():
args = getArgs()
path = getDataDir()
filename = ''
for n in os.listdir(path):
if len(n) < 5:
continue
if n == 'error.log':
filename = path + '/' + n
break
# print filename
filename = getErrorLogsFile()
if not os.path.exists(filename):
return mw.returnJson(False, '指定文件不存在!')
if 'close' in args:
@@ -406,22 +406,21 @@ def initMysqlPwd():
serverdir = getServerDir()
myconf = serverdir + "/etc/my.cnf"
pwd = mw.getRandomString(16)
# cmd_pass = serverdir + '/bin/mysqladmin -uroot password ' + pwd
# cmd_pass = "insert into mysql.user(Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Show_db_priv,Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Repl_slave_priv,Repl_client_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Create_user_priv,Event_priv,Trigger_priv,Create_tablespace_priv,User,Password,host)values('Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','root',password('" + pwd + "'),'127.0.0.1')"
# cmd_pass = cmd_pass + \
# "insert into mysql.user(Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Reload_priv,Shutdown_priv,Process_priv,File_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Show_db_priv,Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Repl_slave_priv,Repl_client_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Create_user_priv,Event_priv,Trigger_priv,Create_tablespace_priv,User,Password,host)values('Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','root',password('" + pwd + "'),'localhost')"
# cmd_pass = cmd_pass + \
# "UPDATE mysql.user SET password=PASSWORD('" + \
# pwd + "') WHERE user='root'"
cmd_pass = serverdir + '/bin/mysql -uroot -e'
cmd_pass = cmd_pass + "\"UPDATE mysql.user SET password=PASSWORD('" + \
cmd_pass = serverdir + '/bin/mysql --defaults-file=' + myconf + ' -uroot -e'
cmd_pass = cmd_pass + \
'"UPDATE mysql.user SET password=PASSWORD(\'' + \
pwd + "') WHERE user='root';"
cmd_pass = cmd_pass + "flush privileges;\""
cmd_pass = cmd_pass + 'flush privileges;"'
data = mw.execShell(cmd_pass)
# print(cmd_pass)
# print(data)
# 删除空账户
drop_empty_user = serverdir + '/bin/mysql -uroot -p' + \
pwd + ' -e "use mysql;delete from user where USER=\'\'"'
mw.execShell(drop_empty_user)
# 删除测试数据库
drop_test_db = serverdir + '/bin/mysql -uroot -p' + \
pwd + ' -e "drop database test";'
@@ -429,14 +428,14 @@ def initMysqlPwd():
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
if hostname != 'localhost':
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
drop_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'\'@\'' + hostname + '\'";'
mw.execShell(drop_hostname)
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
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
@@ -681,14 +680,18 @@ def setMyPort():
return mw.returnJson(True, '编辑成功!')
def runInfo():
def runInfo(version):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动', [])
db = pMysqlDb()
data = db.query('show global status')
gets = ['Max_used_connections', 'Com_commit', 'Com_rollback', 'Questions', 'Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests', 'Key_reads', 'Key_read_requests', 'Key_writes',
isError = isSqlError(data)
if isError != None:
return isError
gets = ['Max_used_connections', 'Com_commit', 'Com_select', 'Com_rollback', 'Questions', 'Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests', 'Key_reads', 'Key_read_requests', 'Key_writes',
'Key_write_requests', 'Qcache_hits', 'Qcache_inserts', 'Bytes_received', 'Bytes_sent', 'Aborted_clients', 'Aborted_connects',
'Created_tmp_disk_tables', 'Created_tmp_tables', 'Innodb_buffer_pool_pages_dirty', 'Opened_files', 'Open_tables', 'Opened_tables', 'Select_full_join',
'Select_range_check', 'Sort_merge_passes', 'Table_locks_waited', 'Threads_cached', 'Threads_connected', 'Threads_created', 'Threads_running', 'Connections', 'Uptime']
@@ -713,7 +716,7 @@ def runInfo():
return mw.getJson(result)
def myDbStatus():
def myDbStatus(version):
result = {}
db = pMysqlDb()
data = db.query('show variables')
@@ -723,6 +726,10 @@ def myDbStatus():
gets = ['table_open_cache', 'thread_cache_size', 'key_buffer_size', 'tmp_table_size', 'max_heap_table_size', 'innodb_buffer_pool_size',
'innodb_additional_mem_pool_size', 'innodb_log_buffer_size', 'max_connections', 'sort_buffer_size', 'read_buffer_size', 'read_rnd_buffer_size', 'join_buffer_size', 'thread_stack', 'binlog_cache_size']
if version != "8.0":
gets.append('query_cache_size')
result['mem'] = {}
for d in data:
vname = d['Variable_name']
@@ -733,9 +740,16 @@ def myDbStatus():
return mw.getJson(result)
def setDbStatus():
def setDbStatus(version):
gets = ['key_buffer_size', 'tmp_table_size', 'max_heap_table_size', 'innodb_buffer_pool_size', 'innodb_log_buffer_size', 'max_connections',
'table_open_cache', 'thread_cache_size', 'sort_buffer_size', 'read_buffer_size', 'read_rnd_buffer_size', 'join_buffer_size', 'thread_stack', 'binlog_cache_size']
if version != "8.0":
# gets.append('query_cache_size')
gets = ['key_buffer_size', 'query_cache_size', 'tmp_table_size', 'max_heap_table_size', 'innodb_buffer_pool_size', 'innodb_log_buffer_size', 'max_connections',
'table_open_cache', 'thread_cache_size', 'sort_buffer_size', 'read_buffer_size', 'read_rnd_buffer_size', 'join_buffer_size', 'thread_stack', 'binlog_cache_size']
# print(gets)
emptys = ['max_connections', 'thread_cache_size', 'table_open_cache']
args = getArgs()
conFile = getConf()
@@ -768,7 +782,7 @@ def isSqlError(mysqlMsg):
if "2003," in mysqlMsg:
return mw.returnJson(False, "Can't connect to MySQL server on '127.0.0.1' (61)")
if "using password:" in mysqlMsg:
return mw.returnJson(False, '数据库管理密码错误!')
return mw.returnJson(False, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
@@ -822,11 +836,77 @@ def setDbBackup():
scDir = mw.getRunDir() + '/scripts/backup.py'
cmd = 'python ' + scDir + ' database ' + args['name'] + ' 3'
cmd = 'python3 ' + scDir + ' database ' + args['name'] + ' 3'
os.system(cmd)
return mw.returnJson(True, 'ok')
def importDbExternal():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
if not data[0]:
return data[1]
file = args['file']
name = args['name']
import_dir = mw.getRootDir() + '/backup/import/'
file_path = import_dir + file
if not os.path.exists(file_path):
return mw.returnJson(False, '文件突然消失?')
exts = ['sql', 'gz', 'zip']
ext = mw.getFileSuffix(file)
if ext not in exts:
return mw.returnJson(False, '导入数据库格式不对!')
tmp = file.split('/')
tmpFile = tmp[len(tmp) - 1]
tmpFile = tmpFile.replace('.sql.' + ext, '.sql')
tmpFile = tmpFile.replace('.' + ext, '.sql')
tmpFile = tmpFile.replace('tar.', '')
# print(tmpFile)
import_sql = ""
if file.find("sql.gz") > -1:
cmd = 'cd ' + import_dir + ' && gzip -dc ' + \
file + " > " + import_dir + tmpFile
info = mw.execShell(cmd)
if info[1] == "":
import_sql = import_dir + tmpFile
if file.find(".zip") > -1:
cmd = 'cd ' + import_dir + ' && unzip -o ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if file.find("tar.gz") > -1:
cmd = 'cd ' + import_dir + ' && tar -zxvf ' + file
mw.execShell(cmd)
import_sql = import_dir + tmpFile
if file.find(".sql") > -1 and file.find(".sql.gz") == -1:
import_sql = import_dir + file
if import_sql == "":
return mw.returnJson(False, '未找SQL文件')
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
os.environ["MYSQL_PWD"] = pwd
mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \
pwd + ' ' + name + ' < ' + import_sql
# print(mysql_cmd)
os.system(mysql_cmd)
if ext != 'sql':
os.remove(import_sql)
return mw.returnJson(True, 'ok')
def importDbBackup():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
@@ -855,13 +935,17 @@ def importDbBackup():
def deleteDbBackup():
args = getArgs()
data = checkArgs(args, ['filename'])
data = checkArgs(args, ['filename', 'path'])
if not data[0]:
return data[1]
path = args['path']
full_file = ""
bkDir = mw.getRootDir() + '/backup/database'
os.remove(bkDir + '/' + args['filename'])
full_file = bkDir + '/' + args['filename']
if path != "":
full_file = path + "/" + args['filename']
os.remove(full_file)
return mw.returnJson(True, 'ok')
@@ -893,6 +977,39 @@ def getDbBackupList():
return mw.returnJson(True, 'ok', rr)
def getDbBackupImportList():
bkImportDir = mw.getRootDir() + '/backup/import'
if not os.path.exists(bkImportDir):
os.mkdir(bkImportDir)
blist = os.listdir(bkImportDir)
rr = []
for x in range(0, len(blist)):
name = blist[x]
p = bkImportDir + '/' + name
data = {}
data['name'] = name
rsize = os.path.getsize(p)
data['size'] = mw.toSize(rsize)
t = os.path.getctime(p)
t = time.localtime(t)
data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', t)
rr.append(data)
data['file'] = p
rdata = {
"list": rr,
"upload_dir": bkImportDir,
}
return mw.returnJson(True, 'ok', rdata)
def getDbList():
args = getArgs()
page = 1
@@ -1194,11 +1311,11 @@ def delDb():
if not data[0]:
return data[1]
try:
id = args['id']
sid = args['id']
name = args['name']
psdb = pSqliteDb('databases')
pdb = pMysqlDb()
find = psdb.where("id=?", (id,)).field(
find = psdb.where("id=?", (sid,)).field(
'id,pid,name,username,password,accept,ps,addtime').find()
accept = find['accept']
username = find['username']
@@ -1214,7 +1331,7 @@ def delDb():
pdb.execute("flush privileges")
# 删除SQLITE
psdb.where("id=?", (id,)).delete()
psdb.where("id=?", (sid,)).delete()
return mw.returnJson(True, '删除成功!')
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
@@ -1231,6 +1348,10 @@ def getDbAccess():
users = pdb.query("select Host from mysql.user where User='" +
username + "' AND Host!='localhost'")
isError = isSqlError(users)
if isError != None:
return isError
if len(users) < 1:
return mw.returnJson(True, "127.0.0.1")
accs = []
@@ -1270,6 +1391,21 @@ def setDbAccess():
return mw.returnJson(True, '设置成功!')
def fixDbAccess(version):
try:
pdb = pMysqlDb()
data = pdb.query('show databases')
isError = isSqlError(data)
if isError != None:
appCMD(version, 'stop')
mw.execShell("rm -rf " + getServerDir() + "/data")
appCMD(version, 'start')
return mw.returnJson(True, '修复成功!')
return mw.returnJson(True, '正常无需修复!')
except Exception as e:
return mw.returnJson(False, '修复失败请重试!')
def setDbRw(version=''):
args = getArgs()
data = checkArgs(args, ['username', 'id', 'rw'])
@@ -1567,55 +1703,57 @@ def setDbMasterAccess():
def getMasterDbList(version=''):
args = getArgs()
page = 1
page_size = 10
search = ''
data = {}
if 'page' in args:
page = int(args['page'])
try:
args = getArgs()
page = 1
page_size = 10
search = ''
data = {}
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'search' in args:
search = args['search']
if 'search' in args:
search = args['search']
conn = pSqliteDb('databases')
limit = str((page - 1) * page_size) + ',' + str(page_size)
condition = ''
dodb = findBinlogDoDb()
data['dodb'] = dodb
conn = pSqliteDb('databases')
limit = str((page - 1) * page_size) + ',' + str(page_size)
condition = ''
dodb = findBinlogDoDb()
data['dodb'] = dodb
slave_dodb = findBinlogSlaveDoDb()
slave_dodb = findBinlogSlaveDoDb()
if not search == '':
condition = "name like '%" + search + "%'"
field = 'id,pid,name,username,password,accept,ps,addtime'
clist = conn.where(condition, ()).field(
field).limit(limit).order('id desc').select()
count = conn.where(condition, ()).count()
if not search == '':
condition = "name like '%" + search + "%'"
field = 'id,pid,name,username,password,accept,ps,addtime'
clist = conn.where(condition, ()).field(
field).limit(limit).order('id desc').select()
count = conn.where(condition, ()).count()
for x in range(0, len(clist)):
if clist[x]['name'] in dodb:
clist[x]['master'] = 1
else:
clist[x]['master'] = 0
for x in range(0, len(clist)):
if clist[x]['name'] in dodb:
clist[x]['master'] = 1
else:
clist[x]['master'] = 0
if clist[x]['name'] in slave_dodb:
clist[x]['slave'] = 1
else:
clist[x]['slave'] = 0
if clist[x]['name'] in slave_dodb:
clist[x]['slave'] = 1
else:
clist[x]['slave'] = 0
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = 'dbList'
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.getJson(data)
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = 'dbList'
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.getJson(data)
except Exception as e:
return mw.returnJson(False, "数据库密码错误,在管理列表-点击【修复】!")
def setDbMaster(version):
@@ -1681,29 +1819,32 @@ def setDbSlave(version):
def getMasterStatus(version=''):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动,或正在启动中...!', [])
try:
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动,或正在启动中...!', [])
conf = getConf()
content = mw.readFile(conf)
master_status = False
if content.find('#log-bin') == -1 and content.find('log-bin') > 1:
dodb = findBinlogDoDb()
if len(dodb) > 0:
master_status = True
conf = getConf()
content = mw.readFile(conf)
master_status = False
if content.find('#log-bin') == -1 and content.find('log-bin') > 1:
dodb = findBinlogDoDb()
if len(dodb) > 0:
master_status = True
data = {}
data['mode'] = recognizeDbMode()
data['status'] = master_status
data = {}
data['mode'] = recognizeDbMode()
data['status'] = master_status
db = pMysqlDb()
dlist = db.query('show slave status')
db = pMysqlDb()
dlist = db.query('show slave status')
# print(dlist[0])
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
data['slave_status'] = True
# print(dlist[0])
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
data['slave_status'] = True
return mw.returnJson(master_status, '设置成功', data)
return mw.returnJson(master_status, '设置成功', data)
except Exception as e:
return mw.returnJson(False, "数据库密码错误,在管理列表-点击【修复】!", 'pwd')
def setMasterStatus(version=''):
@@ -2396,11 +2537,11 @@ if __name__ == "__main__":
elif func == 'uninstall_pre_inspection':
print(uninstallPreInspection(version))
elif func == 'run_info':
print(runInfo())
print(runInfo(version))
elif func == 'db_status':
print(myDbStatus())
print(myDbStatus(version))
elif func == 'set_db_status':
print(setDbStatus())
print(setDbStatus(version))
elif func == 'conf':
print(getConf())
elif func == 'bin_log':
@@ -2427,10 +2568,14 @@ if __name__ == "__main__":
print(setDbBackup())
elif func == 'import_db_backup':
print(importDbBackup())
elif func == 'import_db_external':
print(importDbExternal())
elif func == 'delete_db_backup':
print(deleteDbBackup())
elif func == 'get_db_backup_list':
print(getDbBackupList())
elif func == 'get_db_backup_import_list':
print(getDbBackupImportList())
elif func == 'add_db':
print(addDb())
elif func == 'del_db':
@@ -2447,6 +2592,8 @@ if __name__ == "__main__":
print(getDbAccess())
elif func == 'set_db_access':
print(setDbAccess())
elif func == 'fix_db_access':
print(fixDbAccess(version))
elif func == 'set_db_rw':
print(setDbRw(version))
elif func == 'set_db_ps':
+1 -1
View File
@@ -11,7 +11,7 @@
"path": "server/mysql/VERSION",
"todo_versions":["5.6","5.7","8.0"],
"versions":["5.5", "5.6", "5.7","8.0"],
"updates":["5.5.62","5.6.50", "5.7.32","8.0.22"],
"updates":["5.5.62","5.6.50", "5.7.32","8.0.30"],
"shell":"install.sh",
"checks":"server/mysql",
"path":"server/mysql",
+4
View File
@@ -24,6 +24,10 @@ if [ ! -d $curPath/versions/$2 ];then
exit 0
fi
if [ -d $serverPath/mysql ];then
exit 0
fi
if [ "${action}" == "uninstall" ];then
if [ -f /usr/lib/systemd/system/mysql.service ] || [ -f /lib/systemd/system/mysql.service ];then
+252 -113
View File
@@ -1,18 +1,9 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function myPost(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);
}
@@ -40,7 +31,7 @@ function myPostN(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);
}
@@ -59,7 +50,7 @@ function myPostN(method,args,callback, title){
function myAsyncPost(method,args){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(str2Obj(args));
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
@@ -69,8 +60,7 @@ function myAsyncPost(method,args){
}
function vaildPhpmyadmin(url,username,password){
console.log("Authorization: Basic " + btoa(username + ":" + password));
// console.log("Authorization: Basic " + btoa(username + ":" + password));
$.ajax({
type: "GET",
url: url,
@@ -97,6 +87,7 @@ function runInfo(){
return;
}
// Com_select , Qcache_inserts
var cache_size = ((parseInt(rdata.Qcache_hits) / (parseInt(rdata.Qcache_hits) + parseInt(rdata.Qcache_inserts))) * 100).toFixed(2) + '%';
if (cache_size == 'NaN%') cache_size = 'OFF';
var Con = '<div class="divtable"><table class="table table-hover table-bordered" style="margin-bottom:10px;background-color:#fafafa">\
@@ -204,6 +195,12 @@ function myPerfOpt() {
//获取MySQL配置
myPost('db_status','',function(data){
var rdata = $.parseJSON(data.data);
if ( typeof(rdata.status) != 'undefined' && !rdata.status){
layer.msg(rdata.msg, {icon:2});
return;
}
// console.log(rdata);
var key_buffer_size = toSizeM(rdata.mem.key_buffer_size);
var query_cache_size = toSizeM(rdata.mem.query_cache_size);
@@ -606,7 +603,7 @@ function setDbAccess(username){
yes:function(index){
var data = $("#set_db_access").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
if(!dataObj['access']){
dataObj['access'] = dataObj['dataAccess'];
if ( dataObj['dataAccess'] == 'ip'){
@@ -631,9 +628,17 @@ function setDbAccess(username){
});
}
function setDbPass(id, username, password){
function fixDbAccess(username){
myPost('fix_db_access', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
dbList();
},{icon: rdata.status ? 1 : 2});
});
}
var index = layer.open({
function setDbPass(id, username, password){
layer.open({
type: 1,
area: '500px',
title: '修改数据库密码',
@@ -672,33 +677,15 @@ function setDbPass(id, username, password){
}
function addDatabase(type){
if (type==1){
var data = $("#add_db").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
if(!dataObj['address']){
dataObj['address'] = dataObj['dataAccess'];
}
myPost('add_db', dataObj, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
dbList();
}
$('.layui-layer-close1').click();
},{icon: rdata.status ? 1 : 2},600);
});
return;
}
var index = layer.open({
layer.open({
type: 1,
skin: 'demo-class',
area: '500px',
title: '添加数据库',
closeBtn: 1,
shift: 5,
shadeClose: true,
content: "<form class='bt-form pd20 pb70' id='add_db'>\
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='add_db'>\
<div class='line'>\
<span class='tname'>数据库名</span>\
<div class='info-r'><input name='name' class='bt-input-text mr5' placeholder='新的数据库名称' type='text' style='width:65%' value=''>\
@@ -726,28 +713,39 @@ function addDatabase(type){
</div>\
</div>\
<input type='hidden' name='ps' value='' />\
<div class='bt-form-submit-btn'>\
<button id='my_mod_close' type='button' class='btn btn-danger btn-sm btn-title'>关闭</button>\
<button type='button' class='btn btn-success btn-sm btn-title' onclick=\"addDatabase(1)\" >提交</button>\
</div>\
</form>",
});
success:function(){
$("input[name='name']").keyup(function(){
var v = $(this).val();
$("input[name='db_user']").val(v);
$("input[name='ps']").val(v);
});
$("input[name='name']").keyup(function(){
var v = $(this).val();
$("input[name='db_user']").val(v);
$("input[name='ps']").val(v);
});
$('#my_mod_close').click(function(){
$('.layui-layer-close1').click();
});
$('select[name="dataAccess"]').change(function(){
var v = $(this).val();
if (v == 'ip'){
$(this).after("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
} else {
$('#dataAccess_subid').remove();
$('select[name="dataAccess"]').change(function(){
var v = $(this).val();
if (v == 'ip'){
$(this).after("<input id='dataAccess_subid' class='bt-input-text mr5' type='text' name='address' placeholder='多个IP使用逗号(,)分隔' style='width: 230px; display: inline-block;'>");
} else {
$('#dataAccess_subid').remove();
}
});
},
yes:function(index) {
var data = $("#add_db").serialize();
data = decodeURIComponent(data);
var dataObj = toArrayObject(data);
if(!dataObj['address']){
dataObj['address'] = dataObj['dataAccess'];
}
myPost('add_db', dataObj, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
dbList();
}
},{icon: rdata.status ? 1 : 2},600);
});
}
});
}
@@ -759,7 +757,6 @@ function delDb(id, name){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
$('.layui-layer-close1').click();
},{icon: rdata.status ? 1 : 2}, 600);
});
});
@@ -834,8 +831,8 @@ function openPhpmyadmin(name,username,password){
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_cfg'});
var rdata = $.parseJSON(data.data);
if (rdata.choose == 'mariadb'){
layer.msg('当前为[mariadb]模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
if (rdata.choose != 'mysql'){
layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
return;
}
@@ -881,12 +878,14 @@ function openPhpmyadmin(name,username,password){
}
}
function delBackup(filename,name){
myPost('delete_db_backup',{filename:filename},function(){
function delBackup(filename, name, path){
if(typeof(path) == "undefined"){
path = "";
}
myPost('delete_db_backup',{filename:filename,path:path},function(){
layer.msg('执行成功!');
setTimeout(function(){
$('.layui-layer-close2').click();
setBackup(name);
setBackupReq(name);
},2000);
});
}
@@ -902,9 +901,182 @@ function importBackup(file,name){
});
}
function setBackup(db_name,obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
function importDbExternal(file,name){
myPost('import_db_external',{file:file,name:name}, function(data){
layer.msg('执行成功!');
});
}
function setLocalImport(db_name){
//上传文件
function uploadDbFiles(upload_dir){
var up_db = layer.open({
type:1,
closeBtn: 1,
title:"上传导入文件["+upload_dir+']',
area: ['500px','300px'],
shadeClose:false,
content:'<div class="fileUploadDiv">\
<input type="hidden" id="input-val" value="'+upload_dir+'" />\
<input type="file" id="file_input" multiple="true" autocomplete="off" />\
<button type="button" id="opt" autocomplete="off">添加文件</button>\
<button type="button" id="up" autocomplete="off" >开始上传</button>\
<span id="totalProgress" style="position: absolute;top: 7px;right: 147px;"></span>\
<span style="float:right;margin-top: 9px;">\
<font>文件编码:</font>\
<select id="fileCodeing" >\
<option value="byte">二进制</option>\
<option value="utf-8">UTF-8</option>\
<option value="gb18030">GB2312</option>\
</select>\
</span>\
<button type="button" id="filesClose" autocomplete="off">关闭</button>\
<ul id="up_box"></ul>\
</div>',
success:function(){
$('#filesClose').click(function(){
layer.close(up_db);
});
}
});
uploadStart(function(){
getList();
layer.close(up_db);
});
}
function getList(){
myPost('get_db_backup_import_list',{}, function(data){
var rdata = $.parseJSON(data.data);
var file_list = rdata.data.list;
var upload_dir = rdata.data.upload_dir;
var tbody = '';
for (var i = 0; i < file_list.length; i++) {
tbody += '<tr>\
<td><span> ' + file_list[i]['name'] + '</span></td>\
<td><span> ' + file_list[i]['size'] + '</span></td>\
<td><span> ' + file_list[i]['time'] + '</span></td>\
<td style="text-align: right;">\
<a class="btlink" onclick="importDbExternal(\'' + file_list[i]['name'] + '\',\'' +db_name+ '\')">导入</a> | \
<a class="btlink del" index="'+i+'">删除</a>\
</td>\
</tr>';
}
$('#import_db_file_list').html(tbody);
$('input[name="upload_dir"]').val(upload_dir);
$("#import_db_file_list .del").on('click',function(){
var index = $(this).attr('index');
var filename = file_list[index]["name"];
myPost('delete_db_backup',{filename:filename,path:upload_dir},function(){
showMsg('执行成功!', function(){
getList();
},{icon:1},2000);
});
});
});
}
var layerIndex = layer.open({
type: 1,
title: "从文件导入数据",
area: ['600px', '380px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_file_upload" class="btn btn-success btn-sm" type="button">从本地上传</button>\
</div >\
<div class="divtable">\
<input type="hidden" name="upload_dir" value=""> \
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody id="import_db_file_list" class="gztr"></tbody>\
</table>\
</div>\
<ul class="help-info-text c7">\
<li>仅支持sql、zip、sql.gz、(tar.gz|gz|tgz)</li>\
<li>zip、tar.gz压缩包结构:test.zip或test.tar.gz压缩包内,必需包含test.sql</li>\
<li>若文件过大,您还可以使用SFTP工具,将数据库文件上传到/www/backup/import</li>\
</ul>\
</div>\
</div>',
success:function(index){
$('#btn_file_upload').click(function(){
var upload_dir = $('input[name="upload_dir"]').val();
uploadDbFiles(upload_dir);
});
getList();
},
});
}
function setBackup(db_name){
var layerIndex = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
<button id="btn_local_import" class="btn btn-success btn-sm" type="button">外部导入</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table id="database_table" class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="list"></tbody>\
</table>\
</div>\
</div>\
</div>',
success:function(index){
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
showMsg('执行成功!', function(){
setBackupReq(db_name);
}, {icon:1}, 2000);
});
});
$('#btn_local_import').click(function(){
setLocalImport(db_name);
});
setBackupReq(db_name);
},
});
}
function setBackupReq(db_name, obj){
myPost('get_db_backup_list', {name:db_name}, function(data){
var rdata = $.parseJSON(data.data);
var tbody = '';
for (var i = 0; i < rdata.data.length; i++) {
@@ -919,49 +1091,10 @@ function setBackup(db_name,obj){
</td>\
</tr> ';
}
var s = layer.open({
type: 1,
title: "数据库备份详情",
area: ['600px', '280px'],
closeBtn: 2,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
<button id="btn_backup" class="btn btn-success btn-sm" type="button">备份</button>\
</div >\
<div class="divtable">\
<div id="database_fix" style="height:150px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover "style="border:none">\
<thead>\
<tr>\
<th>文件名称</th>\
<th>文件大小</th>\
<th>备份时间</th>\
<th style="text-align: right;">操作</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
</table>\
</div>\
</div>\
</div>'
});
$('#btn_backup').click(function(){
myPost('set_db_backup',{name:db_name}, function(data){
layer.msg('执行成功!');
setTimeout(function(){
layer.close(s);
setBackup(db_name,obj);
},2000);
});
});
$('#database_table tbody').html(tbody);
});
}
function dbList(page, search){
var _data = {};
if (typeof(page) =='undefined'){
@@ -1027,6 +1160,7 @@ function dbList(page, search){
<button onclick="setRootPwd(0,\''+rdata.info['root_pwd']+'\')" title="设置MySQL管理员密码" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">root密码</button>\
<button onclick="openPhpmyadmin(\'\',\'root\',\''+rdata.info['root_pwd']+'\')" title="打开phpMyadmin" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">phpMyAdmin</button>\
<button onclick="setDbAccess(\'root\')" title="ROOT权限" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">ROOT权限</button>\
<button onclick="fixDbAccess(\'root\')" title="修复" class="btn btn-default btn-sm" type="button" style="margin-right: 5px;">修复</button>\
<span style="float:right"> \
<button batch="true" style="float: right;display: none;margin-left:10px;" onclick="delDbBatch();" title="删除选中项" class="btn btn-default btn-sm">删除选中</button>\
</span>\
@@ -1237,7 +1371,7 @@ function repTools(db_name, res){
type: 1,
title: "MySQL工具箱【" + db_name + "】",
area: ['780px', '580px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="db_list">\
@@ -1332,7 +1466,7 @@ function addMasterRepSlaveUser(){
yes:function(index){
var data = $("#add_master").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
if(!dataObj['address']){
dataObj['address'] = dataObj['dataAccess'];
}
@@ -1377,7 +1511,7 @@ function updateMasterRepSlaveUser(username){
$('#submit_update_master').click(function(){
var data = $("#update_master").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
myPost('update_master_rep_slave_user', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
@@ -1488,7 +1622,7 @@ function setDbMasterAccess(username){
yes:function(index){
var data = $("#set_db_access").serialize();
data = decodeURIComponent(data);
var dataObj = str2Obj(data);
var dataObj = toArrayObject(data);
if(!dataObj['access']){
dataObj['access'] = dataObj['dataAccess'];
if ( dataObj['dataAccess'] == 'ip'){
@@ -1961,9 +2095,14 @@ function masterOrSlaveConf(version=''){
function getMasterStatus(){
myPost('get_master_status', '', function(data){
var rdata = $.parseJSON(data.data);
myPost('get_master_status', '', function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log('mode:',rdata.data);
if ( typeof(rdata.status) != 'undefined' && !rdata.status && rdata.data == 'pwd'){
layer.msg(rdata.msg, {icon:2});
return;
}
var rdata = rdata.data;
var limitCon = '\
<p class="conf_p">\
+3 -1
View File
@@ -51,8 +51,10 @@ Install_mysql()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
+3 -1
View File
@@ -54,8 +54,10 @@ Install_mysql()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
+7 -5
View File
@@ -17,7 +17,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mysqlDir=${serverPath}/source/mysql
VERSION="5.7.39"
VERSION=5.7.39
Install_mysql()
@@ -56,19 +56,21 @@ Install_mysql()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-${VERSION}.tar.gz
fi
#检测文件是否损坏.
md5_mysql_ok=db1b672fc257bd46356c7af26dd22801
md5_mysql_ok=d949b0ef81c3f52f7ef0874066244221
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -76,7 +78,7 @@ Install_mysql()
else
# 重新下载
rm -rf ${mysqlDir}/mysql-${VERSION}
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-${VERSION}.tar.gz
fi
fi
+7 -5
View File
@@ -57,7 +57,7 @@ fi
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
VERSION=8.0.28
VERSION=8.0.30
Install_mysql()
{
mkdir -p ${mysqlDir}
@@ -90,8 +90,10 @@ Install_mysql()
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
@@ -107,11 +109,11 @@ Install_mysql()
fi
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${VERSION}.tar.gz
fi
#检测文件是否损坏.
md5_mysql_ok=362b8141ecaf425b803fe55292e2df98
md5_mysql_ok=313d625fcaa932bd87b48f0cf9b40f1c
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -119,7 +121,7 @@ Install_mysql()
else
# 重新下载
rm -rf ${mysqlDir}/mysql-${VERSION}
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${VERSION}.tar.gz
fi
fi
+61
View File
@@ -0,0 +1,61 @@
import sys
import os
class luamaker:
"""
lua 处理器
"""
@staticmethod
def makeLuaTable(table):
"""
table 转换为 lua table 字符串
"""
_tableMask = {}
_keyMask = {}
def analysisTable(_table, _indent, _parent):
if isinstance(_table, tuple):
_table = list(_table)
if isinstance(_table, list):
_table = dict(zip(range(1, len(_table) + 1), _table))
if isinstance(_table, dict):
_tableMask[id(_table)] = _parent
cell = []
thisIndent = _indent + " "
for k in _table:
if sys.version_info[0] == 2:
if type(k) not in [int, float, bool, list, dict, tuple]:
k = k.encode()
if not (isinstance(k, str) or isinstance(k, int) or isinstance(k, float)):
return
key = isinstance(
k, int) and "[" + str(k) + "]" or "[\"" + str(k) + "\"]"
if _parent + key in _keyMask.keys():
return
_keyMask[_parent + key] = True
var = None
v = _table[k]
if sys.version_info[0] == 2:
if type(v) not in [int, float, bool, list, dict, tuple]:
v = v.encode()
if isinstance(v, str):
# print("lua", var)
v = v.replace("\\", "\\\\")
v = v.replace("\"", "\\\"")
var = "\"" + v + "\""
elif isinstance(v, bool):
var = v and "true" or "false"
elif isinstance(v, int) or isinstance(v, float):
var = str(v)
else:
var = analysisTable(v, thisIndent, _parent + key)
cell.append(thisIndent + key + " = " + str(var))
lineJoin = ",\n"
return "{\n" + lineJoin.join(cell) + "\n" + _indent + "}"
else:
pass
return analysisTable(table, "", "root")
+17
View File
@@ -0,0 +1,17 @@
PRAGMA synchronous = 0;
PRAGMA page_size = 4096;
PRAGMA journal_mode = wal;
PRAGMA journal_size_limit = 1073741824;
CREATE TABLE IF NOT EXISTS `logs` (
`time` INTEGER,
`ip` TEXT,
`domain` TEXT,
`server_name` TEXT,
`method` TEXT,
`status_code` INTEGER,
`user_agent` TEXT,
`uri` TEXT,
`rule_name` TEXT,
`reason` TEXT
);
+8 -6
View File
@@ -1,8 +1,10 @@
lua_shared_dict limit 30m;
lua_shared_dict drop_ip 10m;
lua_shared_dict drop_sum 10m;
lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
lua_shared_dict waf_limit 30m;
lua_shared_dict waf_drop_ip 10m;
lua_shared_dict waf_drop_sum 10m;
lua_package_path "{$WAF_PATH}/html/?.lua;{$WAF_PATH}/conf/?.lua;{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
lua_package_cpath "{$WAF_PATH}/conf/?.so;{$ROOT_PATH}/openresty/lualib/?.so;;";
init_worker_by_lua_file {$WAF_PATH}/lua/init_worker.lua;
access_by_lua_file {$WAF_PATH}/lua/init.lua;
#init_by_lua_file {$WAF_PATH}/lua/init.lua;
#access_by_lua_file {$WAF_PATH}/lua/waf.lua;
# init_by_lua_file {$WAF_PATH}/lua/init.lua;
+16 -2
View File
@@ -1,4 +1,18 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.cur {
background-color: #20a53a;
color: #fff;
}
/*waf*/
.lib-con-title {
height: 26px;
@@ -231,8 +245,8 @@
<p onclick="wafScreen();">首页</p>
<p onclick="wafGloabl();">全局配置</p>
<p onclick="wafSite();">站点配置</p>
<p onclick="wafHistory();">封锁历史</p>
<p onclick="wafLogs();">操作日志</p>
<p onclick="wafLogs();">封锁历史</p>
<!-- <p onclick="wafOpLogs();">操作日志</p> -->
</div>
<!-- lib-con -->
<div class="bt-w-con pd15">
+270 -26
View File
@@ -52,11 +52,50 @@ def checkArgs(data, ck=[]):
return (True, mw.returnJson(True, 'ok'))
sys.path.append(getPluginDir() + "/class")
from luamaker import luamaker
def listToLuaFile(path, lists):
content = luamaker.makeLuaTable(lists)
content = "return " + content
mw.writeFile(path, content)
def htmlToLuaFile(path, content):
content = "return [[" + content + "]]"
mw.writeFile(path, content)
def getConf():
path = mw.getServerDir() + "/openresty/nginx/conf/nginx.conf"
return path
def pSqliteDb(dbname='logs'):
name = "waf"
db_dir = getServerDir() + '/logs/'
if not os.path.exists(db_dir):
mw.execShell('mkdir -p ' + db_dir)
file = db_dir + name + '.db'
if not os.path.exists(file):
conn = mw.M(dbname).dbPos(db_dir, name)
sql = mw.readFile(getPluginDir() + '/conf/init.sql')
sql_list = sql.split(';')
for index in range(len(sql_list)):
conn.execute(sql_list[index])
else:
conn = mw.M(dbname).dbPos(db_dir, name)
conn.execute("PRAGMA synchronous = 0")
conn.execute("PRAGMA page_size = 4096")
conn.execute("PRAGMA journal_mode = wal")
conn.execute("PRAGMA journal_size_limit = 1073741824")
return conn
def initDomainInfo():
data = []
path_domains = getJsonPath('domains')
@@ -107,7 +146,7 @@ def initSiteInfo():
site_contents_new[name] = site_contents[name]
else:
tmp = {}
tmp['cdn'] = False
tmp['cdn'] = True
tmp['log'] = True
tmp['get'] = True
tmp['post'] = True
@@ -120,6 +159,7 @@ def initSiteInfo():
tmp['user-agent'] = config_contents['user-agent']
tmp['cookie'] = config_contents['cookie']
tmp['scan'] = config_contents['scan']
tmp['safe_verify'] = config_contents['safe_verify']
cdn_header = ['x-forwarded-for',
'x-real-ip',
@@ -132,7 +172,6 @@ def initSiteInfo():
'cdn-src-ip',
'cdn-real-ip',
'cf-connecting-ip',
'cf-connecting-ip',
'x-cluster-client-ip',
'wl-proxy-client-ip',
'proxy-client-ip',
@@ -178,7 +217,9 @@ def initTotalInfo():
tmp['get'] = 0
tmp['post'] = 0
tmp['total'] = 0
tmp['url_ext'] = 0
tmp['path'] = 0
tmp['php_path'] = 0
tmp['upload_ext'] = 0
_name = {}
_name[name] = tmp
total_contents['sites'] = _name
@@ -211,10 +252,89 @@ def contentReplace(content):
return content
def autoMakeLuaConfSingle(file):
# path = getPluginDir() + "/waf/rule/" + file + ".json"
path = getServerDir() + "/waf/rule/" + file + ".json"
to_path = getServerDir() + "/waf/conf/rule_" + file + ".lua"
content = mw.readFile(path)
# print(content)
content = json.loads(content)
listToLuaFile(to_path, content)
def autoMakeLuaImportSingle(file):
path = getServerDir() + "/waf/" + file + ".json"
to_path = getServerDir() + "/waf/conf/waf_" + file + ".lua"
content = mw.readFile(path)
# print(content)
content = json.loads(content)
listToLuaFile(to_path, content)
def autoMakeLuaHtmlSingle(file):
path = getServerDir() + "/waf/html/" + file + ".html"
to_path = getServerDir() + "/waf/html/html_" + file + ".lua"
content = mw.readFile(path)
htmlToLuaFile(to_path, content)
def autoMakeLuaConf():
conf_list = ['args', 'cookie', 'ip_black', 'ip_white',
'ipv6_black', 'post', 'scan_black', 'url',
'url_white', 'user_agent']
for x in conf_list:
autoMakeLuaConfSingle(x)
import_list = ['config', 'site', 'domains']
for x in import_list:
autoMakeLuaImportSingle(x)
html_list = ['get', 'post', 'safe_js', 'user_agent', 'cookie', 'other']
for x in html_list:
autoMakeLuaHtmlSingle(x)
def initDefaultInfo():
path = getServerDir()
djson = path + "/waf/domains.json"
default_json = path + "/waf/default.json"
if os.path.exists(djson):
content = mw.readFile(djson)
content = json.loads(content)
ddata = {}
dlist = []
for i in content:
dlist.append(i["name"])
dlist.append('unset')
ddata["list"] = dlist
if len(ddata["list"]) < 1:
ddata["default"] = "unset"
else:
ddata["default"] = dlist[0]
mw.writeFile(default_json, json.dumps(ddata))
def autoMakeConfig():
path = getServerDir()
initDomainInfo()
initSiteInfo()
initTotalInfo()
autoMakeLuaConf()
def restartWeb():
autoMakeConfig()
mw.restartWeb()
def initDreplace():
path = getServerDir()
if not os.path.exists(path + '/waf'):
if not os.path.exists(path + '/waf/lua'):
sdir = getPluginDir() + '/waf'
cmd = 'cp -rf ' + sdir + ' ' + path
mw.execShell(cmd)
@@ -245,6 +365,11 @@ def initDreplace():
content = contentReplace(content)
mw.writeFile(config_common, content)
init_worker = path + "/waf/lua/init_worker.lua"
content = mw.readFile(init_worker)
content = contentReplace(content)
mw.writeFile(init_worker, content)
waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
waf_tpl = getPluginDir() + "/conf/luawaf.conf"
content = mw.readFile(waf_tpl)
@@ -254,6 +379,10 @@ def initDreplace():
initDomainInfo()
initSiteInfo()
initTotalInfo()
autoMakeLuaConf()
initDefaultInfo()
pSqliteDb()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + path)
@@ -267,6 +396,9 @@ def start():
conf = conf.replace('#include luawaf.conf;', "include luawaf.conf;")
mw.writeFile(path, conf)
import tool_task
tool_task.createBgTask()
mw.restartWeb()
return 'ok'
@@ -277,6 +409,10 @@ def stop():
conf = conf.replace('include luawaf.conf;', "#include luawaf.conf;")
mw.writeFile(path, conf)
import tool_task
tool_task.removeBgTask()
mw.restartWeb()
return 'ok'
@@ -288,8 +424,19 @@ def restart():
def reload():
stop()
mw.execShell('rm -rf ' + mw.getServerDir() +
"/openresty/nginx/logs/error.log")
path = getServerDir()
path_tpl = getPluginDir()
config = path + "/waf/lua/init.lua"
config_tpl = path_tpl + "/waf/lua/init.lua"
content = mw.readFile(config_tpl)
content = contentReplace(content)
mw.writeFile(config, content)
errlog = mw.getServerDir() + "/openresty/nginx/logs/error.log"
mw.execShell('rm -rf ' + errlog)
start()
return 'ok'
@@ -340,7 +487,7 @@ def addRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -362,7 +509,7 @@ def removeRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -387,7 +534,7 @@ def setRuleState():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -418,7 +565,7 @@ def modifyRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -459,6 +606,7 @@ def addSiteRule():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -494,6 +642,7 @@ def addIpWhite():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -514,6 +663,8 @@ def removeIpWhite():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -549,6 +700,8 @@ def addIpBlack():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -569,6 +722,8 @@ def removeIpBlack():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -587,6 +742,7 @@ def setIpv6Black():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -603,9 +759,10 @@ def delIpv6Black():
content = json.loads(content)
content.remove(addr)
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -628,6 +785,8 @@ def removeSiteRule():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -642,11 +801,13 @@ def setObjStatus():
cobj = json.loads(content)
o = args['obj']
status = args['statusCode']
status = int(args['statusCode'])
cobj[o]['status'] = status
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -666,6 +827,32 @@ def setRetry():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
def setSafeVerify():
args = getArgs()
data = checkArgs(args, ['auto', 'time', 'cpu'])
if not data[0]:
return data[1]
conf = getJsonPath('config')
content = mw.readFile(conf)
cobj = json.loads(content)
cobj['safe_verify']['time'] = args['time']
cobj['safe_verify']['cpu'] = args['cpu']
if args['auto'] == '0':
cobj['safe_verify']['auto'] = False
else:
cobj['safe_verify']['auto'] = True
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
@@ -676,7 +863,7 @@ def setSiteRetry():
def setCcConf():
args = getArgs()
data = checkArgs(args, ['siteName', 'cycle', 'limit',
'endtime', 'is_open_global', 'increase'])
'endtime', 'is_open_global'])
if not data[0]:
return data[1]
@@ -695,6 +882,8 @@ def setCcConf():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
@@ -711,6 +900,8 @@ def saveScanRule():
path = getRuleJsonPath('scan_black')
cjson = mw.getJson(args)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
@@ -750,6 +941,26 @@ def getSiteConfig():
return mw.returnJson(True, 'ok!', content)
def getSiteListData():
path = getServerDir() + "/waf/default.json"
data = mw.readFile(path)
return json.loads(data)
def setDefaultSite(name):
path = getServerDir() + "/waf/default.json"
data = mw.readFile(path)
data = json.loads(data)
data['default'] = name
mw.writeFile(path, json.dumps(data))
return mw.returnJson(True, 'OK')
def getDefaultSite():
data = getSiteListData()
return mw.returnJson(True, 'OK', data)
def getSiteConfigByName():
args = getArgs()
data = checkArgs(args, ['siteName'])
@@ -783,6 +994,8 @@ def addSiteCdnHeader():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '添加成功!')
@@ -802,6 +1015,8 @@ def removeSiteCdnHeader():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '删除成功!')
@@ -824,29 +1039,44 @@ def importData():
path = getRuleJsonPath(args['s_Name'])
mw.writeFile(path, args['pdata'])
restartWeb()
return mw.returnJson(True, '设置成功!')
def getLogsList():
args = getArgs()
data = checkArgs(args, ['siteName'])
data = checkArgs(args, ['site', 'page', 'page_size', 'tojs'])
if not data[0]:
return data[1]
data = []
path = getServerDir() + '/logs'
page = int(args['page'])
page_size = int(args['page_size'])
domain = args['site']
tojs = args['tojs']
if not os.path.exists(path):
return mw.returnJson(False, '还未生成!', [])
conn = pSqliteDb('logs')
files = os.listdir(path)
for f in files:
if f == '.DS_Store':
continue
f = f.split('_')
if f[0] == args['siteName']:
fl = f[1].split('.')
data.append(fl[0])
field = 'time,ip,domain,server_name,method,uri,user_agent,rule_name,reason'
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
condition = ''
conn = conn.field(field)
conn = conn.where("1=1", ()).where("domain=?", (domain,))
clist = conn.limit(limit).order('time desc').inquiry()
count_key = "count(*) as num"
count = conn.field(count_key).limit('').order('').inquiry()
# print(count)
count = count[0][count_key]
data = {}
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = tojs
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.returnJson(True, 'ok!', data)
@@ -893,6 +1123,7 @@ def setObjOpen():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -922,6 +1153,7 @@ def setSiteObjOpen():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -942,6 +1174,12 @@ def installPreInspection():
return 'ok'
def cleanDropIp():
url = "http://127.0.0.1/clean_waf_drop_ip"
data = mw.httpGet(url)
return mw.returnJson(True, 'ok!', data)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
@@ -998,12 +1236,16 @@ if __name__ == "__main__":
print(setSiteCcConf())
elif func == 'set_retry':
print(setRetry())
elif func == 'set_safe_verify':
print(setSafeVerify())
elif func == 'set_site_retry':
print(setSiteRetry())
elif func == 'save_scan_rule':
print(saveScanRule())
elif func == 'get_site_config':
print(getSiteConfig())
elif func == 'get_default_site':
print(getDefaultSite())
elif func == 'get_site_config_byname':
print(getSiteConfigByName())
elif func == 'add_site_cdn_header':
@@ -1024,5 +1266,7 @@ if __name__ == "__main__":
print(getWafConf())
elif func == 'waf_site':
print(getWafSite())
elif func == 'clean_drop_ip':
print(cleanDropIp())
else:
print('error')
+2 -1
View File
@@ -4,6 +4,7 @@
"name":"op_waf",
"type":"其他插件",
"ps":"有效防止sql注入/xss/一句话木马等常见渗透攻击",
"install_pre_inspection":true,
"shell":"install.sh",
"checks":"server/op_waf",
"path":"server/op_waf",
@@ -11,5 +12,5 @@
"home":"https://github.com/loveshell/ngx_lua_waf",
"date":"2019-04-21",
"pid": "1",
"versions": ["0.1"]
"versions": ["0.2.3"]
}
+74 -6
View File
@@ -7,31 +7,99 @@ rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
version=$2
sys_os=`uname`
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
if [ "$sys_os" == "Darwin" ];then
BAK='_bak'
else
BAK=''
fi
Install_of(){
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source/op_waf
mkdir -p $serverPath/op_waf
echo '0.1' > $serverPath/op_waf/version.pl
# luarocks
if [ ! -f $serverPath/source/op_waf/luarocks-3.5.0.tar.gz ];then
wget --no-check-certificate -O $serverPath/source/op_waf/luarocks-3.5.0.tar.gz http://luarocks.org/releases/luarocks-3.5.0.tar.gz
fi
# which luarocks
# if [ "$?" != "0" ];then
if [ ! -d $serverPath/op_waf/luarocks ];then
cd $serverPath/source/op_waf && tar xvf luarocks-3.5.0.tar.gz
# cd luarocks-3.9.1 && ./configure && make bootstrap
cd luarocks-3.5.0 && ./configure --prefix=$serverPath/op_waf/luarocks --with-lua-include=$serverPath/openresty/luajit/include/luajit-2.1 --with-lua-bin=$serverPath/openresty/luajit/bin
make -I${serverPath}/openresty/luajit/bin
make install
fi
if [ ! -f $serverPath/source/op_waf/lsqlite3_fsl09y.zip ];then
wget --no-check-certificate -O $serverPath/source/op_waf/lsqlite3_fsl09y.zip http://lua.sqlite.org/index.cgi/zip/lsqlite3_fsl09y.zip?uuid=fsl_9y
cd $serverPath/source/op_waf && unzip lsqlite3_fsl09y.zip
fi
if [ ! -d $serverPath/source/op_waf/lsqlite3_fsl09y ];then
cd $serverPath/source/op_waf && unzip lsqlite3_fsl09y.zip
fi
PATH=${serverPath}/openresty/luajit:${serverPath}/openresty/luajit/include/luajit-2.1:$PATH
export PATH=$PATH:$serverPath/op_waf/luarocks/bin
if [ ! -f $serverPath/op_waf/waf/conf/lsqlite3.so ];then
if [ "${sys_os}" == "Darwin" ];then
cd $serverPath/source/op_waf/lsqlite3_fsl09y
find_cfg=`cat Makefile | grep 'SQLITE_DIR'`
if [ "$find_cfg" == "" ];then
LIB_SQLITE_DIR=`brew info sqlite | grep /usr/local/Cellar/sqlite | cut -d \ -f 1 | awk 'END {print}'`
echo $LIB_SQLITE_DIR
sed -i $BAK "s#\$(ROCKSPEC)#\$(ROCKSPEC) SQLITE_DIR=${LIB_SQLITE_DIR}#g" Makefile
fi
make
else
cd $serverPath/source/op_waf/lsqlite3_fsl09y && make
fi
fi
# copy to code path
DEFAULT_DIR=$serverPath/op_waf/luarocks/lib/lua/5.1
if [ -f ${DEFAULT_DIR}/lsqlite3.so ];then
mkdir -p $serverPath/op_waf/waf/conf
cp -rf ${DEFAULT_DIR}/lsqlite3.so $serverPath/op_waf/waf/conf/lsqlite3.so
fi
echo "${version}" > $serverPath/op_waf/version.pl
echo 'install ok' > $install_tmp
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py start
# cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py restart
}
Uninstall_of(){
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
rm -rf $serverPath/op_waf
if [ "$?" == "0" ];then
rm -rf $serverPath/op_waf
fi
}
action=$1
type=$2
action=$1
if [ "${1}" == 'install' ];then
Install_of
+367 -199
View File
@@ -69,8 +69,10 @@ function setObjOpen(ruleName){
owPost('set_obj_open', {obj:ruleName},function(data){
var rdata = $.parseJSON(data.data);
if (rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
wafGloabl();
showMsg(rdata.msg, function(){
wafGloabl();
},{icon:1,time:2000,shade: [0.3, '#000']},2000);
} else {
layer.msg('设置失败!',{icon:0,time:2000,shade: [0.3, '#000']});
}
@@ -84,7 +86,7 @@ function saveCcRule(siteName,is_open_global, type) {
if(type == 2){
// set_aicc_open('start');
increase = "0";
}else{
} else {
// set_aicc_open('stop');
increase = type;
}
@@ -164,7 +166,10 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
<li>请不要设置过于严格的CC规则,以免影响正常用户体验</li>\
<li><font style="color:red;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用:全局设置当前CC规则,且覆盖当前全部站点的CC规则</font></li>\
</ul>\
<div class="bt-form-submit-btn"><button type="button" class="btn btn-danger btn-sm btn_cc_all" style="margin-right:10px;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用</button><button type="button" class="btn btn-success btn-sm btn_cc_present">应用</button></div>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-danger btn-sm btn_cc_all" style="margin-right:10px;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用</button>\
<button type="button" class="btn btn-success btn-sm btn_cc_present">应用</button>\
</div>\
</form>',
success:function(layero,index){
$('.btn_cc_all').click(function(){
@@ -201,9 +206,12 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
</div>\
<ul class="help-info-text c7 ptb10">\
<li><font style="color:red;">'+ retry_cycle + '</font> 秒内累计恶意请求超过 <font style="color:red;">' + retry + '</font> 次,封锁 <font style="color:red;">' + retry_time + '</font> 秒</li>\
<li><font style="color:red;">全局应用:全局设置当前恶意容忍规则,且覆盖当前全部站点的恶意容忍规则</li>\
<li><font style="color:red;">全局应用:全局设置当前恶意容忍规则,且覆盖当前全部站点的恶意容忍规则</font></li>\
</ul>\
<div class="bt-form-submit-btn"><button type="button" class="btn btn-danger btn-sm btn_retry_all" style="margin-right:10px;display:'+ (siteName == undefined?'inline-block;':'none') +';">全局应用</button><button type="button" class="btn btn-success btn-sm btn_retry_present">应用</button></div>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-danger btn-sm btn_retry_all" style="margin-right:10px;display:'+ (siteName == undefined?'inline-block;':'none') +';">全局应用</button>\
<button type="button" class="btn btn-success btn-sm btn_retry_present">应用</button>\
</div>\
</form>',
success:function(){
$('.btn_retry_all').click(function(){
@@ -217,6 +225,65 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
}
//设置safe_verify规则
function setSafeVerify(auto, cpu, time, siteName) {
var svlayer = layer.open({
type: 1,
title: "设置强制安全验证",
area: '500px',
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
<span class="tname">CPU</span>\
<div class="info-r"><input class="bt-input-text" name="cpu" type="number" max-number="100" value="'+ cpu + '" /> %</div>\
</div>\
<div class="line">\
<span class="tname">通行时间</span>\
<div class="info-r"><input class="bt-input-text" name="time" type="number" value="'+ time + '" /> 秒</div>\
</div>\
<div class="line">\
<span class="tname">开启自动</span>\
<div class="info-r">\
<select class="bt-input-text mr5" style="width:80px" name="auto">\
<option value="0" '+(auto==false?"selected=selected":"")+'>关闭</option>\
<option value="1" '+(auto==true?"selected=selected":"")+'>开启</option>\
</select>\
</div>\
</div>\
<ul class="help-info-text c7 ptb10">\
<li><font style="color:red;">全局设置强制安全验证</font></li>\
<li>开启自动后:cpu超过['+cpu+'%]后,强制验证。</li>\
</ul>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-success btn-sm btn_sv_present">应用</button>\
</div>\
</form>',
success:function(index){
$('.btn_sv_present').click(function(){
var pdata = {
siteName: siteName,
cpu: $("input[name='cpu']").val(),
auto: $("select[name='auto']").val(),
time: $("input[name='time']").val(),
}
var act = 'set_safe_verify';
owPost(act, pdata, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg, function() {
layer.close(svlayer);
wafGloabl();
},{ icon: rdata.status ? 1 : 2 },1000);
});
});
},
});
}
//保存retry规则
function saveRetry(siteName,type) {
var pdata = {
@@ -253,15 +320,6 @@ function addRule(ruleName) {
},1000);
}
});
// var loadT = layer.msg('正在添加,请稍候..', { icon: 16, time: 0 });
// $.post('/plugin?action=a&name=btwaf&s=add_rule', pdata, function (rdata) {
// layer.close(loadT);
// layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
// if (rdata.status) {
// set_obj_conf(ruleName, 1);
// }
// });
}
function modifyRule(index, ruleName) {
@@ -633,6 +691,71 @@ function ipWhite(type) {
});
}
//IP白名单
function urlWhite(type) {
var ruleName = "url_white";
if (type == undefined) {
create_l = layer.open({
type: 1,
title: "管理URL白名单",
area: ['700px', '530px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
<input class="bt-input-text" name="ruleValue" type="text" value="" style="width:470px;margin-right:12px;" placeholder="规则内容,请使用正则表达式">\
<input class="bt-input-text mr5" name="rulePs" type="text" style="width:120px;" placeholder="描述">\
<button class="btn btn-success btn-sm va0 pull-right" onclick="addRule(\''+ ruleName + '\');">添加</button>\</div>\
<div class="divtable">\
<div id="jc-file-table" class="table_head_fix" style="max-height:300px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover" style="border:none">\
<thead>\
<tr>\
<th width="360">规则</th>\
<th>说明</th>\
<th>操作</th>\
<th style="text-align: right;">状态</th>\
</tr>\
</thead>\
<tbody id="set_obj_conf_con" class="gztr"></tbody>\
</table>\
</div>\
</div>\
<ul class="help-info-text c7 ptb10">\
<li style="color:red;">注意:如果您不了解正则表达式,请不要随意修改规则内容</li>\
<li>您可以添加或修改规则内容,但请使用正则表达式</li>\
<li>内置规则允许修改,但不可以直接删除,您可以设置规则状态来定义防火墙是否使用此规则</li>\
</ul></div>'
});
tableFixed("jc-file-table");
}
getRuleByName(ruleName, function(data){
var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data);
console.log(rdata);
var tbody = ''
for (var i = 0; i < rdata.length; i++) {
var removeRule = ''
if (rdata[i][3] != 0) removeRule = ' | <a class="btlink" onclick="removeRule(\'' + ruleName + '\',' + i + ')">删除</a>';
tbody += '<tr>\
<td class="rule_body_'+ i + '">' + rdata[i][1] + '</td>\
<td class="rule_ps_'+ i + '">' + rdata[i][2] + '</td>\
<td class="rule_modify_'+ i + '"><a class="btlink" onclick="modifyRule(' + i + ',\'' + ruleName + '\')">编辑</a>' + removeRule + '</td>\
<td class="text-right">\
<div class="pull-right">\
<input class="btswitch btswitch-ios" id="closeua_'+ i + '" type="checkbox" ' + (rdata[i][0] ? 'checked' : '') + '>\
<label class="btswitch-btn" style="width:2.0em;height:1.2em;margin-bottom: 0" for="closeua_'+ i + '" onclick="setRuleState(\'' + ruleName + '\',' + i + ')"></label>\
</div>\
</td>\
</tr>'
}
$("#set_obj_conf_con").html(tbody);
});
}
// 获取IPV4黑名单
function getIpv4Address(callback){
@@ -695,6 +818,23 @@ function addIpBlack() {
});
}
function addIpBlackArgs(ip) {
var pdata = {
start_ip: ip,
end_ip: ip,
}
if (pdata['start_ip'].split('.').length < 4 || pdata['end_ip'].split('.').length < 4) {
layer.msg('起始IP或结束IP格式不正确!');
return;
}
owPost('add_ip_black', pdata, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//从IP黑名单删除IP段
function removeIpBlack(index) {
@@ -820,17 +960,17 @@ function wafScreen(){
con += '<div class="screen">\
<div class="line"><span class="name">POST渗透</span><span class="val">'+rdata.rules.post+'</span></div>\
<div class="line"><span class="name">GET渗透</span><span class="val">0</span></div>\
<div class="line"><span class="name">GET渗透</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\
<div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\
<div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</span></div>\
<div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.url+'</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">恶意文件上传</span><span class="val">0</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.url_ext+'</span></div>\
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">0</span></div>\
<div class="line"><span class="name">恶意文件上传</span><span class="val">'+rdata.rules.upload_ext+'</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.path+'</span></div>\
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">'+rdata.rules.php_path+'</span></div>\
</div>';
con += '<div style="width:660px;"><ul class="help-info-text c7">\
@@ -878,6 +1018,16 @@ function wafGloabl(){
<td style="text-align: center;">--</td>\
<td class="text-right"><a class="btlink" onclick="setRetry('+ rdata.retry.retry_cycle + ',' + rdata.retry.retry + ',' + rdata.retry.retry_time + ')">初始规则</a></td>\
</tr>\
<tr>\
<td>强制安全验证</td>\
<td>'+rdata.safe_verify.ps+'</td>\
<td>--</td>\
<td style="text-align: center;"><div class="ssh-item">\
<input class="btswitch btswitch-ios" id="close_safe_verify" type="checkbox" '+(rdata.safe_verify.open ? 'checked' : '')+'>\
<label class="btswitch-btn" for="close_safe_verify" onclick="setObjOpen(\'safe_verify\')"></label></div>\
</td>\
<td class="text-right"><a class="btlink" onclick="setSafeVerify('+ rdata.safe_verify.auto + ',' + rdata.safe_verify.cpu + ',' + rdata.safe_verify.time + ')">设置</a> | <a class="btlink" href="javascript:;" onclick="onlineEditFile(0,\''+rdata['reqfile_path']+'/safe_js.html\')">响应内容</a></td>\
</tr>\
<tr>\
<td>GET-URI过滤</td>\
<td>'+ rdata.get.ps + '</td>\
@@ -918,6 +1068,11 @@ function wafGloabl(){
<label class="btswitch-btn" for="closescan" onclick="setObjOpen(\'scan\')"></label>\
</div></td><td class="text-right"><a class="btlink" onclick="scanRule()">设置</a></td>\
</tr>\
<tr>\
<td>URL白名单</td><td>所有规则对URL白名单无效</td><td style="text-align: center;">--</td>\
<td style="text-align: center;">--</td>\
<td class="text-right"><a class="btlink" onclick="urlWhite()">设置</a></td>\
</tr>\
<tr>\
<td>IP白名单</td><td>所有规则对IP白名单无效</td><td style="text-align: center;">--</td>\
<td style="text-align: center;">--</td>\
@@ -940,7 +1095,7 @@ function wafGloabl(){
con += '<div style="width:645px;margin-top:10px;"><ul class="help-info-text c7">\
<li>继承: 全局设置将在站点配置中自动继承为默认值</li>\
<li>优先级: IP白名单>IP黑名单>URL白名单>URL黑名单>CC防御>禁止国外IP访问>User-Agent>URI过滤>URL参数>Cookie>POST</li>\
<li>优先级: IP白名单>IP黑名单>URL白名单>URL黑名单>CC防御>User-Agent>URI过滤>URL参数>Cookie>POST</li>\
</ul></div>';
$(".soft-man-con").html(con);
});
@@ -956,146 +1111,6 @@ function back_css(v) {
}
}
//查看网站日志
function siteWafLog(siteName) {
var loadT = layer.msg('正在处理,请稍候..', { icon: 16, time: 0 });
owPost('get_logs_list', { siteName: siteName } , function (data) {
var tmp = $.parseJSON(data.data);
var rdata = tmp.data;
var selectLogDay = "";
var day = rdata[0];
for (var i = 0; i < rdata.length; i++) {
selectLogDay += '<option value="' + rdata[i] + '">' + rdata[i] + '</option>';
}
if (rdata == "") {
layer.msg("暂无日志记录", { icon: 6, shade: 0.3, time: 1000 });
return
}
layer.open({
type: 1,
title: "日志【" + siteName + "】",
area: ['880px', '500px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="lib-box pd15 lib-box-log">\
<div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\
<div class="lib-con">\
<div class="divtable">\
<div id="site_waf_log" style="max-height:400px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover" style="border:none;">\
<thead><tr><th width="150">时间</th><th width="120">用户IP</th><th width="70">类型</th><th>URI地址</th><th class="tdhide">User-Agent</th><th width="60">状态</th><th width="100">过滤器</th><th class="tdhide">过滤规则</th><th width="100" class="text-right">操作</th></tr></thead>\
<tbody id="LogDayCon"></tbody>\
</table>\
</div>\
</div>\
<div class="page pull-right" id="size_log_page" style="margin-top:10px"></div>\
</div>\
</div>'
});
siteLogCon(siteName, day, 1);
tableFixed("site_waf_log");
});
}
//日志内容
function siteLogCon(siteName, day, page) {
if (!page) page = 1;
var last = page - 1;
var next = page + 1;
var pagehtml = '';
$("#site_waf_log").scrollTop(0);
owPost('get_safe_logs', { siteName: siteName, toDate: day, p: page }, function(data){
var tmp = $.parseJSON(data.data);
if (!tmp.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = tmp.data;
var con = '';
for (var i = 0; i < rdata.length; i++) {
con += '<tr>\
<td class="td0">'+ escapeHTML(rdata[i][0]) + '</td>\
<td class="td1"><a class="btlink" href="javascript:add_log_ip_black(\''+ escapeHTML(rdata[i][1]) + '\');" title="加入黑名单">' + escapeHTML(rdata[i][1]) + '</a></td>\
<td class="td2">'+ escapeHTML(rdata[i][2]) + '</td>\
<td class="td3"><span class="td3txt">'+ escapeHTML(rdata[i][3]) + '</span></td>\
<td class="tdhide td4">'+ escapeHTML(rdata[i][4]) + '</td><td>已拦截</td>\
<td class="td5"><span class="filtertext">'+ escapeHTML(rdata[i][5]) + '</span></td>\
<td class="tdhide td6">'+ escapeHTML(rdata[i][6]) + '</td>\
<td class="text-right"><a href="javascript:;" class="btlink submit_msg" data-index="'+ i +'">误报</a> | <a href="javascript:;" class="btlink btwaf_details" data-index="'+ i +'">详细</a></td>\
</tr>'
}
$("#LogDayCon").html(con);
pagehtml = '<a class="Pstart" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',1)">首页</a><a class="prevPage" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',' + last + ')">上一页</a><a class="nextPage" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',' + next + ')">下一页</a><a class="Pcount">第 ' + page + ' 页</a>';
$("#size_log_page").html(pagehtml);
if (rdata.length < 1) $(".nextPage").hide();
if (last < 1) $(".prevPage").hide();
// 发送误报请求
$(".submit_msg").click(function () {
var _this = $(this);
var res = rdata[$(this).attr('data-index')];
layer.confirm('是否确定提交误报反馈?', { title: '误报反馈',closeBtn:2,icon:3}, function () {
var url_address = res[3];
var rule_arry = res[6].split(" &gt;&gt; ");
var pdata = { url_rule: url_address };
var loadT = layer.msg('正在添加URL白名单..', { icon: 16, time: 0 });
$.post('/plugin?action=a&name=btwaf&s=add_url_white', pdata, function (rdata) {
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
layer.close(loadT);
if (rule_arry[1] != undefined){ $.get('https://www.bt.cn/Api/add_waf_logs?data=' + rule_arry[1],function(rdata){},'jsonp')}
});
});
})
// 详情
$(".btwaf_details").click(function () {
var res = rdata[$(this).attr('data-index')];
var time = res[0]; //时间
var ip_address = res[1]; //IP地址
var req_type = res[2]; // 请求类型
var url_address = res[3]; // 请求类型
var user_agent = res[4]; // 请求类型
var filters = res[5]; //过滤器
var filter_rule = ''; //过滤规则
var rule_arry = res[6].split(" &gt;&gt; ");
var incoming_value = '',risk_value = ''; //传入值,风险值
if(rule_arry.length == 0) filter_rule = rule_arry[0]
incoming_value = rule_arry[1] == undefined?'空':rule_arry[1];
risk_value = incoming_value.match(new RegExp(rule_arry[0].replace(/\//g,'\\/'),'i'));
risk_value = risk_value?risk_value[0]:'空';
layer.open({
type: 1,
title: time + "详情",
area: '600px',
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
<tbody><tr><th>时间</th><td>'+ escapeHTML(time) + '</td><th>用户IP</th><td><a class="btlink" href="javascript:add_log_ip_black(\'' + escapeHTML(ip_address) + '\')" title="加入黑名单">' + escapeHTML(ip_address) + '</a></td></tr><tr><th>类型</th><td>' + escapeHTML(req_type) + '</td><th>过滤器</th><td>' + escapeHTML(filters) + '</td></tr></tbody></table>\
<div><b style="margin-left:10px">URI地址</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(url_address) + '</div></div>\
<div><b style="margin-left:10px">User-Agent</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(user_agent) + '</div></div>\
<div><b style="margin-left:10px">过滤规则</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(rule_arry[0]) + '</div></div>\
<div><b style="margin-left:10px">传入值</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(incoming_value) + '</div></div>\
<div><b style="margin-left:10px">风险值</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(risk_value) + '</div></div>\
</div>'
})
})
$("#LogDayCon td").click(function () {
$(this).parents("tr").addClass("active").siblings().removeClass("active");
});
});
}
function html_encode(value) {
return $('<div></div>').html(value).text();
}
@@ -1543,7 +1558,6 @@ function siteWafConfig(siteName, type) {
function wafSite(){
owPost('get_site_config', {}, function(data){
var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data);
@@ -1553,32 +1567,20 @@ function wafSite(){
i += 1;
tbody += '<tr>\
<td><a onclick="siteWafConfig(\''+ k + '\')" class="sitename btlink" title="' + k + '">' + k + '</a></td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span>\
</td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span></td>\
<td>\
<div class="ssh-item" style="margin-left:0">\
<input class="btswitch btswitch-ios" id="closeget_'+ i + '" type="checkbox" ' + (v.open ? 'checked' : '') + '>\
<label class="btswitch-btn" for="closeget_'+ i + '" onclick="setSiteObjState(\'' + k + '\',\'open\')"></label>\
</div>\
</td>\
<td class="text-right"><a onclick="siteWafLog(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink">设置</a></td>\
</tr>'
<td class="text-right"><a onclick="wafLogs(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink">设置</a></td>\
</tr>';
});
var con = '<div class="lib-box">\
@@ -1610,29 +1612,195 @@ function wafSite(){
});
}
function wafLogRequest(page){
var args = {};
args['page'] = page;
args['page_size'] = 10;
args['site'] = $('select[name="site"]').val();
var query_date = 'today';
if ($('#time_choose').attr("data-name") != ''){
query_date = $('#time_choose').attr("data-name");
} else {
query_date = $('#search_time button.cur').attr("data-name");
}
args['query_date'] = query_date;
args['tojs'] = 'wafLogRequest';
owPost('get_logs_list', args, function(rdata){
var rdata = $.parseJSON(rdata.data);
var list = '';
var data = rdata.data.data;
if (data.length > 0){
for(i in data){
list += '<tr>';
list += '<td><span class="overflow_hide" style="width:112px;">' + getLocalTime(data[i]['time'])+'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['domain'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['ip'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['uri'] +'</span></td>';// data[i]['uri']
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['rule_name'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:200px;">' + entitiesEncode(data[i]['reason']) +'</span></td>';//data[i]['reason']
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
list += '</tr>';
}
} else{
list += '<tr><td colspan="8" style="text-align:center;">封锁日志为空</td></tr>';
}
var table = '<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr>\
<th>时间</th>\
<th>域名</th>\
<th>IP</th>\
<th>URI</th>\
<th>规则名</th>\
<th>原因</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
'+ list +'\
</tbody></table>\
</div>\
<div id="wsPage" class="dataTables_paginate paging_bootstrap page"></div>';
$('#ws_table').html(table);
$('#wsPage').html(rdata.data.page);
$(".tablescroll .details").click(function(){
var index = $(this).attr('data-id');
var res = data[index];
var ip = res.ip;
var time = getLocalTime(res.time);
layer.open({
type: 1,
title: "【"+res.domain + "】详情",
area: '600px',
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
<tbody><tr><th>时间</th><td>'+ time + '</td><th>用户IP</th><td><a class="btlink" href="javascript:addIpBlackArgs(\'' + escapeHTML(ip) + '\')" title="加入黑名单">' + escapeHTML(ip) + '</a></td></tr><tr><th>类型</th><td>' + escapeHTML(res.method) + '</td><th>过滤器</th><td>' + escapeHTML(res.rule_name) + '</td></tr></tbody></table>\
<div><b style="margin-left:10px">URI地址</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.uri) + '</div></div>\
<div><b style="margin-left:10px">User-Agent</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.user_agent) + '</div></div>\
<div><b style="margin-left:10px">过滤规则</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.rule_name) + '</div></div>\
<div><b style="margin-left:10px">Reason</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.reason) + '</div></div>\
</div>'
})
});
});
}
function wafLogs(){
var randstr = getRandomString(10);
function wafHistory(){
var html = '<div>\
<div style="padding-bottom:10px;">\
<span>网站: </span>\
<select class="bt-input-text" name="site" style="margin-left:4px;width:100px;">\
<option value="unset">未设置</option>\
</select>\
<span style="margin-left:10px">时间: </span>\
<div class="input-group" style="margin-left:10px;width:350px;display: inline-table;vertical-align: top;">\
<div id="search_time" class="input-group-btn btn-group-sm">\
<button data-name="today" type="button" class="btn btn-default">今日</button>\
<button data-name="yesterday" type="button" class="btn btn-default">昨日</button>\
<button data-name="l7" type="button" class="btn btn-default">近7天</button>\
<button data-name="l30" type="button" class="btn btn-default">近30天</button>\
</div>\
<span class="last-span"><input data-name="" type="text" id="time_choose" lay-key="1000001_'+randstr+'" class="form-control btn-group-sm" autocomplete="off" placeholder="自定义时间" style="display: inline-block;font-size: 12px;padding: 0 10px;height:30px;width: 200px;"></span>\
</div>\
<div style="float:right;"><button id="UncoverAll" class="btn btn-success btn-sm">解封所有</button></div>\
</div>\
<div class="divtable mtb10" id="ws_table"></div>\
</div>';
$(".soft-man-con").html(html);
// wafLogRequest(1);
$("#UncoverAll").click(function(){
owPost('clean_drop_ip',{},function(data){
var rdata = $.parseJSON(data.data);
var ndata = $.parseJSON(rdata.data);
if (ndata.status == 0){
layer.msg("解封所有成功",{icon:1,time:2000,shade: [0.3, '#000']});
} else{
layer.msg("解封所有异常:"+ndata.msg,{icon:5,time:2000,shade: [0.3, '#000']});
}
});
});
//日期范围
laydate.render({
elem: '#time_choose',
value:'',
range:true,
done:function(value, startDate, endDate){
if(!value){
return false;
}
$('#search_time button').each(function(){
$(this).removeClass('cur');
});
var timeA = value.split('-');
var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2])
var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5])
query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00")
$('#time_choose').attr("data-name",query_txt);
$('#time_choose').addClass("cur");
wafLogRequest(1);
},
});
$('#search_time button:eq(0)').addClass('cur');
$('#search_time button').click(function(){
$('#search_time button').each(function(){
if ($(this).hasClass('cur')){
$(this).removeClass('cur');
}
});
$('#time_choose').attr("data-name",'');
$('#time_choose').removeClass("cur");
$(this).addClass('cur');
wafLogRequest(1);
});
owPost('get_default_site',{},function(rdata){
$('select[name="site"]').html('');
var rdata = $.parseJSON(rdata.data);
var rdata = rdata.data;
var default_site = rdata["default"];
var select = '';
for (var i = 0; i < rdata["list"].length; i++) {
if (default_site == rdata["list"][i]){
select += '<option value="'+rdata["list"][i]+'" selected>'+rdata["list"][i]+'</option>';
} else{
select += '<option value="'+rdata["list"][i]+'">'+rdata["list"][i]+'</option>';
}
}
$('select[name="site"]').html(select);
wafLogRequest(1);
$('select[name="site"]').change(function(){
wafLogRequest(1);
});
});
var con = '<button class="btn btn-success btn-sm" onclick="UncoverAll()">解封所有</button>';
con += '<div class="divtable mt10">\
<table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">开始时间</th>\
<th width="44%">IP</th>\
<th width="10%">站点</th>\
<th width="10%">封锁原因</th>\
<th width="10%">封锁时长</th>\
<th style="text-align: center;" width="10%">状态</th>\
</thead>\
</table>\
</div>';
$(".soft-man-con").html(con);
}
function wafLogs(){
function wafOpLogs(){
var con = '<div class="divtable">\
<table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">名称</th>\
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
# echo $rootPath
resty=$rootPath/openresty/bin/resty
RUN_CMD=$resty
if [ ! -f $resty ];then
RUN_CMD=/www/server/openresty/bin/resty
fi
# test
# $RUN_CMD simple.lua
# $RUN_CMD test_gsub.lua
# $RUN_CMD --shdict 'limit 10m' test_find_server_name.lua
# $RUN_CMD --stap --shdict 'limit 10m' test_find_server_name.lua
# $RUN_CMD test_rand.lua
$RUN_CMD test_ffi_time.lua
+18
View File
@@ -0,0 +1,18 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
collectgarbage()
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed: ", (ngx.now() - begin) / N)
+62
View File
@@ -0,0 +1,62 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local ffi = require("ffi")
ffi.cdef[[
struct timeval {
long int tv_sec;
long int tv_usec;
};
int gettimeofday(struct timeval *tv, void *tz);
]];
local tm = ffi.new("struct timeval");
-- 返回微秒级时间戳
local function current_time_millis()
ffi.C.gettimeofday(tm,nil);
local sec = tonumber(tm.tv_sec);
local usec = tonumber(tm.tv_usec);
return sec + usec * 10^-6;
end
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed[1]: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = current_time_millis()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("ffi elapsed: ", (current_time_millis() - begin) / N)
@@ -0,0 +1,75 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local config_domains = {
[1] = {
["name"] = "t1.cn",
["path"] = "/www/wwwroot/t1.cn",
["domains"] = {
[1] = "t1.cn",
[2] = "t3.cn"
}
}
}
local function get_server_name(request_name)
for _,v in ipairs(config_domains)
do
for _,cd_name in ipairs(v['domains'])
do
if request_name == cd_name then
return v['name']
end
end
end
return request_name
end
local function get_server_name_cache(request_name)
local cache_name = ngx.shared.limit:get(request_name)
if cache_name then return cache_name end
for _,v in ipairs(config_domains)
do
for _,cd_name in ipairs(v['domains'])
do
if request_name == cd_name then
ngx.shared.limit:set(cd_name,v['name'],3600)
return v['name']
end
end
end
return request_name
end
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
get_server_name("t3.cn")
end
ngx.update_time()
ngx.say("test get_server_name elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
get_server_name_cache("t3.cn")
end
ngx.update_time()
ngx.say("test get_server_name_cache elapsed: ", (ngx.now() - begin) / N)
+47
View File
@@ -0,0 +1,47 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local function test_string_gsub(str,reps)
local resultStrList = {}
string.gsub(str,'[^'..reps..']+', function(w)
table.insert(resultStrList,w)
return w
end)
end
local function test_ngx_string_gsub(str,reps)
local resultStrList = {}
ngx.re.gsub(str,'[^'..reps..']+', function(w)
table.insert(resultStrList,w[0])
return w
end, "ijo")
end
ngx.update_time()
local begin = ngx.now()
local N = 1e6
for i = 1, N do
test_string_gsub("2409:8a62:e20:95f0:45b7:233e:f003:c0ab",",")
end
ngx.update_time()
ngx.say("test_string_gsub elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e6
for i = 1, N do
test_ngx_string_gsub("2409:8a62:e20:95f0:45b7:233e:f003:c0ab",",")
end
ngx.update_time()
ngx.say("test_ngx_string_gsub elapsed: ", (ngx.now() - begin) / N)
+72
View File
@@ -0,0 +1,72 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local function get_random_t1(n)
math.randomseed(ngx.time())
local t = {
"0","1","2","3","4","5","6","7","8","9",
"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t",
"u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z",
}
local s = ""
for i = 1, n do
s = s .. t[math.random(#t)]
end
return s
end
local function get_random_t2(n)
local t = {
"0","1","2","3","4","5","6","7","8","9",
"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t",
"u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z",
}
local s = ""
for i = 1, n do
s = s .. t[math.random(#t)]
end
return s
end
ngx.update_time()
local begin = ngx.now()
local N = 1e5
for i = 1, N do
get_random_t1(16)
end
ngx.update_time()
ngx.say("test get_random_t1 elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e5
math.randomseed(ngx.time())
for i = 1, N do
get_random_t2(16)
end
ngx.update_time()
ngx.say("test get_random_t2 elapsed: ", (ngx.now() - begin) / N)

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