Compare commits

...
958 Commits
Author SHA1 Message Date
Mr Chen cf00bd3d98 Merge pull request #504 from midoks/dev
0.16.2
2023-11-18 22:55:14 +08:00
Mr Chen ad3f42059d Update config_api.py 2023-11-18 22:54:08 +08:00
Mr Chen 9a1d3f5e15 Update README.md 2023-11-18 22:53:06 +08:00
Mr Chen f2246cf8ba Update index.py 2023-11-18 20:46:11 +08:00
Mr Chen 81aabd3910 Update index.py 2023-11-18 20:44:51 +08:00
Mr Chen 235b1dc5e4 Update install.sh 2023-11-18 20:43:39 +08:00
Mr Chen ad007b07a5 Update haproxy.conf 2023-11-18 20:40:54 +08:00
Mr Chen 53cc020108 Update install.sh 2023-11-18 20:36:34 +08:00
Mr Chen 71d63f3d68 Update install.sh 2023-11-18 20:34:44 +08:00
Mr Chen 917b3f6099 Update default.tpl 2023-11-18 20:29:49 +08:00
Mr Chen 36341f66f1 Update haproxy.conf 2023-11-18 20:29:32 +08:00
Mr Chen 2a16e1d262 安装优化 2023-11-18 20:28:17 +08:00
Mr Chen d27db369dc Update public.js 2023-11-18 20:16:03 +08:00
Mr Chen 6619ae0bc5 haproxy 配置检查 2023-11-18 20:13:39 +08:00
Mr Chen da1646eaed Update info.json 2023-11-18 19:37:14 +08:00
Mr Chen bf88621629 Create keepalived.lvs.nat.master.conf 2023-11-18 18:07:19 +08:00
Mr Chen 7497c4608a Update install.sh 2023-11-18 17:34:15 +08:00
Mr Chen b0ee844b84 Update lvs.js 2023-11-18 17:32:43 +08:00
Mr Chen 3efa46ce70 Update lvs.js 2023-11-18 17:32:29 +08:00
Mr Chen aaaef570a4 Update default.tpl 2023-11-18 17:28:51 +08:00
Mr Chen 53c651724a update 2023-11-18 17:28:11 +08:00
Mr Chen dd8c97f4b8 update 2023-11-18 17:17:55 +08:00
Mr Chen b4e1a5947e Update install.sh 2023-11-18 17:14:49 +08:00
Mr Chen 784056d465 Update install.sh 2023-11-18 17:10:47 +08:00
Mr Chen b1fbdf8d60 Update mw.tpl 2023-11-18 17:08:59 +08:00
Mr Chen f9459089a4 Update mw.tpl 2023-11-18 17:08:46 +08:00
Mr Chen 36c3967e38 Update push_notice_msg.py 2023-11-18 16:25:31 +08:00
Mr Chen c7ba5fa2d9 Update push_ad.py 2023-11-18 16:25:07 +08:00
Mr Chen 5f2f6d15ed Update linux.conf 2023-11-18 16:20:49 +08:00
Mr Chen 5e3c81d785 update 2023-11-18 15:54:40 +08:00
Mr Chen 76560bc4fd Update info.json 2023-11-18 15:27:34 +08:00
Mr Chen e84a104584 Update webstats_common.lua 2023-11-18 12:45:29 +08:00
Mr Chen afe7175941 Update webstats_common.lua 2023-11-18 04:32:35 +08:00
Mr Chen 4b7c821a91 Update index.py 2023-11-18 03:39:53 +08:00
Mr Chen 1941479092 Update index.py 2023-11-18 03:37:41 +08:00
Mr Chen bfcfc2015a Update index.py 2023-11-18 03:36:13 +08:00
Mr Chen 8a5daeb327 网站统计-加入耗时搜索 2023-11-18 03:32:39 +08:00
Mr Chen 66049068aa Update webstats_common.lua 2023-11-18 02:40:03 +08:00
Mr Chen e2d680cb2a 修复反向代理代过来的数据 2023-11-18 02:36:18 +08:00
Mr Chen 719eec4b98 Update install.sh 2023-11-18 01:51:25 +08:00
Mr Chen 9ea859f94c Update install.sh 2023-11-18 01:51:11 +08:00
Mr Chen 0bdd384f46 Update install.sh 2023-11-18 01:50:21 +08:00
Mr Chen c3d20f358c Update install.sh 2023-11-18 01:04:50 +08:00
Mr Chen 7a6454e126 Update requirements.txt 2023-11-18 00:50:33 +08:00
Mr Chen d683069fef Update info.json 2023-11-17 23:45:41 +08:00
Mr Chen 5e7e7af1a7 update 2023-11-17 23:35:23 +08:00
Mr Chen 5894323eec Update README.md 2023-11-17 23:12:54 +08:00
Mr Chen 1cd4996527 Update linux.conf 2023-11-17 20:58:46 +08:00
Mr Chen 78786a92e9 Update linux.conf 2023-11-17 20:57:41 +08:00
Mr Chen 67d5d3fac5 Update linux.conf 2023-11-17 20:57:26 +08:00
Mr Chen 5caf8f52bc Update index.html 2023-11-17 19:16:58 +08:00
Mr Chen b838caea8b update 2023-11-17 18:56:07 +08:00
Mr Chen 57d4ef5fc9 Update index.py 2023-11-17 18:52:05 +08:00
Mr Chen ca3d8cccc9 Update install.sh 2023-11-17 18:33:39 +08:00
Mr Chen c56aa2efa3 Update install.sh 2023-11-17 18:33:21 +08:00
Mr Chen f41ef634bf Update install.sh 2023-11-17 18:30:41 +08:00
Mr Chen 80e3a73fa4 Update install.sh 2023-11-17 17:54:08 +08:00
Mr Chen c4788c03f9 update 2023-11-17 17:49:42 +08:00
Mr Chen 501012b4e6 初始化lvs插件 2023-11-17 17:40:58 +08:00
Mr Chen e7b927bdef Update keepalived.mysql.note.conf 2023-11-16 20:26:45 +08:00
Mr Chen 9c818b0a5d Update keepalived.conf 2023-11-16 20:03:23 +08:00
Mr Chen 8faf553e1d Update chk.sh 2023-11-16 19:55:18 +08:00
Mr Chen e22f296e38 Update chk.sh 2023-11-16 19:45:43 +08:00
Mr Chen b3deeb5a39 Update config_api.py 2023-11-16 19:39:24 +08:00
Mr Chen 2ddb4e9ef8 Update chk.sh 2023-11-16 19:34:58 +08:00
Mr Chen 74b1d424b9 Update chk_mysql.sh 2023-11-16 19:34:32 +08:00
Mr Chen cd13d0bbe7 update 2023-11-16 19:30:43 +08:00
Mr Chen 5dc97276c1 keepalived 脚本模板 2023-11-16 19:16:14 +08:00
Mr Chen 9da7f04379 Update keepalived.mysql.conf 2023-11-16 18:03:09 +08:00
Mr Chen 0bee208795 update 2023-11-16 18:02:34 +08:00
Mr Chen af660daa30 update 2023-11-16 18:00:53 +08:00
Mr Chen 71a2b43c06 Update mw.tpl 2023-11-16 17:49:21 +08:00
Mr Chen ad644c3cf9 Update chk_mysql.sh 2023-11-16 17:19:35 +08:00
Mr Chen e676790250 update 2023-11-16 17:11:49 +08:00
Mr Chen 135b307a98 update 2023-11-16 16:11:17 +08:00
Mr Chen c95c760aef Update index.py 2023-11-16 16:06:15 +08:00
Mr Chen 60125e6bbb Update keepalived.mysql.note.conf 2023-11-16 16:03:30 +08:00
Mr Chen fbef641839 update 2023-11-16 15:29:21 +08:00
Mr Chen 37431a76b6 update 2023-11-16 03:07:51 +08:00
Mr Chen 49cfeb7a39 mysql config 2023-11-16 00:34:03 +08:00
Mr Chen faf433b77d Update install.sh 2023-11-15 19:58:21 +08:00
Mr Chen d0b70841c2 Update install.sh 2023-11-15 19:58:03 +08:00
Mr Chen bf8a820343 Update install.sh 2023-11-15 19:21:27 +08:00
Mr Chen ae1e2cd972 php-fpm状态展示说明 2023-11-15 16:44:20 +08:00
Mr Chen 46da6c0dd0 php性能调整优化 2023-11-14 01:52:02 +08:00
Mr Chen 1e827944ab update 2023-11-14 01:41:51 +08:00
Mr Chen 09bbd5280d update 2023-11-12 13:15:23 +08:00
Mr Chen 01a887efad sync_binlog
默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。

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

需要带上参数post=1来强制使用post
2023-10-14 00:24:11 +08:00
midoks aceb26e309 Update README.md 2023-10-13 21:32:28 +08:00
midoks 1d078a63ca Update index.py 2023-10-13 16:37:23 +08:00
midoks f0ba3d58d6 Update redis.js 2023-10-13 00:52:49 +08:00
midoks 14f2fad644 Update redis.js 2023-10-12 19:43:40 +08:00
midoks 58f0cd69b7 Update files_api.py 2023-10-12 01:47:21 +08:00
midoks 9326138c6e Update files_api.py 2023-10-12 01:46:55 +08:00
midoks ceffb49d61 Update files_api.py 2023-10-12 01:46:32 +08:00
midoks a4e2b2d8b4 Update files_api.py 2023-10-12 01:46:01 +08:00
midoks 1ba42fdc4b Update site_api.py 2023-10-12 01:44:00 +08:00
midoks b0ab2e28cb Update site_api.py 2023-10-12 01:43:09 +08:00
midoks 2471784d1f Update waf_common.lua 2023-10-11 14:48:22 +08:00
Mr Chen 78049fa34f Merge pull request #477 from midoks/dev
php安装的下载文件,md5校验
2023-10-11 02:37:40 +08:00
midoks 09c25924fe php安装的下载文件,md5校验 2023-10-11 02:36:03 +08:00
midoks e8e2487f27 Update install.sh 2023-10-11 02:16:27 +08:00
midoks cf930aeca1 Merge branch 'master' into dev 2023-10-10 23:34:39 +08:00
midoks e6d380c321 Merge branch 'master' into dev 2023-10-10 23:34:11 +08:00
Mr Chen 065b6430f2 Merge pull request #475 from 0honus0/master
修改flask版本过高造成的启动失败
2023-10-10 23:32:44 +08:00
Mr Chen e1c03474eb Merge branch 'master' into master 2023-10-10 23:32:36 +08:00
Mr Chen 3aef5f7bbf Merge pull request #476 from midoks/dev
解决python flask 最新版本影响大部分安装
2023-10-10 23:31:15 +08:00
midoks cebeb7fe90 Update requirements.txt 2023-10-10 23:28:38 +08:00
midoks c5d8166a2a Update mw.tpl 2023-10-10 23:22:46 +08:00
midoks ff30de33ab Update cmd.md 2023-10-10 23:22:02 +08:00
midoks 7700eb92ec Update mw.tpl 2023-10-10 23:21:09 +08:00
midoks 0c8f84e81f Update requirements.txt 2023-10-10 23:18:45 +08:00
midoks 245d026726 Update README.md 2023-10-10 23:13:13 +08:00
midoks 1ac8bf51f2 Update README.md 2023-10-10 23:11:42 +08:00
midoks 248e6b1e0e update 2023-10-10 23:06:27 +08:00
midoks 6ff5d4128b Update README.md 2023-10-10 22:52:25 +08:00
0honus0 82e39f6be4 修改flask版本过高造成的启动失败 2023-10-10 22:39:32 +08:00
Mr Chen 780dfb08a3 Merge pull request #474 from midoks/dev
debian11  python3.9 flask默认安装太高问题解决。
2023-10-10 13:30:53 +08:00
midoks dd586576a7 Create r3.9.txt 2023-10-10 13:26:29 +08:00
Mr Chen c77efccd19 Merge pull request #473 from midoks/dev
mysql初始安装优化
2023-10-09 20:33:52 +08:00
midoks 962b0fa9c5 mysql 优化 2023-10-09 20:32:35 +08:00
midoks 5532dcd968 Update index.py 2023-10-09 18:43:48 +08:00
midoks ce2d060c94 Update .gitignore 2023-10-09 11:40:44 +08:00
Mr Chen 3c388ada21 Merge pull request #471 from midoks/dev
快捷命令说明
2023-10-08 02:03:11 +08:00
midoks c81ddebcd4 Update cmd.md 2023-10-08 02:02:10 +08:00
midoks 9ff01c3cfb Update cmd.md 2023-10-08 02:01:50 +08:00
midoks 6a981e1e8f Update cmd.md 2023-10-08 01:56:51 +08:00
midoks 3643d63a90 Update cmd.md 2023-10-08 01:55:41 +08:00
Mr Chen 8560880944 Merge pull request #470 from midoks/dev
Update mw.tpl
2023-10-08 01:52:55 +08:00
midoks 4210bb87a9 Update mw.tpl 2023-10-08 01:51:52 +08:00
Mr Chen 6473d68421 Merge pull request #469 from midoks/dev
增加命令 mw db 快捷登录数据库
2023-10-08 01:50:17 +08:00
midoks 009b599831 Update mw.tpl 2023-10-08 01:47:35 +08:00
midoks 1c4536980c Update mw.tpl 2023-10-08 00:48:00 +08:00
midoks 9b62a46312 update 2023-10-08 00:46:55 +08:00
midoks bb100b6bf2 Update mw.tpl 2023-10-08 00:42:54 +08:00
midoks 81fba581bd Update mw.tpl 2023-10-08 00:32:21 +08:00
midoks 36cc799c1a Update mw.tpl 2023-10-08 00:31:19 +08:00
midoks 6d64401e22 update 2023-10-08 00:30:35 +08:00
midoks 8e81f423f9 Update mw.tpl 2023-10-08 00:26:47 +08:00
midoks ea4677b2c4 update 2023-10-08 00:26:34 +08:00
midoks 774cf403f1 Update push_ad.py 2023-10-06 17:05:54 +08:00
midoks 3e3e53e58b Update mw.tpl 2023-10-04 21:34:23 +08:00
Mr Chen e0678c8b4c Merge pull request #466 from midoks/dev
gogs同步模板优化
2023-10-04 16:32:13 +08:00
midoks c0bdf2659f Update commit.tpl 2023-10-04 15:57:23 +08:00
midoks ae3cc4bd0b Update commit.tpl 2023-10-04 15:53:59 +08:00
midoks 0f8c9ee740 Update commit.tpl 2023-10-04 15:33:03 +08:00
midoks 4bc4ff5eda Update gogs.js 2023-10-04 15:31:49 +08:00
midoks 7568bd10d8 Update gogs.js 2023-10-04 15:16:38 +08:00
midoks 28410d2bf5 Update gogs.js 2023-10-04 15:16:17 +08:00
midoks c56246a9d7 Update index.py 2023-10-04 15:13:17 +08:00
midoks 5770c6d3c5 Update gogs.js 2023-10-04 15:10:18 +08:00
midoks b9fed0b6e9 Update gogs.js 2023-10-04 14:55:35 +08:00
midoks 899e58500e Update gogs.js 2023-10-04 14:54:40 +08:00
Mr Chen c6a8841a91 Merge pull request #465 from midoks/dev
细节优化2
2023-10-01 23:53:31 +08:00
midoks 40e8393c43 Update mw.tpl 2023-10-01 23:52:41 +08:00
midoks ec3d29fc2b Update install.sh 2023-10-01 21:12:00 +08:00
midoks fba632c393 update 2023-10-01 20:34:27 +08:00
Mr Chen 5dec539d40 Merge pull request #464 from midoks/dev
细节优化
2023-10-01 14:33:43 +08:00
midoks 0119e72771 Update mw.tpl 2023-10-01 14:07:48 +08:00
Mr Chen c1ffb36642 Merge pull request #463 from midoks/dev
增加mosquitto插件
2023-09-30 15:22:52 +08:00
midoks 29d8779233 update
* 增加mosquitto插件。
* redis负载状态读取优化。
2023-09-30 15:21:41 +08:00
midoks 6e9a26c331 Update README.md 2023-09-30 01:39:09 +08:00
midoks e2a491ab97 Update index.py 2023-09-30 01:36:56 +08:00
midoks f1fb16366c Update php.service.tpl 2023-09-30 01:16:49 +08:00
midoks 29ffc62b7c Update index.py 2023-09-30 01:12:02 +08:00
midoks f0d8f12f89 Update README.md 2023-09-29 23:58:37 +08:00
midoks ef36d8729e Update mosquitto.tpl 2023-09-29 23:57:30 +08:00
midoks 28bf685e73 update 2023-09-29 23:45:20 +08:00
midoks 3f424668a7 Update install.sh 2023-09-29 23:39:00 +08:00
midoks dfa53c4c4c Update install.sh 2023-09-29 23:38:13 +08:00
midoks 0b712c7242 Update install.sh 2023-09-29 23:33:59 +08:00
midoks 101792a081 Update mosquitto.js 2023-09-29 23:31:25 +08:00
midoks 0055fa98fa update 2023-09-29 23:23:42 +08:00
midoks 52a8cc6946 Update mosquitto.service.tpl 2023-09-29 23:19:56 +08:00
midoks 3da1ff214f Update mosquitto.service.tpl 2023-09-29 23:16:58 +08:00
midoks ed509e2d8d Update index.py 2023-09-29 23:15:47 +08:00
midoks 5dfc0f7ebb Update index.py 2023-09-29 23:13:41 +08:00
midoks 1129d5753a update 2023-09-29 23:13:07 +08:00
midoks 0c48e0fcbb Update mosquitto.service.tpl 2023-09-29 23:11:02 +08:00
midoks 6a28e72273 Update index.py 2023-09-29 23:02:57 +08:00
midoks 82fc1a3609 Update index.py 2023-09-29 23:01:03 +08:00
midoks 73ff1c664e Update index.py 2023-09-29 22:59:39 +08:00
midoks 9093d4bc3f Update index.py 2023-09-29 22:59:03 +08:00
midoks d50936349c Update index.py 2023-09-29 22:58:20 +08:00
midoks 20d85d0bd7 Update index.py 2023-09-29 22:56:56 +08:00
midoks fc904c9a5d update 2023-09-29 22:54:14 +08:00
midoks 59e616919f mosquitto 初始化 2023-09-29 22:48:38 +08:00
midoks 3447c1e48f Update php.service.tpl 2023-09-29 21:35:31 +08:00
midoks d7c6879d2f Update php.service.tpl 2023-09-29 21:14:49 +08:00
midoks c0240836f7 Update php.service.tpl 2023-09-29 19:53:58 +08:00
midoks 99c6c26859 Update push_ad.py 2023-09-29 14:24:14 +08:00
midoks 7b0e65de42 update 2023-09-28 19:35:39 +08:00
Mr Chen 29c737121b Merge pull request #462 from midoks/dev
网站统计-其他爬虫识别优化
2023-09-27 18:41:19 +08:00
midoks 318d123015 Update webstats_common.lua 2023-09-27 18:36:24 +08:00
midoks 093f8b14f8 Update webstats_common.lua 2023-09-27 18:27:20 +08:00
midoks 2f48df6013 update 2023-09-27 15:22:44 +08:00
Mr Chen 7f42ee741c Merge pull request #461 from midoks/dev
防火墙支持tcp/udp模式
2023-09-26 22:17:36 +08:00
midoks abfb92eaa5 Update README.md 2023-09-26 22:16:32 +08:00
midoks 3f8a822d5e Update index.py 2023-09-26 21:39:32 +08:00
midoks f9bec73252 Update firewall_api.py 2023-09-26 21:35:01 +08:00
midoks a9530b0630 Update firewall_api.py 2023-09-26 21:34:38 +08:00
midoks 33fe1095d7 Update firewall_api.py 2023-09-26 21:32:17 +08:00
midoks ae5a947898 Update index.py 2023-09-26 21:27:03 +08:00
midoks b1128cbddb update 2023-09-26 21:21:42 +08:00
midoks ead8de6e0f update 2023-09-26 20:32:00 +08:00
midoks caf3924b09 Update config_api.py 2023-09-26 20:25:21 +08:00
midoks 526caf0497 Update firewall_api.py 2023-09-26 20:25:03 +08:00
midoks c20dc4af94 Update firewall.js 2023-09-26 20:20:01 +08:00
midoks be500c898e Update firewall_api.py 2023-09-26 20:13:28 +08:00
midoks d2ccea3520 Update firewall_api.py 2023-09-26 20:10:50 +08:00
midoks 051f992e91 Update firewall_api.py 2023-09-26 20:09:41 +08:00
midoks af6b96d18b update 2023-09-26 20:07:11 +08:00
midoks 996786a7b7 update_dev 2023-09-26 19:02:31 +08:00
midoks 42bedca172 调整 - phpMyAdmin默认端口2 2023-09-26 18:00:47 +08:00
midoks 51e3d26492 调整 - phpMyAdmin默认端口 2023-09-26 17:58:38 +08:00
midoks 5ff6ee2763 Update default.sql 2023-09-26 17:49:07 +08:00
midoks 64f0ff8ad9 Update default.sql 2023-09-26 17:39:44 +08:00
midoks 7a6f4323d2 Update default.sql 2023-09-26 17:39:17 +08:00
Mr Chen f927914ff1 Merge pull request #460 from midoks/dev
python gevent 调整
2023-09-26 15:39:01 +08:00
midoks 02ad9c95ee Update requirements.txt 2023-09-26 15:32:59 +08:00
midoks 4d9c102e8b up 2023-09-26 15:28:53 +08:00
midoks ebb53ada1d Update requirements.txt 2023-09-26 15:28:30 +08:00
Mr Chen 87f4307655 Merge pull request #458 from midoks/dev
SSH禁止密码登陆优化
2023-09-25 04:11:56 +08:00
midoks 21cf48b08b Update README.md 2023-09-25 04:11:11 +08:00
midoks dd6d9cf09a Update firewall_api.py 2023-09-25 04:07:47 +08:00
midoks e0e889bbff Update firewall_api.py 2023-09-25 04:01:31 +08:00
midoks 18b36b08a7 Update firewall_api.py 2023-09-25 03:54:37 +08:00
midoks 1389280a70 Update firewall_api.py 2023-09-25 03:54:22 +08:00
midoks 8bc9500b23 Update firewall_api.py 2023-09-25 03:52:54 +08:00
midoks 49a358ccfa Update system_api.py 2023-09-24 00:12:29 +08:00
midoks c9bf5f59f4 Update system_api.py 2023-09-24 00:11:20 +08:00
midoks 577e5f3512 Update system_api.py 2023-09-24 00:06:20 +08:00
Mr Chen 343b815823 Merge pull request #457 from midoks/dev
网站统计安装优化
2023-09-17 23:24:42 +08:00
midoks 3819e2f470 Update install.sh 2023-09-17 23:22:56 +08:00
midoks 0e5f762919 update 2023-09-15 13:28:19 +08:00
midoks e9eab63e99 update 2023-09-15 13:24:19 +08:00
midoks be43b537cc Update install.sh 2023-09-15 13:23:28 +08:00
midoks 6b85710504 Update install_dev.sh 2023-09-15 13:21:53 +08:00
Mr Chen c2d89a91ab Merge pull request #456 from midoks/dev
支持rar解压。
2023-09-15 01:08:21 +08:00
midoks 682f8309c4 支持rar解压 2023-09-15 01:07:29 +08:00
midoks 586302b575 Update config_api.py 2023-09-15 00:59:50 +08:00
midoks 4af7183dbd Update config_api.py 2023-09-15 00:43:01 +08:00
midoks a488f106ca Update files_api.py 2023-09-15 00:37:23 +08:00
midoks f05de84dc2 Update files_api.py 2023-09-15 00:13:05 +08:00
midoks fe4c95276d Update files_api.py 2023-09-15 00:08:13 +08:00
midoks abc6e8f597 支持rar 2023-09-15 00:01:37 +08:00
Mr Chen 0fc03c81db Merge pull request #455 from midoks/dev
unrar&&rar准备
2023-09-14 15:14:39 +08:00
midoks 8a6dbf22c0 加入rar,unrar 2023-09-14 14:21:31 +08:00
midoks 8c18023f64 update 2023-09-14 00:17:01 +08:00
midoks fd521eff3f ad 2023-09-14 00:05:29 +08:00
Mr Chen 55f8e3fd72 Merge pull request #454 from midoks/dev
延长检查时间
2023-09-13 23:18:12 +08:00
midoks 1a26224b6f 延长检查时间 2023-09-13 23:17:16 +08:00
Mr Chen f9ab290d07 Merge pull request #453 from midoks/dev
php83显示&&redis安装优化
2023-09-12 17:22:16 +08:00
midoks 70a30412a5 Update install.sh 2023-09-12 17:00:11 +08:00
midoks ed63341750 Update site_api.py 2023-09-12 16:52:10 +08:00
midoks 81fea53bc7 Update push_notice_msg.py 2023-09-12 16:12:46 +08:00
Mr Chen eab194f5d1 Merge pull request #452 from midoks/dev
update
2023-09-11 13:12:42 +08:00
midoks 0b5299dbe0 update 2023-09-11 13:12:08 +08:00
Mr Chen e5f399e700 Merge pull request #451 from midoks/dev
安装时默认监控开启2
2023-09-11 12:43:57 +08:00
midoks f7ee3a9aed Update common.py 2023-09-11 12:42:27 +08:00
midoks aa60d52662 Update __init__.py 2023-09-11 12:39:16 +08:00
Mr Chen 9249ed7896 Merge pull request #450 from midoks/dev
安装时默认监控开启
2023-09-11 12:25:09 +08:00
midoks a470b3c53c Update common.py 2023-09-11 12:24:27 +08:00
midoks 0851e95fb2 Update common.py 2023-09-11 12:17:08 +08:00
Mr Chen b6f7334f5e Merge pull request #449 from midoks/dev
0.16.1
2023-09-11 11:52:37 +08:00
midoks 27b77f8570 Update push_notice_msg.py 2023-09-10 23:18:13 +08:00
midoks 3d888961bc Update zip.sh 2023-09-10 22:02:43 +08:00
midoks 5edc4fb713 Update install.sh 2023-09-10 21:33:37 +08:00
midoks 214954b298 Update install.sh 2023-09-10 21:29:29 +08:00
midoks 13b0b2752e Update info.json 2023-09-10 21:23:27 +08:00
midoks a2918e651f Update common.py 2023-09-10 14:26:00 +08:00
midoks 55dd1d7d5a update 2023-09-10 14:06:41 +08:00
midoks df50eceeed update 2023-09-10 14:06:19 +08:00
midoks e1de6dd514 Update install_dev.sh 2023-09-10 14:04:13 +08:00
midoks 08328bbb86 Update install_dev.sh 2023-09-10 14:03:53 +08:00
midoks 6abc5b365b Update README.md 2023-09-10 12:37:34 +08:00
midoks 6cc1279729 update 2023-09-10 12:36:23 +08:00
midoks aeafaa2832 update 2023-09-10 12:25:51 +08:00
midoks e74a511763 Update euler.sh 2023-09-10 12:25:01 +08:00
midoks f86159eeac Update README.md 2023-09-10 12:20:02 +08:00
midoks 8097164475 支持华为欧拉系统 2023-09-10 12:19:14 +08:00
midoks 4ebb44e4c0 Update info.json 2023-09-09 22:32:52 +08:00
midoks 584f93461a update 2023-09-09 12:13:16 +08:00
midoks e21f0a53e5 Update update_dev.sh 2023-09-09 11:57:34 +08:00
midoks 1d31a0eae0 Update update.sh 2023-09-09 11:57:15 +08:00
midoks ded33ed6b4 update 2023-09-09 11:55:40 +08:00
midoks b703758d0e update 2023-09-09 11:37:18 +08:00
midoks 33493ac03c up 2023-09-09 11:35:08 +08:00
midoks 74e63c5bbd Update install.sh 2023-09-09 11:33:38 +08:00
midoks f2d34e5551 Update lib.sh 2023-09-09 11:32:02 +08:00
midoks 89c529f44c Update install_dev.sh 2023-09-09 11:28:53 +08:00
midoks 56b728601b MySQL/MYSQL-YUM/MySQL-APT添加重置master功能。
mysql主从同步数据过期时,可使用此命令
2023-09-07 21:17:56 +08:00
midoks bf1d2daeaa Update push_notice_msg.py 2023-09-07 20:37:46 +08:00
midoks cac45b3732 update 2023-09-07 13:36:54 +08:00
midoks ee498b7094 Update install.sh 2023-09-07 13:04:30 +08:00
midoks 385113fe4d Update push_notice_msg.py 2023-09-07 12:58:53 +08:00
midoks 5dbfc5bd51 Update README.md 2023-09-06 19:34:09 +08:00
midoks b76e0f606a Update install.sh 2023-09-06 19:24:25 +08:00
midoks 047702f26d Update debian.sh 2023-09-06 17:48:40 +08:00
midoks eb219caada Update config_api.py 2023-09-04 18:45:49 +08:00
midoks 78b2046f19 Update README.md 2023-09-04 18:45:10 +08:00
Mr Chen 5fe85730e6 Merge pull request #447 from midoks/dev
0.16.1-提前版,合并不release.
2023-09-04 18:44:41 +08:00
midoks adb72ef33b Update config_api.py 2023-09-04 18:40:39 +08:00
midoks d9c8a46031 Update install.sh 2023-09-04 18:35:12 +08:00
midoks 24f520bdc9 Update install.sh 2023-09-04 18:30:40 +08:00
midoks 7492756997 Update install.sh 2023-09-04 18:23:08 +08:00
midoks 616af16635 Update install.sh 2023-09-04 18:15:53 +08:00
midoks 916d39e205 Update install.sh 2023-09-04 18:15:21 +08:00
midoks 017958b6b0 Update install.sh 2023-09-04 18:07:52 +08:00
midoks d403c4c4ad Update opensuse.sh 2023-09-04 17:43:28 +08:00
midoks 9f1481db07 Update mw_api.py 2023-09-04 13:16:42 +08:00
midoks 47e0ec5fae update 2023-09-04 13:14:08 +08:00
midoks a2377d960e 给防盗链增加禁止空来源 2023-09-04 12:47:12 +08:00
midoks 60f1ce2575 update 2023-09-03 00:16:01 +08:00
midoks 0e368f7157 Update index.py 2023-09-03 00:01:20 +08:00
midoks 3cf5c5b190 Update gdriveclient.py 2023-09-02 23:45:33 +08:00
midoks 4ed07beca3 Update gdriveclient.py 2023-09-02 23:43:30 +08:00
midoks cee9619883 update 2023-09-02 23:30:02 +08:00
midoks 5db4a96fc9 Update install.sh 2023-09-02 23:17:38 +08:00
midoks 2e6b7bf5cd Update install.sh 2023-09-02 23:15:52 +08:00
midoks f404caa763 Update install.sh 2023-09-02 22:59:37 +08:00
midoks 062a518492 gdrive云备份开始测试 2023-09-02 22:47:01 +08:00
midoks 0310cab3ae Update msonedrive.js 2023-09-02 21:06:30 +08:00
midoks 4a0b8df57f Update index.html 2023-09-01 16:28:44 +08:00
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
393 changed files with 25186 additions and 2438 deletions
+3 -4
View File
@@ -110,7 +110,6 @@ tmp/*
*.zip
logs/*
data/*.db
data/control.conf
data/iplist.txt
data/json/index.json
data/json/config.json
@@ -159,11 +158,11 @@ data/unauthorized_status.pl
plugins/vip_*
plugins/own_*
plugins/my_*
plugins/op_auth
plugins/l2tp
plugins/openlitespeed
plugins/tamper_proof
plugins/cryptocurrency_trade
plugins/gdrive
plugins/mtproxy
plugins/zimg
plugins/bk_demo
@@ -177,5 +176,5 @@ debug.out
mdioks.session-journal
*.session
mdioks.session-journal
*.session
+25 -9
View File
@@ -10,7 +10,7 @@
简单的Linux面板,感谢BT.CN写出如此好的web管理软件。我一看到,就知道这是我一直想要的页面化管理方式。
复制了后台管理界面,按照自己想要的方式写了一版。
![EulerOS](https://img.shields.io/badge/LINUX-EulerOS-blue?style=for-the-badge&logo=EulerOS)
![Debian](https://img.shields.io/badge/LINUX-Debian-blue?style=for-the-badge&logo=Debian)
![Ubuntu](https://img.shields.io/badge/LINUX-Ubuntu-blue?style=for-the-badge&logo=Ubuntu)
![Fedora](https://img.shields.io/badge/LINUX-Fedora-blue?style=for-the-badge&logo=Fedora)
@@ -66,6 +66,10 @@ Talk is cheap, show me the code. -- linus
- 插件地址 - https://github.com/mw-plugin
- 开发文档 - https://github.com/midoks/mdserver-web/wiki/插件开发
## 其他插件
- OP鉴权 - https://github.com/mw-plugin/op_auth
# Note
@@ -77,6 +81,13 @@ PHP[53-72]支持phpMyAdmin[4.4.15]
PHP[72-82]支持phpMyAdmin[5.2.0]
```
# 郑重声明
不卖、不会监控(统计使用除外)、更不会注入病毒,大家使用方便(望大家不吝捐赠)。
- https://www.youtube.com/watch?v=2taa5K-Jmmw
# 特别赞助
- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.pw/)
@@ -99,15 +110,18 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.15.2
### 版本更新 0.16.2
* OpenResty升级到1.21.4.2
* 计划任务自动脚本运行时间
* rsyncd添加优化
* 使用mariadb二进制导入备份文件
* docker插件-镜像导入导出功能
* 网站设置反向代理升级功能
* 优化初始化安装SSH端口识别
* keepalived插件改造,集成mysql高可用配置。
* redis(主从/集群)配置识别。
* MySQL主从同步1236错误,添加修复功能。
* MySQL二进制日志查看。
* 源码安装成功后删除解压包,节省体积。
* 网站统计-增加查询条件。
* php增加yaml扩展。
* php扩展ioncube修复。
* php-fpm增加【按需】配置。
* gitea/gogs同步功能改造。
### JSDelivr安装地址
@@ -166,6 +180,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
+17 -8
View File
@@ -123,6 +123,11 @@ class cert_api:
return True
def createCertCron(self):
if mw.isAppleSystem():
print('在Macos上不支持创建证书自动续签任务!')
return ''
# 创建证书自动续签任务
try:
import crontab_api
@@ -1496,8 +1501,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 +1520,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 +1533,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
View File
@@ -149,6 +149,7 @@ def initUserInfo():
data = mw.M('users').where('id=?', (1,)).getField('password')
if data == '21232f297a57a5a743894a0e4a801fc3':
pwd = mw.getRandomString(8).lower()
file_pw = mw.getRunDir() + '/data/default.pl'
mw.writeFile(file_pw, pwd)
+1 -1
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api:
__version = '0.15.3'
__version = '0.16.2'
__api_addr = 'data/api.json'
def __init__(self):
+12 -7
View File
@@ -283,6 +283,9 @@ class crontab_api:
return mw.returnJson(is_check_pass, msg)
addData = self.add(params)
if type(addData) == str:
return addData
if addData > 0:
return mw.returnJson(True, '添加成功')
return mw.returnJson(False, '添加失败')
@@ -602,20 +605,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:
+63 -11
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):
@@ -82,6 +87,12 @@ class files_api:
path = request.form.get('path', '')
return self.unzip(sfile, dfile, stype, path)
def uncompressApi(self):
sfile = request.form.get('sfile', '')
dfile = request.form.get('dfile', '')
path = request.form.get('path', '')
return self.uncompress(sfile, dfile, path)
# 移动文件或目录
def mvFileApi(self):
sfile = request.form.get('sfile', '')
@@ -708,10 +719,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):
@@ -799,7 +807,7 @@ class files_api:
if path.find("web_conf") > 0:
mw.restartWeb()
mw.writeLog('文件管理', '文件保存成功', (path,))
mw.writeLog('文件管理', '文件[{1}]保存成功', (path,))
return mw.returnJson(True, '文件保存成功')
except Exception as ex:
return mw.returnJson(False, '文件保存错误:' + str(ex))
@@ -823,15 +831,59 @@ class files_api:
mw.execShell("cd '" + path + "' && tar -zcvf '" +
dfile + "' " + sfiles + " > " + tmps + " 2>&1")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件压缩成功!', (sfile, dfile))
mw.writeLog("文件管理", '文件[{1}]压缩[{2}]成功!', (sfile, dfile))
return mw.returnJson(True, '文件压缩成功!')
except:
return mw.returnJson(False, '文件压缩失败!')
def unzip(self, sfile, dfile, stype, path):
def uncompress(self, sfile, dfile, path):
if not os.path.exists(sfile):
return mw.returnMsg(False, '指定文件不存在!')
return mw.returnJson(False, '指定文件不存在!')
filename = os.path.basename(sfile)
extension = os.path.splitext(filename)[-1]
extension = extension.strip('.')
tar_gz = 'tar.gz'
tar_gz_len = len(tar_gz)
suffix_gz = sfile[-tar_gz_len:]
if suffix_gz == tar_gz:
extension = suffix_gz
if not extension in ['tar.gz', 'gz', 'zip', 'rar']:
return mw.returnJson(False, '现在仅支持gz,zip,rar格式解压!')
if mw.isAppleSystem() and extension == 'rar':
return mw.returnJson(False, 'macosx暂时不支持rar格式解压')
try:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
if extension == 'zip':
cmd = "cd " + path + " && unzip -o -d '" + dfile + \
"' '" + sfile + "' > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if extension == 'tar.gz':
cmd = "cd " + path + " && tar -zxvf " + sfile + \
" -C " + dfile + " > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if extension == 'gz':
cmd = "cd " + path + " && gunzip -k " + sfile + " > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if extension == 'rar':
cmd = "cd " + path + " && unrar x " + sfile + \
" " + dfile + " > " + tmps + " 2>&1 &"
mw.execShell(cmd)
if os.path.exists(dfile):
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件[{1}]解压[{2}]成功!', (sfile, dfile))
return mw.returnJson(True, '文件解压成功!')
except Exception as e:
return mw.returnJson(False, '文件解压失败!:' + str(e))
def unzip(self, sfile, dfile, stype, path):
if not os.path.exists(sfile):
return mw.returnJson(False, '指定文件不存在!')
try:
tmps = mw.getRunDir() + '/tmp/panelExec.log'
@@ -848,7 +900,7 @@ class files_api:
" -C " + dfile + " > " + tmps + " 2>&1 &")
self.setFileAccept(dfile)
mw.writeLog("文件管理", '文件解压成功!', (sfile, dfile))
mw.writeLog("文件管理", '文件[{1}]解压[{2}]成功!', (sfile, dfile))
return mw.returnJson(True, '文件解压成功!')
except:
return mw.returnJson(False, '文件解压失败!')
+98 -70
View File
@@ -84,12 +84,13 @@ class firewall_api:
port = request.form.get('port', '').strip()
ps = request.form.get('ps', '').strip()
stype = request.form.get('type', '').strip()
protocol = request.form.get('protocol', '').strip()
data = self.addAcceptPortArgs(port, ps, stype)
data = self.addAcceptPortArgs(port, ps, stype, protocol)
return mw.getJson(data)
# 添加放行端口
def addAcceptPortArgs(self, port, ps, stype):
def addAcceptPortArgs(self, port, ps, stype, protocol='tcp'):
import re
import time
@@ -103,12 +104,13 @@ class firewall_api:
if mw.M('firewall').where("port=?", (port,)).count() > 0:
return mw.returnData(False, '您要放行的端口已存在,无需重复放行!')
msg = mw.getInfo('放行端口[{1}]成功', (port,))
msg = mw.getInfo('放行端口[{1}][{2}]成功', (port, protocol,))
mw.writeLog("防火墙管理", msg)
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
mw.M('firewall').add('port,ps,addtime', (port, ps, addtime))
mw.M('firewall').add('port,protocol,ps,addtime',
(port, protocol, ps, addtime))
self.addAcceptPort(port)
self.addAcceptPort(port, protocol)
self.firewallReload()
return mw.returnData(True, '添加放行(' + port + ')端口成功!')
@@ -139,32 +141,64 @@ class firewall_api:
self.firewallReload()
return mw.returnJson(True, '删除成功!')
# 删除放行端口
def delAcceptPortApi(self):
port = request.form.get('port', '').strip()
sid = request.form.get('id', '').strip()
mw_port = mw.readFile('data/port.pl')
try:
if(port == mw_port):
return mw.returnJson(False, '失败,不能删除当前面板端口!')
if self.__isUfw:
def delAcceptPortArgs(self, port, protocol='tcp'):
if self.__isUfw:
if protocol == 'tcp':
mw.execShell('ufw delete allow ' + port + '/tcp')
elif self.__isFirewalld:
port = port.replace(':', '-')
if protocol == 'udp':
mw.execShell('ufw delete allow ' + port + '/udp')
if protocol == 'tcp/udp':
mw.execShell('ufw delete allow ' + port + '/tcp')
mw.execShell('ufw delete allow ' + port + '/udp')
elif self.__isFirewalld:
port = port.replace(':', '-')
if protocol == 'tcp':
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
if protocol == 'udp':
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
if protocol == 'tcp/udp':
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
elif self.__isIptables:
elif self.__isIptables:
if protocol == 'tcp':
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
else:
pass
msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
mw.writeLog("防火墙管理", msg)
if protocol == 'udp':
mw.execShell(
'iptables -D INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT')
if protocol == 'tcp/udp':
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
mw.execShell(
'iptables -D INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT')
else:
pass
mw.M('firewall').where("port=?", (port,)).delete()
msg = mw.getInfo('删除防火墙放行端口[{1}][{2}]成功!', (port, protocol,))
mw.writeLog("防火墙管理", msg)
self.firewallReload()
return True
# 删除放行端口
def delAcceptPortApi(self):
port = request.form.get('port', '').strip()
protocol = request.form.get('protocol', 'tcp').strip()
sid = request.form.get('id', '').strip()
mw_port = mw.readFile('data/port.pl')
if(port == mw_port):
return mw.returnJson(False, '失败,不能删除当前面板端口!')
try:
self.delAcceptPortArgs(port, protocol)
mw.M('firewall').where("id=?", (sid,)).delete()
self.firewallReload()
return mw.returnJson(True, '删除成功!')
except Exception as e:
return mw.returnJson(False, '删除失败!:' + str(e))
@@ -178,12 +212,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 = {}
@@ -220,16 +248,13 @@ class firewall_api:
data['pass_prohibit_status'] = False
# 密码登陆配置检查
pass_rep = "#PasswordAuthentication\s+(\w*)\s*\n"
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if pass_status:
data['pass_prohibit_status'] = True
if not data['pass_prohibit_status']:
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if pass_status and pass_status.groups(0)[0].strip() == 'no':
data['pass_prohibit_status'] = True
else:
data['pass_prohibit_status'] = True
data['port'] = port
data['status'] = status
@@ -305,11 +330,17 @@ class firewall_api:
conf = mw.readFile(file)
if status == '1':
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if not pass_status:
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication yes\n", conf)
if status == '1':
rep = "PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication yes\n", conf)
else:
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
rep = "PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication no\n", conf)
mw.writeFile(file, conf)
mw.execShell("systemctl restart sshd.service")
@@ -389,18 +420,13 @@ 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):
start = (page - 1) * limit
_list = mw.M('firewall').field('id,port,ps,addtime').limit(
_list = mw.M('firewall').field('id,port,protocol,ps,addtime').limit(
str(start) + ',' + str(limit)).order('id desc').select()
data = {}
data['data'] = _list
@@ -414,38 +440,40 @@ 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):
def addAcceptPort(self, port, protocol='tcp'):
if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp')
if protocol == 'tcp':
mw.execShell('ufw allow ' + port + '/tcp')
if protocol == 'udp':
mw.execShell('ufw allow ' + port + '/udp')
if protocol == 'tcp/udp':
mw.execShell('ufw allow ' + port + '/tcp')
mw.execShell('ufw allow ' + port + '/udp')
elif self.__isFirewalld:
port = port.replace(':', '-')
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
if protocol == 'tcp':
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
if protocol == 'udp':
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/udp'
mw.execShell(cmd)
if protocol == 'tcp/udp':
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/udp'
mw.execShell(cmd)
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
if protocol == 'tcp':
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
if protocol == 'udp':
cmd = 'iptables -I INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
if protocol == 'tcp/udp':
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
cmd = 'iptables -I INPUT -p udp -m state --state NEW -m udp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
else:
pass
return True
+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)
+19 -10
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'
@@ -424,13 +425,13 @@ def getFileMd5(filename):
def getRandomString(length):
# 取随机字符串
str = ''
rnd_str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
chrlen = len(chars) - 1
random = Random()
for i in range(length):
str += chars[random.randint(0, chrlen)]
return str
rnd_str += chars[random.randint(0, chrlen)]
return rnd_str
def getUniqueId():
@@ -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")
+51 -20
View File
@@ -52,6 +52,7 @@ class plugins_api:
__plugin_dir = 'plugins'
__type = 'data/json/type.json'
__index = 'data/json/index.json'
__index_data = None
setupPath = None
def __init__(self):
@@ -60,6 +61,14 @@ class plugins_api:
self.__type = mw.getRunDir() + '/data/json/type.json'
self.__index = mw.getRunDir() + '/data/json/index.json'
self.initIndexData()
def initIndexData(self):
if not os.path.exists(self.__index):
mw.writeFile(self.__index, '[]')
self.__index_data = json.loads(mw.readFile(self.__index))
##### ----- start ----- ###
def listApi(self):
sType = request.args.get('type', '0')
@@ -615,20 +624,37 @@ class plugins_api:
return plugins_info
def checkDisplayIndex(self, name, version):
if not os.path.exists(self.__index):
mw.writeFile(self.__index, '[]')
def checkIndexList(self, name, version):
indexList = self.__index_data
for i in indexList:
nv = i.split('-')
if nv[0] == name:
return True
return False
indexList = json.loads(mw.readFile(self.__index))
if type(version) == list:
for index in range(len(version)):
vname = name + '-' + version[index]
def checkDisplayIndex(self, name, version, coexist):
# if not os.path.exists(self.__index):
# mw.writeFile(self.__index, '[]')
# indexList = json.loads(mw.readFile(self.__index))
indexList = self.__index_data
if coexist:
if type(version) == list:
for index in range(len(version)):
vname = name + '-' + version[index]
if vname in indexList:
return True
else:
vname = name + '-' + version
if vname in indexList:
return True
else:
vname = name + '-' + version
if vname in indexList:
return True
if type(version) == list:
for index in range(len(version)):
return self.checkIndexList(name, version)
else:
return self.checkIndexList(name, version)
return False
def getVersion(self, path):
@@ -695,7 +721,7 @@ class plugins_api:
pInfo['task'] = self.checkSetupTask(
pInfo['name'], info['versions'], coexist)
pInfo['display'] = self.checkDisplayIndex(
info['name'], pInfo['versions'])
info['name'], pInfo['versions'], coexist)
pInfo['setup'] = os.path.exists(pInfo['install_checks'])
@@ -800,10 +826,10 @@ class plugins_api:
continue
path = self.__plugin_dir + '/' + dirinfo
if os.path.isdir(path):
json_file = path + '/info.json'
if os.path.exists(json_file):
info_file = path + '/info.json'
if os.path.exists(info_file):
try:
data = json.loads(mw.readFile(json_file))
data = json.loads(mw.readFile(info_file))
# 判断是否搜索
if kw != '' and not self.searchKey(data, kw):
continue
@@ -976,19 +1002,24 @@ class plugins_api:
plugin_name = '-'.join(tmpArr)
plugin_ver = tmp[tmp_len - 1]
json_file = self.__plugin_dir + '/' + plugin_name + '/info.json'
if os.path.exists(json_file):
content = mw.readFile(json_file)
read_json_file = self.__plugin_dir + '/' + plugin_name + '/info.json'
if os.path.exists(read_json_file):
content = mw.readFile(read_json_file)
try:
data = json.loads(content)
data = self.makeList(data)
for index in range(len(data)):
if data[index]['versions'] == plugin_ver or plugin_ver in data[index]['versions']:
if data[index]['coexist']:
if data[index]['versions'] == plugin_ver or plugin_ver in data[index]['versions']:
data[index]['display'] = True
plist.append(data[index])
continue
else:
data[index]['display'] = True
plist.append(data[index])
continue
except Exception as e:
print('getIndexList:', e)
print('getIndexList:', mw.getTracebackInfo())
# 使用gevent模式时,无法使用多进程
# plist = self.checkStatusMProcess(plist)
+38 -10
View File
@@ -1149,8 +1149,9 @@ class site_api:
domains = request.form.get('domains', '')
status = request.form.get('status', '')
name = request.form.get('name', '')
none = request.form.get('none', '')
sid = request.form.get('id', '')
return self.setSecurity(sid, name, fix, domains, status)
return self.setSecurity(sid, name, fix, domains, status, none)
def getLogsApi(self):
siteName = request.form.get('siteName', '')
@@ -2430,9 +2431,28 @@ location ^~ {from} {\n\
tmp = re.search(rep, conf).group()
data['fix'] = re.search(
"\(.+\)\$", tmp).group().replace('(', '').replace(')$', '').replace('|', ',')
data['domains'] = ','.join(re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp).groups()[0].split())
data['status'] = True
data['status'] = False
data['none'] = False
valid_referers = re.search(
"valid_referers\s+(.+);\n", tmp)
valid_referers_none = re.search(
"valid_referers\s+none\s+blocked\s+(.+);\n", tmp)
if valid_referers or valid_referers_none:
data['status'] = True
if valid_referers_none:
domain_t = valid_referers_none.groups()[0].split()
data['domains'] = ','.join(domain_t)
data['none'] = True
elif valid_referers:
domain_t = valid_referers.groups()[0].split()
data['domains'] = ','.join(domain_t)
data['none'] = False
# print(data)
else:
data['fix'] = 'jpg,jpeg,gif,png,js,css'
domains = mw.M('domain').where(
@@ -2442,19 +2462,27 @@ location ^~ {from} {\n\
tmp.append(domain['name'])
data['domains'] = ','.join(tmp)
data['status'] = False
data['none'] = False
return mw.getJson(data)
def setSecurity(self, sid, name, fix, domains, status):
def setSecurity(self, sid, name, fix, domains, status, none=''):
if len(fix) < 2:
return mw.returnJson(False, 'URL后缀不能为空!')
file = self.getHostConf(name)
if os.path.exists(file):
conf = mw.readFile(file)
if conf.find('SECURITY-START') != -1:
if status == 'false':
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
mw.writeLog('网站管理', '站点[' + name + ']已关闭防盗链设置!')
else:
rep = "\s{0,4}#SECURITY-START(\n|.){1,500}#SECURITY-END\n?"
conf = re.sub(rep, '', conf)
valid_referers = domains.strip().replace(',', ' ')
if none == 'true':
valid_referers = 'none blocked ' + valid_referers
pre_path = self.setupPath + "/php/conf"
re_path = "include\s+" + pre_path + "/enable-php-"
rconf = '''#SECURITY-START 防盗链配置
@@ -2462,13 +2490,13 @@ location ^~ {from} {\n\
{
expires 30d;
access_log /dev/null;
valid_referers none blocked %s;
valid_referers %s;
if ($invalid_referer){
return 404;
}
}
#SECURITY-END
include %s/enable-php-''' % (fix.strip().replace(',', '|'), domains.strip().replace(',', ' '), pre_path)
include %s/enable-php-''' % (fix.strip().replace(',', '|'), valid_referers, pre_path)
conf = re.sub(re_path, rconf, conf)
mw.writeLog('网站管理', '站点[' + name + ']已开启防盗链!')
mw.writeFile(file, conf)
@@ -2477,7 +2505,7 @@ location ^~ {from} {\n\
def getPhpVersion(self):
phpVersions = ('00', '52', '53', '54', '55',
'56', '70', '71', '72', '73', '74', '80', '81', '82')
'56', '70', '71', '72', '73', '74', '80', '81', '82', '83')
data = []
for val in phpVersions:
tmp = {}
@@ -2760,7 +2788,7 @@ location ^~ {from} {\n\
self.saveCert(keyPath, certPath)
msg = mw.getInfo('网站[{1}]开启SSL成功!', siteName)
msg = mw.getInfo('网站[{1}]开启SSL成功!', (siteName,))
mw.writeLog('网站管理', msg)
mw.restartWeb()
+38 -5
View File
@@ -273,27 +273,60 @@ class system_api:
title = mw.readFile(titlePl).strip()
return title
def getSystemDeviceTemperature(self):
if not hasattr(psutil, "sensors_temperatures"):
return False, "platform not supported"
temps = psutil.sensors_temperatures()
if not temps:
return False, "can't read any temperature"
for name, entries in temps.items():
for entry in entries:
return True, entry.label
# print("%-20s %s °C (high = %s °C, critical = %s °C)" % (
# entry.label or name, entry.current, entry.high,
# entry.critical))
return False, ""
def getSystemVersion(self):
#
# 取操作系统版本
if mw.getOs() == 'darwin':
current_os = mw.getOs()
# sys_temper = self.getSystemDeviceTemperature()
# print(sys_temper)
# mac
if current_os == 'darwin':
data = mw.execShell('sw_vers')[0]
data_list = data.strip().split("\n")
mac_version = ''
for x in data_list:
mac_version += x.split("\t")[1] + ' '
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 +351,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)
+9 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
DIR=$(cd "$(dirname "$0")"; pwd)
MDIR=$(dirname "$DIR")
@@ -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"
@@ -42,6 +46,10 @@ mw_start(){
mw_start_debug(){
if [ ! -f $DIR/logs/task.log ];then
echo '' > $DIR/logs/task.log
fi
python3 task.py >> $DIR/logs/task.log 2>&1 &
port=7200
if [ -f /www/server/mdserver-web/data/port.pl ];then
+10 -1
View File
@@ -4,7 +4,16 @@
- 面板相关命令
```
/etc/init.d/mw default
/etc/init.d/mw default | 显示登录信息
/etc/init.d/mw db | 快捷连接数据库
----------------------------------------
mw debug | 开发测试
mw venv | 进入虚拟环境
mw mirror | 切换镜像
mw install_app | 快捷安装常用软件
mw update | 更新到正式
mw update_dev | 更新到开发
service mw [start|stop|reload|restart|status]
```
+1
View File
@@ -0,0 +1 @@
30
+7 -5
View File
@@ -40,14 +40,16 @@ CREATE TABLE IF NOT EXISTS `crontab` (
CREATE TABLE IF NOT EXISTS `firewall` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`port` TEXT,
`protocol` TEXT DEFAULT 'tcp',
`ps` TEXT,
`addtime` TEXT
);
INSERT INTO `firewall` (`id`, `port`, `ps`, `addtime`) VALUES
(1, '80', '网站默认端口', '0000-00-00 00:00:00'),
(2, '443', 'HTTPS', '0000-00-00 00:00:00'),
(3, '888', 'phpMyAdmin默认端口', '0000-00-00 00:00:00');
ALTER TABLE `firewall` ADD COLUMN `protocol` TEXT DEFAULT 'tcp';
INSERT INTO `firewall` (`id`, `port`, `protocol`, `ps`, `addtime`) VALUES
(1, '80', 'tcp','网站默认端口', '0000-00-00 00:00:00'),
(2, '443', 'tcp', 'HTTPS', '0000-00-00 00:00:00');
@@ -55,7 +57,7 @@ CREATE TABLE IF NOT EXISTS `logs` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`type` TEXT,
`log` TEXT,
`uid` TEXT,
`uid` INTEGER DEFAULT '1',
`addtime` TEXT
);
ALTER TABLE `logs` ADD COLUMN `uid` INTEGER DEFAULT '1';
+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:
+2 -2
View File
@@ -52,8 +52,8 @@ def createBgTask():
removeBgTask()
args = {
"period": "day",
"hour": "2",
"minute": "30",
"hour": "0",
"minute": "15",
}
createBgTaskByName(getPluginName(), args)
Binary file not shown.

After

Width:  |  Height:  |  Size: 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`
+365
View File
@@ -0,0 +1,365 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import io
sys.path.append(os.getcwd() + "/class/core")
import mw
# -----------------------------
import google.oauth2.credentials
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.http import MediaFileUpload
from googleapiclient.http import MediaIoBaseDownload
class gdriveclient():
__plugin_dir = ''
__server_dir = ''
__credentials = "/root/credentials.json"
__backup_dir_name = "backup"
__creds = None
__exclude = ""
__scpos = ['https://www.googleapis.com/auth/drive.file']
_title = 'Google Drive'
_name = 'Google Drive'
__debug = False
_DEFAULT_AUTH_PROMPT_MESSAGE = (
'Please visit this URL to authorize this application: {url}')
"""str: The message to display when prompting the user for
authorization."""
_DEFAULT_AUTH_CODE_MESSAGE = (
'Enter the authorization code: ')
"""str: The message to display when prompting the user for the
authorization code. Used only by the console strategy."""
_DEFAULT_WEB_SUCCESS_MESSAGE = (
'The authentication flow has completed, you may close this window.')
def __init__(self, plugin_dir, server_dir):
self.__plugin_dir = plugin_dir
self.__server_dir = server_dir
self.set_creds()
# self.get_exclode()
def setDebug(self, d=False):
self.__debug = d
def D(self, msg=''):
if self.__debug:
print(msg)
# 检查gdrive连接
def _check_connect(self):
try:
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
results.get('files', [])
except:
return False
return True
# 设置creds
def set_creds(self):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
tmp_data = json.load(token)['credentials']
self.__creds = google.oauth2.credentials.Credentials(
tmp_data['token'],
tmp_data['refresh_token'],
tmp_data['id_token'],
tmp_data['token_uri'],
tmp_data['client_id'],
tmp_data['client_secret'],
tmp_data['scopes'])
# if not self._check_connect():
# return False
# else:
# return True
def get_sign_in_url(self):
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
self.__plugin_dir + '/credentials.json',
scopes=self.__scpos)
# flow.redirect_uri = 'https://drive.aapanel.com'
flow.redirect_uri = 'https://drive.aapanel.com'
auth_url, state = flow.authorization_url(
access_type='offline',
prompt='consent',
include_granted_scopes='false')
return auth_url, state
def set_auth_url(self, url):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
return mw.returnJson(True, "验证成功")
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
self.__plugin_dir + '/credentials.json',
scopes=self.__scpos,
state=url.split('state=')[1].split('&code=')[0])
# flow.redirect_uri = 'https://localhost'
flow.redirect_uri = 'https://drive.aapanel.com'
flow.fetch_token(authorization_response=url)
credentials = flow.credentials
credentials_data = {}
credentials_data['credentials'] = {
'token': credentials.token,
'id_token': credentials.id_token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes}
with open(token_file, 'w') as token:
json.dump(credentials_data, token)
if not self.set_creds():
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
# 获取token
def get_token(self, get):
token_file = self.__server_dir + '/token.json'
import requests
try:
respone = requests.get("https://www.google.com", timeout=2)
except:
return mw.returnJson(False, "连接谷歌失败")
if respone.status_code != 200:
return mw.returnJson(False, "连接谷歌失败")
if not self.set_creds():
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
if not os.path.exists(token_file):
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
# 获取auth_url
def get_auth_url(self, get):
self.get_sign_in_url()
if os.path.exists("/tmp/auth_url"):
return mw.readFile("/tmp/auth_url")
# 检查连接
def check_connect(self, get):
token_file = self.__server_dir + '/token.json'
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
self.set_creds()
else:
self.D("Failed to get Google token, please verify before use")
return mw.returnJson(True, "Failed to get Google token, please verify before use")
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
try:
results.get('files', [])
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
return mw.returnJson(True, "验证成功")
except:
return mw.returnJson(False, "验证失败,请根据页面1 2 3 步骤完成验证")
def _get_filename(self, filename):
l = filename.split("/")
return l[-1]
def _create_folder_cycle(self, filepath):
l = filepath.split("/")
fid_list = []
for i in l:
if not i:
continue
fid = self.__get_folder_id(i)
if fid:
fid_list.append(fid)
continue
if not fid_list:
fid_list.append("")
fid_list.append(self.create_folder(i, fid_list[-1]))
return fid_list[-1]
def build_object_name(self, data_type, file_name):
"""根据数据类型构建对象存储名称
:param data_type:
:param file_name:
:return:
"""
import re
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
if not prefix_dict.get(data_type):
print("data_type 类型错误!!!")
exit(1)
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\."
sub_search = re.search(file_regx.lower(), file_name)
sub_path_name = ""
if sub_search:
sub_path_name = sub_search.groups()[0]
sub_path_name += '/'
# 构建OS存储路径
object_name = self.__backup_dir_name + \
'/{}/{}'.format(data_type, sub_path_name)
if object_name[:1] == "/":
object_name = object_name[1:]
return object_name
# 上传文件
def upload_file(self, filename, data_type=None):
"""
get.filename 上传后的文件名
get.filepath 上传文件路径
被面板新版计划任务调用时
get表示file_name
:param get:
:return:
"""
# filename = filename
filepath = self.build_object_name(data_type, filename)
_filename = self._get_filename(filename)
self.D(filepath)
self.D(filename)
parents = self._create_folder_cycle(filepath)
self.D(parents)
drive_service = build('drive', 'v3', credentials=self.__creds)
file_metadata = {'name': _filename, 'parents': [parents]}
media = MediaFileUpload(filename, resumable=True)
file = drive_service.files().create(
body=file_metadata, media_body=media, fields='id').execute()
self.D('Upload Success ,File ID: %s' % file.get('id'))
return True
def _get_file_id(self, filename):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}'".format(
filename), fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
return []
else:
for item in items:
return item["id"]
def delete_file(self, filename=None, data_type=None):
file_id = self._get_file_id(filename)
self.delete_file_by_id(file_id)
return True
def delete_file_by_id(self, file_id):
self.D("delete id:{}".format(file_id))
try:
drive_service = build('drive', 'v3', credentials=self.__creds)
drive_service.files().delete(fileId=file_id).execute()
return True
except Exception as e:
return False
# 创建目录
def create_folder(self, folder_name, parents=""):
self.D(self.__creds)
self.D("folder_name: {}".format(folder_name))
self.D("parents: {}".format(parents))
service = build('drive', 'v3', credentials=self.__creds)
file_metadata = {
'name': folder_name,
'mimeType': 'application/vnd.google-apps.folder'
}
if parents:
file_metadata['parents'] = [parents]
folder = service.files().create(body=file_metadata, fields='id').execute()
self.D('Create Folder ID: %s' % folder.get('id'))
return folder.get('id')
def get_rootdir_id(self, folder_name='backup'):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(folder_name),
fields="nextPageToken, files(id, name,size,parents,webViewLink)").execute()
items = results.get('files', [])
if len(items) == 0:
self.create_folder(folder_name)
return self.get_rootdir_id(folder_name)
return items[0]['parents'][0]
# 获取目录id
def __get_folder_id(self, floder_name):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, q="name='{}' and mimeType='application/vnd.google-apps.folder'".format(floder_name),
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
return []
else:
for item in items:
return item["id"]
def get_res_info(self, rid):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().get(fileId='{}'.format(rid)).execute()
return results
def get_id_list(self, driveId=''):
service = build('drive', 'v3', credentials=self.__creds)
results = service.files().list(pageSize=10, driveId="{}".format(driveId),
fields="nextPageToken, files(id, name,size,parents)").execute()
items = results.get('files', [])
return items
def get_list(self, dir_id='', next_page_token=''):
if dir_id == '':
dir_id = self.get_rootdir_id(self.__backup_dir_name)
service = build('drive', 'v3', credentials=self.__creds)
cmd_query = "trashed=false and '{}' in parents".format(dir_id)
results = service.files().list(pageSize=10, q=cmd_query, orderBy='folder asc',
fields="nextPageToken, files(id, name,size,createdTime,parents,webViewLink)").execute()
items = results.get('files', [])
nextPageToken = results.get('nextPageToken', [])
# print(items)
# print(nextPageToken)
return items
def get_exclode(self, exclude=[]):
if not exclude:
tmp_exclude = os.getenv('MW_EXCLUDE')
if tmp_exclude:
exclude = tmp_exclude.split(',')
if not exclude:
return ""
for ex in exclude:
self.__exclude += " --exclude=\"" + ex + "\""
self.__exclude += " "
return self.__exclude
def download_file(self, filename):
file_id = self._get_file_id(filename)
service = build('drive', 'v3', credentials=self.__creds)
request = service.files().get_media(fileId=file_id)
with open('/tmp/{}'.format(filename), 'wb') as fh:
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print("Download %d%%." % int(status.progress() * 100))
+13
View File
@@ -0,0 +1,13 @@
{
"web": {
"client_id": "226011946234-d3e1vashgag64utjedu1ljt9u39ncrpq.apps.googleusercontent.com",
"project_id": "light-willow-341609",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "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",
"redirect_uris": [
"https://drive.aapanel.com"
]
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"web": {
"client_id": "540181629246-1horo9i4htamdbhiqar9rcbq33bqe2ob.apps.googleusercontent.com",
"project_id": "plated-inn-369901",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "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",
"redirect_uris": ["https://drive.aapanel.com"]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

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

After

Width:  |  Height:  |  Size: 562 B

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

After

Width:  |  Height:  |  Size: 2.8 KiB

+19
View File
@@ -0,0 +1,19 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('lvs');">服务</p>
<p onclick="pluginInitD('lvs');">自启动</p>
<p onclick="pluginConfig('lvs');">配置修改</p>
<!-- <p onclick="pluginLogs('lvs','','run_log',30);">运行日志</p> -->
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(480);
$.getScript( "/plugins/file?name=lvs&f=js/lvs.js", function(){
pluginService('lvs');
});
</script>
+180
View File
@@ -0,0 +1,180 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import string
import subprocess
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'lvs'
def getIpvsadm():
return 'ipvsadm'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def getConf():
path = '/etc/default/ipvsadm'
return path
def status():
data = mw.execShell("which ipvsadm")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/' + getPluginName()
# initd replace
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = contentReplace(content)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
return file_bin
def haOp(method):
return 'ok'
def start():
return haOp('start')
def stop():
return haOp('stop')
def restart():
return haOp('restart')
def reload():
return haOp('reload')
def initdStatus():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
if current_os.startswith('freebsd'):
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
mw.execShell('systemctl enable ' + getIpvsadm())
return 'ok'
def initdUinstall():
current_os = mw.getOs()
if current_os == 'darwin':
return "Apple Computer does not support"
mw.execShell('systemctl disable ' + getIpvsadm())
return 'ok'
def runLog():
path = getConf()
content = mw.readFile(path)
rep = 'log\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0]
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'conf':
print(getConf())
else:
print('error')
+18
View File
@@ -0,0 +1,18 @@
{
"sort": 7,
"ps": "[<span style='color:red;'>内网</span>]LVS超强负载均衡,通过ipvsadm管理[<span style='color:red;'>暂时不可用</span>]",
"name": "lvs",
"title": "LVS",
"shell": "install.sh",
"versions":["1.0"],
"updates":["1.0"],
"tip": "soft",
"checks": "server/lvs",
"path": "server/lvs",
"display": 1,
"author": "midoks",
"date": "2023-11-17",
"home": "http://www.linuxvirtualserver.org/",
"type": 0,
"pid": "4"
}
+83
View File
@@ -0,0 +1,83 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH=$PATH:/opt/homebrew/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
sys_os=`uname`
VERSION=1.6.22
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/lvs && bash install.sh install 1.0
# cd /www/server/mdserver-web/plugins/lvs && bash install.sh install 1.0
Install_LVS(){
mkdir -p $serverPath/source
which ipvsadm
if [ "$?" == "0" ];then
echo '已安装LVS!!'
exit 0
fi
echo '正在安装LVS...'
# 检测平台命令
which apt
if [ "$?" == "0" ];then
apt install -y ipvsadm
fi
which yum
if [ "$?" == "0" ];then
yum install -y ipvsadm
fi
which ipvsadm
if [ "$?" == "0" ];then
echo '正在安装LVS成功!'
mkdir -p $serverPath/lvs
ipv_version=`ipvsadm -v | awk '{print $2}'`
if [ "$ipv_version" != "" ];then
echo "$ipv_version" > $serverPath/lvs/version.pl
else
echo '1.0' > $serverPath/lvs/version.pl
fi
cd ${rootPath} && python3 ${rootPath}/plugins/lvs/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/lvs/index.py initd_install
else
echo '正在安装LVS失败!'
fi
}
Uninstall_LVS()
{
# 检测平台命令
which apt
if [ "$?" == "0" ];then
apt remove -y ipvsadm
fi
which yum
if [ "$?" == "0" ];then
yum uninstall -y ipvsadm
fi
echo "卸载LVS完成"
if [ -d $serverPath/lvs ];then
rm -rf $serverPath/lvs
fi
}
action=$1
if [ "${1}" == 'install' ];then
Install_LVS
else
Uninstall_LVS
fi
+53
View File
@@ -0,0 +1,53 @@
function lvsPostMin(method, args, callback){
var req_data = {};
req_data['name'] = 'lvs';
req_data['func'] = method;
if (typeof(args) != 'undefined' && args!=''){
req_data['args'] = JSON.stringify(args);
}
$.post('/plugins/run', req_data, function(data) {
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function lvsPost(method, args, callback, msg = '正在获取...'){
var loadT = layer.msg(msg, { icon: 16, time: 0, shade: 0.3 });
lvsPostMin(method,args,function(data){
layer.close(loadT);
if(typeof(callback) == 'function'){
callback(data);
}
});
}
function secToTime(s) {
var t;
if(s > -1){
var hour = Math.floor(s/3600);
var min = Math.floor(s/60) % 60;
var sec = s % 60;
if(hour < 10) {
t = '0'+ hour + ":";
} else {
t = hour + ":";
}
if(min < 10){t += "0";}
t += min + ":";
if(sec < 10){t += "0";}
t += sec.toFixed(2);
}
return t;
}
+20
View File
@@ -0,0 +1,20 @@
debian
# 查看网卡
ls /sys/class/net/
ifconfig ens256 172.16.204.100 netmask 255.255.255.255 broadcast 192.168.212.100 up
route add -host 172.16.204.100 dev ens256
ipvsadm -A -t 172.16.204.100:80 -s rr
ipvsadm -a -t 172.16.204.100:80 -r 172.16.204.129:80 -m
# 清空LVS规则
ipvsadm -C
# 查看LVS
ipvsadm -L -n
+9 -2
View File
@@ -402,6 +402,8 @@ def initMariaDbPwd():
pwd + ' -e "drop database test";'
mw.execShell(drop_test_db)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
# 删除冗余账户
hostname = mw.execShell('hostname')[0].strip()
if hostname != 'localhost':
@@ -412,8 +414,6 @@ def initMariaDbPwd():
drop_root_hostname = serverdir + '/bin/mysql --defaults-file=' + \
myconf + ' -uroot -p' + pwd + ' -e "drop user \'root\'@\'' + hostname + '\'";'
mw.execShell(drop_root_hostname)
pSqliteDb('config').where('id=?', (1,)).save('mysql_root', (pwd,))
return True
@@ -755,6 +755,11 @@ def importDbBackup():
return mw.returnJson(True, 'ok')
def rootPwd():
return pSqliteDb('config').where(
'id=?', (1,)).getField('mysql_root')
def importDbExternal():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
@@ -2740,6 +2745,8 @@ if __name__ == "__main__":
print(setMyPort())
elif func == 'init_pwd':
print(initMysqlPwd())
elif func == 'root_pwd':
print(rootPwd())
elif func == 'get_db_list':
print(getDbList())
elif func == 'set_db_backup':
+1 -1
View File
@@ -8,7 +8,7 @@
"uninstall_pre_inspection":true,
"checks": "server/mariadb",
"path": "server/mariadb",
"versions":["10.6","10.7","10.8","10.9","10.11","11.0"],
"versions":["10.6","10.7","10.8","10.9","10.11","11.0","11.1","11.2","11.3"],
"shell":"install.sh",
"checks":"server/mariadb",
"path":"server/mariadb",
+1 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
curPath=`pwd`
+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:
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -102,16 +102,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
# https://mariadb.org/download/?t=mariadb
@@ -105,16 +105,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.6' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -92,16 +92,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.7' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -92,16 +92,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.8' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+6 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -102,16 +102,17 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.9' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+8 -6
View File
@@ -1,5 +1,5 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.0.1
MY_VER=11.0.3
Install_app()
{
@@ -101,16 +101,18 @@ Install_app()
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
echo '安装完成'
else
echo '安装失败' > $install_tmp
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.1.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.2.1
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.3.0
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成'
else
echo '安装失败'
echo 'install fail'>&2
exit 1
fi
fi
if [ -d ${mariadbDir}/mariadb-${MY_VER} ];then
rm -rf ${mariadbDir}/mariadb-${MY_VER}
fi
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+49 -12
View File
@@ -31,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()
@@ -87,8 +92,10 @@ def checkArgs(data, ck=[]):
def status():
data = mw.execShell(
"ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
cmd = "ps aux|grep " + getPluginName() + " |grep -v grep | grep -v mdserver-web | awk '{print $2}'"
# print(cmd)
data = mw.execShell(cmd)
# print(data)
if data[0] == '':
return 'stop'
return 'start'
@@ -113,8 +120,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)
@@ -137,13 +144,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]
@@ -226,9 +240,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)
@@ -238,17 +258,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
@@ -5,7 +5,7 @@
"title": "Memcached",
"shell": "install.sh",
"versions":["1.6"],
"updates":["1.6.15"],
"updates":["1.6.21"],
"tip": "soft",
"checks": "server/memcached",
"path":"server/memcached",
+18 -6
View File
@@ -1,7 +1,6 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH=$PATH:/opt/homebrew/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
@@ -9,8 +8,10 @@ rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
sys_os=`uname`
VERSION=1.6.22
VERSION=1.6.15
echo $sys_os
Install_mem(){
mkdir -p $serverPath/source
@@ -23,9 +24,18 @@ Install_mem(){
cd $serverPath/source && tar -zxvf memcached.tar.gz
OPTIONS=''
if [ ${sys_os} == "Darwin" ]; then
LIB_DEPEND_DIR=`brew info libevent | grep /opt/homebrew/Cellar/libevent | cut -d \ -f 1 | awk 'END {print}'`
OPTIONS="${OPTIONS} --with-libevent=${LIB_DEPEND_DIR}"
fi
echo "./configure --prefix=${serverPath}/memcached && make && make install"
cd $serverPath/source/memcached-${VERSION} && ./configure --prefix=$serverPath/memcached && make && make install
cd $serverPath/source/memcached-${VERSION}
./configure --prefix=$serverPath/memcached \
$OPTIONS
make && make install
if [ -d $serverPath/memcached ];then
echo '1.6' > $serverPath/memcached/version.pl
@@ -33,6 +43,8 @@ Install_mem(){
cd ${rootPath} && python3 ${rootPath}/plugins/memcached/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/memcached/index.py initd_install
rm -rf $serverPath/source/memcached-${VERSION}
fi
}

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