Compare commits

..
265 Commits
Author SHA1 Message Date
Mr Chen da2d0fd2ce Merge pull request #625 from midoks/dev
Update config_api.py
2024-10-02 20:27:03 +08:00
Mr Chen 6e0d580f6b Update config_api.py 2024-10-02 20:26:36 +08:00
Mr Chen 34481c12e1 Merge pull request #624 from midoks/dev
0.17.3
2024-10-02 20:25:38 +08:00
Mr Chen bc27feab00 Update my.cnf 2024-10-02 19:17:00 +08:00
Mr Chen 1e48b32170 Update my.cnf 2024-10-02 19:13:35 +08:00
Mr Chen b9cbf63945 Update install.sh 2024-10-02 18:58:16 +08:00
Mr Chen 8437e236db update 2024-10-02 18:57:02 +08:00
Mr Chen 838043a9dd Update README.md 2024-10-02 16:20:08 +08:00
Mr Chen 8debe50f1b update 2024-10-02 16:15:19 +08:00
Mr Chen 8a97577b61 Update info.json 2024-10-02 16:09:45 +08:00
Mr Chen cb9b6b2816 Update cert_api.py 2024-10-02 16:00:47 +08:00
Mr Chen 92d5126230 Update cert_api.py 2024-10-02 15:43:40 +08:00
Mr Chen 50c6f9fce5 update 2024-10-02 15:33:23 +08:00
Mr Chen cbb1403f80 update 2024-10-02 14:25:14 +08:00
Mr Chen 21f995f8ac Update install.sh 2024-10-02 04:11:59 +08:00
Mr Chen 185e0dae22 Update README.md 2024-10-02 04:11:44 +08:00
Mr Chen e555829f1b Update install.sh 2024-10-02 04:03:39 +08:00
Mr Chen 2f50a2ffa0 update 2024-10-02 03:51:37 +08:00
Mr Chen 069ececfe1 Update install.sh 2024-10-02 03:48:23 +08:00
Mr Chen 1ea1ad5ae0 Update info.json 2024-10-02 03:37:13 +08:00
Mr Chen 3787913a12 Update index.py 2024-10-02 03:33:28 +08:00
Mr Chen 45f51954f9 update 2024-10-02 03:29:34 +08:00
Mr Chen 0c7773c6d4 Update pgadmin.js 2024-10-02 03:17:59 +08:00
Mr Chen 81e1940b8f Update pgadmin.js 2024-10-02 03:17:42 +08:00
Mr Chen 2e24a715ba Update pgadmin.js 2024-10-02 03:17:03 +08:00
Mr Chen a05be24ed1 up 2024-10-02 03:15:36 +08:00
Mr Chen f09017fe6e Update index.py 2024-10-02 02:58:12 +08:00
Mr Chen 1aedb66132 Update index.py 2024-10-02 02:17:37 +08:00
Mr Chen 2e3aef3776 Update cmd.md 2024-10-02 02:01:35 +08:00
Mr Chen 0d3cf64e9a Update cmd.md 2024-10-02 01:57:53 +08:00
Mr Chen 66220c1963 update 2024-10-02 01:56:26 +08:00
Mr Chen 1ed52a1033 Update pg_init.sh 2024-10-02 01:49:19 +08:00
Mr Chen 1a4ac13f8b Update cmd.md 2024-10-02 01:44:05 +08:00
Mr Chen e2e94015a0 Update index.py 2024-10-02 01:40:20 +08:00
Mr Chen dee7abc850 Update index.py 2024-10-02 01:40:02 +08:00
Mr Chen a1464006db Update pg_init.sh 2024-10-02 01:35:51 +08:00
Mr Chen b4c6bcec6e Update cmd.md 2024-10-02 01:28:08 +08:00
Mr Chen 1d55ef3d0a Update mw.tpl 2024-10-02 01:27:40 +08:00
Mr Chen 24dab4775c update 2024-10-02 01:26:26 +08:00
Mr Chen 7a7b77887c update 2024-10-02 00:53:31 +08:00
Mr Chen c39d21b300 update 2024-10-02 00:39:56 +08:00
Mr Chen 3f7bce197f Update index.py 2024-10-02 00:11:27 +08:00
Mr Chen e706ff17c1 Update index.py 2024-10-02 00:07:35 +08:00
Mr Chen 5a80422b77 Update config_local.py 2024-10-02 00:04:15 +08:00
Mr Chen d3fb392f28 Update config_local.py 2024-10-02 00:02:23 +08:00
Mr Chen 6817043007 Update index.py 2024-10-02 00:02:07 +08:00
Mr Chen 3106c101d8 Update index.py 2024-10-02 00:00:51 +08:00
Mr Chen e25c7f424d update 2024-10-01 23:57:54 +08:00
Mr Chen 156459b6a4 update 2024-10-01 23:49:15 +08:00
Mr Chen c73fe892b7 Update install.sh 2024-10-01 23:09:59 +08:00
Mr Chen 491ad84103 Update pgadmin.conf 2024-10-01 22:29:23 +08:00
Mr Chen cdb27c5d83 Update index.py 2024-10-01 22:18:50 +08:00
Mr Chen 7d35f9d129 Update index.py 2024-10-01 21:31:28 +08:00
Mr Chen b34d1e7caa update 2024-10-01 21:30:16 +08:00
Mr Chen 055a52da03 Update mw.tpl 2024-10-01 21:02:26 +08:00
Mr Chen 2c3746c596 Update mw.tpl 2024-10-01 20:59:30 +08:00
Mr Chen 96a0ca9b2f Update mw.tpl 2024-10-01 18:23:50 +08:00
Mr Chen 1cd436bc5d Update mw.tpl 2024-10-01 18:19:54 +08:00
Mr Chen 3834a9b0b8 update 2024-10-01 18:18:28 +08:00
Mr Chen 30454e3b4a Update index.py 2024-10-01 17:57:29 +08:00
Mr Chen 020354f5bc update 2024-10-01 17:46:49 +08:00
Mr Chen 6e5dbeda72 update 2024-10-01 17:37:39 +08:00
Mr Chen 804922a707 Update pgadmin.js 2024-10-01 17:32:01 +08:00
Mr Chen 23081f4487 Update pgadmin.js 2024-10-01 17:30:06 +08:00
Mr Chen 2f75f57365 Update index.py 2024-10-01 17:27:52 +08:00
Mr Chen f4f7ffe5dd Update pgadmin.js 2024-10-01 17:27:30 +08:00
Mr Chen 0de23a3914 update 2024-10-01 17:24:56 +08:00
Mr Chen d1f47ca406 Update pgadmin.js 2024-10-01 17:13:52 +08:00
Mr Chen 8d16fe1d46 Update index.py 2024-10-01 17:10:57 +08:00
Mr Chen d1bffd74ae Update index.py 2024-10-01 17:10:27 +08:00
Mr Chen 23de77d951 Update index.py 2024-10-01 17:09:43 +08:00
Mr Chen 172fe65df4 Update install.sh 2024-10-01 17:09:32 +08:00
Mr Chen 4cd96252f1 Update index.py 2024-10-01 17:09:17 +08:00
Mr Chen a88f4c35bd Update pgadmin.js 2024-10-01 17:08:39 +08:00
Mr Chen 19ffeb7e8e Update pgadmin.js 2024-10-01 17:07:44 +08:00
Mr Chen 004e1ce03c update 2024-10-01 17:05:59 +08:00
Mr Chen 485efb0c88 Update pgadmin.js 2024-10-01 17:01:36 +08:00
Mr Chen 227107719b Update index.html 2024-10-01 16:32:04 +08:00
Mr Chen d683f18bd0 update 2024-10-01 16:26:44 +08:00
Mr Chen 78446b5a68 update 2024-10-01 16:00:50 +08:00
Mr Chen 3fe638d16c update 2024-10-01 15:57:26 +08:00
Mr Chen f71973b10a Update index.py 2024-10-01 15:52:28 +08:00
Mr Chen 0ab0a918c3 Update index.py 2024-10-01 15:46:11 +08:00
Mr Chen c694688220 Update index.py 2024-10-01 15:42:26 +08:00
Mr Chen f979fd32e3 Update index.py 2024-10-01 15:39:00 +08:00
Mr Chen 7e11e8138e update 2024-10-01 15:37:14 +08:00
Mr Chen 590575f5b1 Update pgadmin.service.tpl 2024-10-01 15:26:42 +08:00
Mr Chen b76c525106 update 2024-10-01 15:21:54 +08:00
Mr Chen 56a276f019 Update index.py 2024-10-01 15:12:14 +08:00
Mr Chen 62050fcff1 Update index.py 2024-10-01 15:11:01 +08:00
Mr Chen d4989bb762 update 2024-10-01 14:24:52 +08:00
Mr Chen dff54109a4 Update index.py 2024-10-01 14:22:05 +08:00
Mr Chen 5850d69c10 update 2024-10-01 14:21:17 +08:00
Mr Chen 908507f64e Update install.sh 2024-10-01 12:25:13 +08:00
Mr Chen ecd455ab21 Update install.sh 2024-10-01 12:24:34 +08:00
Mr Chen c4ebfff55e Update install.sh 2024-10-01 12:22:10 +08:00
Mr Chen 6adf5f472d Update install.sh 2024-10-01 12:16:40 +08:00
Mr Chen ee6b5c304a Update install.sh 2024-10-01 12:14:26 +08:00
Mr Chen 03327a549f init pgadmin 2024-10-01 04:08:12 +08:00
Mr Chen f6e245e77d Update __init__.py 2024-10-01 01:33:47 +08:00
Mr Chen 4dcf9d9a40 Update __init__.py 2024-10-01 01:33:34 +08:00
Mr Chen a6ef4e12ad Update __init__.py 2024-10-01 01:30:44 +08:00
Mr Chen 2e751bb3fb Update __init__.py 2024-10-01 01:30:23 +08:00
Mr Chen 5ab15341e4 update 2024-09-29 12:00:00 +08:00
Mr Chen d6b027e969 Update ubuntu.sh 2024-09-28 22:26:59 +08:00
Mr Chen 76a4b3b3e6 Update debian.sh 2024-09-28 22:23:28 +08:00
Mr Chen 3062aee5cb Update debian.sh 2024-09-28 22:22:13 +08:00
Mr Chen dbf0d95329 Update __init__.py 2024-09-28 21:47:27 +08:00
Mr Chen c42b0d5fda Create webhook_index.py 2024-09-28 21:43:44 +08:00
Mr Chen 59f2688399 Update __init__.py 2024-09-28 21:43:42 +08:00
Mr Chen 395bf3aa5a Update __init__.py 2024-09-28 21:41:29 +08:00
Mr Chen bd85e418bc Update nginx.conf 2024-09-27 17:51:03 +08:00
Mr Chen 091ac05920 Update redis.conf 2024-09-26 14:57:12 +08:00
Mr Chen 127d175e5c Update redis.conf 2024-09-26 00:49:55 +08:00
Mr Chen 744a7f83df Update redis.conf 2024-09-26 00:39:09 +08:00
Mr Chen 5f61a7af17 Update gd_old.sh 2024-09-24 16:00:09 +08:00
Mr Chen c4ceaddcca update 2024-09-24 15:10:18 +08:00
Mr Chen 12729092d8 Update index_php_yum.py 2024-09-24 14:31:22 +08:00
Mr Chen 94830659e9 Update index_php_yum.py 2024-09-24 14:11:46 +08:00
Mr Chen aef307c312 Update index_php_yum.py 2024-09-24 14:11:11 +08:00
Mr Chen 2b15c77cdc Update index_php_yum.py 2024-09-24 14:09:20 +08:00
Mr Chen 78acddb043 Update index_php_yum.py 2024-09-24 14:08:10 +08:00
Mr Chen 9106f3d2f5 Update index_php_yum.py 2024-09-24 14:00:01 +08:00
Mr Chen 2df8355a33 Update index_php_yum.py 2024-09-24 13:59:01 +08:00
Mr Chen c5610aae05 update 2024-09-24 13:55:02 +08:00
Mr Chen f1f3a42557 Update gd_old.sh 2024-09-24 13:41:32 +08:00
Mr Chen 63072120fc Update rocky.sh 2024-09-24 13:40:01 +08:00
Mr Chen 0be966646b Update rocky.sh 2024-09-24 13:38:51 +08:00
Mr Chen c3201118bd Update gd_old.sh 2024-09-24 13:16:20 +08:00
Mr Chen 12896574c7 update 2024-09-23 12:12:47 +08:00
Mr Chen 5bf877647f Update cert_api.py 2024-09-21 14:15:08 +08:00
Mr Chen 697e692c92 Update linux.conf 2024-09-18 22:57:38 +08:00
Mr Chen 7b620a294b Update push_notice_msg.py 2024-09-18 10:06:49 +08:00
Mr Chen 8c1e4d7c4d Update push_ad.py 2024-09-18 10:06:32 +08:00
Mr Chen 468c64df40 Update site.js 2024-09-16 02:26:42 +08:00
Mr Chen c560bc666f up 2024-09-15 22:19:04 +08:00
Mr Chen 8c4ab4a60d Update index.py 2024-09-15 15:53:01 +08:00
Mr Chen 1a0b7895d9 Update common.js 2024-09-15 15:41:33 +08:00
Mr Chen 26a29fea96 Update index.py 2024-09-15 15:39:36 +08:00
Mr Chen 5c9a12a7b2 update 2024-09-15 15:35:31 +08:00
Mr Chen 7d103e8f4a Update index.py 2024-09-15 15:27:33 +08:00
Mr Chen 4f4dfd0ee1 Update common.js 2024-09-15 14:38:36 +08:00
Mr Chen c02e95bc49 update 2024-09-15 05:17:16 +08:00
Mr Chen e77bfb055a Update goedge.py 2024-09-15 01:13:23 +08:00
Mr Chen 712814515c update 2024-09-15 01:03:32 +08:00
Mr Chen 512213df15 update 2024-09-15 00:53:06 +08:00
Mr Chen e07c5ab7f9 Update cert_api.py 2024-09-14 20:55:41 +08:00
Mr Chen 83471a37b0 Update common.js 2024-09-14 19:39:42 +08:00
Mr Chen f82944a043 Update common.js 2024-09-14 19:36:53 +08:00
Mr Chen 6eb5dec1f6 Update goedge.py 2024-09-14 19:31:58 +08:00
Mr Chen f7ec845a7e update 2024-09-14 19:31:15 +08:00
Mr Chen 0e7ed65e04 update 2024-09-14 19:22:10 +08:00
Mr Chen 60910c9d87 Update goedge.py 2024-09-14 17:45:49 +08:00
Mr Chen f4b4b3c3a6 update 2024-09-14 17:42:42 +08:00
Mr Chen ce363b0319 Update index.py 2024-09-14 16:03:03 +08:00
Mr Chen 42b0a4067b update 2024-09-14 15:50:03 +08:00
Mr Chen 1e6f755045 update 2024-09-14 15:47:30 +08:00
Mr Chen c7570e84a0 Update index.py 2024-09-14 15:12:26 +08:00
Mr Chen 34b7a5f7ba Update index.py 2024-09-14 15:04:44 +08:00
Mr Chen ff2146a49d update 2024-09-14 15:02:18 +08:00
Mr Chen 5038d8b07f Update install.sh 2024-09-14 11:59:35 +08:00
Mr Chen aacc87c190 Update index.py 2024-09-14 11:57:28 +08:00
Mr Chen e68a21ccb7 Update index.py 2024-09-14 11:52:07 +08:00
Mr Chen 435f0a0c84 Update index.py 2024-09-14 11:50:33 +08:00
Mr Chen d4269dc886 update 2024-09-14 11:48:43 +08:00
Mr Chen 079ae529ee Update tool_cron.py 2024-09-14 02:39:51 +08:00
Mr Chen f8d3e23025 Update install.sh 2024-09-14 02:38:49 +08:00
Mr Chen efa168a4b1 Update install.sh 2024-09-14 02:37:14 +08:00
Mr Chen ebfc32be74 Update index.py 2024-09-14 02:35:55 +08:00
Mr Chen 79a2f6d7a4 Update install.sh 2024-09-14 02:33:48 +08:00
Mr Chen edd218b139 Create tool_cron.py 2024-09-14 02:31:49 +08:00
Mr Chen d3645425f6 up 2024-09-14 02:21:21 +08:00
Mr Chen 2f34c689d0 update 2024-09-14 02:12:32 +08:00
Mr Chen 548e5fbde1 update 2024-09-14 02:00:13 +08:00
Mr Chen f0b3d7f151 Update common.js 2024-09-14 01:46:37 +08:00
Mr Chen c85a6fd462 Update index.html 2024-09-14 01:42:05 +08:00
Mr Chen ddbc7988b2 update 2024-09-14 01:39:57 +08:00
Mr Chen 83b1e3b8af update 2024-09-14 01:25:59 +08:00
Mr Chen 8fd4f83793 Update common.js 2024-09-14 01:17:41 +08:00
Mr Chen 32321c822f Update acme.sql 2024-09-14 01:04:22 +08:00
Mr Chen bb8e8b7367 Update common.js 2024-09-14 01:01:34 +08:00
Mr Chen 224417e2bd acme_pandominassl_apply 2 2024-09-14 00:35:35 +08:00
Mr Chen afb2a39f8c update 2024-09-13 20:54:22 +08:00
Mr Chen f240f167ff Update install.sh 2024-09-13 15:47:12 +08:00
Mr Chen 69273f9cf9 Update install.sh 2024-09-13 15:44:18 +08:00
Mr Chen e30079bd2c update 2024-09-13 15:31:28 +08:00
Mr Chen d882de1582 update 2024-09-13 15:25:26 +08:00
Mr Chen 2e14dc22ff Update install.sh 2024-09-13 15:24:46 +08:00
Mr Chen 6839e387c2 Update install.sh 2024-09-13 15:21:16 +08:00
Mr Chen bde2bc0b2b update 2024-09-13 00:19:27 +08:00
Mr Chen e6fe0885a5 Update acme.sql 2024-09-13 00:17:46 +08:00
Mr Chen f95440da99 acme_pandominassl_apply init 2024-09-13 00:12:18 +08:00
Mr Chen cbfff99f89 Update index.py 2024-09-09 23:04:09 +08:00
Mr Chen ee119ea3cc Update openresty.js 2024-09-09 23:02:38 +08:00
Mr Chen ebefee67bc Update openresty.js 2024-09-09 23:01:03 +08:00
Mr Chen 60fc2e5803 Update openresty.js 2024-09-09 23:00:01 +08:00
Mr Chen b766a6eb6a Update openresty.js 2024-09-09 22:58:29 +08:00
Mr Chen f67342fd7a Update index.py 2024-09-09 22:56:52 +08:00
Mr Chen 2f98228310 Update .gitignore 2024-09-06 19:30:22 +08:00
Mr Chen b07739a66a Update index.py 2024-09-04 23:11:54 +08:00
Mr Chen 3b293e3163 Update index.py 2024-09-04 13:09:20 +08:00
Mr Chen cec5fc594f Update index.py 2024-09-04 13:07:57 +08:00
Mr Chen ed10a050bc Update .gitignore 2024-09-01 10:54:15 +08:00
Mr Chen cfc3dc73c4 Update cert_api.py 2024-08-30 15:10:36 +08:00
Mr Chen 7c23c16280 Update header_cors.conf 2024-08-26 12:29:41 +08:00
Mr Chen 0f27552817 Update webstats_common.lua 2024-08-20 03:14:40 +08:00
Mr Chen 7464789c8c Update commit.tpl 2024-08-16 13:35:34 +08:00
Mr Chen a1f9c023c7 update 2024-08-15 14:29:19 +08:00
Mr Chen 9e8cdc2c49 Update fail2ban.conf 2024-08-15 14:28:32 +08:00
Mr Chen dc9b44f5f9 update 2024-08-15 14:27:52 +08:00
Mr Chen b7ea4bd6f1 update 2024-08-15 14:24:40 +08:00
Mr Chen 65dddb798c Create fail2ban.bak.conf 2024-08-15 14:23:51 +08:00
Mr Chen 2451f0b593 Update fail2ban.conf 2024-08-15 14:16:55 +08:00
Mr Chen 418734eb31 Update index.py 2024-08-15 14:13:24 +08:00
Mr Chen fce7fe4fe3 Update install.sh 2024-08-15 13:18:25 +08:00
Mr Chen e31407527f Update site_api.py 2024-08-15 09:36:33 +08:00
Mr Chen 9250e81059 Update nosql_mongodb.py 2024-08-10 12:55:15 +08:00
Mr Chen f54f9c6736 update 2024-08-09 21:41:59 +08:00
Mr Chen 54135a88f9 Update mongodb.js 2024-08-09 21:08:28 +08:00
Mr Chen 5b219708db Merge pull request #621 from midoks/dev
一些简单优化
2024-08-09 16:37:50 +08:00
Mr Chen b62a5e457b Update app.js 2024-08-09 14:24:48 +08:00
Mr Chen 3af325f0c4 update 2024-08-09 14:15:26 +08:00
Mr Chen 514ced2cc6 update 2024-08-09 01:46:39 +08:00
Mr Chen 55cdf6c0cf Update linux.conf 2024-08-08 22:14:14 +08:00
Mr Chen 00cd6e4309 Update cmd.md 2024-08-06 13:21:11 +08:00
Mr Chen 03012d8296 Update cmd.md 2024-08-06 13:21:04 +08:00
Mr Chen b4952dbb20 update 2024-08-06 13:14:43 +08:00
Mr Chen 9123cedf4c Update mw.tpl 2024-08-06 13:03:17 +08:00
Mr Chen 1c9fbfc2eb Update mw.tpl 2024-08-06 13:01:22 +08:00
Mr Chen d6e182b94f Update mw.tpl 2024-08-06 13:01:05 +08:00
Mr Chen e48e56f36a Update info.json 2024-08-02 04:19:03 +08:00
Mr Chen adde6acf4d Update gorse.toml 2024-08-02 04:18:10 +08:00
Mr Chen e929aa0875 Update gorse.js 2024-08-02 04:11:06 +08:00
Mr Chen f784376486 Update index.py 2024-08-02 04:04:30 +08:00
Mr Chen 7c0d0f4a07 gorse init 2024-08-02 04:00:41 +08:00
Mr Chen e25804998d PHP默认隐藏版本号 2024-07-30 01:12:53 +08:00
Mr Chen 6e69f843a0 update 2024-07-29 19:49:53 +08:00
Mr Chen 978d2878a4 Update plugins_api.py 2024-07-29 14:02:45 +08:00
Mr Chen 675ea86b83 Update install.sh 2024-07-29 12:44:32 +08:00
Mr Chen c2be36b8b3 Update install.sh 2024-07-29 12:25:31 +08:00
Mr Chen 938e204691 Create euler.sh 2024-07-29 12:24:14 +08:00
Mr Chen 70eb911e58 Update getos.sh 2024-07-29 12:22:59 +08:00
Mr Chen 0440d0f286 update 2024-07-29 11:57:35 +08:00
Mr Chen 9651a88d67 update 2024-07-29 11:55:13 +08:00
Mr Chen 6b8d2622b4 Update install.sh 2024-07-29 11:52:15 +08:00
Mr Chen e743499825 Update install.sh 2024-07-29 11:49:33 +08:00
Mr Chen 127535c7d4 Update install.sh 2024-07-29 11:48:15 +08:00
Mr Chen 0a322c9fed Update index.html 2024-07-28 22:34:05 +08:00
Mr Chen db36c34332 Update index.py 2024-07-28 21:41:21 +08:00
Mr Chen 6c00e8c350 Update index.py 2024-07-28 20:20:34 +08:00
Mr Chen 4e21b136d7 Update index.py 2024-07-28 20:18:34 +08:00
Mr Chen 407b317f01 Update index.py 2024-07-28 20:15:22 +08:00
Mr Chen eb55ff7c30 Update install.sh 2024-07-28 20:13:25 +08:00
Mr Chen 3729146b80 Update install.sh 2024-07-28 20:01:01 +08:00
Mr Chen 48636eae43 Update fail2ban.js 2024-07-28 19:59:24 +08:00
Mr Chen ae62bee78d update 2024-07-28 19:54:38 +08:00
Mr Chen d0f33a0813 Update index.py 2024-07-28 19:42:54 +08:00
Mr Chen 6627b67692 update 2024-07-28 19:39:44 +08:00
Mr Chen 32f58e6323 Update index.py 2024-07-28 19:36:37 +08:00
Mr Chen 4c82688f7d Update index.py 2024-07-28 19:28:46 +08:00
Mr Chen 479ed7ac1e Update install.sh 2024-07-28 19:26:45 +08:00
Mr Chen 1320a8aad1 Update install.sh 2024-07-28 19:26:19 +08:00
Mr Chen ed1b1322fa Update info.json 2024-07-28 19:24:28 +08:00
Mr Chen b9b61d1462 update 2024-07-28 19:24:07 +08:00
Mr Chen fc982674f8 fail2ban init 2024-07-28 19:22:17 +08:00
108 changed files with 7910 additions and 230 deletions
+3 -1
View File
@@ -180,4 +180,6 @@ plugins/frp
plugins/file_search
plugins/proxysql
plugins/tidb
plugins/gorse
plugins/goedge-admin
plugins/goedge-node
plugins/goedge-happy
+4 -4
View File
@@ -110,11 +110,11 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.17.2
### 版本更新 0.17.3
- MySQL9.0。
- zabbix,zabbix-agent测试。
- 正则匹配修复(兼容)。
- 新增pgadmin插件。
- 新增acme_pandominassl_apply插件。
- 新增快捷指令:mw pgdb。
- 常规更新。
### JSDelivr安装地址
+10 -6
View File
@@ -225,8 +225,7 @@ fi
86400 # 24小时后过期
self.saveConfig()
except Exception as e:
raise Exception(
'服务因维护而关闭或发生内部错误,查看 <a href="https://letsencrypt.status.io/" target="_blank" class="btlink">https://letsencrypt.status.io/</a> 了解更多详细信息。')
raise Exception('服务因维护而关闭或发生内部错误,查看 <a href="https://letsencrypt.status.io/" target="_blank" class="btlink">https://letsencrypt.status.io/</a> 了解更多详细信息。')
return self.__apis
# 系列化payload
@@ -1297,9 +1296,9 @@ fullchain.pem 粘贴到证书输入框
site_sql = mw.M('sites')
siteName = None
for domain in domains:
pid = sql.where('name=?', domain).getField('pid')
pid = sql.where('name=?', (domain,)).getField('pid')
if pid:
siteName = site_sql.where('id=?', pid).getField('name')
siteName = site_sql.where('id=?', (pid,)).getField('name')
break
return siteName
@@ -1325,6 +1324,8 @@ fullchain.pem 粘贴到证书输入框
else:
site_name = self.getSiteNameByDomains(domains)
is_rep = api.httpToHttps(site_name)
api.operateProxyConf(site_name,'stop')
mw.restartWeb()
try:
index = self.createOrder(
domains,
@@ -1376,6 +1377,9 @@ fullchain.pem 粘贴到证书输入框
is_rep_decode = json.loads(is_rep)
if is_rep_decode['status']:
api.closeToHttps(site_name)
api.operateProxyConf(site_name,'start')
mw.restartWeb()
writeLog("-" * 70)
return cert
@@ -1447,8 +1451,8 @@ fullchain.pem 粘贴到证书输入框
# 是否到了最大重试次数
if 'retry_count' in self.__config['orders'][i]:
if self.__config['orders'][i]['retry_count'] >= 5:
msg = '|-本次跳过域名:{},因连续5次续签失败,不再续签此证书(可尝试手动续签此证书,成功后错误次数将被重置)'.format(
if self.__config['orders'][i]['retry_count'] >= 100:
msg = '|-本次跳过域名:{},因连续10次续签失败,不再续签此证书(可尝试手动续签此证书,成功后错误次数将被重置)'.format(
self.__config['orders'][i]['domains'])
writeLog(msg)
continue
+1 -1
View File
@@ -28,7 +28,7 @@ from flask import request
class config_api:
__version = '0.17.2'
__version = '0.17.3'
__api_addr = 'data/api.json'
# 统一默认配置文件
+12
View File
@@ -472,6 +472,9 @@ def getJson(data):
import json
return json.dumps(data)
def getObjectByJson(data):
import json
return json.loads(data)
def returnData(status, msg, data=None):
return {'status': status, 'msg': msg, 'data': data}
@@ -687,6 +690,15 @@ def restoreFile(file, act=None):
file_type = "_def"
execShell("cp -p {1} {0}".format(file, file + file_type))
def base64StrEncode(content):
content = bytes(content,'utf-8')
content = base64.b64encode(content)
return content.decode('utf8')
def base64StrDecode(content):
content = bytes(content,'utf-8')
content = base64.urlsafe_b64decode(content)
return content.decode('utf8')
def enPunycode(domain):
if sys.version_info[0] == 2:
+1 -1
View File
@@ -148,7 +148,7 @@ class plugins_api:
def initApi(self):
plugin_names = {
'openresty': '1.25.3.1',
'openresty': '1.25.3',
'php': '56',
'swap': '1.1',
'mysql': '5.7',
+2 -2
View File
@@ -1786,8 +1786,7 @@ class site_api:
data.append({"r_from": _from, "type": _typeCode, "r_type": _rTypeCode,
"r_to": _to, 'keep_path': _keepPath, 'id': _id})
mw.writeFile(data_path, json.dumps(data))
mw.writeFile(
"{}/{}.conf".format(self.getRedirectPath(_siteName), _id), file_content)
mw.writeFile("{}/{}.conf".format(self.getRedirectPath(_siteName), _id), file_content)
self.operateRedirectConf(_siteName, 'start')
mw.restartWeb()
@@ -1977,6 +1976,7 @@ class site_api:
location ^~ {from} {\n\
proxy_pass {to};\n\
proxy_set_header Host {host};\n\
proxy_ssl_server_name on;\n\
proxy_set_header X-Real-IP $remote_addr;\n\
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\
proxy_set_header REMOTE-HOST $remote_addr;\n\
+6 -4
View File
@@ -4,9 +4,11 @@
- 面板相关命令
```
/etc/init.d/mw default | 显示登录信息
/etc/init.d/mw db | 快捷连接MySQL
/etc/init.d/mw redis | 快捷连接Redis
mw default | 显示登录信息
mw db | 快捷连接MySQL
mw redis | 快捷连接Redis
mw mongodb | 快捷连接MongoDB
mw pgdb | 快捷连接PostgreSQL
----------------------------------------
mw open | 开启面板
mw close | 关闭面板
@@ -16,7 +18,7 @@ mw venv | 进入虚拟环境
mw mirror | 切换镜像
mw install_app | 快捷安装常用软件
mw update | 更新到正式
mw update_dev | 更新到开发
mw dev/update_dev | 更新到开发
service mw [start|stop|reload|restart|status]
```
+5
View File
@@ -71,9 +71,14 @@ CREATE TABLE IF NOT EXISTS `sites` (
`type_id` INTEGER,
`ps` TEXT,
`edate` TEXT,
`ssl_effective_date` TEXT,
`ssl_expiration_date` TEXT,
`addtime` TEXT
);
ALTER TABLE `sites` ADD COLUMN `ssl_effective_date` TEXT DEFAULT '';
ALTER TABLE `sites` ADD COLUMN `ssl_expiration_date` TEXT DEFAULT '';
CREATE TABLE IF NOT EXISTS `site_types` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT
@@ -0,0 +1,34 @@
CREATE TABLE IF NOT EXISTS `dnsapi` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`type` TEXT,
`val` TEXT,
`remark` TEXT,
`addtime` TEXT
);
CREATE TABLE IF NOT EXISTS `email` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`addr` TEXT,
`remark` TEXT,
`addtime` TEXT
);
CREATE TABLE IF NOT EXISTS `domain` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`domain` TEXT,
`dnsapi_id` TEXT,
`email` TEXT,
`remark` TEXT,
`effective_date` TEXT,
`expiration_date` TEXT,
`error` TEXT,
`status` INTEGER default '0',
`addtime` TEXT
);
-- ALTER TABLE `domain` ADD COLUMN `effective_date` TEXT DEFAULT '';
-- ALTER TABLE `domain` ADD COLUMN `expiration_date` TEXT DEFAULT '';
-- ALTER TABLE `domain` ADD COLUMN `error` TEXT DEFAULT '';
-- ALTER TABLE `domain` ADD COLUMN `status` INTEGER DEFAULT '0';
@@ -0,0 +1,128 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import requests
import base64
# 8001 / 7788
goedge_addr = 'http://127.0.0.2:8009'
access_keyid = "xxx"
access_key = "xxx"
# 指定用户
userId = 1
sys.path.append(os.getcwd() + "/class/core")
import mw
domain = sys.argv[1]
ssl_path = sys.argv[2]
def getToken():
api_url = goedge_addr+'/APIAccessTokenService/getAPIAccessToken'
post_data = {
"type": "admin",
"accessKeyId": access_keyid,
"accessKey": access_key
}
data = requests.post(api_url,json=post_data)
data_obj = data.json()
return data_obj['data']['token']
token = getToken()
def commonReq(url, data):
headers = {
'X-Edge-Access-Token': token
}
api_url = goedge_addr+url
resp_data = requests.post(api_url,json=data, headers=headers)
return resp_data.json()
def listSSLCerts(domain):
request_data = {
"userId":userId,
"isCA":False,
"keyword": "ACME泛域名自动上传",
"domains":[domain,"*."+domain],
"size":1
}
response_data = commonReq('/SSLCertService/listSSLCerts', request_data)
data = response_data['data']['sslCertsJSON']
data = mw.base64StrDecode(data)
data = mw.getObjectByJson(data)
# print(data)
return data
# createSSLCert(domain)
def createSSLCert(domain, did=0):
ssl_cer_file = ssl_path + '/'+domain+'.cer'
if not os.path.exists(ssl_cer_file):
print("没有有效证书!")
return ''
# print(ssl_cer_file)
ssl_info = mw.getCertName(ssl_cer_file)
cer_data = mw.readFile(ssl_cer_file)
cer_data = mw.base64StrEncode(cer_data)
# print('cer',cer_data)
ssl_key_file = ssl_path + '/'+domain+'.key'
key_data = mw.readFile(ssl_key_file)
key_data = mw.base64StrEncode(key_data)
# print('ssl_info',ssl_info)
timeBeginAt = int(time.mktime(time.strptime(ssl_info['notBefore'], "%Y-%m-%d")))
timeEndAt = int(time.mktime(time.strptime(ssl_info['notAfter'], "%Y-%m-%d")))
request_data = {
"isOn":True,
"userId":userId,
"name": "ACME泛域名自动上传",
"isCA":False,
"description":domain,
"serverName":domain,
"certData":cer_data,
"keyData":key_data,
"timeBeginAt":timeBeginAt,
"timeEndAt": timeEndAt,
"dnsNames":[domain,"*."+domain],
"commonNames":[ssl_info['issuer']]
}
if did>0:
request_data['sslCertId'] = did
# print(request_data)
response_data = commonReq('/SSLCertService/updateSSLCert', request_data)
print('更新成功',domain,response_data)
return response_data
else:
# print(request_data)
response_data = commonReq('/SSLCertService/createSSLCert', request_data)
print('创建成功',domain,response_data)
return response_data
return response_data
def autoSyncDomain(domain):
data = listSSLCerts(domain)
if len(data) > 0 :
did = data[0]['id']
createSSLCert(domain,did)
else:
createSSLCert(domain)
print(data)
autoSyncDomain(domain)
print(domain,ssl_path)
@@ -0,0 +1,12 @@
# coding:utf-8
import sys
import io
import os
import time
import re
domain = sys.argv[1]
path = sys.argv[2]
print(domain,path)
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

+34
View File
@@ -0,0 +1,34 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('acme_pandominassl_apply');">服务</p>
<p onclick="dnsapiList();">DNSAPI *</p>
<p onclick="emailList();">邮件地址 </p>
<p onclick="domainList()">域名SSL *</p>
<p onclick="pluginConfigTpl('acme_pandominassl_apply',$('.plugin_version').attr('version'));">HOOK</p>
<p onclick="pluginLogs('acme_pandominassl_apply','','run_log');">日志</p>
<p onclick="apaReadme();">相关说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinWidth(1000);
resetPluginWinHeight(550);
$.getScript( "/plugins/file?name=acme_pandominassl_apply&f=js/common.js", function(){
pluginService('acme_pandominassl_apply', $('.plugin_version').attr('version'));
});
</script>
+857
View File
@@ -0,0 +1,857 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import requests
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'acme_pandominassl_apply'
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() + "/hook.py"
return path
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
def runLog():
return getServerDir() + '/hook.log'
def getArgs():
args = sys.argv[3:]
# print(args)
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 getHomeDir():
if mw.isAppleSystem():
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return '/Users/' + user
else:
return '/root'
def getRunUser():
if mw.isAppleSystem():
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return user
else:
return 'root'
def configTpl():
path = getPluginDir() + '/hooks'
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 getPidFile():
file = getConf()
content = mw.readFile(file)
rep = r'pidfile\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def status():
return 'start'
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$SERVER_APP}', service_path + '/redis')
content = content.replace('{$REDIS_PASS}', mw.getRandomString(10))
return content
def pSqliteDb(dbname='dnsapi'):
file = getServerDir() + '/acme.db'
name = 'acme'
import_sql = mw.readFile(getPluginDir() + '/conf/acme.sql')
md5_sql = mw.md5(import_sql)
import_sign = False
save_md5_file = getServerDir() + '/acme.md5'
if os.path.exists(save_md5_file):
save_md5_sql = mw.readFile(save_md5_file)
if save_md5_sql != md5_sql:
import_sign = True
mw.writeFile(save_md5_file, md5_sql)
else:
mw.writeFile(save_md5_file, md5_sql)
if not os.path.exists(file) or import_sql:
conn = mw.M(dbname).dbPos(getServerDir(), name)
csql_list = import_sql.split(';')
for index in range(len(csql_list)):
conn.execute(csql_list[index], ())
conn = mw.M(dbname).dbPos(getServerDir(), name)
return conn
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()
run_log_file = runLog()
if not os.path.exists(run_log_file):
mw.writeFile(run_log_file,'')
hook_file = getConf()
if not os.path.exists(hook_file):
mw.writeFile(hook_file,'')
return file_bin
def apaOp(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():
import tool_cron
tool_cron.createBgTask()
return apaOp('start')
def stop():
import tool_cron
tool_cron.removeBgTask()
return apaOp('stop')
def restart():
status = apaOp('restart')
return status
def reload():
return apaOp('reload')
def dnsapiAdd():
conn = pSqliteDb('dnsapi')
args = getArgs()
data = checkArgs(args,['id','name', 'type', 'remark'])
if not data[0]:
return data[1]
name = args['name'].strip()
remark = args['remark'].strip()
stype = args['type'].strip()
val = args['val'].strip()
sid = args['id'].strip()
if name == '':
return mw.returnJson(False, '名称不能为空!')
if sid != '0' : #修改操作
conn.where("id=?", (sid,)).update({
'name':name,
'type':stype,
'val':val,
'remark':remark,
})
return mw.returnJson(True, '修改成功!')
if conn.where("name=?", (name,)).count():
return mw.returnJson(False, name+'已存在!')
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
err = conn.add('name,type,val,remark,addtime', (name, stype, val,remark, addTime))
# print(err)
return mw.returnJson(True, '添加成功!')
def dnsapiDel():
args = getArgs()
data = checkArgs(args, ['id', 'name'])
if not data[0]:
return data[1]
conn = pSqliteDb('dnsapi')
try:
sid = args['id']
name = args['name']
conn.where("id=?", (sid,)).delete()
return mw.returnJson(True, '删除成功!')
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def dnsapiList():
args = getArgs()
page = 1
page_size = 10
search = ''
data = {}
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'search' in args:
search = args['search']
conn = pSqliteDb('dnsapi')
limit = str((page - 1) * page_size) + ',' + str(page_size)
condition = ''
if not search == '':
condition = "name like '%" + search + "%'"
field = 'id,name,type,val,remark,addtime'
clist = conn.where(condition, ()).field(
field).limit(limit).order('id desc').select()
count = conn.where(condition, ()).count()
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = 'dbList'
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.getJson(data)
def dnsapiListAll():
conn = pSqliteDb('dnsapi')
field = 'id,name,type,val,remark,addtime'
data = conn.field(field).limit('1000').select()
return mw.getJson(data)
def emailList():
args = getArgs()
page = 1
page_size = 10
search = ''
data = {}
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'search' in args:
search = args['search']
conn = pSqliteDb('email')
limit = str((page - 1) * page_size) + ',' + str(page_size)
condition = ''
if not search == '':
condition = "addr like '%" + search + "%'"
field = 'id,addr,remark,addtime'
clist = conn.where(condition, ()).field(
field).limit(limit).order('id desc').select()
count = conn.where(condition, ()).count()
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = 'dbList'
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.getJson(data)
def emailAdd():
args = getArgs()
data = checkArgs(args,['addr', 'remark'])
if not data[0]:
return data[1]
addr = args['addr'].strip()
remark = args['remark'].strip()
if addr == '':
return mw.returnJson(False, '邮件地址不能为空!')
conn = pSqliteDb('email')
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
conn.add('addr,remark,addtime', (addr, remark, addTime))
return mw.returnJson(True, '添加成功!')
def emailDel():
args = getArgs()
data = checkArgs(args, ['id', 'name'])
if not data[0]:
return data[1]
conn = pSqliteDb('email')
try:
sid = args['id']
name = args['name']
conn.where("id=?", (sid,)).delete()
return mw.returnJson(True, '删除成功!')
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def domainAdd():
args = getArgs()
data = checkArgs(args,['id','domain', 'dnsapi_id','email','remark'])
if not data[0]:
return data[1]
sid = args['id'].strip()
domain = args['domain'].strip()
remark = args['remark'].strip()
email = args['email'].strip()
dnsapi_id = args['dnsapi_id'].strip()
if domain == '':
return mw.returnJson(False, '域名不能为空!')
if email == '':
return mw.returnJson(False, '邮件不能为空!')
conn = pSqliteDb('domain')
if sid != '0' : #修改操作
conn.where("id=?", (sid,)).update({
'domain':domain,
'dnsapi_id':dnsapi_id,
'email':email,
'remark':remark,
})
return mw.returnJson(True, '修改成功!')
if conn.where("domain=?", (domain,)).count():
return mw.returnJson(False, domain+'已存在!')
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
conn.add('domain,dnsapi_id,email,remark,addtime', (domain, dnsapi_id,email,remark, addTime))
return mw.returnJson(True, '添加成功!')
def domainDel():
args = getArgs()
data = checkArgs(args, ['id', 'name'])
if not data[0]:
return data[1]
conn = pSqliteDb('domain')
try:
sid = args['id']
name = args['name']
conn.where("id=?", (sid,)).delete()
return mw.returnJson(True, '删除成功!')
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def domainStatusToggle():
args = getArgs()
data = checkArgs(args, ['id'])
if not data[0]:
return data[1]
conn = pSqliteDb('domain')
field = 'id,status'
fdata = conn.field(field).where('id=?',(args['id'],)).find()
fstatus = fdata['status']
if fstatus == 0:
fstatus = 1
else:
fstatus = 0
# print(fdata['status'],fstatus)
conn.where("id=?", (args['id'],)).update({
'status':fstatus,
})
return mw.returnJson(True, '切换成功!')
def domainList():
args = getArgs()
page = 1
page_size = 10
search = ''
data = {}
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'search' in args:
search = args['search']
conn = pSqliteDb('domain')
conn_dnsapi = pSqliteDb('dnsapi')
limit = str((page - 1) * page_size) + ',' + str(page_size)
condition = ''
if not search == '':
condition = "domain like '%" + search + "%'"
field = 'id,domain,dnsapi_id,email,status,effective_date,expiration_date,remark,addtime'
clist = conn.where(condition, ()).field(
field).limit(limit).order('id desc').select()
for i in range(len(clist)):
tdata = conn_dnsapi.field('id,name').where('id=?',(clist[i]['dnsapi_id'],)).select()
if len(tdata) > 0:
# print(tdata[0]['name'])
clist[i]['dnsapi_id_alias'] = clist[i]['dnsapi_id']+'('+ tdata[0]['name'] +')'
else:
clist[i]['dnsapi_id_alias'] = clist[i]['dnsapi_id']+' (无)'
count = conn.where(condition, ()).count()
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = 'dbList'
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.getJson(data)
def getDnsapiData(dnsapi_id):
if dnsapi_id == '0':
return {}
conn_dnsapi = pSqliteDb('dnsapi')
tdata = conn_dnsapi.field('id,name,type,val').where('id=?',(dnsapi_id,)).select()
if len(tdata)>0:
return tdata[0]
return {}
def getDnsapiExportVar(val):
cmd_list = val.split('~')
def_var = ''
for x in range(len(cmd_list)):
v = cmd_list[x]
vlist = v.split('|')
def_var += 'export '+vlist[0]+'="'+vlist[1]+'"\n'
return def_var
def getDnsapiKv(val):
cmd_list = val.split('~')
def_var = {}
for x in range(len(cmd_list)):
v = cmd_list[x]
vlist = v.split('|')
kk = vlist[0]
vv = vlist[1]
def_var[kk] = vv
return def_var
def domainApplyPathJudge(domain):
acme_dir = "/root/.acme.sh"
if mw.isAppleSystem():
user = getRunUser()
acme_dir = "/Users/"+user+"/.acme.sh"
abs_domain_path = acme_dir+'/'+domain+'_ecc'
# print(abs_domain_path)
if os.path.exists(abs_domain_path):
return True, abs_domain_path
abs_domain_path = acme_dir+'/'+domain
# print(abs_domain_path)
if os.path.exists(abs_domain_path):
return True, abs_domain_path
return False,''
def hookWriteLog(line):
hook_file = runLog()
mdate = time.strftime('%Y-%m-%d %X', time.localtime())
log = "["+mdate+"]:"+line
print(log)
return mw.writeFile(hook_file,log+"\n",'a+')
def runHookPy(domain,path):
# print(domain,path)
run_log = runLog()
hook_file = getConf()
cmd = 'cd '+mw.getRunDir()
cmd += ' && python3 '+hook_file + ' ' + domain + ' ' + path
cmd += ' >> '+ run_log
print(cmd)
return mw.execShell(cmd)
def autoUpdateSslData(domain, path):
ssl_cer_file = path + '/'+domain+'.cer'
ssl_info = mw.getCertName(ssl_cer_file)
time_begin = int(time.mktime(time.strptime(ssl_info['notBefore'], "%Y-%m-%d")))
time_end = int(time.mktime(time.strptime(ssl_info['notAfter'], "%Y-%m-%d")))
# print(ssl_info)
# print(time_begin,time_end)
conn = pSqliteDb('domain')
conn.where('domain=?', (domain,)).update({
'effective_date':str(time_begin),
'expiration_date':str(time_end),
})
return True
def runHookDstDomain(row):
domain = row['domain']
email = str(row['email'])
if row['effective_date'] != '':
effective_date = int(row['effective_date'])
now_int = int(time.time())
day = (now_int - effective_date)/86400
if int(day) < 8:
common_log = '【'+domain+'】未过期'
hookWriteLog(common_log)
return
hookWriteLog('开始申请【'+domain+'】SSL证书')
cmd = "#!/bin/bash\n"
if mw.isAppleSystem():
user = getRunUser()
cmd += "source /Users/"+user+"/.zshrc\n"
cmd_data = getDnsapiData(row['dnsapi_id'])
# print(cmd_data)
export_val = getDnsapiExportVar(cmd_data['val'])
cmd += export_val
# acme.sh --register-account -m my@example.com
cmd_register = 'acme.sh --register-account -m '+ email + '\n'
cmd += cmd_register
# acme.sh --issue -d "example.com" -d "*.example.com" --dns dns_cf
cmd_apply = 'acme.sh --issue --dns '+str(cmd_data['type'])+' -d '+domain+' -d "*.'+domain+'"'
if row['effective_date'] != '':
effective_date = int(row['effective_date'])
now_int = int(time.time())
day = (now_int - effective_date)/86400
if int(day) > 7:
cmd_apply = 'acme.sh --issue --dns '+str(cmd_data['type'])+' -d '+domain+' -d "*.'+domain+'" --force'
cmd += cmd_apply
run_log = runLog()
cmd += ' >> '+ run_log
print(cmd)
os.system(cmd)
hookWriteLog('结束申请【'+domain+'】SSL证书')
isok, path = domainApplyPathJudge(domain)
print(isok,path)
if isok:
autoUpdateSslData(domain, path)
hookWriteLog('开始执行【'+domain+'】Hook脚本')
runHookPy(domain,path)
hookWriteLog('结束执行【'+domain+'】Hook脚本')
def getHookIdCmd():
args = getArgs()
data = checkArgs(args, ['id'])
if not data[0]:
return data[1]
cmd = "cd "+mw.getRunDir()+" "
cmd += '&& python3 plugins/acme_pandominassl_apply/index.py run_hook_id 1.0 {"id":"'+args['id']+'"}'
return mw.returnJson(True, 'ok',cmd)
def runHookId():
args = getArgs()
data = checkArgs(args, ['id'])
if not data[0]:
return data[1]
conn = pSqliteDb('domain')
field = 'id,domain,dnsapi_id,email,effective_date,expiration_date,remark'
row = conn.field(field).where('id=?',(args['id'],)).find()
runHookDstDomain(row)
return 'run hook '+args['id']+' end'
def runHookCmd():
cmd = "cd "+mw.getRunDir()+" "
cmd += '&& python3 plugins/acme_pandominassl_apply/index.py run_hook'
return mw.returnJson(True, 'ok',cmd)
def runHook():
conn = pSqliteDb('domain')
field = 'id,domain,dnsapi_id,email,effective_date,expiration_date,remark'
clist = conn.field(field).where('status=?',(1,)).limit('1000').order('id desc').select()
for idx in range(len(clist)):
row = clist[idx]
# print(row)
runHookDstDomain(row)
time.sleep(1)
return 'run hook end'
def autoSyncDomain(domain, dnsapi_id, email):
conn = pSqliteDb('domain')
field = 'id,domain,dnsapi_id,email,effective_date,expiration_date,remark'
fdata = conn.field(field).where('domain=?',(domain,)).select()
# print(fdata)
mdate = time.strftime('%Y-%m-%d %X', time.localtime())
if len(fdata) == 0:
conn.add('domain,dnsapi_id,email,remark,addtime', (domain, dnsapi_id, email,"备注", mdate))
print(domain+" 同步成功!")
return True
def runSyncCfDataRow(row, page = 1):
# print(row, page)
cf_key = row['kv']['CF_Key']
cf_mail = row['kv']['CF_Email']
header = {
'X-Auth-Email': cf_mail,
'X-Auth-Key': cf_key,
'Content-Type': 'application/json'
}
url = "https://api.cloudflare.com/client/v4/zones?status=active&page="+str(page)+"&per_page=20&order=status&direction=desc&match=all"
try:
r = requests.get(url, timeout=30, headers=header)
r.raise_for_status()
r.encoding = r.apparent_encoding
# print(r.text)
jdata = json.loads(r.text)
result = jdata['result']
result_info = jdata['result_info']
# print(len(result))
for i in result:
autoSyncDomain(i['name'], row['id'], cf_mail)
if result_info['total_pages'] > page:
page += 1
runSyncCfDataRow(row, page)
# print(result)
except Exception as e:
print(e)
# 同步CloudFlare数据
def runSyncCfData():
print("同步CloudFlare数据开始")
conn_dnsapi = pSqliteDb('dnsapi')
field = "id,name,type,val"
fdata = conn_dnsapi.field(field).where('type=?', ('dns_cf',)).limit('10').select()
for x in range(len(fdata)):
row = fdata[x]
dnsapi_kv = getDnsapiKv(row['val'])
row['kv'] = dnsapi_kv
runSyncCfDataRow(row)
print("同步CloudFlare数据结束")
return ''
def runSyncCfCmd():
cmd = "cd "+mw.getRunDir()+" "
cmd += '&& python3 plugins/acme_pandominassl_apply/index.py run_sync_cf_data'
return mw.returnJson(True, 'ok',cmd)
def runSyncDnspodDataRow(row, page = 1):
# print(row, page)
DPI_Id = row['kv']['DPI_Id']
DPI_Key = row['kv']['DPI_Key']
data = {
'login_token': DPI_Id+','+DPI_Key,
'length':5,
'format':'json',
}
url = "https://api.dnspod.com/Domain.List"
try:
r = requests.post(url, timeout=30, data=data)
r.raise_for_status()
r.encoding = r.apparent_encoding
# print(r.text)
jdata = json.loads(r.text)
info = jdata['info']
domains = jdata['domains']
# print(jdata)
for i in domains:
autoSyncDomain(i['name'], row['id'], i['owner'])
page_total = int(info['domain_total']/data['length'])
if page_total > page:
page += 1
runSyncDnspodDataRow(row, page)
except Exception as e:
print(e)
# 同步DnsPod数据
def runSyncDnsPodData():
print("同步DnsPod数据开始")
conn_dnsapi = pSqliteDb('dnsapi')
field = "id,name,type,val"
fdata = conn_dnsapi.field(field).where('type=?', ('dns_dpi',)).limit('10').select()
for x in range(len(fdata)):
row = fdata[x]
dnsapi_kv = getDnsapiKv(row['val'])
row['kv'] = dnsapi_kv
runSyncDnspodDataRow(row)
print(fdata)
print("同步DnsPod数据结束")
return ''
def runSyncDnsPodCmd():
cmd = "cd "+mw.getRunDir()+" "
cmd += '&& python3 plugins/acme_pandominassl_apply/index.py run_sync_dnspod_data'
return mw.returnJson(True, 'ok',cmd)
if __name__ == "__main__":
func = sys.argv[1]
# print(func)
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 == 'run_info':
print(runInfo())
elif func == 'conf':
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'config_tpl':
print(configTpl())
elif func == 'read_config_tpl':
print(readConfigTpl())
elif func == 'dnsapi_list':
print(dnsapiList())
elif func == 'dnsapi_list_all':
print(dnsapiListAll())
elif func == 'dnsapi_add':
print(dnsapiAdd())
elif func == 'dnsapi_del':
print(dnsapiDel())
elif func == 'email_list':
print(emailList())
elif func == 'email_add':
print(emailAdd())
elif func == 'email_del':
print(emailDel())
elif func == 'domain_list':
print(domainList())
elif func == 'domain_add':
print(domainAdd())
elif func == 'domain_del':
print(domainDel())
elif func == 'domain_status_toggle':
print(domainStatusToggle())
elif func == 'run_hook':
print(runHook())
elif func == 'run_hook_cmd':
print(runHookCmd())
elif func == 'get_run_hook_id_cmd':
print(getHookIdCmd())
elif func == 'run_hook_id':
print(runHookId())
elif func == 'run_sync_cf_data':
print(runSyncCfData())
elif func == 'run_sync_cf_cmd':
print(runSyncCfCmd())
elif func == 'run_sync_dnspod_data':
print(runSyncDnsPodData())
elif func == 'run_sync_dnspod_cmd':
print(runSyncDnsPodCmd())
else:
print('error')
+17
View File
@@ -0,0 +1,17 @@
{
"sort": 7,
"ps": "ACME泛域名SSL申请/管理",
"name": "acme_pandominassl_apply",
"title": "ACME泛域名SSL",
"shell": "install.sh",
"versions":["1.0"],
"tip": "soft",
"checks": "server/acme_pandominassl_apply",
"path": "server/acme_pandominassl_apply",
"display": 1,
"author": "ACME",
"date": "2024-09-12",
"home": "https://github.com/acmesh-official/acme.sh",
"type": 0,
"pid": "5"
}
+55
View File
@@ -0,0 +1,55 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
# curl https://get.acme.sh | sh
# acme.sh --uninstall
# source /Users/xxx/.zshrc
# https://github.com/acmesh-official/acme.sh/wiki/dnsapi
# https://docs.dnspod.com/api-legacy/domains.html#get-the-domain-list
# cd /www/server/mdserver-web && python3 plugins/acme_pandominassl_apply/index.py run_hook
# cd /www/server/mdserver-web && python3 plugins/acme_pandominassl_apply/index.py run_sync_cf_data
# cd /www/server/mdserver-web && python3 plugins/acme_pandominassl_apply/index.py run_sync_dnspod_data
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
# pip install cloudflare
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/acme_pandominassl_apply
echo "${VERSION}" > $serverPath/acme_pandominassl_apply/version.pl
cd ${rootPath} && python3 ${rootPath}/plugins/acme_pandominassl_apply/index.py start
echo '安装[ACME泛域名SSL]完成'
}
Uninstall_App()
{
cd ${rootPath} && python3 ${rootPath}/plugins/acme_pandominassl_apply/index.py stop
rm -rf $serverPath/acme_pandominassl_apply
echo "卸载[ACME泛域名SSL]成功"
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+792
View File
@@ -0,0 +1,792 @@
function apaPost(method, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'acme_pandominassl_apply';
req_data['func'] = method;
req_data['version'] = $('.plugin_version').attr('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 apaPostN(method, args,callback){
var req_data = {};
req_data['name'] = 'acme_pandominassl_apply';
req_data['func'] = method;
req_data['version'] = $('.plugin_version').attr('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) {
if (!data.status){
//错误展示10S
layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function apaPostCallbak(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'acme_pandominassl_apply';
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');
}
function apaReadme(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>ACME泛域名SSL申请/管理/HOOK</li>';
readme += '<li>通过DNS验证获取SSL证书!</li>';
readme += '<li>HOOK: ssl发生变动时调用!</li>';
readme += '<li>暂时仅支持1000个域名管理!</li>';
readme += '<li>DNSAPI文档: https://github.com/acmesh-official/acme.sh/wiki/dnsapi</li>';
readme += '<li>默认7天强制更新!</li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
}
function emailDel(id, name){
safeMessage('删除['+name+']','您真的要删除['+name+']吗?',function(){
var data='id='+id+'&name='+name;
apaPost('email_del', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
emailList();
},{icon: rdata.status ? 1 : 2}, 600);
});
});
}
function emailAdd(type){
layer.open({
type: 1,
area: '500px',
title: '添加邮件地址',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='email_add'>\
<div class='line'>\
<span class='tname'>邮件地址</span>\
<div class='info-r'><input name='addr' class='bt-input-text mr5' style='width:100%;' placeholder='邮件地址' type='text'></div>\
</div>\
<div class='line'>\
<span class='tname'>备注</span>\
<div class='info-r'><input name='remark' class='bt-input-text mr5' style='width:100%;' placeholder='备注' type='text'></div>\
</div>\
</form>",
success:function(){
$("input[name='addr']").keyup(function(){
var v = $(this).val();
$("input[name='remark']").val(v);
});
},
yes:function(index) {
var data = $("#email_add").serialize();
data = decodeURIComponent(data);
// data = toArrayObject(data);
apaPost('email_add', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
emailList();
}
},{icon: rdata.status ? 1 : 2}, 2000);
});
}
});
}
function emailList(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;
}
apaPost('email_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
for(i in rdata.data){
list += '<tr>';
list +='<td><input value="'+rdata.data[i]['id']+'" class="check" onclick="checkSelect();" type="checkbox"></td>';
list += '<td>' + rdata.data[i]['addr'] +'</td>';
list += '<td>' + rdata.data[i]['remark'] +'</td>';
list += '<td style="text-align:right">';
list += '<a href="javascript:;" class="btlink" onclick="emailDel(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['addr']+'\')" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
var con = '<div class="safe bgw">\
<button onclick="emailAdd()" title="添加邮件地址" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加邮件地址</button>\
<span style="float:right"> \
<button batch="true" style="float: right;display: none;margin-left:10px;" onclick="delDbBatch();" title="删除选中项" class="btn btn-default btn-sm">删除选中</button>\
</span>\
<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr><th width="30"><input class="check" onclick="checkSelect();" type="checkbox"></th>\
<th>邮件地址</th>\
<th>备注</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>'+ list +'</tbody>\
</table>\
</div>\
<div class="dataTables_paginate paging_bootstrap page"></div>\
</div>\
</div>';
$(".soft-man-con").html(con);
$('.dataTables_paginate').html(rdata.page);
readerTableChecked();
});
}
function dnsapiDel(id, name){
safeMessage('删除['+name+']','您真的要删除['+name+']吗?',function(){
var data='id='+id+'&name='+name;
apaPost('dnsapi_del', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
dnsapiList();
},{icon: rdata.status ? 1 : 2}, 600);
});
});
}
var dnsapi_option = [
{"name":"dns_cf", "title":'cloudflare', 'key':'CF_Key:CF_Email'},
{"name":"dns_dp", "title":'dnspod/国内', 'key':'DP_Id:DP_Key'},
{"name":"dns_dpi", "title":'dnspod/国际', 'key':'DPI_Id:DPI_Key'},
{"name":"dns_gd", "title":'GoDaddy', 'key':'GD_Key:GD_Secret'},
{"name":"dns_pdns", "title":'PowerDNS', 'key':'PDNS_Url:PDNS_ServerId:PDNS_Token:PDNS_Ttl'},
{"name":"dns_lua", "title":'LuaDNS', 'key':'LUA_Key:LUA_Email'},
{"name":"dns_me", "title":'DNSMadeEasy', 'key':'ME_Key:ME_Secret'},
{"name":"dns_aws", "title":'Amazon Route53', 'key':'AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY'},
{"name":"dns_ali", "title":'Aliyun', 'key':'Ali_Key:Ali_Secret'},
{"name":"dns_ispconfig", "title":'ISPConfig', 'key':'ISPC_User:ISPC_Password:ISPC_Api:ISPC_Api_Insecure'},
{"name":"dns_ad", "title":'Alwaysdata', 'key':'AD_API_KEY'},
{"name":"dns_linode_v4", "title":'Linode', 'key':'LINODE_V4_API_KEY'},
{"name":"dns_freedns", "title":'FreeDNS', 'key':'FREEDNS_User:FREEDNS_Password'},
{"name":"dns_cyon", "title":'cyon.ch', 'key':'CY_Username:CY_Password:CY_OTP_Secret'},
{"name":"dns_gandi_livedns", "title":'LiveDNS', 'key':'GANDI_LIVEDNS_TOKEN'},
{"name":"dns_knot", "title":'Knot', 'key':'KNOT_SERVER:KNOT_KEY'},
{"name":"dns_dgon", "title":'DigitalOcean', 'key':'DO_API_KEY'},
{"name":"dns_cloudns", "title":'ClouDNS.net', 'key':'CLOUDNS_SUB_AUTH_ID:CLOUDNS_AUTH_PASSWORD'},
{"name":"dns_namesilo", "title":'Namesilo', 'key':'Namesilo_Key'},
{"name":"dns_azure", "title":'Azure', 'key':'AZUREDNS_SUBSCRIPTIONID:AZUREDNS_TENANTID:AZUREDNS_APPID:AZUREDNS_CLIENTSECRET'},
{"name":"dns_selectel", "title":'selectel.com', 'key':'SL_Key'},
{"name":"dns_zonomi", "title":'zonomi.com', 'key':'ZM_Key'},
{"name":"dns_kinghost", "title":'KingHost', 'key':'KINGHOST_Username:KINGHOST_Password'},
{"name":"dns_zilore", "title":'Zilore', 'key':'Zilore_Key'},
{"name":"dns_gcloud", "title":'Google Cloud DNS', 'key':'CLOUDSDK_ACTIVE_CONFIG_NAME'},
{"name":"dns_mydnsjp", "title":'MyDNS.JP', 'key':'MYDNSJP_MasterID:MYDNSJP_Password'},
{"name":"dns_doapi", "title":'do.de', 'key':'DO_LETOKEN'},
{"name":"dns_online", "title":'Online', 'key':'ONLINE_API_KEY'},
{"name":"dns_cn", "title":'Core-Networks', 'key':'CN_User:CN_Password'},
{"name":"dns_ultra", "title":'UltraDNS', 'key':'ULTRA_USR:ULTRA_PWD'},
{"name":"dns_hetzner", "title":'Hetzner', 'key':'HETZNER_Token'},
{"name":"dns_ddnss", "title":'DDNSS.de', 'key':'DDNSS_Token'},
];
function getDnsapiKey(name){
for (var i = 0; i < dnsapi_option.length; i++) {
if (dnsapi_option[i]['name'] == name){
return dnsapi_option[i]['key'];
}
}
return '';
}
function getDnsapiTitle(name){
for (var i = 0; i < dnsapi_option.length; i++) {
if (dnsapi_option[i]['name'] == name){
return dnsapi_option[i]['title'];
}
}
return '其他';
}
function dnsapiAdd(row){
// console.log(row);
var option_name = '';
var option_remark = '';
var option_type = 'cf';
var option_val = '';
var option_id = 0;
if (typeof(row) != 'undefined'){
option_name = row['name'];
option_remark = row['remark'];
option_type = row['type'];
option_val = row['val'];
option_id = row['id'];
}
// console.log(option_name);
function renderDnsapiOption(name, val){
var vlist = {};
if (val != ''){
var t = val.split('~');
for (var i = 0; i < t.length; i++) {
var kv = t[i].split('|');
if (kv.length == 2){
vlist[kv[0]] = kv[1];
} else {
vlist[kv[0]] = '';
}
}
// console.log(vlist);
}
var key = getDnsapiKey(name);
var klist = key.split(':');
// console.log(klist);
var option_html = '';
for (var i = 0; i < klist.length; i++) {
var klist_val = '';
if (klist[i] in vlist){
klist_val = vlist[klist[i]];
}
option_html += "\
<span class='tname'>"+klist[i]+"</span>\
<div class='info-r'>\
<input name='"+klist[i]+"' class='bt-input-text mr5' style='width:100%;' value='"+klist_val+"' placeholder='请输入对应值' type='text'>\
</div>";
}
$('#dnsapi_option').html(option_html);
}
layer.open({
type: 1,
area: '500px',
title: '添加DNSAPI',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='dnsapi_add'>\
<div class='line'>\
<span class='tname'>名称</span>\
<div class='info-r'><input name='name' class='bt-input-text mr5' style='width:100%;' placeholder='名称' value='"+option_name+"' type='text'></div>\
</div>\
<div class='line'>\
<span class='tname'>DNSAPI类型</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='type'>\
<option name='cf'>cloudflare</option>\
</select>\
</div>\
</div>\
<div class='line' id='dnsapi_option'>\
<span class='tname'>CF_Key</span>\
<div class='info-r'>\
<input name='v1' class='bt-input-text mr5' style='width:100%;' placeholder='请输入对应值' type='text'>\
</div>\
<span class='tname'>CF_Email</span>\
<div class='info-r'>\
<input name='v2' class='bt-input-text mr5' style='width:100%;' placeholder='请输入对应值' type='text'>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>备注</span>\
<div class='info-r'><input name='remark' class='bt-input-text mr5' style='width:100%;' placeholder='备注' value='"+option_remark+"' type='text'></div>\
</div>\
<input name='id' value='"+option_id+"' type='hidden'>\
</form>",
success:function(){
$("input[name='name']").keyup(function(){
var v = $(this).val();
$("input[name='remark']").val(v);
});
var option = '';
for (var i = 0; i<dnsapi_option.length; i++) {
if (dnsapi_option[i]['name'] == option_type){
option += "<option value='"+dnsapi_option[i]['name']+"' key='"+dnsapi_option[i]['key']+"' selected>"+dnsapi_option[i]['title']+"</option>";
} else {
option += "<option value='"+dnsapi_option[i]['name']+"' key='"+dnsapi_option[i]['key']+"'>"+dnsapi_option[i]['title']+"</option>";
}
}
renderDnsapiOption(option_type, option_val);
$('select[name="type"]').html(option);
$('select[name="type"]').change(function(){
var name = $(this).val();
if (option_type == name){
renderDnsapiOption(name, option_val);
} else {
renderDnsapiOption(name,'');
}
});
},
yes:function(index) {
var data = $("#dnsapi_add").serialize();
data = decodeURIComponent(data);
data = toArrayObject(data);
var key = getDnsapiKey(data['type']);
var klist = key.split(':');
var val = '';
for (var i = 0; i < klist.length; i++) {
var k = klist[i];
if (k in data){
if (klist.length - 1 == i){
val += k + '|' + data[k];
} else {
val += k + '|' + data[k]+'~';
}
}
}
data['val'] = val;
apaPost('dnsapi_add', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
dnsapiList();
}
},{icon: rdata.status ? 1 : 2}, 2000);
});
}
});
}
function dnsapiList(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;
}
apaPost('dnsapi_list', _data, function(data){
var rdata = $.parseJSON(data.data);
var list = '';
for(i in rdata.data){
list += '<tr>';
list +='<td><input value="'+rdata.data[i]['id']+'" class="check" onclick="checkSelect();" type="checkbox"></td>';
list += '<td>' + rdata.data[i]['name'] +'</td>';
list += '<td>' + getDnsapiTitle(rdata.data[i]['type']) +'</td>';
list += '<td>' + rdata.data[i]['val'].split('~').join("<br/>") +'</td>';
list += '<td>' + rdata.data[i]['remark'] +'</td>';
list += '<td style="text-align:right">';
list += '<a href="javascript:;" index="'+i+'" class="btlink edit" title="编辑">编辑</a> | ';
list += '<a href="javascript:;" class="btlink" onclick="dnsapiDel(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['name']+'\')" title="删除">删除</a>';
list += '</td></tr>';
}
var con = '<div class="safe bgw">\
<button onclick="dnsapiAdd()" title="DNSAPI" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加DNSAPI</button>\
<span style="float:right"> \
<button batch="true" style="float: right;display: none;margin-left:10px;" onclick="delDbBatch();" title="删除选中项" class="btn btn-default btn-sm">删除选中</button>\
</span>\
<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr><th width="30"><input class="check" onclick="checkSelect();" type="checkbox"></th>\
<th>名称</th>\
<th>类型</th>\
<th>值</th>\
<th>备注</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>'+ list +'</tbody>\
</table>\
</div>\
<div class="dataTables_paginate paging_bootstrap page"></div>\
</div>\
</div>';
$(".soft-man-con").html(con);
$('.dataTables_paginate').html(rdata.page);
$('.edit').click(function(){
var idx = $(this).attr('index');
var row = rdata.data[idx];
// console.log(row);
dnsapiAdd(row);
})
readerTableChecked();
});
}
function domainDel(id, name){
safeMessage('删除['+name+']','您真的要删除['+name+']吗?',function(){
var data='id='+id+'&name='+name;
apaPost('domain_del', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
domainList();
},{icon: rdata.status ? 1 : 2}, 600);
});
});
}
function domainStatusToggle(id){
var data='id='+id;
apaPost('domain_status_toggle', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
domainList();
},{icon: rdata.status ? 1 : 2}, 600);
});
}
function domainIdCmd(id){
var data='id='+id;
apaPost('get_run_hook_id_cmd', data, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
layer.open({
title: "手动同步命令",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
}
function domainHookCmd(){
apaPost('run_hook_cmd', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.open({
title: "手动同步全部命令",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
}
function syncCfCmd(){
apaPost('run_sync_cf_cmd', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.open({
title: "手动同步CloudFlare全部域名命令",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
}
function syncDnsPodCmd(){
apaPost('run_sync_dnspod_cmd', {}, function(data){
var rdata = $.parseJSON(data.data);
layer.open({
title: "手动同步DnsPod全部域名命令",
area: ['600px', '180px'],
type:1,
closeBtn: 1,
shadeClose: false,
btn:["复制","取消"],
content: '<div class="pd15">\
<div class="divtable">\
<pre class="layui-code">'+rdata.data+'</pre>\
</div>\
</div>',
success:function(){
copyText(rdata.data);
},
yes:function(){
copyText(rdata.data);
}
});
});
}
function domainAdd(row){
var option_domian = '';
var option_remark = '备注';
var option_email = '';
var option_id = 0;
var option_dnsapi_id = 0;
if (typeof(row) != 'undefined'){
option_domian = row['domain'];
option_remark = row['remark'];
option_email = row['email'];
option_id = row['id'];
option_dnsapi_id = row['dnsapi_id'];
}
layer.open({
type: 1,
area: '500px',
title: '添加顶级域名',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:["提交","关闭"],
content: "<form class='bt-form pd20' id='domain_add'>\
<div class='line'>\
<span class='tname'>域名</span>\
<div class='info-r'><input name='domain' class='bt-input-text mr5' style='width:100%;' value='"+option_domian+"' placeholder='域名' type='text'></div>\
</div>\
<div class='line'>\
<span class='tname'>DNSAPI</span>\
<div class='info-r'>\
<select class='bt-input-text mr5' name='dnsapi_id'>\
<option name='0'>无设置</option>\
</select>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>邮件</span>\
<div class='info-r'><input name='email' class='bt-input-text mr5' style='width:100%;' value='"+option_email+"' placeholder='邮件' type='text'></div>\
</div>\
<div class='line'>\
<span class='tname'>备注</span>\
<div class='info-r'><input name='remark' class='bt-input-text mr5' style='width:100%;' value='"+option_remark+"' placeholder='备注' type='text'></div>\
</div>\
<input name='id' value='"+option_id+"' type='hidden'>\
</form>",
success:function(){
// $("input[name='domain']").keyup(function(){
// var v = $(this).val();
// $("input[name='remark']").val(v);
// });
var dnsapi_id_html = "<option value='0'>无设置</option>";
apaPostN('dnsapi_list_all', {}, function(data){
var rdata = $.parseJSON(data.data);
for (var i = 0; i < rdata.length; i++) {
if (option_dnsapi_id == rdata[i]['id']){
dnsapi_id_html += "<option value='"+rdata[i]['id']+"' selected>"+rdata[i]['name']+"</option>";
} else {
dnsapi_id_html += "<option value='"+rdata[i]['id']+"'>"+rdata[i]['name']+"</option>";
}
}
$('select[name="dnsapi_id"]').html(dnsapi_id_html);
});
},
yes:function(index) {
var data = $("#domain_add").serialize();
data = decodeURIComponent(data);
apaPost('domain_add', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
layer.close(index);
domainList();
}
},{icon: rdata.status ? 1 : 2}, 2000);
});
}
});
}
function domainList(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;
}
apaPost('domain_list', _data, function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
var list = '';
for(i in rdata.data){
list += '<tr>';
list +='<td><input value="'+rdata.data[i]['id']+'" class="check" onclick="checkSelect();" type="checkbox"></td>';
list += '<td>' + rdata.data[i]['domain'] +'</td>';
list += '<td>' + rdata.data[i]['dnsapi_id_alias'] +'</td>';
list += '<td>' + rdata.data[i]['email'] +'</td>';
list += '<td>' + rdata.data[i]['remark'] +'</td>';
if (rdata.data[i]['effective_date'] == ''){
list += '<td>空/未申请</td>';
} else {
list += '<td>'+getFormatTime(rdata.data[i]['effective_date'],'yyyy/MM/dd')+'</td>';
}
if (rdata.data[i]['expiration_date'] == ''){
list += '<td>空/未申请</td>';
} else {
list += '<td>'+getFormatTime(rdata.data[i]['expiration_date'],'yyyy/MM/dd')+'</td>';
}
if (rdata.data[i]['status'] == '0'){
list += '<td><a href="javascript:;" index="'+i+'" class="btlink status">否</a></td>';
} else {
list += '<td><a href="javascript:;" index="'+i+'" class="btlink status">是</a></td>';
}
list += '<td style="text-align:right">';
list += '<a href="javascript:;" index="'+i+'" class="btlink cmd" title="命令">命令</a> | ';
list += '<a href="javascript:;" index="'+i+'" class="btlink edit" title="编辑">编辑</a> | ';
list += '<a href="javascript:;" class="btlink" onclick="domainDel(\''+rdata.data[i]['id']+'\',\''+rdata.data[i]['domain']+'\')" title="删除">删除</a>';
list += '</td></tr>';
}
var con = '<div class="safe bgw">\
<button onclick="domainAdd()" title="添加顶级域名" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加域名</button>\
<button onclick="domainHookCmd()" title="全部同步命令" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">全部同步命令</button>\
<button onclick="syncCfCmd()" title="cloudflare同步命令" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">cloudflare同步命令</button>\
<button onclick="syncDnsPodCmd()" title="DnsPod国际同步命令" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">DnsPod国际同步命令</button>\
<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr><th width="30"><input class="check" onclick="checkSelect();" type="checkbox"></th>\
<th>域名</th>\
<th>DNSAPI</th>\
<th>邮件</th>\
<th>备注</th>\
<th>开始</th>\
<th>结束</th>\
<th>同步</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>'+ list +'</tbody>\
</table>\
</div>\
<div class="dataTables_paginate paging_bootstrap page"></div>\
</div>\
</div>';
$(".soft-man-con").html(con);
$('.dataTables_paginate').html(rdata.page);
$('.edit').click(function(){
var idx = $(this).attr('index');
var row = rdata.data[idx];
domainAdd(row);
});
$('.status').click(function(){
var idx = $(this).attr('index');
var row = rdata.data[idx];
domainStatusToggle(row['id']);
});
$('.cmd').click(function(){
var idx = $(this).attr('index');
var row = rdata.data[idx];
domainIdCmd(row['id']);
});
readerTableChecked();
});
}
@@ -0,0 +1,134 @@
# coding:utf-8
import sys
import io
import os
import time
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'acme_pandominassl_apply'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/cron_config.json"
return conf
def getTaskDeltaConf():
conf = getServerDir() + "/cron_delta_config.json"
return conf
def getConfigData():
try:
return json.loads(mw.readFile(getTaskConf()))
except:
pass
return {
"task_id": -1,
"period": "day-n",
"where1": "1",
"hour": "0",
"minute": "15",
}
def createBgTask():
removeBgTask()
createBgTaskByName(getPluginName())
return True
def createBgTaskByName(name):
args = getConfigData()
_name = "[勿删]ACME泛域名SSL[APA]"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in args and args["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (args["task_id"],)).find()
if res and res["id"] == args["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
api = crontab_api.crontab_api()
mw_dir = mw.getRunDir()
cmd = '''
mw_dir=%s
rname=%s
plugin_path=%s
script_path=%s
logs_file=$plugin_path/${rname}.log
''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "python3 $script_path/index.py run_hook"' + "\n"
cmd += 'cd $mw_dir && python3 $script_path/index.py run_hook' + "\n"
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
params = {
'name': _name,
'type': args['period'],
'week': "",
'where1': args['where1'],
'hour': args['hour'],
'minute': args['minute'],
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'urladdress': '',
}
task_id = api.add(params)
if task_id > 0:
args["task_id"] = task_id
args["name"] = name
mw.writeFile(getTaskConf(), json.dumps(args))
def removeBgTask():
cfg = getConfigData()
if "task_id" in cfg and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
mw.writeFile(getTaskConf(), json.dumps(cfg))
return True
return False
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()
+1
View File
@@ -127,6 +127,7 @@ def initConf():
"/var/log/cron",
"/www/wwwlogs",
"/www/server/rsyncd",
"/www/server/acme_pandominassl_apply",
"/www/server/sphinx/index",
"/www/server/mongodb/logs",
"/www/server/php/53/var/log",
+6 -1
View File
@@ -262,7 +262,12 @@ class nosqlMongodbCtr():
# print(where)
result = collection_instance.find(where).skip(start_index).limit(size).sort('_id',-1)
count = collection_instance.count_documents(where)
if where:
count = collection_instance.count_documents(where)
else:
collection_stats = db_instance.command("collStats", collection)
count = collection_stats.get("count")
d = []
for document in result:
d.append(document)
+14
View File
@@ -167,6 +167,19 @@ class nosqlMySQLCtr():
sid = args['sid']
db = args['db']
table = args['table']
if table == '':
page_args = {}
page_args['count'] = 0
page_args['tojs'] = 'mysqlGetDataList'
page_args['p'] = 1
page_args['row'] = 10
rdata = {}
rdata['page'] = mw.getPage(page_args)
rdata['list'] = []
rdata['count'] = 0
return mw.returnData(True,'ok', rdata)
p = 1
size = 10
if 'p' in args:
@@ -223,6 +236,7 @@ class nosqlMySQLCtr():
rdata['soso_field'] = ''
if 'field' in args_where:
rdata['soso_field'] = args_where['field']
return mw.returnData(True,'ok', rdata)
def showProcessList(self,args):
+1 -1
View File
@@ -135,7 +135,7 @@
</div>
</div>
<div class="pull-right" style="padding-top: 5px;">
<div id="mongodb_select" class="pull-right" style="padding-top: 5px;">
<div class="server_list" style="float:left;">
<select name="sid" class="bt-input-text c5 mr5">
<option value="0">本地服务器</option>
+21 -5
View File
@@ -227,7 +227,6 @@ function initTabMongodb(){
}
function initTabMemcached(){
memcachedGetList();
@@ -288,7 +287,11 @@ function mysqlGetDbName(){
}
function mysqlGetTableName(){
return $('#mysql .mysql_table_list select[name=mysql_table]').val();
var table = $('#mysql .mysql_table_list select[name=mysql_table]').val();
if (!table){
return '';
}
return table;
}
function mysqlInitField(f, data){
@@ -397,7 +400,7 @@ function mysqlGetDataList(p){
} else {
request_data['where'] = {};
}
// console.log(request_data);
myPostCB('get_data_list',request_data ,function(rdata){
if (rdata.data.status){
@@ -758,6 +761,7 @@ function mongodbCollectionName(){
function mongodbGetList(){
var sid = mongodbGetSid();
mgdbPostCB('get_db_list',{'sid':sid} ,function(rdata){
// console.log(rdata);
if (rdata.data.status){
var list = rdata.data.data['list'];
var content = '';
@@ -775,6 +779,11 @@ function mongodbGetList(){
mongodbGetCollections(list[0]);
}
$('#mongodb_select .db_list select[name="db"]').change(function(){
var collection_name = $(this).val();
mongodbGetCollections(collection_name);
});
closeInstallLayer();
} else {
showInstallLayer();
@@ -787,6 +796,7 @@ function mongodbGetCollections(name){
var sid = mongodbGetSid();
mgdbPostCB('get_collections_list',{'sid':sid,'name':name} ,function(rdata){
// console.log(rdata);
if (rdata.data.status){
var list = rdata.data.data['collections'];
@@ -817,13 +827,19 @@ function mongodbGetCollections(name){
var isAdd = data.isAdd;
if (isAdd){
$('#mongodb').data('collection',change[0].value);
mongodbDataList(1);
setTimeout(function(){
mongodbDataList(1);
},200);
}
},
});
if (select_list.length > 0){
mongodbDataList(1);
setTimeout(function(){
mongodbDataList(1);
},200);
}
}
});
+594
View File
@@ -0,0 +1,594 @@
[INCLUDES]
before = paths-debian.conf
[DEFAULT]
backend = systemd
ignorecommand =
bantime = 10m
findtime = 10m
maxretry = 5
maxmatches = %(maxretry)s
usedns = warn
logencoding = auto
enabled = false
mode = normal
filter = %(__name__)s[mode=%(mode)s]
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
protocol = tcp
chain = <known/chain>
port = 0:65535
fail2ban_agent = Fail2Ban/%(fail2ban_version)s
banaction = iptables-multiport
banaction_allports = iptables-allports
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mw = %(action_)s
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mwl = %(action_)s
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
action_xarf = %(action_)s
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]
action_abuseipdb = abuseipdb
action = %(action_)s
[sshd]
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
[dropbear]
port = ssh
logpath = %(dropbear_log)s
backend = %(dropbear_backend)s
[selinux-ssh]
port = ssh
logpath = %(auditd_log)s
[apache-auth]
port = http,https
logpath = %(apache_error_log)s
[apache-badbots]
port = http,https
logpath = %(apache_access_log)s
bantime = 48h
maxretry = 1
[apache-noscript]
port = http,https
logpath = %(apache_error_log)s
[apache-overflows]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-nohome]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-botsearch]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-fakegooglebot]
port = http,https
logpath = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>
[apache-modsecurity]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-shellshock]
port = http,https
logpath = %(apache_error_log)s
maxretry = 1
[openhab-auth]
filter = openhab
banaction = %(banaction_allports)s
logpath = /opt/openhab/logs/request.log
[nginx-http-auth]
port = http,https
logpath = %(nginx_error_log)s
[nginx-limit-req]
port = http,https
logpath = %(nginx_error_log)s
[nginx-botsearch]
port = http,https
logpath = %(nginx_error_log)s
maxretry = 2
[php-url-fopen]
port = http,https
logpath = %(nginx_access_log)s
%(apache_access_log)s
[suhosin]
port = http,https
logpath = %(suhosin_log)s
[lighttpd-auth]
port = http,https
logpath = %(lighttpd_error_log)s
[roundcube-auth]
port = http,https
logpath = %(roundcube_errors_log)s
[openwebmail]
port = http,https
logpath = /var/log/openwebmail.log
[horde]
port = http,https
logpath = /var/log/horde/horde.log
[groupoffice]
port = http,https
logpath = /home/groupoffice/log/info.log
[sogo-auth]
port = http,https
logpath = /var/log/sogo/sogo.log
[tine20]
logpath = /var/log/tine20/tine20.log
port = http,https
[drupal-auth]
port = http,https
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
[guacamole]
port = http,https
logpath = /var/log/tomcat*/catalina.out
[monit]
port = 2812
logpath = /var/log/monit
/var/log/monit.log
[webmin-auth]
port = 10000
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[froxlor-auth]
port = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[squid]
port = 80,443,3128,8080
logpath = /var/log/squid/access.log
[3proxy]
port = 3128
logpath = /var/log/3proxy.log
[proftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(proftpd_log)s
backend = %(proftpd_backend)s
[pure-ftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(pureftpd_log)s
backend = %(pureftpd_backend)s
[gssftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
[wuftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(wuftpd_log)s
backend = %(wuftpd_backend)s
[vsftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(vsftpd_log)s
[assp]
port = smtp,465,submission
logpath = /root/path/to/assp/logs/maillog.txt
[courier-smtp]
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[postfix]
mode = more
port = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s
[postfix-rbl]
filter = postfix[mode=rbl]
port = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s
maxretry = 1
[sendmail-auth]
port = submission,465,smtp
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[sendmail-reject]
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[qmail-rbl]
filter = qmail
port = smtp,465,submission
logpath = /service/qmail/log/main/current
[dovecot]
port = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
[sieve]
port = smtp,465,submission
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
[solid-pop3d]
port = pop3,pop3s
logpath = %(solidpop3d_log)s
[exim]
port = smtp,465,submission
logpath = %(exim_main_log)s
[exim-spam]
port = smtp,465,submission
logpath = %(exim_main_log)s
[kerio]
port = imap,smtp,imaps,465
logpath = /opt/kerio/mailserver/store/logs/security.log
[courier-auth]
port = smtp,465,submission,imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[postfix-sasl]
filter = postfix[mode=auth]
port = smtp,465,submission,imap,imaps,pop3,pop3s
logpath = %(postfix_log)s
backend = %(postfix_backend)s
[perdition]
port = imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[squirrelmail]
port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log
[cyrus-imap]
port = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[uwimap-auth]
port = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[named-refused]
port = domain,953
logpath = /var/log/named/security.log
[nsd]
port = 53
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/nsd.log
[asterisk]
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/asterisk/messages
maxretry = 10
[freeswitch]
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/freeswitch.log
maxretry = 10
[znc-adminlog]
port = 6667
logpath = /var/lib/znc/moddata/adminlog/znc.log
[mysqld-auth]
port = 3306
logpath = %(mysql_log)s
backend = %(mysql_backend)s
[mongodb-auth]
port = 27017
logpath = /var/log/mongodb/mongodb.log
[recidive]
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime = 1w
findtime = 1d
[pam-generic]
banaction = %(banaction_allports)s
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[xinetd-fail]
banaction = iptables-multiport-log
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
maxretry = 2
[stunnel]
logpath = /var/log/stunnel4/stunnel.log
[ejabberd-auth]
port = 5222
logpath = /var/log/ejabberd/ejabberd.log
[counter-strike]
logpath = /opt/cstrike/logs/L[0-9]*.log
tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039
udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015
action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"]
[softethervpn]
port = 500,4500
protocol = udp
logpath = /usr/local/vpnserver/security_log/*/sec.log
[gitlab]
port = http,https
logpath = /var/log/gitlab/gitlab-rails/application.log
[grafana]
port = http,https
logpath = /var/log/grafana/grafana.log
[bitwarden]
port = http,https
logpath = /home/*/bwdata/logs/identity/Identity/log.txt
[centreon]
port = http,https
logpath = /var/log/centreon/login.log
[nagios]
logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility
backend = %(syslog_backend)s
maxretry = 1
[oracleims]
logpath = /opt/sun/comms/messaging64/log/mail.log_current
banaction = %(banaction_allports)s
[directadmin]
logpath = /var/log/directadmin/login.log
port = 2222
[portsentry]
logpath = /var/lib/portsentry/portsentry.history
maxretry = 1
[pass2allow-ftp]
port = ftp,ftp-data,ftps,ftps-data
knocking_url = /knocking/
filter = apache-pass[knocking_url="%(knocking_url)s"]
logpath = %(apache_access_log)s
blocktype = RETURN
returntype = DROP
action = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s,
actionstart_on_demand=false, actionrepair_on_unban=true]
bantime = 1h
maxretry = 1
findtime = 1
[murmur]
port = 64738
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/mumble-server/mumble-server.log
[screensharingd]
logpath = /var/log/system.log
logencoding = utf-8
[haproxy-http-auth]
logpath = /var/log/haproxy.log
[slapd]
port = ldap,ldaps
logpath = /var/log/slapd.log
[domino-smtp]
port = smtp,ssmtp
logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log
[phpmyadmin-syslog]
port = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[zoneminder]
port = http,https
logpath = %(apache_error_log)s
[traefik-auth]
port = http,https
logpath = /var/log/traefik/access.log
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

+30
View File
@@ -0,0 +1,30 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('fail2ban');">服务</p>
<p onclick="pluginInitD('fail2ban');">自启动</p>
<p onclick="pluginConfigTpl('fail2ban',$('.plugin_version').attr('version'));">配置修改</p>
<!-- <p onclick="getRedisConfig($('.plugin_version').attr('version'));">性能调整</p> -->
<!-- <p onclick="redisStatus($('.plugin_version').attr('version'));">负载状态</p> -->
<p onclick="pluginLogs('fail2ban','','run_log');">运行日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con" style="height: 520px; overflow: auto;"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=fail2ban&f=js/fail2ban.js", function(){
pluginService('fail2ban', $('.plugin_version').attr('version'));
});
</script>
+284
View File
@@ -0,0 +1,284 @@
# 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 'fail2ban'
def f2bDir():
return '/run/fail2ban'
def f2bEtcDir():
return '/etc/fail2ban'
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 = f2bEtcDir() + "/fail2ban.conf"
return path
def getConfTpl():
path = getPluginDir() + "/config/redis.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 = f2bEtcDir()
pathFile = os.listdir(path)
tmp = []
for one in pathFile:
if one.endswith("conf"):
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 runLog():
return '/var/log/fail2ban.log'
def getPidFile():
f2dir = f2bDir()
return f2dir+'/fail2ban.pid'
def status():
pid_file = getPidFile()
if not os.path.exists(pid_file):
return 'stop'
return 'start'
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
return content
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 = content.replace('{$SERVER_PATH}', service_path)
# mw.writeFile(file_bin, content)
# mw.execShell('chmod +x ' + file_bin)
# 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()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def f2bOp(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 f2bOp('start')
def stop():
return f2bOp('stop')
def restart():
status = f2bOp('restart')
log_file = runLog()
mw.execShell("echo '' > " + log_file)
return status
def reload():
return f2bOp('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"
# 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'
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 == 'read_config_tpl':
print(readConfigTpl())
else:
print('error')
+18
View File
@@ -0,0 +1,18 @@
{
"sort": 7,
"ps": "防止恶意IP地址暴力破解服务、站点,禁止导致多个身份验证错误的主机",
"name": "fail2ban",
"title": "fail2ban",
"shell": "install.sh",
"versions":["1.1.0"],
"updates":["1.1.0"],
"tip": "soft",
"checks": "server/fail2ban",
"path": "server/fail2ban",
"display": 1,
"author": "fail2ban",
"date": "2025-07-28",
"home": "https://www.fail2ban.org",
"type": 0,
"pid": "4"
}
@@ -0,0 +1,22 @@
[Unit]
Description=Fail2Ban Service
Documentation=man:fail2ban(1)
After=network.target iptables.service firewalld.service ip6tables.service ipset.service nftables.service
PartOf=firewalld.service
[Service]
Type=simple
Environment="PYTHONNOUSERSITE=1"
ExecStartPre=/bin/mkdir -p /run/fail2ban
ExecStart=/usr/bin/fail2ban-server -xf start
# if should be logged in systemd journal, use following line or set logtarget to sysout in fail2ban.local
# ExecStart=/usr/bin/fail2ban-server -xf --logtarget=sysout start
ExecStop=/usr/bin/fail2ban-client stop
ExecReload=/usr/bin/fail2ban-client reload
PIDFile=/run/fail2ban/fail2ban.pid
Restart=on-failure
RestartPreventExitStatus=0 255
Environment="PYTHONNOUSERSITE=yes"
[Install]
WantedBy=multi-user.target
+66
View File
@@ -0,0 +1,66 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
export DEBIAN_FRONTEND=noninteractive
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
# cd /www/server/mdserver-web/plugins/fail2ban && bash install.sh install 1.1.0
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
apt install -y fail2ban
mkdir -p $serverPath/fail2ban
echo "${VERSION}" > $serverPath/fail2ban/version.pl
echo '安装fail2ban完成'
cd ${rootPath} && python3 ${rootPath}/plugins/fail2ban/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/fail2ban/index.py initd_install
}
Uninstall_App()
{
apt remove -y fail2ban
if [ -f /usr/lib/systemd/system/fail2ban.service ];then
systemctl stop fail2ban
systemctl disable fail2ban
rm -rf /usr/lib/systemd/system/fail2ban.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/fail2ban.service ];then
systemctl stop fail2ban
systemctl disable fail2ban
rm -rf /lib/systemd/system/fail2ban.service
systemctl daemon-reload
fi
if [ -f $serverPath/fail2ban/initd/fail2ban ];then
$serverPath/fail2ban/initd/fail2ban stop
fi
if [ -d $serverPath/fail2ban ];then
rm -rf $serverPath/fail2ban
fi
echo "卸载fail2ban成功"
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+54
View File
@@ -0,0 +1,54 @@
function f2bPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'fail2ban';
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 f2bPostCallbak(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'fail2ban';
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');
}
+594
View File
@@ -0,0 +1,594 @@
[INCLUDES]
before = paths-debian.conf
[DEFAULT]
backend = systemd
ignorecommand =
bantime = 10m
findtime = 10m
maxretry = 5
maxmatches = %(maxretry)s
usedns = warn
logencoding = auto
enabled = false
mode = normal
filter = %(__name__)s[mode=%(mode)s]
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
protocol = tcp
chain = <known/chain>
port = 0:65535
fail2ban_agent = Fail2Ban/%(fail2ban_version)s
banaction = iptables-multiport
banaction_allports = iptables-allports
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mw = %(action_)s
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mwl = %(action_)s
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
action_xarf = %(action_)s
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]
action_abuseipdb = abuseipdb
action = %(action_)s
[sshd]
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
[dropbear]
port = ssh
logpath = %(dropbear_log)s
backend = %(dropbear_backend)s
[selinux-ssh]
port = ssh
logpath = %(auditd_log)s
[apache-auth]
port = http,https
logpath = %(apache_error_log)s
[apache-badbots]
port = http,https
logpath = %(apache_access_log)s
bantime = 48h
maxretry = 1
[apache-noscript]
port = http,https
logpath = %(apache_error_log)s
[apache-overflows]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-nohome]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-botsearch]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-fakegooglebot]
port = http,https
logpath = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>
[apache-modsecurity]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-shellshock]
port = http,https
logpath = %(apache_error_log)s
maxretry = 1
[openhab-auth]
filter = openhab
banaction = %(banaction_allports)s
logpath = /opt/openhab/logs/request.log
[nginx-http-auth]
port = http,https
logpath = %(nginx_error_log)s
[nginx-limit-req]
port = http,https
logpath = %(nginx_error_log)s
[nginx-botsearch]
port = http,https
logpath = %(nginx_error_log)s
maxretry = 2
[php-url-fopen]
port = http,https
logpath = %(nginx_access_log)s
%(apache_access_log)s
[suhosin]
port = http,https
logpath = %(suhosin_log)s
[lighttpd-auth]
port = http,https
logpath = %(lighttpd_error_log)s
[roundcube-auth]
port = http,https
logpath = %(roundcube_errors_log)s
[openwebmail]
port = http,https
logpath = /var/log/openwebmail.log
[horde]
port = http,https
logpath = /var/log/horde/horde.log
[groupoffice]
port = http,https
logpath = /home/groupoffice/log/info.log
[sogo-auth]
port = http,https
logpath = /var/log/sogo/sogo.log
[tine20]
logpath = /var/log/tine20/tine20.log
port = http,https
[drupal-auth]
port = http,https
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
[guacamole]
port = http,https
logpath = /var/log/tomcat*/catalina.out
[monit]
port = 2812
logpath = /var/log/monit
/var/log/monit.log
[webmin-auth]
port = 10000
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[froxlor-auth]
port = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[squid]
port = 80,443,3128,8080
logpath = /var/log/squid/access.log
[3proxy]
port = 3128
logpath = /var/log/3proxy.log
[proftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(proftpd_log)s
backend = %(proftpd_backend)s
[pure-ftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(pureftpd_log)s
backend = %(pureftpd_backend)s
[gssftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
[wuftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(wuftpd_log)s
backend = %(wuftpd_backend)s
[vsftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(vsftpd_log)s
[assp]
port = smtp,465,submission
logpath = /root/path/to/assp/logs/maillog.txt
[courier-smtp]
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[postfix]
mode = more
port = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s
[postfix-rbl]
filter = postfix[mode=rbl]
port = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s
maxretry = 1
[sendmail-auth]
port = submission,465,smtp
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[sendmail-reject]
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[qmail-rbl]
filter = qmail
port = smtp,465,submission
logpath = /service/qmail/log/main/current
[dovecot]
port = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
[sieve]
port = smtp,465,submission
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
[solid-pop3d]
port = pop3,pop3s
logpath = %(solidpop3d_log)s
[exim]
port = smtp,465,submission
logpath = %(exim_main_log)s
[exim-spam]
port = smtp,465,submission
logpath = %(exim_main_log)s
[kerio]
port = imap,smtp,imaps,465
logpath = /opt/kerio/mailserver/store/logs/security.log
[courier-auth]
port = smtp,465,submission,imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[postfix-sasl]
filter = postfix[mode=auth]
port = smtp,465,submission,imap,imaps,pop3,pop3s
logpath = %(postfix_log)s
backend = %(postfix_backend)s
[perdition]
port = imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[squirrelmail]
port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log
[cyrus-imap]
port = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[uwimap-auth]
port = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[named-refused]
port = domain,953
logpath = /var/log/named/security.log
[nsd]
port = 53
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/nsd.log
[asterisk]
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/asterisk/messages
maxretry = 10
[freeswitch]
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/freeswitch.log
maxretry = 10
[znc-adminlog]
port = 6667
logpath = /var/lib/znc/moddata/adminlog/znc.log
[mysqld-auth]
port = 3306
logpath = %(mysql_log)s
backend = %(mysql_backend)s
[mongodb-auth]
port = 27017
logpath = /var/log/mongodb/mongodb.log
[recidive]
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime = 1w
findtime = 1d
[pam-generic]
banaction = %(banaction_allports)s
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[xinetd-fail]
banaction = iptables-multiport-log
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
maxretry = 2
[stunnel]
logpath = /var/log/stunnel4/stunnel.log
[ejabberd-auth]
port = 5222
logpath = /var/log/ejabberd/ejabberd.log
[counter-strike]
logpath = /opt/cstrike/logs/L[0-9]*.log
tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039
udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015
action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"]
[softethervpn]
port = 500,4500
protocol = udp
logpath = /usr/local/vpnserver/security_log/*/sec.log
[gitlab]
port = http,https
logpath = /var/log/gitlab/gitlab-rails/application.log
[grafana]
port = http,https
logpath = /var/log/grafana/grafana.log
[bitwarden]
port = http,https
logpath = /home/*/bwdata/logs/identity/Identity/log.txt
[centreon]
port = http,https
logpath = /var/log/centreon/login.log
[nagios]
logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility
backend = %(syslog_backend)s
maxretry = 1
[oracleims]
logpath = /opt/sun/comms/messaging64/log/mail.log_current
banaction = %(banaction_allports)s
[directadmin]
logpath = /var/log/directadmin/login.log
port = 2222
[portsentry]
logpath = /var/lib/portsentry/portsentry.history
maxretry = 1
[pass2allow-ftp]
port = ftp,ftp-data,ftps,ftps-data
knocking_url = /knocking/
filter = apache-pass[knocking_url="%(knocking_url)s"]
logpath = %(apache_access_log)s
blocktype = RETURN
returntype = DROP
action = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s,
actionstart_on_demand=false, actionrepair_on_unban=true]
bantime = 1h
maxretry = 1
findtime = 1
[murmur]
port = 64738
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/mumble-server/mumble-server.log
[screensharingd]
logpath = /var/log/system.log
logencoding = utf-8
[haproxy-http-auth]
logpath = /var/log/haproxy.log
[slapd]
port = ldap,ldaps
logpath = /var/log/slapd.log
[domino-smtp]
port = smtp,ssmtp
logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log
[phpmyadmin-syslog]
port = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[zoneminder]
port = http,https
logpath = %(apache_error_log)s
[traefik-auth]
port = http,https
logpath = /var/log/traefik/access.log
+964
View File
@@ -0,0 +1,964 @@
#
# WARNING: heavily refactored in 0.9.0 release. Please review and
# customize settings for your setup.
#
# Changes: in most of the cases you should not modify this
# file, but provide customizations in jail.local file,
# or separate .conf files under jail.d/ directory, e.g.:
#
# HOW TO ACTIVATE JAILS:
#
# YOU SHOULD NOT MODIFY THIS FILE.
#
# It will probably be overwritten or improved in a distribution update.
#
# Provide customizations in a jail.local file or a jail.d/customisation.local.
# For example to change the default bantime for all jails and to enable the
# ssh-iptables jail the following (uncommented) would appear in the .local file.
# See man 5 jail.conf for details.
#
# [DEFAULT]
# bantime = 1h
#
# [sshd]
# enabled = true
#
# See jail.conf(5) man page for more information
# Comments: use '#' for comment lines and ';' (following a space) for inline comments
[INCLUDES]
#before = paths-distro.conf
before = paths-debian.conf
# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.
[DEFAULT]
#
# MISCELLANEOUS OPTIONS
#
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
#bantime.increment = true
# "bantime.rndtime" is the max number of seconds using for mixing with random time
# to prevent "clever" botnets calculate exact time IP can be unbanned again:
#bantime.rndtime =
# "bantime.maxtime" is the max number of seconds using the ban time can reach (doesn't grow further)
#bantime.maxtime =
# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
# default value of factor is 1 and with default value of formula, the ban time
# grows by 1, 2, 4, 8, 16 ...
#bantime.factor = 1
# "bantime.formula" used by default to calculate next value of ban time, default value below,
# the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32...
#bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
#
# more aggressive example of formula has the same values only for factor "2.0 / 2.885385" :
#bantime.formula = ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)
# "bantime.multipliers" used to calculate next value of ban time instead of formula, coresponding
# previously ban count and given "bantime.factor" (for multipliers default is 1);
# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
# always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours
#bantime.multipliers = 1 2 4 8 16 32 64
# following example can be used for small initial ban time (bantime=60) - it grows more aggressive at begin,
# for bantime=60 the multipliers are minutes and equal: 1 min, 5 min, 30 min, 1 hour, 5 hour, 12 hour, 1 day, 2 day
#bantime.multipliers = 1 5 30 60 300 720 1440 2880
# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed
# cross over all jails, if false (dafault), only current jail of the ban IP will be searched
#bantime.overalljails = false
# --------------------
# "ignoreself" specifies whether the local resp. own IP addresses should be ignored
# (default is true). Fail2ban will not ban a host which matches such addresses.
#ignoreself = true
# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
# will not ban a host which matches an address in this list. Several addresses
# can be defined using space (and/or comma) separator.
#ignoreip = 127.0.0.1/8 ::1
# External command that will take an tagged arguments to ignore, e.g. <ip>,
# and return true if the IP is to be ignored. False otherwise.
#
# ignorecommand = /path/to/command <ip>
ignorecommand =
# "bantime" is the number of seconds that a host is banned.
bantime = 10m
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 10m
# "maxretry" is the number of failures before a host get banned.
maxretry = 5
# "maxmatches" is the number of matches stored in ticket (resolvable via tag <matches> in actions).
maxmatches = %(maxretry)s
# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
# This option can be overridden in each jail as well.
#
# pyinotify: requires pyinotify (a file alteration monitor) to be installed.
# If pyinotify is not installed, Fail2ban will use auto.
# gamin: requires Gamin (a file alteration monitor) to be installed.
# If Gamin is not installed, Fail2ban will use auto.
# polling: uses a polling algorithm which does not require external libraries.
# systemd: uses systemd python library to access the systemd journal.
# Specifying "logpath" is not valid for this backend.
# See "journalmatch" in the jails associated filter config
# auto: will try to use the following backends, in order:
# pyinotify, gamin, polling.
#
# Note: if systemd backend is chosen as the default but you enable a jail
# for which logs are present only in its own log files, specify some other
# backend for that jail (e.g. polling) and provide empty value for
# journalmatch. See https://github.com/fail2ban/fail2ban/issues/959#issuecomment-74901200
backend = systemd
# "usedns" specifies if jails should trust hostnames in logs,
# warn when DNS lookups are performed, or ignore all hostnames in logs
#
# yes: if a hostname is encountered, a DNS lookup will be performed.
# warn: if a hostname is encountered, a DNS lookup will be performed,
# but it will be logged as a warning.
# no: if a hostname is encountered, will not be used for banning,
# but it will be logged as info.
# raw: use raw value (no hostname), allow use it for no-host filters/actions (example user)
usedns = warn
# "logencoding" specifies the encoding of the log files handled by the jail
# This is used to decode the lines from the log file.
# Typical examples: "ascii", "utf-8"
#
# auto: will use the system locale setting
logencoding = auto
# "enabled" enables the jails.
# By default all jails are disabled, and it should stay this way.
# Enable only relevant to your setup jails in your .local or jail.d/*.conf
#
# true: jail will be enabled and log files will get monitored for changes
# false: jail is not enabled
enabled = false
# "mode" defines the mode of the filter (see corresponding filter implementation for more info).
mode = normal
# "filter" defines the filter to use by the jail.
# By default jails have names matching their filter name
#
filter = %(__name__)s[mode=%(mode)s]
#
# ACTIONS
#
# Some options used for actions
# Destination email address used solely for the interpolations in
# jail.{conf,local,d/*} configuration files.
destemail = root@localhost
# Sender email address used solely for some actions
sender = root@<fq-hostname>
# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the
# mailing. Change mta configuration parameter to mail if you want to
# revert to conventional 'mail'.
mta = sendmail
# Default protocol
protocol = tcp
# Specify chain where jumps would need to be added in ban-actions expecting parameter chain
chain = <known/chain>
# Ports to be banned
# Usually should be overridden in a particular jail
port = 0:65535
# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3
fail2ban_agent = Fail2Ban/%(fail2ban_version)s
#
# Action shortcuts. To be used to define action parameter
# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports
# The simplest action to take: ban only
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report to the destemail.
action_mw = %(action_)s
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(action_)s
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(action_)s
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
# Report block via blocklist.de fail2ban reporting service API
#
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in
# corresponding jail.d/my-jail.local file).
#
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
# Report ban via badips.com, and use as blacklist
#
# See BadIPsAction docstring in config/action.d/badips.py for
# documentation for this action.
#
# NOTE: This action relies on banaction being present on start and therefore
# should be last action defined for a jail.
#
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
#
# Report ban via badips.com (uses action.d/badips.conf for reporting only)
#
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]
# Report ban via abuseipdb.com.
#
# See action.d/abuseipdb.conf for usage example and details.
#
action_abuseipdb = abuseipdb
# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
#
# JAILS
#
#
# SSH servers
#
[sshd]
# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode = normal
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
[dropbear]
port = ssh
logpath = %(dropbear_log)s
backend = %(dropbear_backend)s
[selinux-ssh]
port = ssh
logpath = %(auditd_log)s
#
# HTTP servers
#
[apache-auth]
port = http,https
logpath = %(apache_error_log)s
[apache-badbots]
# Ban hosts which agent identifies spammer robots crawling the web
# for email addresses. The mail outputs are buffered.
port = http,https
logpath = %(apache_access_log)s
bantime = 48h
maxretry = 1
[apache-noscript]
port = http,https
logpath = %(apache_error_log)s
[apache-overflows]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-nohome]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-botsearch]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-fakegooglebot]
port = http,https
logpath = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>
[apache-modsecurity]
port = http,https
logpath = %(apache_error_log)s
maxretry = 2
[apache-shellshock]
port = http,https
logpath = %(apache_error_log)s
maxretry = 1
[openhab-auth]
filter = openhab
banaction = %(banaction_allports)s
logpath = /opt/openhab/logs/request.log
[nginx-http-auth]
port = http,https
logpath = %(nginx_error_log)s
# To use 'nginx-limit-req' jail you should have `ngx_http_limit_req_module`
# and define `limit_req` and `limit_req_zone` as described in nginx documentation
# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
# or for example see in 'config/filter.d/nginx-limit-req.conf'
[nginx-limit-req]
port = http,https
logpath = %(nginx_error_log)s
[nginx-botsearch]
port = http,https
logpath = %(nginx_error_log)s
maxretry = 2
# Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year
# of usage in production environments.
[php-url-fopen]
port = http,https
logpath = %(nginx_access_log)s
%(apache_access_log)s
[suhosin]
port = http,https
logpath = %(suhosin_log)s
[lighttpd-auth]
# Same as above for Apache's mod_auth
# It catches wrong authentifications
port = http,https
logpath = %(lighttpd_error_log)s
#
# Webmail and groupware servers
#
[roundcube-auth]
port = http,https
logpath = %(roundcube_errors_log)s
# Use following line in your jail.local if roundcube logs to journal.
#backend = %(syslog_backend)s
[openwebmail]
port = http,https
logpath = /var/log/openwebmail.log
[horde]
port = http,https
logpath = /var/log/horde/horde.log
[groupoffice]
port = http,https
logpath = /home/groupoffice/log/info.log
[sogo-auth]
# Monitor SOGo groupware server
# without proxy this would be:
# port = 20000
port = http,https
logpath = /var/log/sogo/sogo.log
[tine20]
logpath = /var/log/tine20/tine20.log
port = http,https
#
# Web Applications
#
#
[drupal-auth]
port = http,https
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
[guacamole]
port = http,https
logpath = /var/log/tomcat*/catalina.out
#logpath = /var/log/guacamole.log
[monit]
#Ban clients brute-forcing the monit gui login
port = 2812
logpath = /var/log/monit
/var/log/monit.log
[webmin-auth]
port = 10000
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[froxlor-auth]
port = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
#
# HTTP Proxy servers
#
#
[squid]
port = 80,443,3128,8080
logpath = /var/log/squid/access.log
[3proxy]
port = 3128
logpath = /var/log/3proxy.log
#
# FTP servers
#
[proftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(proftpd_log)s
backend = %(proftpd_backend)s
[pure-ftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(pureftpd_log)s
backend = %(pureftpd_backend)s
[gssftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
[wuftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = %(wuftpd_log)s
backend = %(wuftpd_backend)s
[vsftpd]
# or overwrite it in jails.local to be
# logpath = %(syslog_authpriv)s
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
port = ftp,ftp-data,ftps,ftps-data
logpath = %(vsftpd_log)s
#
# Mail servers
#
# ASSP SMTP Proxy Jail
[assp]
port = smtp,465,submission
logpath = /root/path/to/assp/logs/maillog.txt
[courier-smtp]
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[postfix]
# To use another modes set filter parameter "mode" in jail.local:
mode = more
port = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s
[postfix-rbl]
filter = postfix[mode=rbl]
port = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s
maxretry = 1
[sendmail-auth]
port = submission,465,smtp
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[sendmail-reject]
# To use more aggressive modes set filter parameter "mode" in jail.local:
# normal (default), extra or aggressive
# See "tests/files/logs/sendmail-reject" or "filter.d/sendmail-reject.conf" for usage example and details.
#mode = normal
port = smtp,465,submission
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[qmail-rbl]
filter = qmail
port = smtp,465,submission
logpath = /service/qmail/log/main/current
# dovecot defaults to logging to the mail syslog facility
# but can be set by syslog_facility in the dovecot configuration.
[dovecot]
port = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
[sieve]
port = smtp,465,submission
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
[solid-pop3d]
port = pop3,pop3s
logpath = %(solidpop3d_log)s
[exim]
# see filter.d/exim.conf for further modes supported from filter:
#mode = normal
port = smtp,465,submission
logpath = %(exim_main_log)s
[exim-spam]
port = smtp,465,submission
logpath = %(exim_main_log)s
[kerio]
port = imap,smtp,imaps,465
logpath = /opt/kerio/mailserver/store/logs/security.log
#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#
[courier-auth]
port = smtp,465,submission,imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[postfix-sasl]
filter = postfix[mode=auth]
port = smtp,465,submission,imap,imaps,pop3,pop3s
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath = %(postfix_log)s
backend = %(postfix_backend)s
[perdition]
port = imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[squirrelmail]
port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log
[cyrus-imap]
port = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
[uwimap-auth]
port = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s
#
#
# DNS servers
#
# !!! WARNING !!!
# Since UDP is connection-less protocol, spoofing of IP and imitation
# of illegal actions is way too simple. Thus enabling of this filter
# might provide an easy way for implementing a DoS against a chosen
# victim. See
# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html
# Please DO NOT USE this jail unless you know what you are doing.
#
# IMPORTANT: see filter.d/named-refused for instructions to enable logging
# This jail blocks UDP traffic for DNS requests.
# [named-refused-udp]
#
# filter = named-refused
# port = domain,953
# protocol = udp
# logpath = /var/log/named/security.log
# IMPORTANT: see filter.d/named-refused for instructions to enable logging
# This jail blocks TCP traffic for DNS requests.
[named-refused]
port = domain,953
logpath = /var/log/named/security.log
[nsd]
port = 53
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/nsd.log
#
# Miscellaneous
#
[asterisk]
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/asterisk/messages
maxretry = 10
[freeswitch]
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/freeswitch.log
maxretry = 10
# enable adminlog; it will log to a file inside znc's directory by default.
[znc-adminlog]
port = 6667
logpath = /var/lib/znc/moddata/adminlog/znc.log
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld] or
# equivalent section:
# log-warnings = 2
#
# for syslog (daemon facility)
# [mysqld_safe]
# syslog
#
# for own logfile
# [mysqld]
# log-error=/var/log/mysqld.log
[mysqld-auth]
port = 3306
logpath = %(mysql_log)s
backend = %(mysql_backend)s
# Log wrong MongoDB auth (for details see filter 'filter.d/mongodb-auth.conf')
[mongodb-auth]
# change port when running with "--shardsvr" or "--configsvr" runtime operation
port = 27017
logpath = /var/log/mongodb/mongodb.log
# Jail for more extended banning of persistent abusers
# !!! WARNINGS !!!
# 1. Make sure that your loglevel specified in fail2ban.conf/.local
# is not at DEBUG level -- which might then cause fail2ban to fall into
# an infinite loop constantly feeding itself with non-informative lines
# 2. Increase dbpurgeage defined in fail2ban.conf to e.g. 648000 (7.5 days)
# to maintain entries for failed logins for sufficient amount of time
[recidive]
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime = 1w
findtime = 1d
# Generic filter for PAM. Has to be used with action which bans all
# ports such as iptables-allports, shorewall
[pam-generic]
# pam-generic filter can be customized to monitor specific subset of 'tty's
banaction = %(banaction_allports)s
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[xinetd-fail]
banaction = iptables-multiport-log
logpath = %(syslog_daemon)s
backend = %(syslog_backend)s
maxretry = 2
# stunnel - need to set port for this
[stunnel]
logpath = /var/log/stunnel4/stunnel.log
[ejabberd-auth]
port = 5222
logpath = /var/log/ejabberd/ejabberd.log
[counter-strike]
logpath = /opt/cstrike/logs/L[0-9]*.log
tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039
udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015
action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"]
[softethervpn]
port = 500,4500
protocol = udp
logpath = /usr/local/vpnserver/security_log/*/sec.log
[gitlab]
port = http,https
logpath = /var/log/gitlab/gitlab-rails/application.log
[grafana]
port = http,https
logpath = /var/log/grafana/grafana.log
[bitwarden]
port = http,https
logpath = /home/*/bwdata/logs/identity/Identity/log.txt
[centreon]
port = http,https
logpath = /var/log/centreon/login.log
# consider low maxretry and a long bantime
# nobody except your own Nagios server should ever probe nrpe
[nagios]
logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility
backend = %(syslog_backend)s
maxretry = 1
[oracleims]
# see "oracleims" filter file for configuration requirement for Oracle IMS v6 and above
logpath = /opt/sun/comms/messaging64/log/mail.log_current
banaction = %(banaction_allports)s
[directadmin]
logpath = /var/log/directadmin/login.log
port = 2222
[portsentry]
logpath = /var/lib/portsentry/portsentry.history
maxretry = 1
[pass2allow-ftp]
# this pass2allow example allows FTP traffic after successful HTTP authentication
port = ftp,ftp-data,ftps,ftps-data
# knocking_url variable must be overridden to some secret value in jail.local
knocking_url = /knocking/
filter = apache-pass[knocking_url="%(knocking_url)s"]
# access log of the website with HTTP auth
logpath = %(apache_access_log)s
blocktype = RETURN
returntype = DROP
action = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s,
actionstart_on_demand=false, actionrepair_on_unban=true]
bantime = 1h
maxretry = 1
findtime = 1
[murmur]
# AKA mumble-server
port = 64738
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/mumble-server/mumble-server.log
[screensharingd]
# For Mac OS Screen Sharing Service (VNC)
logpath = /var/log/system.log
logencoding = utf-8
[haproxy-http-auth]
# HAProxy by default doesn't log to file you'll need to set it up to forward
# logs to a syslog server which would then write them to disk.
# See "haproxy-http-auth" filter for a brief cautionary note when setting
# maxretry and findtime.
logpath = /var/log/haproxy.log
[slapd]
port = ldap,ldaps
logpath = /var/log/slapd.log
[domino-smtp]
port = smtp,ssmtp
logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log
[phpmyadmin-syslog]
port = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s
[zoneminder]
# Zoneminder HTTP/HTTPS web interface auth
# Logs auth failures to apache2 error log
port = http,https
logpath = %(apache_error_log)s
[traefik-auth]
# to use 'traefik-auth' filter you have to configure your Traefik instance,
# see `filter.d/traefik-auth.conf` for details and service example.
port = http,https
logpath = /var/log/traefik/access.log
+6
View File
@@ -16,6 +16,10 @@ fi
git config --global credential.helper store
git config --global pull.rebase false
if [ ! -d $GIT_PROJECT_DIR ];then
git config --global --add safe.directory $GIT_PROJECT_DIR
fi
# echo $GIT_PROJECT_DIR
if [ ! -d $GIT_PROJECT_DIR ];then
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
@@ -24,6 +28,8 @@ fi
unset GIT_DIR
cd $GIT_PROJECT_DIR && git pull
# func 2
+10 -3
View File
@@ -5,7 +5,7 @@ import time
import os
import sys
import re
import subprocess
sys.path.append(os.getcwd() + "/class/core")
import mw
@@ -138,6 +138,8 @@ def initDreplace():
git_dir = mw.getServerDir() + '/git'
if not os.path.exists(git_dir):
mw.execShell('mkdir -p ' + git_dir)
mw.execShell('chown -R www:www ' + git_dir)
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
@@ -762,8 +764,13 @@ def projectScriptRun():
if not os.path.exists(commit_sh):
return mw.returnJson(False, '脚本文件不存在!')
mw.execShell(script_run)
mw.execShell('chown -R www:www ' + commit_log)
repo_dir = mw.getServerDir()+'/git/'+ args['name']
# mw.execShell(script_run)
subprocess.Popen(script_run, stdout=subprocess.PIPE, shell=True,
bufsize=4096, stderr=subprocess.PIPE)
subprocess.Popen('chown -R www:www ' + repo_dir, stdout=subprocess.PIPE, shell=True,
bufsize=4096, stderr=subprocess.PIPE)
return mw.returnJson(True, '脚本文件执行成功,观察日志!')
+1 -1
View File
@@ -2,7 +2,7 @@
"ps": "Gitea是一个开源社区驱动的轻量级代码托管解决方案。",
"name": "gitea",
"title": "Gitea",
"versions": ["1.17.2","1.18.5"],
"versions": ["1.17.2","1.18.5","1.22.1"],
"tip": "soft",
"install_pre_inspection":false,
"uninstall_pre_inspection":true,
+2 -2
View File
@@ -62,7 +62,7 @@ Install_App()
fi
fi
echo '正在安装脚本文件...' > $install_tmp
echo '正在安装脚本文件...'
version=$1
@@ -97,7 +97,7 @@ Install_App()
cd ${rootPath} && python3 plugins/gitea/index.py initd_install
fi
echo 'install success' > $install_tmp
echo 'install success'
}
Uninstall_App()
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+6
View File
@@ -0,0 +1,6 @@
# gorse
推荐系统
# 脚本安装
cd /www/server/mdserver-web/plugins && rm -rf gorse && git clone https://github.com/mw-plugin/gorse && cd gorse && rm -rf .git && cd /www/server/mdserver-web/plugins/gorse && bash install.sh install 0.4.15
+92
View File
@@ -0,0 +1,92 @@
[database]
cache_store = "{$CONFIG_REDIS}"
data_store = "mongodb://127.0.0.1:27017/gorse"
#data_store = "mysql://gorse:gorse@tcp(127.0.0.1:33206)/gorse"
table_prefix = "gorse_"
cache_table_prefix = "gorse_"
data_table_prefix = "gorse_"
[master]
port = 8086
host = "0.0.0.0"
http_port = 8088
http_host = "0.0.0.0"
http_cors_domains = []
http_cors_methods = []
n_jobs = 1
meta_timeout = "10s"
dashboard_user_name = "{$CONFIG_ADMIN}"
dashboard_password = "{$CONFIG_PASS}"
admin_api_key = ""
[server]
default_n = 10
api_key = ""
clock_error = "5s"
auto_insert_user = true
auto_insert_item = true
cache_expire = "10s"
[recommend]
cache_size = 100
cache_expire = "72h"
[recommend.data_source]
positive_feedback_types = ["star","like"]
read_feedback_types = ["read"]
positive_feedback_ttl = 0
item_ttl = 0
[recommend.popular]
popular_window = "720h"
[recommend.user_neighbors]
neighbor_type = "similar"
enable_index = true
index_recall = 0.8
index_fit_epoch = 3
[recommend.item_neighbors]
neighbor_type = "similar"
enable_index = true
index_recall = 0.8
index_fit_epoch = 3
[recommend.collaborative]
enable_index = true
index_recall = 0.9
index_fit_epoch = 3
model_fit_period = "60m"
model_search_period = "360m"
model_search_epoch = 100
model_search_trials = 10
enable_model_size_search = false
[recommend.replacement]
enable_replacement = false
positive_replacement_decay = 0.8
read_replacement_decay = 0.6
[recommend.offline]
check_recommend_period = "1m"
refresh_recommend_period = "24h"
enable_latest_recommend = true
enable_popular_recommend = false
enable_user_based_recommend = true
enable_item_based_recommend = false
enable_collaborative_recommend = true
enable_click_through_prediction = true
explore_recommend = { popular = 0.1, latest = 0.2 }
[recommend.online]
fallback_recommend = ["item_based", "latest"]
num_feedback_fallback_item_based = 10
[tracing]
enable_tracing = false
exporter = "jaeger"
collector_endpoint = "http://localhost:14268/api/traces"
sampler = "always"
ratio = 1
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

+30
View File
@@ -0,0 +1,30 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('gorse');">服务</p>
<p onclick="pluginInitD('gorse');">自启动</p>
<p onclick="pluginConfigTpl('gorse',$('.plugin_version').attr('version'));">配置修改</p>
<p onclick="pluginLogs('gorse','','run_log');">运行日志</p>
<p onclick="gorseReadme();">相关说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con" style="height: 520px; overflow: auto;"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=gorse&f=js/gorse.js", function(){
pluginService('gorse', $('.plugin_version').attr('version'));
});
</script>
+342
View File
@@ -0,0 +1,342 @@
# 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 'gorse'
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() + "/gorse.toml"
return path
def getConfTpl():
path = getPluginDir() + "/config/gorse.toml"
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(':',1)
tmp[t[0]] = t[1]
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':',1)
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def 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 getPidFile():
file = getConf()
content = mw.readFile(file)
rep = r'pidfile\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def status():
# pid_file = getPidFile()
# if not os.path.exists(pid_file):
# return 'stop'
cmd = "ps aux|grep gorse |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def initRedisConf():
requirepass = ""
conf = mw.getServerDir() + '/redis/redis.conf'
content = mw.readFile(conf)
rep = r"^(requirepass" + r')\s*([.0-9A-Za-z_& ~]+)'
tmp = re.search(rep, content, re.M)
if tmp:
requirepass = tmp.groups()[1]
port = "6379"
rep = r"^(port)\s*([.0-9A-Za-z_& ~]+)"
tmp = re.search(rep, content, re.M)
if tmp:
port = tmp.groups()[1]
return 'redis://:'+requirepass+'@127.0.0.1:'+port+'/3'
def contentReplace(content):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$CONFIG_ADMIN}', mw.getRandomString(6))
content = content.replace('{$CONFIG_PASS}', mw.getRandomString(10))
content = content.replace('{$CONFIG_REDIS}', initRedisConf())
return content
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
mw.execShell("mkdir -p " + initD_path)
file_bin = initD_path + '/' + getPluginName()
# initd replace
if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# log
dataLog = getServerDir() + '/data'
if not os.path.exists(dataLog):
mw.execShell('chmod +x ' + file_bin)
# config replace
dst_conf = getServerDir() + '/gorse.toml'
dst_conf_init = getServerDir() + '/init.pl'
if not os.path.exists(dst_conf_init):
content = mw.readFile(getConfTpl())
content = content.replace('{$SERVER_PATH}', service_path)
content = contentReplace(content)
mw.writeFile(dst_conf, content)
mw.writeFile(dst_conf_init, 'ok')
# 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 = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, content)
mw.execShell('systemctl daemon-reload')
return file_bin
def gorseOp(method):
file = initDreplace()
# print(file)
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 gorseOp('start')
def stop():
return gorseOp('stop')
def restart():
status = gorseOp('restart')
log_file = runLog()
mw.execShell("echo '' > " + log_file)
return status
def reload():
return gorseOp('reload')
def getPort():
conf = getServerDir() + '/gorse.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() + '/logs.pl'
def installPreInspection():
redis_path = mw.getServerDir() + "/redis"
if not os.path.exists(redis_path):
return "默认需要安装Redis"
mongodb_path = mw.getServerDir() + "/mongodb"
if not os.path.exists(mongodb_path):
return "默认需要安装MongoDB"
return 'ok'
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'install_pre_inspection':
print(installPreInspection())
elif func == 'conf':
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'config_tpl':
print(configTpl())
elif func == 'read_config_tpl':
print(readConfigTpl())
else:
print('error')
+18
View File
@@ -0,0 +1,18 @@
{
"sort": 7,
"ps": "一款高效简单的推荐系统【单机】",
"name": "gorse",
"title": "Gorse",
"shell": "install.sh",
"versions":["0.4.15"],
"tip": "soft",
"install_pre_inspection":true,
"checks": "server/gorse",
"path": "server/gorse",
"display": 1,
"author": "midoks",
"date": "2024-06-12",
"home": "https://gorse.io/zh/docs/master/deploy/binary.html",
"type": 0,
"pid": "5"
}
+13
View File
@@ -0,0 +1,13 @@
[Unit]
Description=Gorse, an open source recommender system service written in Go.
After=network.target
[Service]
Type=simple
Restart=always
ExecStart={$SERVER_PATH}/gorse/bin/gorse-in-one -c {$SERVER_PATH}/gorse/gorse.toml \
--log-path {$SERVER_PATH}/gorse/gorse.log \
--cache-path {$SERVER_PATH}/gorse/data/cache.data
[Install]
WantedBy=multi-user.target
+57
View File
@@ -0,0 +1,57 @@
#!/bin/sh
# chkconfig: 2345 55 25
# description: Gorse Service
### BEGIN INIT INFO
# Provides: Gorse
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts Gorse
# Description: starts the MDW-Web
### END INIT INFO
# Simple Gorse init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
CONF="{$SERVER_PATH}/gorse/gorse.toml"
APP_DIR={$SERVER_PATH}/gorse
app_start(){
echo "Starting Gorse server..."
echo "$APP_DIR/bin/gorse-in-one -c $CONF"
nohup $APP_DIR/bin/gorse-in-one -c $CONF >> {$SERVER_PATH}/gorse/logs.pl 2>&1 &
}
app_stop(){
echo "Stopping ..."
find_gorse=`ps -ef | grep gorse | grep -v grep | awk "{print $2}"`
for p in ${find_gorse[@]}
do
kill -9 $p > /dev/null 2>&1
done
echo "Gorse stopped"
}
case "$1" in
start)
app_start
;;
stop)
app_stop
;;
restart|reload)
app_stop
sleep 0.3
app_start
;;
*)
echo "Please use start or stop as first argument"
;;
esac
+97
View File
@@ -0,0 +1,97 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
sysArch=`arch`
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/gorse && bash install.sh install 0.4.15
# cd /www/server/mdserver-web/plugins/gorse && bash install.sh install 0.4.15
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/source/gorse
SYSNAME=linux
if [ "$sysName" == "Darwin" ];then
SYSNAME=darwin
fi
ARCH="amd64"
if [ "$sysArch" == "x86_64" ];then
ARCH="amd64"
elif [ "$sysArch" == "aarch64" ];then
ARCH="arm64"
elif [ "$sysArch" == "arm64" ];then
ARCH="arm64"
else
ARCH="amd64"
fi
FILE_TGZ=gorse_${SYSNAME}_${ARCH}.zip
GORSE_DIR=$serverPath/source/gorse
# https://github.com/gorse-io/gorse/releases/download/v0.4.15/gorse_linux_amd64.zip
echo "https://github.com/gorse-io/gorse/releases/download/v${VERSION}/${FILE_TGZ}"
if [ ! -f $GORSE_DIR/${FILE_TGZ} ];then
wget -O $GORSE_DIR/${FILE_TGZ} https://github.com/gorse-io/gorse/releases/download/v${VERSION}/${FILE_TGZ}
fi
mkdir -p $serverPath/gorse/bin
mkdir -p $serverPath/gorse/logs
cd $GORSE_DIR && unzip -d $serverPath/gorse/bin ${FILE_TGZ}
mkdir -p $serverPath/gorse/data
echo "${VERSION}" > $serverPath/gorse/version.pl
echo '安装Gorse完成'
cd ${rootPath} && python3 ${rootPath}/plugins/gorse/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/gorse/index.py initd_install
if [ -d ${GORSE_DIR}/gorse-${VERSION} ];then
rm -rf ${GORSE_DIR}/gorse-${VERSION}
fi
}
Uninstall_App()
{
app_name=gorse
systemctl_dir=/lib/systemd/system
if [ -d /usr/lib/systemd/system ];then
systemctl_dir=/usr/lib/systemd/system
fi
if [ -f ${systemctl_dir}/${app_name}.service ];then
systemctl stop ${app_name}
systemctl disable ${app_name}
rm -rf ${systemctl_dir}/${app_name}.service
systemctl daemon-reload
fi
if [ -f $serverPath/${app_name}/initd/${app_name} ];then
$serverPath/${app_name}/initd/${app_name} stop
fi
if [ -d $serverPath/${app_name} ];then
rm -rf $serverPath/${app_name}
fi
echo "卸载Gorse成功"
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+68
View File
@@ -0,0 +1,68 @@
function gorsePost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'gorse';
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 gorsePostCallbak(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'gorse';
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');
}
function gorseReadme(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>参考官方</li>';
readme += '<li><a target="_blank" href="https://gorse.io">https://gorse.io</a></li>';
readme += '<li>mongodb初始化,是无认证的</li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
}
+252
View File
@@ -0,0 +1,252 @@
[database]
# The database for caching, support Redis, MySQL, Postgres and MongoDB:
# redis://<user>:<password>@<host>:<port>/<db_number>
# rediss://<user>:<password>@<host>:<port>/<db_number>
# redis+cluster://<user>:<password>@<host1>:<port1>,<host2>:<port2>,...,<hostN>:<portN>
# postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full
# postgresql://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full
# mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
# mongodb+srv://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
cache_store = "redis://localhost:6379/0"
# The database for persist data, support MySQL, Postgres, ClickHouse and MongoDB:
# mysql://[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
# postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full
# postgresql://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full
# clickhouse://user:password@host[:port]/database?param1=value1&...&paramN=valueN
# chhttp://user:password@host[:port]/database?param1=value1&...&paramN=valueN
# chhttps://user:password@host[:port]/database?param1=value1&...&paramN=valueN
# mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
# mongodb+srv://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
data_store = "mysql://gorse:gorse_pass@tcp(localhost:3306)/gorse"
# The naming prefix for tables (collections, keys) in databases. The default value is empty.
table_prefix = ""
# The naming prefix for tables (collections, keys) in cache storage databases. The default value is `table_prefix`.
cache_table_prefix = ""
# The naming prefix for tables (collections, keys) in data storage databases. The default value is `table_prefix`.
data_table_prefix = ""
[master]
# GRPC port of the master node. The default value is 8086.
port = 8086
# gRPC host of the master node. The default values is "0.0.0.0".
host = "0.0.0.0"
# HTTP port of the master node. The default values is 8088.
http_port = 8088
# HTTP host of the master node. The default values is "0.0.0.0".
http_host = "0.0.0.0"
# AllowedDomains is a list of allowed values for Http Origin.
# The list may contain the special wildcard string ".*" ; all is allowed
# If empty all are allowed.
http_cors_domains = []
# AllowedMethods is either empty or has a list of http methods names. Checking is case-insensitive.
http_cors_methods = []
# Number of working jobs in the master node. The default value is 1.
n_jobs = 1
# Meta information timeout. The default value is 10s.
meta_timeout = "10s"
# Username for the master node dashboard.
dashboard_user_name = ""
# Password for the master node dashboard.
dashboard_password = ""
# Secret key for admin APIs (SSL required).
admin_api_key = ""
[server]
# Default number of returned items. The default value is 10.
default_n = 10
# Secret key for RESTful APIs (SSL required).
api_key = ""
# Clock error in the cluster. The default value is 5s.
clock_error = "5s"
# Insert new users while inserting feedback. The default value is true.
auto_insert_user = true
# Insert new items while inserting feedback. The default value is true.
auto_insert_item = true
# Server-side cache expire time. The default value is 10s.
cache_expire = "10s"
[recommend]
# The cache size for recommended/popular/latest items. The default value is 10.
cache_size = 100
# Recommended cache expire time. The default value is 72h.
cache_expire = "72h"
[recommend.data_source]
# The feedback types for positive events.
positive_feedback_types = ["star","like"]
# The feedback types for read events.
read_feedback_types = ["read"]
# The time-to-live (days) of positive feedback, 0 means disabled. The default value is 0.
positive_feedback_ttl = 0
# The time-to-live (days) of items, 0 means disabled. The default value is 0.
item_ttl = 0
[recommend.popular]
# The time window of popular items. The default values is 4320h.
popular_window = "720h"
[recommend.user_neighbors]
# The type of neighbors for users. There are three types:
# similar: Neighbors are found by number of common labels.
# related: Neighbors are found by number of common liked items.
# auto: If a user have labels, neighbors are found by number of common labels.
# If this user have no labels, neighbors are found by number of common liked items.
# The default value is "auto".
neighbor_type = "similar"
# Enable approximate user neighbor searching using vector index. The default value is true.
enable_index = true
# Minimal recall for approximate user neighbor searching. The default value is 0.8.
index_recall = 0.8
# Maximal number of fit epochs for approximate user neighbor searching vector index. The default value is 3.
index_fit_epoch = 3
[recommend.item_neighbors]
# The type of neighbors for items. There are three types:
# similar: Neighbors are found by number of common labels.
# related: Neighbors are found by number of common users.
# auto: If a item have labels, neighbors are found by number of common labels.
# If this item have no labels, neighbors are found by number of common users.
# The default value is "auto".
neighbor_type = "similar"
# Enable approximate item neighbor searching using vector index. The default value is true.
enable_index = true
# Minimal recall for approximate item neighbor searching. The default value is 0.8.
index_recall = 0.8
# Maximal number of fit epochs for approximate item neighbor searching vector index. The default value is 3.
index_fit_epoch = 3
[recommend.collaborative]
# Enable approximate collaborative filtering recommend using vector index. The default value is true.
enable_index = true
# Minimal recall for approximate collaborative filtering recommend. The default value is 0.9.
index_recall = 0.9
# Maximal number of fit epochs for approximate collaborative filtering recommend vector index. The default value is 3.
index_fit_epoch = 3
# The time period for model fitting. The default value is "60m".
model_fit_period = "60m"
# The time period for model searching. The default value is "360m".
model_search_period = "360m"
# The number of epochs for model searching. The default value is 100.
model_search_epoch = 100
# The number of trials for model searching. The default value is 10.
model_search_trials = 10
# Enable searching models of different sizes, which consume more memory. The default value is false.
enable_model_size_search = false
[recommend.replacement]
# Replace historical items back to recommendations. The default value is false.
enable_replacement = false
# Decay the weights of replaced items from positive feedbacks. The default value is 0.8.
positive_replacement_decay = 0.8
# Decay the weights of replaced items from read feedbacks. The default value is 0.6.
read_replacement_decay = 0.6
[recommend.offline]
# The time period to check recommendation for users. The default values is 1m.
check_recommend_period = "1m"
# The time period to refresh recommendation for inactive users. The default values is 120h.
refresh_recommend_period = "24h"
# Enable latest recommendation during offline recommendation. The default value is false.
enable_latest_recommend = true
# Enable popular recommendation during offline recommendation. The default value is false.
enable_popular_recommend = false
# Enable user-based similarity recommendation during offline recommendation. The default value is false.
enable_user_based_recommend = true
# Enable item-based similarity recommendation during offline recommendation. The default value is false.
enable_item_based_recommend = false
# Enable collaborative filtering recommendation during offline recommendation. The default value is true.
enable_collaborative_recommend = true
# Enable click-though rate prediction during offline recommendation. Otherwise, results from multi-way recommendation
# would be merged randomly. The default value is false.
enable_click_through_prediction = true
# The explore recommendation method is used to inject popular items or latest items into recommended result:
# popular: Recommend popular items to cold-start users.
# latest: Recommend latest items to cold-start users.
# The default values is { popular = 0.0, latest = 0.0 }.
explore_recommend = { popular = 0.1, latest = 0.2 }
[recommend.online]
# The fallback recommendation method is used when cached recommendation drained out:
# item_based: Recommend similar items to cold-start users.
# popular: Recommend popular items to cold-start users.
# latest: Recommend latest items to cold-start users.
# Recommenders are used in order. The default values is ["latest"].
fallback_recommend = ["item_based", "latest"]
# The number of feedback used in fallback item-based similar recommendation. The default values is 10.
num_feedback_fallback_item_based = 10
[tracing]
# Enable tracing for REST APIs. The default value is false.
enable_tracing = false
# The type of tracing exporters should be one of "jaeger", "zipkin", "otlp" and "otlphttp". The default value is "jaeger".
exporter = "jaeger"
# The endpoint of tracing collector.
collector_endpoint = "http://localhost:14268/api/traces"
# The type of tracing sampler should be one of "always", "never" and "ratio". The default value is "always".
sampler = "always"
# The ratio of ratio based sampler. The default value is 1.
ratio = 1
+1 -1
View File
@@ -38,7 +38,7 @@ max_connections = 500
max_connect_errors = 100
open_files_limit = 65535
skip-name-resolve = 1
skip-name-resolve
#skip-networking
#skip-external-locking
#loose-skip-innodb
+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","11.1","11.2","11.3","11.4"],
"versions":["10.6","10.7","10.8","10.9","10.11","11.0","11.1","11.2","11.3","11.4","11.5"],
"shell":"install.sh",
"checks":"server/mariadb",
"path":"server/mariadb",
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.4.2
MY_VER=11.4.3
Install_app()
{
+121
View File
@@ -0,0 +1,121 @@
#!/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.5.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
INSTALL_CMD=cmake
# check cmake version
CMAKE_VERSION=`cmake -version | grep version | awk '{print $3}' | awk -F '.' '{print $1}'`
if [ "$CMAKE_VERSION" -eq "2" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
INSTALL_CMD=cmake3
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && ${INSTALL_CMD} \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '11.4' > $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
+7 -6
View File
@@ -15,14 +15,14 @@ echo $sys_os
Install_mem(){
mkdir -p $serverPath/source
# mkdir -p $serverPath/memcached
mkdir -p $serverPath/source/memcached
echo '正在安装脚本文件...' > $install_tmp
if [ ! -f $serverPath/source/memcached.tar.gz ];then
wget --no-check-certificate -O $serverPath/source/memcached.tar.gz http://www.memcached.org/files/memcached-${VERSION}.tar.gz
wget --no-check-certificate -O $serverPath/source/memcached/memcached.tar.gz https://www.memcached.org/files/memcached-${VERSION}.tar.gz
fi
cd $serverPath/source && tar -zxvf memcached.tar.gz
cd $serverPath/source/memcached && tar -zxvf memcached.tar.gz
OPTIONS=''
if [ ${sys_os} == "Darwin" ]; then
@@ -31,7 +31,7 @@ Install_mem(){
fi
echo "./configure --prefix=${serverPath}/memcached && make && make install"
cd $serverPath/source/memcached-${VERSION}
cd $serverPath/source/memcached/memcached-${VERSION}
./configure --prefix=$serverPath/memcached \
$OPTIONS
@@ -39,12 +39,12 @@ Install_mem(){
if [ -d $serverPath/memcached ];then
echo '1.6' > $serverPath/memcached/version.pl
echo 'install ok' > $install_tmp
echo '安装memcached成功'
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}
rm -rf $serverPath/source/memcached/memcached-${VERSION}
fi
}
@@ -62,6 +62,7 @@ Uninstall_mem()
$serverPath/memcached/initd/memcached stop
fi
rm -rf $serverPath/memcached
echo '卸载memcached成功'
}
+29
View File
@@ -662,6 +662,27 @@ def delDb():
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def delDbTable():
client = mongdbClient()
db = client.admin
sqlite_db = pSqliteDb('databases')
args = getArgs()
data = checkArgs(args, ['table_name', 'name'])
if not data[0]:
return data[1]
name = args['name']
table_name = args['table_name']
try:
cur_db = client[name]
cur_db[table_name].drop()
return mw.returnJson(True, '删除成功!')
except Exception as ex:
return mw.returnJson(False, '删除失败!' + str(ex))
def setRootPwd(version=''):
args = getArgs()
data = checkArgs(args, ['password'])
@@ -1289,6 +1310,10 @@ def getListBson(dbname=''):
r.append(x)
return r
def rootPwd():
return pSqliteDb('config').where(
'id=?', (1,)).getField('mg_root')
def importDbExternal():
args = getArgs()
data = checkArgs(args, ['file', 'name'])
@@ -1568,12 +1593,16 @@ if __name__ == "__main__":
print(saveConfig())
elif func == 'set_config_auth':
print(setConfigAuth())
elif func == 'root_pwd':
print(rootPwd())
elif func == 'get_db_list':
print(getDbList())
elif func == 'add_db':
print(addDb())
elif func == 'del_db':
print(delDb())
elif func == 'del_db_table':
print(delDbTable())
elif func == 'set_root_pwd':
print(setRootPwd())
elif func == 'set_user_pwd':
+2 -2
View File
@@ -36,7 +36,7 @@ if [ -f ${rootPath}/bin/activate ];then
fi
Install_app()
{
echo '正在安装脚本文件...' > $install_tmp
echo '正在安装脚本文件...'
mkdir -p $serverPath/source
# if id mongodb &> /dev/null ;then
@@ -66,7 +66,7 @@ Install_app()
if [ -f $shell_file ];then
bash -x $shell_file
else
echo '不支持...' > $install_tmp
echo '不支持...'
exit 1
fi
+54 -16
View File
@@ -767,6 +767,18 @@ function delDb(id, name){
});
}
function delDbTable( name, table_name){
safeMessage('删除['+name+']','您真的要删除['+table_name+']吗?',function(){
var data='name='+name+'&table_name='+table_name;
mgPost('del_db_table', '', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
repTools(name);
},{icon: rdata.status ? 1 : 2}, 600);
});
});
}
function delDbBatch(){
var arr = [];
$('input[type="checkbox"].check:checked').each(function () {
@@ -835,22 +847,10 @@ function setDbPass(id, username, password){
}
function repTools(db_name, res){
mgPost('get_db_info', '', {name:db_name}, function(data){
var rdata = $.parseJSON(data.data);
var rdata = rdata.data;
// console.log(rdata.collection_list);
var tbody = '';
for (var i = 0; i < rdata.collection_list.length; i++) {
tbody += '<tr>\
<td><span style="width:220px;"> ' + rdata.collection_list[i].collection_name + '</span></td>\
<td><span style="width:220px;"> ' + rdata.collection_list[i].count + '</span></td>\
<td>' + toSize(rdata.collection_list[i].size) + '</td>\
<td><span style="width:90px;"> ' + toSize(rdata.collection_list[i].avg_obj_size) + '</span></td>\
<td>' + toSize(rdata.collection_list[i].storage_size) + '</td>\
<td>' + rdata.collection_list[i].nindexes + '</td>\
<td>' + toSize(rdata.collection_list[i].total_index_size) + '</td>\
</tr> '
}
layer.open({
type: 1,
@@ -858,7 +858,7 @@ function repTools(db_name, res){
area: ['780px', '480px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
content: '<div class="pd15" id="mongodb_list">\
<div class="db_list">\
<span><a>数据库名称:'+ db_name + '</a>\
<a>集合:'+ rdata.collections + '</a>\
@@ -879,13 +879,51 @@ function repTools(db_name, res){
<th>存储大小</th>\
<th>索引数量</th>\
<th>索引大小</th>\
<th>操作</th>\
</tr>\
</thead>\
<tbody class="gztr">' + tbody + '</tbody>\
<tbody class="gztr"></tbody>\
</table>\
</div>\
</div>\
</div>'
</div>',
success:function(layer_id, layer_index){
var tbody = '';
for (var i = 0; i < rdata.collection_list.length; i++) {
tbody += '<tr>\
<td><span style="width:220px;"> ' + rdata.collection_list[i].collection_name + '</span></td>\
<td><span style="width:220px;"> ' + rdata.collection_list[i].count + '</span></td>\
<td>' + toSize(rdata.collection_list[i].size) + '</td>\
<td><span style="width:90px;"> ' + toSize(rdata.collection_list[i].avg_obj_size) + '</span></td>\
<td>' + toSize(rdata.collection_list[i].storage_size) + '</td>\
<td>' + rdata.collection_list[i].nindexes + '</td>\
<td>' + toSize(rdata.collection_list[i].total_index_size) + '</td>\
<td>' + '<a href="javascript:;" data-index="'+i+'" class="delete btlink" title="删除">删除</a>'+'</td>\
</tr>';
}
$('#mongodb_list tbody').html(tbody);
$('#mongodb_list .delete').click(function(){
var index = $(this).data('index');
var name = db_name;
var table_name = rdata.collection_list[index].collection_name;
safeMessage('删除['+name+']','您真的要删除['+table_name+']吗?',function(){
var data='name='+name+'&table_name='+table_name;
mgPost('del_db_table', '', data, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
layer.close(layer_index);
repTools(name);
},{icon: rdata.status ? 1 : 2}, 600);
});
});
});
}
});
tableFixed('database_fix');
});
+108
View File
@@ -0,0 +1,108 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=7.0.9
SYS_ARCH=`arch`
SYS_VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
SYS_NAME=${SYS_VERSION_ID/./}
SYS_NAME_LEN=`echo "$SYS_NAME" | wc -L`
if [ "$SYS_NAME_LEN" == "1" ];then
SYS_NAME=${SYS_NAME}0
fi
if [ "$SYS_ARCH" == "aarch64" ];then
if [ "$SYS_NAME" -gt "90" ];then
SYS_NAME="90"
fi
if [ "$SYS_NAME" -lt "82" ];then
SYS_NAME="82"
fi
else
if [ "$SYS_NAME" -gt "90" ];then
SYS_NAME="90"
fi
if [ "$SYS_NAME" -lt "70" ];then
SYS_NAME="70"
fi
fi
MG_DIR=$serverPath/source/mongodb
mkdir -p $MG_DIR
FILE_NAME=mongodb-linux-${SYS_ARCH}-rhel${SYS_NAME}-${VERSION}
FILE_NAME_TGZ=${FILE_NAME}.tgz
if [ ! -f $MG_DIR/${FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${FILE_NAME_TGZ} https://fastdl.mongodb.org/linux/${FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${FILE_NAME} ];then
cd $MG_DIR && tar -zxvf ${FILE_NAME_TGZ}
fi
if [ ! -d $serverPath/mongodb/bin ];then
mkdir -p $serverPath/mongodb
cd $MG_DIR/${FILE_NAME} && cp -rf ./bin $serverPath/mongodb
fi
cd ${MG_DIR} && rm -rf ${MG_DIR}/${FILE_NAME}
#--------------- mongosh tool install ------------------ #
TOOL_VERSION=2.2.5
TOOL_FILE_NAME=mongosh-${TOOL_VERSION}-linux-x64
if [ "aarch64" == ${SYS_ARCH} ];then
TOOL_FILE_NAME=mongosh-${TOOL_VERSION}-linux-arm64
fi
TOOL_FILE_NAME_TGZ=${TOOL_FILE_NAME}.tgz
if [ ! -f $MG_DIR/${TOOL_FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${TOOL_FILE_NAME_TGZ} https://downloads.mongodb.com/compass/${TOOL_FILE_NAME_TGZ}
echo "wget --no-check-certificate -O $MG_DIR/${TOOL_FILE_NAME_TGZ} https://downloads.mongodb.com/compass/${TOOL_FILE_NAME_TGZ}"
fi
if [ ! -d $MG_DIR/${TOOL_FILE_NAME_TGZ} ];then
cd $MG_DIR && tar -zxvf ${TOOL_FILE_NAME_TGZ}
fi
cd ${MG_DIR}/${TOOL_FILE_NAME} && cp -rf ./bin $serverPath/mongodb
cd ${MG_DIR} && rm -rf ${MG_DIR}/${TOOL_FILE_NAME}
# https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel90-aarch64-100.9.4.tgz
# https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel90-x86_64-100.9.4.tgz
# https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel83-s390x-100.9.4.tgz
#--------------- mongodb database install ------------------ #
TOOL_VERSION=100.9.4
TOOL_FILE_NAME=mongodb-database-tools-rhel${SYS_NAME}-x86_64-${TOOL_VERSION}
if [ "aarch64" == ${SYS_ARCH} ];then
TOOL_FILE_NAME=mongodb-database-tools-rhel${SYS_NAME}-aarch64-${TOOL_VERSION}
fi
if [ "arm64" == ${SYS_ARCH} ];then
TOOL_FILE_NAME=mongodb-database-tools-rhel${SYS_NAME}-arm64-${TOOL_VERSION}
fi
TOOL_FILE_NAME_TGZ=${TOOL_FILE_NAME}.tgz
if [ ! -f $MG_DIR/${TOOL_FILE_NAME_TGZ} ]; then
wget --no-check-certificate -O $MG_DIR/${TOOL_FILE_NAME_TGZ} https://fastdl.mongodb.org/tools/db/${TOOL_FILE_NAME_TGZ}
fi
if [ ! -d $MG_DIR/${TOOL_FILE_NAME_TGZ} ];then
cd $MG_DIR && tar -zxvf ${TOOL_FILE_NAME_TGZ}
fi
cd ${MG_DIR}/${TOOL_FILE_NAME} && cp -rf ./bin $serverPath/mongodb
cd ${MG_DIR} && rm -rf ${MG_DIR}/${TOOL_FILE_NAME}
+1 -1
View File
@@ -103,7 +103,7 @@ secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
max_allowed_packet = 16M
max_allowed_packet = 32M
[mysql]
no-auto-rehash
+1 -1
View File
@@ -106,7 +106,7 @@ secure-file-priv={$SERVER_APP_PATH}/tmp
[mysqldump]
quick
max_allowed_packet = 16M
max_allowed_packet = 32M
[mysql]
no-auto-rehash
+4 -3
View File
@@ -62,9 +62,10 @@ http
# CACEH_BEGIN
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_buffer_size 1024k;
proxy_buffers 16 1024k;
proxy_busy_buffers_size 2048k;
proxy_temp_file_write_size 2048k;
proxy_cache_path {$SERVER_PATH}/openresty/nginx/proxy_cache_temp levels=1:2 keys_zone=mw_cache:512m inactive=5m max_size=2g use_temp_path=off;
#proxy timeout
proxy_connect_timeout 3s;
+5 -1
View File
@@ -400,6 +400,10 @@ def initdUinstall():
def runInfo():
op_status = status()
if op_status == 'stop':
return mw.returnJson(False, "未启动!")
# 取Openresty负载状态
try:
url = 'http://127.0.0.1/nginx_status'
@@ -429,7 +433,7 @@ def runInfo():
data['Waiting'] = tmp[15]
return mw.getJson(data)
except Exception as e:
return 'oprenresty not started'
return mw.returnJson(False, "oprenresty not started!")
def errorLogPath():
+6 -5
View File
@@ -114,13 +114,14 @@ function orPluginOpServiceOp(a,b,c,d,a,v,request_callback){
function getOpStatus() {
var loadT = layer.msg('正在处理,请稍后...', { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'openresty', func:'run_info'}, function(data) {
layer.close(loadT);
if (!data.status){
showMsg(data.msg, function(){}, null,3000);
return;
}
layer.close(loadT);
try {
var rdata = $.parseJSON(data.data);
if ('status' in rdata && !rdata.status){
showMsg(rdata.msg, function(){}, null,3000);
return;
}
var con = "<div><table class='table table-hover table-bordered'>\
<tr><th>活动连接(Active connections)</th><td>" + rdata.active + "</td></tr>\
<tr><th>总连接次数(accepts)</th><td>" + rdata.accepts + "</td></tr>\
+6
View File
@@ -0,0 +1,6 @@
LOG_FILE = '{$DATA_PATH}/pgadmin4/pgadmin4.log'
SQLITE_PATH = '{$DATA_PATH}/pgadmin4/pgadmin4.db'
SESSION_DB_PATH = '{$DATA_PATH}/pgadmin4/sessions'
STORAGE_DIR = '{$DATA_PATH}/pgadmin4/storage'
AZURE_CREDENTIAL_CACHE_DIR = '{$DATA_PATH}/pgadmin4/azurecredentialcache'
SERVER_MODE = True
+21
View File
@@ -0,0 +1,21 @@
server
{
listen 5051;
server_name 127.0.0.1;
index index.html index.htm index.php;
root {$SERVER_PATH}/pgadmin;
#error_page 404 /404.html;
#AUTH_START
auth_basic "Authorization";
auth_basic_user_file {$SERVER_PATH}/pgadmin/pg.pass;
#AUTH_END
location / {
proxy_pass http://unix:/tmp/pgadmin4.sock;
}
access_log {$SERVER_PATH}/pgadmin/access.log;
error_log {$SERVER_PATH}/pgadmin/error.log;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

+22
View File
@@ -0,0 +1,22 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('pgadmin');">服务</p>
<p onclick="pluginConfig('pgadmin');">重写模版</p>
<p onclick="homePage()">主页</p>
<p onclick="safeConf();">安全设置</p>
<p onclick="pluginLogs('pgadmin','','access_log');">访问日志</p>
<p onclick="pluginLogs('pgadmin','','error_log');">错误日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
resetPluginWinHeight(500);
$.getScript( "/plugins/file?name=pgadmin&f=js/pgadmin.js", function(){
pluginService('pgadmin');
});
</script>
+418
View File
@@ -0,0 +1,418 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
import site_api
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'pgadmin'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
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():
return mw.getServerDir() + '/web_conf/nginx/vhost/pgadmin.conf'
def getPort():
file = getConf()
content = mw.readFile(file)
rep = 'listen\s*(.*);'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def getHomePage():
try:
port = getPort()
ip = '127.0.0.1'
if not mw.isAppleSystem():
ip = mw.getLocalIp()
cfg = getCfg()
auth = cfg['username']+':'+cfg['password']
url = 'http://' + auth + '@' + ip + ':' + port + '/'
return mw.returnJson(True, 'OK', url)
except Exception as e:
return mw.returnJson(False, '插件未启动!')
def contentReplace(content):
cfg = getCfg()
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$APP_PATH}', service_path+'/'+getPluginName()+'/data')
port = cfg["port"]
rep = 'listen\s*(.*);'
content = re.sub(rep, "listen " + port + ';', content)
return content
def initCfg():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
data = {}
data['port'] = '5051'
data['path'] = ''
data['username'] = 'admin'
data['password'] = 'admin'
data['web_pg_username'] = 'mdserver-web@gmail.com'
data['web_pg_password'] = 'admin'
mw.writeFile(cfg, json.dumps(data))
def setCfg(key, val):
cfg = getServerDir() + "/cfg.json"
data = mw.readFile(cfg)
data = json.loads(data)
data[key] = val
mw.writeFile(cfg, json.dumps(data))
def getCfg():
cfg = getServerDir() + "/cfg.json"
data = mw.readFile(cfg)
data = json.loads(data)
return data
def returnCfg():
cfg = getServerDir() + "/cfg.json"
data = mw.readFile(cfg)
return data
def __release_port(port):
from collections import namedtuple
try:
import firewall_api
firewall_api.firewall_api().addAcceptPortArgs(port, 'pgAdmin默认端口', 'port')
return port
except Exception as e:
return "Release failed {}".format(e)
def __delete_port(port):
from collections import namedtuple
try:
import firewall_api
firewall_api.firewall_api().delAcceptPortArgs(port, 'tcp')
return port
except Exception as e:
return "Release failed {}".format(e)
def openPort():
conf = getCfg()
port = conf['port']
for i in [port]:
__release_port(i)
return True
def delPort():
conf = getCfg()
port = conf['port']
for i in [port]:
__delete_port(i)
return True
def cleanNginxLog():
log_a = accessLog()
log_e = errorLog()
for i in [log_a, log_e]:
if os.path.exists(i):
cmd = "echo '' > " + i
mw.execShell(cmd)
def getPythonName():
cmd = "ls /www/server/pgadmin/run/lib/ | grep python | cut -d \\ -f 1 | awk 'END {print}'"
data = mw.execShell(cmd)
return data[0].strip();
def initPgConfFile():
file_tpl = getPluginDir() + '/conf/config_local.py'
dst_file = getServerDir()+'/run/lib/python3.10/site-packages/pgadmin4/config_local.py'
if not os.path.exists(dst_file):
service_path = mw.getServerDir()
content = mw.readFile(file_tpl)
content = content.replace('{$DATA_PATH}', service_path+'/'+getPluginName()+'/data')
mw.writeFile(dst_file, content)
def initReplace():
initPgConfFile()
file_tpl = getPluginDir() + '/conf/pgadmin.conf'
file_run = getConf()
if not os.path.exists(file_run):
content = mw.readFile(file_tpl)
content = contentReplace(content)
mw.writeFile(file_run, content)
pass_path = getServerDir() + '/pg.pass'
if not os.path.exists(pass_path):
username = mw.getRandomString(8)
password = mw.getRandomString(10)
pass_cmd = username + ':' + mw.hasPwd(password)
setCfg('username', username)
setCfg('password', password)
mw.writeFile(pass_path, pass_cmd)
# pg_conf = getCfg()
judge_file = getServerDir()+'/data/pgadmin4/pgadmin4.db'
if not os.path.exists(judge_file):
pg_init_bash = getPluginDir()+'/pg_init.sh'
pg_rand = mw.getRandomString(8)
pg_username = "mw."+pg_rand+"@gmail.com"
setCfg('web_pg_username', pg_username)
pg_password = mw.getRandomString(10)
setCfg('web_pg_password', pg_password)
t = mw.execShell("bash "+ pg_init_bash + " " + pg_username + " " + pg_password)
# print(t)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/pgadmin.service'
if os.path.exists(systemDir) and not os.path.exists(systemService):
systemServiceTpl = getPluginDir() + '/init.d/pgadmin.service.tpl'
service_path = mw.getServerDir()
content = mw.readFile(systemServiceTpl)
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$PY_VER}', getPythonName())
mw.writeFile(systemService, content)
mw.execShell('systemctl daemon-reload')
def pgOp(method):
file = initReplace()
current_os = mw.getOs()
if current_os == "darwin":
return 'ok'
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 status():
sock = '/tmp/pgadmin4.sock'
if os.path.exists(sock):
return 'start'
return 'stop'
def start():
initCfg()
openPort()
pgOp('start')
mw.restartWeb()
return 'ok'
def stop():
pgOp('stop')
conf = getConf()
if os.path.exists(conf):
os.remove(conf)
delPort()
mw.restartWeb()
return 'ok'
def restart():
cleanNginxLog()
state = pgOp('restart')
mw.restartWeb()
return state
def reload():
cleanNginxLog()
return pgOp('reload')
def getPgOption():
data = getCfg()
return mw.returnJson(True, 'ok', data)
def getPgPort():
try:
port = getPort()
return mw.returnJson(True, 'OK', port)
except Exception as e:
# print(e)
return mw.returnJson(False, '插件未启动!')
def setPgPort():
args = getArgs()
data = checkArgs(args, ['port'])
if not data[0]:
return data[1]
port = args['port']
if port == '80':
return mw.returnJson(False, '80端不能使用!')
file = getConf()
if not os.path.exists(file):
return mw.returnJson(False, '插件未启动!')
content = mw.readFile(file)
rep = r'listen\s*(.*);'
content = re.sub(rep, "listen " + port + ';', content)
mw.writeFile(file, content)
setCfg("port", port)
mw.restartWeb()
return mw.returnJson(True, '修改成功!')
def setPgUsername():
args = getArgs()
data = checkArgs(args, ['username'])
if not data[0]:
return data[1]
username = args['username']
setCfg('username', username)
cfg = getCfg()
pma_path = getServerDir() + '/pg.pass'
username = mw.getRandomString(10)
pass_cmd = cfg['username'] + ':' + mw.hasPwd(cfg['password'])
mw.writeFile(pma_path, pass_cmd)
mw.restartWeb()
return mw.returnJson(True, '修改成功!')
def setPgPassword():
args = getArgs()
data = checkArgs(args, ['password'])
if not data[0]:
return data[1]
password = args['password']
setCfg('password', password)
cfg = getCfg()
pma_path = getServerDir() + '/pg.pass'
username = mw.getRandomString(10)
pass_cmd = cfg['username'] + ':' + mw.hasPwd(cfg['password'])
mw.writeFile(pma_path, pass_cmd)
mw.restartWeb()
return mw.returnJson(True, '修改成功!')
def accessLog():
return getServerDir() + '/access.log'
def errorLog():
return getServerDir() + '/error.log'
def installVersion():
return mw.readFile(getServerDir() + '/version.pl')
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 == 'conf':
print(getConf())
elif func == 'version':
print(installVersion())
elif func == 'get_cfg':
print(returnCfg())
elif func == 'get_home_page':
print(getHomePage())
elif func == 'get_pg_port':
print(getPgPort())
elif func == 'set_pg_port':
print(setPgPort())
elif func == 'get_pg_option':
print(getPgOption())
elif func == 'set_pg_username':
print(setPgUsername())
elif func == 'set_pg_password':
print(setPgPassword())
elif func == 'access_log':
print(accessLog())
elif func == 'error_log':
print(errorLog())
else:
print('error')
+15
View File
@@ -0,0 +1,15 @@
{
"title":"pgadmin",
"tip":"soft",
"name":"pgadmin",
"type":"运行环境",
"ps":"全能Postgres数据库Web管理工具",
"versions":["4"],
"shell":"install.sh",
"checks":"server/pgadmin",
"path": "server/pgadmin",
"author":"pgadmin",
"home":"https://www.pgadmin.org/download/pgadmin-4-python/",
"date":"2024-10-1",
"pid": "2"
}
@@ -0,0 +1,16 @@
# It's not recommended to modify this file in-place, because it
# will be overwritten during upgrades. If you want to customize,
# the best way is to use the "systemctl edit" command.
# systemctl daemon-reload
[Unit]
Description=pgadmin service
After=network.target
[Service]
ExecStart=gunicorn --bind unix:/tmp/pgadmin4.sock --workers=1 --threads=25 --chdir {$SERVER_PATH}/pgadmin/run/lib/{$PY_VER}/site-packages/pgadmin4 pgAdmin4:app
ExecReload=/bin/kill -USR2 $MAINPID
PrivateTmp=false
[Install]
WantedBy=multi-user.target
+123
View File
@@ -0,0 +1,123 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin
export PATH
function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
P_VER=`python3 -V | awk '{print $2}'`
echo "python:$P_VER"
# https://cn.linux-console.net/?p=6560
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/pgadmin && bash install.sh install 4
# cd /www/server/mdserver-web/plugins/pgadmin && bash install.sh install 4
# source /www/server/pgadmin/run/bin/activate
# python /www/server/pgadmin/run/lib/python3.10/site-packages/pgadmin4/setup.py --help
# python /www/server/pgadmin/run/lib/python3.10/site-packages/pgadmin4/setup.py add-user mdserver-web@gmail.com 123123
# cd /www/server/mdserver-web && python3 plugins/pgadmin/index.py start
# cd /www/server/mdserver-web && python3 plugins/pgadmin/index.py stop
install_tmp=${rootPath}/tmp/mw_install.pl
if [ "$sys_os" == "Darwin" ];then
BAK='_bak'
else
BAK=''
fi
sysName=`uname`
echo "use system: ${sysName}"
if [ "${sysName}" == "Darwin" ]; then
OSNAME='macos'
elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
OSNAME='centos'
elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then
OSNAME='fedora'
elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
OSNAME='debian'
elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
OSNAME='ubuntu'
elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then
OSNAME='raspbian'
else
OSNAME='unknow'
fi
Install_pgadmin()
{
# if [ -d $serverPath/pgadmin ];then
# exit 0
# fi
if version_lt "$P_VER" "3.8.0" ;then
echo 'Python版本太低,无法安装'
exit 0
fi
PG_DIR=${serverPath}/pgadmin/run
PG_DATA_DIR=${serverPath}/pgadmin/data
mkdir -p $PG_DIR
mkdir -p $PG_DATA_DIR
echo "${1}" > ${serverPath}/pgadmin/version.pl
if [ ! -f $PG_DIR/bin/activate ];then
if version_ge "$P_VER" "3.11.0" ;then
echo "python3 > 3.11"
cd $PG_DIR && python3 -m venv $PG_DIR
else
echo "python3 < 3.10"
cd $PG_DIR && python3 -m venv .
fi
fi
if [ -f ${PG_DIR}/bin/activate ];then
source ${PG_DIR}/bin/activate
fi
# pip install https://ftp.postgresql.org/pub/pgadmin/pgadmin4/v8.10/pip/pgadmin4-8.10-py3-none-any.whl
pip install https://ftp.postgresql.org/pub/pgadmin/pgadmin4/v8.12/pip/pgadmin4-8.12-py3-none-any.whl
cd ${rootPath} && python3 ${rootPath}/plugins/pgadmin/index.py start
echo '安装完成'
}
Uninstall_pgadmin()
{
cd ${rootPath} && python3 ${rootPath}/plugins/pgadmin/index.py stop
if [ -f /usr/lib/systemd/system/pgadmin.service ];then
systemctl stop pgadmin
systemctl disable pgadmin
rm -rf /usr/lib/systemd/system/pgadmin.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/pgadmin.service ];then
systemctl stop pgadmin
systemctl disable pgadmin
rm -rf /lib/systemd/system/pgadmin.service
systemctl daemon-reload
fi
rm -rf ${serverPath}/pgadmin
# rm -rf /var/lib/pgadmin
# rm -rf /var/log/pgadmin
echo '卸载完成'
}
action=$1
if [ "${1}" == 'install' ];then
Install_pgadmin $2
else
Uninstall_pgadmin $2
fi
+119
View File
@@ -0,0 +1,119 @@
function pgPost(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:'pgadmin', 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 pgAsyncPost(method,args){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
return syncPost('/plugins/run', {name:'pgadmin', func:method, args:_args});
}
function homePage(){
pgPost('get_home_page', '', function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var con = '<button class="btn btn-default btn-sm" onclick="window.open(\'' + rdata.data + '\')">主页</button>';
$(".soft-man-con").html(con);
});
}
//phpmyadmin安全设置
function safeConf() {
pgPost('get_pg_option', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']});
return;
}
var cfg = rdata.data;
var con = '<div class="ver line">\
<span class="tname">访问端口</span>\
<input style="width:110px" class="bt-input-text phpmyadmindk mr20" name="Name" id="pmport" value="' + cfg['port'] + '" placeholder="pgadmin访问端口" maxlength="5" type="number">\
<button class="btn btn-success btn-sm" onclick="setPgPort()">保存</button>\
</div>\
<div class="ver line">\
<span class="tname">用户名</span>\
<input style="width:110px" class="bt-input-text mr20" name="username" id="pmport" value="' + cfg['username'] + '" placeholder="认证用户名" type="text">\
<button class="btn btn-success btn-sm" onclick="setPgUsername()">保存</button>\
</div>\
<div class="ver line">\
<span class="tname">密码</span>\
<input style="width:110px" class="bt-input-text mr20" name="password" id="pmport" value="' + cfg['password'] + '" placeholder="密码" type="text">\
<button class="btn btn-success btn-sm" onclick="setPgPassword()">保存</button>\
</div>\
<hr/>\
<div class="ver line">pgadmin登录信息</div>\
<div class="ver line">\
<span class="tname">PG登录用户名</span>\
<input style="width:110px" class="bt-input-text mr20" name="username" id="pmport" value="' + cfg['web_pg_username'] + '" placeholder="PG登录用户名" type="text">\
<button class="btn btn-success btn-sm" onclick="setPgUsername()">保存</button>\
</div>\
<div class="ver line">\
<span class="tname">PG登录密码</span>\
<input style="width:110px" class="bt-input-text mr20" name="password" id="pmport" value="' + cfg['web_pg_password'] + '" placeholder="PG登录密码" type="text">\
<button class="btn btn-success btn-sm" onclick="setPgPassword()">保存</button>\
</div>';
$(".soft-man-con").html(con);
});
}
function setPgUsername(){
var username = $("input[name=username]").val();
pgPost('set_pg_username',{'username':username}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
function setPgPassword(){
var password = $("input[name=password]").val();
pgPost('set_pg_password',{'password':password}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//修改phpmyadmin端口
function setPgPort() {
var pmport = $("#pmport").val();
if (pmport < 80 || pmport > 65535) {
layer.msg('端口范围不合法!', { icon: 2 });
return;
}
var data = 'port=' + pmport;
pgPost('set_pg_port',data, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
python_ver=`ls /www/server/pgadmin/run/lib/ | grep python | cut -d \ -f 1 | awk 'END {print}'`
email=$1
email_pwd=$2
expect <<-EOF
set time 10
spawn gunicorn --bind unix:/tmp/pgadmin4.sock \
--workers=1 \
--threads=25 \
--chdir /www/server/pgadmin/run/lib/${python_ver}/site-packages/pgadmin4 pgAdmin4:app
expect {
"Email address:" { send "${email}\r"; exp_continue }
"Password" { send "${email_pwd}\r"; exp_continue }
"Retype password" { send "${email_pwd}\r" }
}
expect eof
EOF
pids=$(ps aux | grep 'pgAdmin4:app' | grep -v grep | awk '{print $2}')
arr=($pids)
for p in ${arr[@]}
do
kill -9 $p > /dev/null 2>&1
done
+154
View File
@@ -0,0 +1,154 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import shutil
# reload(sys)
# sys.setdefaultencoding('utf8')
sys.path.append(os.getcwd() + "/class/core")
import mw
if mw.isAppleSystem():
cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
info = mw.execShell(cmd)
p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
sys.path.append(p)
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'php'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return '/etc/opt/remi'
def getInitDFile(version):
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() + version
def getConf(version):
path = getServerDir() + '/php' + version + '/php.ini'
return path
def getFpmConfFile(version):
return getServerDir() + '/php' + version + '/php-fpm.d/mw.conf'
def getPhpSocket(version):
path = getFpmConfFile(version)
content = mw.readFile(path)
rep = 'listen\s*=\s*(.*)'
tmp = re.search(rep, content)
return tmp.groups()[0].strip()
def status(version):
# ps -ef|grep 'php/81' |grep -v grep | grep -v python | awk '{print $2}
cmd = "ps -ef|grep 'remi/php" + version + "' |grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def getFpmAddress(version):
fpm_address = '/var/opt/remi/php{}/run/php-fpm/www.sock'.format(version)
php_fpm_file = getFpmConfFile(version)
try:
content = readFile(php_fpm_file)
tmp = re.findall(r"listen\s*=\s*(.+)", content)
if not tmp:
return fpm_address
if tmp[0].find('sock') != -1:
return fpm_address
if tmp[0].find(':') != -1:
listen_tmp = tmp[0].split(':')
if bind:
fpm_address = (listen_tmp[0], int(listen_tmp[1]))
else:
fpm_address = ('127.0.0.1', int(listen_tmp[1]))
else:
fpm_address = ('127.0.0.1', int(tmp[0]))
return fpm_address
except:
return fpm_address
def getPhpinfo(version):
stat = status(version)
if stat == 'stop':
return 'PHP[' + version + ']未启动,不可访问!!!'
sock_file = getFpmAddress(version)
root_dir = mw.getRootDir() + '/phpinfo'
mw.execShell("rm -rf " + root_dir)
mw.execShell("mkdir -p " + root_dir)
mw.writeFile(root_dir + '/phpinfo.php', '<?php phpinfo(); ?>')
sock_data = mw.requestFcgiPHP(sock_file, '/phpinfo.php', root_dir)
os.system("rm -rf " + root_dir)
phpinfo = str(sock_data, encoding='utf-8')
return phpinfo
def libConfCommon(version):
fname = getConf(version)
if not os.path.exists(fname):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(fname)
libpath = getPluginDir() + '/versions/phplib.conf'
phplib = json.loads(mw.readFile(libpath))
libs = []
tasks = mw.M('tasks').where(
"status!=?", ('1',)).field('status,name').select()
for lib in phplib:
lib['task'] = '1'
for task in tasks:
tmp = mw.getStrBetween('[', ']', task['name'])
if not tmp:
continue
tmp1 = tmp.split('-')
if tmp1[0].lower() == lib['name'].lower():
lib['task'] = task['status']
lib['phpversions'] = []
lib['phpversions'].append(tmp1[1])
if phpini.find(lib['check']) == -1:
lib['status'] = False
else:
lib['status'] = True
libs.append(lib)
return libs
def get_php_info(args):
return getPhpinfo(args['version'])
def get_lib_conf(data):
libs = libConfCommon(data['version'])
return mw.returnData(True, 'OK!', libs)
+3 -2
View File
@@ -26,12 +26,13 @@ function phpPost(method, version, args,callback){
},'json');
}
function phpPostCallbak(method, version, args,callback){
function phpPostCallback(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'php-yum';
req_data['func'] = method;
req_data['script']='index_php_yum';
args['version'] = version;
if (typeof(args) == 'string'){
@@ -593,7 +594,7 @@ function getPHPInfo_old(version) {
}
function getPHPInfo(version) {
phpPostCallbak('get_php_info', version, {}, function(data){
phpPostCallback('get_php_info', version, {}, function(data){
if (!data.status){
layer.msg(rdata.msg, { icon: 2 });
return;
+3 -2
View File
@@ -68,7 +68,7 @@ Install_lib()
echo "[${LIBNAME}]" >> $extIni
echo "zend_extension=${LIBNAME}.so" >> $extIni
systemctl restart php${version}-fpm
systemctl restart php${version}-fpm
echo '==========================================================='
echo 'successful!'
}
@@ -80,7 +80,8 @@ Uninstall_lib()
if [ -f $extIni ];then
rm -rf $extIni
fi
systemctl restart php${version}-fpm
echo '==============================================='
echo 'successful!'
}
+122
View File
@@ -0,0 +1,122 @@
#!/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")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sourcePath=${serverPath}/source/php
# https://www.sourceguardian.com/loaders.html
# support 52-83
LIBNAME=sg11
LIBV=0
sysName=`uname`
actionType=$1
version=$2
SG_VER=${version:0:1}.${version:1:2}
SORT_LIBNAME="10-${LIBNAME}"
extVer=`bash $curPath/lib.sh $version`
extFile=/opt/remi/php${version}/root/usr/lib64/php
extSoFile=$extFile/modules/${LIBNAME}.so
cfgDir=/etc/opt/remi/php${version}/php.d
extIni=${cfgDir}/10-${LIBNAME}.ini
if [ "$sysName" == "Darwin" ];then
BAK='_bak'
else
BAK=''
fi
Install_lib()
{
bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
if [ "$OSNAME" == 'macos' ];then
VERSION_ID=none
else
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
fi
echo "${OSNAME}:${VERSION_ID}"
DEFAULT_OSNAME=linux-x86_64
SUFFIX_NAME=lin
if [ "$OSNAME" == 'macos' ];then
DEFAULT_OSNAME=macosx
SUFFIX_NAME=dar
fi
if [ ! -f "$extFile" ];then
php_lib=$sourcePath/php_lib
mkdir -p $php_lib
mkdir -p $php_lib/sg11
if [ ! -f $php_lib/sg11_loaders.tar.bz2 ];then
curl -sSLo $php_lib/sg11_loaders.tar.bz2 https://www.sourceguardian.com/loaders/download/loaders.tar.bz2
echo "cd $php_lib && tar -jxvf $php_lib/sg11_loaders.tar.bz2 -C $php_lib/sg11"
cd $php_lib && tar -jxvf $php_lib/sg11_loaders.tar.bz2 -C $php_lib/sg11
fi
if [ ! -d $php_lib/sg11/macosx ];then
cd $php_lib && tar -jxvf $php_lib/sg11_loaders.tar.bz2 -C $php_lib/sg11
fi
cd $php_lib/sg11
if [ -f $php_lib/sg11/${DEFAULT_OSNAME}/ixed.${SG_VER}.${SUFFIX_NAME} ];then
cp -rf $php_lib/sg11/${DEFAULT_OSNAME}/ixed.${SG_VER}.${SUFFIX_NAME} $extSoFile
else
echo 'Not supported temporarily'
exit
fi
if [ "$OSNAME" == 'macos' ];then
xattr -c * $extSoFile
fi
fi
if [ ! -f "$extSoFile" ];then
echo "ERROR!"
return
fi
echo "" >> $extIni
echo "[${LIBNAME}]" >> $extIni
echo "extension=${LIBNAME}.so" >> $extIni
systemctl restart php${version}-fpm
echo '==========================================================='
echo 'successful!'
}
Uninstall_lib()
{
if [ -f $extIni ];then
rm -rf $extIni
fi
systemctl restart php${version}-fpm
echo '==============================================='
echo 'successful!'
}
if [ "$actionType" == 'install' ];then
Install_lib
elif [ "$actionType" == 'uninstall' ];then
Uninstall_lib
fi
+14
View File
@@ -96,6 +96,20 @@
"shell": "zend_optimizer.sh",
"check": "ZendOptimizer"
},
{
"name": "sg11",
"versions": [
"74",
"80",
"81",
"82",
"83"
],
"type": "脚本解密",
"msg": "用于解密SG11加密脚本!",
"shell": "sg11.sh",
"check": "sg11.so"
},
{
"name": "ionCube",
"versions": [
+1 -1
View File
@@ -9,7 +9,7 @@ implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
zend.enable_gc = On
expose_php = On
expose_php = Off
max_execution_time = 30
max_input_time = 60
max_input_vars = 1000
+1 -1
View File
@@ -9,7 +9,7 @@ implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
zend.enable_gc = On
expose_php = On
expose_php = Off
max_execution_time = 30
max_input_time = 60
max_input_vars = 1000
+1 -1
View File
@@ -9,7 +9,7 @@ implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
zend.enable_gc = On
expose_php = On
expose_php = Off
max_execution_time = 30
max_input_time = 60
max_input_vars = 1000
+2 -2
View File
@@ -16,7 +16,7 @@ function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.2.21
version=8.2.24
PHP_VER=82
Install_php()
{
@@ -57,7 +57,7 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then
fi
#检测文件是否损坏.
md5_file_ok=8cc44d51bb2506399ec176f70fe110f0c9e1f7d852a5303a2cd1403402199707
md5_file_ok=80a5225746a9eb484475b312d4c626c63a88a037d8e56d214f30205e1ba1411a
if [ -f $sourcePath/php/php-${version}.tar.xz ];then
md5_file=`sha256sum $sourcePath/php/php-${version}.tar.xz | awk '{print $1}'`
if [ "${md5_file}" != "${md5_file_ok}" ]; then
+2 -2
View File
@@ -15,7 +15,7 @@ function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)"
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.3.9
version=8.3.12
PHP_VER=83
Install_php()
{
@@ -56,7 +56,7 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then
fi
#检测文件是否损坏.
md5_file_ok=bf4d7b8ea60a356064f88485278bd6f941a230ec16f0fc401574ce1445ad6c77
md5_file_ok=f774e28633e26fc8c5197f4dae58ec9e3ff87d1b4311cbc61ab05a7ad24bd131
if [ -f $sourcePath/php/php-${version}.tar.xz ];then
md5_file=`sha256sum $sourcePath/php/php-${version}.tar.xz | awk '{print $1}'`
if [ "${md5_file}" != "${md5_file_ok}" ]; then
+4 -2
View File
@@ -87,8 +87,10 @@ Install_lib()
--with-gd \
--with-jpeg-dir \
--with-png-dir \
--with-freetype-dir=${serverPath}/lib/freetype_old
# --enable-gd-jis-conv
--with-webp-dir \
--with-zlib-dir \
--enable-gd-jis-conv
# --with-freetype-dir=${serverPath}/lib/freetype_old
# --enable-gd-native-ttf
make clean && make && make install && make clean
+4
View File
@@ -696,6 +696,8 @@ def setDbBackup():
os.system(cmd)
return mw.returnJson(True, 'ok')
def rootPwd():
return pSqliteDb('config').where('id=?', (1,)).getField('pg_root')
def importDbBackup():
args = getArgs()
@@ -1589,6 +1591,8 @@ if __name__ == "__main__":
print(getPgPort())
elif func == 'set_pg_port':
print(setPgPort())
elif func == 'root_pwd':
print(rootPwd())
elif func == 'get_db_list':
print(getDbList())
elif func == 'add_db':
+1 -1
View File
@@ -8,7 +8,7 @@
"coexist": false,
"install_pre_inspection":true,
"uninstall_pre_inspection":true,
"versions":["14","15","16"],
"versions":["14","15","16","17"],
"shell":"install.sh",
"checks":"server/postgresql",
"path":"server/postgresql",
+5 -2
View File
@@ -7,12 +7,15 @@ rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
# cd /www/server/mdserver-web/plugins/postgresql && bash install.sh install 16
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
type=$2
VERSION=(${type//./ })
pip install psycopg2-binary
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
@@ -25,7 +28,7 @@ if [ "${2}" == "" ];then
exit 0
fi
if [ ! -d $curPath/versions/$2 ];then
if [ ! -d $curPath/versions/$VERSION ];then
echo '缺少安装脚本2...'
exit 0
fi
@@ -40,7 +43,7 @@ if [ "${action}" == "uninstall" ];then
fi
fi
sh -x $curPath/versions/$2/install.sh $1
sh -x $curPath/versions/$VERSION/install.sh $1
if [ "${action}" == "install" ] && [ -d $serverPath/postgresql ];then
#初始化
+30 -8
View File
@@ -34,10 +34,10 @@ Install_App()
mkdir -p /home/postgres
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# if [ "$sysName" != "Darwin" ];then
# mkdir -p /var/log/mariadb
# touch /var/log/mariadb/mariadb.log
# fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
@@ -87,16 +87,38 @@ Install_App()
if [ -d $serverPath/postgresql ];then
echo "${VERSION}" > $serverPath/postgresql/version.pl
echo 'install successful' > $install_tmp
echo '安装postgresql成功'
else
echo 'install fail' > $install_tmp
echo '安装postgresql失败'
rm -rf ${postgreDir}/postgresql-${VERSION}.tar.bz2
fi
}
Uninstall_App()
{
rm -rf $serverPath/postgresql
echo '卸载完成' > $install_tmp
if [ -f /usr/lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /usr/lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f $serverPath/postgresql/initd/postgresql ];then
$serverPath/postgresql/initd/postgresql stop
fi
if [ -d $serverPath/postgresql ];then
rm -rf $serverPath/postgresql
fi
echo '卸载[postgresql]完成'
}
action=$1
+30 -8
View File
@@ -34,10 +34,10 @@ Install_App()
mkdir -p /home/postgres
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# if [ "$sysName" != "Darwin" ];then
# mkdir -p /var/log/mariadb
# touch /var/log/mariadb/mariadb.log
# fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
@@ -87,16 +87,38 @@ Install_App()
if [ -d $serverPath/postgresql ];then
echo "${VERSION}" > $serverPath/postgresql/version.pl
echo 'install successful' > $install_tmp
echo '安装postgresql成功'
else
echo 'install fail' > $install_tmp
echo '安装postgresql失败'
rm -rf ${postgreDir}/postgresql-${VERSION}.tar.bz2
fi
}
Uninstall_App()
{
rm -rf $serverPath/postgresql
echo '卸载完成' > $install_tmp
if [ -f /usr/lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /usr/lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f $serverPath/postgresql/initd/postgresql ];then
$serverPath/postgresql/initd/postgresql stop
fi
if [ -d $serverPath/postgresql ];then
rm -rf $serverPath/postgresql
fi
echo '卸载[postgresql]完成'
}
action=$1
+31 -9
View File
@@ -13,7 +13,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
postgreDir=${serverPath}/source/postgresql
VERSION=16.3
VERSION=16.4
# su - postgres -c "/www/server/postgresql/bin/pg_ctl start -D /www/server/postgresql/data"
@@ -34,10 +34,10 @@ Install_App()
mkdir -p /home/postgres
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# if [ "$sysName" != "Darwin" ];then
# mkdir -p /var/log/mariadb
# touch /var/log/mariadb/mariadb.log
# fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
@@ -87,16 +87,38 @@ Install_App()
if [ -d $serverPath/postgresql ];then
echo "${VERSION}" > $serverPath/postgresql/version.pl
echo '安装成功'
echo '安装postgresql成功'
else
echo '安装失败'
echo '安装postgresql失败'
rm -rf ${postgreDir}/postgresql-${VERSION}.tar.bz2
fi
}
Uninstall_App()
{
rm -rf $serverPath/postgresql
echo '卸载完成'
if [ -f /usr/lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /usr/lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f $serverPath/postgresql/initd/postgresql ];then
$serverPath/postgresql/initd/postgresql stop
fi
if [ -d $serverPath/postgresql ];then
rm -rf $serverPath/postgresql
fi
echo '卸载[postgresql]完成'
}
action=$1
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://www.postgresql.org/ftp/source/
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
postgreDir=${serverPath}/source/postgresql
VERSION=17.0
# su - postgres -c "/www/server/postgresql/bin/pg_ctl start -D /www/server/postgresql/data"
Install_App()
{
mkdir -p ${postgreDir}
echo '正在安装脚本文件...' > $install_tmp
if id postgres &> /dev/null ;then
echo "postgres uid is `id -u postgres`"
echo "postgres shell is `grep "^postgres:" /etc/passwd |cut -d':' -f7 `"
else
groupadd postgres
useradd -g postgres postgres
fi
if [ ! -d /home/postgres ];then
mkdir -p /home/postgres
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
# for stable installation
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -f ${postgreDir}/postgresql-${VERSION}.tar.bz2 ];then
wget --no-check-certificate -O ${postgreDir}/postgresql-${VERSION}.tar.bz2 --tries=3 https://ftp.postgresql.org/pub/source/v${VERSION}/postgresql-${VERSION}.tar.bz2
fi
if [ ! -d ${postgreDir}/postgresql-${VERSION} ];then
cd ${postgreDir} && tar -jxvf ${postgreDir}/postgresql-${VERSION}.tar.bz2
fi
if [ ! -d $serverPath/postgresql ];then
cd ${postgreDir}/postgresql-${VERSION} && ./configure \
--prefix=$serverPath/postgresql \
--with-openssl
# --with-pgport=33206
echo "cd ${postgreDir}/postgresql-${VERSION} && ./configure \
--prefix=$serverPath/postgresql \
--with-openssl"
# --with-pgport=33206
make -j${cpuCore} && make install && make clean
fi
if [ -d $serverPath/postgresql ];then
echo "${VERSION}" > $serverPath/postgresql/version.pl
echo '安装postgresql成功'
else
echo '安装postgresql失败'
rm -rf ${postgreDir}/postgresql-${VERSION}.tar.bz2
fi
}
Uninstall_App()
{
if [ -f /usr/lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /usr/lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f /lib/systemd/system/postgresql.service ];then
systemctl stop postgresql
systemctl disable postgresql
rm -rf /lib/systemd/system/postgresql.service
systemctl daemon-reload
fi
if [ -f $serverPath/postgresql/initd/postgresql ];then
$serverPath/postgresql/initd/postgresql stop
fi
if [ -d $serverPath/postgresql ];then
rm -rf $serverPath/postgresql
fi
echo '卸载[postgresql]完成'
}
action=$1
if [ "${1}" == "install" ];then
Install_App
else
Uninstall_App
fi
+4 -6
View File
@@ -15,10 +15,10 @@ databases 16
################################ SNAPSHOTTING #################################
save 900 100
save 300 1000
save 900 1000
save 300 10000
save 60 1000000
stop-writes-on-bgsave-error yes
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
@@ -44,7 +44,6 @@ maxmemory-policy volatile-ttl
############################## APPEND ONLY MODE ###############################
# appendonly no
# appendfsync always
@@ -53,8 +52,7 @@ maxmemory-policy volatile-ttl
# appendfilename "appendonly.aof"
# no-appendfsync-on-rewrite no
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
+3
View File
@@ -1,3 +1,5 @@
# sysctl -w fs.file-max=6553560
fs.file-max = 6553560
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
@@ -33,6 +35,7 @@ net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024 65000
vm.overcommit_memory=1
vm.max_map_count = 262144
# error:table full, dropping packet.
net.nf_conntrack_max = 25000000
+1 -1
View File
@@ -42,7 +42,7 @@ def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|end
# https://t.me/gjgzs2022 | 22/m | @GJ_gzs
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,9/15 | @baleite
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,12/15 | @baleite
# 综合包网/NG接口开户 | 28/m | 6m | next,10/28 | @aabbcx888
# 实名认证/过人脸🕵️‍♀️各种账号处理✅ | 30/m| next,12/30 | @nngzs
# 桃花资源采集| 13/m| next,1/13 | @xiaolizi1122
@@ -51,7 +51,7 @@ def send_msg(bot, tag='ad', trigger_time=300):
# 信号只在一个周期内执行一次|end
# https://t.me/gjgzs2022 | 22/m | @GJ_gzs
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,9/15 | @baleite
# https://zhaoziyuan1.cc | web | 15/m | 2m | next,12/15 | @baleite
# 综合包网/NG接口开户 | 28/m | 6m | next,10/28 | @aabbcx888
# 实名认证/过人脸🕵️‍♀️各种账号处理✅ | 30/m| next,12/30 | @nngzs
# 桃花资源采集| 13/m| next,1/13 | @xiaolizi1122
+1
View File
@@ -26,6 +26,7 @@
</div>
<script type="text/javascript">
resetPluginWinWidth(1000);
$.getScript( "/plugins/file?name=webhook&f=js/webhook.js",function() {
getHookList();
});
+63
View File
@@ -0,0 +1,63 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'webhook'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getCfgFilePath():
return getServerDir() + "/cfg.json"
def getCfg():
cfg = getCfgFilePath()
if not os.path.exists(cfg):
initCfg()
data = mw.readFile(cfg)
data = json.loads(data)
return data
def runShellArgs(args):
data = getCfg()
for i in range(len(data)):
if data[i]['access_key'] == args['access_key']:
script_dir = getServerDir() + "/scripts"
shellFile = script_dir + '/' + args['access_key']
param = args['params']
if param == '':
param = 'no-parameters'
param = re.sub("\"", '', param)
cmd = "bash {} {} >> {}.log 2>&1 &".format(
shellFile, param, shellFile)
# print(cmd)
os.system(cmd)
data[i]['count'] += 1
data[i]['uptime'] = int(time.time())
mw.writeFile(getCfgFilePath(), json.dumps(data))
return mw.returnJson(True, '运行成功!')
return mw.returnJson(False, '指定Hook不存在!')
+3 -1
View File
@@ -945,7 +945,7 @@ function _M.match_spider(self, ua)
end
-- Curl|Yahoo|HeadlessChrome|包含bot|Wget|Spider|Crawler|Scrapy|zgrab|python|java|Adsbot|DuckDuckGo
find_spider, _ = ngx.re.match(ua, "(Yahoo|Slurp|DuckDuckGo|Semrush|Spider|Bot)", "ijo")
find_spider, _ = ngx.re.match(ua, "(Yahoo|Slurp|DuckDuckGo|Semrush|Spider|Bot|crawler)", "ijo")
if find_spider then
spider_match = string.lower(find_spider[0])
if string.find(spider_match, "yahoo", 1, true) then
@@ -960,6 +960,8 @@ function _M.match_spider(self, ua)
spider_name = "other"
elseif string.find(spider_match, "bot", 1, true) then
spider_name = "other"
elseif string.find(spider_match, "crawler", 1, true) then
spider_name = "other"
end
return true, spider_name, spider_table[spider_name]
end
+8 -2
View File
@@ -1,9 +1,15 @@
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,POST' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Origin' $http_origin always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With, Cache-Control' always;
#add_header Access-Control-Allow-Origin *;
#add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
#add_header Access-Control-Allow-Origin *;
#add_header Access-Control-Allow-Methods *;
#add_header Access-Control-Allow-Header *;

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