Compare commits

...
407 Commits
Author SHA1 Message Date
Mr Chen 63e427b488 Merge pull request #445 from midoks/dev
0.16.0
2023-08-30 23:26:30 +08:00
midoks c688c692f9 0.16.0
yum install -y libargon2-devel
apt install -y libargon2-dev

OP防火墙 - 重载即可

* 增加PHP83。
* 面板日志单独为一页并加入日志审计功能。
* 修复webssh服务器读取问题。
* 站点批量删除修复。
* OP防火墙-修复`自动强制验证`关闭不生效。
* 新增OneDrive备份插件。
* FTP备份优化。
2023-08-30 23:24:49 +08:00
midoks c9f074b319 FTP备份优化 2023-08-30 20:48:54 +08:00
midoks 38b4042c5a Update msonedrive.js 2023-08-30 19:51:52 +08:00
midoks bf32390f0e Update README.md 2023-08-30 18:40:21 +08:00
midoks 91a9be4cc0 Update mw.py 2023-08-30 18:26:08 +08:00
midoks be5f438f84 Delete config.conf 2023-08-30 17:47:38 +08:00
midoks 2705fd7ba2 Update config_api.py 2023-08-30 17:45:21 +08:00
midoks 4de7e72f0a Update test.py 2023-08-30 17:37:49 +08:00
midoks da668c723c onedrive插件OK 2023-08-30 17:35:41 +08:00
midoks 20624217bf Update backup.py 2023-08-30 15:11:17 +08:00
midoks 2403af08c6 Update crontab.js 2023-08-30 13:35:52 +08:00
midoks 2350b73896 Update layout.html 2023-08-28 23:50:14 +08:00
midoks 464fa9cc0f Update cert_api.py 2023-08-28 23:06:16 +08:00
midoks 9a79f0b728 Update README.md 2023-08-28 22:57:47 +08:00
midoks 52cfff7038 OP防火墙-修复自动强制验证关闭不生效。 2023-08-28 22:50:03 +08:00
midoks 8d42f8137c Update .gitignore 2023-08-28 11:45:37 +08:00
midoks 41fb9759a3 Create readme.md 2023-08-28 11:38:44 +08:00
midoks 7d3833b2ef Update index.py 2023-08-27 19:56:17 +08:00
midoks 0badb053e0 站点批量删除修复。 2023-08-27 19:46:56 +08:00
midoks 80b9e7cbf7 Update index.py 2023-08-27 19:00:13 +08:00
midoks 94df21192f Update dynamic-tracking.js 2023-08-27 18:50:25 +08:00
midoks 346d687368 Update simple_trace.sh 2023-08-27 18:34:47 +08:00
midoks 46ec655365 Update simple_trace.sh 2023-08-27 18:28:52 +08:00
midoks e852020c38 Update simple_trace.sh 2023-08-27 17:51:18 +08:00
midoks d06e83676b Update simple_trace.sh 2023-08-27 17:50:32 +08:00
midoks 7a511f8217 Update dynamic-tracking.js 2023-08-27 17:09:49 +08:00
midoks 8c5021b9dc Update simple_trace.sh 2023-08-27 16:48:05 +08:00
midoks b7d50540ac Create ubuntu.sh 2023-08-27 16:45:06 +08:00
midoks 2a95fcc59a Update install.sh 2023-08-27 16:29:52 +08:00
midoks 2b04cb3947 Update dynamic-tracking.js 2023-08-27 16:17:15 +08:00
midoks 7f0ad25342 Update simple_macosx_trace.sh 2023-08-27 15:51:42 +08:00
midoks 09f7e6f5b5 update 2023-08-27 15:50:52 +08:00
midoks 17a7ffa0b4 update 2023-08-27 15:38:00 +08:00
midoks ba6dcabd04 Update simple_trace.sh 2023-08-27 14:29:17 +08:00
midoks 0ff5c170d3 update 2023-08-27 14:28:26 +08:00
midoks b78e020993 Update index.py 2023-08-26 23:14:06 +08:00
midoks 9586eeda07 up 2023-08-26 23:02:17 +08:00
midoks ea462aa51d update 2023-08-26 22:43:13 +08:00
midoks aaac8b5239 文件管理-svg预览优化 2023-08-26 22:38:27 +08:00
midoks 2b86c375b0 动态追踪- svg查看功能 2023-08-26 22:23:13 +08:00
midoks 600e2688f9 update 2023-08-26 21:11:34 +08:00
midoks 3537bc520f Update dynamic-tracking.js 2023-08-26 17:47:06 +08:00
midoks 9ffdffadd6 Update README.md 2023-08-26 17:42:59 +08:00
midoks 3942f2fbf5 Update index.py 2023-08-26 17:35:48 +08:00
midoks 8ff2f217b3 Update index.py 2023-08-26 17:23:34 +08:00
midoks 480bd154c6 Update index.py 2023-08-26 17:21:20 +08:00
midoks 5eb3ed4524 Update README.md 2023-08-26 16:49:19 +08:00
midoks 50e78ae6f6 Update logs.html 2023-08-26 16:22:08 +08:00
midoks 0ec9b31c2f update 2023-08-26 16:17:54 +08:00
midoks 191b54821e Update logs_api.py 2023-08-26 16:07:19 +08:00
midoks c2188a2c7e update 2023-08-26 16:04:35 +08:00
midoks d23b64a92c Update update_dev.sh 2023-08-26 16:03:29 +08:00
midoks 3ae97e1c75 Update config_api.py 2023-08-26 15:59:04 +08:00
midoks f0e7361436 Update logs_api.py 2023-08-26 15:57:54 +08:00
midoks 5f85d41352 日志审计转移完成 2023-08-26 15:55:09 +08:00
midoks 6fc8803446 update 2023-08-26 00:29:44 +08:00
midoks b3120f3435 日志功能从防火墙提出来 2023-08-26 00:24:04 +08:00
midoks f9f1b1a113 update 2023-08-25 21:21:58 +08:00
midoks 2645297cee update 2023-08-25 21:20:56 +08:00
midoks 7f171f5986 update 2023-08-25 20:56:53 +08:00
midoks c3b3e3b01c update 2023-08-25 16:55:44 +08:00
midoks 3824b394ad php argon2 2023-08-25 16:55:32 +08:00
midoks 270660fb53 update 2023-08-25 15:26:23 +08:00
midoks c4171a9506 Update install.sh 2023-08-25 15:09:54 +08:00
midoks 222943e312 Update index.py 2023-08-24 22:35:44 +08:00
midoks 92f8a4e949 Update mw.tpl 2023-08-24 22:12:02 +08:00
midoks eff1f55a21 Update cli.sh 2023-08-24 22:10:43 +08:00
midoks 0b54da9747 Update freebsd.sh 2023-08-24 21:39:29 +08:00
midoks 0bec57937f Update index.py 2023-08-24 21:31:35 +08:00
midoks 6c64f8ee5e Update install.sh 2023-08-24 21:25:15 +08:00
midoks b65ad9de80 Update install.sh 2023-08-24 21:18:49 +08:00
midoks 07be263d81 Update install.sh 2023-08-24 21:12:53 +08:00
midoks bf9cb52fec Update index.py 2023-08-24 21:07:42 +08:00
midoks f7135a6ded Update index.py 2023-08-24 21:02:36 +08:00
midoks 7b98dde1aa Update index.py 2023-08-24 21:02:26 +08:00
midoks b51f3fdd68 update 2023-08-24 21:00:47 +08:00
midoks e02c52df49 Update freebsd.sh 2023-08-24 20:58:26 +08:00
midoks 730bc7171b Update index.py 2023-08-24 20:55:57 +08:00
midoks c065eabb48 Update index.py 2023-08-24 20:47:49 +08:00
midoks 1ad1e3326d php扩展库读取优化 2023-08-24 20:45:25 +08:00
midoks d4346a51bc Update crontab_api.py 2023-08-24 20:22:53 +08:00
midoks 8260cc5f4a Update crontab_api.py 2023-08-24 20:12:50 +08:00
midoks 021b299b7d Update mw.tpl 2023-08-24 20:09:53 +08:00
midoks a767e7e578 Update index.py 2023-08-24 20:05:08 +08:00
midoks 57da2aef27 Update freebsd.sh 2023-08-24 19:48:06 +08:00
midoks 5b43438cb1 Update index.py 2023-08-24 19:46:02 +08:00
midoks 7ab88a1bea Update index.py 2023-08-24 19:05:11 +08:00
midoks 31291a13c7 Update index.py 2023-08-24 18:58:59 +08:00
midoks 43d0b75d98 Update index.py 2023-08-24 18:58:35 +08:00
midoks 5490197b8a Update index.py 2023-08-24 18:58:16 +08:00
midoks 8f03574bce update 2023-08-24 18:56:19 +08:00
midoks 94487e0b3d Update index.py 2023-08-24 18:54:09 +08:00
midoks 45cc0159af Update index.py 2023-08-24 18:48:07 +08:00
midoks 504a618eb1 Update index.py 2023-08-24 18:33:48 +08:00
midoks 5e25849464 Update index.py 2023-08-24 18:33:22 +08:00
midoks 9bb59a1559 Update index.py 2023-08-24 18:10:07 +08:00
midoks 6883316efc Update index.py 2023-08-24 18:09:16 +08:00
midoks de7ea503e5 update 2023-08-24 18:03:23 +08:00
midoks 4fcad95c79 Update index.py 2023-08-24 15:28:10 +08:00
midoks 75dc1bd70d Update freebsd.sh 2023-08-24 15:18:38 +08:00
midoks 44758e3e55 Update index.py 2023-08-24 15:02:20 +08:00
midoks 140624e62f Update index.py 2023-08-24 14:47:01 +08:00
midoks 65f90b473c Update index.py 2023-08-24 14:44:59 +08:00
midoks 0a089fcedf Update index.py 2023-08-24 14:41:58 +08:00
midoks 010624023f update 2023-08-24 14:39:32 +08:00
midoks 9399a14a92 update 2023-08-24 12:52:10 +08:00
midoks 2875b40e62 Update README.md 2023-08-23 20:15:28 +08:00
midoks 78c3686091 Update freebsd.sh 2023-08-23 13:12:29 +08:00
midoks d7447197ec Update freebsd.sh 2023-08-22 19:58:23 +08:00
midoks 9b64ec5c6d Update freebsd.sh 2023-08-22 18:48:18 +08:00
midoks dad51dad77 Update files_api.py 2023-08-22 18:48:07 +08:00
midoks d89751f733 update 2023-08-22 18:25:46 +08:00
midoks 1dc486711b Update install.sh 2023-08-22 17:42:34 +08:00
midoks 60a2f85f02 Update install.sh 2023-08-22 17:41:57 +08:00
midoks 830d387ddb up 2023-08-22 17:37:53 +08:00
midoks ae225780f9 Update system_api.py 2023-08-22 17:27:21 +08:00
midoks e0a0a82d68 update 2023-08-22 17:25:54 +08:00
midoks 0b23c5f330 update 2023-08-22 17:18:32 +08:00
midoks fb01c68f5a Update mw.py 2023-08-22 17:09:26 +08:00
midoks 5755121fa5 Update mw.py 2023-08-22 17:05:23 +08:00
midoks 3d1c613864 Update mw.py 2023-08-22 17:02:39 +08:00
midoks 9590c4bb7d Update mw.py 2023-08-22 17:01:45 +08:00
midoks 32c0bdf093 Update system_api.py 2023-08-22 16:52:15 +08:00
midoks 4f5424a746 Update freebsd.sh 2023-08-22 16:36:56 +08:00
midoks 81ba3bce9d Update freebsd.sh 2023-08-22 16:21:24 +08:00
midoks 22b3a1bc42 Update op_waf.js 2023-08-21 23:15:10 +08:00
midoks df9a34aa31 Update index.py 2023-08-21 22:33:33 +08:00
midoks 2400213533 up 2023-08-21 22:20:51 +08:00
midoks 465eb118a9 0.16.0
改版为【老子面板】
2023-08-21 20:28:06 +08:00
midoks 7e81aa109f Update all_test.sh 2023-08-21 19:49:47 +08:00
midoks b23b41c7a7 Update phplib.conf 2023-08-21 19:22:19 +08:00
midoks 724a77ae81 Update install.sh 2023-08-21 19:17:37 +08:00
midoks 3499ed74ee Update info.json 2023-08-21 19:13:36 +08:00
midoks 52997049e2 Update layout.html 2023-08-21 19:11:28 +08:00
midoks a96a36b087 Create install.sh 2023-08-21 19:02:52 +08:00
midoks 5926f688a6 Update macos.sh 2023-08-21 00:41:26 +08:00
midoks 1b754f5c43 Update push_notice_msg.py 2023-08-21 00:12:30 +08:00
midoks c4c20de520 Update install.sh 2023-08-20 22:37:42 +08:00
midoks 616895785f Update init_cmd.py 2023-08-20 20:37:30 +08:00
midoks 29d6c8740a Update receive_music163_search.py 2023-08-20 20:35:33 +08:00
midoks 64aa9a9d01 Update receive_music163_search.py 2023-08-20 19:46:30 +08:00
midoks ffbe8ba6d4 Update receive_music163_search.py 2023-08-20 19:41:04 +08:00
midoks ed39c5d243 Update receive_music163_search.py 2023-08-20 16:56:48 +08:00
midoks 4bb2115040 Update receive_music163_search.py 2023-08-20 15:32:16 +08:00
midoks 6b0cf8129d Update receive_music163_search.py 2023-08-20 15:11:19 +08:00
midoks ab7bbe942b Update receive_music163_search.py 2023-08-20 15:11:01 +08:00
midoks a8a3fa1754 update 2023-08-20 15:10:58 +08:00
midoks e343f33b47 Update receive_faq.py 2023-08-20 14:58:48 +08:00
midoks f55367ab5e Update index.py 2023-08-20 00:26:17 +08:00
midoks 050bd158c1 update 2023-08-20 00:25:46 +08:00
midoks d35a680fec update 2023-08-19 20:11:08 +08:00
midoks 4a4ddeaabe Update system_api.py 2023-08-19 00:17:23 +08:00
midoks 0e74b0cccf Update system_api.py 2023-08-19 00:15:39 +08:00
midoks 806e29577e Update system_api.py 2023-08-19 00:14:47 +08:00
midoks 75923f5363 Update system_api.py 2023-08-19 00:13:19 +08:00
midoks 834196883c Update index.py 2023-08-18 00:53:15 +08:00
midoks 341826c641 Update index.py 2023-08-18 00:52:28 +08:00
midoks 1bd1ce5b31 Update index.py 2023-08-18 00:42:20 +08:00
Mr Chen eef504e172 Merge pull request #442 from midoks/dev
OP防火墙测试功能修复
2023-08-18 00:20:06 +08:00
midoks a0434ef7d6 Update index.py 2023-08-18 00:13:17 +08:00
midoks 893bbb8ea7 Update install.sh 2023-08-17 22:49:01 +08:00
midoks 92e3e277cc Update info.json 2023-08-17 21:38:44 +08:00
midoks 58e48bf013 Update info.json 2023-08-17 21:36:41 +08:00
midoks 644760d5b0 update 2023-08-17 21:35:37 +08:00
midoks d6ccd81def 动态追踪 - 专业人员使用 2023-08-17 21:29:54 +08:00
Mr Chen d32e71b2d9 Merge pull request #441 from midoks/dev
centos9 mysql8安装需要patchelf
2023-08-17 18:43:28 +08:00
midoks ae9e56c56c Update rhel.sh 2023-08-17 18:41:42 +08:00
midoks d7c0285bbf Update rhel.sh 2023-08-17 18:38:43 +08:00
midoks 5cc0957ffd Update rhel.sh 2023-08-17 18:38:18 +08:00
Mr Chen 1e44d64ace Merge pull request #440 from midoks/dev
mysql安装优化
2023-08-17 17:55:46 +08:00
midoks 907851c413 update 2023-08-17 17:29:04 +08:00
midoks 0faafc654b Update install.sh 2023-08-17 16:58:36 +08:00
Mr Chen 4cdc399b77 Merge pull request #439 from midoks/dev
mongodb脚本升级和检查openresty状态优化
2023-08-17 16:25:46 +08:00
midoks a085e5b1ea Update mw.py 2023-08-17 16:20:07 +08:00
midoks bdbf4dddc6 Update mongodb.tpl 2023-08-17 15:39:45 +08:00
midoks 5cee2f2b6d mongodb centos 2023-08-17 15:36:13 +08:00
Mr Chen b9652a7940 Merge pull request #437 from midoks/dev
0.15.4
2023-08-17 14:53:59 +08:00
midoks dc7ddbcf6b up 2023-08-17 14:52:52 +08:00
midoks 87a8bfe59e Update freebsd.sh 2023-08-17 13:49:30 +08:00
midoks cfdd5e5f73 Update freebsd.sh 2023-08-17 13:48:38 +08:00
midoks e2acf621ca Update freebsd.sh 2023-08-17 13:46:21 +08:00
midoks 0711a922d2 Update freebsd.sh 2023-08-17 13:45:05 +08:00
midoks 055ea0ca0c Update README.md 2023-08-17 13:23:26 +08:00
midoks 772d9c50f6 update 2023-08-17 13:18:46 +08:00
midoks 0809b51725 updaate 2023-08-17 12:27:31 +08:00
midoks 4e901e6750 update 2023-08-17 11:51:01 +08:00
midoks 5c62397234 update 2023-08-17 11:39:40 +08:00
midoks 63021a3eab Create centos.sh 2023-08-17 11:35:02 +08:00
midoks e617b07790 update 2023-08-17 11:32:03 +08:00
midoks 960eeed4ce update 2023-08-17 11:18:25 +08:00
midoks ccf020bf6b Update index.py 2023-08-17 11:14:56 +08:00
midoks c4918d8cd7 update 2023-08-17 11:09:50 +08:00
midoks b3d3ceb058 update 2023-08-17 11:02:39 +08:00
midoks 17a301c745 update 2023-08-17 00:56:07 +08:00
midoks 1bfa2ae3ab update 2023-08-17 00:52:43 +08:00
midoks 9be5dcfd8a Update index.py 2023-08-17 00:47:29 +08:00
midoks d9e8f1d4ad Update ubuntu.sh 2023-08-17 00:43:22 +08:00
midoks d85f544773 Create ubuntu.sh 2023-08-17 00:35:43 +08:00
midoks 577ac1f8ee Update debian.sh 2023-08-17 00:24:02 +08:00
midoks ed117a1b40 Update debian.sh 2023-08-17 00:21:44 +08:00
midoks 9d54f0b6cd Create debian.sh 2023-08-17 00:19:23 +08:00
midoks 707eced7bf Create debian.sh 2023-08-17 00:16:28 +08:00
midoks dd96833c09 Update index.py 2023-08-17 00:10:38 +08:00
midoks 4c61143918 update 2023-08-17 00:04:19 +08:00
midoks 8cb8a1bc70 update 2023-08-16 23:20:22 +08:00
midoks c55c3c23d1 up 2023-08-16 22:37:31 +08:00
midoks 04e6b9367a Update index.py 2023-08-16 22:24:41 +08:00
midoks f4f25b8ab3 Update index.py 2023-08-16 22:20:12 +08:00
midoks a0b0b9b294 update 2023-08-16 22:18:31 +08:00
midoks 699ad0b8ca Update debian.sh 2023-08-16 22:11:39 +08:00
midoks a45eaf1c3b Update debian.sh 2023-08-16 22:09:35 +08:00
midoks 0f51a6d481 update 2023-08-16 22:06:43 +08:00
midoks 142d5f7ed8 update 2023-08-16 22:00:57 +08:00
midoks 72bd528a24 update 2023-08-16 21:40:41 +08:00
midoks af2dc0585b up 2023-08-16 18:27:12 +08:00
midoks 0a0021b09d Update install.sh 2023-08-16 13:46:00 +08:00
midoks c5811d4494 Update install.sh 2023-08-16 12:11:11 +08:00
midoks e329892cd2 Update openssl.sh 2023-08-16 11:32:40 +08:00
midoks 368324a813 Update install.sh 2023-08-16 11:28:52 +08:00
midoks 6a7cc4f054 Update install.sh 2023-08-16 11:27:54 +08:00
midoks 1d3cba599c Update install.sh 2023-08-16 11:15:14 +08:00
midoks 7d902a50eb Update install.sh 2023-08-16 11:09:48 +08:00
midoks 25feb7c0ad Update install.sh 2023-08-16 11:07:32 +08:00
midoks e15d1716e5 Update install.sh 2023-08-16 11:02:48 +08:00
midoks ee16e0142e Update install.sh 2023-08-16 10:59:15 +08:00
midoks 68e06aa8f5 u 2023-08-16 10:52:58 +08:00
midoks d88003ca52 Update install.sh 2023-08-16 03:55:40 +08:00
midoks 8757c646f6 Update index.py 2023-08-16 03:49:13 +08:00
midoks c3e9d8aa4c update 2023-08-16 03:45:39 +08:00
midoks 7e3983f612 update 2023-08-16 03:25:46 +08:00
midoks a4e43b492d OP防火墙-加入地区限制 2023-08-16 02:53:29 +08:00
midoks 1f57517ea7 Update push_notice_msg.py 2023-08-15 09:47:44 +08:00
midoks b2fe35771d up 2023-08-15 00:00:44 +08:00
midoks 00ce3e00d3 update 2023-08-14 20:16:16 +08:00
midoks c7c28731a4 update 2023-08-14 19:42:08 +08:00
midoks 3305eab770 update 2023-08-14 18:30:29 +08:00
midoks b595359f38 Update index.py 2023-08-14 18:29:00 +08:00
midoks 5dc06b90ca Update init.lua 2023-08-14 12:56:59 +08:00
midoks 651fa7672c Update layout.html 2023-08-14 11:53:53 +08:00
midoks 7a0db5abef Update layout.html 2023-08-14 11:52:51 +08:00
midoks d21a5dfacc Update push_notice_msg.py 2023-08-14 09:15:50 +08:00
midoks 0c49749b63 Update waf_maxminddb.lua 2023-08-14 00:11:02 +08:00
midoks 11bb65a739 Update index.py 2023-08-13 22:03:55 +08:00
midoks ce44353cbf debug 1 2023-08-13 21:13:13 +08:00
midoks 2e5c5ef5b9 update 2023-08-13 18:32:30 +08:00
Mr Chen d1b687476b Merge pull request #436 from midoks/dev
0.15.4
2023-08-13 16:08:33 +08:00
midoks a46eabce10 update 2023-08-13 16:06:40 +08:00
midoks 08e378a3e4 Update push_ad.py 2023-08-13 16:02:29 +08:00
midoks c80ce63a4b Update push_notice_msg.py 2023-08-13 16:02:07 +08:00
midoks 72bb94df42 Update README.md 2023-08-13 15:26:45 +08:00
midoks e9b7aca47a Update imagemagick.sh 2023-08-13 15:20:26 +08:00
midoks f25d4f5a4f Update imagemagick.sh 2023-08-13 15:18:25 +08:00
midoks 59fcef76fe Update imagemagick.sh 2023-08-13 15:15:10 +08:00
midoks 4ab6ccbcbb Update imagemagick.sh 2023-08-13 15:14:22 +08:00
midoks fd457df3c8 up 2023-08-13 15:04:54 +08:00
midoks 147bec02a5 Update phplib.conf 2023-08-13 14:58:38 +08:00
midoks 34c126fbb7 Update ioncube.sh 2023-08-13 14:57:41 +08:00
midoks 4d21c920a8 Update all_test.sh 2023-08-13 14:56:25 +08:00
midoks 2d810fe7ab Update opcache.sh 2023-08-13 14:52:34 +08:00
midoks fb5260b9a5 Update opcache.sh 2023-08-13 14:50:24 +08:00
midoks 32b5542534 Update all_test.sh 2023-08-13 14:46:15 +08:00
midoks c665486122 Update redis.sh 2023-08-13 14:44:11 +08:00
midoks d3b885b1f9 Update redis.sh 2023-08-13 14:43:45 +08:00
midoks e476e36420 Update solr.sh 2023-08-13 14:37:24 +08:00
midoks 587503dc67 Update solr.sh 2023-08-13 14:31:18 +08:00
midoks cecfe9470f Update imagemagick.sh 2023-08-13 14:23:54 +08:00
midoks abc37acacc Update all_test.sh 2023-08-13 14:18:56 +08:00
midoks e0197fef3a Update eaccelerator.sh 2023-08-13 14:13:32 +08:00
midoks 04c4e7ddc8 Update xdebug.sh 2023-08-13 14:10:08 +08:00
midoks 6fb3e29a91 Update intl.sh 2023-08-13 14:01:10 +08:00
midoks 66fe66b479 update 2023-08-13 13:59:07 +08:00
midoks 4329d2470c update 2023-08-13 13:57:46 +08:00
midoks 0cd4527234 Update phalcon.sh 2023-08-13 13:44:07 +08:00
midoks bdba9149f2 update 2023-08-13 13:43:04 +08:00
midoks e05f7a9c3f Update seaslog.sh 2023-08-13 13:41:46 +08:00
midoks bddd81c94d Update zlib.sh 2023-08-13 13:40:54 +08:00
midoks f470392382 Update swoole.sh 2023-08-13 13:39:55 +08:00
midoks 895a250f06 update 2023-08-13 13:39:14 +08:00
midoks dd579b7e5c update 2023-08-13 13:33:47 +08:00
midoks cd0653d092 Update memcache.sh 2023-08-13 13:32:37 +08:00
midoks f2bc938ade Update memcache.sh 2023-08-13 13:32:18 +08:00
midoks dc694cae35 Update gettext.sh 2023-08-13 13:30:44 +08:00
midoks 0b98e40fec Update iconv.sh 2023-08-13 13:29:34 +08:00
midoks 10c40800ff Update mcrypt.sh 2023-08-13 13:28:38 +08:00
midoks 424d9fa799 Update intl.sh 2023-08-13 13:28:06 +08:00
midoks 1350fc7a4a Update gd_old.sh 2023-08-13 13:26:22 +08:00
midoks d678ade262 Update pcntl.sh 2023-08-13 13:24:54 +08:00
midoks 0b0b0bc9c5 Update bcmath.sh 2023-08-13 13:22:46 +08:00
midoks f3eee40e1e Update openssl.sh 2023-08-13 12:15:43 +08:00
midoks 8e0327a084 Update openssl.sh 2023-08-13 12:14:23 +08:00
midoks 0a4b5529b9 Update install.sh 2023-08-13 11:59:08 +08:00
midoks a8c17e1f3c update 2023-08-13 11:55:33 +08:00
midoks 4d242dd322 update 2023-08-13 11:49:54 +08:00
midoks 272a08f4eb Update install.sh 2023-08-13 11:45:15 +08:00
midoks 453009da40 Update install.sh 2023-08-13 11:39:20 +08:00
midoks 9c8880e1bb Update install.sh 2023-08-13 10:49:24 +08:00
midoks 4f716830ef update 2023-08-13 10:46:54 +08:00
midoks b4d799f8bd up 2023-08-13 10:14:22 +08:00
midoks e9fc7d5344 up 2023-08-13 01:42:50 +08:00
midoks 585d3d1839 Update install.sh 2023-08-13 00:12:35 +08:00
midoks 3278dd23b5 Update install.sh 2023-08-13 00:08:50 +08:00
midoks 5b406eaeb1 Update my8.0.cnf 2023-08-12 21:48:48 +08:00
midoks 0a354f649d mysql添加可过滤的同步错误 2023-08-12 21:11:32 +08:00
midoks 176dd4a5b8 Update install.sh 2023-08-12 20:13:44 +08:00
midoks 4bb9cc2d67 Update config_api.py 2023-08-12 17:05:12 +08:00
midoks f1edb26540 up 2023-08-12 17:04:56 +08:00
midoks 0692537cbd update 2023-08-12 16:41:15 +08:00
midoks 0710ca590a Update ubuntu.sh 2023-08-12 15:46:44 +08:00
midoks c19b12e8df Update swoole.sh 2023-08-12 15:37:40 +08:00
midoks 99eeee19ef Update all_test.sh 2023-08-12 15:19:10 +08:00
midoks fff3707031 Update solr.sh 2023-08-12 15:11:49 +08:00
midoks 0d0cb4add1 Update phalcon.sh 2023-08-12 15:06:52 +08:00
midoks 5ed37443da Update phalcon.sh 2023-08-12 14:47:18 +08:00
midoks 25b836e6f5 Update memcached.sh 2023-08-12 14:43:40 +08:00
midoks 4ca5c8e1a8 Merge branch 'master' into dev 2023-08-12 14:38:18 +08:00
midoks b522287a87 Merge branch 'master' into dev 2023-08-12 14:37:36 +08:00
Mr Chen 05cec7e0bf Merge pull request #435 from msycn/master
修复Openssl 1.1.1 重大漏洞/更新MySQL到8.0.34/更新php到8.2.8/更新redis到7.0.12
2023-08-12 14:36:42 +08:00
msycn b731868e06 Update openssl.sh 1.1.1 to 3.0.10
最新的稳定版本是 3.1 系列,支持到 2025 年 3 月 14 日。还提供 3.0 系列,它是长期支持 (LTS) 版本,支持到 2026 年 9 月 7 日。之前的 LTS 版本(1.1.1 系列)是 也可用并支持到 2023 年 9 月 11 日。所有旧版本(包括 1.1.0、1.0.2、1.0.0 和 0.9.8)现已不再支持,不应使用。 我们鼓励这些旧版本的用户尽快升级到3.1或3.0。 提供了对 1.0.2 的扩展支持,以获取该版本的安全修复程序。

The latest stable version is the 3.1 series supported until 14th March 2025. Also available is the 3.0 series which is a Long Term Support (LTS) version and is supported until 7th September 2026. The previous LTS version (the 1.1.1 series) is also available and is supported until 11th September 2023. All older versions (including 1.1.0, 1.0.2, 1.0.0 and 0.9.8) are now out of support and should not be used. Users of these older versions are encouraged to upgrade to 3.1 or 3.0 as soon as possible. Extended support for 1.0.2 to gain access to security fixes for that version is available.
2023-08-12 00:57:04 +08:00
msycn 9c4ceca41f Update install.sh 8.2.7 to 8.2.8
Version 8.2.8
06 Jul 2023
CLI:
Fixed bug GH-11246 (cli/get_set_process_title fails on MacOS).
Core:
Fixed build for the riscv64 architecture/GCC 12.
Curl:
Fixed bug GH-11433 (Unable to set CURLOPT_ACCEPT_ENCODING to NULL).
Date:
Fixed bug GH-11455 (Segmentation fault with custom object date properties).
DOM:
Fixed bugs GH-11288 and GH-11289 and GH-11290 and GH-9142 (DOMExceptions and segfaults with replaceWith).
Fixed bug GH-10234 (Setting DOMAttr::textContent results in an empty attribute value).
Fix return value in stub file for DOMNodeList::item.
Fix spec compliance error with '*' namespace for DOMDocument::getElementsByTagNameNS.
Fix DOMElement::append() and DOMElement::prepend() hierarchy checks.
Fixed bug GH-11347 (Memory leak when calling a static method inside an xpath query).
Fixed bug #67440 (append_node of a DOMDocumentFragment does not reconcile namespaces).
Fixed bug #81642 (DOMChildNode::replaceWith() bug when replacing a node with itself).
Fixed bug #77686 (Removed elements are still returned by getElementById).
Fixed bug #70359 (print_r() on DOMAttr causes Segfault in php_libxml_node_free_list()).
Fixed bug #78577 (Crash in DOMNameSpace debug info handlers).
Fix lifetime issue with getAttributeNodeNS().
Fix "invalid state error" with cloned namespace declarations.
Fixed bug #55294 and #47530 and #47847 (various namespace reconciliation issues).
Fixed bug #80332 (Completely broken array access functionality with DOMNamedNodeMap).
Opcache:
Fix allocation loop in zend_shared_alloc_startup().
Access violation on smm_shared_globals with ALLOC_FALLBACK.
Fixed bug GH-11336 (php still tries to unlock the shared memory ZendSem with opcache.file_cache_only=1 but it was never locked).
OpenSSL:
Fixed bug GH-9356 Incomplete validation of IPv6 Address fields in subjectAltNames (James Lucas, Jakub Zelenka).
PCRE:
Fix preg_replace_callback_array() pattern validation.
PGSQL:
Fixed intermittent segfault with pg_trace.
Phar:
Fix cross-compilation check in phar generation for FreeBSD.
SPL:
Fixed bug GH-11338 (SplFileInfo empty getBasename with more than one slash).
Standard:
Fix access on NULL pointer in array_merge_recursive().
Fix exception handling in array_multisort().
SQLite3:
Fixed bug GH-11451 (Invalid associative array containing duplicate keys).
2023-08-12 00:52:40 +08:00
msycn 22d266e710 Update redis 7.0.4 to 7.0.12 2023-08-12 00:50:36 +08:00
msycn d35bf118ff Update install.sh to 8.0.34 2023-08-12 00:48:17 +08:00
msycn 1adb2f751c Update MySQL to 8.0.34
Update MySQL to 8.0.34
2023-08-12 00:46:07 +08:00
midoks 54e743037e Update index.py 2023-08-11 21:04:46 +08:00
midoks 6debb93fd1 Update init.lua 2023-08-11 21:01:17 +08:00
midoks 7229f9c569 Update index.py 2023-08-11 20:59:34 +08:00
midoks 844dcbda00 cf验证问题解决 2023-08-11 20:58:52 +08:00
midoks af2b45a6f4 Update index.py 2023-08-11 20:54:37 +08:00
midoks d848d41a71 Update index.py 2023-08-11 20:44:59 +08:00
midoks 826ebfb2e5 Update init.lua 2023-08-11 20:05:04 +08:00
midoks e1807c1585 Update index.py 2023-08-11 17:17:08 +08:00
midoks 6e9d5a19c0 关于强制性验证优化 2023-08-11 17:15:47 +08:00
midoks 6eadad5db4 OP防火墙部分优化 2023-08-11 12:56:07 +08:00
midoks 2b2fc08120 Update index.py 2023-08-11 01:20:45 +08:00
midoks 175061884d update 2023-08-11 01:11:45 +08:00
midoks cc3fa8ac95 Update init.lua 2023-08-11 00:51:54 +08:00
midoks c9d736e338 update 2023-08-10 22:35:08 +08:00
midoks e4437e42f3 Update site_api.py 2023-08-10 21:19:49 +08:00
midoks 644fc2c81f Update mw.py 2023-08-10 21:09:59 +08:00
midoks d2314bf26f Update push_notice_msg.py 2023-08-10 18:44:22 +08:00
Mr Chen c17314b634 Merge pull request #434 from midoks/dev
MySQL,MariaDB数据库主从同步及多源同步
2023-08-10 11:32:24 +08:00
midoks 92a4b28fbf mariadb,mysql多源同步支持 2023-08-10 11:28:17 +08:00
midoks 733e4e81be update 2023-08-10 09:54:19 +08:00
midoks 8b99ae2515 update 2023-08-09 13:01:41 +08:00
midoks 2a72422402 update ad 2023-08-09 12:57:38 +08:00
midoks 145a259ef9 update 2023-08-09 08:57:49 +08:00
midoks a34b7719c8 update 2023-08-09 08:52:36 +08:00
midoks 4d98455c35 up 2023-08-08 21:17:49 +08:00
midoks c0c9def1fb Update index.py 2023-08-08 21:07:53 +08:00
midoks 02d8416466 update 2023-08-08 21:06:56 +08:00
midoks d505740269 Update index.py 2023-08-08 21:01:21 +08:00
midoks b1f6314df7 Update index.py 2023-08-08 16:54:17 +08:00
midoks 533653fe47 Update index.py 2023-08-08 16:48:21 +08:00
midoks dff4551fb1 update 2023-08-08 16:45:46 +08:00
midoks 79723149a5 Update install.sh 2023-08-08 16:32:07 +08:00
midoks 76da8a2ad5 Update install.sh 2023-08-08 16:25:40 +08:00
midoks 645538e633 Update index.py 2023-08-08 16:11:17 +08:00
midoks 1a1b4e9f3a Update index.py 2023-08-08 16:09:07 +08:00
midoks 3afde01f93 Update index.py 2023-08-08 16:07:44 +08:00
midoks a14db23971 Update index.py 2023-08-08 16:04:25 +08:00
midoks 316f06911b Update index.py 2023-08-08 16:01:34 +08:00
midoks 698d049314 up 2023-08-08 15:50:20 +08:00
midoks d397d74f73 Update index.py 2023-08-08 15:44:25 +08:00
midoks 8a7447a4ee Update mysql-apt.js 2023-08-08 15:37:45 +08:00
midoks 98414db41d update 2023-08-08 15:25:23 +08:00
midoks 7024185b59 Update my8.0.cnf 2023-08-08 14:52:57 +08:00
midoks 495f16f2cf Update mysql.js 2023-08-08 14:52:19 +08:00
midoks 62444b7b6d Update mysql.js 2023-08-08 14:51:59 +08:00
midoks 50b11457f7 update 2023-08-08 14:26:00 +08:00
midoks 393cbc3974 Merge branch 'master' into dev 2023-08-08 13:27:41 +08:00
midoks ce3bfc2ebd Merge branch 'master' into dev 2023-08-08 13:25:56 +08:00
Mr Chen b68e8f3650 Merge pull request #433 from midoks/midoks-patch-1
AD删除
2023-08-08 13:25:25 +08:00
midoks 08c83edeb9 update 2023-08-08 13:17:39 +08:00
midoks c114e9aca8 Update index.py 2023-08-07 22:50:52 +08:00
midoks c5123268d0 Update index.py 2023-08-07 22:48:34 +08:00
midoks 54bbc3ff57 Update index.py 2023-08-07 22:39:24 +08:00
midoks 4658b991a9 Update index.py 2023-08-07 22:15:14 +08:00
midoks 52145e710b Update index.py 2023-08-07 22:05:01 +08:00
midoks 4acc48ded2 Update index.py 2023-08-07 22:04:00 +08:00
midoks 0d858f87ea Update index.py 2023-08-07 22:03:00 +08:00
midoks f37f08a9f5 Update index.py 2023-08-07 21:53:28 +08:00
midoks 0b5fc1de55 Update index.py 2023-08-07 21:52:53 +08:00
midoks 8748777101 Update index.py 2023-08-07 21:47:03 +08:00
midoks 48ed0b8034 Update index.py 2023-08-07 21:44:32 +08:00
midoks 41c9f6b7b6 Update mariadb.js 2023-08-07 21:24:42 +08:00
midoks c47336b65f update 2023-08-07 21:22:29 +08:00
midoks 24d7204ccc Update index.py 2023-08-07 21:05:22 +08:00
midoks 8c00fb8859 Update index.py 2023-08-07 20:42:08 +08:00
midoks c573b28f16 Update index.py 2023-08-07 20:41:11 +08:00
midoks afad548cf9 Update index.py 2023-08-07 20:22:26 +08:00
midoks 2605849de2 Update index.py 2023-08-07 20:02:18 +08:00
midoks 77598fa8a7 Update index.py 2023-08-07 19:44:47 +08:00
midoks b175ab735d Update index.py 2023-08-07 19:34:57 +08:00
midoks 54ed17ab8f Update index.py 2023-08-07 19:32:47 +08:00
midoks cadf72ea69 Update index.py 2023-08-07 17:53:33 +08:00
midoks dadb737f88 update 2023-08-07 15:59:00 +08:00
midoks fef2acf683 Update index.py 2023-08-07 15:56:59 +08:00
midoks 4b6dbf8887 Update mariadb.js 2023-08-07 15:46:10 +08:00
midoks 06c99e1cc1 Update index.py 2023-08-07 15:26:54 +08:00
midoks afb3e920f8 mariadb多住一从功能 2023-08-07 15:10:38 +08:00
midoks 2c346c9850 Update my.cnf 2023-08-06 14:38:47 +08:00
midoks 5b6c5be288 Update mariadb.js 2023-08-06 00:43:24 +08:00
midoks 63bd806222 Update index.py 2023-08-06 00:25:22 +08:00
midoks afe3848b71 update 2023-08-05 21:34:04 +08:00
midoks cd361ec7ec Update install.sh 2023-08-05 21:33:14 +08:00
midoks eb399fe799 Update install.sh 2023-08-05 21:32:25 +08:00
midoks 53e588b6fc Update install.sh 2023-08-05 21:31:58 +08:00
200 changed files with 9819 additions and 2106 deletions
+2 -2
View File
@@ -177,5 +177,5 @@ debug.out
mdioks.session-journal
*.session
mdioks.session-journal
*.session
+16 -8
View File
@@ -80,6 +80,7 @@ PHP[72-82]支持phpMyAdmin[5.2.0]
# 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.pw/)
- [鲲鹏vpn,免费试用,解锁流媒体和chatGPT](https://down.xbjc888.top/?agent_code=github)
# AD - VPS推荐 - 🙏
@@ -99,15 +100,20 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.15.2
### 版本更新 0.16.0
* OpenResty升级到1.21.4.2
* 计划任务自动脚本运行时间
* rsyncd添加优化
* 使用mariadb二进制导入备份文件
* docker插件-镜像导入导出功能
* 网站设置反向代理升级功能
* 优化初始化安装SSH端口识别
yum install -y libargon2-devel
apt install -y libargon2-dev
OP防火墙 - 重载即可
* 增加PHP83。
* 面板日志单独为一页并加入日志审计功能。
* 修复webssh服务器读取问题。
* 站点批量删除修复。
* OP防火墙-修复`自动强制验证`关闭不生效。
* 新增OneDrive备份插件。
* FTP备份优化。
### JSDelivr安装地址
@@ -166,6 +172,8 @@ curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install_dev.sh | bash
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
wget --no-check-certificate -O install.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install.sh && bash install.sh
wget --no-check-certificate -O uninstall.sh https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/uninstall.sh && bash uninstall.sh
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/quick/debug.sh | bash
+12 -8
View File
@@ -1496,8 +1496,9 @@ fullchain.pem 粘贴到证书输入框
'cert_timeout'] = int(time.time())
if self.__config['orders'][i]['cert_timeout'] > start_time:
writeLog(
"|-本次跳过域名: {},未过期!".format(self.__config['orders'][i]['domains'][0]))
msg = "|-本次跳过域名: {},未过期!".format(
self.__config['orders'][i]['domains'][0])
writeLog(msg)
continue
# 已删除的网站直接跳过续签
@@ -1514,8 +1515,9 @@ fullchain.pem 粘贴到证书输入框
break
if not mw.M('domain').where("name=?", (domain,)).count() and not mw.M('binding').where("domain=?", domain).count():
auth_to = None
writeLog(
"|-跳过被删除的域名: {}".format(self.__config['orders'][i]['domains']))
msg = "|-跳过被删除的域名: {}".format(
self.__config['orders'][i]['domains'])
writeLog(msg)
if not auth_to:
continue
@@ -1526,15 +1528,17 @@ fullchain.pem 粘贴到证书输入框
timeout = self.__config['orders'][i][
'next_retry_time'] - int(time.time())
if timeout > 0:
writeLog('|-本次跳过域名:{},因第上次续签失败,还需要等待{}小时后再重试'.format(
self.__config['orders'][i]['domains'], int(timeout / 60 / 60)))
msg = '|-本次跳过域名:{},因第上次续签失败,还需要等待{}小时后再重试'.format(
self.__config['orders'][i]['domains'], int(timeout / 60 / 60))
writeLog(msg)
continue
# 是否到了最大重试次数
if 'retry_count' in self.__config['orders'][i]:
if self.__config['orders'][i]['retry_count'] >= 5:
writeLog('|-本次跳过域名:{},因连续5次续签失败,不再续签此证书(可尝试手动续签此证书,成功后错误次数将被重置)'.format(
self.__config['orders'][i]['domains']))
msg = '|-本次跳过域名:{},因连续5次续签失败,不再续签此证书(可尝试手动续签此证书,成功后错误次数将被重置)'.format(
self.__config['orders'][i]['domains'])
writeLog(msg)
continue
# 加入到续签订单
+1 -1
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api:
__version = '0.15.2'
__version = '0.16.0'
__api_addr = 'data/api.json'
def __init__(self):
+9 -7
View File
@@ -602,20 +602,22 @@ echo "--------------------------------------------------------------------------
# 将Shell脚本写到文件
def writeShell(self, config):
u_file = '/var/spool/cron/crontabs/root'
if not os.path.exists(u_file):
file = '/var/spool/cron/crontabs/root'
current_os = mw.getOs()
if current_os == 'darwin':
file = '/etc/crontab'
elif current_os.startswith("freebsd"):
file = '/var/cron/tabs/root'
if not os.path.exists(file):
file = '/var/spool/cron/root'
if mw.isAppleSystem():
file = '/etc/crontab'
else:
file = u_file
if not os.path.exists(file):
mw.writeFile(file, '')
conf = mw.readFile(file)
conf += str(config) + "\n"
if mw.writeFile(file, conf):
if not os.path.exists(u_file):
if not os.path.exists(file):
mw.execShell("chmod 600 '" + file +
"' && chown root.root " + file)
else:
+7 -5
View File
@@ -64,8 +64,13 @@ class files_api:
filename = request.args.get('filename', '')
if not os.path.exists(filename):
return ''
is_attachment = True
if filename.endswith(".svg"):
is_attachment = False
response = make_response(send_from_directory(
os.path.dirname(filename), os.path.basename(filename), as_attachment=True))
os.path.dirname(filename), os.path.basename(filename), as_attachment=is_attachment))
return response
def zipApi(self):
@@ -708,10 +713,7 @@ class files_api:
return not path in nDirs
def getDirSize(self, path):
if mw.isAppleSystem():
tmp = mw.execShell('du -sh ' + path)
else:
tmp = mw.execShell('du -sbh ' + path)
tmp = mw.execShell('du -sh ' + path)
return tmp
def checkFileName(self, filename):
-33
View File
@@ -178,12 +178,6 @@ class firewall_api:
limit = request.form.get('limit', '10').strip()
return self.getList(int(p), int(limit))
def getLogListApi(self):
p = request.form.get('p', '1').strip()
limit = request.form.get('limit', '10').strip()
search = request.form.get('search', '').strip()
return self.getLogList(int(p), int(limit), search)
def getSshInfoApi(self):
data = {}
@@ -389,11 +383,6 @@ class firewall_api:
return mw.returnData(True, '设置成功!')
def delPanelLogsApi(self):
mw.M('logs').where('id>?', (0,)).delete()
mw.writeLog('面板设置', '面板操作日志已清空!')
return mw.returnJson(True, '面板操作日志已清空!')
##### ----- start ----- ###
def getList(self, page, limit):
@@ -414,28 +403,6 @@ class firewall_api:
data['page'] = mw.getPage(_page)
return mw.getJson(data)
def getLogList(self, page, limit, search=''):
find_search = ''
if search != '':
find_search = "type like '%" + search + "%' or log like '%" + \
search + "%' or addtime like '%" + search + "%'"
start = (page - 1) * limit
_list = mw.M('logs').where(find_search, ()).field(
'id,type,log,addtime').limit(str(start) + ',' + str(limit)).order('id desc').select()
data = {}
data['data'] = _list
count = mw.M('logs').where(find_search, ()).count()
_page = {}
_page['count'] = count
_page['tojs'] = 'getLogs'
_page['p'] = page
data['page'] = mw.getPage(_page)
return mw.getJson(data)
def addAcceptPort(self, port):
if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp')
+352
View File
@@ -0,0 +1,352 @@
# 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
import sys
import mw
import re
import json
import pwd
from datetime import datetime
from flask import request
class logs_api:
__months = {'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04', 'May': '05', 'Jun': '06',
'Jul': '07', 'Aug': '08', 'Sep': '09', 'Sept': '09', 'Oct': '10', 'Nov': '11', 'Dec': '12'}
def __init__(self):
pass
def delPanelLogsApi(self):
mw.M('logs').where('id>?', (0,)).delete()
mw.writeLog('面板设置', '面板操作日志已清空!')
return mw.returnJson(True, '面板操作日志已清空!')
def getLogListApi(self):
p = request.form.get('p', '1').strip()
limit = request.form.get('limit', '10').strip()
search = request.form.get('search', '').strip()
return self.getLogList(int(p), int(limit), search)
def getLogList(self, page, limit, search=''):
find_search = ''
if search != '':
find_search = "type like '%" + search + "%' or log like '%" + \
search + "%' or addtime like '%" + search + "%'"
start = (page - 1) * limit
_list = mw.M('logs').where(find_search, ()).field(
'id,type,log,addtime').limit(str(start) + ',' + str(limit)).order('id desc').select()
data = {}
data['data'] = _list
count = mw.M('logs').where(find_search, ()).count()
_page = {}
_page['count'] = count
_page['tojs'] = 'getLogs'
_page['p'] = page
data['page'] = mw.getPage(_page)
return mw.getJson(data)
def getLogsTitle(self, log_name):
log_name = log_name.replace('.1', '')
if log_name in ['mw-update.log']:
return '面板更新日志'
if log_name in ['mw-install.log']:
return '面板安装日志'
if log_name in ['auth.log', 'secure'] or log_name.find('auth.') == 0:
return '授权日志'
if log_name in ['dmesg'] or log_name.find('dmesg') == 0:
return '内核缓冲区日志'
if log_name in ['syslog'] or log_name.find('syslog') == 0:
return '系统警告/错误日志'
if log_name in ['btmp']:
return '失败的登录记录'
if log_name in ['utmp', 'wtmp']:
return '登录和重启记录'
if log_name in ['lastlog']:
return '用户最后登录'
if log_name in ['yum.log']:
return 'yum包管理器日志'
if log_name in ['anaconda.log']:
return 'Anaconda日志'
if log_name in ['dpkg.log']:
return 'dpkg日志'
if log_name in ['daemon.log']:
return '系统后台守护进程日志'
if log_name in ['boot.log']:
return '启动日志'
if log_name in ['kern.log']:
return '内核日志'
if log_name in ['maillog', 'mail.log']:
return '邮件日志'
if log_name.find('Xorg') == 0:
return 'Xorg日志'
if log_name in ['cron.log']:
return '定时任务日志'
if log_name in ['alternatives.log']:
return '更新替代信息'
if log_name in ['debug']:
return '调试信息'
if log_name.find('apt') == 0:
return 'apt-get相关日志'
if log_name.find('installer') == 0:
return '系统安装相关日志'
if log_name in ['messages']:
return '综合日志'
return '{}日志'.format(log_name.split('.')[0])
def getAuditLogsFilesApi(self):
log_dir = '/var/log'
log_files = []
for log_file in os.listdir(log_dir):
log_suffix = log_file.split('.')[-1:]
if log_suffix[0] in ['gz', 'xz', 'bz2', 'asl']:
continue
if log_file in ['.', '..', 'faillog', 'fontconfig.log', 'unattended-upgrades', 'tallylog']:
continue
filename = os.path.join(log_dir, log_file)
if os.path.isfile(filename):
file_size = os.path.getsize(filename)
if not file_size:
continue
tmp = {
'name': log_file,
'size': file_size,
'log_file': filename,
'title': self.getLogsTitle(log_file),
'uptime': os.path.getmtime(filename)
}
log_files.append(tmp)
else:
for next_name in os.listdir(filename):
if next_name[-3:] in ['.gz', '.xz']:
continue
next_file = os.path.join(filename, next_name)
if not os.path.isfile(next_file):
continue
file_size = os.path.getsize(next_file)
if not file_size:
continue
log_name = '{}/{}'.format(log_file, next_name)
tmp = {
'name': log_name,
'size': file_size,
'log_file': next_file,
'title': self.getLogsTitle(log_name),
'uptime': os.path.getmtime(next_file)
}
log_files.append(tmp)
log_files = sorted(log_files, key=lambda x: x['name'], reverse=True)
return mw.getJson(log_files)
def getAuditFileApi(self):
log_name = request.form.get('log_name', '').strip()
return self.getAuditLogsName(log_name)
def __to_date2(self, date_str):
tmp = date_str.split()
s_date = str(tmp[-1]) + '-' + self.__months.get(tmp[1],
tmp[1]) + '-' + tmp[2] + ' ' + tmp[3]
return s_date
def __to_date3(self, date_str):
tmp = date_str.split()
s_date = str(datetime.now().year) + '-' + \
self.__months.get(tmp[1], tmp[1]) + '-' + tmp[2] + ' ' + tmp[3]
return s_date
def __to_date4(self, date_str):
tmp = date_str.split()
s_date = str(datetime.now().year) + '-' + \
self.__months.get(tmp[0], tmp[0]) + '-' + tmp[1] + ' ' + tmp[2]
return s_date
def getAuditLast(self, log_name):
# 获取日志
cmd = '''LANG=en_US.UTF-8 last -n 200 -x -f {} |grep -v 127.0.0.1|grep -v " begins"'''.format(
'/var/log/' + log_name)
result = mw.execShell(cmd)
lastlog_list = []
for _line in result[0].split("\n"):
if not _line:
continue
tmp = {}
sp_arr = _line.split()
tmp['用户'] = sp_arr[0]
if sp_arr[0] == 'runlevel':
tmp['来源'] = sp_arr[4]
tmp['端口'] = ' '.join(sp_arr[1:4])
tmp['时间'] = self.__to_date3(
' '.join(sp_arr[5:])) + ' ' + ' '.join(sp_arr[-2:])
elif sp_arr[0] in ['reboot', 'shutdown']:
tmp['来源'] = sp_arr[3]
tmp['端口'] = ' '.join(sp_arr[1:3])
if sp_arr[-3] == '-':
tmp['时间'] = self.__to_date3(
' '.join(sp_arr[4:])) + ' ' + ' '.join(sp_arr[-3:])
else:
tmp['时间'] = self.__to_date3(
' '.join(sp_arr[4:])) + ' ' + ' '.join(sp_arr[-2:])
elif sp_arr[1] in ['tty1', 'tty', 'tty2', 'tty3', 'hvc0', 'hvc1', 'hvc2'] or len(sp_arr) == 9:
tmp['来源'] = ''
tmp['端口'] = sp_arr[1]
tmp['时间'] = self.__to_date3(
' '.join(sp_arr[2:])) + ' ' + ' '.join(sp_arr[-3:])
else:
tmp['来源'] = sp_arr[2]
tmp['端口'] = sp_arr[1]
tmp['时间'] = self.__to_date3(
' '.join(sp_arr[3:])) + ' ' + ' '.join(sp_arr[-3:])
# tmp['_line'] = _line
lastlog_list.append(tmp)
# lastlog_list = sorted(lastlog_list,key=lambda x:x['时间'],reverse=True)
return mw.returnData(True, 'ok!', lastlog_list)
def getAuditLastLog(self):
cmd = '''LANG=en_US.UTF-8 lastlog|grep -v Username'''
result = mw.execShell(cmd)
lastlog_list = []
for _line in result[0].split("\n"):
if not _line:
continue
tmp = {}
sp_arr = _line.split()
tmp['用户'] = sp_arr[0]
# tmp['_line'] = _line
if _line.find('Never logged in') != -1:
tmp['最后登录时间'] = '0'
tmp['最后登录来源'] = '-'
tmp['最后登录端口'] = '-'
lastlog_list.append(tmp)
continue
tmp['最后登录来源'] = sp_arr[2]
tmp['最后登录端口'] = sp_arr[1]
tmp['最后登录时间'] = self.__to_date2(' '.join(sp_arr[3:]))
lastlog_list.append(tmp)
lastlog_list = sorted(lastlog_list, key=lambda x: x[
'最后登录时间'], reverse=True)
for i in range(len(lastlog_list)):
if lastlog_list[i]['最后登录时间'] == '0':
lastlog_list[i]['最后登录时间'] = '从未登录过'
return mw.returnData(True, 'ok!', lastlog_list)
def parseAuditFile(self, log_name, result):
log_list = []
is_string = True
for _line in result.split("\n"):
if not _line.strip():
continue
if log_name.find('sa/sa') == -1:
if _line[:3] in self.__months:
_msg = _line[16:]
_tmp = _msg.split(": ")
_act = ''
if len(_tmp) > 1:
_act = _tmp[0]
_msg = _tmp[1]
else:
_msg = _tmp[0]
_line = {
"时间": self.__to_date4(_line[:16].strip()),
"角色": _act,
"事件": _msg
}
is_string = False
elif _line[:2] in ['19', '20', '21', '22', '23', '24']:
_msg = _line[19:]
_tmp = _msg.split(" ")
_act = _tmp[1]
_msg = ' '.join(_tmp[2:])
_line = {
"时间": _line[:19].strip(),
"角色": _act,
"事件": _msg
}
is_string = False
elif log_name.find('alternatives') == 0:
_tmp = _line.split(": ")
_last = _tmp[0].split(" ")
_act = _last[0]
_msg = ' '.join(_tmp[1:])
_line = {
"时间": ' '.join(_last[1:]).strip(),
"角色": _act,
"事件": _msg
}
is_string = False
else:
if not is_string:
if type(_line) != dict:
continue
log_list.append(_line)
return log_list
def getAuditLogsName(self, log_name):
# print(log_name)
if log_name in ['wtmp', 'btmp', 'utmp'] or log_name.find('wtmp') == 0 or log_name.find('btmp') == 0 or log_name.find('utmp') == 0:
return self.getAuditLast(log_name)
if log_name.find('lastlog') == 0:
return self.getAuditLastLog()
if log_name.find('sa/sa') == 0:
if log_name.find('sa/sar') == -1:
return mw.execShell("sar -f /var/log/{}".format(log_name))[0]
log_dir = '/var/log'
log_file = log_dir + '/' + log_name
if not os.path.exists(log_file):
return mw.returnData(False, '日志文件不存在!')
result = mw.getLastLine(log_file, 100)
try:
log_list = self.parseAuditFile(log_name, result)
_string = []
_dict = []
_list = []
for _line in log_list:
if isinstance(_line, str):
_string.append(_line.strip())
elif isinstance(_line, dict):
_dict.append(_line)
elif isinstance(_line, list):
_list.append(_line)
else:
continue
_str_len = len(_string)
_dict_len = len(_dict)
_list_len = len(_list)
if _str_len > _dict_len + _list_len:
return "\n".join(_string)
elif _dict_len > _str_len + _list_len:
return mw.returnData(True, 'ok!', _dict)
else:
return mw.returnData(True, 'ok!', _list)
except:
return mw.returnData(True, 'ok!', result)
+16 -7
View File
@@ -349,7 +349,8 @@ def restartMw():
def checkWebConfig():
op_dir = getServerDir() + '/openresty/nginx'
cmd = "ulimit -n 10240 && " + op_dir + \
# "ulimit -n 10240 && " +
cmd = op_dir + \
"/sbin/nginx -t -c " + op_dir + "/conf/nginx.conf"
result = execShell(cmd)
searchStr = 'test is successful'
@@ -1355,6 +1356,12 @@ def getCpuType():
cpuinfo = execShell(cmd)
return cpuinfo[0].strip()
current_os = getOs()
if current_os.startswith('freebsd'):
cmd = "sysctl -a | egrep -i 'hw.model' | awk -F ':' '{print $2}'"
cpuinfo = execShell(cmd)
return cpuinfo[0].strip()
# 取CPU类型
cpuinfo = open('/proc/cpuinfo', 'r').read()
rep = "model\s+name\s+:\s+(.+)"
@@ -1411,7 +1418,7 @@ def makeConf():
file = getRunDir() + '/data/json/config.json'
if not os.path.exists(file):
c = {}
c['title'] = '金灵面板'
c['title'] = '老子面板'
c['home'] = 'http://github/midoks/mdserver-web'
c['recycle_bin'] = True
c['template'] = 'default'
@@ -1550,7 +1557,9 @@ def checkInput(data):
def checkCert(certPath='ssl/certificate.pem'):
# 验证证书
openssl = '/usr/local/openssl/bin/openssl'
openssl = '/usr/bin/openssl'
if not os.path.exists(openssl):
openssl = '/usr/local/openssl/bin/openssl'
if not os.path.exists(openssl):
openssl = 'openssl'
certPem = readFile(certPath)
@@ -2097,15 +2106,15 @@ done
def echoStart(tag):
print("=" * 90)
print("=" * 89)
print("★开始{}[{}]".format(tag, formatDate()))
print("=" * 90)
print("=" * 89)
def echoEnd(tag):
print("=" * 90)
print("=" * 89)
print("☆{}完成[{}]".format(tag, formatDate()))
print("=" * 90)
print("=" * 89)
print("\n")
+1 -1
View File
@@ -2760,7 +2760,7 @@ location ^~ {from} {\n\
self.saveCert(keyPath, certPath)
msg = mw.getInfo('网站[{1}]开启SSL成功!', siteName)
msg = mw.getInfo('网站[{}]开启SSL成功!', siteName)
mw.writeLog('网站管理', msg)
mw.restartWeb()
+22 -5
View File
@@ -274,26 +274,43 @@ class system_api:
return title
def getSystemVersion(self):
#
# 取操作系统版本
if mw.getOs() == 'darwin':
current_os = mw.getOs()
# mac
if current_os == 'darwin':
data = mw.execShell('sw_vers')[0]
data_list = data.strip().split("\n")
mac_version = ''
for x in data_list:
mac_version += x.split("\t")[1] + ' '
return mac_version
arch_ver = mw.execShell("arch")
return mac_version + " (" + arch_ver[0].strip() + ")"
# freebsd
if current_os.startswith('freebsd'):
version = mw.execShell(
"cat /etc/*-release | grep PRETTY_NAME | awk -F = '{print $2}' | awk -F '\"' '{print $2}'")
arch_ver = mw.execShell(
"sysctl -a | egrep -i 'hw.machine_arch' | awk -F ':' '{print $2}'")
return version[0].strip() + " (" + arch_ver[0].strip() + ")"
redhat_series = '/etc/redhat-release'
if os.path.exists(redhat_series):
version = mw.readFile('/etc/redhat-release')
version = version.replace('release ', '').strip()
return version
arch_ver = mw.execShell("arch")
return version + " (" + arch_ver[0].strip() + ")"
os_series = '/etc/os-release'
if os.path.exists(os_series):
version = mw.execShell(
"cat /etc/*-release | grep PRETTY_NAME | awk -F = '{print $2}' | awk -F '\"' '{print $2}'")
return version[0].strip()
arch_ver = mw.execShell("arch")
return version[0].strip() + " (" + arch_ver[0].strip() + ")"
return '未识别系统信息'
@@ -318,7 +335,7 @@ class system_api:
cpuCount = psutil.cpu_count()
cpuLogicalNum = psutil.cpu_count(logical=False)
used = psutil.cpu_percent(interval=interval)
cpuLogicalNum = 0
if os.path.exists('/proc/cpuinfo'):
c_tmp = mw.readFile('/proc/cpuinfo')
d_tmp = re.findall("physical id.+", c_tmp)
+4
View File
@@ -7,6 +7,10 @@ MDIR=$(dirname "$DIR")
PATH=$PATH:$DIR/bin
if [ -f bin/activate ];then
source bin/activate
if [ "$?" != "0" ];then
echo "load local python env fail!"
fi
fi
export LC_ALL="en_US.UTF-8"
+48 -6
View File
@@ -14,6 +14,7 @@ if sys.platform != "darwin":
sys.path.append(os.getcwd() + "/class/core")
import mw
import db
_ver = sys.version_info
is_py2 = (_ver[0] == 2)
@@ -185,6 +186,35 @@ def backupAllFunc(stype):
"path": "path",
}
backups = []
sql = db.Sql()
# print("stype:", stype)
# 提前获取-清理多余备份
if stype == 'site':
pid = sql.table('sites').where('name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('0', pid)).field('id,filename').select()
if stype == 'database':
db_path = mw.getServerDir() + '/mysql'
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
if stype == 'path':
backup_path = backup_dir + '/path'
_name = 'path_{}'.format(os.path.basename(name))
backups = findPathName(backup_path, _name)
# 其他类型关系性数据库(mysql类的)
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
db_path = mw.getServerDir() + '/' + plugin_name
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
args = stype + " " + name + " " + num
cmd = 'python3 ' + mw.getRunDir() + '/scripts/backup.py ' + args
if stype.find('database_') > -1:
@@ -213,19 +243,31 @@ def backupAllFunc(stype):
filename = mw.execShell(find_new_file)[0].strip()
if filename == "":
mw.echoInfo("not find upload file!")
return False
return ''
print("|-准备上传文件 {}".format(filename))
ftp = FtpPSClient()
ftp.uploadFile(filename, stype)
# print(backups)
backups = sorted(backups, key=lambda x: x['filename'], reverse=False)
mw.echoStart('开始删除远程备份')
num = int(num)
sep = len(backups) - num
if sep > -1:
for backup in backups:
fn = os.path.basename(backup['filename'])
object_name = ftp.buildDirName(stype, fn)
ftp.deleteFile(object_name)
mw.echoInfo("---已清理远程过期备份文件:" + object_name)
sep -= 1
if sep < 0:
break
mw.echoEnd('结束删除远程备份')
return ''
def backupSite():
# 备份站点
pass
def in_array(name, arr=[]):
for x in arr:
if name == x:
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+19
View File
@@ -0,0 +1,19 @@
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('dynamic-tracking');">服务</p>
<p onclick="pluginInitD('dynamic-tracking');">自启动</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(300);
resetPluginWinWidth(500);
$.getScript( "/plugins/file?name=dynamic-tracking&f=static/js/dynamic-tracking.js", function(){
pluginService('dynamic-tracking', $('.plugin_version').attr('version'));
});
</script>
+228
View File
@@ -0,0 +1,228 @@
# 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 'dynamic-tracking'
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 getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':')
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def status():
dir_path = getServerDir() + '/trace'
if not os.path.exists(dir_path):
os.mkdir(dir_path)
return 'start'
def dtOp(method):
return 'ok'
def start():
return dtOp('start')
def stop():
return dtOp('stop')
def restart():
status = dtOp('restart')
return status
def reload():
return dtOp('reload')
def initdStatus():
return 'ok'
def initdInstall():
return 'ok'
def initdUinstall():
return 'ok'
def get_file(args):
dir_path = getServerDir() + '/trace'
path = dir_path + '/' + args['file'] + '/main.svg'
if os.path.exists(path):
d = mw.readFile(path)
return mw.returnData(True, 'ok', d)
else:
return mw.returnData(False, '无效目录')
def get_file_path(args):
dir_path = getServerDir() + '/trace'
path = dir_path + '/' + args['file'] + '/main.svg'
if os.path.exists(path):
return mw.returnData(True, 'ok', path)
else:
return mw.returnData(False, '无效目录')
def dtGetFilePath():
args = getArgs()
data = checkArgs(args, ['file'])
if not data[0]:
return data[1]
dir_path = getServerDir() + '/trace'
path = dir_path + '/' + args['file'] + '/main.svg'
if os.path.exists(path):
return mw.returnJson(True, 'ok', path)
else:
return mw.returnJson(False, '无效目录')
def dtRemoveFilePath():
args = getArgs()
data = checkArgs(args, ['file'])
if not data[0]:
return data[1]
dir_path = getServerDir() + '/trace'
path = dir_path + '/' + args['file']
if os.path.exists(path):
mw.execShell('rm -rf ' + path)
return mw.returnJson(True, '删除成功!')
def dtFileList():
dir_path = getServerDir() + '/trace'
if not os.path.exists(dir_path):
os.mkdir(dir_path)
file_info = []
for name in os.listdir(dir_path):
if name == ".DS_Store":
continue
# print(name)
info = {}
try:
info['name'] = name
info['abs_path'] = dir_path + '/' + name + '/main.svg'
except Exception as e:
return mw.returnJson(False, str(e))
file_info.append(info)
file_info = sorted(file_info, key=lambda x: x['name'], reverse=False)
return mw.returnJson(True, 'ok!', file_info)
def dtSimpleTrace():
if mw.isAppleSystem():
return mw.returnJson(False, 'macosx只能手动执行!')
args = getArgs()
data = checkArgs(args, ['pid'])
if not data[0]:
return data[1]
plugins_shell = getPluginDir() + '/shell/simple_trace.sh'
cmd = plugins_shell + ' "' + args['pid'] + '"'
data = mw.execShell("bash " + cmd + " &")
return mw.returnJson(True, '执行成功!')
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'run_info':
print(runInfo())
elif func == 'conf':
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'file_list':
print(dtFileList())
elif func == 'get_file_path':
print(dtGetFilePath())
elif func == 'remove_file_path':
print(dtRemoveFilePath())
elif func == 'simple_trace':
print(dtSimpleTrace())
else:
print('error')
+36
View File
@@ -0,0 +1,36 @@
{
"hook":[
{
"tag":"menu",
"menu": {
"title":"动态追踪",
"name":"dynamic-tracking",
"path":"static/html/index.html",
"css_path":"static/css/dynamic-tracking.css",
"js_path":"static/js/dynamic-tracking.js"
}
},
{
"tag":"global_static",
"global_static": {
"title":"动态追踪",
"name":"dynamic-tracking",
"css_path":"static/css/ico.css"
}
}
],
"sort": 7,
"ps": "专业使用,动态追踪调试程序<无侵入>![<span style='color:red;'>潜龙勿用|实验</span>]",
"name": "dynamic-tracking",
"title": "动态追踪",
"shell": "install.sh",
"versions":["0.1"],
"tip": "soft",
"checks": "server/dynamic-tracking",
"path": "server/dynamic-tracking",
"display": 1,
"author": "midoks",
"date": "2023-08-17",
"type": 0,
"pid": "4"
}
+88
View File
@@ -0,0 +1,88 @@
#!/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/dynamic-tracking && /bin/bash install.sh uninstall 1.0
# cd /www/server/mdserver-web/plugins/dynamic-tracking && /bin/bash install.sh install 1.0
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
OSNAME=`bash ${rootPath}/scripts/getos.sh`
if [ "" == "$OSNAME" ];then
OSNAME=`cat ${rootPath}/data/osname.pl`
fi
if [ "macos" != "$OSNAME" ];then
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
fi
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/dynamic-tracking
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
HTTP_PREFIX="https://ghproxy.com/"
fi
# FlameGraph start
if [ ! -d $serverPath/dynamic-tracking/FlameGraph ];then
if [ ! -f $serverPath/source/FlameGraph.zip ]; then
wget --no-check-certificate -O $serverPath/source/FlameGraph.zip ${HTTP_PREFIX}github.com/brendangregg/FlameGraph/archive/refs/heads/master.zip
fi
cd $serverPath/source && unzip $serverPath/source/FlameGraph.zip
mv $serverPath/source/FlameGraph-master $serverPath/dynamic-tracking/FlameGraph
fi
# FlameGraph end
shell_file=${curPath}/versions/${OSNAME}.sh
echo $shell_file
if [ ! -f $shell_file ];then
echo '不支持...' > $install_tmp
exit 1
fi
bash -x $shell_file
echo "cp -rf ${curPath}/shell $serverPath/dynamic-tracking"
cp -rf ${curPath}/shell $serverPath/dynamic-tracking
echo "${VERSION}" > $serverPath/dynamic-tracking/version.pl
echo '安装完成' > $install_tmp
cd ${rootPath} && python3 ${rootPath}/plugins/dynamic-tracking/index.py start
# cd ${rootPath} && python3 ${rootPath}/plugins/dynamic-tracking/index.py initd_install
}
Uninstall_App()
{
rm -rf $serverPath/dynamic-tracking
echo "Uninstall_App" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
@@ -0,0 +1,39 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# debug
# cd /www/server/mdserver-web
# bash /www/server/mdserver-web/plugins/dynamic-tracking/shell/simple_macosx_trace.sh "22431"
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web
# bash /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/dynamic-tracking/shell/simple_macosx_trace.sh "22431"
# dtrace -x ustackframes=100 -n 'pid$target::mach_msg_trap:entry { @[ustack()] = count(); } tick-30s { exit(0); }' -p 18572 -o out.SystemUIServer_stacks
# /Users/midoks/Desktop/mwdev/server/dynamic-tracking/FlameGraph/stackcollapse.pl out.SystemUIServer_stacks > kernel.cbt
# /Users/midoks/Desktop/mwdev/server/dynamic-tracking/FlameGraph/flamegraph.pl kernel.cbt > kernel.svg
curPath=`pwd`
rootPath=$(dirname "$curPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
PID=$1
echo $rootPath # /Users/midoks/Desktop/mwdev/server
echo $curPath # /Users/midoks/Desktop/mwdev/server/mdserver-web
APP_DIR=${rootPath}/dynamic-tracking
DST_FILE_DIR=${APP_DIR}/trace/PID_${PID}
mkdir -p $DST_FILE_DIR
DST_FILE=${DST_FILE_DIR}/out.SystemUIServer_stacks
if [ ! -f $DST_FILE ];then
sudo dtrace -x ustackframes=100 -n 'pid$target::mach_msg_trap:entry { @[ustack()] = count(); } tick-30s { exit(0); }' -p "$PID" -o $DST_FILE
fi
${APP_DIR}/FlameGraph/stackcollapse.pl $DST_FILE > ${DST_FILE_DIR}/kernel.cbt
${APP_DIR}/FlameGraph/flamegraph.pl ${DST_FILE_DIR}/kernel.cbt > ${DST_FILE_DIR}/main.svg
@@ -0,0 +1,43 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# debug
# cd /www/server/mdserver-web
# bash /www/server/mdserver-web/plugins/dynamic-tracking/shell/simple_trace.sh "2401699"
curPath=`pwd`
rootPath=$(dirname "$curPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
PID=$1
echo $rootPath # /Users/midoks/Desktop/mwdev/server
echo $curPath # /Users/midoks/Desktop/mwdev/server/mdserver-web
APP_DIR=/www/server/dynamic-tracking
DST_FILE_DIR=${APP_DIR}/trace/PID_${PID}
mkdir -p $DST_FILE_DIR
# DST_FILE=${DST_FILE_DIR}/main.strace
# perf record -F 99 -p 335584 -g -- sleep 30
cd ${DST_FILE_DIR}
perf record -F 99 -p ${PID} -g -- sleep 30
perf script > out.perf
${APP_DIR}/FlameGraph/stackcollapse-perf.pl ${DST_FILE_DIR}/out.perf > ${DST_FILE_DIR}/out.folded
${APP_DIR}/FlameGraph/flamegraph.pl ${DST_FILE_DIR}/out.folded > ${DST_FILE_DIR}/main.svg
# perf record -F 99 -p 2401699 -g -- sleep 30
# perf script > out.perf
# /www/server/dynamic-tracking/FlameGraph/stackcollapse-perf.pl out.perf > out.folded
# /www/server/dynamic-tracking/FlameGraph/flamegraph.pl out.folded > php-zend-flame-graph.svg
# ${APP_DIR}/FlameGraph/stackcollapse.pl $DST_FILE > ${DST_FILE_DIR}/kernel.cbt
# ${APP_DIR}/FlameGraph/flamegraph.pl ${DST_FILE_DIR}/kernel.cbt > ${DST_FILE_DIR}/main.svg
@@ -0,0 +1,75 @@
.screen-all {
padding: 5px;
}
.s-right .panel-default{
margin-bottom: 10px;
}
.s-left .panel-default{
margin-bottom: 10px;
}
.data-collect {
width: 45px;
height: 30px;
border: 0;
cursor: pointer;
margin-right: 2px;
margin-top: 10px;
color: #fff;
background-color: #20a53a;
border-color: #20a53a;
}
#file_list .list {
list-style: none;
border-top: none;
border: 1px solid #ececec;
overflow-y: auto;
}
#file_list .list li.active {
background-color: #f2f2f2;
}
#file_list .tab-con{
padding: 0px;
margin-top: 10px;
}
#file_list .list li>span {
vertical-align: top;
display: inline-block;
}
#file_list .list li {
display: inline-block;
height: 38px;
line-height: 38px;
color: #444;
border-bottom: 1px solid #ececec;
font-size: 13px;
cursor: pointer;
position: relative;
width: 100%;
}
#file_list .file {
padding-left: 10px;
}
#file_list .list li .tootls{
width: 70px;
text-align: right;
padding-right: 10px;
/* display: none; */
position: absolute;
right: 5px;
}
/*.tab-con .tab-block.on {
display: inline-block;
}*/
@@ -0,0 +1,11 @@
/* menu start */
.menu .current .menu_dynamic-tracking:hover {
background-image: url("/plugins/file?name=dynamic-tracking&f=ico.png");
}
.menu .menu_plugin_dynamic-tracking {
background-image: url("/plugins/file?name=dynamic-tracking&f=ico.png");
}
/* menu end */
@@ -0,0 +1,81 @@
<style>
.weblog{
font-size: 12px;
display:inline-block;
line-height:30px;
}
.weblog em{
font-style:normal;
color:#666;
margin: 0 30px;
}
.weblog span{
margin-right:5px;
}
.weblog a{
color:#20a53a;
}
.firewall-port-box{
margin-bottom:15px;
}
</style>
<div class="main-content">
<div class="container-fluid">
<div class="pos-box bgw mtb15">
<div class="position f14 c9 pull-left">
<a class="plr10 c4" href="/">首页</a>/<span class="plr10 c4">动态追踪</span>
</div>
<div class="search pull-right">
<form target="hid" onsubmit='return false;'>
<input type="text" id="searchValue" class="ser-text pull-left" placeholder="进程ID" />
<button type="button" class="data-collect pull-left">采样</button>
</form>
</div>
</div>
<!-- //// -->
<div class="safe bgw pd15 mtb15" id="ff_box">
<div id="file_list" style="float:left;width:300px;">
<div class="tab-nav">
<span class="on">文件列表</span>
</div>
<div class="tab-con">
<div class="tab-block on">
<ul class="list" style="display: block; height: 94px;"></ul>
</div>
</div>
</div>
<div id="flame_graph" style="float:left;">
<div class="tab-nav">
<span class="on">火焰图</span>
</div>
<div class="tab-con">
<iframe class="tab-block on" width="100%" height="100%"
src=""
frameborder="0"
border="0"
marginwidth="0"
marginheight="0"
scrolling="yes"
noresize=""
allowfullscreen="allowfullscreen"
mozallowfullscreen="mozallowfullscreen"
msallowfullscreen="msallowfullscreen"
oallowfullscreen="oallowfullscreen"
webkitallowfullscreen="webkitallowfullscreen"
allowfullscreen="true"></iframe>
</div>
</div>
</div>
<!-- //// -->
</div>
</div>
+178
View File
@@ -0,0 +1,178 @@
function changeDivH(){
var l = $(window).height();
var w = $(window).width();
$('#ff_box').css('height',l-80-60);
$('#file_list').css('height',l-80-60);
$('#file_list .tab-con .list').css('height', l-80-60-70);
$('#flame_graph').css('height',l-80-60).css('width',w-300-200-40);
$('#flame_graph iframe').css('height',l-80-60-70);
}
$(document).ready(function(){
var tag = $.getUrlParam('tag');
if(tag == 'dynamic-tracking'){
dynamicTrackingLoad();
}
});
function dynamicTrackingLoad(){
changeDivH();
$(window).resize(function(){
changeDivH();
});
//加载采样数据列表
dtFileList();
}
$('.data-collect').click(function(){
layer.msg('开始采样',{icon:0,time:2000});
var pid = $('#searchValue').val();
dtPost('simple_trace', '', {pid:pid}, function(rdata){
// console.log(rdata);
var rdata = $.parseJSON(rdata.data);
layer.msg(rdata['msg'],{icon:rdata['status']?1:2,time:2000,shade: [0.3, '#000']});
});
});
function dtPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'dynamic-tracking';
req_data['func'] = method;
req_data['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', req_data, function(data) {
layer.close(loadT);
if (!data.status){
//错误展示10S
layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function dtPostCb(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var pdata = {};
pdata['name'] = 'dynamic-tracking';
pdata['func'] = method;
args['version'] = version;
if (typeof(args) == 'string'){
pdata['args'] = JSON.stringify(toArrayObject(args));
} else {
pdata['args'] = JSON.stringify(args);
}
$.post('/plugins/callback', pdata, 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 dtFileList(){
dtPost('file_list', '', {}, function(data){
var rdata = $.parseJSON(data.data);
var alist = rdata.data;
if (alist.length == 0){
var em ='<li class="data-file-list" style="text-align: center;">无数据</li>';
$('#file_list .list').html(em);
return;
}
var tli = '';
for (var i = 0; i < alist.length; i++) {
if (i==0){
tli +='<li title="双击打开浏览" class="data-file-list active" data-index="'+i+'" data-file="'+alist[i]['name']+'">\
<span class="file">'+alist[i]['name']+'</span>\
<span class="tootls">\
<span class="glyphicon glyphicon-link" aria-hidden="true" title="外部连接"></span>\
<span class="glyphicon glyphicon-trash" aria-hidden="true" title="删除"></span>\
</span>\
</li>';
} else{
tli +='<li class="data-file-list" data-index="'+i+'" data-file="'+alist[i]['name']+'">\
<span class="file">'+alist[i]['name']+'</span>\
<span class="tootls">\
<span class="glyphicon glyphicon-link" aria-hidden="true" title="外部连接"></span>\
<span class="glyphicon glyphicon-trash" aria-hidden="true" title="删除"></span>\
</span>\
</li>';
}
}
$('#file_list .list').html(tli);
dtGetFile(alist[0]['name']);
$('#file_list li .file').click(function(){
$('#file_list li').removeClass('active');
$(this).parent().addClass('active');
var i = $(this).parent().data('index');
dtGetFile(alist[i]['name']);
});
$('#file_list li .glyphicon-link').click(function(){
var i = $(this).parent().parent().data('index');
var abs_p = alist[i]['abs_path'];
var durl = '/files/download?filename='+abs_p;
window.open(durl);
});
$('#file_list li .glyphicon-trash').click(function(){
var i = $(this).parent().parent().data('index');
var f = alist[i]['name'];
dtPost('remove_file_path', '',{file:f}, function(rdata){
var rdata = $.parseJSON(rdata.data);
layer.msg(rdata['msg'],{icon:rdata['status']?1:2,time:2000});
if (rdata.status){
dtFileList();
}
});
});
});
}
function dtGetFile(file){
dtPost('get_file_path', '', {file:file}, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
if (!rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [2, '#000']});
return;
}
var durl = '/files/download?filename='+rdata.data;
$('#flame_graph .tab-con .tab-block').attr('src',durl);
});
}
@@ -0,0 +1,11 @@
#!/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_ARCH=`arch`
@@ -0,0 +1,26 @@
#!/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_ARCH=`arch`
# apt-get install linux-perf
# apt-get update -y
# strace -p $(ps -ef|grep "pool www" | awk '{print $2}' | grep -v grep | tr '\n' ',' )
# perf record -F 99 -p 2401699 -g -- sleep 30
# perf script > out.perf
# /www/server/dynamic-tracking/FlameGraph/stackcollapse-perf.pl out.perf > out.folded
# /www/server/dynamic-tracking/FlameGraph/flamegraph.pl out.folded > php-zend-flame-graph.svg
# WWW_PID=$(ps -ef|grep "pool www" | awk '{print $2}' | grep -v grep | tr '\n' ',')
# WWW_PID=${WWW_PID//,/}
# WWW_PID=${var%,}
# perf record -F 99 -p "1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1127,1128,1129,1130,1131,1473,1768,2848,2962,21582,35891" \
# -g -- sleep 30
@@ -0,0 +1,21 @@
#!/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_ARCH=`arch`
# 关于macosx使用dtrace
# https://groups.google.com/g/openresty/c/MswlH_8DDHA
# http://dtrace.org/blogs/brendan/2012/11/14/dtracing-in-anger/
# dtrace -x ustackframes=100 -n 'pid$target::mach_msg_trap:entry { @[ustack()] = count(); } tick-30s { exit(0); }' -p 18572 -o out.SystemUIServer_stacks
# /Users/midoks/Desktop/mwdev/server/dynamic-tracking/FlameGraph/stackcollapse.pl out.SystemUIServer_stacks > kernel.cbt
# /Users/midoks/Desktop/mwdev/server/dynamic-tracking/FlameGraph/flamegraph.pl kernel.cbt > kernel.svg
@@ -0,0 +1,11 @@
#!/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_ARCH=`arch`
+1
View File
@@ -65,6 +65,7 @@ binlog-ignore-db = performance_schema
#slave
log-slave-updates
slave_skip_errors=1062
#replicate-do-db
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
+2 -7
View File
@@ -2,7 +2,7 @@
<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>
<!-- <script type="text/javascript">console.log($('.plugin_version').attr('version'));</script> -->
<p class="bgw" onclick="pluginService('mariadb', $('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('mariadb', $('.plugin_version').attr('version'));">自启动</p>
<p onclick="pluginConfig('mariadb', $('.plugin_version').attr('version'));">配置文件</p>
@@ -15,14 +15,12 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<style type="text/css">
.db_list{
padding: 0px 0 10px 0;
@@ -52,10 +50,7 @@
</style>
<script type="text/javascript">
resetPluginWinWidth(800);
var loading = layer.msg("资源加载中...", { icon: 16, time: 0, shade: 0.3 });
$.getScript( "/plugins/file?name=mariadb&f=js/mariadb.js", function(){
layer.close(loading);
pluginService('mariadb',$('.plugin_version').attr('version'));
});
</script>
+258 -203
View File
@@ -48,19 +48,19 @@ def getInitDFile():
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = args[0].strip('{').strip('}').strip()
if (t == ''):
return tmp
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
@@ -107,6 +107,14 @@ def getDbPort():
return tmp.groups()[0].strip()
def getDbServerId():
file = getConf()
content = mw.readFile(file)
rep = 'server-id\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
@@ -664,15 +672,15 @@ def isSqlError(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, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -940,7 +948,7 @@ def getDbList():
def syncGetDatabases():
pdb = pMysqlDb()
pdb = pMysqlDb('mysql')
psdb = pSqliteDb('databases')
data = pdb.query('show databases')
isError = isSqlError(data)
@@ -1706,12 +1714,14 @@ def getMasterStatus(version=''):
data['mode'] = recognizeDbMode()
data['status'] = master_status
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb('mysql')
dlist = pdb.query('show slave status')
if len(dlist) < 1:
dlist = pdb.query("show all slaves 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
for v in dlist:
if v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes':
data['slave_status'] = True
return mw.returnJson(master_status, '设置成功', data)
except Exception as e:
@@ -1855,6 +1865,9 @@ def getMasterRepSlaveUserCmd(version):
clist = psdb.field(f).where("username=?", (username,)).limit(
'1').order('id desc').select()
if len(clist) == 0:
return mw.returnJson(False, '错误同步账户!')
ip = mw.getLocalIp()
port = getMyPort()
db = pMysqlDb()
@@ -1868,15 +1881,23 @@ def getMasterRepSlaveUserCmd(version):
# 查找同步点
# SELECT BINLOG_GTID_POS('master1-bin.000002', 561866201);
sid = getDbServerId()
connection_name = ""
if sid != '':
connection_name = "'r{}' ".format(sid)
# MASTER_USE_GTID={current_pos|slave_pos|no}
# current_pos 依赖-> select @@global.gtid_current_pos;
# slave_pos 依赖-> select @@global.gtid_slave_pos;
# no -> 啥都不依赖,保证多主同步成功。同步出现问题,根据日志查找问题。
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
sql = "CHANGE MASTER " + connection_name + "TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', " + "MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + \
str(mstatus[0]["Position"]) + \
",MASTER_USE_GTID=slave_pos,MASTER_CONNECT_RETRY=10;"
"',MASTER_USE_GTID=no,MASTER_CONNECT_RETRY=10;"
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
sql = "CHANGE MASTER " + connection_name + "TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
@@ -2151,48 +2172,20 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
tmp['Last_Error'] = dlist[x]["Last_Error"]
tmp['Last_IO_Error'] = dlist[x]["Last_IO_Error"]
tmp['Last_SQL_Error'] = dlist[x]["Last_SQL_Error"]
tmp['Slave_SQL_Running_State'] = dlist[x]["Slave_SQL_Running_State"]
if len(dlist) == 0:
dlist = db.query('show all slaves status')
tmp['Error'] = ''
if tmp['Last_Error'] != '':
tmp['Error'] = tmp['Last_Error']
if tmp['Last_IO_Error'] != '':
tmp['Error'] = tmp['Last_IO_Error']
if tmp['Last_SQL_Error'] != '':
tmp['Error'] = tmp['Last_SQL_Error']
if tmp['Error'] == '':
tmp['Error'] = tmp['Slave_SQL_Running_State']
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
cmd = 'cd ' + root + ' && python3 ' + root + \
'/plugins/mysql/index.py do_full_sync {"db":"all"}'
'/plugins/mariadb/index.py do_full_sync {"db":"all","sign":""}'
return mw.returnJson(True, 'ok', cmd)
@@ -2208,102 +2201,151 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version)
def parseSlaveSyncCmd(cmd):
a = {}
vlist = cmd.split(',')
has_connection_name = vlist[0]
pattern_c = r"CHANGE MASTER \'(.*)\' TO MASTER_HOST"
match_val = re.match(pattern_c, has_connection_name, re.I)
if match_val:
m_groups = match_val.groups()
a['Connection_name'] = m_groups[0]
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('id,ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
msg = ''
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb.query("stop slave")
pdb.query("stop all slaves")
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
# print(u['cmd'])
t = db.query(u['cmd'])
# print(t)
db.query("start slave")
return mw.returnJson(True, '初始化成功!')
mode_name = 'classic'
if slave_data[x]['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
pdb.query(cmd_sql)
pdb.query("start slave")
pdb.query("start all slaves ")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
if len(dlist) == 0:
dlist = db.query('show all slaves status')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa,db_user').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
for data in ssh_list:
ip = data['ip']
master_port = data['port']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
time.sleep(1)
ssh.close()
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
cmd_data = json.loads(result)
time.sleep(1)
ssh.close()
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
db.query('stop all slaves')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
# print(cmd)
db.query(cmd)
db.query("start slave")
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# print(cmd)
db.query(cmd)
db.query("start slave")
db.query("start all slaves")
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
os.system("rm -rf " + SSH_PRIVATE_KEY)
return mw.returnJson(True, '初始化成功!')
@@ -2312,61 +2354,39 @@ def setSlaveStatus(version=''):
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
dlist = pdb.query('show all slaves status')
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Connection_name' in v:
connection_name = v['Connection_name']
cmd = "slave '{}'".format(connection_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行[初始化]!')
# print(dlist)
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
db.query("start slave")
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave '{}'".format(sign))
db.query("reset slave '{}' all".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2402,14 +2422,54 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mariadb_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
def fullSync(version=''):
args = getArgs()
data = checkArgs(args, ['db', 'begin'])
if not data[0]:
return data[1]
sign = ''
if 'sign' in args:
sign = args['sign']
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
if os.path.exists(status_file):
c = mw.readFile(status_file)
tmp = json.loads(c)
if tmp['code'] == 1:
sys_dump_sql = "/tmp/dump.sql"
if os.path.exists(sys_dump_sql):
dump_size = os.path.getsize(sys_dump_sql)
tmp['msg'] = tmp['msg'] + ":" + "同步文件:" + mw.toSize(dump_size)
c = json.dumps(tmp)
# if tmp['code'] == 6:
# os.remove(status_file)
return c
return json.dumps({'code': 0, 'msg': '点击开始,开始同步!', 'progress': 0})
def doFullSync(version=''):
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
@@ -2424,16 +2484,23 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
# print(sync_sign, sync_db)
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2442,12 +2509,12 @@ def doFullSyncUser(version=''):
bak_file = '/tmp/tmp.sql'
writeDbSyncStatus({'code': 0, 'msg': '开始同步...', 'progress': 0})
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 10})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file
print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
@@ -2458,24 +2525,38 @@ def doFullSyncUser(version=''):
' ' + sync_db + ' < ' + bak_file
mw.execShell(my_import_cmd)
db.query("start slave")
pinfo = parseSlaveSyncCmd(data['cmd'])
# print(pinfo)
if 'Connection_name' in pinfo:
db.query("start slave '{}'".format(pinfo['Connection_name']))
else:
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
db = pMysqlDb()
sync_db = args['db']
sync_sign = args['sign']
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2498,7 +2579,6 @@ def doFullSyncSSH(version=''):
return 'fail'
try:
# ssh.load_system_host_keys()
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
@@ -2516,7 +2596,7 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && python3 plugins/mariadb/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 plugins/mariadb/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2539,13 +2619,19 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mariadb/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result == '':
writeDbSyncStatus({'code': 1, 'msg': '同步命令获取失败!', 'progress': 100})
return 'fail'
cmd_data = json.loads(result)
db.query('stop slave')
db.query('stop all slaves')
writeDbSyncStatus({'code': 3, 'msg': '停止从库完成...', 'progress': 45})
cmd = cmd_data['data']['cmd']
@@ -2578,6 +2664,7 @@ def doFullSyncSSH(version=''):
return 'fail'
db.query("start slave")
db.query("start all slaves")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2585,38 +2672,6 @@ def doFullSyncSSH(version=''):
return True
def fullSync(version=''):
args = getArgs()
data = checkArgs(args, ['db', 'begin'])
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
if os.path.exists(status_file):
c = mw.readFile(status_file)
tmp = json.loads(c)
if tmp['code'] == 1:
sys_dump_sql = "/tmp/dump.sql"
if os.path.exists(sys_dump_sql):
dump_size = os.path.getsize(sys_dump_sql)
tmp['msg'] = tmp['msg'] + ":" + "同步文件:" + mw.toSize(dump_size)
c = json.dumps(tmp)
# if tmp['code'] == 6:
# os.remove(status_file)
return c
return json.dumps({'code': 0, 'msg': '点击开始,开始同步!', 'progress': 0})
def installPreInspection(version):
swap_path = mw.getServerDir() + "/swap"
if not os.path.exists(swap_path):
+178 -86
View File
@@ -431,7 +431,6 @@ function syncToDatabase(type){
var postData = 'type='+type+'&ids='+JSON.stringify(data);
myPost('sync_to_databases', postData, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
showMsg(rdata.msg,function(){
dbList();
},{ icon: rdata.status ? 1 : 2 });
@@ -439,18 +438,6 @@ function syncToDatabase(type){
}
function setRootPwd(type, pwd){
if (type==1){
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
$('.layui-layer-close1').click();
},{icon: rdata.status ? 1 : 2});
});
return;
}
var index = layer.open({
type: 1,
area: '500px',
@@ -467,8 +454,16 @@ function setRootPwd(type, pwd){
</div>\
</div>\
</form>",
yes:function(){
setRootPwd(1);
yes:function(index,layero){
var password = $("#MyPassword").val();
myPost('set_root_pwd', {password:password}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dbList();
layer.close(index);
},{icon: rdata.status ? 1 : 2});
});
return;
}
});
}
@@ -490,7 +485,6 @@ function showHidePass(obj){
function checkSelect(){
setTimeout(function () {
var num = $('input[type="checkbox"].check:checked').length;
// console.log(num);
if (num == 1) {
$('button[batch="true"]').hide();
$('button[batch="false"]').show();
@@ -861,7 +855,6 @@ function downloadBackup(file){
function importBackup(file,name){
myPost('import_db_backup',{file:file,name:name}, function(data){
// console.log(data);
layer.msg('执行成功!');
});
}
@@ -1619,7 +1612,6 @@ function getMasterRepSlaveList(){
_data['page'] = page;
_data['page_size'] = 10;
myPost('get_master_rep_slave_list', _data, function(data){
// console.log(data);
var rdata = [];
try {
rdata = $.parseJSON(data.data);
@@ -1672,12 +1664,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign = ''){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1685,28 +1677,72 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Connection_name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
function fullSync(db, sign, begin){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1715,23 +1751,11 @@ function getFullSyncStatus(db){
if (rdata['code']==6 ||rdata['code']<0){
layer.msg(rdata['msg']);
clearInterval(timeId);
$("#begin_full_sync").attr('data-status','init');
$("#begin_full_sync").data('status','init');
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -2077,7 +2101,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2101,7 +2125,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2142,11 +2166,15 @@ function handlerRun(){
function initSlaveStatus(){
myPost('init_slave_status', '', function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status ){
layer.msg(rdata.msg,{icon:2,time:10000});
return;
}
showMsg(rdata.msg,function(){
if (rdata.status){
masterOrSlaveConf();
}
},{icon:rdata.status?1:2},2000);
},{icon:1},2000);
});
}
@@ -2204,33 +2232,48 @@ function masterOrSlaveConf(version=''){
}
_data['page'] = page;
_data['page_size'] = 10;
_data['page_size'] = 100;
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Connection_name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
list += '<tr>';
list += '<td>' + rdata.data[i]['Master_Host'] +'</td>';
list += '<td>' + rdata.data[i]['Master_Port'] +'</td>';
list += '<td>' + rdata.data[i]['Master_User'] +'</td>';
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
list += '<td>' + v['Master_Host'] +'</td>';
list += '<td>' + v['Master_Port'] +'</td>';
list += '<td>' + v['Master_User'] +'</td>';
list += '<td>' + v['Master_Log_File'] +'</td>';
list += '<td>' + v['Slave_IO_Running'] +'</td>';
list += '<td>' + v['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Connection_name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'</td>';
list += '<td style="text-align:right">\
<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>\
</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2241,6 +2284,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2255,22 +2299,75 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Connection_name' in v){
deleteSlave(v['Connection_name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
@@ -2320,14 +2417,12 @@ function masterOrSlaveConf(version=''){
});
}
function getMasterStatus(){
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});
layer.msg(rdata.msg, {icon:2,time:2000});
return;
}
@@ -2409,7 +2504,6 @@ function masterOrSlaveConf(version=''){
return false;
},
change:function(index,mode,reload){
console.log(index,mode,reload);
myPost('set_dbrun_mode',{'mode':mode,'reload':reload},function(data){
layer.close(index);
var rdata = $.parseJSON(data.data);
@@ -2425,10 +2519,8 @@ function masterOrSlaveConf(version=''){
getMasterDbList();
}
// if (rdata.slave_status){
getAsyncMasterDbList();
getAsyncDataList()
// }
getAsyncMasterDbList();
getAsyncDataList()
});
}
getMasterStatus();
+2 -2
View File
@@ -87,7 +87,7 @@ class backupTools:
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(
mw.M('backup').add('type,name,pid,filename,addtime,size', (3, os.path.basename(
filename), pid, filename, endDate, os.path.getsize(filename)))
log = "数据库[" + name + "]备份成功,用时[" + str(round(outTime, 2)) + "]秒"
mw.writeLog('计划任务', log)
@@ -97,7 +97,7 @@ class backupTools:
# 清理多余备份
backups = mw.M('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
'type=? and pid=?', ('3', pid)).field('id,filename').select()
num = len(backups) - int(count)
if num > 0:
+10 -1
View File
@@ -71,10 +71,19 @@ Install_app()
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
+10 -1
View File
@@ -73,8 +73,17 @@ Install_app()
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
+9 -1
View File
@@ -72,9 +72,17 @@ Install_app()
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
+50 -11
View File
@@ -14,6 +14,10 @@ if mw.isAppleSystem():
app_debug = True
import warnings
warnings.filterwarnings('ignore', category=DeprecationWarning)
def getPluginName():
return 'memcached'
@@ -27,8 +31,13 @@ def getServerDir():
def getInitDFile():
if app_debug:
current_os = mw.getOs()
if current_os == 'darwin':
return '/tmp/' + getPluginName()
if current_os.startswith('freebsd'):
return '/etc/rc.d/' + getPluginName()
return '/etc/init.d/' + getPluginName()
@@ -84,7 +93,7 @@ def checkArgs(data, ck=[]):
def status():
data = mw.execShell(
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
"ps aux|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
@@ -109,8 +118,8 @@ def initDreplace():
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/memcached.service'
systemServiceTpl = getPluginDir() + '/init.d/memcached.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
systemServiceTpl = getPluginDir() + '/init.d/memcached.service.tpl'
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
@@ -133,13 +142,20 @@ def initDreplace():
def memOp(method):
file = initDreplace()
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
current_os = mw.getOs()
if current_os == "darwin":
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell(file + ' ' + method)
if current_os.startswith("freebsd"):
data = mw.execShell('service ' + getPluginName() + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return data[1]
@@ -222,9 +238,15 @@ def saveConf():
def initdStatus():
if mw.isAppleSystem():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
@@ -234,17 +256,34 @@ def initdStatus():
def initdInstall():
if mw.isAppleSystem():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
# freebsd initd install
if current_os.startswith('freebsd'):
import shutil
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="YES"')
return 'ok'
mw.execShell('systemctl enable ' + getPluginName())
return 'ok'
def initdUinstall():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="NO"')
return 'ok'
mw.execShell('systemctl disable ' + getPluginName())
return 'ok'
+1 -1
View File
@@ -6,7 +6,7 @@ port = 27017
fork = true
auth = false
# 5.0.2 - Master/slave replication is no longer supported
# Master/slave replication is no longer supported
#master = true
pidfilepath = {$SERVER_PATH}/mongodb/mongodb.pid
+37 -51
View File
@@ -35,13 +35,8 @@ def getInitDFile():
def getConf():
if mw.isAppleSystem():
path = getServerDir() + "/mongodb.conf"
return path
if os.path.exists("/etc/mongodb.conf"):
return "/etc/mongodb.conf"
return "/etc/mongod.conf"
path = getServerDir() + "/mongodb.conf"
return path
def getConfTpl():
@@ -90,6 +85,14 @@ def initDreplace():
os.mkdir(initD_path)
file_bin = initD_path + '/' + getPluginName()
logs_dir = getServerDir() + '/logs'
if not os.path.exists(logs_dir):
os.mkdir(logs_dir)
data_dir = getServerDir() + '/data'
if not os.path.exists(data_dir):
os.mkdir(data_dir)
# initd replace
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
@@ -101,6 +104,17 @@ def initDreplace():
conf_content = conf_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(getServerDir() + '/mongodb.conf', conf_content)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/mongodb.service'
systemServiceTpl = getPluginDir() + '/init.d/mongodb.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
@@ -112,14 +126,10 @@ def mgOp(method):
return 'ok'
return data[1]
cmd = 'systemctl ' + method + ' mongod'
if os.path.exists("/usr/lib/systemd/system/mongodb.service"):
cmd = 'systemctl ' + start + ' mongodb'
data = mw.execShell(cmd)
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return data[1]
return 'fail'
def start():
@@ -162,13 +172,7 @@ def runInfo():
result["version"] = serverStatus['version']
result["uptime"] = serverStatus['uptime']
result['db_path'] = '/var/lib/mongo'
if os.path.exists("/var/lib/mongodb"):
result['db_path'] = '/var/lib/mongodb'
if mw.isAppleSystem():
result['db_path'] = getServerDir() + "/data"
result['db_path'] = getServerDir() + "/data"
result["connections"] = serverStatus['connections']['current']
if 'catalogStats' in serverStatus:
@@ -182,11 +186,7 @@ def initdStatus():
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status mongod | grep loaded | grep "enabled;"'
if os.path.exists("/usr/lib/systemd/system/mongodb.service"):
shell_cmd = 'systemctl status mongodb | grep loaded | grep "enabled;"'
shell_cmd = 'systemctl status mongodb | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
@@ -197,10 +197,7 @@ def initdInstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
if os.path.exists("/usr/lib/systemd/system/mongodb.service"):
mw.execShell('systemctl enable mongodb')
else:
mw.execShell('systemctl enable mongod')
mw.execShell('systemctl enable mongodb')
return 'ok'
@@ -208,24 +205,21 @@ def initdUinstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
if os.path.exists("/usr/lib/systemd/system/mongodb.service"):
mw.execShell('systemctl disable mongodb')
else:
mw.execShell('systemctl disable mongod')
mw.execShell('systemctl disable mongodb')
return 'ok'
def runLog():
if mw.isAppleSystem():
return getServerDir() + '/logs/mongodb.log'
if os.path.exists("/var/log/mongodb/mongodb.log"):
return "/var/log/mongodb/mongodb.log"
return "/var/log/mongodb/mongod.log"
f = getServerDir() + '/logs/mongodb.log'
if os.path.exists(f):
return f
return getServerDir() + '/logs.pl'
def installPreInspection(version):
if mw.isAppleSystem():
return 'ok'
sys = mw.execShell(
"cat /etc/*-release | grep PRETTY_NAME |awk -F = '{print $2}' | awk -F '\"' '{print $2}'| awk '{print $1}'")
@@ -238,17 +232,9 @@ def installPreInspection(version):
sysName = sys[0].strip().lower()
sysId = sys_id[0].strip()
if not sysName in ('centos', 'fedora', 'ubuntu', 'debian'):
return '暂时仅不支持{}'.format(sysName)
if sysName == 'debian':
if version > 10:
return 'mongodb[' + version + ']不支持安装在debian[' + sysId + ']'
if sysName == 'ubuntu':
if version < 16:
return 'mongodb[' + version + ']不支持安装在ubuntu[' + sysId + ']'
supportOs = ['centos', 'ubuntu', 'debian', 'opensuse']
if not sysName in supportOs:
return '暂时仅支持{}'.format(','.join(supportOs))
return 'ok'
if __name__ == "__main__":
+2 -2
View File
@@ -4,8 +4,8 @@
"name": "mongodb",
"title": "Mongodb",
"shell": "install.sh",
"versions":["4.4","5.0"],
"updates":["4.4","5.0"],
"install_pre_inspection":true,
"versions":["4.4","5.0","6.0","7.0"],
"tip": "soft",
"checks": "server/mongodb",
"path": "server/mongodb",
@@ -0,0 +1,36 @@
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network-online.target
Wants=network-online.target
[Service]
User=root
Group=root
#EnvironmentFile=-/etc/default/mongod
Environment="MONGODB_CONFIG_OVERRIDE_NOFORK=1"
PIDFile={$SERVER_PATH}/mongodb/mongodb.pid
ExecStart={$SERVER_PATH}/mongodb/bin/mongod -f {$SERVER_PATH}/mongodb/mongodb.conf
ExecReload=/bin/kill -HUP $MAINPID
#RuntimeDirectory=mongodb
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings
[Install]
WantedBy=multi-user.target
+4 -3
View File
@@ -30,8 +30,9 @@ app_start(){
echo "Starting mongodb server..."
echo $EXEC -f $CONF
$EXEC -f $CONF >> {$SERVER_PATH}/mongodb/logs.pl 2>&1 &
$EXEC -f $CONF >> {$SERVER_PATH}/mongodb/logs.pl 1>&1 2>&1 &
}
app_stop(){
if [ ! -f $PIDFILE ]
then
@@ -42,10 +43,10 @@ app_stop(){
kill -9 $PID
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
echo "Waiting for mongodb to shutdown ..."
sleep 1
done
echo "Redis stopped"
echo "mongodb stopped"
rm -rf $PIDFILE
fi
}
+287
View File
@@ -0,0 +1,287 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
# cd /www/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
sysName=`uname`
echo "use system: ${sysName}"
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
Install_app_mac()
{
mkdir -p $serverPath/mongodb
if [ "$VERSION" == "5.0" ];then
G_VERSION="5.0.11"
elif [[ "$VERSION" == "4.4" ]]; then
G_VERSION="4.4.11"
fi
if [ ! -f $serverPath/source/mongodb-macos-x86_64-${G_VERSION}.tgz ];then
wget -O $serverPath/source/mongodb-macos-x86_64-${G_VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${G_VERSION}.tgz
fi
cd $serverPath/source && tar -zxvf mongodb-macos-x86_64-${G_VERSION}.tgz
cd mongodb-macos-x86_64-${G_VERSION} && mv ./* $serverPath/mongodb
}
Install_Linux_Ubuntu()
{
##################### Ubuntu start #####################
if [ "$SYS_VERSION_ID" == "22" ]; then
echo "Not yet supported"
exit 1
fi
echo $SYS_VERSION_ID
SOURCE_NAME=bionic
if [ "$SYS_VERSION_ID" == "18.04" ];then
SOURCE_NAME=bionic
elif [ "$SYS_VERSION_ID" == "16.04" ];then
SOURCE_NAME=xenial
elif [ "$SYS_VERSION_ID" == "20.04" ];then
SOURCE_NAME=focal
fi
# wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
# apt install -y gnupg
# touch /etc/apt/sources.list.d/mongodb-org-4.4.list
# echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
wget -qO - https://www.mongodb.org/static/pgp/server-${VERSION}.asc | sudo apt-key add -
apt install -y gnupg
touch /etc/apt/sources.list.d/mongodb-org-${VERSION}.list
lsb_release -dc
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu ${SOURCE_NAME}/mongodb-org/${VERSION} multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-${VERSION}.list
apt update -y
apt install -y mongodb-org
##################### Ubuntu end #####################
}
Uninstall_Linux_Ubuntu()
{
if [ -f /lib/systemd/system/mongod.service ] || [ -f /usr/lib/systemd/system/mongod.service ] ;then
systemctl stop mongod
fi
apt purge -y mongodb-org*
apt autoremove -y
rm -r /var/log/mongodb
rm -r /var/lib/mongodb
}
Install_Linux_Debian()
{
##################### debian start #####################
if [ "$SYS_VERSION_ID" -eq "11" ] && [ "$VERSION" -eq "4.4" ]; then
echo "Not yet supported"
exit 1
fi
if [ -f /usr/lib/systemd/system/mongod.service ];then
echo 'alreay install exist!'
exit 0
fi
wget -qO - https://www.mongodb.org/static/pgp/server-${VERSION}.asc | sudo apt-key add -
apt install -y gnupg
wget -qO - https://www.mongodb.org/static/pgp/server-${VERSION}.asc | sudo apt-key add -
echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/${VERSION} main" | sudo tee /etc/apt/sources.list.d/mongodb-org-${VERSION}.list
apt update -y
apt install -y mongodb-org
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections
##################### debian end #####################
}
Uninstall_Linux_Debian()
{
systemctl stop mongod
apt purge -y mongodb-org*
apt autoremove -y
rm -r /var/log/mongodb
rm -r /var/lib/mongodb
}
Install_Linux_Opensuse()
{
##################### opensuse start #####################
if [ "$SYS_VERSION_ID" -gt "15" ]; then
echo "Not yet supported"
exit 1
fi
if [ -f /usr/lib/systemd/system/mongod.service ];then
echo 'alreay exist!'
exit 0
fi
rpm --import https://www.mongodb.org/static/pgp/server-${VERSION}.asc
zypper addrepo --gpgcheck "https://repo.mongodb.org/zypper/suse/15/mongodb-org/${VERSION}/x86_64/" mongodb
zypper -n install mongodb-org
# zypper install mongodb-org-4.4.15 mongodb-org-server-4.4.15 mongodb-org-shell-4.4.15 mongodb-org-mongos-4.4.15 mongodb-org-tools-4.4.15
##################### opensuse end #####################
}
Uninstall_Linux_Opensuse()
{
systemctl stop mongod
zypper remove -y $(rpm -qa | grep mongodb-org)
rm -r /var/log/mongodb
rm -r /var/lib/mongo
}
# https://repo.mongodb.org/yum/redhat/7/mongodb-org/5.0/x86_64/RPMS/mongodb-org-server-5.0.4-1.el7.x86_64.rpm
Install_Linux_CentOS()
{
if [ -f /usr/lib/systemd/system/mongod.service ];then
echo 'alreay exist!'
exit 0
fi
#清空mongo的repo源
rm -rf /etc/yum.repos.d/mongodb-org-*
##################### centos start #####################
echo "
[mongodb-org-${VERSION}]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/${VERSION}/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-${VERSION}.asc
" > /etc/yum.repos.d/mongodb-org-${VERSION}.repo
yum install -y mongodb-org
##################### centos end #####################
}
Uninstall_Linux_CentOS()
{
systemctl stop mongod
yum erase -y $(rpm -qa | grep mongodb-org)
rm -r /var/log/mongodb
rm -r /var/lib/mongo
rm -rf /etc/yum.repos.d/mongodb-org-${VERSION}.repo
}
Install_app_linux()
{
if [ "$OSNAME" == "ubuntu" ];then
Install_Linux_Ubuntu
elif [ "$OSNAME" == "debian" ];then
Install_Linux_Debian
elif [ "$OSNAME" == "centos" ];then
Install_Linux_CentOS
elif [ "$OSNAME" == "opensuse" ];then
Install_Linux_Opensuse
else
echo "Not yet supported"
exit 1
fi
}
Install_app()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
if [ "macos" == "$OSNAME" ];then
Install_app_mac
else
Install_app_linux
fi
if [ "$?" == "0" ];then
mkdir -p $serverPath/mongodb
echo "${VERSION}" > $serverPath/mongodb/version.pl
echo '安装完成' > $install_tmp
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/mongodb/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/mongodb/index.py initd_install
fi
}
Uninstall_app_linux()
{
##################
if [ "$OSNAME" == "ubuntu" ];then
Uninstall_Linux_Ubuntu
elif [ "$OSNAME" == "debian" ];then
Uninstall_Linux_Debian
elif [ "$OSNAME" == "centos" ];then
Uninstall_Linux_CentOS
elif [ "$OSNAME" == "opensuse" ];then
Uninstall_Linux_Opensuse
else
echo "ok"
fi
##################
}
Uninstall_app()
{
if [ "macos" == "$OSNAME" ];then
echo 'mac'
else
Uninstall_app_linux
fi
rm -rf $serverPath/mongodb
echo "Uninstall_mongodb" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+107
View File
@@ -0,0 +1,107 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
# cd /www/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
sysName=`uname`
echo "use system: ${sysName}"
# bash ${rootPath}/scripts/getos.sh
# OSNAME=`cat ${rootPath}/data/osname.pl`
# SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
Install_app()
{
# ----- 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 ------
echo '正在安装脚本文件...' > $install_tmp
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh
echo "cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh"
export PKG_CONFIG_PATH=$serverPath/lib/openssl/lib/pkgconfig
if [ ! -f $MG_DIR/mongodb-src-r${VERSION}.tar.gz ]; then
wget --no-check-certificate -O $MG_DIR/mongodb-src-r${VERSION}.tar.gz https://fastdl.mongodb.org/src/mongodb-src-r${VERSION}.tar.gz
echo "wget --no-check-certificate -O $MG_DIR/mongodb-src-r${VERSION}.tar.gz https://fastdl.mongodb.org/src/mongodb-src-r${VERSION}.tar.gz"
fi
if [ ! -d $MG_DIR/mongodb-src-r${VERSION} ];then
cd $MG_DIR && tar -zxvf $MG_DIR/mongodb-src-r${VERSION}.tar.gz
fi
cd $MG_DIR/mongodb-src-r${VERSION} && python3 -m pip install requirements_parser
cd $MG_DIR/mongodb-src-r${VERSION} && python3 -m pip install -r etc/pip/compile-requirements.txt
# cd $MG_DIR/mongodb-src-r${VERSION} && python3 buildscripts/scons.py all -j 2
# echo "cd $MG_DIR/mongodb-src-r${VERSION} && python3 buildscripts/scons.py all -j 2"
# cd $MG_DIR/mongodb-src-r${VERSION} && python3 buildscripts/scons.py all MONGO_VERSION=${VERSION} -j 4
cd $MG_DIR/mongodb-src-r${VERSION} && python3 buildscripts/scons.py install-mongod MONGO_VERSION=${VERSION} -j ${cpuCore}
cd $MG_DIR/mongodb-src-r${VERSION} && python3 buildscripts/scons.py DESTDIR=$serverPath/mongodb install-mongod MONGO_VERSION=${VERSION} \
--ssl=off
echo "cd $MG_DIR/mongodb-src-r${VERSION} && python3 buildscripts/scons.py DESTDIR=$serverPath/mongodb install MONGO_VERSION=${VERSION} \
--ssl=off CPPPATH=$serverPath/lib/openssl/include \
LIBPATH=$serverPath/lib/openssl/lib"
if [ "$?" == "0" ];then
mkdir -p $serverPath/mongodb
echo "${VERSION}" > $serverPath/mongodb/version.pl
echo '安装完成' > $install_tmp
#初始化
cd ${rootPath} && python3 ${rootPath}/plugins/mongodb/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/mongodb/index.py initd_install
fi
}
Uninstall_app()
{
rm -rf $serverPath/mongodb
echo "Uninstall_mongodb" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+51 -240
View File
@@ -2,8 +2,15 @@
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
# cd /www/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
# https://www.mongodb.com/try/download/community
'''
cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 5.0.4
cd /www/server/mdserver-web/plugins/mongodb && /bin/bash install.sh install 7.0
cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/mongodb/index.py start
'''
curPath=`pwd`
rootPath=$(dirname "$curPath")
@@ -16,230 +23,48 @@ VERSION=$2
sysName=`uname`
echo "use system: ${sysName}"
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
OSNAME=`bash ${rootPath}/scripts/getos.sh`
Install_app_mac()
{
mkdir -p $serverPath/mongodb
if [ "$VERSION" == "5.0" ];then
G_VERSION="5.0.11"
elif [[ "$VERSION" == "4.4" ]]; then
G_VERSION="4.4.11"
fi
if [ ! -f $serverPath/source/mongodb-macos-x86_64-${G_VERSION}.tgz ];then
wget -O $serverPath/source/mongodb-macos-x86_64-${G_VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${G_VERSION}.tgz
fi
cd $serverPath/source && tar -zxvf mongodb-macos-x86_64-${G_VERSION}.tgz
cd mongodb-macos-x86_64-${G_VERSION} && mv ./* $serverPath/mongodb
}
Install_Linux_Ubuntu()
{
##################### Ubuntu start #####################
if [ "$SYS_VERSION_ID" == "22" ]; then
echo "Not yet supported"
exit 1
if [ "" == "$OSNAME" ];then
OSNAME=`cat ${rootPath}/data/osname.pl`
fi
echo $SYS_VERSION_ID
SOURCE_NAME=bionic
if [ "$SYS_VERSION_ID" == "18.04" ];then
SOURCE_NAME=bionic
elif [ "$SYS_VERSION_ID" == "16.04" ];then
SOURCE_NAME=xenial
elif [ "$SYS_VERSION_ID" == "20.04" ];then
SOURCE_NAME=focal
if [ "macos" != "$OSNAME" ];then
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
fi
# wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
# apt install -y gnupg
# touch /etc/apt/sources.list.d/mongodb-org-4.4.list
# echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
wget -qO - https://www.mongodb.org/static/pgp/server-${VERSION}.asc | sudo apt-key add -
apt install -y gnupg
touch /etc/apt/sources.list.d/mongodb-org-${VERSION}.list
lsb_release -dc
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu ${SOURCE_NAME}/mongodb-org/${VERSION} multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-${VERSION}.list
apt update -y
apt install -y mongodb-org
##################### Ubuntu end #####################
}
Uninstall_Linux_Ubuntu()
{
if [ -f /lib/systemd/system/mongod.service ] || [ -f /usr/lib/systemd/system/mongod.service ] ;then
systemctl stop mongod
fi
apt purge -y mongodb-org*
apt autoremove -y
rm -r /var/log/mongodb
rm -r /var/lib/mongodb
}
Install_Linux_Debian()
{
##################### debian start #####################
if [ "$SYS_VERSION_ID" -eq "11" ] && [ "$VERSION" -eq "4.4" ]; then
echo "Not yet supported"
exit 1
fi
if [ -f /usr/lib/systemd/system/mongod.service ];then
echo 'alreay install exist!'
exit 0
fi
wget -qO - https://www.mongodb.org/static/pgp/server-${VERSION}.asc | sudo apt-key add -
apt install -y gnupg
wget -qO - https://www.mongodb.org/static/pgp/server-${VERSION}.asc | sudo apt-key add -
echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/${VERSION} main" | sudo tee /etc/apt/sources.list.d/mongodb-org-${VERSION}.list
apt update -y
apt install -y mongodb-org
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections
##################### debian end #####################
}
Uninstall_Linux_Debian()
{
systemctl stop mongod
apt purge -y mongodb-org*
apt autoremove -y
rm -r /var/log/mongodb
rm -r /var/lib/mongodb
}
Install_Linux_Opensuse()
{
##################### opensuse start #####################
if [ "$SYS_VERSION_ID" -gt "15" ]; then
echo "Not yet supported"
exit 1
fi
if [ -f /usr/lib/systemd/system/mongod.service ];then
echo 'alreay exist!'
exit 0
fi
rpm --import https://www.mongodb.org/static/pgp/server-${VERSION}.asc
zypper addrepo --gpgcheck "https://repo.mongodb.org/zypper/suse/15/mongodb-org/${VERSION}/x86_64/" mongodb
zypper -n install mongodb-org
# zypper install mongodb-org-4.4.15 mongodb-org-server-4.4.15 mongodb-org-shell-4.4.15 mongodb-org-mongos-4.4.15 mongodb-org-tools-4.4.15
##################### opensuse end #####################
}
Uninstall_Linux_Opensuse()
{
systemctl stop mongod
zypper remove -y $(rpm -qa | grep mongodb-org)
rm -r /var/log/mongodb
rm -r /var/lib/mongo
}
# https://repo.mongodb.org/yum/redhat/7/mongodb-org/5.0/x86_64/RPMS/mongodb-org-server-5.0.4-1.el7.x86_64.rpm
Install_Linux_CentOS()
{
if [ -f /usr/lib/systemd/system/mongod.service ];then
echo 'alreay exist!'
exit 0
fi
#清空mongo的repo源
rm -rf /etc/yum.repos.d/mongodb-org-*
##################### centos start #####################
echo "
[mongodb-org-${VERSION}]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/${VERSION}/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-${VERSION}.asc
" > /etc/yum.repos.d/mongodb-org-${VERSION}.repo
yum install -y mongodb-org
##################### centos end #####################
}
Uninstall_Linux_CentOS()
{
systemctl stop mongod
yum erase -y $(rpm -qa | grep mongodb-org)
rm -r /var/log/mongodb
rm -r /var/lib/mongo
rm -rf /etc/yum.repos.d/mongodb-org-${VERSION}.repo
}
Install_app_linux()
{
if [ "$OSNAME" == "ubuntu" ];then
Install_Linux_Ubuntu
elif [ "$OSNAME" == "debian" ];then
Install_Linux_Debian
elif [ "$OSNAME" == "centos" ];then
Install_Linux_CentOS
elif [ "$OSNAME" == "opensuse" ];then
Install_Linux_Opensuse
else
echo "Not yet supported"
exit 1
fi
}
Install_app()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
if [ "macos" == "$OSNAME" ];then
Install_app_mac
# if id mongodb &> /dev/null ;then
# echo "mongodb uid is `id -u mongodb`"
# echo "mongodb shell is `grep "^mongodb:" /etc/passwd |cut -d':' -f7 `"
# else
# groupadd mongodb
# useradd -g mongodb mongodb
# fi
# if [ "centos" == "$OSNAME" ];then
# OSNAME=rhel
# fi
# if [ "fedora" == "$OSNAME" ];then
# OSNAME=rhel
# fi
# if [ "rocky" == "$OSNAME" ];then
# OSNAME=rhel
# fi
shell_file=${curPath}/versions/${VERSION}/${OSNAME}.sh
if [ -f $shell_file ];then
bash -x $shell_file
else
Install_app_linux
echo '不支持...' > $install_tmp
exit 1
fi
if [ "$?" == "0" ];then
@@ -253,34 +78,20 @@ Install_app()
fi
}
Uninstall_app_linux()
{
##################
if [ "$OSNAME" == "ubuntu" ];then
Uninstall_Linux_Ubuntu
elif [ "$OSNAME" == "debian" ];then
Uninstall_Linux_Debian
elif [ "$OSNAME" == "centos" ];then
Uninstall_Linux_CentOS
elif [ "$OSNAME" == "opensuse" ];then
Uninstall_Linux_Opensuse
else
echo "ok"
fi
##################
}
Uninstall_app()
{
if [ "macos" == "$OSNAME" ];then
echo 'mac'
else
Uninstall_app_linux
cd ${rootPath} && python3 ${rootPath}/plugins/mongodb/index.py stop
rm -rf $serverPath/mongodb
if [ -f /usr/lib/systemd/system/mongodb.service ] || [ -f /lib/systemd/system/mongodb.service ];then
systemctl stop mongodb
systemctl disable mongodb
rm -rf /usr/lib/systemd/system/mongodb.service
rm -rf /lib/systemd/system/mongodb.service
systemctl daemon-reload
fi
rm -rf $serverPath/mongodb
echo "Uninstall_mongodb" > $install_tmp
}
+66
View File
@@ -0,0 +1,66 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=4.4.23
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
SYS_NAME_LEN=`echo "$SYS_NAME" | wc -L`
if [ "$SYS_NAME_LEN" == "1" ];then
SYS_NAME=${SYS_NAME}0
fi
if [ "$SYS_ARCH" == "aarch64" ];then
if [ "$SYS_NAME" -gt "82" ];then
SYS_NAME="82"
fi
if [ "$SYS_NAME" -lt "62" ];then
SYS_NAME="62"
fi
else
if [ "$SYS_NAME" -gt "80" ];then
SYS_NAME="80"
fi
if [ "$SYS_NAME" -lt "70" ];then
SYS_NAME="70"
fi
fi
# https://fastdl.mongodb.org/linux/mongodb-linux-aarch64-rhel82-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-aarch64-rhel82-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.4.23.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-rhel${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=4.4.23
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
if [ "$SYS_NAME" -gt "10" ];then
SYS_NAME="10"
fi
if [ "$SYS_NAME" -lt "10" ];then
SYS_NAME="10"
fi
FILE_NAME=mongodb-linux-${SYS_ARCH}-debian${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME_TGZ} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME}} && cp -rf ./bin $serverPath/mongodb
fi
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=4.4.23
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz ]; then
wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz
echo "wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz"
fi
if [ ! -d $MG_DIR/mongodb-macos-x86_64-${VERSION} ];then
cd $MG_DIR && tar -zxvf mongodb-macos-x86_64-${VERSION}.tgz
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/mongodb-macos-x86_64-${VERSION} && cp -rf ./bin $serverPath/mongodb
fi
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=4.4.23
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}' | awk -F . '{print $1}'`
SYS_NAME="15"
if [ "$SYS_VERSION_ID" -gt "15" ];then
SYS_NAME="15"
fi
if [ "$SYS_NAME" -lt "12" ];then
SYS_NAME="12"
fi
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse15-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse12-4.4.23.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-suse${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=4.4.23
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
SYS_NAME_LEN=`echo "$SYS_NAME" | wc -L`
if [ "$SYS_NAME_LEN" == "1" ];then
SYS_NAME=${SYS_NAME}0
fi
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.23.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-ubuntu${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=4.4.23
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-4.4.23.tgz
if [ "$SYS_NAME" -gt "2004" ];then
SYS_NAME="2004"
fi
if [ "$SYS_NAME" -lt "1604" ];then
SYS_NAME="1604"
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-ubuntu${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+53
View File
@@ -0,0 +1,53 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=5.0.20
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
SYS_NAME_LEN=`echo "$SYS_NAME" | wc -L`
if [ "$SYS_NAME_LEN" == "1" ];then
SYS_NAME=${SYS_NAME}0
fi
if [ "$SYS_ARCH" == "aarch64" ];then
SYS_NAME="82"
else
if [ "$SYS_NAME" -gt "80" ];then
SYS_NAME="80"
fi
if [ "$SYS_NAME" -lt "70" ];then
SYS_NAME="70"
fi
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-rhel${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=5.0.20
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
if [ "$SYS_NAME" -gt "11" ];then
SYS_NAME="11"
fi
if [ "$SYS_NAME" -lt "10" ];then
SYS_NAME="10"
fi
FILE_NAME=mongodb-linux-${SYS_ARCH}-debian${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME_TGZ} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME}} && cp -rf ./bin $serverPath/mongodb
fi
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=5.0.20
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz ]; then
wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz
echo "wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz"
fi
if [ ! -d $MG_DIR/mongodb-macos-x86_64-${VERSION} ];then
cd $MG_DIR && tar -zxvf mongodb-macos-x86_64-${VERSION}.tgz
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/mongodb-macos-x86_64-${VERSION} && cp -rf ./bin $serverPath/mongodb
fi
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=5.0.20
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}' | awk -F . '{print $1}'`
SYS_NAME="15"
if [ "$SYS_VERSION_ID" -gt "15" ];then
SYS_NAME="15"
fi
if [ "$SYS_NAME" -lt "12" ];then
SYS_NAME="12"
fi
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse15-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse12-4.4.23.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-suse${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=5.0.20
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-4.4.23.tgz
if [ "$SYS_NAME" -gt "2004" ];then
SYS_NAME="2004"
fi
if [ "$SYS_NAME" -lt "1804" ];then
SYS_NAME="1804"
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-ubuntu${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=6.0.9
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
SYS_NAME_LEN=`echo "$SYS_NAME" | wc -L`
if [ "$SYS_NAME_LEN" == "1" ];then
SYS_NAME=${SYS_NAME}0
fi
if [ "$SYS_ARCH" == "aarch64" ];then
if [ "$SYS_NAME" -gt "90" ];then
SYS_NAME="90"
fi
if [ "$SYS_NAME" -lt "82" ];then
SYS_NAME="82"
fi
else
if [ "$SYS_NAME" -gt "90" ];then
SYS_NAME="90"
fi
if [ "$SYS_NAME" -lt "70" ];then
SYS_NAME="70"
fi
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-rhel${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=6.0.9
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
if [ "$SYS_NAME" -gt "11" ];then
SYS_NAME="11"
fi
if [ "$SYS_NAME" -lt "10" ];then
SYS_NAME="10"
fi
FILE_NAME=mongodb-linux-${SYS_ARCH}-debian${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME_TGZ} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME}} && cp -rf ./bin $serverPath/mongodb
fi
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=6.0.9
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz ]; then
wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz
echo "wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz"
fi
if [ ! -d $MG_DIR/mongodb-macos-x86_64-${VERSION} ];then
cd $MG_DIR && tar -zxvf mongodb-macos-x86_64-${VERSION}.tgz
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/mongodb-macos-x86_64-${VERSION} && cp -rf ./bin $serverPath/mongodb
fi
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=6.0.9
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}' | awk -F . '{print $1}'`
SYS_NAME="15"
if [ "$SYS_VERSION_ID" -gt "15" ];then
SYS_NAME="15"
fi
if [ "$SYS_NAME" -lt "12" ];then
SYS_NAME="12"
fi
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse15-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse12-4.4.23.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-suse${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=6.0.9
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-4.4.23.tgz
if [ "$SYS_NAME" -gt "2204" ];then
SYS_NAME="2204"
fi
if [ "$SYS_NAME" -lt "1804" ];then
SYS_NAME="1804"
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-ubuntu${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=7.0.0
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
SYS_NAME_LEN=`echo "$SYS_NAME" | wc -L`
if [ "$SYS_NAME_LEN" == "1" ];then
SYS_NAME=${SYS_NAME}0
fi
if [ "$SYS_ARCH" == "aarch64" ];then
if [ "$SYS_NAME" -gt "90" ];then
SYS_NAME="90"
fi
if [ "$SYS_NAME" -lt "82" ];then
SYS_NAME="82"
fi
else
if [ "$SYS_NAME" -gt "90" ];then
SYS_NAME="90"
fi
if [ "$SYS_NAME" -lt "70" ];then
SYS_NAME="70"
fi
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-rhel${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=7.0.0
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
if [ "$SYS_NAME" -gt "11" ];then
SYS_NAME="11"
fi
if [ "$SYS_NAME" -lt "11" ];then
SYS_NAME="11"
fi
FILE_NAME=mongodb-linux-${SYS_ARCH}-debian${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME_TGZ} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME}} && cp -rf ./bin $serverPath/mongodb
fi
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=7.0.0
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
if [ ! -f $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz ]; then
wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz
echo "wget --no-check-certificate -O $MG_DIR/mongodb-macos-x86_64-${VERSION}.tgz https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${VERSION}.tgz"
fi
if [ ! -d $MG_DIR/mongodb-macos-x86_64-${VERSION} ];then
cd $MG_DIR && tar -zxvf mongodb-macos-x86_64-${VERSION}.tgz
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/mongodb-macos-x86_64-${VERSION} && cp -rf ./bin $serverPath/mongodb
fi
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=7.0.0
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}' | awk -F . '{print $1}'`
SYS_NAME="15"
if [ "$SYS_VERSION_ID" -gt "15" ];then
SYS_NAME="15"
fi
if [ "$SYS_NAME" -lt "12" ];then
SYS_NAME="12"
fi
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse15-4.4.23.tgz
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-suse12-4.4.23.tgz
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-suse${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=7.0.0
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
# https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-4.4.23.tgz
if [ "$SYS_NAME" -gt "2204" ];then
SYS_NAME="2204"
fi
if [ "$SYS_NAME" -lt "2004" ];then
SYS_NAME="2004"
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-ubuntu${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
+820
View File
@@ -0,0 +1,820 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import io
sys.path.append(os.getcwd() + "/class/core")
import mw
import oauthlib
import requests
import datetime
from requests_oauthlib import OAuth2Session
DEBUG = False
def setDebug(d=False):
DEBUG = d
class UnauthorizedError(Exception):
pass
class ObjectNotFoundError(Exception):
pass
class msodclient:
plugin_dir = ''
server_dir = ''
credential_file = 'credentials.json'
user_conf = "user.conf"
token_file = 'token.pickle'
def __init__(self, plugin_dir, server_dir):
self.plugin_dir = plugin_dir
self.server_dir = server_dir
self.load()
def setDebug(self, d=False):
DEBUG = d
def load(self):
credential_path = os.path.join(self.plugin_dir, self.credential_file)
credential = json.loads(mw.readFile(credential_path))
# print(credential)
self.credential = credential["onedrive-international"]
self.authorize_url = '{0}{1}'.format(
self.credential['authority'],
self.credential['authorize_endpoint'])
self.token_url = '{0}{1}'.format(
self.credential['authority'],
self.credential['token_endpoint'])
self.token_path = os.path.join(self.server_dir, self.token_file)
self.root_uri = self.credential["api_uri"] + "/me/drive/root"
self.backup_path = 'backup'
def store_token(self, token):
"""存储token"""
enstr = mw.enDoubleCrypt('msodc', json.dumps(token))
mw.writeFile(self.token_path, enstr)
return True
def get_store_token(self):
rdata = mw.readFile(self.token_path)
destr = mw.deDoubleCrypt('msodc', rdata)
return json.loads(destr)
def clear_token(self):
"""清除token记录"""
try:
if os.path.isfile(self.token_path):
os.remove(self.token_path)
except:
if DEBUG:
print("清除token失败。")
def refresh_token(self, origin_token):
"""刷新token"""
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
os.environ['OAUTHLIB_IGNORE_SCOPE_CHANGE'] = '1'
refresh_token = origin_token["refresh_token"]
aad_auth = OAuth2Session(
self.credential["client_id"],
scope=self.credential["scopes"],
redirect_uri=self.credential["redirect_uri"])
new_token = aad_auth.refresh_token(
self.token_url,
refresh_token=refresh_token,
client_id=self.credential["client_id"],
client_secret=self.credential["client_secret"])
return new_token
def get_token_from_authorized_url(self, authorized_url, expected_state=None):
"""通过授权编码获取访问token"""
# 忽略token scope与已请求的scope不一致
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
os.environ['OAUTHLIB_IGNORE_SCOPE_CHANGE'] = '1'
aad_auth = OAuth2Session(self.credential["client_id"],
state=expected_state,
scope=self.credential['scopes'],
redirect_uri=self.credential['redirect_uri'])
token = aad_auth.fetch_token(
self.token_url,
client_secret=self.credential["client_secret"],
authorization_response=authorized_url)
return token
def get_token(self):
token = self.get_store_token()
now = time.time()
expire_time = token["expires_at"] - 300
if now >= expire_time:
new_token = self.refresh_token(token)
self.store_token(new_token)
return new_token
return token
def get_sign_in_url(self):
"""生成签名地址"""
# Initialize the OAuth client
aad_auth = OAuth2Session(self.credential["client_id"],
scope=self.credential['scopes'],
redirect_uri=self.credential['redirect_uri'])
sign_in_url, state = aad_auth.authorization_url(self.authorize_url,
prompt='login')
return sign_in_url, state
def get_authorized_header(self):
token_obj = self.get_token()
token = token_obj["access_token"]
header = {
"Authorization": "Bearer " + token,
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/67.0.3396.99 Safari/537.36'
}
return header
def get_user_from_ms(self):
"""查询用户信息"""
try:
headers = self.get_authorized_header()
user_api_base = self.credential["api_uri"] + "/me"
# select_user_info_uri = self.build_uri(base=user_api_base)
response = requests.get(user_api_base, headers=headers)
if DEBUG:
print("Debug get user:")
print(response.status_code)
print(response.text)
if response.status_code == 200:
response_data = response.json()
user_principal_name = response_data["userPrincipalName"]
return user_principal_name
except oauthlib.oauth2.rfc6749.errors.InvalidGrantError:
self.clear_auth()
if DEBUG:
print("用户授权已过期。")
return None
def clear_auth(self):
self.clear_token()
self.clear_user()
def clear_user(self):
try:
# 清空user
path = os.path.join(self.server_dir, self.user_conf)
if os.path.isfile(path):
os.remove(path)
except:
if DEBUG:
print("清除user失败。")
def store_user(self):
"""更新并存储用户信息"""
user = self.get_user_from_ms()
if user:
path = os.path.join(self.server_dir, self.user_conf)
mw.writeFile(path, user)
else:
raise RuntimeError("无法获取用户信息。")
# --------------------- 文件操作功能 ----------------------
# 取目录路径
def get_path(self, path):
sep = ":"
if path == '/':
path = ''
if path[-1:] == '/':
path = path[:-1]
if path[:1] != "/" and path[:1] != sep:
path = "/" + path
if path == '/':
path = ''
# if path[:1] != sep:
# path = sep + path
try:
from urllib.parse import quote
except:
from urllib import quote
# path = quote(path)
return path.replace('//', '/')
def build_uri(self, path="", operate=None, base=None):
"""构建请求URL
API请求URI格式参考:
https://graph.microsoft.com/v1.0/me/drive/root:/bt_backup/:content
--------------------------------------------- ---------- --------
base path operate
各部分之间用“:”连接。
:param path 子资源路径
:param operate 对文件进行的操作,比如content,children
:return 请求url
"""
if base is None:
base = self.root_uri
path = self.get_path(path)
sep = ":"
if operate:
if operate[:1] != "/":
operate = "/" + operate
if path:
uri = base + sep + path
if operate:
uri += sep + operate
else:
uri = base
if operate:
uri += operate
return uri
def get_list(self, path="/"):
"""获取存储空间中的所有文件对象"""
list_uri = self.build_uri(path, operate="/children")
if DEBUG:
print("List uri:")
print(list_uri)
data = []
response = requests.get(list_uri, headers=self.get_authorized_header())
status_code = response.status_code
if status_code == 200:
if DEBUG:
print("DEBUG:")
print(response.json())
response_data = response.json()
drive_items = response_data["value"]
for item in drive_items:
tmp = {}
tmp['name'] = item["name"]
tmp['size'] = item["size"]
if "folder" in item:
# print("{} is folder:".format(item["name"]))
# print(item["folder"])
tmp["type"] = None
tmp['download'] = ""
if "file" in item:
tmp["type"] = "File"
tmp['download'] = item["@microsoft.graph.downloadUrl"]
# print("{} is file:".format(item["name"]))
# print(item["file"])
formats = ["%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ"]
t = None
for time_format in formats:
try:
t = datetime.datetime.strptime(
item["lastModifiedDateTime"], time_format)
break
except:
continue
t += datetime.timedelta(hours=8)
ts = int(
(time.mktime(t.timetuple()) + t.microsecond / 1000000.0))
tmp['time'] = ts
data.append(tmp)
mlist = {'path': path, 'list': data}
return mlist
def get_object(self, object_name):
"""查询对象信息"""
try:
get_uri = self.build_uri(path=object_name)
if DEBUG:
print("Get uri:")
print(get_uri)
response = requests.get(get_uri,
headers=self.get_authorized_header())
if response.status_code in [200]:
response_data = response.json()
if DEBUG:
print("Object info:")
print(response_data)
return response_data
if response.status_code == 404:
if DEBUG:
print("对象不存在。")
if DEBUG:
print("Get Object debug:")
print(response.status_code)
print(response.text)
except Exception as e:
if DEBUG:
print("Get object has excepiton:")
print(e)
return None
def is_folder(self, obj):
if "folder" in obj:
return True
return False
def delete_object_by_os(self, object_name):
"""删除对象
:param object_name:
:return: True 删除成功
其他 删除失败
"""
obj = self.get_object(object_name)
if obj is None:
if DEBUG:
print("对象不存在,删除操作未执行。")
return True
if self.is_folder(obj):
child_count = obj["folder"]["childCount"]
if child_count > 0:
if DEBUG:
print("文件夹不是空文件夹无法删除。")
return False
headers = self.get_authorized_header()
delete_uri = self.build_uri(object_name)
response = requests.delete(delete_uri, headers=headers)
if response.status_code == 204:
if DEBUG:
print("对象: {} 已被删除。".format(object_name))
return True
return False
def delete_object(self, object_name, retries=2):
"""删除对象
:param object_name:
:param retries: 重试次数,默认2次
:return: True 删除成功
其他 删除失败
"""
try:
return self.delete_object_by_os(object_name)
except Exception as e:
print("删除文件异常:")
print(e)
# 重试
if retries > 0:
print("重新尝试删除文件{}...".format(object_name))
return self.delete_object(
object_name,
retries=retries - 1)
return False
def build_object_name(self, data_type, file_name):
"""根据数据类型构建对象存储名称
:param data_type:
:param file_name:
:return:
"""
import re
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
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
if object_name[:1] == "/":
object_name = object_name[1:]
return object_name
def delete_file(self, file_name, data_type=None):
"""删除文件
根据传入的文件名称和文件数据类型构建对象名称,再删除
:param file_name:
:param data_type: 数据类型 site/database/path
:return: True 删除成功
其他 删除失败
"""
object_name = self.build_object_name(data_type, file_name)
return self.delete_object(object_name)
def create_dir_by_step(self, parent_folder, sub_folder):
create_uri = self.build_uri(path=parent_folder, operate="/children")
if DEBUG:
print("Create dir uri:")
print(create_uri)
post_data = {
"name": sub_folder,
"folder": {"@odata.type": "microsoft.graph.folder"},
"@microsoft.graph.conflictBehavior": "fail"
}
headers = self.get_authorized_header()
headers.update({"Content-type": "application/json"})
response = requests.post(create_uri, headers=headers, json=post_data)
if response.status_code in [201, 409]:
if DEBUG:
if response.status_code == 409:
print("目录:{} 已经存在。".format(sub_folder))
return True
else:
if DEBUG:
print("目录:{} 创建失败:".format(sub_folder))
print(response.status_code)
print(response.text)
return False
def create_dir(self, dir_name):
"""创建远程目录
# API 请求结构
# POST /me/drive/root/children
# or
# POST /me/drive/root:/bt_backup/:/children
# Content - Type: application / json
# {
# "name": "New Folder",
# "folder": {},
# "@microsoft.graph.conflictBehavior": "rename"
# }
# Response: status code == 201 新创建/ 409 已存在
# @microsoft.graph.conflictBehavior: fail/rename/replace
:param dir_name: 目录名称
:param parent_id: 父目录ID
:return: True/False
"""
dir_name = self.get_path(dir_name.strip())
onedrive_business_reserved = r"[\*<>?:|#%]"
if re.search(onedrive_business_reserved, dir_name) \
or dir_name[-1] == "." or dir_name[:1] == "~":
if DEBUG:
print("文件夹名称包含非法字符。")
return False
parent_folder = self.get_path(os.path.split(dir_name)[0])
sub_folder = os.path.split(dir_name)[1]
# print("create_dir:", dir_name)
obj = self.get_object(dir_name)
# 判断对象是否存在
if obj is None:
if not self.create_dir_by_step(parent_folder, sub_folder):
# 兼容OneDrive 商业版文件夹创建
folder_array = dir_name.split("/")
parent_folder = self.get_path(folder_array[0])
for i in range(1, len(folder_array)):
sub_folder = folder_array[i]
if DEBUG:
print("Parent folder: {}".format(parent_folder))
print("Sub folder: {}".format(sub_folder))
if self.create_dir_by_step(parent_folder, sub_folder):
parent_folder += "/" + folder_array[i]
else:
return False
return True
else:
if self.is_folder(obj):
if DEBUG:
print("文件夹已存在。")
return True
def resumable_upload(self,
local_file_name,
object_name=None,
progress_callback=None,
progress_file_name=None,
multipart_threshold=1024 * 1024 * 2,
part_size=1024 * 1024 * 5,
store_dir="/tmp",
auto_cancel=True,
retries=5,
):
"""断点续传
:param local_file_name: 本地文件名称
:param object_name: 指定OS中存储的对象名称
:param part_size: 指定分片上传的每个分片的大小。必须是320*1024的整数倍。
:param multipart_threshold: 文件长度大于该值时,则用分片上传。
:param progress_callback: 进度回调函数,默认是把进度信息输出到标准输出。
:param progress_file_name: 进度信息保存文件,进度格式参见[report_progress]
:param store_dir: 上传分片存储目录, 默认/tmp。
:param auto_cancel: 当备份失败是否自动取消上传记录
:param retries: 上传重试次数
:return: True上传成功/False or None上传失败
"""
try:
file_size_separation_value = 4 * 1024 * 1024
if part_size % 320 != 0:
if DEBUG:
print("Part size 必须是320的整数倍。")
return False
if object_name is None:
temp_file_name = os.path.split(local_file_name)[1]
object_name = os.path.join(self.backup_path, temp_file_name)
# if progress_file_name:
# os.environ[PROGRESS_FILE_NAME] = progress_file_name
# progress_callback = report_progress
print("|-正在上传到 {}...".format(object_name))
dir_name = os.path.split(object_name)[0]
if not self.create_dir(dir_name):
if DEBUG:
print("目录创建失败!")
return False
local_file_size = os.path.getsize(local_file_name)
# if local_file_size < file_size_separation_value:
if False:
# 小文件上传
upload_uri = self.build_uri(path=object_name,
operate="/content")
if DEBUG:
print("Upload uri:")
print(upload_uri)
headers = self.get_authorized_header()
# headers.update({
# "Content-Type": "application/octet-stream"
# })
# files = {"file": (object_name, open(local_file_name, "rb"))}
file_data = open(local_file_name, "rb")
response = requests.put(upload_uri,
headers=headers,
data=file_data)
if DEBUG:
print("status code:")
print(response.status_code)
# print(response.text)
if response.status_code in [201, 200]:
if DEBUG:
print("文件上传成功!")
return True
else:
# 大文件上传
# 1. 创建上传session
create_session_uri = self.build_uri(
path=object_name,
operate="createUploadSession")
headers = self.get_authorized_header()
response = requests.post(create_session_uri, headers=headers)
if response.status_code == 200:
response_data = response.json()
upload_url = response_data["uploadUrl"]
expiration_date_time = response_data["expirationDateTime"]
if DEBUG:
print("上传session已建立。")
print("Upload url: {}".format(upload_url))
print("Expiration datetime: {}".format(
expiration_date_time))
# 2. 分片上传文件
requests.adapters.DEFAULT_RETRIES = 1
session = requests.session()
session.keep_alive = False
# 开始分片上传
import math
parts = int(math.ceil(local_file_size / part_size))
for i in range(parts):
if DEBUG:
if i == parts - 1:
num = "最后"
else:
num = "第{}".format(i + 1)
print("正在上传{}部分...".format(num))
upload_range_start = i * part_size
upload_range_end = min(upload_range_start + part_size,
local_file_size)
content_length = upload_range_end - upload_range_start
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/67.0.3396.99 Safari/537.36'
}
# 开发记录
# Content-Range和标准的http请求头中的Range作用有所不同
# Content-Range是OneDrive自定义的分片上传标识,格式也不一样
headers.update({
"Content-Length": repr(content_length),
"Content-Range": "bytes {}-{}/{}".format(
upload_range_start,
upload_range_end - 1,
local_file_size),
"Content-Type": "application/octet-stream"
})
if DEBUG:
print("Headers:")
print(headers)
'''# TODO 优化read的读取占用内存'''
f = io.open(local_file_name, "rb")
f.seek(upload_range_start)
upload_data = f.read(content_length)
sub_response = session.put(upload_url,
headers=headers,
data=upload_data)
expected_status_code = [200, 201, 202]
if sub_response.status_code in expected_status_code:
if DEBUG:
print("Response status code: {}, "
"bytes {}-{} 已上传成功。".format(
sub_response.status_code,
upload_range_start,
upload_range_end - 1)
)
print(sub_response.text)
if sub_response.status_code in [200, 201]:
if DEBUG:
print("文件 {} 上传成功。".format(object_name))
return True
else:
print(sub_response.status_code)
print(sub_response.text)
_error_msg = "Bytes {}-{} 分片上传失败。".format(
upload_range_start,
upload_range_end
)
if self.error_msg:
self.error_msg += r"\n"
self.error_msg += _error_msg
raise RuntimeError(_error_msg)
time.sleep(0.5)
else:
raise RuntimeError("session创建失败。")
except UnauthorizedError as e:
_error_msg = str(e)
if self.error_msg:
self.error_msg += r"\n"
self.error_msg += _error_msg
print(_error_msg)
return False
except Exception as e:
print("文件上传出现错误:")
print(e)
if self.error_msg:
self.error_msg += r"\n"
self.error_msg += "文件{}上传出现错误:{}".format(object_name, str(e))
try:
if upload_url:
if DEBUG:
print("正在清理上传session.")
session.delete(upload_url)
except:
pass
finally:
try:
f.close()
except:
pass
try:
session.close()
except:
pass
# 重试断点续传
if retries > 0:
print("重试上传文件....")
return self.resumable_upload(
local_file_name,
object_name=object_name,
store_dir=store_dir,
part_size=part_size,
multipart_threshold=multipart_threshold,
progress_callback=progress_callback,
progress_file_name=progress_file_name,
retries=retries - 1,
)
else:
if self.error_msg:
self.error_msg += r"\n"
self.error_msg += "文件{}上传失败。".format(object_name)
return False
def upload_abs_file(self, file_name, remote_dir, *args, **kwargs):
"""按照数据类型上传文件
:param file_name: 上传文件名称
:param data_type: 数据类型 site/database/path
:return: True/False
"""
try:
import re
# 根据数据类型提取子分类名称
# 比如data_type=database,子分类名称是数据库的名称。
# 提取方式是从file_name中利用正则规则去提取。
self.error_msg = ""
file_name = os.path.abspath(file_name)
temp_name = os.path.split(file_name)[1]
object_name = 'backup/' + temp_name
print(file_name)
print(object_name)
return self.resumable_upload(file_name,
object_name=object_name,
*args,
**kwargs)
except Exception as e:
if self.error_msg:
self.error_msg += r"\n"
self.error_msg += "文件上传出现错误:{}".format(str(e))
return False
def upload_file(self, file_name, data_type, *args, **kwargs):
"""按照数据类型上传文件
:param file_name: 上传文件名称
:param data_type: 数据类型 site/database/path
:return: True/False
"""
try:
import re
# 根据数据类型提取子分类名称
# 比如data_type=database,子分类名称是数据库的名称。
# 提取方式是从file_name中利用正则规则去提取。
self.error_msg = ""
if not file_name or not data_type:
_error_msg = "文件参数错误。"
print(_error_msg)
self.error_msg = _error_msg
return False
file_name = os.path.abspath(file_name)
temp_name = os.path.split(file_name)[1]
object_name = self.build_object_name(data_type, temp_name)
# dir_name = os.path.dirname(object_name)
# self.create_dir(dir_name)
if DEBUG:
print(file_name)
print(object_name)
print(dir_name)
return self.resumable_upload(file_name,
object_name=object_name,
*args,
**kwargs)
except Exception as e:
if self.error_msg:
self.error_msg += r"\n"
self.error_msg += "文件上传出现错误:{}".format(str(e))
return False
+12
View File
@@ -0,0 +1,12 @@
{
"onedrive-international": {
"client_id": "08125e6b-6502-4ac9-9548-ad682f00848d",
"client_secret": "0WA8Q~sZkZFZKv50ryP4ux~.fpVtbHw7BuTZmbQB",
"authority": "https://login.microsoftonline.com/common",
"token_endpoint": "/oauth2/v2.0/token",
"authorize_endpoint": "/oauth2/v2.0/authorize",
"scopes": "offline_access Files.ReadWrite.All User.Read",
"redirect_uri": "http://localhost",
"api_uri": "https://graph.microsoft.com/v1.0"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+311
View File
@@ -0,0 +1,311 @@
<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="authApi()">授权</button>
<button class="btn btn-default btn-sm pull-right mr20 btn-title" onclick="createDir()">新建文件夹</button>
</div>
<div class="upyunlist pd15">
<div class="divtable" style="margin-bottom:15px">
<table class="table table-hover">
<thead><tr><th>名称</th><th>大小</th><th>更新时间</th><th class="text-right">操作</th></tr></thead>
<tbody class="list-list"></tbody>
</table>
</div>
</div>
</div>
<style type="text/css">
.check_api {
padding: 20px;
}
.up-place {
height: 62px;
border-bottom: 1px solid #ddd;
}
.up-place .btn {
border-radius: 0;
}
.up-place .place-input {
background-color: #f3f3f3;
border: 1px solid #ccc;
height: 30px;
line-height: 28px;
overflow: hidden;
margin: 1px 0 0 -1px;
width: 340px;
}
.place-input ul {
display: inline-block;
position: relative;
width: auto;
}
.place-input ul li {
background: url("/static/img/ico/ico-ltr.png") no-repeat right center;
float: left;
padding-left: 10px;
padding-right: 18px;
}
.place-input ul li a {
height: 28px;
cursor: pointer;
display: inline-block;
}
.upyunlist {
height: 546px;
overflow: auto;
}
.up-bottom {
background-color: #fafafa;
border-top: 1px solid #eee;
bottom: 0;
position: absolute;
width: 100%;
}
.up-use {
line-height: 50px
}
.list-list .cursor span {
line-height: 30px;
}
.btn-title {
margin-top: 1px
}
.step_item{
clear: both;
}
.step_item .serial_box{
display: inline-block;
clear: both;
}
.step_item .serial{
width: 70px;
height: 30px;
line-height: 30px;
text-align: center;
display: inline-block;
float: left;
}
.step_item .serial span{
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 28px;
font-size: 11px;
border-radius: 50%;
color: #20a53a;
border: 2px solid #20a53a;
}
.step_item .serial_title{
margin-bottom: 10px;
font-size: 15px;
line-height: 30px;
color: #666;
}
.step_two_url{
display: inline-block;
overflow: hidden;
width: 380px;
/*text-overflow: ellipsis;*/
white-space: nowrap;
height: 35px;
line-height: 35px;
margin-right: 15px;
border-radius: 2px;
padding: 0 10px;
float: left;
width:360px;
padding-right: 35px;
}
.btn_btlink{
display: inline-block;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
border: 1px solid #20a53a;
color: #fff;
background-color: #20a53a;
margin-right:10px;
}
.btn_btlink:hover{
color: #fff;
background-color: #10952a;
border-color: #398439;
}
.btn_btlink a:visited{
color: #fff;
background-color: #10952a;
border-color: #398439;
}
.view_video{
margin-bottom: 10px;
}
.view_video ul li{
line-height: 20px;
font-size: 13px;
}
.setp_one i{
position: absolute;
top: 8px;
left: 25px;
width: 30px;
height: 30px;
}
.OneDrive{
width:465px;
height:100px;
margin-bottom:10px;
}
</style>
<script type="text/html" id="check_api">
<div class="check_api">
<div class="step_two">
<div class="step_item">
<div class="serial"><span>1</span></div>
<div class="serial_box">
<div class="serial_title">阅读简易操作教程:如何获取Microsoft OneDrive授权?</div>
<div class="serial_conter">
<div class="view_video">
<ul>
<li>1. 点击下面第<div class="serial" style="float: none;width: 45px;"><span>2</span></div>步中的 打开授权链接。<li>
<li>2. 在新窗口页面上登录Microsoft账号。阅读授权权限,并同意。<li>
<li>3. 页面跳转后,将浏览器的地址栏地址复制到第<div class="serial" style="float: none;width: 45px;"><span>3</span></div>步的文本框中。<li>
<li>4. 点击 获取授权,随即完成授权。<li>
</ul>
</div>
<hr/>
</div>
</div>
</div>
<div class="step_item pb15">
<div class="serial"><span>2</span></div>
<div class="serial_box">
<div class="serial_title">操作1:👇打开授权链接,根据网页提示对插件进行授权。</div>
<div class="serial_conter step_two" style="width: 500px;">
<input class="bt-input-text mr5 step_two_url" type="text" disabled>
<span class="ico-copy mr10" data-copy="" style="vertical-align: middle;cursor: pointer;margin-left: -37px;margin-right: 20px;"></span>
<a href="" class="btn_btlink open_btlink" target="_blank" style="padding: 7px 10px;">打开授权链接</a>
</div>
</div>
</div>
<div class="step_item">
<div class="serial"><span>3</span></div>
<div class="serial_box">
<div class="serial_title">操作2:复制回浏览器跳转后的地址:</div>
<div class="serial_conter">
<textarea row="3" placeholder="验证URL地址" class="bt-input-text OneDrive" style="resize: none;"/></br>
<button type="button" class="btn btn-success btn-sm set_auth_btn">获取授权</button>
</div>
</div>
</div>
</div>
</div>
</script>
<script type="text/javascript" src="/plugins/file?name=msonedrive&f=js/msonedrive.js"></script>
<script type="text/javascript">
$.getScript( "/plugins/file?name=msonedrive&f=js/msonedrive.js", function(){
odList('/');
});
</script>
+351
View File
@@ -0,0 +1,351 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
# print(sys.platform)
if sys.platform != "darwin":
os.chdir("/www/server/mdserver-web")
sys.path.append(os.getcwd() + "/class/core")
import mw
import db
_ver = sys.version_info
is_py2 = (_ver[0] == 2)
is_py3 = (_ver[0] == 3)
DEBUG = False
if is_py2:
reload(sys)
sys.setdefaultencoding('utf-8')
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'msonedrive'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def in_array(name, arr=[]):
for x in arr:
if name == x:
return True
return False
sys.path.append(getPluginDir() + "/class")
from msodclient import msodclient
msodc = msodclient(getPluginDir(), getServerDir())
msodc.setDebug(False)
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':', 1)
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def status():
return 'start'
def isAuthApi():
cfg = getServerDir() + "/user.conf"
if os.path.exists(cfg):
return True
return False
def getConf():
if not isAuthApi():
sign_in_url, state = msodc.get_sign_in_url()
return mw.returnJson(False, "未授权!", {'auth_url': sign_in_url})
return mw.returnJson(True, "OK")
def setAuthUrl():
args = getArgs()
data = checkArgs(args, ['url'])
if not data[0]:
return data[1]
url = args['url']
try:
if url.startswith("http://"):
url = url.replace("http://", "https://")
token = msodc.get_token_from_authorized_url(authorized_url=url)
msodc.store_token(token)
msodc.store_user()
return mw.returnJson(True, "授权成功!")
except Exception as e:
return mw.returnJson(False, "授权失败2!:" + str(e))
return mw.returnJson(False, "授权失败!:" + str(e))
def clearAuth():
cfg = getServerDir() + "/user.conf"
if os.path.exists(cfg):
os.remove(cfg)
token = getServerDir() + "/token.pickle"
if os.path.exists(token):
os.remove(token)
return mw.returnJson(True, "清空授权成功!")
def getList():
cfg = getServerDir() + "/user.conf"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置,请点击`授权`", [])
args = getArgs()
data = checkArgs(args, ['path'])
if not data[0]:
return data[1]
try:
flist = msodc.get_list(args['path'])
return mw.returnJson(True, "ok", flist)
except Exception as e:
return mw.returnJson(False, str(e), [])
def createDir():
cfg = getServerDir() + "/user.conf"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置OneDrive,请点击`授权`", [])
args = getArgs()
data = checkArgs(args, ['path', 'name'])
if not data[0]:
return data[1]
file = args['path'] + "/" + args['name']
isok = msodc.create_dir(file)
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]
file = args['path'] + "/" + args['dir_name']
file = file.strip('/')
isok = msodc.delete_object(file)
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]
file = args['path'] + "/" + args['filename']
file = file.strip('/')
isok = msodc.delete_object(file)
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "删除失败")
def findPathName(path, filename):
f = os.scandir(path)
l = []
for ff in f:
t = {}
if ff.name.find(filename) > -1:
t['filename'] = path + '/' + ff.name
l.append(t)
return l
def backupAllFunc(stype):
if not isAuthApi():
mw.echoInfo("未授权API,无法使用!!!")
return ''
os.chdir(mw.getRunDir())
backup_dir = mw.getBackupDir()
run_dir = mw.getRunDir()
stype = sys.argv[1]
name = sys.argv[2]
num = sys.argv[3]
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
backups = []
sql = db.Sql()
# print("stype:", stype)
# 提前获取-清理多余备份
if stype == 'site':
pid = sql.table('sites').where('name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('0', pid)).field('id,filename').select()
if stype == 'database':
db_path = mw.getServerDir() + '/mysql'
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
if stype == 'path':
backup_path = backup_dir + '/path'
_name = 'path_{}'.format(os.path.basename(name))
backups = findPathName(backup_path, _name)
# 其他类型关系性数据库(mysql类的)
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
db_path = mw.getServerDir() + '/' + plugin_name
pid = mw.M('databases').dbPos(db_path, 'mysql').where(
'name=?', (name,)).getField('id')
backups = sql.table('backup').where(
'type=? and pid=?', ('1', pid)).field('id,filename').select()
args = stype + " " + name + " " + num
cmd = 'python3 ' + run_dir + '/scripts/backup.py ' + args
if stype.find('database_') > -1:
plugin_name = stype.replace('database_', '')
args = "database " + name + " " + num
cmd = 'python3 ' + run_dir + '/plugins/' + \
plugin_name + '/scripts/backup.py ' + args
if stype == 'path':
name = os.path.basename(name)
# print("cmd:", cmd)
os.system(cmd)
# 开始执行上传信息.
if stype.find('database_') > -1:
bk_name = 'database'
plugin_name = stype.replace('database_', '')
bk_prefix = plugin_name + '/db'
stype = 'database'
else:
bk_prefix = prefix_dict[stype]
bk_name = stype
find_path = backup_dir + '/' + bk_name + '/' + bk_prefix + '_' + name
find_new_file = "ls " + find_path + \
"_* | grep '.gz' | cut -d \ -f 1 | awk 'END {print}'"
# print(find_new_file)
filename = mw.execShell(find_new_file)[0].strip()
if filename == "":
mw.echoInfo("not find upload file!")
return False
mw.echoInfo("准备上传文件 {}".format(filename))
mw.echoStart('开始上传')
msodc.upload_file(filename, stype)
mw.echoEnd('上传成功')
# print(backups)
backups = sorted(backups, key=lambda x: x['filename'], reverse=False)
mw.echoStart('开始删除远程备份')
num = int(num)
sep = len(backups) - num
if sep > -1:
for backup in backups:
fn = os.path.basename(backup['filename'])
msodc.delete_file(fn, stype)
mw.echoInfo("---已清理远程过期备份文件:" + fn)
sep -= 1
if sep < 0:
break
mw.echoEnd('结束删除远程备份')
return ''
def installPreInspection():
return 'ok'
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'install_pre_inspection':
print(installPreInspection())
elif func == 'conf':
print(getConf())
elif func == 'set_auth_url':
print(setAuthUrl())
elif func == 'clear_auth':
print(clearAuth())
elif func == "get_list":
print(getList())
elif func == "create_dir":
print(createDir())
elif func == "delete_dir":
print(deleteDir())
elif func == 'delete_file':
print(deleteFile())
elif in_array(func, ['site', 'database', 'path']) or func.find('database_') > -1:
print(backupAllFunc(func))
else:
print('error')
+14
View File
@@ -0,0 +1,14 @@
{
"hook":["backup"],
"title": "OneDrive",
"tip": "lib",
"name": "msonedrive",
"type": "sort",
"ps": "微软家的云网盘服务。",
"versions": "1.0",
"shell": "install.sh",
"checks": "server/msonedrive",
"author": "midoks",
"date": "2023-8-18",
"pid": "4"
}
+41
View File
@@ -0,0 +1,41 @@
#!/bin/bash
PATH=/www/server/panel/pyenv/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
Install_App()
{
pip install requests-oauthlib==1.3.0
mkdir -p $serverPath/msonedrive
echo '正在安装脚本文件...' > $install_tmp
echo "${VERSION}" > $serverPath/msonedrive/version.pl
echo '安装完成' > $install_tmp
echo "Successify"
}
Uninstall_App()
{
rm -rf $serverPath/msonedrive
}
if [ "${1}" == 'install' ];then
Install_App
elif [ "${1}" == 'uninstall' ];then
Uninstall_App
else
echo 'Error!';
fi
+258
View File
@@ -0,0 +1,258 @@
function msodPost(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:'msonedrive', func:method, args:_args}, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function createDir(){
layer.open({
type: 1,
area: "400px",
title: "创建目录",
closeBtn: 1,
shift: 5,
shadeClose: false,
btn: ['确定','取消'],
content:'<div class="bingfa bt-form c6" style="padding-bottom: 10px;">\
<p>\
<span class="span_tit">目录名称:</span>\
<input style="width: 200px;" type="text" name="newPath" value="">\
</p>\
</div>',
success:function(){
$("input[name='newPath']").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(index,layero){
var name = $("input[name='newPath']").val();
if(name == ''){
layer.msg('目录名称不能为空!',{icon:2});
return;
}
var path = $("#myPath").val();
var dirname = name;
var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']});
msodPost('create_dir', {path:path,name:dirname}, function(data){
layer.close(loadT);
var rdata = $.parseJSON(data.data);
if(rdata.status) {
showMsg(rdata.msg, function(){
layer.close(index);
odList(path);
} ,{icon:1}, 2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
});
}
});
}
//设置API
function authApi(){
msodPost('conf', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
// console.log(rdata);
// console.log(rdata.data.auth_url);
var apicon = '';
if (rdata.status){
var html = '';
html += '<button id="clear_auth" onclick="clearAuth();" class="btn btn-default btn-sm">清空配置</button>';
var loadOpen = layer.open({
type: 1,
title: '已授权',
area: '240px',
content:'<div class="change-default pd20">'+html+'</div>',
success: function(){
$('#clear_auth').click(function(){
msodPost('clear_auth', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
layer.close(loadOpen);
odList('/');
},{icon:rdata.status?1:2},2000);
});
});
}
});
return true;
} else{
apicon = '<div class="new_form">'+$("#check_api").html()+'</div>';
}
var layer_auth = layer.open({
type: 1,
area: "620px",
title: "OneDrive授权",
closeBtn: 1,
shift: 5,
shadeClose: false,
content:apicon,
success:function(layero,index){
// console.log(layero,index);
if (!rdata.status){
$('.check_api .step_two_url').val(rdata.data['auth_url']);
$('.check_api .open_btlink').attr('href',rdata.data['auth_url']);
$('.check_api .ico-copy').click(function(){
copyPass(rdata.data['auth_url']);
});
$('.check_api .set_auth_btn').click(function(){
var url = $('.check_api .OneDrive').val();
if ( url == ''){
layer.msg("验证URL不能为空",{icon:2});
return;
}
// console.log(url);
msodPost('set_auth_url', {url:url}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var show_time = 2000;
if (!rdata.status){
show_time = 10000;
}
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(layer_auth);
odList('/');
}
},{icon:rdata.status?1:2},show_time);
});
});
}
}
});
});
}
//计算当前目录偏移
function upPathLeft(){
var UlWidth = $(".place-input ul").width();
var SpanPathWidth = $(".place-input").width() - 20;
var Ml = UlWidth - SpanPathWidth;
if(UlWidth > SpanPathWidth ){
$(".place-input ul").css("left",-Ml)
}
else{
$(".place-input ul").css("left",0)
}
}
function odList(path){
msodPost('get_list', {path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
if(rdata.status === false){
showMsg(rdata.msg,function(){
authApi();
},{icon:2},2000);
return;
}
var mlist = rdata.data;
var listBody = ''
var listFiles = ''
for(var i=0;i<mlist.list.length;i++){
if(mlist.list[i].type == null){
listBody += '<tr><td class="cursor" onclick="odList(\''+(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>'+getLocalTime(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() {
odList(backPath);
});
$('.upyunCon .refreshBtn').unbind().click(function(){
odList(path);
});
});
}
//删除文件
function deleteFile(name, is_dir){
if (is_dir === false){
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
var filename = name;
msodPost('delete_file', {filename:filename,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
odList(path);
},{icon:rdata.status?1:2},2000);
});
});
} else {
safeMessage('删除文件夹','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
msodPost('delete_dir', {dir_name:name,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
odList(path);
},{icon:rdata.status?1:2},2000);
});
});
}
}
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/python
# coding: utf-8
# python3 plugins/msonedrive/t/test.py
# https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/08125e6b-6502-4ac9-9548-ad682f00848d/objectId/62b1d655-9828-47ed-be99-65eb18c3a929/isMSAApp~/false/defaultBlade/Overview/appSignInAudience/AzureADandPersonalMicrosoftAccount/servicePrincipalCreated~/true
# 0WA8Q~sZkZFZKv50ryP4ux~.fpVtbHw7BuTZmbQB
# client_id:d9878fac-8526-4ff6-8036-e1c92dd9dd80
# 08125e6b-6502-4ac9-9548-ad682f00848d
# https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=code&client_id=d9878fac-8526-4ff6-8036-e1c92dd9dd80&redirect_uri=http://localhost&scope=offline_access+Files.ReadWrite.All+User.Read&state=cwopMdHiPIkze4MvgFL6WfSl8LdYAl&prompt=login
# http://localhost/?code=M.C106_BAY.2.3e12c859-6107-0c5b-9ef4-14b3fb8269ba&state=JzHdzHXmA7x6zl7Be6cJ6uOlf9Bg69
# python3 /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/msonedrive/index.py site t1.cn 3
# python3 /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/msonedrive/index.py database t1 3
# python3
# /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/msonedrive/index.py
# path /Users/midoks/Desktop/dev/python 3
import sys
import io
import os
import time
import re
import json
from requests_oauthlib import OAuth2Session
sys.path.append(os.getcwd() + "/class/core")
import mw
def getPluginName():
return 'msonedrive'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
sys.path.append(getPluginDir() + "/class")
from msodclient import msodclient
msodclient.setDebug(True)
msodc = msodclient(getPluginDir(), getServerDir())
# sign_in_url, state = msodc.get_sign_in_url()
# print(sign_in_url)
def set_auth_url(url):
try:
if url.startswith("http://"):
url = url.replace("http://", "https://")
token = msodc.get_token_from_authorized_url(
authorized_url=url)
msodc.store_token(token)
msodc.store_user()
return mw.returnJson(True, "授权成功!")
except Exception as e:
print(e)
return mw.returnJson(False, "授权失败2!:" + str(e))
return mw.returnJson(False, "授权失败!:" + str(e))
# url = 'http://localhost/?code=M.C106_BAY.2.310112f3-a158-c400-9667-d158cbd1de6c&state=jEJz0ucR9bpZYD9PGxp2GgRDotrzO6'
# token = set_auth_url(url)
# print(token)
# token = msodc.get_token()
# print("token:", token)
# t = msodc.get_list('/backup')
# print(t)
# t = msodc.create_dir('backup')
# print(t)
# t = msodc.delete_object('backup')
# print(t)
t = msodc.upload_file('web_t1.cn_20230830_134549.tar.gz', 'site')
print(t)
# print(msodc.error_msg)
# /Users/midoks/Desktop/mwdev/server/mdserver-web/paramiko.log
# backup/site/paramiko.log
# |-正在上传到 backup/site/paramiko.log...
# True
# t = msodc.upload_abs_file(
# 'web_t1.cn_20230830_134549.tar.gz', 'site')
# print(t)
# print(msodc.error_msg)
+7 -2
View File
@@ -14,6 +14,9 @@ port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
language={$SERVER_APP_PATH}/bin/usr/share/mysql/english
@@ -45,7 +48,6 @@ skip-ssl
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
@@ -65,12 +67,15 @@ binlog-ignore-db = performance_schema
#slave
log-slave-updates
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+7 -2
View File
@@ -16,6 +16,9 @@ mysqlx_port = 33260
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
key_buffer_size = 8M
@@ -43,7 +46,6 @@ max_allowed_packet = 128M
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
@@ -62,12 +64,15 @@ binlog-ignore-db = performance_schema
#slave
log_replica_updates
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+1 -1
View File
@@ -15,7 +15,7 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
+234 -179
View File
@@ -28,6 +28,10 @@ def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -51,19 +55,20 @@ def is_number(s):
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
t = args[i].split(':', 1)
tmp[t[0]] = t[1]
return tmp
@@ -116,6 +121,10 @@ def contentReplace(content):
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$SERVER_APP_PATH}',
service_path + '/' + getPluginName())
server_id = int(time.time())
content = content.replace('{$SERVER_ID}', str(server_id))
return content
@@ -161,6 +170,10 @@ def pMysqlDb():
def initDreplace(version=''):
t = getServerDir()
if not os.path.exists(t):
return
conf_dir = getServerDir() + '/etc'
mode_dir = conf_dir + '/mode'
@@ -654,15 +667,15 @@ def isSqlError(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, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -1885,27 +1898,34 @@ def getMasterRepSlaveUserCmd(version):
mode = recognizeDbMode()
sid = getDbServerId()
channel_name = ""
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"])
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + str(mstatus[0]["Position"])
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2176,40 +2196,10 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
tmp['Last_Error'] = dlist[x]["Last_Error"]
tmp['Last_IO_Error'] = dlist[x]["Last_IO_Error"]
tmp['Last_SQL_Error'] = dlist[x]["Last_SQL_Error"]
tmp['Slave_SQL_Running_State'] = dlist[x]["Slave_SQL_Running_State"]
tmp['Error'] = ''
if tmp['Last_Error'] != '':
tmp['Error'] = tmp['Last_Error']
if tmp['Last_IO_Error'] != '':
tmp['Error'] = tmp['Last_IO_Error']
if tmp['Last_SQL_Error'] != '':
tmp['Error'] = tmp['Last_SQL_Error']
if tmp['Error'] == '':
tmp['Error'] = tmp['Slave_SQL_Running_State']
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
@@ -2217,7 +2207,7 @@ def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
cmd = 'cd ' + root + ' && python3 ' + root + \
'/plugins/mysql/index.py do_full_sync {"db":"all"}'
'/plugins/mysql/index.py do_full_sync {"db":"all","sign":""}'
return mw.returnJson(True, 'ok', cmd)
@@ -2233,100 +2223,151 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version)
def parseSlaveSyncCmd(cmd):
a = {}
if cmd.lower().find('for') > 0:
cmd_tmp = cmd.split('for')
cmd = cmd_tmp[0].strip()
pattern_c = r"channel \'(.*)\';"
match_val = re.match(pattern_c, cmd_tmp[1].strip(), re.I)
if match_val:
m_groups = match_val.groups()
a['channel'] = m_groups[0]
vlist = cmd.split(',')
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
msg = ''
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
mode_name = 'classic'
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
t = db.query(u['cmd'])
# print(t)
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
if slave_t['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
t = pdb.query(cmd_sql)
isError = isSqlError(t)
if isError:
return isError
# pdb.query("start slave user='{}' password='{}';".format(
# u['user'], u['pass']))
pdb.query("start slave")
pdb.query("start all slaves")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
local_mode = recognizeDbMode()
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
db.query('stop slave')
db.query('reset slave all')
for data in ssh_list:
ip = data['ip']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
cmd_data = json.loads(result)
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']:【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
u = cmd_data['data']['info']
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ps = u['username'] + "|" + u['password']
print(ps)
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
db.query("start slave user='{}' password='{}';".format(
u['username'], u['password']))
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ssh.close()
time.sleep(1)
os.system("rm -rf " + SSH_PRIVATE_KEY)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
ssh.close()
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
db.query('start slave')
return mw.returnJson(True, '初始化成功!')
@@ -2336,60 +2377,37 @@ def setSlaveStatus(version=''):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Channel_Name' in v:
ch_name = v['Channel_Name']
cmd = "slave for channel '{}'".format(ch_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行[初始化]!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
u = data['ps'].split("|")
db.query("start slave user='{}' password='{}';".format(u[0], u[1]))
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2425,11 +2443,13 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mysql_apt_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
@@ -2447,16 +2467,32 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_db_import = args['db']
if sync_db.lower() == 'all':
sync_db_import = ''
dbs = findBinlogSlaveDoDb()
dbs_str = ''
for x in dbs:
dbs_str += ' ' + x
sync_db = "--databases " + dbs_str.strip()
sync_sign = args['sign']
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2473,17 +2509,18 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
dump_sql_data = getServerDir() + "/bin/usr/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
if os.path.exists(bak_file):
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db + ' < ' + bak_file
my_import_cmd = getServerDir() + '/bin/usr/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db_import + ' < ' + bak_file
mw.execShell(my_import_cmd)
if version == '8.0':
@@ -2492,21 +2529,30 @@ def doFullSyncUser(version=''):
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2548,7 +2594,8 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && python3 plugins/mysql/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 " + \
getSPluginDir() + "/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2571,7 +2618,10 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
@@ -2583,10 +2633,12 @@ def doFullSyncSSH(version=''):
cmd = cmd_data['data']['cmd']
# 保证同步IP一致
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
uinfo = cmd_data['data']['info']
@@ -2598,8 +2650,10 @@ def doFullSyncSSH(version=''):
root_dir = getServerDir()
msock = root_dir + "/mysql.sock"
mw.execShell("cd /tmp && gzip -d dump.sql.gz")
cmd = root_dir + "/bin/mysql -S " + msock + \
cmd = root_dir + "/bin/usr/bin/mysql -S " + msock + \
" -uroot -p" + pwd + " < /tmp/dump.sql"
print(cmd)
import_data = mw.execShell(cmd)
if import_data[0] == '':
print(import_data[1])
@@ -2609,8 +2663,9 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
db.query("start slave user='{}' password='{}';".format(
uinfo['username'], uinfo['password']))
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2624,12 +2679,12 @@ def fullSync(version=''):
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
@@ -2667,8 +2722,8 @@ def installPreInspection(version):
if not sysName in ('debian', 'ubuntu'):
return '仅支持debian,ubuntu'
if (sysName == 'debian' and not sysId in('11', '10')):
return 'debian支持10,11'
if (sysName == 'debian' and not sysId in('12', '11', '10')):
return 'debian支持10,11,12'
if (sysName == 'ubuntu' and version == '5.7' and not sysId in ('18.04')):
return "Ubuntu Apt MySQL[" + version + "] 仅支持18.04"
+5 -1
View File
@@ -48,7 +48,11 @@ fi
sh -x $curPath/versions/$2/install.sh $1
if [ "${action}" == "install" ];then
# #初始化
#初始化
if [ "$?" != "0" ];then
exit $?
fi
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py start ${type}
cd ${rootPath} && python3 ${rootPath}/plugins/mysql-apt/index.py initd_install ${type}
fi
+165 -81
View File
@@ -162,34 +162,6 @@ function myPort(){
});
}
//数据库存储信置
function changeMySQLDataPath(act) {
if (act != undefined) {
layer.confirm(lan.soft.mysql_to_msg, { closeBtn: 2, icon: 3 }, function() {
var datadir = $("#datadir").val();
var data = 'datadir=' + datadir;
var loadT = layer.msg(lan.soft.mysql_to_msg1, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/database?action=SetDataDir', data, function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
});
});
return;
}
$.post('/database?action=GetMySQLInfo', '', function(rdata) {
var LimitCon = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function myPerfOpt() {
//获取MySQL配置
@@ -1691,12 +1663,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1704,28 +1676,73 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Channel_Name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
function fullSync(db,sign,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1734,23 +1751,10 @@ function getFullSyncStatus(db){
if (rdata['code']==6 ||rdata['code']<0){
layer.msg(rdata['msg']);
clearInterval(timeId);
$("#begin_full_sync").attr('data-status','init');
$("#begin_full_sync").data('data','init');
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -1920,18 +1924,29 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[最好填好]</span>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
val = cmd_tmp[0].trim();
const channel_str = cmd_tmp[1].trim();
const ch_reg = /channel \'(.*)\';/;
var match_val = channel_str.match(ch_reg);
if (match_val.length>1){
a['channel'] = match_val[1];
}
}
var vlist = val.split(',');
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
@@ -2098,7 +2113,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2122,7 +2137,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2230,10 +2245,16 @@ function masterOrSlaveConf(version=''){
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Channel_Name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
@@ -2245,13 +2266,23 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Channel_Name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2262,6 +2293,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2276,22 +2308,74 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$('.db_error').click(function(){
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Channel_Name' in v){
deleteSlave(v['Channel_Name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
+16 -1
View File
@@ -35,7 +35,22 @@ if [ "$OSNAME" == "ubuntu" ];then
VERSION_ID="18.04"
fi
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_amd64
ARCH="amd64"
TMP_ARCH=`arch`
if [ "$TMP_ARCH" == "x86_64" ];then
ARCH="amd64"
elif [ "$TMP_ARCH" == "aarch64" ];then
ARCH="arm64"
else
ARCH="amd64"
fi
if [ "$ARCH" != "amd64" ];then
echo "暂时不支持该${ARCH}" > $install_tmp
exit 0
fi
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_${ARCH}
APT_INSTALL()
{
+18 -2
View File
@@ -22,8 +22,25 @@ VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -
# cd /www/server/mdserver-web/plugins/mysql-apt && bash install.sh install 8.0
ARCH="amd64"
TMP_ARCH=`arch`
if [ "$TMP_ARCH" == "x86_64" ];then
ARCH="amd64"
elif [ "$TMP_ARCH" == "aarch64" ];then
ARCH="arm64"
else
ARCH="amd64"
fi
if [ "$ARCH" != "amd64" ];then
echo "暂时不支持该${ARCH}" > $install_tmp
exit 1
fi
MYSQL_VER=8.0.30
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_amd64
SUFFIX_NAME=${MYSQL_VER}-1${OSNAME}${VERSION_ID}_${ARCH}
# /lib/systemd/system/mysql.service
@@ -81,7 +98,6 @@ Install_mysql()
useradd -g mysql mysql
fi
isApt=`which apt`
if [ "$isApt" != "" ];then
APT_INSTALL
+7 -2
View File
@@ -14,6 +14,9 @@ port = 33206
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
language={$SERVER_APP_PATH}/bin/usr/share/mysql/english
@@ -46,7 +49,6 @@ skip-ssl
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
@@ -66,12 +68,15 @@ binlog-ignore-db = performance_schema
#slave
log-slave-updates
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+7 -2
View File
@@ -16,6 +16,9 @@ mysqlx_port = 33260
socket = {$SERVER_APP_PATH}/mysql.sock
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
key_buffer_size = 8M
@@ -43,7 +46,6 @@ max_allowed_packet = 128M
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
@@ -62,12 +64,15 @@ binlog-ignore-db = performance_schema
#slave
log_replica_updates
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
default_storage_engine = InnoDB
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+1 -1
View File
@@ -15,7 +15,7 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
+236 -158
View File
@@ -36,25 +36,30 @@ def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
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(':')
if t.strip() == '':
tmp = []
else:
t = t.split(':', 1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
t = args[i].split(':', 1)
tmp[t[0]] = t[1]
return tmp
@@ -101,6 +106,14 @@ def getDbPort():
return tmp.groups()[0].strip()
def getDbServerId():
file = getConf()
content = mw.readFile(file)
rep = 'server-id\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
@@ -123,6 +136,9 @@ def contentReplace(content):
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$SERVER_APP_PATH}',
service_path + '/' + getPluginName())
server_id = int(time.time())
content = content.replace('{$SERVER_ID}', str(server_id))
return content
@@ -640,15 +656,15 @@ def isSqlError(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, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -1863,27 +1879,34 @@ def getMasterRepSlaveUserCmd(version):
mode = recognizeDbMode()
sid = getDbServerId()
channel_name = ""
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"])
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + str(mstatus[0]["Position"])
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2154,22 +2177,10 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
@@ -2193,100 +2204,149 @@ def initSlaveStatus(version=''):
return initSlaveStatusSyncUser(version)
def parseSlaveSyncCmd(cmd):
a = {}
if cmd.lower().find('for') > 0:
cmd_tmp = cmd.split('for')
cmd = cmd_tmp[0].strip()
pattern_c = r"channel \'(.*)\';"
match_val = re.match(pattern_c, cmd_tmp[1].strip(), re.I)
if match_val:
m_groups = match_val.groups()
a['channel'] = m_groups[0]
vlist = cmd.split(',')
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
msg = ''
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
mode_name = 'classic'
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
t = db.query(u['cmd'])
# print(t)
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
if slave_t['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
# print(u['cmd'])
t = pdb.query(cmd_sql)
isError = isSqlError(t)
if isError:
return isError
# pdb.query("start slave user='{}' password='{}';".format(
# u['user'], u['pass']))
pdb.query("start slave")
pdb.query("start all slaves")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
local_mode = recognizeDbMode()
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
db.query('stop slave')
db.query('reset slave all')
for data in ssh_list:
ip = data['ip']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql-yum/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
cmd_data = json.loads(result)
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']:【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
u = cmd_data['data']['info']
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ps = u['username'] + "|" + u['password']
print(ps)
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
db.query("start slave user='{}' password='{}';".format(
u['username'], u['password']))
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ssh.close()
time.sleep(1)
os.system("rm -rf " + SSH_PRIVATE_KEY)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
ssh.close()
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
db.query('start slave')
return mw.returnJson(True, '初始化成功!')
@@ -2296,60 +2356,37 @@ def setSlaveStatus(version=''):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Channel_Name' in v:
ch_name = v['Channel_Name']
cmd = "slave for channel '{}'".format(ch_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行[初始化]!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
u = data['ps'].split("|")
db.query("start slave user='{}' password='{}';".format(u[0], u[1]))
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2385,11 +2422,13 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mysql_yum_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
@@ -2407,16 +2446,32 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_db_import = args['db']
if sync_db.lower() == 'all':
sync_db_import = ''
dbs = findBinlogSlaveDoDb()
dbs_str = ''
for x in dbs:
dbs_str += ' ' + x
sync_db = "--databases " + dbs_str.strip()
sync_sign = args['sign']
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2433,17 +2488,18 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
dump_sql_data = getServerDir() + "/bin/usr/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
if os.path.exists(bak_file):
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db + ' < ' + bak_file
my_import_cmd = getServerDir() + '/bin/usr/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db_import + ' < ' + bak_file
mw.execShell(my_import_cmd)
if version == '8.0':
@@ -2452,21 +2508,30 @@ def doFullSyncUser(version=''):
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2508,7 +2573,8 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && python3 plugins/mysql/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 " + \
getSPluginDir() + "/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2531,7 +2597,10 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
@@ -2543,10 +2612,12 @@ def doFullSyncSSH(version=''):
cmd = cmd_data['data']['cmd']
# 保证同步IP一致
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*)'", "SOURCE_HOST='" + ip + "'", cmd, 1)
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
uinfo = cmd_data['data']['info']
@@ -2558,8 +2629,10 @@ def doFullSyncSSH(version=''):
root_dir = getServerDir()
msock = root_dir + "/mysql.sock"
mw.execShell("cd /tmp && gzip -d dump.sql.gz")
cmd = root_dir + "/bin/mysql -S " + msock + \
cmd = root_dir + "/bin/usr/bin/mysql -S " + msock + \
" -uroot -p" + pwd + " < /tmp/dump.sql"
print(cmd)
import_data = mw.execShell(cmd)
if import_data[0] == '':
print(import_data[1])
@@ -2569,8 +2642,9 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
db.query("start slave user='{}' password='{}';".format(
uinfo['username'], uinfo['password']))
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2584,12 +2658,16 @@ def fullSync(version=''):
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
sign = ''
if 'sign' in args:
sign = args['sign']
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
+164 -80
View File
@@ -162,34 +162,6 @@ function myPort(){
});
}
//数据库存储信置
function changeMySQLDataPath(act) {
if (act != undefined) {
layer.confirm(lan.soft.mysql_to_msg, { closeBtn: 2, icon: 3 }, function() {
var datadir = $("#datadir").val();
var data = 'datadir=' + datadir;
var loadT = layer.msg(lan.soft.mysql_to_msg1, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/database?action=SetDataDir', data, function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
});
});
return;
}
$.post('/database?action=GetMySQLInfo', '', function(rdata) {
var LimitCon = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="ChangePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function myPerfOpt() {
//获取MySQL配置
@@ -1691,12 +1663,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1704,28 +1676,73 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Channel_Name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
function fullSync(db,sign,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1738,19 +1755,6 @@ function getFullSyncStatus(db){
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -1920,18 +1924,29 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[最好填好]</span>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
val = cmd_tmp[0].trim();
const channel_str = cmd_tmp[1].trim();
const ch_reg = /channel \'(.*)\';/;
var match_val = channel_str.match(ch_reg);
if (match_val.length>1){
a['channel'] = match_val[1];
}
}
var vlist = val.split(',');
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
@@ -2098,7 +2113,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2122,7 +2137,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2230,10 +2245,16 @@ function masterOrSlaveConf(version=''){
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Channel_Name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
@@ -2245,13 +2266,23 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Channel_Name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2262,6 +2293,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2276,22 +2308,74 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$('.db_error').click(function(){
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Channel_Name' in v){
deleteSlave(v['Channel_Name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
+1 -1
View File
@@ -70,7 +70,7 @@ log-slave-updates = 1
# Prevent replication from starting automatically with MySQL
#skip-slave-start = 1
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
+2 -1
View File
@@ -18,6 +18,7 @@ basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
@@ -72,7 +73,7 @@ log-slave-updates = 1
# Prevent replication from starting automatically with MySQL
#skip-slave-start = 1
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
+4 -1
View File
@@ -16,6 +16,7 @@ basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
explicit_defaults_for_timestamp=true
default_storage_engine = InnoDB
@@ -74,12 +75,14 @@ binlog-ignore-db = performance_schema
# Prevent replication from starting automatically with MySQL
#skip-slave-start = 1
#replicate-do-db
slave_skip_errors=1062
slave_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+4 -1
View File
@@ -20,6 +20,7 @@ basedir = {$SERVER_APP_PATH}
datadir = {$SERVER_APP_PATH}/data
log-error = {$SERVER_APP_PATH}/data/error.log
server-id = {$SERVER_ID}
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
default_storage_engine = InnoDB
@@ -71,12 +72,14 @@ log_replica_updates = 1
# Prevent replication from starting automatically with MySQL
#skip_replica_start = 1
#replicate-do-db
replica_skip_errors=1062
replica_skip_errors=1062,1396
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
replicate-ignore-db = test
master_info_repository = table
relay_log_info_repository = table
innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
+1 -1
View File
@@ -15,7 +15,7 @@
<p onclick="dbList()">管理列表</p>
<p onclick="masterOrSlaveConf($('.plugin_version').attr('version'))">主从配置</p>
</div>
<div class="bt-w-con pd15">
<div class="bt-w-con pd15" style="height:555px;overflow: auto;">
<div class="soft-man-con"></div>
</div>
</div>
+278 -184
View File
@@ -36,13 +36,21 @@ def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getSPluginDir():
return '/www/server/mdserver-web/plugins/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
if app_debug:
current_os = mw.getOs()
if current_os == 'darwin':
return '/tmp/' + getPluginName()
if current_os.startswith('freebsd'):
return '/etc/rc.d/' + getPluginName()
return '/etc/init.d/' + getPluginName()
@@ -85,6 +93,14 @@ def getDbPort():
return tmp.groups()[0].strip()
def getDbServerId():
file = getConf()
content = mw.readFile(file)
rep = 'server-id\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getSocketFile():
file = getConf()
content = mw.readFile(file)
@@ -512,12 +528,26 @@ def initMysql8Pwd():
def myOp(version, method):
# import commands
init_file = initDreplace(version)
current_os = mw.getOs()
try:
isInited = initMysqlData()
if not isInited:
mw.execShell('systemctl start mysql')
if current_os.startswith("freebsd"):
mw.execShell('service ' + getPluginName() + ' start')
else:
mw.execShell('systemctl start mysql')
initMysqlPwd()
mw.execShell('systemctl stop mysql')
if current_os.startswith("freebsd"):
mw.execShell('service ' + getPluginName() + ' stop')
else:
mw.execShell('systemctl stop mysql')
if current_os.startswith("freebsd"):
data = mw.execShell('service ' + getPluginName() + ' ' + method)
return 'ok'
mw.execShell('systemctl ' + method + ' mysql')
return 'ok'
@@ -598,9 +628,15 @@ def reload(version=''):
def initdStatus():
if mw.isAppleSystem():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status mysql | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
@@ -609,17 +645,34 @@ def initdStatus():
def initdInstall():
if mw.isAppleSystem():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
import shutil
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="YES"')
return 'ok'
mw.execShell('systemctl enable mysql')
return 'ok'
def initdUinstall():
if mw.isAppleSystem():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('sysrc ' + getPluginName() + '_enable="NO"')
return 'ok'
mw.execShell('systemctl disable mysql')
return 'ok'
@@ -736,6 +789,9 @@ def runInfo(version):
def myDbStatus(version):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动', [])
result = {}
db = pMysqlDb()
data = db.query('show variables')
@@ -802,15 +858,15 @@ def isSqlError(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, '数据库密码错误,在管理列表-点击【修复】!')
if "1045" in mysqlMsg:
if "1045," in mysqlMsg:
return mw.returnJson(False, '连接错误!')
if "SQL syntax" in mysqlMsg:
return mw.returnJson(False, 'SQL语法错误!')
if "Connection refused" in mysqlMsg:
return mw.returnJson(False, '数据库连接失败,请检查数据库服务是否启动!')
if "1133" in mysqlMsg:
if "1133," in mysqlMsg:
return mw.returnJson(False, '数据库用户不存在!')
if "1007" in mysqlMsg:
if "1007," in mysqlMsg:
return mw.returnJson(False, '数据库已经存在!')
return None
@@ -1887,13 +1943,14 @@ def getMasterStatus(version=''):
data = {}
data['mode'] = recognizeDbMode()
data['status'] = master_status
data['slave_status'] = False
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
for v in dlist:
if v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes':
data['slave_status'] = True
return mw.returnJson(master_status, '设置成功', data)
except Exception as e:
@@ -2057,27 +2114,34 @@ def getMasterRepSlaveUserCmd(version):
mode = recognizeDbMode()
sid = getDbServerId()
channel_name = ""
if sid != '':
channel_name = " for channel 'r{}';".format(sid)
if mode == "gtid":
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + "', MASTER_AUTO_POSITION=1" + channel_name
if version == '8.0':
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + "', MASTER_AUTO_POSITION=1"
clist[0]['password'] + \
"', MASTER_AUTO_POSITION=1" + channel_name
else:
sql = "CHANGE MASTER TO MASTER_HOST='" + ip + "', MASTER_PORT=" + port + ", MASTER_USER='" + \
clist[0]['username'] + "', MASTER_PASSWORD='" + \
clist[0]['password'] + \
"', MASTER_LOG_FILE='" + mstatus[0]["File"] + \
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"])
"',MASTER_LOG_POS=" + str(mstatus[0]["Position"]) + channel_name
if version == "8.0":
sql = "CHANGE REPLICATION SOURCE TO SOURCE_HOST='" + ip + "', SOURCE_PORT=" + port + ", SOURCE_USER='" + \
clist[0]['username'] + "', SOURCE_PASSWORD='" + \
clist[0]['password'] + \
"', SOURCE_LOG_FILE='" + mstatus[0]["File"] + \
"',SOURCE_LOG_POS=" + str(mstatus[0]["Position"])
"',SOURCE_LOG_POS=" + \
str(mstatus[0]["Position"]) + channel_name
data = {}
data['cmd'] = sql
@@ -2348,52 +2412,27 @@ def updateSlaveSSH(version=''):
def getSlaveList(version=''):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动', [])
db = pMysqlDb()
dlist = db.query('show slave status')
ret = []
for x in range(0, len(dlist)):
tmp = {}
tmp['Master_User'] = dlist[x]["Master_User"]
tmp['Master_Host'] = dlist[x]["Master_Host"]
tmp['Master_Port'] = dlist[x]["Master_Port"]
tmp['Master_Log_File'] = dlist[x]["Master_Log_File"]
tmp['Slave_IO_Running'] = dlist[x]["Slave_IO_Running"]
tmp['Slave_SQL_Running'] = dlist[x]["Slave_SQL_Running"]
tmp['Last_Error'] = dlist[x]["Last_Error"]
tmp['Last_IO_Error'] = dlist[x]["Last_IO_Error"]
tmp['Last_SQL_Error'] = dlist[x]["Last_SQL_Error"]
tmp['Slave_SQL_Running_State'] = dlist[x]["Slave_SQL_Running_State"]
tmp['Error'] = ''
if tmp['Last_Error'] != '':
tmp['Error'] = tmp['Last_Error']
if tmp['Last_IO_Error'] != '':
tmp['Error'] = tmp['Last_IO_Error']
if tmp['Last_SQL_Error'] != '':
tmp['Error'] = tmp['Last_SQL_Error']
if tmp['Error'] == '':
tmp['Error'] = tmp['Slave_SQL_Running_State']
ret.append(tmp)
data = {}
data['data'] = ret
data['data'] = dlist
return mw.getJson(data)
def getSlaveSyncCmd(version=''):
root = mw.getRunDir()
cmd = 'cd ' + root + ' && python3 ' + root + \
'/plugins/mysql/index.py do_full_sync {"db":"all"}'
'/plugins/mysql/index.py do_full_sync {"db":"all","sign",""}'
return mw.returnJson(True, 'ok', cmd)
def initSlaveStatus(version=''):
if status(version) == 'stop':
return mw.returnJson(False, 'MySQL未启动', [])
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
@@ -2424,111 +2463,152 @@ def makeSyncUsercmd(u, version=''):
return sql
def parseSlaveSyncCmd(cmd):
a = {}
if cmd.lower().find('for') > 0:
cmd_tmp = cmd.split('for')
cmd = cmd_tmp[0].strip()
pattern_c = r"channel \'(.*)\';"
match_val = re.match(pattern_c, cmd_tmp[1].strip(), re.I)
if match_val:
m_groups = match_val.groups()
a['channel'] = m_groups[0]
vlist = cmd.split(',')
for i in vlist:
tmp = i.strip()
tmp_a = tmp.split(" ")
real_tmp = tmp_a[len(tmp_a) - 1]
kv = real_tmp.split("=")
a[kv[0]] = kv[1].replace("'", '').replace("'", '').replace(";", '')
return a
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
slave_data = conn.field('ip,port,user,pass,mode,cmd').select()
if len(slave_data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
pdb = pMysqlDb()
if len(slave_data) == 1:
dlist = pdb.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
msg = ''
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
for x in range(len(slave_data)):
slave_t = slave_data[x]
mode_name = 'classic'
base_t = 'IP:' + slave_t['ip'] + ",PORT:" + \
slave_t['port'] + ",USER:" + slave_t['user']
if u['cmd'] == '' and local_mode == 'gtid':
sql = makeSyncUsercmd(u, version)
# print(sql)
t = db.query(sql)
else:
if u['cmd'] == '':
return mw.returnJson(False, '经典模式下,必须手写同步命令!')
if slave_t['mode'] == '1':
mode_name = 'gtid'
if local_mode != mode_name:
msg += base_t + '->同步模式不一致'
continue
cmd_sql = slave_t['cmd']
if cmd_sql == '':
msg += base_t + '->同步命令不能为空'
continue
try:
pinfo = parseSlaveSyncCmd(cmd_sql)
except Exception as e:
return mw.returnJson(False, base_t + '->CMD同步命令不合规范!')
# print(u['cmd'])
t = db.query(u['cmd'])
isError = isSqlError(t)
if isError:
return isError
t = pdb.query(cmd_sql)
isError = isSqlError(t)
if isError:
return isError
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
# pdb.query("start slave user='{}' password='{}';".format(
# u['user'], u['pass']))
pdb.query("start slave")
pdb.query("start all slaves")
if msg == '':
msg = '初始化成功!'
return mw.returnJson(True, msg)
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,port,id_rsa').find()
ssh_list = conn.field('ip,port,id_rsa,db_user').select()
if len(data) < 1:
return mw.returnJson(False, '需要先添加SSH配置!')
if len(ssh_list) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
local_mode = recognizeDbMode()
import paramiko
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
try:
db.query('stop slave')
db.query('reset slave all')
for data in ssh_list:
ip = data['ip']
SSH_PRIVATE_KEY = "/tmp/t_ssh_" + ip + ".txt"
master_port = data['port']
mw.writeFile(SSH_PRIVATE_KEY, data['id_rsa'].replace('\\n', '\n'))
mw.execShell("chmod 600 " + SSH_PRIVATE_KEY)
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
try:
key = paramiko.RSAKey.from_private_key_file(SSH_PRIVATE_KEY)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, port=int(master_port),
username='root', pkey=key)
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
cmd_data = json.loads(result)
db_user = data['db_user']
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
if result.strip() == "":
return mw.returnJson(False, '[主][' + ip + ']:获取同步命令失败!')
if not cmd_data['status']:
return mw.returnJson(False, '[主]:' + cmd_data['msg'])
cmd_data = json.loads(result)
if not cmd_data['status']:
return mw.returnJson(False, '[主][' + ip + ']:' + cmd_data['msg'])
local_mode = recognizeDbMode()
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '主【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
if local_mode != cmd_data['data']['mode']:
return mw.returnJson(False, '[主][' + ip + ']:【{}】从【{}】,运行模式不一致!'.format(cmd_data['data']['mode'], local_mode))
u = cmd_data['data']['info']
ps = u['username'] + "|" + u['password']
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
u = cmd_data['data']['info']
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ps = u['username'] + "|" + u['password']
print(ps)
conn.where('ip=?', (ip,)).setField('ps', ps)
db.query('stop slave')
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
db.query("start slave user='{}' password='{}';".format(
u['username'], u['password']))
except Exception as e:
return mw.returnJson(False, 'SSH认证配置连接失败!' + str(e))
# 保证同步IP一致
cmd = cmd_data['data']['cmd']
if cmd.find('SOURCE_HOST') > -1:
cmd = re.sub(r"SOURCE_HOST='(.*?)'",
"SOURCE_HOST='" + ip + "'", cmd, 1)
ssh.close()
time.sleep(1)
os.system("rm -rf " + SSH_PRIVATE_KEY)
if cmd.find('MASTER_HOST') > -1:
cmd = re.sub(r"MASTER_HOST='(.*?)'",
"MASTER_HOST='" + ip + "'", cmd, 1)
db.query(cmd)
ssh.close()
if os.path.exists(SSH_PRIVATE_KEY):
os.system("rm -rf " + SSH_PRIVATE_KEY)
except Exception as e:
return mw.returnJson(False, '[主][' + ip + ']:SSH认证配置连接失败!' + str(e))
db.query('start slave')
return mw.returnJson(True, '初始化成功!')
@@ -2538,60 +2618,37 @@ def setSlaveStatus(version=''):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
pdb = pMysqlDb()
dlist = pdb.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
for v in dlist:
connection_name = ''
cmd = "slave"
if 'Channel_Name' in v:
ch_name = v['Channel_Name']
cmd = "slave for channel '{}'".format(ch_name)
db.query("start slave")
# db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加主服务命令或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_id_rsa')
data = conn.field('ip,ps').where("ip=?", (ip,)).find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
u = data['ps'].split("|")
db.query("start slave user='{}' password='{}';".format(u[0], u[1]))
if (v["Slave_IO_Running"] == 'Yes' or v["Slave_SQL_Running"] == 'Yes'):
pdb.query("stop {}".format(cmd))
else:
pdb.query("start {}".format(cmd))
return mw.returnJson(True, '设置成功!')
def deleteSlave(version=''):
args = getArgs()
db = pMysqlDb()
dlist = db.query('stop slave')
dlist = db.query('reset slave all')
if 'sign' in args:
sign = args['sign']
db.query("stop slave for channel '{}'".format(sign))
db.query("reset slave all for channel '{}'".format(sign))
else:
db.query('stop slave')
db.query('reset slave all')
return mw.returnJson(True, '删除成功!')
@@ -2628,11 +2685,13 @@ def dumpMysqlData(version=''):
############### --- 重要 同步---- ###########
def asyncTmpfile():
path = '/tmp/mysql_async_status.txt'
return path
def writeDbSyncStatus(data):
path = '/tmp/db_async_status.txt'
# status_data['code'] = 1
# status_data['msg'] = '主服务器备份完成...'
# status_data['progress'] = 30
path = asyncTmpfile()
mw.writeFile(path, json.dumps(data))
@@ -2650,16 +2709,32 @@ def doFullSync(version=''):
def doFullSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_db_import = args['db']
if sync_db.lower() == 'all':
sync_db_import = ''
dbs = findBinlogSlaveDoDb()
dbs_str = ''
for x in dbs:
dbs_str += ' ' + x
sync_db = "--databases " + dbs_str.strip()
sync_sign = args['sign']
db = pMysqlDb()
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if sync_sign != '':
data = conn.field('ip,port,user,pass,mode,cmd').where(
'ip=?', (sync_sign,)).find()
else:
data = conn.field('ip,port,user,pass,mode,cmd').find()
user = data['user']
apass = data['pass']
port = data['port']
@@ -2687,7 +2762,8 @@ def doFullSyncUser(version=''):
pwd = pSqliteDb('config').where('id=?', (1,)).getField('mysql_root')
sock = getSocketFile()
my_import_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + pwd + \
' ' + sync_db + ' < ' + bak_file
' ' + sync_db_import + ' < ' + bak_file
# print(my_import_cmd)
mw.execShell(my_import_cmd)
if version == '8.0':
@@ -2696,21 +2772,30 @@ def doFullSyncUser(version=''):
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + bak_file)
if os.path.exists(bak_file):
os.system("rm -rf " + bak_file)
return True
def doFullSyncSSH(version=''):
args = getArgs()
data = checkArgs(args, ['db'])
data = checkArgs(args, ['db', 'sign'])
if not data[0]:
return data[1]
sync_db = args['db']
sync_sign = args['sign']
db = pMysqlDb()
id_rsa_conn = pSqliteDb('slave_id_rsa')
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
if sync_sign != '':
data = id_rsa_conn.field('ip,port,db_user,id_rsa').where(
'ip=?', (sync_sign,)).find()
else:
data = id_rsa_conn.field('ip,port,db_user,id_rsa').find()
SSH_PRIVATE_KEY = "/tmp/mysql_sync_id_rsa.txt"
id_rsa = data['id_rsa'].replace('\\n', '\n')
@@ -2752,7 +2837,8 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 0, 'msg': '登录Master成功...', 'progress': 5})
dbname = args['db']
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
cmd = "cd /www/server/mdserver-web && source bin/activate && python3 " + \
getSPluginDir() + "/index.py dump_mysql_data {\"db\":'" + dbname + "'}"
print(cmd)
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
@@ -2775,7 +2861,10 @@ def doFullSyncSSH(version=''):
if copy_status == None:
writeDbSyncStatus({'code': 2, 'msg': '数据同步本地完成...', 'progress': 40})
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 plugins/mysql/index.py get_master_rep_slave_user_cmd {"username":"' + db_user + '","db":""}'
cmd = 'cd /www/server/mdserver-web && source bin/activate && python3 ' + \
getSPluginDir() + \
'/index.py get_master_rep_slave_user_cmd {"username":"' + \
db_user + '","db":""}'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
result = result.decode('utf-8')
@@ -2817,8 +2906,9 @@ def doFullSyncSSH(version=''):
writeDbSyncStatus({'code': 5, 'msg': '导入数据失败...', 'progress': 100})
return 'fail'
db.query("start slave user='{}' password='{}';".format(
uinfo['username'], uinfo['password']))
# "start slave user='{}' password='{}';".format(uinfo['username'], uinfo['password'])
db.query("start slave")
writeDbSyncStatus({'code': 6, 'msg': '从库重启完成...', 'progress': 100})
os.system("rm -rf " + SSH_PRIVATE_KEY)
@@ -2832,12 +2922,16 @@ def fullSync(version=''):
if not data[0]:
return data[1]
status_file = '/tmp/db_async_status.txt'
sign = ''
if 'sign' in args:
sign = args['sign']
status_file = asyncTmpfile()
if args['begin'] == '1':
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + \
getPluginDir() + \
'/index.py do_full_sync {"db":"' + args['db'] + '"} &'
print(cmd)
cmd = 'cd ' + mw.getRunDir() + ' && python3 ' + getPluginDir() + \
'/index.py do_full_sync {"db":"' + \
args['db'] + '","sign":"' + sign + '"} &'
# print(cmd)
mw.execShell(cmd)
return json.dumps({'code': 0, 'msg': '同步数据中!', 'progress': 0})
+2 -2
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.30"],
"updates":["5.5.62","5.6.50", "5.7.32","8.0.34"],
"shell":"install.sh",
"checks":"server/mysql",
"path":"server/mysql",
@@ -19,4 +19,4 @@
"home":"https://dev.mysql.com/downloads/mysql",
"date":"2017-11-24",
"pid": "2"
}
}
+164 -80
View File
@@ -162,34 +162,6 @@ function myPort(){
});
}
//数据库存储信置
function changeMySQLDataPath(act) {
if (act != undefined) {
layer.confirm(lan.soft.mysql_to_msg, { closeBtn: 2, icon: 3 }, function() {
var datadir = $("#datadir").val();
var data = 'datadir=' + datadir;
var loadT = layer.msg(lan.soft.mysql_to_msg1, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/database?action=SetDataDir', data, function(rdata) {
layer.close(loadT)
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 5 });
});
});
return;
}
$.post('/database?action=GetMySQLInfo', '', function(rdata) {
var LimitCon = '<p class="conf_p">\
<input id="datadir" class="phpUploadLimit bt-input-text mr5" style="width:350px;" type="text" value="' + rdata.datadir + '" name="datadir">\
<span onclick="changePath(\'datadir\')" class="glyphicon glyphicon-folder-open cursor mr20" style="width:auto"></span><button class="btn btn-success btn-sm" onclick="changeMySQLDataPath(1)">' + lan.soft.mysql_to + '</button>\
</p>';
$(".soft-man-con").html(LimitCon);
});
}
//数据库配置状态
function myPerfOpt() {
//获取MySQL配置
@@ -1691,12 +1663,12 @@ function getMasterRepSlaveListPage(){
}
function deleteSlave(){
myPost('delete_slave', {}, function(data){
function deleteSlave(sign){
myPost('delete_slave', {sign:sign}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata['msg'], function(){
masterOrSlaveConf();
},{},3000);
},{icon:rdata.status?1:2,time:3000},3000);
});
}
@@ -1704,28 +1676,73 @@ function deleteSlave(){
function getFullSyncStatus(db){
var timeId = null;
var btn = '<div class="table_toolbar" style="left:0px;"><span data-status="init" class="sync btn btn-default btn-sm" id="begin_full_sync" title="">开始</span></div>';
var loadOpen = layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
"+btn+"\
</div>",
cancel: function(){
clearInterval(timeId);
myPost('get_slave_list', {page:1,page_size:100}, function(data){
var rdata = $.parseJSON(data.data);
var rsource = rdata.data;
if (db == 'ALL' && rsource.length>1){
layer.msg("多主不支持该模式!",{icon:2});
return;
}
var dataSource = '';
if (rsource.length>1){
var sourceList = '';
for (var i = 0; i < rsource.length; i++) {
if ('Channel_Name' in rsource[i]){
sourceList += '<option val="'+rsource[i]['Master_Host']+'">'+rsource[i]['Master_Host']+'</option>';
}
}
dataSource = "<p class='line' style='text-align:center;'>\
<span>同步数据源:</span>\
<select class='bt-input-text' name='data_source' style='width:200px;'>" + sourceList + "</select>\
</p>";
}
layer.open({
type: 1,
title: '全量同步['+db+']',
area: '500px',
content:"<div class='bt-form pd15'>\
<div class='divtable mtb10'>\
"+dataSource+"\
<span id='full_msg'></span>\
<div class='progress'>\
<div class='progress-bar' role='progressbar' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='min-width: 2em;'>0%</div>\
</div>\
</div>\
<div class='table_toolbar' style='left:0px;'>\
<span data-status='init' class='sync btn btn-default btn-sm' id='begin_full_sync'>开始</span>\
</div>\
</div>",
cancel: function(){
clearInterval(timeId);
},
success:function(){
$('#begin_full_sync').click(function(){
var val = $(this).data('status');
var sign = '';
if (dataSource !=''){
sign = $('select[name="data_source"]').val();
}
if (val == 'init'){
fullSync(db, sign, 1);
timeId = setInterval(function(){
fullSync(db,sign,0);
}, 1000);
$(this).data('status','starting');
} else {
layer.msg("正在同步中..",{icon:0});
}
});
}
});
});
function fullSync(db,begin){
function fullSync(db,sign,begin){
myPostN('full_sync', {db:db,begin:begin}, function(data){
myPostN('full_sync', {db:db,sign:sign,begin:begin}, function(data){
var rdata = $.parseJSON(data.data);
$('#full_msg').text(rdata['msg']);
$('.progress-bar').css('width',rdata['progress']+'%');
@@ -1738,19 +1755,6 @@ function getFullSyncStatus(db){
}
});
}
$('#begin_full_sync').click(function(){
var val = $(this).attr('data-status');
if (val == 'init'){
fullSync(db,1);
timeId = setInterval(function(){
fullSync(db,0);
}, 1000);
$(this).attr('data-status','starting');
} else {
layer.msg("正在同步中..");
}
});
}
function addSlaveSSH(ip=''){
@@ -1920,18 +1924,29 @@ function addSlaveSyncUser(ip=''){
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[最好填好]</span>\
<span class='tname'>CMD[必须填写]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
if (val.toLowerCase().indexOf('for')>0){
cmd_tmp = val.split('for');
val = cmd_tmp[0].trim();
const channel_str = cmd_tmp[1].trim();
const ch_reg = /channel \'(.*)\';/;
var match_val = channel_str.match(ch_reg);
if (match_val.length>1){
a['channel'] = match_val[1];
}
}
var vlist = val.split(',');
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
@@ -2098,7 +2113,7 @@ function getSlaveUserList(){
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2122,7 +2137,7 @@ function getSlaveSSHList(page=1){
layerId = layer.open({
type: 1,
title: 'SSH列表',
area: '500px',
area: '600px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
@@ -2230,10 +2245,16 @@ function masterOrSlaveConf(version=''){
myPost('get_slave_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
var isHasSign = false;
for(i in rdata.data){
var v = rdata.data[i];
var status = "<a class='btlink db_error'>异常</>";
if ('Channel_Name' in v){
isHasSign = true;
}
var status = "<a data-id="+i+" class='btlink db_error'>异常</>";
if (v['Slave_SQL_Running'] == 'Yes' && v['Slave_IO_Running'] == 'Yes'){
status = "正常";
}
@@ -2245,13 +2266,23 @@ function masterOrSlaveConf(version=''){
list += '<td>' + rdata.data[i]['Master_Log_File'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_IO_Running'] +'</td>';
list += '<td>' + rdata.data[i]['Slave_SQL_Running'] +'</td>';
if (isHasSign){
list += '<td>' + v['Channel_Name'] +'</td>';
}
list += '<td>' + status +'</td>';
list += '<td style="text-align:right">' +
'<a href="javascript:;" class="btlink" onclick="deleteSlave()" title="删除">删除</a>' +
'<a data-id="'+i+'" href="javascript:;" class="btlink btn_delete_slave" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var signThead_th = '';
if (isHasSign){
var signThead_th = '<th>标识</th>';
}
var con = '<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
@@ -2262,6 +2293,7 @@ function masterOrSlaveConf(version=''){
<th>日志</th>\
<th>IO</th>\
<th>SQL</th>\
'+signThead_th+'\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
@@ -2276,22 +2308,74 @@ function masterOrSlaveConf(version=''){
// </div>
$(".table_slave_status_list").html(con);
$('.db_error').click(function(){
$(".btn_delete_slave").click(function(){
var id = $(this).data('id');
var v = rdata.data[id];
if ('Channel_Name' in v){
deleteSlave(v['Channel_Name']);
} else{
deleteSlave();
}
});
$('.db_error').click(function(){
var id = $(this).data('id');
var info = rdata.data[id];
var err_line = "";
err_line +="<tr>\
<td>IO错误</td>\
<td>"+ (info['Last_IO_Error'] == '' ? '无':info['Last_IO_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>SQL错误</td>\
<td>"+(info['Last_SQL_Error'] == '' ? '无':info['Last_SQL_Error'])+"</td>\
</tr>";
err_line +="<tr>\
<td>状态</td>\
<td>"+(info['Slave_SQL_Running_State'] == '' ? '无':info['Slave_SQL_Running_State']) +"</td>\
</tr>";
layer.open({
type: 1,
title: '同步异常信息',
area: '500px',
content:"<form class='bt-form pd20 pb70'>\
<div class='line'>"+v['Error']+"</div>\
<div class='bt-form-submit-btn'>\
<button type='button' class='btn btn-success btn-sm btn-title class-copy-db-err'>复制</button>\
area: ['600px','300px'],
btn:['复制错误',"取消"],
content:"<form class='bt-form pd15'>\
<div class='divtable mtb10'>\
<div class='tablescroll'>\
<table class='table table-hover' width='100%' cellspacing='0' cellpadding='0' border='0' style='border: 0 none;'>\
<thead><tr>\
<th style='width:80px;'>类型</th>\
<th>内容</th>\
</tr></thead>\
<tbody>"+ err_line +"</tbody>\
</table>\
</div>\
</div>\
</form>",
</form>",
success:function(){
copyText(v['Error']);
$('.class-copy-db-err').click(function(){
copyText(v['Error']);
});
// copyText(v['Error']);
// $('.class-copy-db-err').click(function(){
// copyText(v['Error']);
// });
},
yes:function(){
if (info['Last_IO_Error'] != ''){
copyText(info['Last_IO_Error']);
return;
}
if (info['Last_SQL_Error'] != ''){
copyText(info['Last_SQL_Error']);
return;
}
if (info['Slave_SQL_Running_State'] != ''){
copyText(info['Slave_SQL_Running_State']);
return;
}
}
});
});
+11 -2
View File
@@ -66,6 +66,15 @@ Install_mysql()
cd ${mysqlDir} && tar -zxvf ${mysqlDir}/mysql-5.5.62.tar.gz
fi
WHERE_DIR_GCC=/usr/bin/gcc
WHERE_DIR_GPP=/usr/bin/g++
if [ ! -f $WHERE_DIR_GCC ];then
WHERE_DIR_GCC=`which gcc`
fi
if [ ! -f $WHERE_DIR_GPP ];then
WHERE_DIR_GPP=`which g++`
fi
if [ ! -d $serverPath/mysql ];then
cd ${mysqlDir}/mysql-5.5.62 && cmake \
@@ -81,8 +90,8 @@ Install_mysql()
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
-DCMAKE_C_COMPILER=$WHERE_DIR_GCC \
-DCMAKE_CXX_COMPILER=$WHERE_DIR_GPP
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mysql ];then
+3 -3
View File
@@ -76,9 +76,9 @@ Install_mysql()
OPENSSL_VERSION=`openssl version|awk '{print $2}'|awk -F '.' '{print $1}'`
if [ "${OPENSSL_VERSION}" -ge "3" ];then
#openssl version to high
cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl"
cd ${rootPath}/plugins/php/lib && /bin/bash openssl10.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl10/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl10"
fi
if [ ! -d $serverPath/mysql ];then
+3 -3
View File
@@ -91,9 +91,9 @@ Install_mysql()
OPENSSL_VERSION=`openssl version|awk '{print $2}'|awk -F '.' '{print $1}'`
if [ "${OPENSSL_VERSION}" -ge "3" ];then
#openssl version to high
cd ${rootPath}/plugins/php/lib && /bin/bash openssl.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl"
cd ${rootPath}/plugins/php/lib && /bin/bash openssl_11.sh
export PKG_CONFIG_PATH=$serverPath/lib/openssl11/lib/pkgconfig
OPTIONS="-DWITH_SSL=${serverPath}/lib/openssl11"
fi
if [ ! -d $serverPath/mysql ];then

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