diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 148367b1..502f87f3 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,32 +1,45 @@
-name: 批量保活进程
-
-on:
- schedule:
- # 使用cron表达式定义任务运行的时间
- # github使用utc时间
- - cron: '3 2 * * *' #波兰凌晨3点3分
- workflow_dispatch:
-
-jobs:
- deploy:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: 安装依赖
- run: |
- sudo apt-get install sshpass
- sudo apt-get install jq
-
- - name: 登录各个serv00并执行保活脚本
- env:
- HOSTS_JSON: ${{ secrets.HOSTS_JSON }}
- TELEGRAM_TOKEN: ${{secrets.TELEGRAM_TOKEN}}
- TELEGRAM_USERID: ${{secrets.TELEGRAM_USERID}}
- WXSENDKEY: ${{secrets.WXSENDKEY}}
- SENDTYPE: ${{secrets.SENDTYPE}}
- run: |
- chmod +x ./revive.sh
- ./revive.sh
+name: 批量保活进程
+
+on:
+ schedule:
+ # 使用cron表达式定义任务运行的时间
+ # github使用utc时间
+ - cron: '3 22 * * *' #北京时间6点
+ workflow_dispatch:
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: 安装依赖
+ run: |
+ sudo apt-get install sshpass
+ sudo apt-get install jq
+ sudo apt-get install connect-proxy
+ sudo apt-get install -y netcat-openbsd
+
+ - name: 登录各个serv00并执行保活脚本
+ env:
+ HOSTS_JSON: ${{ secrets.HOSTS_JSON }}
+ TELEGRAM_TOKEN: ${{secrets.TELEGRAM_TOKEN}}
+ TELEGRAM_USERID: ${{secrets.TELEGRAM_USERID}}
+ WXSENDKEY: ${{secrets.WXSENDKEY}}
+ WXPUSH_URL: ${{secrets.WXPUSH_URL}}
+ WX_TOKEN: ${{secrets.WX_TOKEN}}
+ SENDTYPE: ${{secrets.SENDTYPE}}
+ BUTTON_URL: ${{secrets.BUTTON_URL}}
+ AUTOUPDATE: ${{vars.AUTOUPDATE}}
+ LOGININFO: ${{vars.LOGININFO}}
+ LOGINONCE: ${{vars.LOGINONCE}}
+ PROXY_HOST: ${{secrets.PROXY_HOST}}
+ PROXY_PORT: ${{secrets.PROXY_PORT}}
+ PROXY_USER: ${{secrets.PROXY_USER}}
+ PROXY_PASS: ${{secrets.PROXY_PASS}}
+
+ run: |
+ chmod +x ./revive.sh
+ ./revive.sh
diff --git a/.github/workflows/keep.yml b/.github/workflows/keep.yml
new file mode 100644
index 00000000..e38ebaea
--- /dev/null
+++ b/.github/workflows/keep.yml
@@ -0,0 +1,36 @@
+name: 批量访问保活进程
+
+on:
+ schedule:
+ # 使用cron表达式定义任务运行的时间
+ #github最小时间间隔为10分钟
+ - cron: '*/10 * * * *'
+ workflow_dispatch:
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: 安装依赖
+ run: |
+ sudo apt-get install jq
+
+ - name: 访问各个serv00并执行保活脚本
+ env:
+ HOSTS_JSON: ${{ secrets.HOSTS_JSON }}
+ TELEGRAM_TOKEN: ${{secrets.TELEGRAM_TOKEN}}
+ TELEGRAM_USERID: ${{secrets.TELEGRAM_USERID}}
+ WXPUSH_URL: ${{secrets.WXPUSH_URL}}
+ WX_TOKEN: ${{secrets.WX_TOKEN}}
+ SENDTYPE: ${{secrets.SENDTYPE}}
+ BUTTON_URL: ${{secrets.BUTTON_URL}}
+ AUTOUPDATE: ${{vars.AUTOUPDATE}}
+ LOGININFO: ${{vars.LOGININFO}}
+ TOKEN: ${{secrets.TOKEN}}
+ run: |
+ chmod +x ./revive_node.sh
+ ./revive_node.sh
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index ecdcaa87..17a833cc 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -1,40 +1,40 @@
-name: Sync Fork with Upstream
-
-on:
- schedule:
- - cron: '0 19 * * *'
- workflow_dispatch:
-
-permissions:
- contents: write
-
-jobs:
- sync_latest_from_upstream:
- name: Sync latest commits from upstream repo
- runs-on: ubuntu-latest
- if: ${{ github.event.repository.fork }}
-
- steps:
- # Step 1: run a standard checkout action
- - name: Checkout target repo
- uses: actions/checkout@v3
-
- # Step 2: run the sync action
- - name: Sync upstream changes
- id: sync
- uses: aormsby/Fork-Sync-With-Upstream-action@v3.4
- with:
- upstream_sync_repo: frankiejun/serv00-play
- upstream_sync_branch: main
- target_sync_branch: main
- target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set
- exclude: |
- .github/workflows/sync.yml
-
- - name: Check for errors
- if: failure()
- run: echo "Sync failed! Please check the logs for more details."
-
- - name: Sync success message
- if: success()
- run: echo "Sync completed successfully!"
+name: Sync Fork with Upstream
+
+on:
+ schedule:
+ - cron: '0 19 * * *'
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ sync_latest_from_upstream:
+ name: Sync latest commits from upstream repo
+ runs-on: ubuntu-latest
+ if: ${{ github.event.repository.fork }}
+
+ steps:
+ # Step 1: run a standard checkout action
+ - name: Checkout target repo
+ uses: actions/checkout@v3
+
+ # Step 2: run the sync action
+ - name: Sync upstream changes
+ id: sync
+ uses: aormsby/Fork-Sync-With-Upstream-action@v3.4
+ with:
+ upstream_sync_repo: frankiejun/serv00-play
+ upstream_sync_branch: main
+ target_sync_branch: main
+ target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set
+ exclude: |
+ .github/workflows/sync.yml
+
+ - name: Check for errors
+ if: failure()
+ run: echo "Sync failed! Please check the logs for more details."
+
+ - name: Sync success message
+ if: success()
+ run: echo "Sync completed successfully!"
diff --git a/.gitignore b/.gitignore
index 2f3cc09a..41d77cf5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,12 @@
-*.log
-*.json
-*.out
-*.js
-a.*
-*.swp
-vmess/node_modules
-vmess/list
-vmess/cloudflared
-vless/node_modules
-tools/
\ No newline at end of file
+*.log
+*.json
+*.out
+*test
+a.*
+*.swp
+vmess/node_modules
+vmess/list
+vmess/cloudflared
+vless/node_modules
+tools/
+.vscode/
diff --git a/LICENSE b/LICENSE
index ebc743d4..079cec5e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,13 +1,13 @@
-Copyright [2024] [饭奇骏]
-
-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.
+Copyright [2024] [饭奇骏]
+
+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.
diff --git a/README.md b/README.md
index 6871e676..189f1d60 100644
--- a/README.md
+++ b/README.md
@@ -1,95 +1,114 @@
-# serv00 上的一些应用,包括 argo+vmess/vmess+ws/hy2/socks5/mtproto/alist/哪吒探针/sun-panel/webssh 等, 自动化部署、批量保号、进程防杀、消息推送
-
-💖 如果你在用这个项目,请给我打个 star,好让我知道有多少人从这个项目中受益。
-
-## 前置工作
-
-1. 你需要有一个 serv00 帐号
-2. 首次运行,无需使用面板,选 1 安装 serv00-play 后,选 13 按回车,它会自动重新登录,输入 ss 回车进入界面。(以后都是输入 ss 回车进入界面)
-
-## 安装说明
-
-```s
-bash <(curl -Ls https://raw.githubusercontent.com/frankiejun/serv00-play/main/start.sh)
-```
-
-## 变量说明
-
-| 变量名 | 示例 | 备注 |
-| --------------- | ------ | ---------------------------------------- |
-| HOSTS_JSON | 见示例 | 可存放 n 个服务器信息 |
-| TELEGRAM_TOKEN | 略 | telegram 机器人的 token |
-| TELEGRAM_USERID | 略 | 待通知的 teltegram 用户 ID |
-| WXSENDKEY | 略 | server 酱的 sendkey,用于接收微信消息 |
-| SENDTYPE | 3 | 选择推送方式,1.Telegram, 2.微信, 3.都有 |
-
-各主机保活时可不必输入消息通知参数,由 github 同一配置参数。
-
-如果主机上配置了消息推送参数,则优先级大于 github 上的配置。
-
-## action 保活内容
-
-1.定时自动登录各个主机,起到保号作用(因 serv00 需要每 3 个月登录一次)
-2.执行兜底保活策略
-3.检查主机上保活用的 cronjob 是否被删,若被删重建保活 cronjob
-4.自动更新 serv00-play 代码
-5.同步更新 telegram、微信等参数
-6.登录失败有 TG 消息通知,提醒可能封号(平时正常不会给你发消息,发消息之时便是你封号之日)
-
-## 消息推送
-
-支持向 Telegram 和微信用户发送通知
-
-关于如何配置 Telegram 以实现消息推送,可以看 [这个视频](https://www.youtube.com/watch?v=l8fPnMfq86c&t=3s)
-
-关于微信的配置,目前使用第三方平台提供的功能,可以到 [这里](https://sct.ftqq.com/r/13223) 注册并登录 server 酱,取得 sendKey
-
-## HOSTS_JSON 的配置实例
-
-```js
- {
- "info": [
- {
- "host": "s2.serv00.com",
- "username": "kkk",
- "port": 22,
- "password": "fdsafjijgn"
- },
- {
- "host": "s2.serv00.com",
- "username": "bbb",
- "port": 22,
- "password": "fafwwwwazcs"
- }
- ]
-}
-```
-
-## 安装说明视频
-
-安装使用说明可以看[这里](https://youtu.be/bpYV8r85F-8)
-临时隧道已失效,请使用固定隧道名,[如何申请固定隧道名](https://youtu.be/KyMvtWknu-k)
-argo+vmess 的搭建教学看[这里](https://youtu.be/nmb2F6uBKsg?si=v8twWIkIjsN8UYb-)
-
-由于本项目一直在迭代开发,界面会有些变化,想详细了解,可以看这一系列视频[serv00-play 系列](https://www.youtube.com/playlist?list=PLaMnUIjE3d5zArqlLzTU2oMZ0h-5VP6C0)
-
-## 赞助
-
- [点击展开] 请作者喝杯咖啡 ~🧧
-_捐赠将是对我最大的支持,它将激励我持续的创新和创作。_
-
-
-
-- **USDT-TRC20:** `TUa2hLirmyq6tUPpfxHuMmWJExR91vHo5t`
-
-
-
-## 项目鸣谢
-
-[nekohasekai](https://github.com/SagerNet/sing-box)、[AlistGo](https://github.com/AlistGo/alist)、[9seconds](https://github.com/9seconds/mtg)、[eooce](https://github.com/eooce)、[nrootconauto](https://github.com/nrootconauto/MrChrootBSD)、[nezhahq](https://github.com/nezhahq/agent)、[huashengdun](https://github.com/huashengdun/webssh)、[hslr-s](https://github.com/hslr-s/sun-panel)
-[yangtb2024](https://github.com/yangtb2024/OneTimeMessagePHP)
-
-## 免责声明
-
-本程序仅供学习了解, 非盈利目的,请于下载后 24 小时内删除, 不得用作任何商业用途, 代码、数据及图片均有所属版权, 如转载须注明来源。
-使用本程序必循遵守部署免责声明。使用本程序必循遵守部署服务器所在地、所在国家和用户所在国家的法律法规, 程序作者不对使用者任何不当行为负责。
+# serv00/hostuno 上的一些应用,包括 argo+vmess/vmess+ws/hy2/socks5/mtproto/alist/哪吒探针|面板/sun-panel/webssh 等, 自动化部署、批量保号、进程防杀、消息推送
+
+💖 如果你在用这个项目,请给我打个 star,好让我知道有多少人从这个项目中受益。
+
+## 前置工作
+
+1. 你需要有一个 serv00/hostuno 帐号
+2. 运行安装命令后重新登录,输入 ss 回车进入界面。(以后都是输入 ss 回车进入界面)
+
+## 安装说明
+
+```s
+bash <(curl -Ls https://raw.githubusercontent.com/frankiejun/serv00-play/main/start.sh) --install
+```
+
+## 变量说明
+
+| 变量名 | 示例 | 是否必须 | 变量类型 | 备注 |
+| --------------- | ----------- | -------- | ---------- | -------------------------------------------------------------------------------- |
+| HOSTS_JSON | 见示例 | ✅ | secrets | 可存放 n 个服务器信息 (必选) |
+| TELEGRAM_TOKEN | 略 | ❌ | secrets | telegram 机器人的 token (发送 TG 消息必选) |
+| TELEGRAM_USERID | 略 | ❌ | secrets | 待通知的 teltegram 用户 ID (发送 TG 消息必选) |
+| ~~WXSENDKEY~~ | ~~略~~ | ~~❌~~ | ~~secrets~~ | ~~server 酱的 sendkey,用于接收微信消息 (发送微信消息必选)~~ |
+| WXPUSH_URL | 略 | ❌ | secrets | [wxpush](https://github.com/frankiejun/wxpush)项目的请求url |
+| WX_TOKEN | 略 | ❌ | secrets | [wxpush](https://github.com/frankiejun/wxpush)项目的API_TOKEN |
+| SENDTYPE | 1 | ❌ | secrets | 选择推送方式,1.Telegram, 2.微信, 3.都有 (发送消息必选) |
+| BUTTON_URL | 略 | ❌ | secrets | 设置 TG 推送消息中的按钮链接 (发送 TG 消息可选),支持#HOST,#USER,#PASS 等变量。 |
+| AUTOUPDATE | Y/N | ❌ | variable | 设置是否自动更新服务器上的代码,设置在 variable 变量中,值为 Y/N(默认: Y) |
+| LOGININFO | Y/N | ❌ | variable | 在 variable 变量中设置(默认为 N),Y:发送登录汇总消息 N:只在登录失败时发送 |
+| LOGINONCE | Y/N | ❌ | variable | 在 variable 变量中设置(默认为 N),Y:每天只登录一个账号 N:每天登录所有账号送 |
+| TOKEN | 123456 | ❌ | secrets | 网页保活(keepalive)的密钥(必选) |
+| PROXY_HOST | 127.0.0.1 | ❌ | secrets | 代理服务器地址 (可选) |
+| PROXY_PORT | 1080 | ❌ | secrets | 代理服务器端口 (可选) |
+| PROXY_USER | user | ❌ | secrets | 代理服务器用户名 (可选) |
+| PROXY_PASS | password | ❌ | secrets | 代理服务器密码 (可选) |
+
+各主机保活时可不必输入消息通知参数,由 github 同一配置参数。
+
+如果主机上配置了消息推送参数,则优先级大于 github 上的配置。
+
+## action 保活内容
+
+1.定时自动登录各个主机,起到保号作用(因 serv00 需要每 3 个月登录一次)
+2.执行兜底保活策略
+3.检查主机上保活用的 cronjob 是否被删,若被删重建保活 cronjob
+4.自动更新 serv00-play 代码
+5.同步更新 telegram、微信等参数
+6.默认情况下只有登录失败才有 TG 消息通知,提醒可能封号(平时正常不会给你发消息,发消息之时便是你封号之日)
+也可以设定 LOGININFO=Y,每次保活都会做汇总通知(但相信我,你不会喜欢这个功能)
+7.keepalive 保活虽然不做 ssh 登录,但一样有延续服务器有效期的效果(不再需要 3 月一登)。
+
+## 消息推送
+
+支持向 Telegram 和微信用户发送通知
+
+关于如何配置 Telegram 以实现消息推送,可以看 [这个视频](https://www.youtube.com/watch?v=l8fPnMfq86c&t=3s)
+
+关于微信的配置,使用我的项目[wxpush](https://github.com/frankiejun/wxpush), 不会配可以看[这个视频](https://youtu.be/sE1Kcol_XRs?si=G-UbUGlMhyysv-US)
+
+
+## HOSTS_JSON 的配置实例
+
+```js
+ {
+ "info": [
+ {
+ "host": "s2.serv00.com",
+ "username": "kkk",
+ "port": 22,
+ "password": "fdsafjijgn"
+ },
+ {
+ "host": "s2.serv00.com",
+ "username": "bbb",
+ "port": 22,
+ "password": "fafwwwwazcs"
+ }
+ ]
+}
+```
+
+## 安装说明视频
+
+安装使用说明可以看[这里](https://youtu.be/ZCr7YiQX8Qs)
+临时隧道已失效,请使用固定隧道名,[如何申请固定隧道名](https://youtu.be/KyMvtWknu-k)
+argo+vmess 的搭建教学看[这里](https://youtu.be/nmb2F6uBKsg?si=v8twWIkIjsN8UYb-)
+
+由于本项目一直在迭代开发,界面会有些变化,想详细了解,可以看这一系列视频[serv00-play 系列](https://www.youtube.com/playlist?list=PLaMnUIjE3d5zArqlLzTU2oMZ0h-5VP6C0)
+
+## 赞助
+
+ [点击展开] 请作者喝杯咖啡 ~🧧
+_捐赠将是对我最大的支持,它将激励我持续的创新和创作。捐赠>=5u, 可联系我加入饭友会会员群, 捐赠>=10u, 加入赞助人感谢名单_
+
+
+
+- **USDT-TRC20:** `TUa2hLirmyq6tUPpfxHuMmWJExR91vHo5t`
+
+
+
+| 赞助人 | 赞助方式 | 备注 |
+| ---------------------------------------------------------------------------------------------------------------------- | ------------------------ | ---- |
+| [YXVM](https://support.nodeget.com/page/promotion?id=105) 和 [NodeSupport](https://github.com/NodeSeekDev/NodeSupport) | 赞助本项目提供永久服务器 | -- |
+
+## 项目鸣谢
+
+[nekohasekai](https://github.com/SagerNet/sing-box)、[AlistGo](https://github.com/AlistGo/alist)、[9seconds](https://github.com/9seconds/mtg)、[eooce](https://github.com/eooce)、[nrootconauto](https://github.com/nrootconauto/MrChrootBSD)、[nezhahq](https://github.com/nezhahq/agent)、[huashengdun](https://github.com/huashengdun/webssh)、[hslr-s](https://github.com/hslr-s/sun-panel)、[yangtb2024](https://github.com/yangtb2024/OneTimeMessagePHP)
+
+测试人员: [ryty1](https://github.com/ryty1), [fgr178707](https://github.com/fgr178707)
+
+## 免责声明
+
+本程序仅供学习了解, 非盈利目的,请于下载后 24 小时内删除, 不得用作任何商业用途, 代码、数据及图片均有所属版权, 如转载须注明来源。
+使用本程序必循遵守部署免责声明。使用本程序必循遵守部署服务器所在地、所在国家和用户所在国家的法律法规, 程序作者不对使用者任何不当行为负责。
diff --git a/domains-support/websites/christmas.html b/domains-support/websites/christmas.html
new file mode 100644
index 00000000..7f473137
--- /dev/null
+++ b/domains-support/websites/christmas.html
@@ -0,0 +1,265 @@
+
+
+
+
+
+ 圣诞快乐 - 暖心贺卡
+
+
+
+
+
+
+ 您的浏览器不支持 audio 元素。
+
+
+
+
+
+ 🎵
+
+
+
+ 🛷🦌🎅
+
+
+
+
MERRY CHRISTMAS
+
+
+
愿你的圣诞充满温馨与喜悦
+
在这个繁星闪烁的夜晚,所有的愿望都能成真 ✨
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/domains-support/websites/deyiedu.html b/domains-support/websites/deyiedu.html
new file mode 100644
index 00000000..f6db1c9e
--- /dev/null
+++ b/domains-support/websites/deyiedu.html
@@ -0,0 +1,269 @@
+
+
+
+
+
+ 德一教育 - 后台管理系统
+
+
+
+
+
+
+
+
diff --git a/domains-support/websites/game.html b/domains-support/websites/game.html
new file mode 100644
index 00000000..a6285772
--- /dev/null
+++ b/domains-support/websites/game.html
@@ -0,0 +1,1012 @@
+
+
+
+
+
+ 游戏殿堂 - 游戏资讯与社区
+
+
+
+
+
+
+
+
+
+
+
+
+
+
次世代游戏体验
+
探索最新发布的AAA大作,感受前所未有的视觉冲击和沉浸式游戏体验。从开放世界到竞技对战,总有一款适合你。
+
立即体验
+
+
+
+
+
+
独立游戏精选
+
发现那些充满创意和艺术感的独立游戏作品。这些游戏或许没有庞大的预算,却有着独特的玩法和感人的故事。
+
发现独立游戏
+
+
+
+
+
+
竞技游戏联赛
+
加入全球玩家的竞技场,体验紧张刺激的电竞赛事。从新手到职业选手,这里有你展示实力的舞台。
+
加入比赛
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
在广阔的宇宙中展开史诗般的冒险,探索未知星球,与外星种族建立联系,揭开古老文明的神秘面纱。
+
+
+ 角色扮演
+ 开放世界
+ 科幻
+
+
+
+
+
+
+
+
+
+
+
+
+
第一人称战术射击游戏,带领精英小队执行高风险任务。体验真实的武器系统和团队协作玩法。
+
+
+ 第一人称射击
+ 战术
+ 多人合作
+
+
+
+
+
+
+
+
+
+
+
+
+
建立你的帝国,从石器时代发展到太空时代。管理资源,发展科技,征服敌对文明,成为历史上最伟大的统治者。
+
+
+ 策略
+ 模拟
+ 历史
+
+
+
+
+
+
+
+
+
+
+
+
+
一段关于生命、死亡和情感的动人旅程。通过精美的艺术风格和感人的故事,探索人类情感的深度。
+
+
+ 独立游戏
+ 冒险
+ 情感叙事
+
+
+
+
+
+
+
+
+
+
+
+
+
体验最真实的赛车模拟,驾驶数百款授权车辆在全球知名赛道上驰骋。从街头赛到专业赛道,满足所有赛车爱好者的需求。
+
+
+ 竞速
+ 模拟
+ 体育
+
+
+
+
+
+
+
+
+
+
+
+
+
在一所魔法学校中,学习各种魔法咒语,解开古老谜题,与同学建立友谊,共同对抗威胁魔法世界的黑暗力量。
+
+
+ 角色扮演
+ 魔法
+ 冒险
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
人力资源管理系统 - 登录
+
+
+
+
+
+
+
+
diff --git a/domains-support/websites/resume.html b/domains-support/websites/resume.html
new file mode 100644
index 00000000..da5a497c
--- /dev/null
+++ b/domains-support/websites/resume.html
@@ -0,0 +1,146 @@
+
+
+
+
+
+
Li Ming's Resume
+
+
+
+
+
+
+
+
+ Personal Information
+
+
Name: Li Ming
+
Date of Birth: May 1, 1995
+
Email: liming@gmail.com
+
Phone: +86 138 6666 8888
+
Address: Haidian District, Beijing, China
+
+
+
+
+ Education
+
+
+
Tsinghua University, Department of Computer Science - Bachelor's Degree
+
Graduation Date: June 2022
+
Major Courses: Data Structures and Algorithms, Computer Networks, Operating Systems, Artificial Intelligence, Machine Learning
+
+
+
+
+
+ Work Experience
+
+
+
Tencent - Software Engineer
+
Employment Period: July 2022 - December 2024
+
Job Description: Involved in the architecture design and development of Tencent Cloud Platform, optimized system performance, and maintained backend services for company products. Led a cross-team project that successfully improved data processing efficiency.
+
+
+
ByteDance - Backend Engineer
+
Employment Period: January 2024 - Present
+
Job Description: Responsible for backend service development and optimization for a short-video platform, wrote efficient API interfaces using Python and Go, and performed system tuning to ensure service stability under high concurrency environments.
+
+
+
+
+
+ Skills
+
+
+ Proficient in Python, Java, Go, and other programming languages
+ Deep understanding of data structures and algorithms, capable of solving problems efficiently
+ Familiar with Linux operating system, capable of system performance optimization and troubleshooting
+ Experienced in developing and maintaining large-scale distributed systems
+ Familiar with common database technologies such as MySQL, Redis, and MongoDB
+ Strong teamwork and communication skills
+
+
+
+
+
+ Project Experience
+
+
+
Online Education Platform
+
Project Description: Designed and developed an online education platform that supports live video streaming, courseware sharing, and interaction. Responsible for backend development, optimized video streaming and real-time data interaction, enhancing user experience.
+
+
+
Social Media Analytics System
+
Project Description: Participated in the development of a social media data analytics system that can capture and analyze data from social platforms in real time, helping businesses monitor brand sentiment. Optimized data storage and retrieval performance.
+
+
+
+
+
+ Language Skills
+
+
Chinese: Native
+
English: Fluent (TOEFL 100)
+
+
+
+
+
+
+
+
diff --git a/domains-support/websites/sakura.html b/domains-support/websites/sakura.html
new file mode 100644
index 00000000..7658a8c8
--- /dev/null
+++ b/domains-support/websites/sakura.html
@@ -0,0 +1,225 @@
+
+
+
+
+
+
欢迎来到xx的博客
+
+
+
+
+
+
+
+
+
+
+
+
+
欢迎来到xx的博客
+
+
+
春日赏樱小记
+
2025年3月15日
+
+ 今日阳光明媚,我独自前往城郊的樱花园赏花。园中樱花已盛开七分,粉白相间,美不胜收。微风拂过,花瓣纷纷扬扬落下,宛如一场粉色的雪。
+
+
+ 游人如织,却不觉拥挤。或许是被这美景所感染,大家都轻声细语,生怕惊扰了这份宁静。我在一棵古老的樱花树下小憩,看着阳光透过花瓣在地上投下斑驳的影子,心中无比平静。
+
+
+ 樱花花期短暂,正因如此才更显珍贵。人生亦如是,美好的事物总是转瞬即逝,我们更应珍惜当下,把握每一个绽放的瞬间。
+
+
+
+
+
学习前端开发的感悟
+
2025年2月28日
+
+ 最近开始系统地学习前端开发,从HTML、CSS到JavaScript,一步步构建自己的知识体系。虽然有时会遇到困难,但解决问题的过程也充满了乐趣。
+
+
+ 今天完成了这个博客网站的基本框架,虽然还很简陋,但看到自己的想法通过代码变成现实,那种成就感是无可比拟的。特别是实现了樱花飘落的效果,让整个页面生动起来。
+
+
+ 学习编程就像是在学习一门新的语言,通过这种语言,我们可以与计算机交流,创造出无限可能。期待未来能做出更多有趣的项目!
+
+
+
+
+
+
© 2025 xx的博客 - 由serv00-play搭建
+
+
+
+
+
diff --git a/keepalive.sh b/keepalive.sh
index a00b3d95..e13de23c 100644
--- a/keepalive.sh
+++ b/keepalive.sh
@@ -1,183 +1,273 @@
#!/bin/bash
-
installpath="$HOME"
source ${installpath}/serv00-play/utils.sh
+LOCKFILE="$installpath/serv00-play/.keepalive.lock"
+
+# 检查是否已经有一个实例在运行
+if [ -e "$LOCKFILE" ]; then
+ echo "另一个实例正在运行,退出..."
+ exit 1
+fi
+
+# 创建锁文件
+touch "$LOCKFILE"
+
+# 定义清理函数
+cleanup() {
+ rm -f "$LOCKFILE"
+ exit
+}
+
+# 捕获脚本退出信号并调用清理函数
+trap cleanup INT TERM EXIT
+
autoUp=$1
sendtype=$2
TELEGRAM_TOKEN="$3"
TELEGRAM_USERID="$4"
WXSENDKEY="$5"
+BUTTON_URL="$6"
+PASS="$7"
+WXPUSH_URL="$8"
+WX_TOKEN="$9"
+autoUpdateHyIP="${10}"
+#echo "TELEGRAM_TOKEN=$TELEGRAM_TOKEN, TELEGRAM_USERID=$TELEGRAM_USERID,WXSENDKEY=$WXSENDKEY,BUTTON_URL=$BUTTON_URL,pass=$PASS"
checkHy2Alive() {
- if ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
- return 0
- else
- return 1
- fi
+ if ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
+ return 0
+ else
+ return 1
+ fi
}
-
sendMsg() {
- local msg=$1
- if [ -n "$msg" ]; then
- cd $installpath/serv00-play
- msg="Host:$host, user:$user, $msg"
- if [ "$sendtype" == "1" ]; then
- ./tgsend.sh "$msg"
- elif [ "$sendtype" == "2" ]; then
- ./wxsend.sh "$msg"
- elif [ "$sendtype" == "3" ]; then
- ./tgsend.sh "$msg"
- ./wxsend.sh "$msg"
- fi
- fi
+ local msg=$1
+ if [ -n "$msg" ]; then
+ cd $installpath/serv00-play
+ msg="Host:$host, user:$user, $msg"
+ if [ "$sendtype" == "1" ]; then
+ ./tgsend.sh "$msg"
+ elif [ "$sendtype" == "2" ]; then
+ ./wxsend.sh "$msg"
+ elif [ "$sendtype" == "3" ]; then
+ ./tgsend.sh "$msg"
+ ./wxsend.sh "$msg"
+ fi
+ fi
+}
+
+cleanUselessProc() {
+ # 获取域名列表
+ local l_domains=$(ps aux | awk '{ print $11 $14}' | grep node | awk -F: '{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}')
+
+ echo "开始检查无用进程..."
+
+ # 直接使用devil列表进行查找
+ for domain in $l_domains; do
+ echo "检查域名: $domain"
+
+ # 在devil列表输出中查找包含该域名的行
+ result=$(devil www list | grep -w "$domain")
+
+ if [ -z "$result" ]; then
+ echo "发现无用进程,准备删除: $domain"
+ pgrep -f "$domain" | xargs kill
+ fi
+ done
}
checkResetCron() {
- echo "run checkResetCron"
- local msg=""
- cd ${installpath}/serv00-play/
- crontab -l | grep keepalive
- if ! crontab -l | grep keepalive; then
- msg="crontab记录被删过,并且已重建。"
- tm=$(jq -r ".chktime" config.json)
- addCron "$tm"
- sendMsg $msg
- fi
+ echo "run checkResetCron"
+ local msg=""
+ cd ${installpath}/serv00-play/
+ tm=$(jq -r ".chktime" config.json)
+ if [ "$tm" == "null" ]; then
+ return
+ fi
+ crontab -l | grep keepalive
+ if ! crontab -l | grep keepalive; then
+ msg="crontab记录被删过,并且已重建。"
+ addCron "$tm"
+ sendMsg $msg
+ fi
}
#构建消息配置文件
-makeMsgConfig(){
- echo "构造消息配置文件..."
- cat > msg.json <
msg.json </dev/null 2>&1 &
+ local workedir="${installpath}/serv00-play/nezha"
+ cd ${workedir}
+ local config="nezha.json"
+ if [[ ! -e "$config" ]]; then
+ red "未安装哪吒探针,请先进行安装!"
+ return 1
+ fi
+ nezha_domain=$(jq -r ".nezha_domain" $config)
+ nezha_port=$(jq -r ".nezha_port" $config)
+ nezha_pwd=$(jq -r ".nezha_pwd" $config)
+ ver=$(jq -r ".version" $config)
+ tls=$(jq -r ".tls" $config)
+
+ if checknezhaAgentAlive; then
+ stopNeZhaAgent
+ fi
+
+ local args="--report-delay 4 --disable-auto-update --disable-force-update "
+ if [[ "$tls" == "y" ]]; then
+ args="${args} --tls "
+ fi
+
+ if [[ "$ver" == "1" ]]; then
+ nohup ./nezha-agent ${args} -s "${nezha_domain}:${nezha_port}" -p "${nezha_pwd}" >/dev/null 2>&1 &
+ else
+ local yamlcfg="config.yaml"
+ local datatls=""
+ if [[ "$tls" == "y" ]]; then
+ datatls="tls: true"
+ else
+ datatls="tls: false"
+ fi
+ nohup ./nezha-agent -c $yamlcfg 2>&1 &
+ fi
}
startMtg() {
- cd ${installpath}/serv00-play/dmtg
+ cd ${installpath}/serv00-play/dmtg
- config="config.json"
+ config="config.json"
- secret=$(jq -r ".secret" $config)
- port=$(jq -r ".port" $config)
- cmd="nohup ./mtg simple-run -n 1.1.1.1 -t 30s -a 1MB 0.0.0.0:$port $secret -c 8192 --prefer-ip=\"prefer-ipv6\" >/dev/null 2>&1 &"
- eval "$cmd"
- sleep 3
- if checkMtgAlive; then
- echo "启动成功"
- else
- echo "启动失败,请检查进程"
- fi
+ secret=$(jq -r ".secret" $config)
+ port=$(jq -r ".port" $config)
+ cmd="nohup ./mtg simple-run -n 1.1.1.1 -t 30s -a 1MB 0.0.0.0:$port $secret -c 8192 --prefer-ip=\"prefer-ipv6\" >/dev/null 2>&1 &"
+ eval "$cmd"
+ sleep 1
+ if checkMtgAlive; then
+ echo "启动成功"
+ else
+ echo "启动失败,请检查进程"
+ fi
}
+startNeZhaDashboard() {
+ cd ${installpath}/serv00-play/nezha-board
+ if checkProcAlive nezha-dashboard; then
+ stopNeZhaDashboard
+ fi
+ nohup ./nezha-dashboard -c config.yaml >borad.log 2>&1 &
+ if checkProcAlive nezha-dashboard; then
+ green "面板已启动!"
+ else
+ red "面板启动失败,请查看日志borad.log"
+ fi
+
+}
startAlist() {
- alistpath="${installpath}/serv00-play/alist"
-
- if [[ -d "$alistpath/data" && -e "$alistpath/alist" ]]; then
- echo "正在启动alist..."
- cd $alistpath
- domain=$(jq -r ".domain" config.json)
-
- if checkProcAlive "alist"; then
- echo "alist已启动,请勿重复启动!"
- else
- nohup ./alist server >/dev/null 2>&1 &
- sleep 3
- if ! checkProcAlive "alist"; then
- red "启动失败,请检查!"
- return 1
- else
- echo "启动成功!"
- fi
- fi
- else
- red "请先行安装再启动!"
- return
- fi
+ alistpath="${installpath}/serv00-play/alist"
+
+ if [[ -d "$alistpath/data" && -e "$alistpath/alist" ]]; then
+ echo "正在启动alist..."
+ cd $alistpath
+ domain=$(jq -r ".domain" config.json)
+
+ if checkProcAlive "alist"; then
+ echo "alist已启动,请勿重复启动!"
+ else
+ nohup ./alist server >/dev/null 2>&1 &
+ sleep 2
+ if ! checkProcAlive "alist"; then
+ red "启动失败,请检查!"
+ return 1
+ else
+ echo "启动成功!"
+ fi
+ fi
+ else
+ red "请先行安装再启动!"
+ return
+ fi
}
-startSunPanel(){
- cd ${installpath}/serv00-play/sunpanel
- cmd="nohup ./sun-panel >/dev/null 2>&1 &"
- eval "$cmd"
+startSunPanel() {
+ cd ${installpath}/serv00-play/sunpanel
+ cmd="nohup ./sun-panel >/dev/null 2>&1 &"
+ eval "$cmd"
}
-startWebSSH(){
- cd ${installpath}/serv00-play/webssh
- ssh_port=$(jq -r ".port" config.json)
- cmd="nohup ./wssh --port=$ssh_port --fbidhttp=False --xheaders=False --encoding='utf-8' --delay=10 >/dev/null 2>&1 &"
- eval "$cmd"
+startWebSSH() {
+ cd ${installpath}/serv00-play/webssh
+ ssh_port=$(jq -r ".port" config.json)
+ cmd="nohup ./wssh --port=$ssh_port --fbidhttp=False --wpintvl=30 --xheaders=False --encoding='utf-8' --delay=10 >/dev/null 2>&1 &"
+ eval "$cmd"
}
#main
-if [ -n "$autoUp" ]; then
- echo "run autoUpdate"
- autoUpdate
+host=$(hostname)
+user=$(whoami)
+
+echo "正在调用keepalive.sh"
+if [[ "$autoUp" == "autoupdate" ]]; then
+ echo "run autoUpdate"
+ autoUpdate
fi
+#echo "Host:$host, user:$user"
cd ${installpath}/serv00-play/
+
+if [[ -n "$autoUp" ]]; then
+ makeMsgConfig
+fi
if [ ! -f config.json ]; then
- echo "未配置保活项目,请先行配置!"
- exit 0
+ echo "未配置保活项目,请先行配置!"
+ cleanup
fi
monitor=($(jq -r ".item[]" config.json))
@@ -185,141 +275,215 @@ monitor=($(jq -r ".item[]" config.json))
tg_token=$(jq -r ".telegram_token // empty" config.json)
if [[ -z "$tg_token" ]]; then
- echo "从msg.json获取 telegram_token"
- TELEGRAM_TOKEN=$(jq -r '.telegram_token // empty' msg.json)
+ echo "从msg.json获取 telegram_token"
+ if [[ -e "msg.json" ]]; then
+ TELEGRAM_TOKEN=$(jq -r '.telegram_token // empty' msg.json)
+ fi
else
- TELEGRAM_TOKEN=$tg_token
+ TELEGRAM_TOKEN=$tg_token
fi
tg_userid=$(jq -r ".telegram_userid // empty" config.json)
if [[ -z "$tg_userid" ]]; then
- echo "从msg.json获取telegram_userid"
- TELEGRAM_USERID=$(jq -r ".telegram_userid // empty" msg.json)
+ echo "从msg.json获取telegram_userid"
+ if [[ -e "msg.json" ]]; then
+ TELEGRAM_USERID=$(jq -r ".telegram_userid // empty" msg.json)
+ fi
else
- TELEGRAM_USERID=$tg_userid
+ TELEGRAM_USERID=$tg_userid
fi
wx_sendkey=$(jq -r ".wxsendkey // empty" config.json)
if [[ -z "$wx_sendkey" ]]; then
- echo "从msg.json获取wxsendkey"
- WXSENDKEY=$(jq -r ".wxsendkey // empty" msg.json)
+ echo "从msg.json获取wxsendkey"
+ if [[ -e "msg.json" ]]; then
+ WXSENDKEY=$(jq -r ".wxsendkey // empty" msg.json)
+ fi
+else
+ WXSENDKEY=$wx_sendkey
+fi
+
+wx_push_url=$(jq -r ".wxpush_url // empty" config.json)
+if [[ -z "$wx_push_url" ]]; then
+ echo "从msg.json获取wxpush_url"
+ if [[ -e "msg.json" ]]; then
+ WXPUSH_URL=$(jq -r ".wxpush_url // empty" msg.json)
+ fi
+else
+ WXPUSH_URL=$wx_push_url
+fi
+
+wx_token=$(jq -r ".wx_token // empty" config.json)
+if [[ -z "$wx_token" ]]; then
+ echo "从msg.json获取wx_token"
+ if [[ -e "msg.json" ]]; then
+ WX_TOKEN=$(jq -r ".wx_token // empty" msg.json)
+ fi
else
- WXSENDKEY=$wx_sendkey
+ WX_TOKEN=$wx_token
fi
send_type=$(jq -r ".sendtype // empty" config.json)
if [ -z "$send_type" ]; then
- echo "从msg.json获取 sendtype"
- sendtype=$(jq -r ".sendtype // empty" msg.json)
+ echo "从msg.json获取 sendtype"
+ if [[ -e "msg.json" ]]; then
+ sendtype=$(jq -r ".sendtype // empty" msg.json)
+ fi
else
- sendtype=$send_type
+ sendtype=$send_type
fi
-export TELEGRAM_TOKEN TELEGRAM_USERID WXSENDKEY sendtype
+if [ -z "$BUTTON_URL" ]; then
+ echo "从msg.json获取 button_url"
+ if [[ -e "msg.json" ]]; then
+ BUTTON_URL=$(jq -r ".button_url // empty" msg.json)
+ fi
+fi
+
+if [ -z "$PASS" ]; then
+ echo "从msg.json获取 password"
+ if [[ -e "msg.json" ]]; then
+ PASS=$(jq -r ".password // empty" msg.json)
+ fi
+fi
+
+export TELEGRAM_TOKEN TELEGRAM_USERID WXSENDKEY sendtype BUTTON_URL PASS WXPUSH_URL WX_TOKEN
#echo "最终TELEGRAM_TOKEN=$TELEGRAM_TOKEN,TELEGRAM_USERID=$TELEGRAM_USERID"
-host=$(hostname)
-user=$(whoami)
for obj in "${monitor[@]}"; do
- msg=""
- # echo "obj= $obj"
- if [ "$obj" == "sun-panel" ]; then
- if ! checkProcAlive "sun-panel"; then
- startSunPanel
- sleep 3
- if ! checkProcAlive "sun-panel"; then
- msg="sun-panel restarted failure."
- else
- msg="sun-panel restarted successfully."
- fi
- fi
- elif [ "$obj" == "webssh" ]; then
- if ! checkProcAlive "wssh"; then
- startWebSSH
- sleep 5
- if ! checkProcAlive "wssh"; then
- msg="webssh restarted failure."
- else
- msg="webssh restarted successfully."
- fi
- fi
- elif [ "$obj" == "vmess" ]; then
- if ! checkvmessAlive; then
- cd ${installpath}/serv00-play/singbox
- chmod +x ./start.sh && ./start.sh 1 keep
- sleep 5
- if ! checkvmessAlive; then
- msg="vmess restarted failure."
- else
- msg="vmess restarted successfully."
- fi
- fi
- #hy2和vmess+ws都只需要启动serv00sb,所以可以这么写
- elif [[ "$obj" == "hy2/vmess+ws" || "$obj" == "hy2" ]]; then
- if ! checkHy2Alive; then
- #echo "重启serv00sb中..."
- cd ${installpath}/serv00-play/singbox
- chmod +x ./start.sh && ./start.sh 2 keep
- sleep 5
- if ! checkHy2Alive; then
- msg="hy2 restarted failure."
- else
- msg="hy2 restarted successfully."
- fi
- fi
- elif [ "$obj" == "nezha-agent" ]; then
- if ! checknezhaAgentAlive; then
- cd ${installpath}/serv00-play/nezha
- startNeZhaAgent
- sleep 5
- if ! checknezhaAgentAlive; then
- msg="nezha-agent restarted failure."
- else
- msg="nezha-agent restarted successfully."
- fi
- fi
- elif [ "$obj" == "mtg" ]; then
- if ! checkMtgAlive; then
- cd ${installpath}/serv00-play/dmtg
- startMtg
- sleep 5
- if ! checkMtgAlive; then
- msg="mtproto restarted failure."
- else
- msg="mtproto restarted successfully."
- fi
- fi
- elif [ "$obj" == "alist" ]; then
- if ! checkProcAlive "alist"; then
- startAlist
- sleep 5
- if ! checkProcAlive "alist"; then
- msg="alist restarted failure."
- else
- msg="alist restarted successfully."
- fi
- fi
- elif [ "$obj" == "wssh" ]; then
- if ! checkProcAlive wssh; then
- startAlist
- sleep 5
- if ! checkAlistAlive; then
- msg="alist restarted failure."
- else
- msg="alist restarted successfully."
- fi
- fi
- else
- continue
- fi
-
- sendMsg "$msg"
+ msg=""
+ # echo "obj= $obj"
+ if [ "$obj" == "sun-panel" ]; then
+ if ! checkProcAlive "sun-panel"; then
+ startSunPanel
+ sleep 2
+ if ! checkProcAlive "sun-panel"; then
+ msg="sun-panel 重启失败."
+ else
+ msg="sun-panel 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "webssh" ]; then
+ if ! checkProcAlive "wssh"; then
+ startWebSSH
+ sleep 2
+ if ! checkProcAlive "wssh"; then
+ msg="webssh 重启失败."
+ else
+ msg="webssh 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "vmess" ]; then
+ if ! checkvmessAlive; then
+ cd ${installpath}/serv00-play/singbox
+ chmod +x ./start.sh && ./start.sh 1 keep
+ sleep 1
+ if ! checkvmessAlive; then
+ msg="vmess 重启失败."
+ else
+ msg="vmess 重启成功."
+ fi
+ fi
+ #hy2和vmess+ws都只需要启动serv00sb,所以可以这么写
+ elif [[ "$obj" == "hy2/vmess+ws" || "$obj" == "hy2" ]]; then
+ if ! checkHy2Alive; then
+ #echo "重启serv00sb中..."
+ cd ${installpath}/serv00-play/singbox
+ chmod +x ./start.sh && ./start.sh 2 keep
+ sleep 1
+ if ! checkHy2Alive; then
+ msg="hy2 重启失败."
+ else
+ msg="hy2 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "nezha-agent" ]; then
+ if ! checknezhaAgentAlive; then
+ cd ${installpath}/serv00-play/nezha
+ startNeZhaAgent
+ sleep 1
+ if ! checknezhaAgentAlive; then
+ msg="nezha-agent 重启失败."
+ else
+ msg="nezha-agent 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "nezha-dashboard" ]; then
+ if ! checkProcAlive "nezha-dashboard"; then
+ cd ${installpath}/serv00-play/nezha-board
+ startNeZhaDashboard
+ sleep 1
+ if ! checkProcAlive "nezha-dashboard"; then
+ msg="nezha-dashboard 重启失败."
+ else
+ msg="nezha-dashboard 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "mtg" ]; then
+ if ! checkMtgAlive; then
+ cd ${installpath}/serv00-play/dmtg
+ startMtg
+ sleep 1
+ if ! checkMtgAlive; then
+ msg="mtproto 重启失败."
+ else
+ msg="mtproto 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "alist" ]; then
+ if ! checkProcAlive "alist"; then
+ startAlist
+ sleep 1
+ if ! checkProcAlive "alist"; then
+ msg="alist 重启失败."
+ else
+ msg="alist 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "wssh" ]; then
+ if ! checkProcAlive wssh; then
+ startAlist
+ sleep 1
+ if ! checkAlistAlive; then
+ msg="wssh 重启失败."
+ else
+ msg="wssh 重启成功."
+ fi
+ fi
+ elif [ "$obj" == "redis-server" ]; then
+ if ! checkProcAlive redis-server; then
+ echo "正在启动redis-server..."
+ cd ${installpath}/serv00-play/redis
+ nohup ./redis-server ./redis.conf >/dev/null 2>&1 &
+ sleep 2
+ if ! checkProcAlive redis-server; then
+ msg="redis-server 重启失败."
+ else
+ msg="redis-server 重启成功."
+ fi
+ fi
+ else
+ continue
+ fi
+
+ sendMsg "$msg"
done
if [ ${#monitor[@]} -gt 0 ]; then
- checkResetCron
+ checkResetCron
+fi
+
+if [[ "$autoUpdateHyIP" == "Y" ]]; then
+ echo "正在自动更新HY2IP..."
+ cd ${installpath}/serv00-play/singbox
+ chmod +x ./autoUpdateHyIP.sh && ./autoUpdateHyIP.sh
fi
+
+devil info account &>/dev/null
+cleanUselessProc
+# 清理锁文件
+cleanup
diff --git a/keepalive/app.js b/keepalive/app.js
new file mode 100644
index 00000000..170ef8ea
--- /dev/null
+++ b/keepalive/app.js
@@ -0,0 +1,200 @@
+const express = require('express')
+const fs = require('fs')
+const path = require('path')
+const { exec } = require('child_process')
+const bodyParser = require('body-parser')
+const { log } = require('console')
+const app = express()
+
+app.use(bodyParser.json())
+app.use(bodyParser.urlencoded({ extended: true }))
+app.use('/static', express.static(path.join(__dirname, 'static')))
+const user = require('child_process').execSync('whoami').toString().trim()
+const serv00PlayDir = `/home/${user}/serv00-play`
+const keepaliveScript = `${serv00PlayDir}/keepalive.sh`
+
+// 读取配置文件
+const configPath = path.join(__dirname, 'config.json')
+let config = {}
+if (fs.existsSync(configPath)) {
+ config = JSON.parse(fs.readFileSync(configPath, 'utf8'))
+}
+
+// 实现 loadConfig 方法
+function loadConfig() {
+ if (fs.existsSync(configPath)) {
+ config = JSON.parse(fs.readFileSync(configPath, 'utf8'))
+ logError('配置文件重新加载成功')
+ } else {
+ logError('配置文件不存在')
+ }
+}
+
+// 监听配置文件变化
+fs.watchFile(configPath, (curr, prev) => {
+ if (curr.mtime !== prev.mtime) {
+ logError('检测到配置文件变化, 重新加载配置')
+ loadConfig()
+ }
+})
+
+// 验证token
+function validateToken(req, res, next) {
+ const token = cleanAndDecode(req.query.token)
+ if (!token || token !== config.token) {
+ logError(`Token验证失败: ${token}`)
+ return res.status(401).send('无授权不能访问!')
+ }
+ next()
+}
+
+// 修改日志函数,确保同步写入
+function logError(message) {
+ if (config.showlog !== 'Y') {
+ return
+ }
+ try {
+ const timestamp = new Date().toISOString()
+ const logMessage = `[${timestamp}] ${message}\n`
+ const logFile = path.join(__dirname, 'logs', 'debug.log')
+
+ // 确保日志目录存在
+ if (!fs.existsSync(path.dirname(logFile))) {
+ fs.mkdirSync(path.dirname(logFile), { recursive: true })
+ }
+
+ // 同步写入日志
+ fs.appendFileSync(logFile, logMessage)
+ console.log(logMessage) // 同时输出到控制台
+ } catch (error) {
+ console.error('日志记录失败:', error)
+ }
+}
+// 添加请求日志中间件
+app.use((req, res, next) => {
+ logError(`${req.method} ${req.url}`)
+ next()
+})
+
+// 清理和解码函数
+function cleanAndDecode(str) {
+ if (!str || str === 'null') return 'null'
+ try {
+ return Buffer.from(str.trim(), 'base64')
+ .toString('utf8')
+ .replace(/[\s\uFEFF\xA0]/g, '')
+ } catch (e) {
+ logError(`Base64 decode error: ${e.message}`)
+ return 'null'
+ }
+}
+
+// 定时调用脚本的方法
+function scheduleScript() {
+ const cmd = `cd ${serv00PlayDir} && bash ${keepaliveScript} `
+
+ const executeScript = () => {
+ const interval = (parseInt(config.interval, 10) || 5) * 60000 // 默认5分钟
+
+ logError(`定时执行脚本: ${cmd}, 间隔: ${interval}ms`)
+ exec(cmd, (error, stdout, stderr) => {
+ if (error) {
+ logError(`定时执行脚本错误: ${error.message}`)
+ logError(stderr)
+ } else {
+ logError('定时执行脚本成功')
+ logError(stdout)
+ }
+ })
+
+ // 设置定时器
+ setTimeout(executeScript, interval)
+ }
+
+ // 立即执行一次
+ executeScript()
+}
+
+// 启动定时任务
+scheduleScript()
+
+// 记录启动信息
+logError('服务启动')
+// 获取 autoupdate 状态
+function getAutoupdateStatus(autoupdate) {
+ return autoupdate === 'Y' ? 'autoupdate' : 'noupdate'
+}
+
+// 处理首页请求
+app.get('/', (req, res) => {
+ if (config.img) {
+ res.send(`
+
+
+
+
+
+ 首页
+
+
+
+
+
+ `)
+ } else {
+ res.send('Welcome')
+ }
+})
+
+app.get('/keep', validateToken, async (req, res) => {
+ logError('开始处理参数')
+ // 处理参数
+ logError('接收到的参数:')
+ logError(`autoupdate: ${req.query.autoupdate}`)
+ logError(`sendtype: ${req.query.sendtype}`)
+ logError(`telegramtoken: ${req.query.telegramtoken}`)
+ logError(`telegramuserid: ${req.query.telegramuserid}`)
+ logError(`wxsendkey: ${req.query.wxsendkey}`)
+ logError(`buttonurl: ${req.query.buttonurl}`)
+ logError(`pass: ${req.query.pass}`)
+ logError(`wxpushurl: ${req.query.wxpushurl}`)
+ logError(`wxtoken: ${req.query.wxtoken}`)
+
+ const params = {
+ autoupdate: getAutoupdateStatus(req.query.autoupdate),
+ sendtype: req.query.sendtype ? req.query.sendtype.trim() : 'null',
+ telegramtoken: cleanAndDecode(req.query.telegramtoken),
+ telegramuserid: req.query.telegramuserid
+ ? req.query.telegramuserid.trim()
+ : 'null',
+ wxsendkey: cleanAndDecode(req.query.wxsendkey),
+ buttonurl: cleanAndDecode(req.query.buttonurl),
+ pass: cleanAndDecode(req.query.password),
+ wxpushurl: cleanAndDecode(req.query.wxpushurl),
+ wxtoken: cleanAndDecode(req.query.wxtoken),
+ }
+
+ logError(
+ '处理参数: ' +
+ JSON.stringify({
+ ...params,
+ pass: '***',
+ })
+ )
+ // 本地执行
+ logError('本地执行keepalive')
+ const cmd = `cd ${serv00PlayDir} && nohup bash ${keepaliveScript} ${params.autoupdate} ${params.sendtype} ${params.telegramtoken} ${params.telegramuserid} ${params.wxsendkey} ${params.buttonurl} ${params.pass} ${params.wxpushurl} ${params.wxtoken} > /dev/null 2>&1 &`
+ logError('cmd:' + cmd)
+ exec(cmd, (error) => {
+ if (error) {
+ logError(`本地执行错误: ${error}`)
+ } else {
+ logError('本地执行成功')
+ }
+ })
+ res.send('ok')
+})
+
+app.listen(3000, () => {
+ console.log('Server is running on port 3000')
+})
diff --git a/keepalive/config.json b/keepalive/config.json
new file mode 100644
index 00000000..3def90f0
--- /dev/null
+++ b/keepalive/config.json
@@ -0,0 +1,6 @@
+{
+ "interval": "TM",
+ "token": "uuid",
+ "img": "nezha.jpg",
+ "showlog": "N"
+}
diff --git a/keepalive/nezha.jpg b/keepalive/nezha.jpg
new file mode 100644
index 00000000..a05ba8ed
Binary files /dev/null and b/keepalive/nezha.jpg differ
diff --git a/mkprofile.pl b/mkprofile.pl
index 61b82ead..881656f6 100644
--- a/mkprofile.pl
+++ b/mkprofile.pl
@@ -7,6 +7,8 @@
export TZ=Asia/Shanghai
export EDITOR=vim
export VISUAL=vim
+export LANG=en_US.UTF-8
+export LC_ALL=en_US.UTF-8
alias l='ls -ltr'
alias pp='ps aux'
alias ss='cd ~/serv00-play && ./start.sh'
diff --git a/revive.sh b/revive.sh
old mode 100755
new mode 100644
index 8ea09781..47cd1b55
--- a/revive.sh
+++ b/revive.sh
@@ -1,34 +1,114 @@
#!/bin/bash
-#HOSTS_JSON='{
-#"info": [
-#{
-# "host": "s2.serv00.com",
-# "username": "xloong",
-# "port": 22,
-# "password": "abc123"
-#}
-#]
-#}'
-#echo "host info:$HOSTS_JSON"
-# 使用 jq 提取 JSON 数组,并将其加载为 Bash 数组
-hosts_info=($(echo "${HOSTS_JSON}" | jq -c ".info[]"))
-
-for info in "${hosts_info[@]}"; do
- user=$(echo $info | jq -r ".username")
- host=$(echo $info | jq -r ".host")
- port=$(echo $info | jq -r ".port")
- pass=$(echo $info | jq -r ".password")
-
- script="/home/$user/serv00-play/keepalive.sh autoupdate ${SENDTYPE} ${TELEGRAM_TOKEN} ${TELEGRAM_USERID} ${WXSENDKEY}"
-
- output=$(sshpass -p "$pass" ssh -o StrictHostKeyChecking=no -p "$port" "$user@$host" "bash -s" <<< "$script")
-
- echo "output:$output"
- if echo "$output" | grep -q "更新完毕"; then
- echo "登录成功"
- else
- echo "登录失败"
- ./tgsend.sh "主机:$host,用户名:$user,登录失败请检查!"
- fi
-done
+AUTOUPDATE=${AUTOUPDATE:-Y}
+SENDTYPE=${SENDTYPE:-null}
+TELEGRAM_TOKEN=${TELEGRAM_TOKEN:-null}
+TELEGRAM_USERID=${TELEGRAM_USERID:-null}
+WXSENDKEY=${WXSENDKEY:-null}
+WXPUSH_URL=${WXPUSH_URL:-null}
+WX_TOKEN=${WX_TOKEN:-null}
+BUTTON_URL=${BUTTON_URL:-null}
+LOGININFO=${LOGININFO:-N}
+LOGINONCE=${LOGINONCE:-N}
+export TELEGRAM_TOKEN TELEGRAM_USERID BUTTON_URL WXSENDKEY WXPUSH_URL WX_TOKEN
+
+PROXY_HOST=${PROXY_HOST:-null}
+PROXY_PORT=${PROXY_PORT:-null}
+PROXY_USER=${PROXY_USER:-null}
+PROXY_PASS=${PROXY_PASS:-null}
+
+export SOCKS5_USER="$PROXY_USER"
+export SOCKS5_PASSWD="$PROXY_PASS"
+
+sendMsg() {
+ local msg="$1"
+ chmod +x ./tgsend.sh ./wxsend.sh
+ if [ -n "$msg" ]; then
+ if [ "$SENDTYPE" == "1" ]; then
+ ./tgsend.sh "$msg"
+ elif [ "$SENDTYPE" == "2" ]; then
+ ./wxsend.sh "$msg"
+ elif [ "$SENDTYPE" == "3" ]; then
+ ./tgsend.sh "$msg"
+ ./wxsend.sh "$msg"
+ fi
+ fi
+}
+
+# 登录服务器并执行保活脚本
+login_server() {
+ local user=$1
+ local host=$2
+ local port=$3
+ local pass=$4
+ local msg=""
+
+ if [[ "$AUTOUPDATE" == "Y" ]]; then
+ script="bash /home/$user/serv00-play/keepalive.sh autoupdate ${SENDTYPE} \"${TELEGRAM_TOKEN}\" \"${TELEGRAM_USERID}\" \"${WXSENDKEY}\" \"${BUTTON_URL}\" \"${pass}\" \"${WXPUSH_URL}\" \"${WX_TOKEN}\""
+ else
+ script="bash /home/$user/serv00-play/keepalive.sh noupdate ${SENDTYPE} \"${TELEGRAM_TOKEN}\" \"${TELEGRAM_USERID}\" \"${WXSENDKEY}\" \"${BUTTON_URL}\" \"${pass}\" \"${WXPUSH_URL}\" \"${WX_TOKEN}\""
+ fi
+ #使用socks5代理进行登录
+ if [[ "$PROXY_HOST" != "null" ]]; then
+ echo "测试基础连接..." >&2
+ if timeout 5 nc -zv "$PROXY_HOST" "$PROXY_PORT" &>/dev/null; then
+ echo "✓ 可以连接到代理服务器" >&2
+ else
+ echo "✗ 无法连接到代理服务器" >&2
+ exit 1
+ fi
+ output=$(sshpass -p "$pass" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=30 -o ProxyCommand="connect -S ${PROXY_HOST}:${PROXY_PORT} %h %p" -p "$port" "$user@$host" "bash -s" <<<"$script")
+ else
+ output=$(sshpass -p "$pass" ssh -o StrictHostKeyChecking=no -p "$port" "$user@$host" "bash -s" <<<"$script")
+ fi
+
+ #echo "output:$output" >&2
+
+ if echo "$output" | grep -q "keepalive.sh"; then
+ echo "登录成功" >&2
+ msg="🟢主机 ${host}, 用户 ${user}, 登录成功!\n"
+ else
+ echo "登录失败" >&2
+ msg="🔴主机 ${host}, 用户 ${user}, 登录失败!\n"
+ export PASS=$pass
+ sendMsg "Host:$host, user:$user, 登录失败,请检查!"
+ fi
+ echo -n "$msg"
+}
+
+summary=""
+if [[ "$LOGINONCE" == "Y" ]]; then
+ echo "只登录一次模式"
+ # 计算今天是今年的第几天(1-366)
+ DAY_OF_YEAR=$(date +%j)
+
+ # 获取服务器数量
+ SERVER_COUNT=$(echo "$HOSTS_JSON" | jq '.info | length')
+
+ # 计算今天应该登录哪个服务器(取模运算)
+ INDEX=$(((10#$DAY_OF_YEAR - 1) % SERVER_COUNT))
+
+ # 获取对应的服务器配置
+ CONFIG=$(echo "$HOSTS_JSON" | jq ".info[$INDEX]")
+
+ HOST=$(echo "$CONFIG" | jq -r '.host')
+ USERNAME=$(echo "$CONFIG" | jq -r '.username')
+ PORT=$(echo "$CONFIG" | jq -r '.port')
+ PASSWORD=$(echo "$CONFIG" | jq -r '.password')
+
+ summary=$(login_server "$USERNAME" "$HOST" "$PORT" "$PASSWORD")
+else
+ mapfile -t hosts_info < <(echo "${HOSTS_JSON}" | jq -c ".info[]")
+ for info in "${hosts_info[@]}"; do
+ user=$(echo "$info" | jq -r ".username")
+ host=$(echo "$info" | jq -r ".host")
+ port=$(echo "$info" | jq -r ".port")
+ pass=$(echo "$info" | jq -r ".password")
+
+ summary=$summary$(login_server "$user" "$host" "$port" "$pass")
+ done
+fi
+
+if [[ "$LOGININFO" == "Y" ]]; then
+ sendMsg "$summary"
+fi
diff --git a/revive_node.sh b/revive_node.sh
new file mode 100644
index 00000000..3bfbfef7
--- /dev/null
+++ b/revive_node.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+toBase64() {
+ echo -n "$1" | base64
+}
+
+AUTOUPDATE=${AUTOUPDATE:-Y}
+SENDTYPE=${SENDTYPE:-null}
+TELEGRAM_TOKEN=${TELEGRAM_TOKEN:-null}
+TELEGRAM_USERID=${TELEGRAM_USERID:-null}
+WXSENDKEY=${WXSENDKEY:-null}
+WXPUSH_URL=${WXPUSH_URL:-null}
+WX_TOKEN=${WX_TOKEN:-null}
+BUTTON_URL=${BUTTON_URL:-null}
+LOGININFO=${LOGININFO:-N}
+TOKEN=${TOKEN:-""}
+
+TOKEN=$(toBase64 $TOKEN)
+base64_TELEGRAM_TOKEN=$(toBase64 $TELEGRAM_TOKEN)
+Base64BUTTON_URL=$(toBase64 $BUTTON_URL)
+base64_WXPUSH_URL=$(toBase64 $WXPUSH_URL)
+base64_WX_TOKEN=$(toBase64 $WX_TOKEN)
+
+export TELEGRAM_TOKEN TELEGRAM_USERID BUTTON_URL
+
+# 使用 jq 提取 JSON 数组,并将其加载为 Bash 数组
+hosts_info=($(echo "${HOSTS_JSON}" | jq -c ".info[]"))
+summary=""
+for info in "${hosts_info[@]}"; do
+ user=$(echo $info | jq -r ".username")
+ host=$(echo $info | jq -r ".host")
+ pass=$(echo $info | jq -r ".password")
+
+ echo "host: $host"
+ bas64_pass=$(toBase64 $pass)
+ output=$(curl -s -o /dev/null -w "%{http_code}" "https://$user.serv00.net/keep?token=$TOKEN&autoupdate=$AUTOUPDATE&sendtype=$SENDTYPE&telegramtoken=$base64_TELEGRAM_TOKEN&telegramuserid=$TELEGRAM_USERID&wxsendkey=$WXSENDKEY&buttonurl=$Base64BUTTON_URL&password=$bas64_pass&wxpushurl=$base64_WXPUSH_URL&wxtoken=$base64_WX_TOKEN")
+
+ if [ "$output" -eq 200 ]; then
+ echo "连接成功,账号正常"
+ msg="🟢主机 ${host}, 用户 ${user}, 连接成功,账号正常!\n"
+ elif [ "$output" -eq 403 ]; then
+ echo "账号被封"
+ msg="🔴主机 ${host}, 用户 ${user}, 账号被封!\n"
+ chmod +x ./tgsend.sh
+ export PASS=$pass
+ ./tgsend.sh "Host:$host, user:$user, 账号被封,请检查!"
+ elif [ "$output" -eq 404 ]; then
+ echo "keepalive服务不在线"
+ msg="🔴主机 ${host}, 用户 ${user}, keepalive服务不在线!\n"
+ chmod +x ./tgsend.sh
+ export PASS=$pass
+ ./tgsend.sh "Host:$host, user:$user, keepalive服务不在线,请检查!"
+ elif [ "$output" -eq 401 ]; then
+ echo "授权码错误"
+ msg="🔴主机 ${host}, 用户 ${user}, 授权码错误!\n"
+ chmod +x ./tgsend.sh
+ export PASS=$pass
+ ./tgsend.sh "Host:$host, user:$user, 授权码错误,请检查!"
+ else
+ echo "连接失败,可能网络问题!"
+ msg="🔴主机 ${host}, 用户 ${user}, 连接失败,可能网络问题!\n"
+ chmod +x ./tgsend.sh
+ export PASS=$pass
+ ./tgsend.sh "Host:$host, user:$user, 连接失败,可能网络问题,可直接访问主页查看: https://$user.serv00.net"
+ fi
+ summary=$summary$(echo -n $msg)
+done
+
+if [[ "$LOGININFO" == "Y" ]]; then
+ chmod +x ./tgsend.sh
+ ./tgsend.sh "$summary"
+fi
diff --git a/singbox/autoUpdateHyIP.sh b/singbox/autoUpdateHyIP.sh
new file mode 100644
index 00000000..d517a079
--- /dev/null
+++ b/singbox/autoUpdateHyIP.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+installpath="$HOME"
+USER="$(whoami)"
+if [[ -e "$installpath/serv00-play" ]]; then
+ source ${installpath}/serv00-play/utils.sh
+fi
+
+cd ${installpath}/serv00-play/singbox
+if [[ ! -e "singbox.json" || ! -e "config.json" ]]; then
+ red "未安装节点,请先安装!"
+ exit
+fi
+config="singbox.json"
+cur_hy2_ip=$(jq -r ".HY2IP" $config)
+# 检查 cur_hy2_ip 是否为空
+if [[ -z "$cur_hy2_ip" ]]; then
+ red "当前 HY2IP 为空,未安装hy2节点!"
+ exit
+fi
+
+show_ip_status
+
+if printf '%s\n' "${useIPs[@]}" | grep -q "$cur_hy2_ip"; then
+ echo "目前ip可用"
+ exit
+fi
+
+if [[ ${#useIPs[@]} -eq 0 ]]; then
+ red "当前无可用IP!"
+ exit
+fi
+
+hy2_ip=${useIPs[0]}
+
+if [[ -z "$hy2_ip" ]]; then
+ red "很遗憾,已无可用IP!"
+ exit
+fi
+
+if ! upInsertFd singbox.json HY2IP "$hy2_ip"; then
+ red "更新singbox.json配置文件失败!"
+ exit
+fi
+
+if ! upSingboxFd config.json "inbounds" "tag" "hysteria-in" "listen" "$hy2_ip"; then
+ red "更新config.json配置文件失败!"
+ exit
+fi
+green "HY2 更换IP成功,当前IP为 $hy2_ip"
+
+echo "正在重启sing-box..."
+stop_sing_box
+start_sing_box
diff --git a/singbox/killsing-box.sh b/singbox/killsing-box.sh
index 77cc29e6..d02b9af7 100644
--- a/singbox/killsing-box.sh
+++ b/singbox/killsing-box.sh
@@ -1,18 +1,17 @@
#!/bin/bash
-r=$(ps aux | grep cloudflare | grep -v grep | awk '{print $2}')
-if [ -z "$r" ]; then
- echo "can't find cloudflare" >/dev/null
-else
- echo $r
- kill -9 $r
-fi
+# 定义需要检查和终止的进程名
+processes=("cloudflare" "serv00sb")
-r=$(ps aux | grep serv00sb | grep -v grep | awk '{print $2}')
+for process in "${processes[@]}"; do
+ # 查找进程 ID
+ pids=$(pgrep "$process")
-if [ -z "$r" ]; then
- echo "can't find serv00sb" >/dev/null
-else
- echo $r
- kill -9 $r
-fi
+ if [ -n "$pids" ]; then
+ echo "Killing process: $process (PIDs: $pids)"
+ # 逐个杀死进程
+ for pid in $pids; do
+ kill -9 "$pid"
+ done
+ fi
+done
diff --git a/singbox/start.sh b/singbox/start.sh
index 81fba785..4464c0be 100644
--- a/singbox/start.sh
+++ b/singbox/start.sh
@@ -1,6 +1,10 @@
#!/bin/bash
config="singbox.json"
+installpath="$HOME"
+if [[ -e "$installpath/serv00-play" ]]; then
+ source ${installpath}/serv00-play/utils.sh
+fi
VMPORT=$(jq -r ".VMPORT" $config)
HY2PORT=$(jq -r ".HY2PORT" $config)
@@ -10,12 +14,12 @@ WSPATH=$(jq -r ".WSPATH" $config)
ARGO_AUTH=$(jq -r ".ARGO_AUTH" $config)
ARGO_DOMAIN=$(jq -r ".ARGO_DOMAIN" $config)
-
+TUNNEL_NAME=$(jq -r ".TUNNEL_NAME" $config)
GOOD_DOMAIN=$(jq -r ".GOOD_DOMAIN" $config)
SOCKS5_PORT=$(jq -r ".SOCKS5_PORT" $config)
SOCKS5_USER=$(jq -r ".SOCKS5_USER" $config)
SOCKS5_PASS=$(jq -r ".SOCKS5_PASS" $config)
-
+user="$(whoami)"
if [ -z $1 ]; then
type=$(jq -r ".TYPE" $config)
@@ -25,38 +29,37 @@ fi
keep=$2
-
-
run() {
if ps aux | grep cloudflared | grep -v "grep" >/dev/null; then
return
fi
- if [[ -n "${ARGO_AUTH}" && -n "${ARGO_DOMAIN}" ]]; then
- if [[ "$ARGO_AUTH" =~ TunnelSecret ]]; then
- echo "$ARGO_AUTH" | sed 's@{@{"@g;s@[,:]@"\0"@g;s@}@"}@g' >tunnel.json
- cat >tunnel.yml <>tunnel.yml </dev/null 2>&1 &
- elif [[ "$ARGO_AUTH" =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then
- nohup ./cloudflared tunnel --edge-ip-version auto --protocol http2 run --token ${ARGO_AUTH} >/dev/null 2>&1 &
- fi
+ if [[ "${ARGO_AUTH}" != "null" && "${ARGO_DOMAIN}" != "null" ]]; then
+ nohup ./cloudflared tunnel --edge-ip-version auto --protocol http2 run --token ${ARGO_AUTH} >/dev/null 2>&1 &
+ elif [[ "$ARGO_DOMAIN" != "null" && "$TUNNEL_NAME" != "null" ]]; then
+ nohup ./cloudflared tunnel run $TUNNEL_NAME >/dev/null 2>&1 &
else
- nohup ./cloudflared tunnel --edge-ip-version auto --protocol http2 --no-autoupdate --url http://localhost:${VMPORT} >/dev/null 2>&1 &
- sleep 5
- ARGO_DOMAIN=$(wget -qO- $(sockstat -4 -l -P tcp | grep cloudflare | awk '{for(i=1;i<=NF;i++) if($i ~ /127\.0\.0\.1/) print $i}')/quicktunnel | jq -r '.hostname')
- echo "ARGO_DOMAIN:$ARGO_DOMAIN"
+ echo "未有tunnel相关配置!"
+ return 1
+ fi
+}
+
+uploadList() {
+ local token="$1"
+ local content="$2"
+ local user="${user,,}"
+ local url="${linkBaseurl}/addlist?token=$token"
+ local encode_content=$(echo -n "$content" | base64 -w 0)
+
+ #echo "encode_content:$encode_content"
+ curl -X POST "$url" \
+ -H "Content-Type: application/json" \
+ -d "{\"content\":\"$encode_content\",
+ \"user\":\"$user\"}"
+
+ if [[ $? -eq 0 ]]; then
+ return 0
+ else
+ return 1
fi
}
@@ -64,32 +67,47 @@ export_list() {
user="$(whoami)"
host="$(hostname | cut -d '.' -f 1)"
if [[ "$HY2IP" != "::" ]]; then
- myip=${HY2IP}
+ myip=${HY2IP}
else
- myip="$(curl -s ifconfig.me)"
+ myip="$(curl -s icanhazip.com)"
+ fi
+ if [[ "$GOOD_DOMAIN" == "null" ]]; then
+ GOOD_DOMAIN="www.visa.com.hk"
fi
vmessname="Argo-vmess-$host-$user"
hy2name="Hy2-$host-$user"
- VMESSWS="{\"v\":\"2\",\"ps\": \"Vmessws-${host}-${user}\", \"add\":\"www.visa.com.hk\", \"port\":\"443\", \"id\": \"${UUID}\", \"aid\": \"0\", \"scy\": \"none\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"${GOOD_DOMAIN}\", \"path\": \"/${WSPATH}?ed=2048\", \"tls\": \"tls\", \"sni\": \"${GOOD_DOMAIN}\", \"alpn\": \"\", \"fp\": \"\"}"
- ARGOVMESS="{ \"v\": \"2\", \"ps\": \"$vmessname\", \"add\": \"www.visa.com.hk\", \"port\": \"443\", \"id\": \"${UUID}\", \"aid\": \"0\", \"scy\": \"none\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"${ARGO_DOMAIN}\", \"path\": \"/${WSPATH}?ed=2048\", \"tls\": \"tls\", \"sni\": \"${ARGO_DOMAIN}\", \"alpn\": \"\" }"
+ VMESSWS="{ \"v\":\"2\", \"ps\": \"Vmessws-${host}-${user}\", \"add\":\"$GOOD_DOMAIN\", \"port\":\"443\", \"id\": \"${UUID}\", \"aid\": \"0\", \"scy\": \"none\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"${GOOD_DOMAIN}\", \"path\": \"/${WSPATH}?ed=2048\", \"tls\": \"tls\", \"sni\": \"${GOOD_DOMAIN}\", \"alpn\": \"\", \"fp\": \"\"}"
+ ARGOVMESS="{ \"v\": \"2\", \"ps\": \"$vmessname\", \"add\": \"$GOOD_DOMAIN\", \"port\": \"443\", \"id\": \"${UUID}\", \"aid\": \"0\", \"scy\": \"none\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"${ARGO_DOMAIN}\", \"path\": \"/${WSPATH}?ed=2048\", \"tls\": \"tls\", \"sni\": \"${ARGO_DOMAIN}\", \"alpn\": \"\", \"fp\": \"\" }"
hysteria2="hysteria2://$UUID@$myip:$HY2PORT/?sni=www.bing.com&alpn=h3&insecure=1#$hy2name"
- socks5="https://t.me/socks?server=${host}.serv00.com&port=${SOCKS5_PORT}&user=${SOCKS5_USER}&pass=${SOCKS5_PASS}"
- proxyip="proxyip://${SOCKS5_USER}:${SOCKS5_PASS}@${host}.serv00.com:${SOCKS5_PORT}"
-
+ socks5="https://t.me/socks?server=${host}.$(getDoMain)&port=${SOCKS5_PORT}&user=${SOCKS5_USER}&pass=${SOCKS5_PASS}"
+ proxyip="proxyip://${SOCKS5_USER}:${SOCKS5_PASS}@${host}.$(getDoMain):${SOCKS5_PORT}"
cat >list </dev/null; then
- nohup ./serv00sb run -c ./config.json >/dev/null 2>&1 &
+ nohup ./serv00sb run -c ./config.json >/dev/null 2>&1 &
fi
elif [[ "$type" =~ ^(1|3|1.1|3.1|4.4|2.4)$ ]]; then
- chmod +x ./serv00sb
- if ! ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
- nohup ./serv00sb run -c ./config.json >/dev/null 2>&1 &
- fi
+ chmod +x ./serv00sb
+ if ! ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
+ nohup ./serv00sb run -c ./config.json >/dev/null 2>&1 &
+ fi
fi
if [ -z "$keep" ]; then
diff --git a/ssl/cronSSL.sh b/ssl/cronSSL.sh
index af4847cb..a1a62229 100644
--- a/ssl/cronSSL.sh
+++ b/ssl/cronSSL.sh
@@ -3,6 +3,7 @@
installpath="$HOME"
domain=$1
host="$(hostname | cut -d '.' -f 1)"
+user=$(whoami)
sno=${host/s/web}
webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
resp=$(devil ssl www add $webIp le le $domain)
@@ -13,15 +14,26 @@ if [[ "$resp" =~ .*succesfully.*$ ]]; then
crontab -l | grep -v "$domain" >tmpcron
crontab tmpcron
rm -rf tmpcron
- config="../config.json"
+ if grep "telegram_token" ../config.json; then
+ config="../config.json"
+ else
+ config="../msg.json"
+ fi
if [ -e "$config" ]; then
TELEGRAM_TOKEN=$(jq -r ".telegram_token" "$config")
TELEGRAM_USERID=$(jq -r ".telegram_userid" "$config")
if [[ -n "$TELEGRAM_TOKEN" && -n "$TELEGRAM_USERID" ]]; then
- msg="你的域名($domain)申请的SSL证书已下发,请查收!"
+ msg="Host:$host, user:$user, 你的域名($domain)申请的SSL证书已下发,请查收!"
cd $installpath/serv00-play
export TELEGRAM_TOKEN="$TELEGRAM_TOKEN" TELEGRAM_USERID="$TELEGRAM_USERID"
./tgsend.sh "$msg"
fi
fi
+elif [[ "$resp" =~ .*already.*$ ]]; then
+ echo "域名($domain)的SSL证书已存在,无需重复申请!"
+ crontab -l | grep -v "$domain" >tmpcron
+ crontab tmpcron
+ rm -rf tmpcron
+else
+ echo "申请SSL证书失败,请检查域名($domain)是否正确!"
fi
diff --git a/start.sh b/start.sh
index 39fc0a1a..75740e29 100755
--- a/start.sh
+++ b/start.sh
@@ -9,257 +9,299 @@ CYAN='\033[0;96m'
WHITE='\033[0;37m'
RESET='\033[0m'
yellow() {
- echo -e "${YELLOW}$1${RESET}"
+ echo -e "${YELLOW}$1${RESET}"
}
green() {
- echo -e "${GREEN}$1${RESET}"
+ echo -e "${GREEN}$1${RESET}"
}
red() {
- echo -e "${RED}$1${RESET}"
+ echo -e "${RED}$1${RESET}"
}
installpath="$HOME"
-if [[ -e "$installpath/serv00-play" ]]; then
- source ${installpath}/serv00-play/utils.sh
+USER="$(whoami)"
+if [[ -e "$installpath/serv00-play" ]]; then
+ source ${installpath}/serv00-play/utils.sh
fi
PS3="请选择(输入0退出): "
-install(){
- cd ${installpath}
- if [ -d serv00-play ]; then
- cd "serv00-play"
- git stash
- if git pull; then
- echo "更新完毕"
- #重新给各个脚本赋权限
- chmod +x ./start.sh
- chmod +x ./keepalive.sh
- chmod +x ${installpath}/serv00-play/singbox/start.sh
- chmod +x ${installpath}/serv00-play/singbox/killsing-box.sh
- chmod +x ${installpath}/serv00-play/ssl/cronSSL.sh
- red "请重新启动脚本!"
- exit 0
- fi
- fi
-
- cd ${installpath}
- echo "正在安装..."
- if ! git clone https://github.com/frankiejun/serv00-play.git; then
- echo -e "${RED}安装失败!${RESET}"
- exit 1;
- fi
- echo -e "${YELLOW}安装成功${RESET}"
-}
-
-showSingBoxInfo(){
- cd ${installpath}/serv00-play/singbox
-
- if [ ! -f singbox.json ]; then
- red "配置文件不存在,请先行配置!"
- return
- fi
- if [ ! -e list ]; then
- red "请先运行sing-box"
- fi
- config="singbox.json"
- type=$(jq -r ".TYPE" $config)
- chmod +x ./start.sh && ./start.sh $type list
-
-}
-
-
-chooseSingbox(){
- echo "保活sing-box中哪个项目: "
- echo " 1.hy2/vmess+ws/socks5 "
- echo " 2.argo+vmess "
- echo " 3.all "
- read -p "请选择:" input
-
- if [ "$input" = "1" ]; then
- item+=("hy2/vmess+ws")
- elif [ "$input" = "2" ]; then
- item+=("vmess")
- elif [ "$input" = "3" ]; then
- item+=("hy2/vmess+ws")
- item+=("vmess")
- else
- red "无效选择!"
- return 1
- fi
-
-}
-
-setConfig(){
- cd ${installpath}/serv00-play/
-
- if [ -f config.json ]; then
- echo "目前已有配置:"
- config_content=$(cat config.json)
- echo $config_content
- read -p "是否修改? [y/n] [y]:" input
- input=${input:-y}
- if [ "$input" != "y" ]; then
- return
- fi
- fi
- createConfigFile
-}
-
-createConfigFile(){
-
- echo "选择你要保活的项目(可多选,用空格分隔):"
- echo "1. sun-panel "
- echo "2. sing-box(包含hy2,vmess,socks5) "
- echo "3. 哪吒探针 "
- echo "4. mtproto代理"
- echo "5. alist"
- echo "6. webssh"
- echo "88. 暂停所有保活功能"
- echo "99. 复通所有保活功能(之前有配置的情况下)"
- item=()
-
- read -p "请选择: " choices
- choices=($choices)
-
- if [[ "${choices[@]}" =~ "88" && ${#choices[@]} -gt 1 ]]; then
- red "选择出现了矛盾项,请重新选择!"
- return 1
- fi
-
- #过滤重复
- choices=($(echo "${choices[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
-
- # 根据选择来询问对应的配置
- for choice in "${choices[@]}"; do
- case "$choice" in
- 1)
- item+=("sun-panel")
- ;;
- 2)
- if ! chooseSingbox; then
- return
- fi
- ;;
- 3)
- item+=("nezha-agent")
- ;;
- 4)
- item+=("mtg")
- ;;
- 5)
- item+=("alist")
- ;;
- 6)
- item+=("webssh")
- ;;
- 88)
- delCron
- backupConfig "config.json"
- green "设置完毕!"
- return 0
- ;;
- 99)
- if [[ ! -e config.bak ]]; then
- red "之前未有配置,未能复通!"
- return 1
- fi
- restoreConfig "config.bak"
- tm=$(jq -r ".chktime" config.json)
- addCron $tm
- green "设置完毕!"
- return 0
- ;;
- *)
- echo "无效选择"
- return 1
- ;;
- esac
-done
-
- json_content="{\n"
- json_content+=" \"item\": [\n"
-
- for item in "${item[@]}"; do
- json_content+=" \"$item\","
- done
-
- # 删除最后一个逗号并换行
- json_content="${json_content%,}\n"
- json_content+=" ],\n"
-
- if [ "$num" = "4" ]; then
- json_content+=" \"chktime\": \"null\""
- json_content+="}\n"
- printf "$json_content" > ./config.json
- echo -e "${YELLOW} 设置完成! ${RESET} "
- delCron
- return
- fi
-
- read -p "配置保活检查的时间间隔(单位分钟,默认5分钟):" tm
- tm=${tm:-"5"}
-
- json_content+=" \"chktime\": \"$tm\","
-
- read -p "是否需要配置消息推送? [y/n] [n]:" input
- input=${input:-n}
-
- if [ "${input}" == "y" ]; then
- json_content+="\n"
-
- echo "选择要推送的app:"
- echo "1) Telegram "
- echo "2) 微信 "
- echo "3) 以上皆是"
-
- read -p "请选择:" sendtype
-
- if [ "$sendtype" == "1" ]; then
- writeTG
- elif [ "$sendtype" == "2" ]; then
- writeWX
- elif [ "$sendtype" == "3" ]; then
- writeTG
- writeWX
- else
- echo "无效选择"
- return
- fi
- else
- sendtype=${sendtype:-"null"}
- fi
- json_content+="\n \"sendtype\": $sendtype \n"
- json_content+="}\n"
-
- # 使用 printf 生成文件
- printf "$json_content" > ./config.json
- addCron $tm
- chmod +x ${installpath}/serv00-play/keepalive.sh
- echo -e "${YELLOW} 设置完成! ${RESET} "
-
-}
-
-backupConfig(){
- local filename=$1
- if [[ -e "$filename" ]]; then
- if [[ "$filename" =~ ".json" ]]; then
- local basename=${filename%.json}
- mv $filename $basename.bak
- fi
- fi
-}
-
-restoreConfig(){
- local filename=$1
- if [[ -e "$filename" ]]; then
- if [[ "$filename" =~ ".bak" ]]; then
- local basename=${filename%.bak}
- mv $filename $basename.json
- fi
- fi
+install() {
+ local input=$1
+ cd ${installpath}
+ if [ -d "serv00-play" ]; then
+ cd "serv00-play"
+ git stash
+ if git pull origin main; then
+ git fetch --tags
+ echo "更新完毕"
+ #重新给各个脚本赋权限
+ chmod +x ./start.sh
+ chmod +x ./keepalive.sh
+ chmod +x ./tgsend.sh
+ chmod +x ./wxsend.sh
+ chmod +x ${installpath}/serv00-play/singbox/start.sh
+ chmod +x ${installpath}/serv00-play/singbox/killsing-box.sh
+ chmod +x ${installpath}/serv00-play/singbox/autoUpdateHyIP.sh
+ chmod +x ${installpath}/serv00-play/ssl/cronSSL.sh
+ red "请重新启动脚本!"
+ exit 0
+ fi
+ fi
+
+ cd ${installpath}
+ echo "正在安装..."
+ if ! git clone https://github.com/frankiejun/serv00-play.git; then
+ echo -e "${RED}安装失败!${RESET}"
+ exit 1
+ fi
+ devil binexec on
+ touch .profile
+ cat .profile | perl ./serv00-play/mkprofile.pl >tmp_profile
+ mv -f tmp_profile .profile
+ if [[ ! -e "${installpath}/serv00-play" ]]; then
+ red "安装不成功!"
+ return
+ fi
+
+ cd ${installpath}/serv00-play
+ chmod +x ./start.sh
+ chmod +x ./keepalive.sh
+ chmod +x ./tgsend.sh
+ chmod +x ./wxsend.sh
+ chmod +x ${installpath}/serv00-play/singbox/start.sh
+ chmod +x ${installpath}/serv00-play/singbox/killsing-box.sh
+ chmod +x ${installpath}/serv00-play/singbox/autoUpdateHyIP.sh
+ chmod +x ${installpath}/serv00-play/ssl/cronSSL.sh
+ if [ -z "$input" ]; then
+ read -p "$(yellow 设置完毕,需要重新登录才能生效,是否重新登录?[y/n] [y]:)" input
+ input=${input:-y}
+ fi
+ echo -e "${YELLOW}安装成功${RESET}"
+
+ if [ "$input" = "y" ]; then
+ kill -9 $PPID
+ fi
+
+}
+
+showSingBoxInfo() {
+ cd ${installpath}/serv00-play/singbox
+
+ if [ ! -f singbox.json ]; then
+ red "配置文件不存在,请先行配置!"
+ return
+ fi
+ if [ ! -e list ]; then
+ red "请先运行sing-box"
+ fi
+ config="singbox.json"
+ type=$(jq -r ".TYPE" $config)
+ chmod +x ./start.sh && ./start.sh $type list
+
+}
+
+chooseSingbox() {
+ echo "保活sing-box中哪个项目(单选): "
+ echo " 1.hy2/vmess+ws/socks5 "
+ echo " 2.argo+vmess "
+ echo " 3.all "
+ read -p "请选择:" input
+
+ if [ "$input" = "1" ]; then
+ item+=("hy2/vmess+ws")
+ elif [ "$input" = "2" ]; then
+ item+=("vmess")
+ elif [ "$input" = "3" ]; then
+ item+=("hy2/vmess+ws")
+ item+=("vmess")
+ else
+ red "无效选择!"
+ return 1
+ fi
+
+}
+
+setConfig() {
+ cd ${installpath}/serv00-play/
+
+ if [ -f config.json ]; then
+ echo "目前已有配置:"
+ config_content=$(cat config.json)
+ echo $config_content
+ read -p "是否修改? [y/n] [y]:" input
+ input=${input:-y}
+ if [ "$input" != "y" ]; then
+ return
+ fi
+ fi
+ createConfigFile
+}
+
+createConfigFile() {
+ echo "选择你要保活的项目(可多选,用空格分隔):"
+ echo "1. sun-panel "
+ echo "2. sing-box(包含hy2,vmess,socks5) "
+ echo "3. 哪吒探针 "
+ echo "4. mtproto代理"
+ echo "5. alist"
+ echo "6. webssh"
+ echo "7. 哪吒面板"
+ echo "8. redis"
+ echo "88. 暂停所有保活功能"
+ echo "99. 复通所有保活功能(之前有配置的情况下)"
+ echo "0. 返回主菜单"
+ item=()
+
+ read -p "请选择: " choices
+ choices=($choices)
+
+ if [[ "${choices[@]}" =~ "88" && ${#choices[@]} -gt 1 ]]; then
+ red "选择出现了矛盾项,请重新选择!"
+ return 1
+ fi
+
+ #过滤重复
+ choices=($(echo "${choices[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
+
+ # 根据选择来询问对应的配置
+ for choice in "${choices[@]}"; do
+ case "$choice" in
+ 0)
+ showMenu
+ break
+ ;;
+ 1)
+ item+=("sun-panel")
+ ;;
+ 2)
+ if ! chooseSingbox; then
+ return
+ fi
+ ;;
+ 3)
+ item+=("nezha-agent")
+ ;;
+ 4)
+ item+=("mtg")
+ ;;
+ 5)
+ item+=("alist")
+ ;;
+ 6)
+ item+=("webssh")
+ ;;
+ 7)
+ item+=("nezha-dashboard")
+ ;;
+ 8)
+ item+=("redis-server")
+ ;;
+ 88)
+ #delCron
+ backupConfig "config.json"
+ green "设置完毕!"
+ return 0
+ ;;
+ 99)
+ if [[ ! -e config.bak ]]; then
+ red "之前未有配置,未能复通!"
+ return 1
+ fi
+ restoreConfig "config.bak"
+ tm=$(jq -r ".chktime" config.json)
+ addCron $tm
+ green "设置完毕!"
+ return 0
+ ;;
+ *)
+ echo "无效选择"
+ return 1
+ ;;
+ esac
+ done
+
+ json_content="{\n"
+ json_content+=" \"item\": [\n"
+
+ for item in "${item[@]}"; do
+ json_content+=" \"$item\","
+ done
+
+ # 删除最后一个逗号并换行
+ json_content="${json_content%,}\n"
+ json_content+=" ],\n"
+
+ read -p "是否需要配置消息推送? [y/n] [n]:" input
+ input=${input:-n}
+
+ if [ "${input}" == "y" ]; then
+ json_content+="\n"
+
+ echo "选择要推送的app:"
+ echo "1) Telegram "
+ echo "2) 微信 "
+ echo "3) 以上皆是"
+
+ read -p "请选择:" sendtype
+
+ if [ "$sendtype" == "1" ]; then
+ writeTG
+ elif [ "$sendtype" == "2" ]; then
+ writeWX
+ elif [ "$sendtype" == "3" ]; then
+ writeTG
+ writeWX
+ else
+ echo "无效选择"
+ return
+ fi
+ else
+ sendtype=${sendtype:-"null"}
+ fi
+
+ read -p "是否使用cron保活? [y/n] [n]:" setcron
+ setcron=${setcron:-n}
+
+ if [[ "$setcron" == "y" ]]; then
+ read -p "配置保活检查的时间间隔(单位分钟[1~59],默认5分钟):" tm
+ tm=${tm:-"5"}
+ json_content+=" \"chktime\": \"$tm\","
+ fi
+ json_content+="\n \"sendtype\": $sendtype \n"
+ json_content+="}\n"
+
+ # 使用 printf 生成文件
+ printf "$json_content" >./config.json
+ if [[ "$setcron" == "y" ]]; then
+ addCron $tm
+ fi
+
+ chmod +x ${installpath}/serv00-play/keepalive.sh
+ echo -e "${YELLOW} 设置完成! ${RESET} "
+
+}
+
+backupConfig() {
+ local filename=$1
+ if [[ -e "$filename" ]]; then
+ if [[ "$filename" =~ ".json" ]]; then
+ local basename=${filename%.json}
+ mv $filename $basename.bak
+ fi
+ fi
+}
+
+restoreConfig() {
+ local filename=$1
+ if [[ -e "$filename" ]]; then
+ if [[ "$filename" =~ ".bak" ]]; then
+ local basename=${filename%.bak}
+ mv $filename $basename.json
+ fi
+ fi
}
make_vmess_config() {
- cat >tempvmess.json <tempvmess.json <temp_outbound_socks5.json < temphy2.json <temphy2.json < tmpsocks5.json <tmpsocks5.json <config.json <config.json < singbox.json <~/.cloudflared/config.yml <singbox.json < /dev/null 2>&1
- rsync -a $srcpath/ ~/ 2>/dev/null
- yellow "快照恢复完成!"
- return
- elif [ "$input" = "2" ]; then
- declare -A foundArr
- read -p "输入你要恢复到文件或目录:" infile
-
- for folder in "${!snapshot_paths[@]}"; do
- path="${snapshot_paths[$folder]}"
- results=$(find "${path}" -name "$infile" 2>/dev/null)
- # echo "111results:|$results|"
- if [[ -n "$results" ]]; then
- #echo "put |$results| to folder:$folder"
- foundArr["$folder"]="$results"
- fi
- done
- local i=1
- sortedFoundArr=($(echo "${!foundArr[@]}" | tr ' ' '\n' | sort -r))
- declare -A indexPathArr
- for folder in "${sortedFoundArr[@]}"; do
- echo "$i. $folder:"
- results="${foundArr[${folder}]}"
- IFS=$'\n' read -r -d '' -a paths <<< "$results"
- local j=1
- for path in "${paths[@]}"; do
- indexPathArr["$i"."$j"]="$path"
- echo " $j. $path"
-
- j=$((j+1))
- done
- i=$((i+1))
- done
-
- while [ true ]; do
- read -p "输入要恢复的文件序号,格式:日期序号.文件序号, 多个以逗号分隔.(如输入 1.2,3.2)[按enter返回]:" input
- regex='^([0-9]+\.[0-9]+)(,[0-9]+\.[0-9]+)*$'
-
- if [ -z "$input" ]; then
- return
- fi
-
- if [[ "$input" =~ $regex ]]; then
- declare -a pairNos
- declare -a fileNos
- IFS=',' read -r -a pairNos <<< "$input"
-
- echo "请选择文件恢复的目标路径:"
- echo "1.原路返回 "
- echo "2.${installpath}/restore "
- read -p "请选择:" targetDir
-
- if [[ "$targetDir" != "1" ]] && [[ "$targetDir" != "2" ]];then
- red "无效输入!"
- return
- fi
-
- for pairNo in "${pairNos[@]}"; do
- srcpath="${indexPathArr[$pairNo]}"
-
- if [ "$targetDir" = "1" ]; then
- local user=$(whoami)
- targetPath=${srcpath#*${user}}
- if [ -d $srcpath ]; then
- targetPath=${targetPath%/*}
- fi
- echo "cp -r $srcpath $HOME/$targetPath"
- cp -r ${srcpath} $HOME/${targetPath}
-
- elif [ "$targetDir" = "2" ]; then
- targetPath="${installpath}/restore"
- if [ ! -e "$targetPath" ]; then
- mkdir -p "$targetPath"
- fi
- cp -r $srcpath $targetPath/
- fi
- done
- green "完成文件恢复"
-
- else
- red "输入格式不对,请重新输入!"
- fi
- done
- fi
-
-}
-
-uninstall(){
- read -p "确定卸载吗? [y/n] [n]:" input
- input=${input:-n}
-
- if [ "$input" == "y" ]; then
- delCron
- stopSingBox
- cd $HOME
- rm -rf serv00-play
- echo "bye!"
- fi
-}
-
-InitServer(){
- read -p "$(red "将初始化帐号系统,要继续?[y/n] [n]:")" input
- input=${input:-n}
- read -p "是否保留用户配置?[y/n] [y]:" saveProfile
- saveProfile=${saveProfile:-y}
-
- if [[ "$input" == "y" ]] || [[ "$input" == "Y" ]]; then
- cleanCron
- green "清理进程中..."
- killUserProc
- green "清理磁盘中..."
- if [[ "$saveProfile" = "y" ]] || [[ "$saveProfile" = "Y" ]]; then
- rm -rf ~/* 2>/dev/null
- else
- rm -rf ~/* ~/.* 2>/dev/null
- fi
- cleanPort
- yellow "初始化完毕"
-
- exit 0
- fi
-}
-
-manageNeZhaAgent(){
- if ! checkInstalled "serv00-play"; then
- return 1
- fi
- while true; do
- yellow "-------------------------"
- echo "探针管理:"
- echo "1.安装探针"
- echo "2.升级探针"
- echo "3.启动/重启探针"
- echo "4.停止探针"
- echo "9.返回主菜单"
- echo "0.退出脚本"
- yellow "-------------------------"
-
- read -p "请选择:" choice
- case $choice in
- 1)
- installNeZhaAgent
- ;;
- 2)
- updateAgent
- ;;
- 3)
- startAgent
- exit 0;
- ;;
- 4)
- stopNeZhaAgent
- ;;
- 9)
- break
- ;;
- 0) exit 0
- ;;
- *)
- echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
-}
-
-updateAgent(){
- red "暂不提供在线升级, 只适配哪吒面板v0版本系列。"
- return 1
- exepath="${installpath}/serv00-play/nezha/nezha-agent"
- if [ ! -e "$exepath" ]; then
- red "未安装探针,请先安装!!!"
- return
- fi
-
- local workedir="${installpath}/serv00-play/nezha"
- cd $workedir
-
- local_version="v"$(./nezha-agent -v)
- latest_version=$(curl -sL https://github.com/nezhahq/agent/releases/latest | sed -n 's/.*tag\/\(v[0-9.]*\).*/\1/p' | head -1)
-
- if [[ "$local_version" != "$latest_version" ]]; then
- echo "发现新版本: $latest_version,当前版本: $local_version。正在更新..."
- download_url="https://github.com/nezhahq/agent/releases/download/$latest_version/nezha-agent_freebsd_amd64.zip"
-
- local filezip="nezha-agent_latest.zip"
- curl -sL -o "$filezip" "$download_url"
- if [[ ! -e "$filezip" || -n $(file "$filezip" | grep "text") ]]; then
- echo "下载探针文件失败!"
- return
- fi
- local agent_runing=0
- if checknezhaAgentAlive; then
- stopNeZhaAgent
- agent_runing=1
- fi
- unzip -o $filezip -d .
- chmod +x ./nezha-agent
- if [ $agent_runing -eq 1 ]; then
- startAgent
- fi
- rm -rf $filezip
- green "更新完成!新版本: $latest_version"
- else
- echo "已经是最新版本: $local_version"
- fi
- if [[ $agent_runing -eq 1 ]]; then
- exit 0;
- fi
-}
-
-startAgent(){
- local workedir="${installpath}/serv00-play/nezha"
- if [ ! -e "${workedir}" ]; then
- red "未安装探针,请先安装!!!"
- return
- fi
- cd $workedir
-
- local configfile="./nezha.json"
- if [ ! -e "$configfile" ]; then
- red "未安装探针,请先安装!!!"
- return
- fi
-
- nezha_domain=$(jq -r ".nezha_domain" $configfile)
- nezha_port=$(jq -r ".nezha_port" $configfile)
- nezha_pwd=$(jq -r ".nezha_pwd" $configfile)
- tls=$(jq -r ".tls" $configfile)
-
- if checknezhaAgentAlive; then
- stopNeZhaAgent
- fi
-
- local args="--report-delay 4 --disable-auto-update --disable-force-update "
- if [[ "$tls" == "y" ]]; then
- args="${args} --tls "
- fi
-
- #echo "./nezha-agent ${args} -s ${nezha_domain}:${nezha_port} -p ${nezha_pwd}"
- nohup ./nezha-agent ${args} -s ${nezha_domain}:${nezha_port} -p ${nezha_pwd} >/dev/null 2>&1 &
-
- if checknezhaAgentAlive; then
- green "启动成功!"
- else
- red "启动失败!"
- fi
- #即便使用nohup放后台,此处如果使用ctrl+c退出脚本,nezha-agent进程也会退出。非常奇葩,因此startAgent后只能exit退出脚本,避免用户使用ctrl+c退出。
-
-}
-
-installNeZhaAgent(){
- local workedir="${installpath}/serv00-play/nezha"
- if [ ! -e "${workedir}" ]; then
- mkdir -p "${workedir}"
- fi
- cd ${workedir}
- if [[ ! -e nezha-agent ]]; then
- echo "正在下载哪吒探针..."
- local url="https://github.com/nezhahq/agent/releases/download/v0.20.3/nezha-agent_freebsd_amd64.zip"
- agentZip="nezha-agent.zip"
- if ! wget -qO "$agentZip" "$url"; then
- red "下载哪吒探针失败"
- return 1
- fi
- unzip $agentZip > /dev/null 2>&1
- chmod +x ./nezha-agent
- green "下载完毕"
- fi
-
- local config="nezha.json"
- local input="y"
- if [[ -e "$config" ]]; then
- echo "哪吒探针配置如下:"
- cat "$config"
- read -p "是否修改? [y/n] [n]:" input
- input=${input:-n}
- fi
-
- if [[ "$input" == "y" ]]; then
- read -p "请输入哪吒面板的域名或ip:" nezha_domain
- read -p "请输入哪吒面板RPC端口(默认 5555):" nezha_port
- nezha_port=${nezha_port:-5555}
- read -p "请输入服务器密钥(从哪吒面板中获取):" nezha_pwd
- read -p "是否启用针对 gRPC 端口的 SSL/TLS加密 (--tls),需要请按 [y],默认是不需要,不理解用户可回车跳过: " tls
- tls=${tls:-"N"}
- else
- nezha_domain=$(jq -r ".nezha_domain" $config)
- nezha_port=$(jq -r ".nezha_port" $config)
- nezha_pwd=$(jq -r ".nezha_pwd" $config)
- tls=$(jq -r ".tls" $config)
- fi
-
- if [[ -z "$nezha_domain" || -z "$nezha_port" || -z "$nezha_pwd" ]]; then
- red "以上参数都不能为空!"
- return 1
- fi
-
- cat > $config </dev/null 2>&1
+ rsync -a $srcpath/ ~/ 2>/dev/null
+ yellow "快照恢复完成!"
+ return
+ elif [ "$input" = "2" ]; then
+ declare -A foundArr
+ read -p "输入你要恢复到文件或目录:" infile
+
+ for folder in "${!snapshot_paths[@]}"; do
+ path="${snapshot_paths[$folder]}"
+ results=$(find "${path}" -name "$infile" 2>/dev/null)
+ # echo "111results:|$results|"
+ if [[ -n "$results" ]]; then
+ #echo "put |$results| to folder:$folder"
+ foundArr["$folder"]="$results"
+ fi
+ done
+ local i=1
+ sortedFoundArr=($(echo "${!foundArr[@]}" | tr ' ' '\n' | sort -r))
+ declare -A indexPathArr
+ for folder in "${sortedFoundArr[@]}"; do
+ echo "$i. $folder:"
+ results="${foundArr[${folder}]}"
+ IFS=$'\n' read -r -d '' -a paths <<<"$results"
+ local j=1
+ for path in "${paths[@]}"; do
+ indexPathArr["$i"."$j"]="$path"
+ echo " $j. $path"
+
+ j=$((j + 1))
+ done
+ i=$((i + 1))
+ done
+
+ while [ true ]; do
+ read -p "输入要恢复的文件序号,格式:日期序号.文件序号, 多个以逗号分隔.(如输入 1.2,3.2)[按enter返回]:" input
+ regex='^([0-9]+\.[0-9]+)(,[0-9]+\.[0-9]+)*$'
+
+ if [ -z "$input" ]; then
+ return
+ fi
+
+ if [[ "$input" =~ $regex ]]; then
+ declare -a pairNos
+ declare -a fileNos
+ IFS=',' read -r -a pairNos <<<"$input"
+
+ echo "请选择文件恢复的目标路径:"
+ echo "1.原路返回 "
+ echo "2.${installpath}/restore "
+ read -p "请选择:" targetDir
+
+ if [[ "$targetDir" != "1" ]] && [[ "$targetDir" != "2" ]]; then
+ red "无效输入!"
+ return
+ fi
+
+ for pairNo in "${pairNos[@]}"; do
+ srcpath="${indexPathArr[$pairNo]}"
+
+ if [ "$targetDir" = "1" ]; then
+ local user=$(whoami)
+ targetPath=${srcpath#*${user}}
+ if [ -d $srcpath ]; then
+ targetPath=${targetPath%/*}
+ fi
+ echo "cp -r $srcpath $HOME/$targetPath"
+ cp -r ${srcpath} $HOME/${targetPath}
+
+ elif [ "$targetDir" = "2" ]; then
+ targetPath="${installpath}/restore"
+ if [ ! -e "$targetPath" ]; then
+ mkdir -p "$targetPath"
+ fi
+ cp -r $srcpath $targetPath/
+ fi
+ done
+ green "完成文件恢复"
+
+ else
+ red "输入格式不对,请重新输入!"
+ fi
+ done
+ fi
+
+}
+
+get_domain_webip() {
+ local domain=$1
+ if [[ -z "$domain" ]]; then
+ echo ""
+ return
+ fi
+ devil ssl www list | awk -v d="$domain" 'tolower($1)==tolower(d) {print $2; exit}'
+}
+
+delete_domain_service() {
+ local domain=$1
+ if [[ -z "$domain" ]]; then
+ return
+ fi
+ domain="${domain,,}"
+ local webip=$(get_domain_webip "$domain")
+ if [[ -n "$webip" ]]; then
+ devil ssl www del $webip $domain >/dev/null 2>&1
+ fi
+ devil www del $domain --remove >/dev/null 2>&1
+ rm -rf "${installpath}/domains/$domain"
+ green "已删除域名服务: $domain"
+}
+
+delete_domains_from_domainlist() {
+ local list_file=$1
+ if [[ ! -f "$list_file" ]]; then
+ red "domainlist文件不存在!"
+ return 1
+ fi
+ while read -r domain; do
+ domain=$(echo "$domain" | xargs)
+ if [[ -z "$domain" ]]; then
+ continue
+ fi
+ delete_domain_service "$domain"
+ done < <(awk 'NF && $1 != "Domain" {print $1}' "$list_file")
+}
+
+delete_domains_from_phpconfig() {
+ local config_file=$1
+ if [[ ! -f "$config_file" ]]; then
+ red "未找到phpconfig.json!"
+ return 1
+ fi
+ local domains=$(jq -r '.domains[].domain' "$config_file" 2>/dev/null)
+ if [[ -z "$domains" ]]; then
+ red "phpconfig.json中未找到域名!"
+ return 1
+ fi
+ while read -r domain; do
+ domain=$(echo "$domain" | xargs)
+ if [[ -z "$domain" ]]; then
+ continue
+ fi
+ delete_domain_service "$domain"
+ done <<<"$domains"
+}
+
+backupAll() {
+ local delete_choice=""
+ read -p "是否删除所有域名关联服务? [y/n] [n]:" delete_choice
+ delete_choice=${delete_choice:-n}
+ local phpconfig_file="${installpath}/serv00-play/domains-support/phpconfig.json"
+ local tarfile="${installpath}/all.tar.gz"
+ local phpconfig_rel="serv00-play/domains-support/phpconfig.json"
+ if [[ ! -f "$phpconfig_file" ]]; then
+ red "未找到phpconfig.json!"
+ return 1
+ fi
+ echo "正在备份中,请稍后(可能需要几分钟)..."
+ tar -czf "$tarfile" -C "$installpath" "$phpconfig_rel"
+ if [[ $? -ne 0 ]]; then
+ red "备份失败!"
+ return 1
+ fi
+ green "备份完成: $tarfile"
+ if [[ "$delete_choice" == "y" ]]; then
+ delete_domains_from_phpconfig "$phpconfig_file"
+ fi
+}
+
+restore_domains_from_config() {
+ local workdir="${installpath}/serv00-play/domains-support"
+ local config_file="${workdir}/phpconfig.json"
+ if [[ ! -f "$config_file" ]]; then
+ red "未找到phpconfig.json!"
+ return 1
+ fi
+ cd $workdir
+ local domains=$(jq -r '.domains[].domain' "$config_file" 2>/dev/null)
+ if [[ -z "$domains" ]]; then
+ red "phpconfig.json中未找到域名!"
+ return 1
+ fi
+ read -r -p "是否自动配置 Cloudflare 域名 DNS?(y/n) [默认: n]: " auto_cf_dns
+ auto_cf_dns=${auto_cf_dns:-n}
+ local cf_api_token=""
+ local cf_email=""
+ if [[ "$auto_cf_dns" == "y" || "$auto_cf_dns" == "Y" ]]; then
+ read -r -p "请输入 Cloudflare API Token: " cf_api_token
+ if [[ -z "$cf_api_token" ]]; then
+ red "API Token 不能为空!"
+ return 1
+ fi
+ read -r -p "请输入 Cloudflare 账户邮箱: " cf_email
+ if [[ -z "$cf_email" ]]; then
+ red "账户邮箱不能为空!"
+ return 1
+ fi
+ fi
+ local failed_domains=()
+ while read -r domain; do
+ domain=$(echo "$domain" | xargs)
+ if [[ -z "$domain" ]]; then
+ continue
+ fi
+ domain="${domain,,}"
+ domainPath="$installpath/domains/$domain/public_html"
+ webIp=""
+ echo "正在恢复域名: $domain"
+ if ! makeWWW "" "" "php" "y" "$domain"; then
+ red "绑定域名 $domain 失败!"
+ continue
+ fi
+ if [[ "$auto_cf_dns" == "y" || "$auto_cf_dns" == "Y" ]]; then
+ if [[ -n "$webIp" && -n "$cf_api_token" && -n "$cf_email" ]]; then
+ yellow "正在为 $domain 配置 Cloudflare DNS..."
+ local zone_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${domain}" \
+ -H "X-Auth-Email: ${cf_email}" \
+ -H "X-Auth-Key: ${cf_api_token}" \
+ -H "Content-Type: application/json" | jq -r '.result[0].id')
+
+ if [[ -z "$zone_id" || "$zone_id" == "null" ]]; then
+ red "无法获取域名 $domain 的 Zone ID,请检查域名是否已添加到您的 Cloudflare 账户。"
+ failed_domains+=("$domain")
+ continue
+ else
+ local existing_record_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records?type=A&name=${domain}" \
+ -H "X-Auth-Email: ${cf_email}" \
+ -H "X-Auth-Key: ${cf_api_token}" \
+ -H "Content-Type: application/json" | jq -r --arg domain "$domain" '.result[] | select(.name == $domain) | .id')
+
+ if [[ -n "$existing_record_id" && "$existing_record_id" != "null" ]]; then
+ yellow "✓ 域名 $domain 已存在 A 记录,正在更新 IP 地址为 $webIp..."
+ local update_record_response=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records/${existing_record_id}" \
+ -H "X-Auth-Email: ${cf_email}" \
+ -H "X-Auth-Key: ${cf_api_token}" \
+ -H "Content-Type: application/json" \
+ --data '{"type":"A","name":"'"$domain"'","content":"'"$webIp"'","ttl":1,"proxied":false}')
+
+ if [[ $(echo "$update_record_response" | jq -r '.success') != "true" ]]; then
+ red "更新域名 $domain 的 A 记录失败: $(echo "$update_record_response" | jq -r '.errors[0].message')"
+ failed_domains+=("$domain")
+ continue
+ fi
+ else
+ yellow "正在为 $domain 创建新的 A 记录..."
+ local create_record_response=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records" \
+ -H "X-Auth-Email: ${cf_email}" \
+ -H "X-Auth-Key: ${cf_api_token}" \
+ -H "Content-Type: application/json" \
+ --data '{"type":"A","name":"'"$domain"'","content":"'"$webIp"'","ttl":1,"proxied":false}')
+
+ if [[ $(echo "$create_record_response" | jq -r '.success') != "true" ]]; then
+ red "为 $domain 创建 A 记录失败: $(echo "$create_record_response" | jq -r '.errors[0].message')"
+ failed_domains+=("$domain")
+ continue
+ fi
+ fi
+ fi
+ else
+ red "缺少 WebIP 或 Cloudflare 凭证,无法自动配置 DNS。"
+ failed_domains+=("$domain")
+ continue
+ fi
+ fi
+ sleep 10
+ if ! applyLE "$domain" "$webIp" "y"; then
+ red "申请证书失败: $domain"
+ fi
+ if [[ ! -d "$domainPath" ]]; then
+ red "目标目录不存在: $domainPath"
+ continue
+ fi
+ local style_choice=$((RANDOM % 6 + 1))
+ case "$style_choice" in
+ 1)
+ cp websites/sakura.html "$domainPath/index.html"
+ sed -i.bak "s|xx|樱花|g" "$domainPath/index.html"
+ ;;
+ 2)
+ cp websites/hr.html "$domainPath/index.html"
+ ;;
+ 3)
+ cp websites/deyiedu.html "$domainPath/index.html"
+ ;;
+ 4)
+ cp websites/resume.html "$domainPath/index.html"
+ ;;
+ 5)
+ cp websites/game.html "$domainPath/index.html"
+ ;;
+ 6)
+ cp websites/christmas.html "$domainPath/index.html"
+ ;;
+ esac
+ green "域名 $domain 的网站恢复完成!"
+ done <<<"$domains"
+ if [[ ${#failed_domains[@]} -gt 0 ]]; then
+ red "以下域名 DNS 配置失败,请手动修改 DNS 后再进行批量导入域名:"
+ for d in "${failed_domains[@]}"; do
+ echo "$d"
+ done
+ fi
+}
+
+restoreAll() {
+ local tarfile="${installpath}/all.tar.gz"
+ local phpconfig_file="${installpath}/serv00-play/domains-support/phpconfig.json"
+ if [[ ! -f "$tarfile" ]]; then
+ red "未发现备份文件: $tarfile"
+ return 1
+ fi
+ tar -xzf "$tarfile" -C "$installpath"
+ if [[ $? -ne 0 ]]; then
+ red "恢复失败!"
+ return 1
+ fi
+ if [[ ! -f "$phpconfig_file" ]]; then
+ red "未恢复到phpconfig.json!"
+ return 1
+ fi
+ green "文件恢复完成!"
+ restore_domains_from_config
+}
+
+backupRestoreServ() {
+ while true; do
+ yellow "---------------------"
+ echo "备份/恢复功能:"
+ echo "1. 备份"
+ echo "2. 恢复"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ backupAll
+ ;;
+ 2)
+ restoreAll
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+uninstall() {
+ local input=$1
+ if [ -z "$input" ]; then
+ read -p "确定卸载吗? [y/n] [n]:" input
+ input=${input:-n}
+ fi
+
+ if [ "$input" == "y" ]; then
+ delCron
+ stopSingBox
+ cd $HOME
+ rm -rf serv00-play
+ echo "bye!"
+ fi
+}
+
+InitServer() {
+ read -p "$(red "将初始化帐号系统,要继续?[y/n] [n]:")" input
+ input=${input:-n}
+ if [[ "$input" != "y" ]]; then
+ return
+ fi
+ read -p "是否保留用户配置?[y/n] [y]:" saveProfile
+ saveProfile=${saveProfile:-y}
+
+ if [[ "$input" == "y" ]] || [[ "$input" == "Y" ]]; then
+ cleanCron
+ green "清理进程中..."
+ killUserProc
+ green "清理磁盘中..."
+ if [[ "$saveProfile" == "y" ]] || [[ "$saveProfile" == "Y" ]]; then
+ find ~ -mindepth 1 -maxdepth 1 ! -name "domains" ! -name "backups" ! -name "repo" ! -name "mail" ! -name ".*" -exec rm -rf {} + >/dev/null 2>&1
+ else
+ rm -rf ~/* ~/.* 2>/dev/null
+ clean_all_domains
+ clean_all_dns
+ create_default_domain
+ fi
+ cleanPort
+ yellow "初始化完毕"
+
+ exit 0
+ fi
+}
+
+manageNeZhaAgent() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "-------------------------"
+ echo "探针管理:"
+ echo "服务状态: $(checkProcStatus nezha-agent)"
+ echo "1.安装探针(v0或v1)"
+ echo "2.升级探针(仅v1以上版本)"
+ echo "3.启动/重启探针"
+ echo "4.停止探针"
+ echo "5.卸载探针"
+ echo "9.返回主菜单"
+ echo "0.退出脚本"
+ yellow "-------------------------"
+
+ read -p "请选择:" choice
+ case $choice in
+ 1)
+ installNeZhaAgent
+ ;;
+ 2)
+ updateAgent
+ ;;
+ 3)
+ startAgent
+ exit 0
+ ;;
+ 4)
+ stopNeZhaAgent
+ ;;
+ 5)
+ uninstallAgent
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+installNeZhaAgent() {
+ local workedir="${installpath}/serv00-play/nezha"
+ if [ ! -e "${workedir}" ]; then
+ mkdir -p "${workedir}"
+ fi
+
+ cd ${workedir}
+ if [ -e nezha-agent ]; then
+ red "探针已安装,重新安装请先卸载!"
+ return 1
+ fi
+ echo "确认安装哪吒探针的版本:"
+ echo "1. v0.20.5"
+ echo "2. v1 -latest"
+ read -p "请选择:" ver
+ if [[ "$ver" != "1" && "$ver" != "2" ]]; then
+ echo "无效输入!"
+ return 1
+ fi
+
+ echo "正在下载哪吒探针..."
+ if [[ "$ver" == "1" ]]; then
+ # 安装v0版本
+ local url="https://github.com/nezhahq/agent/releases/download/v0.20.5/nezha-agent_freebsd_amd64.zip"
+ agentZip="nezha-agent.zip"
+ if ! wget -qO "$agentZip" "$url"; then
+ red "下载哪吒探针失败"
+ return 1
+ fi
+ unzip $agentZip >/dev/null 2>&1
+ else
+ latest_version=$(curl -sL https://github.com/nezhahq/agent/releases/latest | sed -n 's/.*tag\/\(v[0-9.]*\).*/\1/p' | head -1)
+ download_url="https://github.com/nezhahq/agent/releases/download/$latest_version/nezha-agent_freebsd_amd64.zip"
+ local filezip="nezha-agent_latest.zip"
+ curl -sL -o "$filezip" "$download_url"
+ if [[ ! -e "$filezip" || -n $(file "$filezip" | grep "text") ]]; then
+ echo "下载探针文件失败!"
+ return
+ fi
+ unzip -o $filezip -d .
+ fi
+ chmod +x ./nezha-agent
+ green "下载完毕"
+
+ local config="nezha.json"
+
+ read -p "请输入哪吒面板的域名或ip:" nezha_domain
+ read -p "请输入哪吒面板RPC端口(默认 5555):" nezha_port
+ nezha_port=${nezha_port:-5555}
+ read -p "请输入服务器密钥(从哪吒面板中获取):" nezha_pwd
+ read -p "是否启用针对 gRPC 端口的 SSL/TLS加密 (--tls),需要请按 [y],默认是不需要,不理解用户可回车跳过: " tls
+ tls=${tls:-"N"}
+
+ if [[ -z "$nezha_domain" || -z "$nezha_port" || -z "$nezha_pwd" ]]; then
+ red "以上参数都不能为空!"
+ return 1
+ fi
+
+ cat >$config <$yamlcfg </dev/null 2>&1 &
+ else
+ nohup ./nezha-agent -c $yamlcfg >/dev/null 2>&1 &
+ fi
+ green "哪吒探针成功启动!"
+
+}
+
+updateAgent() {
+ exepath="${installpath}/serv00-play/nezha/nezha-agent"
+ if [ ! -e "$exepath" ]; then
+ red "未安装探针,请先安装!!!"
+ return
+ fi
+
+ cd ${installpath}/serv00-play/nezha
+
+ if ! check_update_from_net "nezha-agent"; then
+ return 1
+ fi
+
+ stopNeZhaAgent
+ download_from_net "nezha-agent"
+ if [[ -e "nezha-agent" ]]; then
+ chmod +x ./nezha-agent
+ else
+ red "下载失败!"
+ return
+ fi
+ startNeZhaAgent
+ green "更新完毕!"
+
+ return
+
+}
+
+startAgent() {
+ local exepath="${installpath}/serv00-play/nezha/nezha-agent"
+ if [ ! -e "${exepath}" ]; then
+ red "未安装探针,请先安装!!!"
+ return
+ fi
+ cd "${installpath}/serv00-play/nezha"
+
+ local configfile="./nezha.json"
+ if [ ! -e "$configfile" ]; then
+ red "未安装探针,请先安装!!!"
+ return
+ fi
+
+ nezha_domain=$(jq -r ".nezha_domain" $configfile)
+ nezha_port=$(jq -r ".nezha_port" $configfile)
+ nezha_pwd=$(jq -r ".nezha_pwd" $configfile)
+ ver=$(jq -r ".version" $configfile)
+ tls=$(jq -r ".tls" $configfile)
+
+ if checknezhaAgentAlive; then
+ stopNeZhaAgent
+ fi
+
+ local args="--report-delay 4 --disable-auto-update --disable-force-update "
+ if [[ "$tls" == "y" ]]; then
+ args="${args} --tls "
+ fi
+
+ if [[ "$ver" == "1" ]]; then
+ #echo "./nezha-agent ${args} -s ${nezha_domain}:${nezha_port} -p ${nezha_pwd}"
+ nohup ./nezha-agent ${args} -s ${nezha_domain}:${nezha_port} -p ${nezha_pwd} >/dev/null 2>&1 &
+ else
+ nohup ./nezha-agent -c config.yaml 2>&1 &
+ fi
+
+ if checknezhaAgentAlive; then
+ green "启动成功!"
+ else
+ red "启动失败!"
+ fi
+ #即便使用nohup放后台,此处如果使用ctrl+c退出脚本,nezha-agent进程也会退出。非常奇葩,因此startAgent后只能exit退出脚本,避免用户使用ctrl+c退出。
+
+}
+
+uninstallAgent() {
+ read -p "确定卸载哪吒探针? [y/n] [n]:" input
+ input=${input:-n}
+
+ if [[ "$input" == "y" ]]; then
+ if checknezhaAgentAlive; then
+ stopNeZhaAgent
+ fi
+ local workedir="${installpath}/serv00-play/nezha"
+ rm -rf $workedir
+ green "卸载完毕!"
+ fi
+
+}
+manageNeZhaBoard() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "---------------------"
+ echo "哪吒面板管理(仅支持v1):"
+ echo "服务状态: $(checkProcStatus nezha-dashboard)"
+ echo "1. 安装"
+ echo "2. 启动"
+ echo "3. 停止"
+ echo "4. 更新"
+ echo "8. 卸载"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ installNeZhaDashboard
+ ;;
+ 2)
+ startNeZhaDashboard
+ ;;
+ 3)
+ stopNeZhaDashboard
+ ;;
+ 4)
+ updateNeZhaDashboard
+ ;;
+ 8)
+ uninstallNeZhaDashboard
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+installNeZhaDashboard() {
+ local workedir="${installpath}/serv00-play/nezha-board"
+ if [ ! -e "${workedir}" ]; then
+ mkdir -p "${workedir}"
+ fi
+
+ cd ${workedir}
+ if [ -e "./nezha-dashboard" ]; then
+ red "面板已安装,重新安装请先卸载!"
+ return 1
+ fi
+ if ! download_from_net "nezha-dashboard"; then
+ return 1
+ fi
+ if [[ -e "dashboard" ]]; then
+ mv ./dashboard ./nezha-dashboard
+ chmod +x ./nezha-dashboard
+ else
+ red "下载失败!"
+ return 1
+ fi
+
+ #自动分配端口
+ loadPort
+ randomPort tcp nezha-dashboard
+ if [[ -n "$port" ]]; then
+ nz_port="$port"
+ else
+ red "未输入端口号"
+ return 1
+ fi
+ read -p "请输入站点标题: " nz_site_title
+ echo "请指定后台语言"
+ echo "1. 中文(简体)"
+ echo "2. 中文(繁体)"
+ echo "3. English"
+ while true; do
+ read -p "请输入选项 [1-3]" option
+ case "${option}" in
+ 1)
+ nz_lang=zh_CN
+ break
+ ;;
+ 2)
+ nz_lang=zh_TW
+ break
+ ;;
+ 3)
+ nz_lang=en_US
+ break
+ ;;
+ *)
+ echo "请输入正确的选项 [1-3]"
+ ;;
+ esac
+ done
+ echo "正在安装哪吒面板,请等待..."
+ domain=""
+ webIp=""
+ if ! makeWWW "" $nz_port; then
+ echo "绑定域名失败!"
+ return 1
+ fi
+ if ! applyLE $domain $webIp; then
+ echo "申请证书失败!"
+ return 1
+ fi
+ cd ${workedir}
+ nz_hostport="${domain}:${nz_port}"
+ #serv00不支持gprc转发,所以不需要tls
+
+ cat >config.yaml </dev/null 2>&1 &
- green "哪吒探针成功启动!"
-
-}
-
-uninstallAgent(){
- read -p "确定卸载哪吒探针? [y/n] [n]:" input
- input=${input:-n}
-
- if [[ "$input" == "y" ]]; then
- if checknezhaAgentAlive; then
- stopNeZhaAgent
- fi
- local workedir="${installpath}/serv00-play/nezha"
- rm -rf $workedir
- green "卸载完毕!"
- fi
-
-}
-
-setCnTimeZone(){
- read -p "确定设置中国上海时区? [y/n] [y]:" input
- input=${input:-y}
-
- cd ${installpath}
- if [ "$input" = "y" ]; then
- devil binexec on
- touch .profile
- cat .profile | perl ./serv00-play/mkprofile.pl > tmp_profile
- mv -f tmp_profile .profile
-
- read -p "$(yellow 设置完毕,需要重新登录才能生效,是否重新登录?[y/n] [y]:)" input
- input=${input:-y}
-
- if [ "$input" = "y" ]; then
- kill -9 $PPID
- fi
- fi
-
-}
-
-setColorWord(){
- cd ${installpath}
- # 定义颜色编码
- bright_black="\033[1;90m"
- bright_red="\033[1;91m"
- bright_green="\033[1;92m"
- bright_yellow="\033[1;93m"
- bright_blue="\033[1;94m"
- bright_magenta="\033[1;95m"
- bright_cyan="\033[1;96m"
- bright_white="\033[1;97m"
- reset="\033[0m"
-
- # 显示颜色选项列表,并使用颜色着色
- echo -e "请选择一个颜色来输出你的签名:"
- echo -e "1) ${bright_black}明亮黑色${reset}"
- echo -e "2) ${bright_red}明亮红色${reset}"
- echo -e "3) ${bright_green}明亮绿色${reset}"
- echo -e "4) ${bright_yellow}明亮黄色${reset}"
- echo -e "5) ${bright_blue}明亮蓝色${reset}"
- echo -e "6) ${bright_magenta}明亮紫色${reset}"
- echo -e "7) ${bright_cyan}明亮青色${reset}"
- echo -e "8) ${bright_white}明亮白色${reset}"
-
- # 读取用户输入的选择
- read -p "请输入你的选择(1-8): " color_choice
-
- read -p "请输入你的大名(仅支持ascii字符):" name
-
- # 根据用户的选择设置颜色
- case $color_choice in
- 1) color_code="90" ;; # 明亮黑色
- 2) color_code="91" ;; # 明亮红色
- 3) color_code="92" ;; # 明亮绿色
- 4) color_code="93" ;; # 明亮黄色
- 5) color_code="94" ;; # 明亮蓝色
- 6) color_code="95" ;; # 明亮紫色
- 7) color_code="96" ;; # 明亮青色
- 8) color_code="97" ;; # 明亮白色
- *) echo "无效选择,使用默认颜色 (明亮白色)"; color_code="97" ;;
- esac
-
- if grep "chAngEYourName" .profile > /dev/null ; then
- cat .profile | grep -v "chAngEYourName" > tmp_profile
- echo "echo -e \"\033[1;${color_code}m\$(figlet \"${name}\")\033[0m\" #chAngEYourName" >> tmp_profile
- mv -f tmp_profile .profile
- else
- echo "echo -e \"\033[1;${color_code}m\$(figlet \"${name}\")\033[0m\" #chAngEYourName" >> .profile
- fi
-
- read -p "设置完毕! 重新登录看效果? [y/n] [y]:" input
- input=${input:-y}
- if [[ "$input" == "y" ]]; then
- kill -9 $PPID
- fi
-
-}
-
-showIP(){
- myip="$(curl -s ifconfig.me)"
- green "本机IP: $myip"
-}
-
-uninstallMtg(){
- read -p "确定卸载? [y/n] [n]:" input
- input=${input:-n}
-
- if [[ "$input" == "n" ]]; then
- return 1
- fi
-
- if [[ -e "mtg" ]]; then
- if checkProcAlive mtg; then
- stopMtg
- fi
- cd ${installpath}/serv00-play
- rm -rf dmtg
- green "卸载完毕!"
- fi
-}
-
-installMtg(){
- if [ ! -e "mtg" ]; then
- # read -p "请输入使用密码:" password
- if ! checkDownload "mtg"; then
- return 1
- fi
- fi
-
- chmod +x ./mtg
- if [ -e "config.json" ]; then
- echo "已存在配置如下:"
- cat config.json
- read -p "是否重新生成配置? [y/n] [n]:" input
- input=${input:-n}
- if [ "$input" == "n" ]; then
- return 0
- fi
- fi
-
- #自动生成密钥
- head=$(hostname | cut -d '.' -f 1)
- no=${head#s}
- host="panel${no}.serv00.com"
- secret=$(./mtg generate-secret --hex $host )
- loadPort
- randomPort tcp mtg
- if [[ -n "$port" ]]; then
- mtpport="$port"
- fi
-
- cat > config.json <borad.log 2>&1 &
+ if checkProcAlive nezha-dashboard; then
+ green "面板已启动!"
+ else
+ red "面板启动失败,请查看日志borad.log"
+ fi
+
+}
+stopNeZhaDashboard() {
+ if checkProcAlive nezha-dashboard; then
+ stopProc nezha-dashboard
+ else
+ red "面板未启动!"
+ fi
+}
+updateNeZhaDashboard() {
+ if [ ! -e "${installpath}/serv00-play/nezha-board/nezha-dashboard" ]; then
+ red "未安装面板,请先安装!!!"
+ return
+ fi
+ cd ${installpath}/serv00-play/nezha-board
+
+ if ! check_update_from_net "nezha-dashboard"; then
+ return 1
+ fi
+
+ stopNeZhaDashboard
+ download_from_net "nezha-dashboard"
+ if [[ -e "dashboard" ]]; then
+ mv -f ./dashboard ./nezha-dashboard
+ chmod +x ./nezha-dashboard
+ fi
+ startNeZhaDashboard
+ green "更新完毕!"
+
+ return
+}
+
+uninstallNeZhaDashboard() {
+ local workedir="${installpath}/serv00-play/nezha-board"
+ if [ ! -e "${workedir}" ]; then
+ red "未安装面板!"
+ return
+ fi
+ uninstallProc $workedir "nezha-dashboard"
+}
+
+setCnTimeZone() {
+ read -p "确定设置中国上海时区? [y/n] [y]:" input
+ input=${input:-y}
+
+ cd ${installpath}
+ if [ "$input" = "y" ]; then
+ devil binexec on
+ touch .profile
+ cat .profile | perl ./serv00-play/mkprofile.pl >tmp_profile
+ mv -f tmp_profile .profile
+
+ read -p "$(yellow 设置完毕,需要重新登录才能生效,是否重新登录?[y/n] [y]:)" input
+ input=${input:-y}
+
+ if [ "$input" = "y" ]; then
+ kill -9 $PPID
+ fi
+ fi
+
+}
+
+setColorWord() {
+ cd ${installpath}
+ # 定义颜色编码
+ bright_black="\033[1;90m"
+ bright_red="\033[1;91m"
+ bright_green="\033[1;92m"
+ bright_yellow="\033[1;93m"
+ bright_blue="\033[1;94m"
+ bright_magenta="\033[1;95m"
+ bright_cyan="\033[1;96m"
+ bright_white="\033[1;97m"
+ reset="\033[0m"
+
+ # 显示颜色选项列表,并使用颜色着色
+ echo -e "请选择一个颜色来输出你的签名:"
+ echo -e "1) ${bright_black}明亮黑色${reset}"
+ echo -e "2) ${bright_red}明亮红色${reset}"
+ echo -e "3) ${bright_green}明亮绿色${reset}"
+ echo -e "4) ${bright_yellow}明亮黄色${reset}"
+ echo -e "5) ${bright_blue}明亮蓝色${reset}"
+ echo -e "6) ${bright_magenta}明亮紫色${reset}"
+ echo -e "7) ${bright_cyan}明亮青色${reset}"
+ echo -e "8) ${bright_white}明亮白色${reset}"
+
+ # 读取用户输入的选择
+ read -p "请输入你的选择(1-8): " color_choice
+
+ read -p "请输入你的大名(仅支持ascii字符):" name
+
+ # 根据用户的选择设置颜色
+ case $color_choice in
+ 1) color_code="90" ;; # 明亮黑色
+ 2) color_code="91" ;; # 明亮红色
+ 3) color_code="92" ;; # 明亮绿色
+ 4) color_code="93" ;; # 明亮黄色
+ 5) color_code="94" ;; # 明亮蓝色
+ 6) color_code="95" ;; # 明亮紫色
+ 7) color_code="96" ;; # 明亮青色
+ 8) color_code="97" ;; # 明亮白色
+ *)
+ echo "无效选择,使用默认颜色 (明亮白色)"
+ color_code="97"
+ ;;
+ esac
+
+ if grep "chAngEYourName" .profile >/dev/null; then
+ cat .profile | grep -v "chAngEYourName" >tmp_profile
+ echo "echo -e \"\033[1;${color_code}m\$(figlet \"${name}\")\033[0m\" #chAngEYourName" >>tmp_profile
+ mv -f tmp_profile .profile
+ else
+ echo "echo -e \"\033[1;${color_code}m\$(figlet \"${name}\")\033[0m\" #chAngEYourName" >>.profile
+ fi
+
+ read -p "设置完毕! 重新登录看效果? [y/n] [y]:" input
+ input=${input:-y}
+ if [[ "$input" == "y" ]]; then
+ kill -9 $PPID
+ fi
+
+}
+
+showIP() {
+ myip="$(curl -s icanhazip.com)"
+ green "本机IP: $myip"
+}
+
+uninstallMtg() {
+ read -p "确定卸载? [y/n] [n]:" input
+ input=${input:-n}
+
+ if [[ "$input" == "n" ]]; then
+ return 1
+ fi
+
+ if [[ -e "mtg" ]]; then
+ if checkProcAlive mtg; then
+ stopMtg
+ fi
+ cd ${installpath}/serv00-play
+ rm -rf dmtg
+ green "卸载完毕!"
+ fi
+}
+
+installMtg() {
+ local workedir="${installpath}/serv00-play/dmtg"
+ if [ ! -e "${workedir}" ]; then
+ mkdir -p "${workedir}"
+ fi
+ cd ${workedir}
+
+ if [ ! -e "mtg" ]; then
+ # read -p "请输入使用密码:" password
+ if ! checkDownload "mtg"; then
+ return 1
+ fi
+ fi
+
+ chmod +x ./mtg
+ if [ -e "config.json" ]; then
+ echo "已存在配置如下:"
+ cat config.json
+ read -p "是否重新生成配置? [y/n] [n]:" input
+ input=${input:-n}
+ if [ "$input" == "n" ]; then
+ return 0
+ fi
+ fi
+
+ #自动生成密钥
+ head=$(hostname | cut -d '.' -f 1)
+ no=${head#s}
+ host="panel${no}.$(getDoMain)"
+ secret=$(./mtg generate-secret --hex $host)
+ loadPort
+ randomPort tcp mtg
+ if [[ -n "$port" ]]; then
+ mtpport="$port"
+ fi
+
+ cat >config.json <&1 &"
- eval "$cmd"
- sleep 3
- if checkMtgAlive; then
- mtproto="https://t.me/proxy?server=${host}.serv00.com&port=${port}&secret=${secret}"
- echo "$mtproto"
- green "启动成功"
- else
- echo "启动失败,请检查进程"
- fi
-
-}
-
-stopMtg(){
- r=$(ps aux | grep mtg | grep -v "grep" | awk '{print $2}' )
- if [ -z "$r" ]; then
- echo "没有运行!"
- return
- else
- kill -9 $r
- fi
- echo "已停掉mtproto!"
-
-}
-
-mtprotoServ(){
- if ! checkInstalled "serv00-play"; then
- return 1
- fi
- cd ${installpath}/serv00-play
-
- if [ ! -e "dmtg" ]; then
- mkdir -p dmtg
- fi
- cd dmtg
-
- while true; do
- yellow "---------------------"
- echo "服务状态: $(checkProcStatus mtg)"
- echo "mtproto管理:"
- echo "1. 安装"
- echo "2. 启动"
- echo "3. 停止"
- echo "4. 卸载"
- echo "9. 返回主菜单"
- echo "0. 退出脚本"
- yellow "---------------------"
- read -p "请选择:" input
-
- case $input in
- 1) installMtg
- ;;
- 2) startMtg
- ;;
- 3) stopMtg
- ;;
- 4) uninstallMtg
- ;;
- 9) break
- ;;
- 0) exit 0
- ;;
- *)
- echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
-
+ yellow "安装完成!"
+}
+
+startMtg() {
+ cd ${installpath}/serv00-play
+
+ if [ ! -e "dmtg" ]; then
+ ehco "未安装mtproto,请先行安装配置!"
+ return 1
+ fi
+ cd dmtg
+ config="config.json"
+ if [ ! -e $config ]; then
+ red "未安装mtproto,请先行安装配置!"
+ return 1
+ fi
+
+ if checkMtgAlive; then
+ echo "已在运行,请勿重复启动"
+ return 0
+ fi
+
+ read -p "是否需要日志?: [y/n] [n]:" input
+ input=${input:-n}
+
+ if [ "$input" == "y" ]; then
+ green "日志文件名称为:mtg.log"
+ logfile="-d >mtg.log"
+ else
+ logfile=" >/dev/null "
+ fi
+
+ host="$(hostname | cut -d '.' -f 1)"
+
+ secret=$(jq -r ".secret" $config)
+ port=$(jq -r ".port" $config)
+
+ cmd="nohup ./mtg simple-run -n 1.1.1.1 -t 30s -a 1MB 0.0.0.0:${port} ${secret} -c 8192 --prefer-ip=\"prefer-ipv6\" ${logfile} 2>&1 &"
+ eval "$cmd"
+ sleep 3
+ if checkMtgAlive; then
+ mtproto="https://t.me/proxy?server=${host}.$(getDoMain)&port=${port}&secret=${secret}"
+ echo "$mtproto"
+ green "启动成功"
+ else
+ echo "启动失败,请检查进程"
+ fi
+
+}
+
+stopMtg() {
+ r=$(ps aux | grep mtg | grep -v "grep" | awk '{print $2}')
+ if [ -z "$r" ]; then
+ echo "没有运行!"
+ return
+ else
+ kill -9 $r
+ fi
+ echo "已停掉mtproto!"
+
+}
+
+mtprotoServ() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ cd ${installpath}/serv00-play
+
+ if [ ! -e "dmtg" ]; then
+ mkdir -p dmtg
+ fi
+ cd dmtg
+
+ while true; do
+ yellow "---------------------"
+ echo "服务状态: $(checkProcStatus mtg)"
+ echo "mtproto管理:"
+ echo "1. 安装"
+ echo "2. 启动"
+ echo "3. 停止"
+ echo "4. 卸载"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ installMtg
+ ;;
+ 2)
+ startMtg
+ ;;
+ 3)
+ stopMtg
+ ;;
+ 4)
+ uninstallMtg
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+
}
extract_user_and_password() {
- output=$1
+ output=$1
- username=$(echo "$output" | grep "username:" | sed 's/.*username: //')
- password=$(echo "$output" | grep "password:" | sed 's/.*password: //')
- echo "生成用户密码如下,请谨记! 只会出现一次:"
- green "Username: $username"
- green "Password: $password"
+ username=$(echo "$output" | grep "username:" | sed 's/.*username: //')
+ password=$(echo "$output" | grep "password:" | sed 's/.*password: //')
+ echo "生成用户密码如下,请谨记! 只会出现一次:"
+ green "Username: $username"
+ green "Password: $password"
}
update_http_port() {
- cd data || return 1
- local port=$1
- local config_file="config.json"
-
- if [ -z "$port" ]; then
- echo "Error: No port number provided."
- return 1
- fi
- # 使用 jq 来更新配置文件中的 http_port
- jq --argjson new_port "$port" '.scheme.http_port = $new_port' "$config_file" > tmp.$$.json && mv tmp.$$.json "$config_file"
-
- echo "配置文件处理完毕."
-
-}
-
-
-installAlist(){
- if ! checkInstalled "serv00-play"; then
- return 1
- fi
- cd ${installpath}/serv00-play/ || return 1
- alistpath="${installpath}/serv00-play/alist"
-
- if [[ ! -e "$alistpath" ]]; then
- mkdir -p $alistpath
- fi
- if [[ -d "$alistpath/data" && -e "$alistpath/alist" ]]; then
- echo "已安装,请勿重复安装。"
- return
- else
- cd "alist" || return 1
- if [ ! -e "alist" ]; then
- # read -p "请输入使用密码:" password
- if ! checkDownload "alist"; then
- return 1
- fi
- fi
- fi
-
- loadPort
- randomPort tcp alist
- if [[ -n "$port" ]]; then
- alist_port="$port"
- fi
- echo "正在安装alist,请等待..."
- domain=""
- webIp=""
- if ! makeWWW alist $alist_port ; then
- echo "绑定域名失败!"
- return 1
- fi
- if ! applyLE $domain $webIp; then
- echo "申请证书失败!"
- return 1
- fi
- cd $alistpath
- rt=$(chmod +x ./alist && ./alist admin random 2>&1 )
- extract_user_and_password "$rt"
- update_http_port "$alist_port"
-
- green "安装完毕"
-
-}
-
-startAlist(){
- alistpath="${installpath}/serv00-play/alist"
- cd $alistpath
- domain=$(jq -r ".domain" config.json)
-
- if [[ -d "$alistpath/data" && -e "$alistpath/alist" ]]; then
- cd $alistpath
- echo "正在启动alist..."
- if checkProcAlive alist; then
- echo "alist已启动,请勿重复启动!"
- else
- nohup ./alist server > /dev/null 2>&1 &
- sleep 3
- if ! checkProcAlive alist; then
- red "启动失败,请检查!"
- return 1
- else
- green "启动成功!"
- green "alist管理地址: https://$domain"
- fi
- fi
- else
- red "请先行安装再启动!"
- return
- fi
-}
-
-stopAlist(){
- if checkProcAlive "alist"; then
- stopProc "alist"
- sleep 3
- fi
-
+ cd data || return 1
+ local port=$1
+ local config_file="config.json"
+
+ if [ -z "$port" ]; then
+ echo "Error: No port number provided."
+ return 1
+ fi
+ # 使用 jq 来更新配置文件中的 http_port
+ jq --argjson new_port "$port" '.scheme.http_port = $new_port' "$config_file" >tmp.$$.json && mv tmp.$$.json "$config_file"
+
+ echo "配置文件处理完毕."
+
+}
+
+installAlist() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ cd ${installpath}/serv00-play/ || return 1
+ alistpath="${installpath}/serv00-play/alist"
+
+ if [[ ! -e "$alistpath" ]]; then
+ mkdir -p $alistpath
+ fi
+ if [[ -d "$alistpath/data" && -e "$alistpath/alist" ]]; then
+ echo "已安装,请勿重复安装。"
+ return
+ else
+ cd "alist" || return 1
+ if [ ! -e "alist" ]; then
+ if ! download_from_net "alist"; then
+ return 1
+ fi
+ fi
+ fi
+
+ loadPort
+ randomPort tcp alist
+ if [[ -n "$port" ]]; then
+ alist_port="$port"
+ fi
+ echo "正在安装alist,请等待..."
+ domain=""
+ webIp=""
+ if ! makeWWW alist $alist_port; then
+ echo "绑定域名失败!"
+ return 1
+ fi
+ if ! applyLE $domain $webIp; then
+ echo "申请证书失败!"
+ return 1
+ fi
+ cd $alistpath
+ rt=$(chmod +x ./alist && ./alist admin random 2>&1)
+ extract_user_and_password "$rt"
+ update_http_port "$alist_port"
+
+ green "安装完毕"
+
+}
+
+startAlist() {
+ alistpath="${installpath}/serv00-play/alist"
+ cd $alistpath
+ domain=$(jq -r ".domain" config.json)
+
+ if [[ -d "$alistpath/data" && -e "$alistpath/alist" ]]; then
+ cd $alistpath
+ echo "正在启动alist..."
+ if checkProcAlive alist; then
+ echo "alist已启动,请勿重复启动!"
+ else
+ nohup ./alist server >/dev/null 2>&1 &
+ sleep 3
+ if ! checkProcAlive alist; then
+ red "启动失败,请检查!"
+ return 1
+ else
+ green "启动成功!"
+ green "alist管理地址: https://$domain"
+ fi
+ fi
+ else
+ red "请先行安装再启动!"
+ return
+ fi
+}
+
+stopAlist() {
+ if checkProcAlive "alist"; then
+ stopProc "alist"
+ sleep 3
+ fi
+
}
# uninstallPHP(){
@@ -1447,302 +2219,375 @@ stopAlist(){
# yellow "已删除域名 $domain 的相关服务!"
# }
-uninstallProc(){
- local path=$1
- local procname=$2
-
- if [ ! -e "$path" ]; then
- red "未安装$procname!!!"
- return 1
- fi
- cd $path
- read -p "确定卸载${procname}吗? [y/n] [n]:" input
- input=${input:-n}
- if [[ "$input" == "y" ]]; then
- stopProc "$procname"
- domain=$(jq -r ".domain" config.json)
- webip=$(jq -r ".webip" config.json)
- resp=$(devil ssl www del $webIp $domain)
- resp=$(devil www del $domain --remove)
- cd ${installpath}/serv00-play
- rm -rf $path
- green "卸载完毕!"
- fi
-
-}
-
-uninstallAlist(){
- alistpath="${installpath}/serv00-play/alist"
- uninstallProc "$alistpath" alist
-
-}
-
-resetAdminPass(){
- alistpath="${installpath}/serv00-play/alist"
- cd $alistpath
-
- output=$(./alist admin random 2>&1)
- extract_user_and_password "$output"
-}
-
-alistServ(){
- if ! checkInstalled "serv00-play"; then
- return 1
- fi
- while true; do
- yellow "----------------------"
- echo "alist:"
- echo "服务状态: $(checkProcStatus alist)"
- echo "1. 安装部署alist "
- echo "2. 启动alist"
- echo "3. 停掉alist"
- echo "4. 重置admin密码"
- echo "8. 卸载alist"
- echo "9. 返回主菜单"
- echo "0. 退出脚本"
- yellow "----------------------"
- read -p "请选择:" input
-
- case $input in
- 1) installAlist
- ;;
- 2) startAlist
- ;;
- 3) stopAlist
- ;;
- 4) resetAdminPass
- ;;
- 8) uninstallAlist
- ;;
- 9) break
- ;;
- 0) exit 0
- ;;
- *)
- echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
+uninstallProc() {
+ local path=$1
+ local procname=$2
+
+ if [ ! -e "$path" ]; then
+ red "未安装$procname!!!"
+ return 1
+ fi
+ cd $path
+ read -p "确定卸载${procname}吗? [y/n] [n]:" input
+ input=${input:-n}
+ if [[ "$input" == "y" ]]; then
+ stopProc "$procname"
+ domain=$(jq -r ".domain" config.json)
+ webip=$(jq -r ".webip" config.json)
+ resp=$(devil ssl www del $webIp $domain)
+ resp=$(devil www del $domain --remove)
+ cd ${installpath}/serv00-play
+ rm -rf $path
+ green "卸载完毕!"
+ fi
+
}
-declare -a indexPorts
-loadIndexPorts(){
- output=$(devil port list)
+uninstallAlist() {
+ alistpath="${installpath}/serv00-play/alist"
+ uninstallProc "$alistpath" alist
- indexPorts=()
- # 解析输出内容
- index=0
- while read -r port typ opis; do
- # 跳过标题行
- if [[ "$port" =~ "Port" ]]; then
- continue
- fi
- #echo "port:$port,typ:$typ, opis:$opis"
- if [[ "$port" =~ "Brak" || "$port" =~ "No" ]]; then
- echo "未分配端口"
- return 0
- fi
+}
- if [[ -n "$port" ]]; then
- opis=${opis:-""}
- indexPorts[$index]="$port|$typ|$opis"
- ((index++))
- fi
- done <<< "$output"
+resetAdminPass() {
+ alistpath="${installpath}/serv00-play/alist"
+ cd $alistpath
+
+ output=$(./alist admin random 2>&1)
+ extract_user_and_password "$output"
+}
+updateAlist() {
+ cd ${installpath}/serv00-play/alist || (echo "未安装alist" && return)
+
+ if ! check_update_from_net "alist"; then
+ return 1
+ fi
+
+ stopAlist
+ download_from_net "alist"
+ chmod +x ./alist
+ startAlist
+ echo "更新完毕!"
+}
+
+alistServ() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "----------------------"
+ echo "alist:"
+ echo "服务状态: $(checkProcStatus alist)"
+ echo "1. 安装部署"
+ echo "2. 启动"
+ echo "3. 停掉"
+ echo "4. 重置admin密码"
+ echo "5. 更新"
+ echo "8. 卸载"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "----------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ installAlist
+ ;;
+ 2)
+ startAlist
+ ;;
+ 3)
+ stopAlist
+ ;;
+ 4)
+ resetAdminPass
+ ;;
+ 5)
+ updateAlist
+ ;;
+ 8)
+ uninstallAlist
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+declare -a indexPorts
+loadIndexPorts() {
+ output=$(devil port list)
+
+ indexPorts=()
+ # 解析输出内容
+ index=0
+ while read -r port typ opis; do
+ # 跳过标题行
+ if [[ "$port" =~ "Port" ]]; then
+ continue
+ fi
+ #echo "port:$port,typ:$typ, opis:$opis"
+ if [[ "$port" =~ "Brak" || "$port" =~ "No" ]]; then
+ echo "未分配端口"
+ return 0
+ fi
+
+ if [[ -n "$port" ]]; then
+ opis=${opis:-""}
+ indexPorts[$index]="$port|$typ|$opis"
+ ((index++))
+ fi
+ done <<<"$output"
}
printIndexPorts() {
- local i=1
- echo " Port | Type | Description"
- for entry in "${indexPorts[@]}"; do
- # 使用 | 作为分隔符拆分 port、typ 和 opis
-
- IFS='|' read -r port typ opis <<< "$entry"
- echo "${i}. $port | $typ | $opis"
- ((i++))
- done
-}
-
-
-delPortMenu(){
- loadIndexPorts
-
- if [[ ${#indexPorts[@]} -gt 0 ]]; then
- printIndexPorts
- read -p "请选择要删除的端口记录编号(输入0删除所有端口记录, 回车返回):" number
- number=${number:-99}
-
- if [[ $number -eq 99 ]]; then
- return
- elif [[ $number -gt 3 || $number -lt 0 ]]; then
- echo "非法输入!"
- return
- elif [[ $number -eq 0 ]]; then
- cleanPort
- else
- idx=$((number-1))
- IFS='|' read -r port typ opis <<< ${indexPorts[$idx]}
- devil port del $typ $port > /dev/null 2>&1
- fi
- echo "删除完毕!"
- else
- red "未有分配任何端口!"
- fi
-
-}
-
-addPortMenu(){
- echo "选择端口类型:"
- echo "1. tcp"
- echo "2. udp"
- read -p "请选择:" co
-
- if [[ "$co" != "1" && "$co" != "2" ]]; then
- red "非法输入"
- return
- fi
- local type=""
- if [[ "$co" == "1" ]]; then
- type="tcp"
- else
- type="udp"
- fi
- loadPort
- read -p "请输入端口备注(如hy2,vmess,用于脚本自动获取端口):" opts
- local port=$(getPort $type $opts )
- if [[ "$port" == "failed" ]]; then
- red "分配端口失败,请重新操作!"
- else
- green "分配出来的端口是:$port"
- fi
-}
-
-portServ(){
- while true; do
- yellow "----------------------"
- echo "端口管理:"
- echo "1. 删除某条端口记录"
- echo "2. 增加一条端口记录"
- echo "9. 返回主菜单"
- echo "0. 退出脚本"
- yellow "----------------------"
- read -p "请选择:" input
- case $input in
- 1) delPortMenu
- ;;
- 2) addPortMenu
- ;;
- 9)
- break
- ;;
- 0)
- exit 0
- ;;
- *)
- echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
-}
-
-cronLE(){
- read -p "请输入定时运行的时间间隔(小时[1-23]):" tm
- tm=${tm:-""}
- if [[ -z "$tm" ]]; then
- red "时间不能为空"
- return 1
- fi
- if [[ $tm -lt 1 || $tm -gt 23 ]]; then
- red "输入非法!"
- return 1
- fi
- crontab -l > le.cron
- echo "0 */$tm * * * $workpath/cronSSL.sh $domain > /dev/null 2>&1 " >> le.cron
- crontab le.cron > /dev/null 2>&1
- rm -rf le.cron
- echo "设置完毕!"
-}
-
-get_default_webip(){
- local host="$(hostname | cut -d '.' -f 1)"
- local sno=${host/s/web}
- local webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
- echo "$webIp"
-}
-
-applyLE(){
- local domain=$1
- local webIp=$2
- workpath="${installpath}/serv00-play/ssl"
- cd "$workpath"
-
- if [[ -z "$domain" ]]; then
- read -p "请输入待申请证书的域名:" domain
- domain=${domain:-""}
- if [[ -z "$domain" ]]; then
- red "域名不能为空"
- return 1
- fi
- fi
- inCron="0"
- if crontab -l | grep -F "$domain" > /dev/null 2>&1 ; then
- inCron="1"
- echo "该域名已配置定时申请证书,是否删除定时配置记录,改为手动申请?[y/n] [n]:" input
- input=${input:-n}
-
- if [[ "$input" == "y" ]]; then
- crontab -l | grep -v "$domain" | crontab -
- fi
- fi
- if [[ -z "$webIp" ]]; then
- read -p "是否指定webip? [y/n] [n]:" input
- input=${input:-n}
- if [[ "$input" == "y" ]]; then
- read -p "请输入webip:" webIp
- if [[ -z "webIp" ]]; then
- red "webip 不能为空!!!"
- return 1
- fi
- else
- host="$(hostname | cut -d '.' -f 1)"
- sno=${host/s/web}
- webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
- fi
- fi
- #echo "申请证书时,webip是: $webIp"
- resp=$(devil ssl www add $webIp le le $domain)
- if [[ ! "$resp" =~ .*succesfully.*$ ]]; then
- red "申请ssl证书失败!$resp"
- if [[ "$inCron" == "0" ]]; then
- read -p "是否配置定时任务自动申请SSL证书? [y/n] [n]:" input
- input=${input:-n}
- if [[ "$input" == "y" ]]; then
- cronLE
- fi
- fi
- else
- green "证书申请成功!"
- fi
-}
-
-selfSSL(){
- workpath="${installpath}/serv00-play/ssl"
- cd "$workpath"
-
- read -p "请输入待申请证书的域名:" self_domain
- self_domain=${self_domain:-""}
- if [[ -z "$self_domain" ]]; then
- red "域名不能为空"
- return 1
- fi
-
- echo "正在生成证书..."
-
- cat > openssl.cnf </dev/null 2>&1
+ fi
+ echo "删除完毕!"
+ else
+ red "未有分配任何端口!"
+ fi
+
+}
+
+addPortMenu() {
+ echo "选择端口类型:"
+ echo "1. tcp"
+ echo "2. udp"
+ read -p "请选择:" co
+
+ if [[ "$co" != "1" && "$co" != "2" ]]; then
+ red "非法输入"
+ return
+ fi
+ local type=""
+ if [[ "$co" == "1" ]]; then
+ type="tcp"
+ else
+ type="udp"
+ fi
+ loadPort
+ read -p "请输入端口备注(如hy2,vmess,用于脚本自动获取端口):" opts
+ read -p "是否自动分配端口? [y/n] [y]:" input
+ input=${input:-y}
+ if [[ "$input" == "y" ]]; then
+ port=$(getPort $type $opts)
+ if [[ "$port" == "failed" ]]; then
+ red "分配端口失败,请重新操作!"
+ else
+ green "分配出来的端口是:$port"
+ fi
+ else
+ read -p "请输入端口号:" port
+ if [[ -z "$port" ]]; then
+ red "端口不能为空"
+ return 1
+ fi
+ resp=$(devil port add $type $port $opts)
+ if [[ "$resp" =~ .*succesfully.*$ || "$resp" =~ .*Ok.*$ ]]; then
+ green "添加端口成功!"
+ else
+ red "添加端口失败!"
+ fi
+ fi
+
+}
+
+portServ() {
+ while true; do
+ yellow "----------------------"
+ echo "端口管理:"
+ echo "1. 删除某条端口记录"
+ echo "2. 增加一条端口记录"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "----------------------"
+ read -p "请选择:" input
+ case $input in
+ 1)
+ delPortMenu
+ ;;
+ 2)
+ addPortMenu
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+cronLE() {
+ local l_domain=$1
+ local nointeraction=$2
+ if [[ -n "$nointeraction" ]]; then
+ tm=1
+ else
+ read -p "请输入定时运行的时间间隔(小时[1-23]):" tm
+ tm=${tm:-""}
+ if [[ -z "$tm" ]]; then
+ red "时间不能为空"
+ return 1
+ fi
+ if [[ $tm -lt 1 || $tm -gt 23 ]]; then
+ red "输入非法!"
+ return 1
+ fi
+ fi
+ crontab -l >le.cron
+ # 生成0-59的随机数
+ local mm=$((RANDOM % 60))
+ if [[ $tm -eq 1 ]]; then
+ #每小时执行一次
+ echo "$mm * * * * bash $workpath/cronSSL.sh $l_domain > /dev/null 2>&1 " >>le.cron
+ else
+ #每tm小时执行一次
+ echo "$mm */$tm * * * bash $workpath/cronSSL.sh $l_domain > /dev/null 2>&1 " >>le.cron
+ fi
+ crontab le.cron >/dev/null 2>&1
+ rm -rf le.cron
+ echo "设置完毕!"
+}
+
+get_default_webip() {
+ local host="$(hostname | cut -d '.' -f 1)"
+ local sno=${host/s/web}
+ local webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
+ echo "$webIp"
+}
+
+applyLE() {
+ local l_domain=$1
+ local l_webip=$2
+ local nointeraction=$3
+ workpath="${installpath}/serv00-play/ssl"
+ cd "$workpath"
+
+ #echo "domain=$l_domain, webip=$l_webip, nointeraction=$nointeraction"
+ if [[ -z "$l_domain" ]]; then
+ read -p "请输入待申请证书的域名:" l_domain
+ l_domain=${l_domain:-""}
+ if [[ -z "$l_domain" ]]; then
+ red "域名不能为空"
+ return 1
+ fi
+ fi
+ local inCron="0"
+ if crontab -l | grep -F "$l_domain" >/dev/null 2>&1; then
+ inCron="1"
+ if [[ -z "$nointeraction" ]]; then
+ echo "该域名已配置定时申请证书,是否删除定时配置记录,改为手动申请?[y/n] [n]:" input
+ input=${input:-n}
+
+ if [[ "$input" == "y" ]]; then
+ crontab -l | grep -v "$l_domain" | crontab -
+ fi
+ else
+ crontab -l | grep -v "$l_domain" | crontab -
+ fi
+ fi
+ if [[ -z "$l_webip" ]]; then
+ read -p "是否指定webip? [y/n] [n]:" input
+ input=${input:-n}
+
+ if [[ "$input" == "y" ]]; then
+ read -p "请输入webIp:" l_webip
+ if [[ -z "$l_webip" ]]; then
+ red "webIp 不能为空!!!"
+ return 1
+ fi
+ else
+ host="$(hostname | cut -d '.' -f 1)"
+ sno=${host/s/web}
+ l_webip=$(devil vhost list public | grep "$sno" | awk '{print $1}')
+ fi
+ fi
+ #echo "申请证书时,webip是: $l_webip"
+ resp=$(devil ssl www add $l_webip le le $l_domain)
+ if [[ ! "$resp" =~ .*succesfully.*$ ]]; then
+ red "申请ssl证书失败!$resp"
+ #echo "inCron: $inCron"
+ if [[ "$inCron" == "0" ]]; then
+ if [[ -z "$nointeraction" ]]; then
+ read -p "是否配置定时任务自动申请SSL证书? [y/n] [n]:" input
+ input=${input:-n}
+ else
+ input="y"
+ fi
+ if [[ "$input" == "y" ]]; then
+ if [[ -z "$nointeraction" ]]; then
+ cronLE $l_domain
+ else
+ cronLE $l_domain $nointeraction
+ fi
+ fi
+ fi
+ else
+ green "证书申请成功!"
+ fi
+ cd -
+}
+
+selfSSL() {
+ workpath="${installpath}/serv00-play/ssl"
+ cd "$workpath"
+
+ read -p "请输入待申请证书的域名:" self_domain
+ self_domain=${self_domain:-""}
+ if [[ -z "$self_domain" ]]; then
+ red "域名不能为空"
+ return 1
+ fi
+
+ echo "正在生成证书..."
+
+ cat >openssl.cnf < /dev/null 2>&1
- if [ $? -ne 0 ]; then
- echo "生成证书失败!"
- return 1
- fi
-
- echo "已生成证书:"
- green "_private.key"
- green "_cert.crt"
-
- echo "正在导入证书.."
- host="$(hostname | cut -d '.' -f 1)"
- sno=${host/s/web}
- webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
- resp=$(devil ssl www add "$webIp" ./_cert.crt ./_private.key "$self_domain" )
-
- if [[ ! "$resp" =~ .*succesfully.*$ ]]; then
- echo "导入证书失败:$resp"
- return 1
- fi
-
- echo "导入成功!"
-
-}
-
-domainSSLServ(){
- while true; do
- yellow "---------------------"
- echo "域名证书管理:"
- echo "1. 抢域名证书"
- echo "2. 配置自签证书"
- echo "9. 返回主菜单"
- echo "0. 退出脚本"
- yellow "---------------------"
- read -p "请选择:" input
-
- case $input in
- 1) applyLE
- ;;
- 2) selfSSL
- ;;
- 9) break
- ;;
- 0)
- exit 0
- ;;
- *)
- echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
-}
-
-installRoot(){
- workpath="${installpath}/serv00-play/root"
- if [[ ! -e $workpath ]]; then
- mkdir -p "$workpath"
- fi
-
- if [[ -e "$workpath/MrChrootBSD/mrchroot" ]]; then
- echo "检测到已经安装mrchroot,请勿重复安装!"
- return
- fi
- echo "正在安装..."
- cd $workpath
- git clone https://github.com/nrootconauto/MrChrootBSD.git
- cd MrChrootBSD
- wget https://download.freebsd.org/releases/amd64/14.1-RELEASE/base.txz
- wget https://download.freebsd.org/releases/amd64/14.1-RELEASE/lib32.txz #Needed for gdb for some reason
- mkdir chroot
- cd chroot
- tar xvf ../base.txz
- tar xvf ../lib32.txz
- cd ..
- cmake .
- make
- cp /etc/resolv.conf chroot/etc
- if screen -S rootsession -dm ./mrchroot chroot /bin/sh; then
- echo "安装成功!"
- else
- echo "安装失败!"
- fi
-
-}
-
-enterRoot(){
- workpath="${installpath}/serv00-play/root/MrChrootBSD"
- if [[ ! -e "$workpath/mrchroot" ]]; then
- red "未安装mrchroot,请先行安装!"
- return
- fi
-
- SESSION_NAME="rootsession"
- if screen -list | grep -q "\.$SESSION_NAME"; then
- echo "进入root..."
- screen -r "$SESSION_NAME"
- else
- echo "未发现root进程,尝试创建井进入root..."
- cd $workpath
- if screen -S $SESSION_NAME -dm ./mrchroot chroot /bin/sh; then
- echo "创建成功!"
- screen -r "$SESSION_NAME"
- else
- echo "创建失败!"
- fi
-
- fi
-}
-
-uninstallRoot(){
- SESSION_NAME="rootsession"
-
- if [[ ! -e "${installpath}/serv00-play/root" ]]; then
- echo "未安装root,无需卸载!"
- return
- fi
-
- read -p "确定卸载root吗?[y/n] [n]:" input
- input=${input:-n}
-
- if [[ "$input" == "y" ]]; then
-
- if screen -list | grep -q "\.${SESSION_NAME}"; then
- screen -S "$SESSION_NAME" -X quit
- fi
-
- workpath="${installpath}/serv00-play/"
- cd $workpath
- rm -rf ./root
- fi
-
- green "卸载完毕!"
-}
-
-rootServ(){
- while true; do
- yellow "---------------------"
- echo "一键root:"
- echo "1. 安装root"
- echo "2. 进入root"
- echo "3. 卸载root"
- echo "9. 返回主菜单"
- echo "0. 退出脚本"
- yellow "---------------------"
- read -p "请选择:" input
-
- case $input in
- 1) installRoot
- ;;
- 2) enterRoot
- ;;
- 3) uninstallRoot
- ;;
- 9) break
- ;;
- 0) exit 0
- ;;
- *) echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
-}
-
-getUnblockIP(){
- local hostname=$(hostname)
- local host_number=$(echo "$hostname" | awk -F'[s.]' '{print $2}')
- local hosts=("cache${host_number}.serv00.com" "web${host_number}.serv00.com" "$hostname")
-
- yellow "----------------------------------------------"
- green " 主机名称 | IP | 状态"
- yellow "----------------------------------------------"
- # 遍历主机名称数组
- for host in "${hosts[@]}"; do
- # 获取 API 返回的数据
- local response=$(curl -s "https://ss.botai.us.kg/api/getip?host=$host")
-
- # 检查返回的结果是否包含 "not found"
- if [[ "$response" =~ "not found" ]]; then
- echo "未识别主机${host}, 请联系作者饭奇骏!"
- return
- fi
- local ip=$(echo "$response" | awk -F "|" '{print $1 }')
- local status=$(echo "$response" | awk -F "|" '{print $2 }')
- printf "%-20s | %-15s | %-10s\n" "$host" "$ip" "$status"
- done
-
-}
-
-checkProcStatus(){
- local procname=$1
- if checkProcAlive $procname ; then
- green "运行"
- else
- red "未运行"
- fi
-
-}
-
-sunPanelServ(){
- if ! checkInstalled "serv00-play"; then
- return 1
- fi
- while true; do
- yellow "---------------------"
- echo "sun-panel:"
- echo "服务状态: $(checkProcStatus sun-panel)"
- echo "1. 安装"
- echo "2. 启动"
- echo "3. 停止"
- echo "4. 初始化密码"
- echo "8. 卸载"
- echo "9. 返回主菜单"
- echo "0. 退出脚本"
- yellow "---------------------"
- read -p "请选择:" input
-
- case $input in
- 1) installSunPanel
- ;;
- 2) startSunPanel
- ;;
- 3) stopSunPanel
- ;;
- 4) resetSunPanelPwd
- ;;
- 8) uninstallSunPanel
- ;;
- 9) break
- ;;
- 0) exit 0
- ;;
- *) echo "无效选项,请重试"
- ;;
- esac
- done
- showMenu
-}
-
-uninstallSunPanel(){
- local workdir="${installpath}/serv00-play/sunpanel"
- uninstallProc "$workdir" "sun-panel"
-}
-
-resetSunPanelPwd(){
- local exepath="${installpath}/serv00-play/sunpanel/sun-panel"
- if [[ ! -e $exepath ]]; then
- echo "未安装,请先安装!"
- return
- fi
- read -p "确定初始化密码? [y/n][n]:" input
- input=${input:-n}
-
- if [[ "$input" == "y" ]]; then
- local workdir="${installpath}/serv00-play/sunpanel"
- cd $workdir
- ./sun-panel -password-reset
- fi
-
-}
-
-stopSunPanel(){
- stopProc "sun-panel"
- if checkProcAlive "sun-panel"; then
- echo "未能停止,请手动杀进程!"
- fi
-
-}
-
-installSunPanel(){
- local workdir="${installpath}/serv00-play/sunpanel"
- local exepath="${installpath}/serv00-play/sunpanel/sun-panel"
- if [[ -e $exepath ]]; then
- echo "已安装,请勿重复安装!"
- return
- fi
- mkdir -p $workdir
- cd $workdir
-
- if ! checkDownload "sun-panel"; then
- return 1
- fi
- if ! checkDownload "panelweb" 1; then
- return 1
- fi
-
- if [[ ! -e "sun-panel" ]]; then
- echo "下载文件解压失败!"
- return 1
- fi
- #初始化密码,并且生成相关目录文件
- ./sun-panel -password-reset
-
- if [[ ! -e "conf/conf.ini" ]]; then
- echo "无配置文件生成!"
- return 1
- fi
-
- loadPort
- port=""
- randomPort "tcp" "sun-panel"
- if [ -n "$port" ]; then
- sunPanelPort=$port
- else
- echo "未输入端口!"
- return 1
- fi
- cd conf
- sed -i.bak -E "s/^http_port=[0-9]+$/http_port=${sunPanelPort}/" conf.ini
- cd ..
-
- domain=""
- webIp=""
- if ! makeWWW panel $sunPanelPort ; then
- echo "绑定域名失败!"
- return 1
- fi
- # 自定义域名时申请证书的webip可以从2个ip中选择
- if [ $is_self_domain -eq 1 ]; then
- if ! applyLE $domain $webIp; then
- echo "申请证书失败!"
- return 1
- fi
- else # 没有自定义域名时,webip是内置固定的,就是web(x).serv00.com
- if ! applyLE $domain ; then
- echo "申请证书失败!"
- return 1
- fi
- fi
- green "安装完毕!"
-
-}
-
-makeWWW(){
- local proc=$1
- local port=$2
- local www_type=${3:-"proxy"}
-
- echo "正在处理服务IP,请等待..."
- is_self_domain=0
- webIp=$(get_webip)
- default_webip=$(get_default_webip)
- green "可用webip是: $webIp, 默认webip是: $default_webip"
- read -p "是否使用自定义域名? [y/n] [n]:" input
- input=${input:-n}
- if [[ "$input" == "y" ]]; then
- is_self_domain=1
- read -p "请输入域名(确保此前域名已指向webip):" domain
- else
- user="$(whoami)"
- if isServ00 ; then
- domain="${proc}.$user.serv00.net"
- else
- domain="$proc.$user.ct8.pl"
- fi
- fi
-
- if [[ -z "$domain" ]]; then
- red "输入无效域名!"
- return 1
- fi
-
- domain=${domain,,}
- echo "正在绑定域名,请等待..."
- if [[ "$www_type" == "proxy" ]]; then
- resp=$(devil www add $domain proxy localhost $port)
- else
- resp=$(devil www add $domain php)
- fi
- #echo "resp:$resp"
- if [[ ! "$resp" =~ .*succesfully.*$ && ! "$resp" =~ .*Ok.*$ ]]; then
- if [[ ! "$resp" =~ "This domain already exists" ]]; then
- red "申请域名$domain 失败!"
- return 1
- fi
- fi
-
- # 自定义域名的特殊处理
- if [[ $is_self_domain -eq 1 ]]; then
- host="$(hostname | cut -d '.' -f 1)"
- sno=${host/s/web}
- default_webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
- rid=$(devil dns list "$domain" | grep "$default_webIp" | awk '{print $1}')
- resp=$(echo "y" | devil dns del "$domain" $rid)
- #echo "resp:$resp"
- else
- webIp=$(get_default_webip)
- fi
- # 保存信息
- if [[ "$www_type" == "proxy" ]]; then
- cat > config.json </dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "生成证书失败!"
+ return 1
+ fi
+
+ echo "已生成证书:"
+ green "_private.key"
+ green "_cert.crt"
+
+ echo "正在导入证书.."
+ host="$(hostname | cut -d '.' -f 1)"
+ sno=${host/s/web}
+ webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
+ resp=$(devil ssl www add "$webIp" ./_cert.crt ./_private.key "$self_domain")
+
+ if [[ ! "$resp" =~ .*succesfully.*$ ]]; then
+ echo "导入证书失败:$resp"
+ return 1
+ fi
+
+ echo "导入成功!"
+ cd -
+}
+
+domainSSLServ() {
+ while true; do
+ yellow "---------------------"
+ echo "域名证书管理:"
+ echo "1. 抢域名证书"
+ echo "2. 配置自签证书"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ applyLE
+ ;;
+ 2)
+ selfSSL
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+installRoot() {
+ workpath="${installpath}/serv00-play/root"
+ if [[ ! -e $workpath ]]; then
+ mkdir -p "$workpath"
+ fi
+
+ if [[ -e "$workpath/MrChrootBSD/mrchroot" ]]; then
+ echo "检测到已经安装mrchroot,请勿重复安装!"
+ return
+ fi
+ echo "正在安装..."
+ cd $workpath
+ git clone https://github.com/nrootconauto/MrChrootBSD.git
+ cd MrChrootBSD
+ wget https://download.freebsd.org/releases/amd64/14.1-RELEASE/base.txz
+ wget https://download.freebsd.org/releases/amd64/14.1-RELEASE/lib32.txz #Needed for gdb for some reason
+ mkdir chroot
+ cd chroot
+ tar xvf ../base.txz
+ tar xvf ../lib32.txz
+ cd ..
+ cmake .
+ make
+ cp /etc/resolv.conf chroot/etc
+ if screen -S rootsession -dm ./mrchroot chroot /bin/sh; then
+ echo "安装成功!"
+ else
+ echo "安装失败!"
+ fi
+
+}
+
+enterRoot() {
+ workpath="${installpath}/serv00-play/root/MrChrootBSD"
+ if [[ ! -e "$workpath/mrchroot" ]]; then
+ red "未安装mrchroot,请先行安装!"
+ return
+ fi
+
+ SESSION_NAME="rootsession"
+ if screen -list | grep -q "\.$SESSION_NAME"; then
+ echo "进入root..."
+ screen -r "$SESSION_NAME"
+ else
+ echo "未发现root进程,尝试创建井进入root..."
+ cd $workpath
+ if screen -S $SESSION_NAME -dm ./mrchroot chroot /bin/sh; then
+ echo "创建成功!"
+ screen -r "$SESSION_NAME"
+ else
+ echo "创建失败!"
+ fi
+
+ fi
+}
+
+uninstallRoot() {
+ SESSION_NAME="rootsession"
+
+ if [[ ! -e "${installpath}/serv00-play/root" ]]; then
+ echo "未安装root,无需卸载!"
+ return
+ fi
+
+ read -p "确定卸载root吗?[y/n] [n]:" input
+ input=${input:-n}
+
+ if [[ "$input" == "y" ]]; then
+
+ if screen -list | grep -q "\.${SESSION_NAME}"; then
+ screen -S "$SESSION_NAME" -X quit
+ fi
+
+ workpath="${installpath}/serv00-play/"
+ cd $workpath
+ rm -rf ./root
+ fi
+
+ green "卸载完毕!"
+}
+
+rootServ() {
+ while true; do
+ yellow "---------------------"
+ echo "一键root:"
+ echo "1. 安装root"
+ echo "2. 进入root"
+ echo "3. 卸载root"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ installRoot
+ ;;
+ 2)
+ enterRoot
+ ;;
+ 3)
+ uninstallRoot
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+showIPStatus() {
+ yellow "----------------------------------------------"
+ green " 主机名称 | IP | 状态"
+ yellow "----------------------------------------------"
+
+ show_ip_status
+}
+
+checkProcStatus() {
+ local procname=$1
+ if checkProcAlive $procname; then
+ green "运行"
+ else
+ red "未运行"
+ fi
+
+}
+
+sunPanelServ() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "---------------------"
+ echo "sun-panel:"
+ echo "服务状态: $(checkProcStatus sun-panel)"
+ echo "1. 安装"
+ echo "2. 启动"
+ echo "3. 停止"
+ echo "4. 初始化密码"
+ echo "5. 导入serv00账号信息(频道会员尊享功能)"
+ echo "8. 卸载"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ installSunPanel
+ ;;
+ 2)
+ startSunPanel
+ ;;
+ 3)
+ stopSunPanel
+ ;;
+ 4)
+ resetSunPanelPwd
+ ;;
+ 5)
+ import_accounts
+ ;;
+ 8)
+ uninstallSunPanel
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+}
+
+import_accounts() {
+ local workdir="${installpath}/serv00-play/sunpanel"
+ if ! vip_statement; then
+ return 1
+ fi
+
+ cd $workdir
+ read -p "请输入会员密码:" passwd
+ if ! checkDownload "importd_panel_accounts.sh" 0 "$passwd" 1; then
+ return 1
+ fi
+
+ chmod +x ./importd_panel_accounts.sh
+
+ ./importd_panel_accounts.sh && rm -rf ./importd_panel_accounts.sh
+
+ if [[ $? -ne 0 ]]; then
+ echo "导入失败!"
+ else
+ echo "导入成功!"
+ fi
+
+}
+
+import_accounts() {
+ local workdir="${installpath}/serv00-play/sunpanel"
+ if ! vip_statement; then
+ return 1
+ fi
+
+ cd $workdir
+ read -s -p "请输入会员密码:" passwd
+ if ! checkDownload "importd_panel_accounts.sh" 0 "$passwd" 1; then
+ return 1
+ fi
+
+ chmod +x ./importd_panel_accounts.sh
+
+ ./importd_panel_accounts.sh && rm -rf ./importd_panel_accounts.sh
+
+ if [[ $? -ne 0 ]]; then
+ echo "导入失败!"
+ else
+ echo "导入成功!"
+ fi
+
+}
+
+uninstallSunPanel() {
+ local workdir="${installpath}/serv00-play/sunpanel"
+ uninstallProc "$workdir" "sun-panel"
+}
+
+resetSunPanelPwd() {
+ local exepath="${installpath}/serv00-play/sunpanel/sun-panel"
+ if [[ ! -e $exepath ]]; then
+ echo "未安装,请先安装!"
+ return
+ fi
+ read -p "确定初始化密码? [y/n][n]:" input
+ input=${input:-n}
+
+ if [[ "$input" == "y" ]]; then
+ local workdir="${installpath}/serv00-play/sunpanel"
+ cd $workdir
+ ./sun-panel -password-reset
+ fi
+
+}
+
+stopSunPanel() {
+ stopProc "sun-panel"
+ if checkProcAlive "sun-panel"; then
+ echo "未能停止,请手动杀进程!"
+ fi
+
+}
+
+installSunPanel() {
+ local workdir="${installpath}/serv00-play/sunpanel"
+ local exepath="${installpath}/serv00-play/sunpanel/sun-panel"
+ if [[ -e $exepath ]]; then
+ echo "已安装,请勿重复安装!"
+ return
+ fi
+ mkdir -p $workdir
+ cd $workdir
+
+ if ! checkDownload "sun-panel"; then
+ return 1
+ fi
+ if ! checkDownload "panelweb" 1; then
+ return 1
+ fi
+
+ if [[ ! -e "sun-panel" ]]; then
+ echo "下载文件解压失败!"
+ return 1
+ fi
+ #初始化密码,并且生成相关目录文件
+ ./sun-panel -password-reset
+
+ if [[ ! -e "conf/conf.ini" ]]; then
+ echo "无配置文件生成!"
+ return 1
+ fi
+
+ loadPort
+ port=""
+ randomPort "tcp" "sun-panel"
+ if [ -n "$port" ]; then
+ sunPanelPort=$port
+ else
+ echo "未输入端口!"
+ return 1
+ fi
+ cd conf
+ sed -i.bak -E "s/^http_port=[0-9]+$/http_port=${sunPanelPort}/" conf.ini
+ cd ..
+
+ domain=""
+ webIp=""
+ if ! makeWWW panel $sunPanelPort; then
+ echo "绑定域名失败!"
+ return 1
+ fi
+ # 自定义域名时申请证书的webip可以从2个ip中选择
+ if [ $is_self_domain -eq 1 ]; then
+ if ! applyLE $domain $webIp; then
+ echo "申请证书失败!"
+ return 1
+ fi
+ else # 没有自定义域名时,webip是内置固定的,就是web(x).serv00.com
+ if ! applyLE $domain; then
+ echo "申请证书失败!"
+ return 1
+ fi
+ fi
+ green "安装完毕!"
+
+}
+
+makeWWW() {
+ local proc=$1
+ local port=$2
+ local www_type=${3:-"proxy"}
+ local input=${4:-""}
+ domain=${5:-"$domain"}
+
+ echo "正在处理服务IP,请等待..."
+ is_self_domain=0
+ webIp=$(get_webip)
+ default_webip=$(get_default_webip)
+ if [[ -z "$webIp" ]]; then
+ webIp=$default_webip
+ fi
+ green "可用webip是: $webIp, 默认webip是: $default_webip"
+ if [[ -z "$domain" ]]; then
+ if [[ -z "$input" ]]; then
+ read -p "是否使用自定义域名? [y/n] [n]:" input
+ input=${input:-n}
+ fi
+ if [[ "$input" == "y" ]]; then
+ is_self_domain=1
+ read -p "请输入域名(确保此前域名已指向webip):" domain
+ else
+ if [[ -z ${proc:""} ]]; then
+ read -p "请输入默认域名的二级域名的前缀(如二级域名 sub.main.com, 则填sub):" proc
+ fi
+ domain=$(getUserDoMain "$proc")
+ fi
+ else
+ is_self_domain=1
+ fi
+
+ if [[ -z "$domain" ]]; then
+ red "输入无效域名!"
+ return 1
+ fi
+
+ domain=${domain,,}
+ echo "正在绑定域名,请等待..."
+ if [[ "$www_type" == "proxy" ]]; then
+ resp=$(devil www add $domain proxy localhost $port)
+ else
+ resp=$(devil www add $domain php)
+ fi
+ #echo "resp:$resp"
+ if [[ ! "$resp" =~ .*succesfully.*$ && ! "$resp" =~ .*Ok.*$ ]]; then
+ if [[ ! "$resp" =~ "This domain already exists" ]]; then
+ red "申请域名$domain 失败!"
+ return 1
+ fi
+ fi
+
+ # 自定义域名的特殊处理
+ # if [[ $is_self_domain -eq 1 ]]; then
+ # host="$(hostname | cut -d '.' -f 1)"
+ # sno=${host/s/web}
+ # default_webIp=$(devil vhost list public | grep "$sno" | awk '{print $1}')
+ # rid=$(devil dns list "$domain" | grep "$default_webIp" | awk '{print $1}')
+ # resp=$(echo "y" | devil dns del "$domain" $rid)
+ # #echo "resp:$resp"
+ # else
+ # webIp=$(get_default_webip)
+ # fi
+ # 保存信息
+ if [[ "$www_type" == "proxy" ]]; then
+ cat >config.json < $configfile <> "$profile"
- source $profile
- fi
- domain=""
- webIp=""
- if ! makeWWW ssh $websshPort ; then
- echo "绑定域名失败!"
- return 1
- fi
- if ! applyLE $domain $webIp; then
- echo "申请证书失败!"
- return 1
- fi
- echo "安装完成!"
-
-}
-
-stopWebSSH(){
- stopProc "wssh"
- sleep 2
- if ! checkProcAlive "wssh"; then
- echo "wssh已停止!"
- else
- echo "未能停止,请手动杀进程!"
- fi
-}
-
-startWebSSH(){
- local workdir="${installpath}/serv00-play/webssh"
- local configfile="$workdir/config.json"
- if [ ! -e "$configfile" ]; then
- echo "未安装,请先安装!"
- return
- fi
- cd $workdir
- read -p "是否需要日志($workdir/running.log)? [y/n] [n]:" input
- input=${input:-n}
- args=""
- if [[ "$input" == "y" ]]; then
- args=" > running.log 2>&1 "
- else
- args=" > /dev/null 2>&1 "
- fi
- port=$(jq -r ".port" $configfile)
- if checkProcAlive "wssh"; then
- stopProc "wssh"
- fi
- echo "正在启动中..."
- cmd="nohup ./wssh --port=$port --fbidhttp=False --xheaders=False --encoding='utf-8' --delay=10 $args &"
- eval "$cmd"
- sleep 2
- if checkProcAlive wssh; then
- green "启动成功!"
- else
- echo "启动失败!"
- fi
-}
-
-nonServ(){
- cat < $configfile <>"$profile"
+ source $profile
+ fi
+ domain=""
+ webIp=""
+ if ! makeWWW ssh $websshPort; then
+ echo "绑定域名失败!"
+ return 1
+ fi
+ if ! applyLE $domain $webIp; then
+ echo "申请证书失败!"
+ return 1
+ fi
+ echo "安装完成!"
+
+}
+
+stopWebSSH() {
+ stopProc "wssh"
+ sleep 2
+ if ! checkProcAlive "wssh"; then
+ echo "wssh已停止!"
+ else
+ echo "未能停止,请手动杀进程!"
+ fi
+}
+
+startWebSSH() {
+ local workdir="${installpath}/serv00-play/webssh"
+ local configfile="$workdir/config.json"
+ if [ ! -e "$configfile" ]; then
+ echo "未安装,请先安装!"
+ return
+ fi
+ cd $workdir
+ read -p "是否需要日志($workdir/running.log)? [y/n] [n]:" input
+ input=${input:-n}
+ args=""
+ if [[ "$input" == "y" ]]; then
+ args=" > running.log 2>&1 "
+ else
+ args=" > /dev/null 2>&1 "
+ fi
+ port=$(jq -r ".port" $configfile)
+ if checkProcAlive "wssh"; then
+ stopProc "wssh"
+ fi
+ echo "正在启动中..."
+ cmd="nohup ./wssh --port=$port --wpintvl=30 --fbidhttp=False --xheaders=False --encoding='utf-8' --delay=10 $args &"
+ eval "$cmd"
+ sleep 2
+ if checkProcAlive wssh; then
+ green "启动成功!"
+ else
+ echo "启动失败!"
+ fi
+}
+
+nonServ() {
+ cat <"
- echo -e "${CYAN}${art_wrod}${RESET}"
- echo -e "${GREEN} 饭奇骏频道:https://www.youtube.com/@frankiejun8965 ${RESET}"
- echo -e "${GREEN} TG交流群:https://t.me/fanyousuiqun ${RESET}"
- echo "<------------------------------------------------------------------>"
- echo "请选择一个选项:"
-
- options=("安装/更新serv00-play项目" "sun-panel" "webssh" "阅后即焚" "待开发" "设置保活的项目" "配置sing-box" \
- "运行sing-box" "停止sing-box" "显示sing-box节点信息" "快照恢复" "系统初始化" "前置工作及设置中国时区" "管理哪吒探针" "卸载探针" "设置彩色开机字样" "显示本机IP" \
- "mtproto代理" "alist管理" "端口管理" "域名证书管理" "一键root" "自动检测主机IP状态" "一键更换hy2的IP" "卸载" )
-
- select opt in "${options[@]}"
- do
- case $REPLY in
- 1)
- install
- ;;
- 2)
- sunPanelServ
- ;;
- 3)
- websshServ
- ;;
- 4)
- burnAfterReadingServ
- ;;
- 5)
- nonServ
- ;;
- 6)
- setConfig
- ;;
- 7)
- configSingBox
- ;;
- 8)
- startSingBox
- ;;
- 9)
- stopSingBox
- ;;
- 10)
- showSingBoxInfo
- ;;
- 11)
- ImageRecovery
- ;;
- 12)
- InitServer
- ;;
- 13)
- setCnTimeZone
- ;;
- 14)
- manageNeZhaAgent
- ;;
- 15)
- uninstallAgent
- ;;
- 16)
- setColorWord
- ;;
- 17)
- showIP
- ;;
- 18)
- mtprotoServ
- ;;
- 19)
- alistServ
- ;;
- 20)
- portServ
- ;;
- 21)
- domainSSLServ
- ;;
- 22)
- rootServ
- ;;
- 23)
- getUnblockIP
- ;;
- 24)
- changeHy2IP
- ;;
- 25)
- uninstall
- ;;
- 0)
- echo "退出"
- exit 0
- ;;
- *)
- echo "无效的选项 "
- ;;
- esac
-
- done
-
-}
-
-
-showMenu
\ No newline at end of file
+checkInstalled() {
+ local model=$1
+ if [[ "$model" == "serv00-play" ]]; then
+ if [[ ! -d "${installpath}/$model" ]]; then
+ red "请先安装$model !!!"
+ return 1
+ else
+ return 0
+ fi
+ else
+ if [[ ! -d "${installpath}/serv00-play/$model" ]]; then
+ red "请先安装$model !!!"
+ return 1
+ else
+ return 0
+ fi
+ fi
+ return 1
+}
+
+changeHy2IP() {
+ cd ${installpath}/serv00-play/singbox
+ if [[ ! -e "singbox.json" || ! -e "config.json" ]]; then
+ red "未安装节点,请先安装!"
+ return 1
+ fi
+ showIPStatus
+ read -p "是否让程序为HY2选择可用的IP?[y/n] [y]:" input
+ input=${input:-y}
+
+ if [[ "$input" == "n" ]]; then
+ read -p "是否手动选择IP?[y/n] [y]:" choose
+ choose=${choose:-y}
+ if [[ "$choose" == "y" ]]; then
+ read -p "请选择你要的IP的序号:" num
+ if [[ -z "$num" ]]; then
+ red "选择不能为空!"
+ return 1
+ fi
+ if [[ $num -lt 1 || $num -gt ${#localIPs[@]} ]]; then
+ echo "错误:num 的值非法!请输入 1 到 ${#localIPs[@]} 之间的整数。"
+ return 1
+ fi
+ hy2_ip=${localIPs[$((num - 1))]}
+ else
+ return 1
+ fi
+ else
+ hy2_ip=$(get_ip)
+ fi
+
+ if [[ -z "$hy2_ip" ]]; then
+ red "很遗憾,已无可用IP!"
+ return 1
+ fi
+ if ! upInsertFd singbox.json HY2IP "$hy2_ip"; then
+ red "更新singbox.json配置文件失败!"
+ return 1
+ fi
+
+ if ! upSingboxFd config.json "inbounds" "tag" "hysteria-in" "listen" "$hy2_ip"; then
+ red "更新config.json配置文件失败!"
+ return 1
+ fi
+ green "HY2 更换IP成功,当前IP为 $hy2_ip"
+
+ echo "正在重启sing-box..."
+ stopSingBox
+ startSingBox
+
+}
+
+linkAliveServ() {
+ workdir="${installpath}/serv00-play/linkalive"
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ if ! vip_statement "linkAliveStatment"; then
+ return 1
+ fi
+
+ if [[ ! -e $workdir ]]; then
+ mkdir -p $workdir
+ fi
+ cd $workdir
+
+ read -s -p "请输入会员密码:" passwd
+ #判断密码是否为空
+ if [[ -z "$passwd" ]]; then
+ red "密码不能为空!"
+ return 1
+ fi
+ if ! checkDownload "linkAlive.sh" $ISFILE "$passwd" $ISVIP; then
+ return 1
+ fi
+
+ chmod +x ./linkAlive.sh
+ ./linkAlive.sh "$passwd"
+
+ #showMenu
+}
+
+DSServ() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "---------------------"
+ echo "Domains-Support:"
+ echo "服务状态: $(checkCronNameStatus domains-support)"
+ echo "1. 新增域名"
+ echo "2. 删除域名"
+ echo "3. 配置"
+ echo "4. 开启服务"
+ echo "5. 停止服务"
+ echo "6. 批量新增域名"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ addDomain
+ ;;
+ 2)
+ delDomain
+ ;;
+ 3)
+ configDs
+ ;;
+ 4)
+ startDs
+ ;;
+ 5)
+ stopDs
+ ;;
+ 6)
+ batchAddDomains
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+
+}
+write_ds_config() {
+ local domain=$1
+ local url=$2
+ cat >config.json < /dev/null 2>&1 #domains-support" >>mycron
+ crontab mycron >/dev/null 2>&1
+ rm mycron
+
+}
+
+stopDs() {
+ local workdir="${installpath}/serv00-play/domains-support"
+ cd $workdir
+ if [[ ! -e "config.json" ]]; then
+ red "未配置,请先配置!"
+ return 1
+ fi
+ if checkCronName domains-support; then
+ echo "正在停止服务..."
+ crontab -l | grep -v "domains-support" >mycron
+ crontab mycron >/dev/null 2>&1
+ rm mycron
+ green "服务已停止!"
+ else
+ red "服务未开启!"
+ fi
+}
+
+addDomain() {
+ local workdir="${installpath}/serv00-play/domains-support"
+ if [[ ! -e $workdir ]]; then
+ mkdir -p $workdir
+ fi
+ cd $workdir
+ domain=""
+ webIp=""
+ if ! makeWWW "" "" "php" "y"; then
+ echo "绑定域名失败!"
+ return 1
+ fi
+ #echo "after makeWWW, domain=$domain,webIp=$webIp"
+ if ! applyLE "$domain" "$webIp" "n"; then
+ echo "申请证书失败!"
+ return 1
+ fi
+ cd $workdir
+ target="$installpath/domains/$domain/public_html"
+ if [[ ! -e "$target" ]]; then
+ red "目标目录不存在!"
+ fi
+
+ while true; do
+ echo "建站样式选择:"
+ echo "1. 樱花博客"
+ echo "2. 人力资源管理系统"
+ echo "3. 德一教育系统后台"
+ echo "4. 李明的英文简历"
+ echo "5. 游戏殿堂"
+ echo "6. 圣诞节贺卡"
+ echo "99. 自定义网站"
+
+ read -p "你的选择: " choice
+
+ case $choice in
+ 1)
+ echo "你选择了樱花博客"
+ break
+ ;;
+ 2)
+ echo "你选择了人力资源管理系统"
+ break
+ ;;
+ 3)
+ echo "你选择了德一教育系统后台"
+ break
+ ;;
+ 4)
+ echo "你选择了李明的英文简历"
+ break
+ ;;
+ 5)
+ echo "你选择了游戏殿堂"
+ break
+ ;;
+ 6)
+ echo "你选择了圣诞节贺卡"
+ break
+ ;;
+ 99)
+ break
+ ;;
+ 0)
+ echo "返回上一级"
+ return
+ ;;
+ *)
+ echo "无效选择,请重新输入"
+ ;;
+ esac
+ done
+
+ if [[ "$choice" == "1" ]]; then
+ cp websites/sakura.html $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ read -p "输入你的名字([xx的博客]里的xx):" name
+ name=${name:-"樱花"}
+ sed -i.bak "s|xx|$name|g" $target/index.html
+ fi
+ if [[ "$choice" == "2" ]]; then
+ cp websites/hr.html $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ fi
+ if [[ "$choice" == "3" ]]; then
+ cp websites/deyiedu.html $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ fi
+ if [[ "$choice" == "4" ]]; then
+ cp websites/resume.html $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ fi
+ if [[ "$choice" == "5" ]]; then
+ cp websites/game.html $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ fi
+ if [[ "$choice" == "6" ]]; then
+ cp websites/christmas.html $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ fi
+ if [[ "$choice" == "99" ]]; then
+ read -p "输入网址html文件路径:" input
+ if [[ -z "$input" ]]; then
+ red "输入不能为空!"
+ return 1
+ fi
+ if [[ ! -e "$input" ]]; then
+ red "文件不存在!"
+ return 1
+ fi
+ cp "$input" $target/index.html
+ if [ $? -ne 0 ]; then
+ red "安装失败!"
+ return 1
+ fi
+ fi
+
+ add_domain $domain $webIp
+ if [[ -e "config.json" ]]; then
+ local api_token=$(jq -r ".API_TOKEN" config.json)
+ local url=$(jq -r ".URL" config.json)
+ if [[ -z "$api_token" || -z "$url" ]]; then
+ red "配置文件错误,请检查!"
+ return 1
+ fi
+ read -p "是否录入域名信息到数据库? [y/n] [n]:" input
+ input=${input:-n}
+ if [[ "$input" == "y" ]]; then
+ read -p "请输入注册商名称:" registrar
+ registrar=${registrar:-"注册商"}
+
+ read -p "请输入注册商链接(可选):" registrar_link
+ registrar_link=${registrar_link:-""}
+
+ read -p "请输入注册日期(格式: YYYY-MM-DD):" registrar_date
+ registrar_date=${registrar_date:-$(date +%Y-%m-%d)}
+
+ read -p "请输入到期日期(格式: YYYY-MM-DD):" expiry_date
+ expiry_date=${expiry_date:-$(date -v+1y +%Y-%m-%d)}
+
+ local host=$(hostname)
+ local username=$(whoami)
+
+ read -p "请输入备注(可选):" memo
+ memo=${memo:-"$host-$username"}
+ fi
+ curl -X POST "https://$url/api/addrec?token=$api_token" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "domain": "'"$domain"'",
+ "registrar": "'"$registrar"'",
+ "registrar_date": "'"$registrar_date"'",
+ "registrar_link": "'"$registrar_link"'",
+ "expiry_date": "'"$expiry_date"'",
+ "service_type": "伪装网站",
+ "status": "在线",
+ "tgsend": "1",
+ "memo": "'"$memo"'"
+ }' >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ red "域名信息录入失败!"
+ return 1
+ fi
+ fi
+ green "域名的网站安装成功!"
+}
+
+delDomain() {
+ local workdir="${installpath}/serv00-play/domains-support"
+ if [[ ! -e $workdir ]]; then
+ red "未安装,请先安装!"
+ return 1
+ fi
+ cd $workdir
+ print_domains
+ read -p "请输入要删除的域名(-1删除所有,0返回上级菜单):" domain
+ if [[ -z "$domain" ]]; then
+ red "输入不能为空!"
+ return 1
+ fi
+ if [[ "$domain" == "-1" ]]; then
+ read -p "是否删除所有域名? [y/n] [n]:" input
+ input=${input:-n}
+ if [[ "$input" != "y" ]]; then
+ return 1
+ fi
+ delete_all_domains
+ rm -rf "${installpath}/serv00-play/domains-support"
+ green "删除成功!"
+ return 0
+ fi
+ if [[ "$domain" == "0" ]]; then
+ return 0
+ fi
+ delete_domain "$domain"
+ green "域名删除成功!"
+}
+
+keepAliveServ() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "---------------------"
+ echo "keepAlive:"
+ echo "1. 安装"
+ echo "2. 更新(须先按1更新serv00-play)"
+ echo "3. 更新保活时间间隔"
+ echo "4. 修改token"
+ echo "8. 卸载"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ installkeepAlive
+ ;;
+ 2)
+ updatekeepAlive
+ ;;
+ 3)
+ setKeepAliveInterval
+ ;;
+ 4)
+ changeKeepAliveToken
+ ;;
+ 8)
+ uninstallkeepAlive
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+
+ showMenu
+}
+
+installkeepAlive() {
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ local domainPath="${installpath}/domains/$domain/public_nodejs"
+ local workdir="${installpath}/serv00-play/keepalive"
+ if [[ -e "$domainPath/config.json" ]]; then
+ red "已安装,请勿重复安装!"
+ return 1
+ fi
+ cd $workdir
+
+ read -p "需要使用默认域名[$domain]进行安装,若继续安装将会删除默认域名,确认是否继续? [y/n] [y]:" input
+ input=${input:-y}
+ if [[ "$input" != "y" ]]; then
+ echo "取消安装"
+ return 1
+ fi
+ delDefaultDomain
+ echo "正在安装..."
+ if ! createDefaultDomain; then
+ return 1
+ fi
+ mv "$domainPath/public" "$domainPath/static"
+ cp ./nezha.jpg $domainPath/static
+ cp ./config.json $domainPath
+ cp ./app.js $domainPath
+
+ cd $domainPath
+ if ! npm22 install express body-parser child_process fs; then
+ red "安装依赖失败"
+ return 1
+ fi
+
+ read -p "是否需要自定义token? [y/n] [y]:" input
+ input=${input:-y}
+ if [[ "$input" == "y" ]]; then
+ uuid=""
+ read -p "请输入token:" uuid
+ if [[ -z "$uuid" ]]; then
+ red "token不能为空!"
+ return 1
+ fi
+ else
+ uuid=$(uuidgen)
+ fi
+ green "你的token是:$uuid"
+ sed -i '' "s/uuid/$uuid/g" config.json
+ read -p "输入保活时间间隔(单位:分钟)[默认:2分钟]:" interval
+ interval=${interval:-2}
+ sed -i '' "s/TM/$interval/g" config.json
+
+ green "安装成功"
+
+}
+
+uninstallkeepAlive() {
+ local input=$1
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ local domainPath="${installpath}/domains/$domain/public_nodejs"
+ if [ -z "$input" ]; then
+ read -p "是否卸载? [y/n] [n]:" input
+ input=${input:-n}
+ if [[ "$input" != "y" ]]; then
+ return 1
+ fi
+ fi
+ if ! delDefaultDomain; then
+ return 1
+ fi
+ green "卸载成功"
+}
+
+createDefaultDomain() {
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ rt=$(devil www add $domain nodejs /usr/local/bin/node22 production)
+ if [[ ! "$rt" =~ .*succesfully*$ ]]; then
+ red "创建默认域名失败"
+ return 1
+ fi
+}
+
+delDefaultDomain() {
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ rt=$(devil www del $domain --remove)
+ if [[ ! "$rt" =~ .*deleted*$ ]]; then
+ red "删除默认域名失败"
+ return 1
+ fi
+}
+
+updatekeepAlive() {
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ domainPath="${installpath}/domains/$domain/public_nodejs"
+ workDir="$installpath/serv00-play/keepalive"
+ if [[ ! -e "$domainPath/config.json" ]]; then
+ red "未安装,请先安装!"
+ return 1
+ fi
+ if [[ ! -e "$workDir" ]]; then
+ mkdir -p $workDir
+ fi
+ cd $workDir
+
+ cp ./app.js $domainPath
+
+ cp $workDir/app.js $domainPath
+ devil www restart $domain
+ green "更新成功"
+}
+
+changeKeepAliveToken() {
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ domainPath="${installpath}/domains/$domain/public_nodejs"
+ if [[ ! -e "$domainPath/config.json" ]]; then
+ red "未安装,请先安装!"
+ return 1
+ fi
+
+ cur_token=$(jq -r ".token" $domainPath/config.json)
+ echo "当前token为: $cur_token"
+ token=""
+ read -p "输入新的token:" token
+ if [[ -z "$token" ]]; then
+ red "token不能为空!"
+ return 1
+ fi
+ upInsertFd $domainPath/config.json token $token
+ if [ $? -ne 0 ]; then
+ red "更新失败!"
+ return 1
+ fi
+ green "更新成功"
+}
+
+setKeepAliveInterval() {
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ domainPath="${installpath}/domains/$domain/public_nodejs"
+ if [[ ! -e "$domainPath/config.json" ]]; then
+ red "未安装,请先安装!"
+ return 1
+ fi
+
+ cur_interval=$(jq -r ".interval" $domainPath/config.json)
+ echo "当前保活时间间隔为: $cur_interval 分钟"
+ read -p "输入保活时间间隔(单位:分钟)[默认:2分钟]:" interval
+ interval=${interval:-2}
+ upInsertFd $domainPath/config.json interval $interval
+ if [ $? -ne 0 ]; then
+ red "更新失败!"
+ return 1
+ fi
+ green "更新成功"
+}
+installRedis() {
+ local workdir="${installpath}/serv00-play/redis"
+ if [[ ! -d "$workdir" ]]; then
+ mkdir -p "$workdir"
+ fi
+ # 使用 || 来处理 cd 失败的情况,增加脚本健壮性
+ cd "$workdir" || {
+ red "错误:无法进入工作目录 $workdir"
+ return 1
+ }
+
+ # 步骤 1: 检查 redis.conf,如果不存在则下载
+ if [ ! -f "redis.conf" ]; then
+ yellow "redis.conf 文件不存在,正在从 Redis 官方 GitHub 仓库下载..."
+ # 使用 curl 下载文件,-fsSL 参数可以在失败时静默处理并支持重定向
+ if ! curl -fsSL -o redis.conf https://raw.githubusercontent.com/redis/redis/7.4/redis.conf; then
+ red "下载 redis.conf 失败!请检查网络连接或稍后重试。"
+ return 1
+ fi
+ green "redis.conf 下载成功!"
+ else
+ yellow "检测到已存在的 redis.conf,将在此基础上进行修改。"
+ fi
+
+ # 步骤 2: 交互式获取配置信息
+ green "----------------------------------------"
+ loadPort
+ randomPort tcp redis
+ if [[ -n "$port" ]]; then
+ redis_port="$port"
+ else
+ red "未输入端口号"
+ return 1
+ fi
+
+ read -r -p "密码 (Password) [留空则禁用密码]: " redis_password
+
+ read -r -p "日志文件路径 (Log file path) [默认: \"\"]: " redis_logfile
+
+ read -r -p "是否允许所有网络接口访问 (全网监听)?(y/n) [默认: n]: " listen_all
+ listen_all=${listen_all:-n}
+ green "----------------------------------------"
+
+ # 步骤 3: 根据输入修改配置文件
+ yellow "正在根据您的输入修改 redis.conf..."
+
+ # 修改端口
+ sed -i '' "s/^port .*/port ${redis_port}/" redis.conf
+
+ # 修改密码
+ if [[ -n "$redis_password" ]]; then
+ # 如果 requirepass 存在且未被注释,则直接替换
+ if grep -q "^requirepass" redis.conf; then
+ sed -i '' "s/^requirepass .*/requirepass ${redis_password}/" redis.conf
+ # 如果 requirepass 存在但被注释,则取消注释并替换
+ elif grep -q "^# requirepass" redis.conf; then
+ sed -i '' "s/^# requirepass .*/requirepass ${redis_password}/" redis.conf
+ # 如果不存在,则追加
+ else
+ echo "requirepass ${redis_password}" >>redis.conf
+ fi
+ green "✓ 密码已设置"
+ else
+ # 如果用户输入为空,则注释掉密码设置
+ sed -i '' 's/^requirepass .*/# requirepass foobared/' redis.conf
+ yellow "✓ 密码已禁用"
+ fi
+
+ # 修改日志文件路径
+ sed -i '' "s|^logfile.*|logfile \"${redis_logfile}\"|" redis.conf
+ green "✓ 日志文件路径已设置"
+
+ # 修改网络监听
+ if [[ "$listen_all" == "y" || "$listen_all" == "Y" ]]; then
+ # 注释掉所有 bind 开头的行,以允许所有 IP 访问
+ sed -i '' 's/^bind /# bind /' redis.conf
+ green "✓ 已配置为全网监听"
+ else
+ # 确保只监听本地回环地址
+ sed -i '' 's/^# bind 127.0.0.1 -::1/bind 127.0.0.1 -::1/' redis.conf
+ green "✓ 已配置为仅本地监听"
+ fi
+
+ green "----------------------------------------"
+ green "redis.conf 配置修改完成!"
+}
+
+startRedis() {
+ local workdir="${installpath}/serv00-play/redis"
+ if [[ ! -d "$workdir" ]]; then
+ red "未安装redis,请先安装!"
+ return 1
+ fi
+ cd "$workdir"
+ if checkProcAlive "redis-server"; then
+ red "redis已启动,请勿重复启动!"
+ return 1
+ fi
+ echo "正在启动redis..."
+ nohup redis-server ./redis.conf >/dev/null 2>&1 &
+ sleep 2
+ if checkProcAlive "redis-server"; then
+ green "启动成功!"
+ else
+ echo "启动失败!"
+ fi
+}
+stopRedis() {
+ local workdir="${installpath}/serv00-play/redis"
+ if [[ ! -d "$workdir" ]]; then
+ red "未安装redis,请先安装!"
+ return 1
+ fi
+ cd "$workdir"
+ if ! checkProcAlive "redis-server"; then
+ red "redis未启动!"
+ return 1
+ fi
+ echo "正在停止redis..."
+ stopProc "redis-server"
+ sleep 2
+ if ! checkProcAlive "redis-server"; then
+ green "停止成功!"
+ else
+ echo "未能停止,请手动杀进程!"
+ fi
+}
+
+uninstallRedis() {
+ local input=$1
+ local workdir="${installpath}/serv00-play/redis"
+ if [[ ! -d "$workdir" ]]; then
+ red "未安装redis,请先安装!"
+ return 1
+ fi
+ if [ -z "$input" ]; then
+ read -p "是否卸载? [y/n] [n]:" input
+ input=${input:-n}
+ if [[ "$input" != "y" ]]; then
+ return 1
+ fi
+ fi
+ stopRedis
+ rm -rf "$workdir"
+ green "卸载成功"
+}
+
+redisManage() {
+ while true; do
+ yellow "---------------------"
+ echo "redis管理:"
+ echo "服务状态: $(checkProcStatus redis-server)"
+ echo "1. 安装/修改配置"
+ echo "2. 启动"
+ echo "3. 停止"
+ echo "8. 卸载"
+ echo "9. 返回主菜单"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+ read -p "请选择:" input
+ case $input in
+ 1)
+ installRedis
+ ;;
+ 2)
+ startRedis
+ ;;
+ 3)
+ stopRedis
+ ;;
+ 8)
+ uninstallRedis
+ ;;
+ 9)
+ break
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+
+}
+
+devManage() {
+ if ! checkInstalled "serv00-play"; then
+ return 1
+ fi
+ while true; do
+ yellow "---------------------"
+ echo "开发工具管理:"
+ echo "1. redis"
+ echo "0. 退出脚本"
+ yellow "---------------------"
+
+ read -p "请选择:" input
+
+ case $input in
+ 1)
+ redisManage
+ ;;
+ 0)
+ exit 0
+ ;;
+ *)
+ echo "无效选项,请重试"
+ ;;
+ esac
+ done
+ showMenu
+
+}
+
+linkAliveStatment() {
+ cat </dev/null)
+ if [ $? -ne 0 ]; then
+ echo null
+ else
+ echo $ver
+ fi
+}
+
+showMenu() {
+ art_wrod=$(figlet "serv00-play")
+ echo "<------------------------------------------------------------------>"
+ echo -e "${CYAN}${art_wrod}${RESET}"
+ echo -e "${GREEN} 饭奇骏频道:https://www.youtube.com/@frankiejun8965 ${RESET}"
+ echo -e "${GREEN} TG交流群:https://t.me/fanyousuiqun ${RESET}"
+ echo -e "${GREEN} 当前版本号:$(getCurrentVer) 最新版本号:$(getLatestVer) ${RESET}"
+ echo "<------------------------------------------------------------------>"
+ echo "请选择一个选项:"
+
+ options=("安装/更新serv00-play项目" "sun-panel" "webssh" "阅后即焚" "linkalive" "设置保活的项目" "配置sing-box"
+ "运行sing-box" "停止sing-box" "显示sing-box节点信息" "快照恢复" "系统初始化" "前置工作及设置中国时区" "哪吒探针管理" "哪吒面板管理" "设置彩色开机字样" "显示本机IP"
+ "mtproto代理" "alist管理" "端口管理" "域名证书管理" "一键root" "自动检测主机IP状态" "一键更换hy2的IP" "KeepAlive" "Domains-Support" "微信消息推送界面管理"
+ "开发工具管理" "备份/恢复" "卸载")
+
+ select opt in "${options[@]}"; do
+ case $REPLY in
+ 1)
+ install
+ ;;
+ 2)
+ sunPanelServ
+ ;;
+ 3)
+ websshServ
+ ;;
+ 4)
+ burnAfterReadingServ
+ ;;
+ 5)
+ linkAliveServ
+ ;;
+ 6)
+ setConfig
+ ;;
+ 7)
+ configSingBox
+ ;;
+ 8)
+ startSingBox
+ ;;
+ 9)
+ stopSingBox
+ ;;
+ 10)
+ showSingBoxInfo
+ ;;
+ 11)
+ ImageRecovery
+ ;;
+ 12)
+ InitServer
+ ;;
+ 13)
+ setCnTimeZone
+ ;;
+ 14)
+ manageNeZhaAgent
+ ;;
+ 15)
+ manageNeZhaBoard
+ ;;
+ 16)
+ setColorWord
+ ;;
+ 17)
+ showIP
+ ;;
+ 18)
+ mtprotoServ
+ ;;
+ 19)
+ alistServ
+ ;;
+ 20)
+ portServ
+ ;;
+ 21)
+ domainSSLServ
+ ;;
+ 22)
+ rootServ
+ ;;
+ 23)
+ showIPStatus
+ ;;
+ 24)
+ changeHy2IP
+ ;;
+ 25)
+ keepAliveServ
+ ;;
+ 26)
+ DSServ
+ ;;
+ 27)
+ manageWxPushSkin
+ ;;
+ 28)
+ devManage
+ ;;
+ 29)
+ backupRestoreServ
+ ;;
+ 30)
+ uninstall
+ ;;
+ 0)
+ echo "退出"
+ exit 0
+ ;;
+ *)
+ echo "无效的选项 "
+ ;;
+ esac
+
+ done
+
+}
+
+if [ "$1" == "--uninstall" ]; then
+ echo "执行卸载操作"
+ uninstall "y"
+ exit 0
+elif [ "$1" == "--install" ]; then
+ echo "执行更新操作"
+ install "y"
+ exit 0
+else
+ showMenu
+fi
diff --git a/tgsend.sh b/tgsend.sh
index 4eaa6008..916c338d 100755
--- a/tgsend.sh
+++ b/tgsend.sh
@@ -1,21 +1,116 @@
#!/bin/bash
message_text=$1
-#解析模式,可选HTML或Markdown
-MODE='HTML'
-#api接口
+
+replaceValue() {
+ local url=$1
+ local target=$2
+ local value=$3
+ local result
+ result=$(printf '%s' "$url" | sed "s|#${target}|${value//&/\\&}|g")
+ echo "$result"
+}
+
+toBase64() {
+ echo -n "$1" | base64
+}
+
+urlencode() {
+ local input="$1"
+ local output=""
+ local length=${#input}
+ for ((i = 0; i < length; i++)); do
+ local char="${input:i:1}"
+ case "$char" in
+ [a-zA-Z0-9.~_-]) output+="$char" ;;
+ *) output+="$(printf '%%%02X' "'$char")" ;;
+ esac
+ done
+ echo "$output"
+}
+
+toTGMsg() {
+ local msg=$1
+ local title="*Serv00-play通知*"
+ local host_icon="🖥️"
+ local user_icon="👤"
+ local time_icon="⏰"
+ local notify_icon="📢"
+
+ # 获取当前时间
+ local current_time=$(date "+%Y-%m-%d %H:%M:%S")
+
+ if [[ "$msg" != Host:* ]]; then
+ local formatted_msg="${title} \n\n"
+ formatted_msg+="${time_icon} *时间:* ${current_time} \n"
+ formatted_msg+="${notify_icon} *通知内容:* \n$msg \n\n"
+ echo -e "$formatted_msg"
+ return
+ fi
+
+ local host=$(echo "$msg" | sed -n 's/.*Host:\([^,]*\).*/\1/p' | xargs)
+ local user=$(echo "$msg" | sed -n 's/.*user:\([^,]*\).*/\1/p' | xargs)
+ local notify_content=$(echo "$msg" | sed -E 's/.*user:[^,]*,//' | xargs)
+
+ # 格式化消息内容,Markdown 换行使用两个空格 + 换行
+ local formatted_msg="${title} \n\n"
+ formatted_msg+="${host_icon} *主机:* ${host} \n"
+ formatted_msg+="${user_icon} *用户:* ${user} \n"
+ formatted_msg+="${time_icon} *时间:* ${current_time} \n\n"
+ formatted_msg+="${notify_icon} *通知内容:* ${notify_content} \n\n"
+
+ echo -e "$formatted_msg|${host}|${user}" # 使用 -e 选项以确保换行符生效
+}
+
telegramBotToken=${TELEGRAM_TOKEN}
telegramBotUserId=${TELEGRAM_USERID}
+result=$(toTGMsg "$message_text")
+formatted_msg=$(echo "$result" | awk -F'|' '{print $1}')
+host=$(echo "$result" | awk -F'|' '{print $2}')
+user=$(echo "$result" | awk -F'|' '{print $3}')
+
+if [[ "$BUTTON_URL" == "null" ]]; then
+ button_url="https://www.youtube.com/@frankiejun8965"
+else
+ button_url=${BUTTON_URL:-"https://www.youtube.com/@frankiejun8965"}
+fi
URL="https://api.telegram.org/bot${telegramBotToken}/sendMessage"
+
+if [[ -n "$host" ]]; then
+ button_url=$(replaceValue $button_url HOST $host)
+fi
+if [[ -n "$user" ]]; then
+ button_url=$(replaceValue $button_url USER $user)
+fi
+if [[ -n "$PASS" ]]; then
+ pass=$(toBase64 $PASS)
+ button_url=$(replaceValue $button_url PASS $pass)
+fi
+encoded_url=$(urlencode "$button_url")
+#echo "encoded_url: $encoded_url"
+reply_markup='{
+ "inline_keyboard": [
+ [
+ {"text": "点击查看", "url": "'"${encoded_url}"'"}
+ ]
+ ]
+ }'
+#echo "reply_markup: $reply_markup"
+#echo "telegramBotToken:$telegramBotToken,telegramBotUserId:$telegramBotUserId"
if [[ -z ${telegramBotToken} ]]; then
echo "未配置TG推送"
else
- res=$(timeout 20s curl -s -X POST $URL -d chat_id=${telegramBotUserId} -d parse_mode=${MODE} -d text="${message_text}")
+ res=$(curl -s -X POST "https://api.telegram.org/bot${telegramBotToken}/sendMessage" \
+ -d chat_id="${telegramBotUserId}" \
+ -d parse_mode="Markdown" \
+ -d text="$formatted_msg" \
+ -d reply_markup="$reply_markup")
if [ $? == 124 ]; then
echo 'TG_api请求超时,请检查网络是否重启完成并是否能够访问TG'
exit 1
fi
+ #echo "res:$res"
resSuccess=$(echo "$res" | jq -r ".ok")
if [[ $resSuccess = "true" ]]; then
echo "TG推送成功"
diff --git a/utils.sh b/utils.sh
index b1f4ef4a..e97c5680 100644
--- a/utils.sh
+++ b/utils.sh
@@ -9,397 +9,438 @@ CYAN='\033[0;96m'
WHITE='\033[0;37m'
RESET='\033[0m'
yellow() {
- echo -e "${YELLOW}$1${RESET}"
+ echo -e "${YELLOW}$1${RESET}"
}
green() {
- echo -e "${GREEN}$1${RESET}"
+ echo -e "${GREEN}$1${RESET}"
}
red() {
- echo -e "${RED}$1${RESET}"
+ echo -e "${RED}$1${RESET}"
}
installpath="$HOME"
+baseurl="https://ss.fkj.pp.ua"
+linkBaseurl="https://la.fkj.pp.ua"
checknezhaAgentAlive() {
- if ps aux | grep nezha-agent | grep -v "grep" >/dev/null; then
- return 0
- else
- return 1
- fi
+ if ps aux | grep nezha-agent | grep -v "grep" >/dev/null; then
+ return 0
+ else
+ return 1
+ fi
}
checkvmessAlive() {
- local c=0
- if ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
- ((c++))
- fi
+ local c=0
+ if ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
+ ((c++))
+ fi
- if ps aux | grep cloudflared | grep -v "grep" >/dev/null; then
- ((c++))
- fi
+ if ps aux | grep cloudflared | grep -v "grep" >/dev/null; then
+ ((c++))
+ fi
- if [ $c -eq 2 ]; then
- return 0
- fi
+ if [ $c -eq 2 ]; then
+ return 0
+ fi
- return 1 # 有一个或多个进程不在运行
+ return 1 # 有一个或多个进程不在运行
}
#返回0表示成功, 1表示失败
#在if条件中,0会执行,1不会执行
checkProcAlive() {
- local procname=$1
- if ps aux | grep "$procname" | grep -v "grep" >/dev/null; then
- return 0
- else
- return 1
- fi
+ local procname=$1
+ if ps aux | grep "$procname" | grep -v "grep" >/dev/null; then
+ return 0
+ else
+ return 1
+ fi
}
stopProc() {
- local procname=$1
- r=$(ps aux | grep "$procname" | grep -v "grep" | awk '{print $2}')
- if [ -z "$r" ]; then
- return 0
- else
- kill -9 $r
- fi
- echo "已停掉$procname!"
+ local procname=$1
+ r=$(ps aux | grep "$procname" | grep -v "grep" | awk '{print $2}')
+ if [ -z "$r" ]; then
+ return 0
+ else
+ kill -9 $r
+ fi
+ echo "已停掉$procname!"
+ return 0
}
checkSingboxAlive() {
- local c=0
- if ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
- ((c++))
- fi
+ local c=0
+ if ps aux | grep serv00sb | grep -v "grep" >/dev/null; then
+ ((c++))
+ fi
- if ps aux | grep cloudflare | grep -v "grep" >/dev/null; then
- ((c++))
- fi
+ if ps aux | grep cloudflare | grep -v "grep" >/dev/null; then
+ ((c++))
+ fi
- if [ $c -eq 2 ]; then
- return 0
- fi
+ if [ $c -eq 2 ]; then
+ return 0
+ fi
- return 1 # 有一个或多个进程不在运行
+ return 1 # 有一个或多个进程不在运行
}
checkMtgAlive() {
- if ps aux | grep mtg | grep -v "grep" >/dev/null; then
- return 0
- else
- return 1
- fi
+ if ps aux | grep mtg | grep -v "grep" >/dev/null; then
+ return 0
+ else
+ return 1
+ fi
}
stopNeZhaAgent() {
- r=$(ps aux | grep nezha-agent | grep -v "grep" | awk '{print $2}')
- if [ -z "$r" ]; then
- return 0
- else
- kill -9 $r
- fi
- echo "已停掉nezha-agent!"
+ r=$(ps aux | grep nezha-agent | grep -v "grep" | awk '{print $2}')
+ if [ -z "$r" ]; then
+ return 0
+ else
+ kill -9 $r
+ fi
+ echo "已停掉nezha-agent!"
}
writeWX() {
- has_fd=$(echo "$config_content" | jq 'has("wxsendkey")')
- if [ "$has_fd" == "true" ]; then
- wx_sendkey=$(echo "$config_content" | jq -r ".wxsendkey")
- read -p "已有 WXSENDKEY ($wx_sendkey), 是否修改? [y/n] [n]:" input
- input=${input:-n}
- if [ "$input" == "y" ]; then
- read -p "请输入 WXSENDKEY:" wx_sendkey
- fi
- json_content+=" \"wxsendkey\": \"${wx_sendkey}\", \n"
- else
- read -p "请输入 WXSENDKEY:" wx_sendkey
- json_content+=" \"wxsendkey\": \"${wx_sendkey}\", \n"
- fi
+ has_fd=$(echo "$config_content" | jq 'has("wxsendkey")')
+ if [ "$has_fd" == "true" ]; then
+ wx_sendkey=$(echo "$config_content" | jq -r ".wxsendkey")
+ read -p "已有 WXSENDKEY ($wx_sendkey), 是否修改? [y/n] [n]:" input
+ input=${input:-n}
+ if [ "$input" == "y" ]; then
+ read -p "请输入 WXSENDKEY:" wx_sendkey
+ fi
+ json_content+=" \"wxsendkey\": \"${wx_sendkey}\", \n"
+ else
+ read -p "请输入 WXSENDKEY:" wx_sendkey
+ json_content+=" \"wxsendkey\": \"${wx_sendkey}\", \n"
+ fi
}
writeTG() {
- has_fd=$(echo "$config_content" | jq 'has("telegram_token")')
- if [ "$has_fd" == "true" ]; then
- tg_token=$(echo "$config_content" | jq -r ".telegram_token")
- read -p "已有 TELEGRAM_TOKEN ($tg_token), 是否修改? [y/n] [n]:" input
- input=${input:-n}
- if [ "$input" == "y" ]; then
- read -p "请输入 TELEGRAM_TOKEN:" tg_token
- fi
- json_content+=" \"telegram_token\": \"${tg_token}\", \n"
- else
- read -p "请输入 TELEGRAM_TOKEN:" tg_token
- json_content+=" \"telegram_token\": \"${tg_token}\", \n"
- fi
-
- has_fd=$(echo "$config_content" | jq 'has("telegram_userid")')
- if [ "$has_fd" == "true" ]; then
- tg_userid=$(echo "$config_content" | jq -r ".telegram_userid")
- read -p "已有 TELEGRAM_USERID ($tg_userid), 是否修改? [y/n] [n]:" input
- input=${input:-n}
- if [ "$input" == "y" ]; then
- read -p "请输入 TELEGRAM_USERID:" tg_userid
- fi
- json_content+=" \"telegram_userid\": \"${tg_userid}\", \n"
- else
- read -p "请输入 TELEGRAM_USERID:" tg_userid
- json_content+=" \"telegram_userid\": \"${tg_userid}\",\n"
- fi
+ has_fd=$(echo "$config_content" | jq 'has("telegram_token")')
+ if [ "$has_fd" == "true" ]; then
+ tg_token=$(echo "$config_content" | jq -r ".telegram_token")
+ read -p "已有 TELEGRAM_TOKEN ($tg_token), 是否修改? [y/n] [n]:" input
+ input=${input:-n}
+ if [ "$input" == "y" ]; then
+ read -p "请输入 TELEGRAM_TOKEN:" tg_token
+ fi
+ json_content+=" \"telegram_token\": \"${tg_token}\", \n"
+ else
+ read -p "请输入 TELEGRAM_TOKEN:" tg_token
+ json_content+=" \"telegram_token\": \"${tg_token}\", \n"
+ fi
+
+ has_fd=$(echo "$config_content" | jq 'has("telegram_userid")')
+ if [ "$has_fd" == "true" ]; then
+ tg_userid=$(echo "$config_content" | jq -r ".telegram_userid")
+ read -p "已有 TELEGRAM_USERID ($tg_userid), 是否修改? [y/n] [n]:" input
+ input=${input:-n}
+ if [ "$input" == "y" ]; then
+ read -p "请输入 TELEGRAM_USERID:" tg_userid
+ fi
+ json_content+=" \"telegram_userid\": \"${tg_userid}\", \n"
+ else
+ read -p "请输入 TELEGRAM_USERID:" tg_userid
+ json_content+=" \"telegram_userid\": \"${tg_userid}\",\n"
+ fi
}
cleanCron() {
- echo "" >null
- crontab null
- rm null
+ echo "" >null
+ crontab null
+ rm null
}
delCron() {
- crontab -l | grep -v "keepalive" >mycron
- crontab mycron >/dev/null 2>&1
- rm mycron
+ crontab -l | grep -v "keepalive" >mycron
+ crontab mycron >/dev/null 2>&1
+ rm mycron
}
addCron() {
- local tm=$1
- crontab -l | grep -v "keepalive" >mycron
- echo "*/$tm * * * * bash ${installpath}/serv00-play/keepalive.sh > /dev/null 2>&1 " >>mycron
- crontab mycron >/dev/null 2>&1
- rm mycron
+ local tm=$1
+ crontab -l | grep -v "keepalive" >mycron
+ echo "*/$tm * * * * bash ${installpath}/serv00-play/keepalive.sh > /dev/null 2>&1 " >>mycron
+ crontab mycron >/dev/null 2>&1
+ rm mycron
}
get_webip() {
- # 获取主机名称,例如:s2.serv00.com
- local hostname=$(hostname)
-
- # 提取主机名称中的数字,例如:2
- local host_number=$(echo "$hostname" | awk -F'[s.]' '{print $2}')
-
- # 构造主机名称的数组
- local hosts=("web${host_number}.serv00.com" "cache${host_number}.serv00.com")
-
- # 初始化最终 IP 变量
- local final_ip=""
-
- # 遍历主机名称数组
- for host in "${hosts[@]}"; do
- # 获取 API 返回的数据
- local response=$(curl -s "https://ss.botai.us.kg/api/getip?host=$host")
-
- # 检查返回的结果是否包含 "not found"
- if [[ "$response" =~ "not found" ]]; then
- continue
- fi
-
- # 提取第一个字段作为 IP,并检查第二个字段是否为 "Accessible"
- local ip=$(echo "$response" | awk -F "|" '{ if ($2 == "Accessible") print $1 }')
- # webxx.serv00.com域名对应的ip作为兜底ip
- if [[ "$host" == "web${host_number}.serv00.com" ]]; then
- final_ip=$(echo "$response" | awk -F "|" '{print $1}')
- fi
-
- # 如果找到了 "Accessible",返回 IP
- if [[ -n "$ip" ]]; then
- echo "$ip"
- return
- fi
- done
-
- echo "$final_ip"
+ # 获取主机名称,例如:s2.serv00.com
+ local hostname=$(hostname)
+
+ # 提取主机名称中的数字,例如:2
+ local host_number=$(echo "$hostname" | awk -F'[s.]' '{print $2}')
+
+ # 构造主机名称的数组
+ local hosts=("web${host_number}.$(getDoMain)" "cache${host_number}.$(getDoMain)")
+
+ # 初始化最终 IP 变量
+ local final_ip="$(devil vhost list | grep web | awk '{print $1}')"
+ local hostmain=$(getDoMain)
+ hostmain="${hostmain%.com}"
+ # 遍历主机名称数组
+ for host in "${hosts[@]}"; do
+ # 获取 API 返回的数据
+ local response=$(curl -s "${baseurl}/api/getip?host=$host&type=$hostmain")
+
+ # 检查返回的结果是否包含 "not found"
+ if [[ "$response" =~ "not found" ]]; then
+ continue
+ fi
+
+ # 提取第一个字段作为 IP,并检查第二个字段是否为 "Accessible"
+ local ip=$(echo "$response" | awk -F "|" '{ if ($2 == "Accessible") print $1 }')
+ # webxx.serv00.com域名对应的ip作为兜底ip
+ if [[ "$host" == "web${host_number}.$(getDoMain)" ]]; then
+ final_ip=$(echo "$response" | awk -F "|" '{print $1}')
+ fi
+
+ # 如果找到了 "Accessible",返回 IP
+ if [[ -n "$ip" ]]; then
+ echo "$ip"
+ return
+ fi
+ done
+
+ echo "$final_ip"
}
get_ip() {
- # 获取主机名称,例如:s2.serv00.com
- local hostname=$(hostname)
+ # 获取主机名称,例如:s2.serv00.com
+ local hostname=$(hostname)
- # 提取主机名称中的数字,例如:2
- local host_number=$(echo "$hostname" | awk -F'[s.]' '{print $2}')
+ # 提取主机名称中的数字,例如:2
+ local host_number=$(echo "$hostname" | awk -F'[s.]' '{print $2}')
- # 构造主机名称的数组
- local hosts=("cache${host_number}.serv00.com" "web${host_number}.serv00.com" "$hostname")
+ # 构造主机名称的数组
+ local hosts=("cache${host_number}.$(getDoMain)" "web${host_number}.$(getDoMain)" "$hostname")
- # 初始化最终 IP 变量
- local final_ip=""
+ # 初始化最终 IP 变量
+ local final_ip="$(curl -s icanhazip.com)"
- # 遍历主机名称数组
- for host in "${hosts[@]}"; do
- # 获取 API 返回的数据
- local response=$(curl -s "https://ss.botai.us.kg/api/getip?host=$host")
+ local hostmain=$(getDoMain)
+ hostmain="${hostmain%.com}"
+ # 遍历主机名称数组
+ for host in "${hosts[@]}"; do
+ # 获取 API 返回的数据
+ local response=$(curl -s "${baseurl}/api/getip?host=$host&type=$hostmain")
- # 检查返回的结果是否包含 "not found"
- if [[ "$response" =~ "not found" ]]; then
- continue
- fi
+ # 检查返回的结果是否包含 "not found"
+ if [[ "$response" =~ "not found" ]]; then
+ continue
+ fi
- # 提取第一个字段作为 IP,并检查第二个字段是否为 "Accessible"
- local ip=$(echo "$response" | awk -F "|" '{ if ($2 == "Accessible") print $1 }')
+ # 提取第一个字段作为 IP,并检查第二个字段是否为 "Accessible"
+ local ip=$(echo "$response" | awk -F "|" '{ if ($2 == "Accessible") print $1 }')
- # 如果找到了 "Accessible",返回 IP
- if [[ -n "$ip" ]]; then
- echo "$ip"
- return
- fi
+ # 如果找到了 "Accessible",返回 IP
+ if [[ -n "$ip" ]]; then
+ echo "$ip"
+ return
+ fi
- final_ip=$ip
- done
+ final_ip=$ip
+ done
- echo "$final_ip"
+ echo "$final_ip"
}
isServ00() {
- [[ $(hostname) == *"serv00"* ]]
+ [[ $(hostname) == *"serv00"* ]]
+}
+
+getDoMain() {
+ if isServ00; then
+ echo -n "serv00.com"
+ else
+ echo -n "hostuno.com"
+ fi
+}
+
+getUserDoMain() {
+ local proc=$1
+ local baseDomain=""
+ user="$(whoami)"
+ if isServ00; then
+ baseDomain="$user.serv00.net"
+ else
+ baseDomain="$user.useruno.com"
+ fi
+ if [[ -n "$proc" ]]; then
+ echo -n "$proc.$baseDomain"
+ else
+ echo -n "$baseDomain"
+ fi
}
#获取端口
getPort() {
- local type=$1
- local opts=$2
-
- local key="$type|$opts"
- #echo "key: $key"
- #port list中查找,如果没有随机分配一个
- if [[ -n "${port_array["$key"]}" ]]; then
- #echo "找到list中的port"
- echo "${port_array["$key"]}"
- else
- # echo "devil port add $type random $opts"
- rt=$(devil port add $type random $opts)
- if [[ "$rt" =~ .*succesfully.*$ || "$rt" =~ .*Ok.*$ ]]; then
- loadPort
- if [[ -n "$port_array["$key"]" ]]; then
- echo "${port_array["$key"]}"
- else
- echo "failed"
- fi
- else
- echo "failed"
- fi
- fi
+ local type=$1
+ local opts=$2
+
+ local key="$type|$opts"
+ #echo "key: $key"
+ #port list中查找,如果没有随机分配一个
+ if [[ -n "${port_array["$key"]}" ]]; then
+ #echo "找到list中的port"
+ echo "${port_array["$key"]}"
+ else
+ # echo "devil port add $type random $opts"
+ rt=$(devil port add $type random $opts)
+ if [[ "$rt" =~ .*succesfully.*$ || "$rt" =~ .*Ok.*$ ]]; then
+ loadPort
+ if [[ -n "${port_array["$key"]}" ]]; then
+ echo "${port_array["$key"]}"
+ else
+ echo "failed"
+ fi
+ else
+ echo "failed"
+ fi
+ fi
}
randomPort() {
- local type=$1
- local opts=$2
- port=""
- #echo "type:$type, opts:$opts"
- read -p "是否自动分配${opts}端口($type)?[y/n] [y]:" input
- input=${input:-y}
- if [[ "$input" == "y" ]]; then
- port=$(getPort $type $opts)
- if [[ "$port" == "failed" ]]; then
- read -p "自动分配端口失败,请手动输入${opts}端口:" port
- else
- green "自动分配${opts}端口为:${port}"
- fi
- else
- read -p "请输入${opts}端口($type):" port
- fi
+ local type=$1
+ local opts=$2
+ port=""
+ #echo "type:$type, opts:$opts"
+ read -p "是否自动分配${opts}端口($type)?[y/n] [y]:" input
+ input=${input:-y}
+ if [[ "$input" == "y" ]]; then
+ port=$(getPort $type $opts)
+ if [[ "$port" == "failed" ]]; then
+ read -p "自动分配端口失败,请手动输入${opts}端口:" port
+ else
+ green "自动分配${opts}端口为:${port}"
+ fi
+ else
+ read -p "请输入${opts}端口($type):" port
+ fi
}
declare -A port_array
#检查是否可以自动分配端口
loadPort() {
- output=$(devil port list)
-
- port_array=()
- # 解析输出内容
- index=0
- while read -r port typ opis; do
- # 跳过标题行
- if [[ "$port" =~ "Port" ]]; then
- continue
- fi
- #echo "port:$port,typ:$typ, opis:$opis"
- if [[ "$port" =~ "Brak" || "$port" == "No" ]]; then
- echo "未分配端口"
- return 0
- fi
- # 将 Typ 和 Opis 合并并存储到数组中
- if [[ -n "$typ" ]]; then
- # 如果 Opis 为空则用空字符串代替
- opis=${opis:-""}
- combined="${typ}|${opis}"
- port_array["$combined"]="$port"
- # echo "port_array 读入 key=$combined, value=$port"
- ((index++))
- fi
- done <<<"$output"
-
- return 0
+ output=$(devil port list)
+
+ port_array=()
+ # 解析输出内容
+ index=0
+ while read -r port typ opis; do
+ # 跳过标题行
+ if [[ "$port" =~ "Port" ]]; then
+ continue
+ fi
+ #echo "port:$port,typ:$typ, opis:$opis"
+ if [[ "$port" =~ "Brak" || "$port" == "No" ]]; then
+ echo "未分配端口"
+ return 0
+ fi
+ # 将 Typ 和 Opis 合并并存储到数组中
+ if [[ -n "$typ" ]]; then
+ # 如果 Opis 为空则用空字符串代替
+ opis=${opis:-""}
+ combined="${typ}|${opis}"
+ port_array["$combined"]="$port"
+ # echo "port_array 读入 key=$combined, value=$port"
+ ((index++))
+ fi
+ done <<<"$output"
+
+ return 0
}
cleanPort() {
- output=$(devil port list)
- while read -r port typ opis; do
- # 跳过标题行
- if [[ "$typ" == "Type" ]]; then
- continue
- fi
- if [[ "$port" == "Brak" || "$port" == "No" ]]; then
- return 0
- fi
- if [[ -n "$typ" ]]; then
- devil port del $typ $port >/dev/null 2>&1
- fi
- done <<<"$output"
- return 0
-}
-
+ output=$(devil port list)
+ while read -r port typ opis; do
+ # 跳过标题行
+ if [[ "$typ" == "Type" ]]; then
+ continue
+ fi
+ if [[ "$port" == "Brak" || "$port" == "No" ]]; then
+ return 0
+ fi
+ if [[ -n "$typ" ]]; then
+ devil port del $typ $port >/dev/null 2>&1
+ fi
+ done <<<"$output"
+ return 0
+}
+
+ISIDR=1
+ISFILE=0
+ISVIP=1
+NOTVIP=0
checkDownload() {
- local file=$1
- local filegz="$file.gz"
- local is_dir=${2:-0}
-
- if [[ $is_dir -eq 1 ]]; then
- filegz="$file.tar.gz"
- fi
-
- #检查并下载核心程序
- if [[ ! -e $file ]] || [[ $(file $file) == *"text"* ]]; then
- echo "正在下载 $file..."
- url="https://gfg.fkj.pp.ua/app/serv00/$filegz?pwd=fkjyyds666"
- curl -L -sS --max-time 20 -o $filegz "$url"
-
- if file $filegz | grep -q "text"; then
- echo "无法正确下载!!!"
- rm -f $filegz
- return 1
- fi
- if [ -e $filegz ]; then
- if [[ $is_dir -eq 1 ]]; then
- tar -zxf $filegz
- else
- gzip -d $filegz
- fi
- else
- echo "下载失败,可能是网络问题."
- return 1
- fi
- #下载失败
- if [[ $is_dir -eq 0 && ! -e $file ]]; then
- echo "无法下载核心程序,可能网络问题,请检查!"
- return 1
- fi
- # 设置可执行权限
- if [[ $is_dir -eq 0 ]]; then
- chmod +x "$file"
- fi
- echo "下载完毕!"
- fi
- return 0
+ local file=$1
+ local is_dir=${2:-0}
+ local passwd=${3:-"fkjyyds666"}
+ local vipflag=${4:-0}
+ local filegz="$file.gz"
+
+ if [[ $is_dir -eq 1 ]]; then
+ filegz="$file.tar.gz"
+ fi
+
+ #检查并下载核心程序
+ if [[ ! -e $file ]] || [[ $(file $file) == *"text"* ]]; then
+ echo "正在下载 $file..."
+ if [[ $vipflag -eq 1 ]]; then
+ url="https://gfg.fkj.pp.ua/app/vip/$filegz?pwd=$passwd"
+ else
+ url="https://gfg.fkj.pp.ua/app/serv00/$filegz?pwd=$passwd"
+ fi
+ #echo "url:$url"
+ curl -L -sS --max-time 20 -o $filegz "$url"
+
+ if file $filegz | grep -q "text"; then
+ echo "无法正确下载!!!"
+ rm -f $filegz
+ return 1
+ fi
+ if [ -e $filegz ]; then
+ if [[ $is_dir -eq 1 ]]; then
+ tar -zxf $filegz
+ else
+ gzip -d $filegz
+ fi
+ else
+ echo "下载失败,可能是网络问题."
+ return 1
+ fi
+ #下载失败
+ if [[ $is_dir -eq 0 && ! -e $file ]]; then
+ echo "无法下载核心程序,可能网络问题,请检查!"
+ return 1
+ fi
+ # 设置可执行权限
+ if [[ $is_dir -eq 0 ]]; then
+ chmod +x "$file"
+ fi
+ echo "下载完毕!"
+ fi
+ return 0
}
# 对json文件字段进行插入或修改
# usage: upInsertFd jsonfile fieldname value
upInsertFd() {
- local jsonfile=$1
- local field=$2
- local value=$3
+ local jsonfile=$1
+ local field=$2
+ local value=$3
- jq --arg field "$field" --arg value "$value" '
+ jq --arg field "$field" --arg value "$value" '
if has($field) then
.[$field] = $value
else
@@ -407,137 +448,402 @@ upInsertFd() {
end
' "$jsonfile" >tmp.json && mv tmp.json "$jsonfile"
- return $?
+ return $?
}
# 针对singbox.json, 对指定字段进行修改
upSingboxFd() {
- local jsonfile=$1
- local array_name=$2
- local selector_key=$3
- local selector_value=$4
- local field_path=$5
- local value=$6
-
- jq --arg selector_key "$selector_key" \
- --arg selector_value "$selector_value" \
- --arg field_path "$field_path" \
- --arg value "$value" "
+ local jsonfile=$1
+ local array_name=$2
+ local selector_key=$3
+ local selector_value=$4
+ local field_path=$5
+ local value=$6
+
+ jq --arg selector_key "$selector_key" \
+ --arg selector_value "$selector_value" \
+ --arg field_path "$field_path" \
+ --arg value "$value" "
(.$array_name[] | select(.$selector_key == \$selector_value) | .[\$field_path]) = \$value
" "$jsonfile" >tmp.json && mv tmp.json "$jsonfile"
- return $?
+ return $?
}
# php默认配置文件操作
PHPCONFIG_FILE="phpconfig.json"
# 判断JSON文件是否存在,若不存在则创建并初始化
initialize_json() {
- if [ ! -f "$PHPCONFIG_FILE" ]; then
- echo '{"domains": []}' >"$PHPCONFIG_FILE"
- fi
+ if [ ! -f "$PHPCONFIG_FILE" ]; then
+ echo '{"domains": []}' >"$PHPCONFIG_FILE"
+ fi
}
# 添加新域名
add_domain() {
- local new_domain="$1"
- local webip="$2"
+ local new_domain="$1"
+ local webip="$2"
- # 初始化JSON文件(如果不存在的话)
- initialize_json
+ # 初始化JSON文件(如果不存在的话)
+ initialize_json
- # 读取当前的JSON配置文件并检查域名是否已存在
- if grep -q "\"$new_domain\"" "$PHPCONFIG_FILE"; then
- echo "域名 '$new_domain' 已存在!"
- return 1
- fi
+ # 读取当前的JSON配置文件并检查域名是否已存在
+ if grep -q "\"$new_domain\"" "$PHPCONFIG_FILE"; then
+ echo "域名 '$new_domain' 已存在!"
+ return 1
+ fi
- # 使用jq来处理JSON,添加新的域名到domains数组
- #jq --arg domain "$new_domain" '.domains += [$domain]' "$PHPCONFIG_FILE" >temp.json && mv temp.json "$PHPCONFIG_FILE"
- jq ".domains += [{\"domain\": \"$domain\", \"webip\": \"$webip\"}]" "$PHPCONFIG_FILE" >"$PHPCONFIG_FILE.tmp" && mv "$PHPCONFIG_FILE.tmp" "$PHPCONFIG_FILE"
- #echo "域名 '$new_domain' 添加成功!"
- return 0
+ # 使用jq来处理JSON,添加新的域名到domains数组
+ #jq --arg domain "$new_domain" '.domains += [$domain]' "$PHPCONFIG_FILE" >temp.json && mv temp.json "$PHPCONFIG_FILE"
+ jq ".domains += [{\"domain\": \"$domain\", \"webip\": \"$webip\"}]" "$PHPCONFIG_FILE" >"$PHPCONFIG_FILE.tmp" && mv "$PHPCONFIG_FILE.tmp" "$PHPCONFIG_FILE"
+ #echo "域名 '$new_domain' 添加成功!"
+ return 0
}
# 删除域名
delete_domain() {
- local domain_to_delete="$1"
+ local domain_to_delete="$1"
- # 初始化JSON文件(如果不存在的话)
- initialize_json
+ # 初始化JSON文件(如果不存在的话)
+ initialize_json
- # 读取当前的JSON配置文件并检查域名是否存在
- if ! grep -q "\"$domain_to_delete\"" "$PHPCONFIG_FILE"; then
- echo "域名 '$domain_to_delete' 不存在!"
- return 1
- fi
+ # 读取当前的JSON配置文件并检查域名是否存在
+ if ! grep -q "\"$domain_to_delete\"" "$PHPCONFIG_FILE"; then
+ echo "域名 '$domain_to_delete' 不存在!"
+ return 1
+ fi
- local webip=$(jq -r ".domains[] | select(.domain == \"$domain\") | .webip" "$PHPCONFIG_FILE")
- # 使用jq来处理JSON,删除指定的域名
- jq "del(.domains[] | select(.domain == \"$domain\"))" "$PHPCONFIG_FILE" >"$PHPCONFIG_FILE.tmp" && mv "$PHPCONFIG_FILE.tmp" "$PHPCONFIG_FILE"
- local domainPath="$installpath/domains/$domain"
- echo "正在删除域名相关服务,请等待..."
- rm -rf "$domainPath"
- resp=$(devil ssl www del $webip $domain)
- resp=$(devil www del $domain --remove)
- echo "已卸载域名[$domain_to_delete]相关服务!"
- return 0
+ local webip=$(jq -r ".domains[] | select(.domain == \"$domain\") | .webip" "$PHPCONFIG_FILE")
+ # 使用jq来处理JSON,删除指定的域名
+ jq "del(.domains[] | select(.domain == \"$domain\"))" "$PHPCONFIG_FILE" >"$PHPCONFIG_FILE.tmp" && mv "$PHPCONFIG_FILE.tmp" "$PHPCONFIG_FILE"
+ local domainPath="$installpath/domains/$domain"
+ echo "正在删除域名相关服务,请等待..."
+ rm -rf "$domainPath"
+ resp=$(devil ssl www del $webip $domain)
+ resp=$(devil www del $domain --remove)
+ echo "已卸载域名[$domain_to_delete]相关服务!"
+ return 0
}
# 判断domains数组是否为空
check_domains_empty() {
- initialize_json
+ initialize_json
- local domains_count=$(jq '.domains | length' "$PHPCONFIG_FILE")
+ local domains_count=$(jq '.domains | length' "$PHPCONFIG_FILE")
- if [ "$domains_count" -eq 0 ]; then
- return 0
- else
- return 1
- fi
+ if [ "$domains_count" -eq 0 ]; then
+ return 0
+ else
+ return 1
+ fi
}
print_domains() {
- yellow "----------------------------"
- green "域名\t\t|\t服务IP"
- yellow "----------------------------"
+ yellow "----------------------------"
+ green "域名\t\t|\t服务IP"
+ yellow "----------------------------"
- # 使用jq格式化输出
- jq -r '.domains[] | "\(.domain)\t|\(.webip)"' "$PHPCONFIG_FILE"
+ # 使用jq格式化输出
+ jq -r '.domains[] | "\(.domain)\t|\(.webip)"' "$PHPCONFIG_FILE"
}
delete_all_domains() {
- initialize_json
-
- jq -r '.domains[] | "\(.domain)\t\(.webip)"' "$PHPCONFIG_FILE" | while read -r domain webip; do
- echo "域名: $domain, 服务IP: $webip"
- delete_domain "$domain"
- done
+ initialize_json
+
+ jq -r '.domains[] | "\(.domain)\t\(.webip)"' "$PHPCONFIG_FILE" | while read -r domain webip; do
+ echo "域名: $domain, 服务IP: $webip"
+ delete_domain "$domain"
+ done
+}
+
+get_one_domain() {
+ initialize_json
+
+ local first_domain=$(jq -r '.domains[0].domain' "$PHPCONFIG_FILE")
+ echo "$first_domain"
+}
+
+download_from_net() {
+ local app=$1
+
+ case $app in
+ "alist")
+ download_from_github_release "AlistGo" "alist" "alist-freebsd-amd64.tar.gz"
+ ;;
+ "nezha-agent")
+ download_from_github_release "nezhahq" "agent" "nezha-agent_freebsd_amd64.zip"
+ ;;
+ "nezha-dashboard")
+ download_from_github_release "frankiejun" "freebsd-nezha" "dashboard.gz"
+ ;;
+ esac
+}
+
+check_update_from_net() {
+ local app=$1
+
+ case $app in
+ "alist")
+ local current_version=$(./alist version | grep "Version: v" | awk '{print $2}')
+ if ! check_from_github "AlistGo" "alist" "$current_version"; then
+ echo "未发现新版本!"
+ return 1
+ fi
+ download_from_github_release "AlistGo" "alist" "alist-freebsd-amd64.tar.gz"
+ ;;
+ "nezha-agent")
+ local current_version="v"$(./nezha-agent -v | awk '{print $3}')
+ if ! check_from_github "nezhahq" "agent" "$current_version"; then
+ echo "未发现新版本!"
+ return 1
+ fi
+ download_from_github_release "nezhahq" "agent" "nezha-agent_freebsd_amd64.zip"
+ ;;
+ "nezha-dashboard")
+ local current_version=$(./nezha-dashboard -v)
+ if ! check_from_github "frankiejun" "freebsd-nezha" "$current_version"; then
+ echo "未发现新版本!"
+ return 1
+ fi
+ download_from_github_release "frankiejun" "freebsd-nezha" "dashboard.gz"
+ ;;
+ esac
+}
+
+check_from_github() {
+ local user=$1
+ local repository=$2
+ local local_version="$3"
+ local url="https://github.com/${user}/${repository}"
+ local latestUrl="$url/releases/latest"
+
+ latest_version=$(curl -sL $latestUrl | sed -n 's/.*tag\/\(v[0-9.]*\).*/\1/p' | head -1)
+ #latest_version=$(curl -sL "https://api.github.com/repos/${user}/${repository}/releases/latest" | jq -r '.tag_name // empty')
+ if [[ "$local_version" != "$latest_version" ]]; then
+ echo "发现新版本: $latest_version,当前版本: $local_version, 正在更新..."
+ return 0
+ fi
+ return 1
+}
+
+download_allcode_from_github_release() {
+ local user=$1
+ local repository=$2
+
+ local url="https://github.com/${user}/${repository}"
+ local latestUrl="$url/releases/latest"
+ local latest_version=$(curl -sL $latestUrl | sed -n 's/.*tag\/\(v[0-9.]*\).*/\1/p' | head -1)
+ local download_url="${url}/archive/refs/tags/${latest_version}.zip"
+
+ curl -sL -o "${repository}-${latest_version}.zip" "$download_url"
+ if [[ ! -e "${repository}-${latest_version}.zip" || -n $(file "${repository}-${latest_version}.zip" | grep "text") ]]; then
+ echo "下载 ${repository}-${latest_version}.zip 文件失败!"
+ return 1
+ fi
+
+ # 原地解压缩
+ # 创建临时目录tmp
+ mkdir -p tmp
+ local clean_version="${latest_version#v}"
+ local target_dir="${repository}-${clean_version}"
+ #echo "target_dir: $target_dir"
+ case "${repository}-${latest_version}.zip" in
+ *.zip)
+ unzip -o "${repository}-${latest_version}.zip" -d tmp
+ # 使用cp命令替代mv命令,避免"Directory not empty"错误
+ cp -r "tmp/${target_dir}/"* tmp/
+ rm -rf "tmp/${target_dir}"
+ ;;
+ *.tar.gz)
+ tar -xzf "${repository}-${latest_version}.tar.gz" --xform="s|^[^/]*|tmp|"
+ ;;
+ *)
+ echo "不支持的文件格式"
+ return 1
+ ;;
+ esac
+ rm -rf "${repository}-${latest_version}.zip"
}
download_from_github_release() {
- local user=$1
- local repository=$2
- local package=$3
- local zippackage="$package.zip"
-
- local url="https://github.com/${user}/${repository}"
- local latestUrl="$url/releases/latest"
-
- local latest_version=$(curl -sL $latestUrl | sed -n 's/.*tag\/\(v[0-9.]*\).*/\1/p' | head -1)
-
- local download_url="${url}/releases/download/$latest_version/$zippackage"
- curl -sL -o "$zippackage" "$download_url"
- if [[ ! -e "$zippackage" || -n $(file "$zippackage" | grep "text") ]]; then
- echo "下载 $zippackage 文件失败!"
- return 1
- fi
- # 原地解压缩
- unzip -o "$zippackage" -d .
- if [[ $? -ne 0 ]]; then
- echo "解压 $zippackage 文件失败!"
- return 1
- fi
- rm -rf "$zippackage"
- echo "下载并解压 $zippackage 成功!"
- return 0
+ local user=$1
+ local repository=$2
+ local zippackage="$3"
+
+ local url="https://github.com/${user}/${repository}"
+ local latestUrl="$url/releases/latest"
+
+ local latest_version=$(curl -sL $latestUrl | sed -n 's/.*tag\/\(v[0-9.]*\).*/\1/p' | head -1)
+ #latest_version=$(curl -sL "https://api.github.com/repos/${user}/${repository}/releases/latest" | jq -r '.tag_name // empty')
+ local download_url="${url}/releases/download/$latest_version/$zippackage"
+ curl -sL -o "$zippackage" "$download_url"
+ if [[ ! -e "$zippackage" || -n $(file "$zippackage" | grep "text") ]]; then
+ echo "下载 $zippackage 文件失败!"
+ return 1
+ fi
+ # 原地解压缩
+ case "$zippackage" in
+ *.zip)
+ unzip -o "$zippackage" -d .
+ ;;
+ *.tar.gz | *.tgz)
+ tar -xzf "$zippackage"
+ ;;
+ *.tar.bz2 | *.tbz2)
+ tar -xjf "$zippackage"
+ ;;
+ *.tar.xz | *.txz)
+ tar -xJf "$zippackage"
+ ;;
+ *.gz)
+ gzip -d "$zippackage"
+ ;;
+ *.tar)
+ tar -xf "$zippackage"
+ ;;
+ *)
+ echo "不支持的文件格式: $zippackage"
+ return 1
+ ;;
+ esac
+
+ if [[ $? -ne 0 ]]; then
+ echo "解压 $zippackage 文件失败!"
+ return 1
+ fi
+
+ rm -rf "$zippackage"
+ echo "下载并解压 $zippackage 成功!"
+ return 0
+}
+
+clean_all_domains() {
+ echo "正在清理域名..."
+ output=$(devil www list)
+ if echo "$output" | grep -q "No elements to display"; then
+ echo "没有发现在用域名."
+ return 0
+ fi
+ domains=($(echo "$output" | awk 'NF && NR>2 {print $1}'))
+
+ for domain in "${domains[@]}"; do
+ devil www del $domain --remove
+ done
+ echo "域名清理完毕!"
+}
+
+create_default_domain() {
+ echo "正在创建默认域名..."
+ local domain=$(getUserDoMain)
+ domain="${domain,,}"
+ devil www add $domain php
+ echo "默认域名创建成功!"
+}
+
+clean_all_dns() {
+ echo "正在清理DNS..."
+ output=$(devil dns list)
+ if echo "$output" | grep -q "No elements to display"; then
+ echo "没有发现在用DNS."
+ return 0
+ fi
+ domains=($(echo "$output" | awk 'NF && NR>2 {print $1}'))
+
+ for domain in "${domains[@]}"; do
+ devil dns del $domain
+ done
+ echo "DNS清理完毕!"
+}
+
+show_ip_status() {
+ localIPs=()
+ useIPs=()
+ local hostname=$(hostname)
+ local host_number=$(echo "$hostname" | awk -F'[s.]' '{print $2}')
+ local hosts=("cache${host_number}.$(getDoMain)" "web${host_number}.$(getDoMain)" "$hostname")
+ local hostmain=$(getDoMain)
+ hostmain="${hostmain%.com}"
+ # 遍历主机名称数组
+ local i=0
+ for host in "${hosts[@]}"; do
+ ((i++))
+ # 获取 API 返回的数据
+ local response=$(curl -s "${baseurl}/api/getip?host=$host&type=$hostmain")
+
+ # 检查返回的结果是否包含 "not found"
+ if [[ "$response" =~ "not found" ]]; then
+ echo "未识别主机${host}, 请联系作者饭奇骏!"
+ return
+ fi
+ local ip=$(echo "$response" | awk -F "|" '{print $1 }')
+ local status=$(echo "$response" | awk -F "|" '{print $2 }')
+ localIPs+=("$ip")
+ if [[ "$status" == "Accessible" ]]; then
+ useIPs+=("$ip")
+ fi
+ printf "%-2d %-20s | %-15s | %-10s\n" $i "$host" "$ip" "$status"
+ done
+}
+
+stop_sing_box() {
+ cd ${installpath}/serv00-play/singbox
+ if [ -f killsing-box.sh ]; then
+ chmod 755 ./killsing-box.sh
+ ./killsing-box.sh
+ else
+ echo "请先安装serv00-play!!!"
+ return
+ fi
+ echo "已停掉sing-box!"
+}
+
+start_sing_box() {
+ cd ${installpath}/serv00-play/singbox
+
+ if [[ ! -e "singbox.json" ]]; then
+ red "请先进行配置!"
+ return 1
+ fi
+
+ if ! checkDownload "serv00sb"; then
+ return
+ fi
+ if ! checkDownload "cloudflared"; then
+ return
+ fi
+
+ if checkSingboxAlive; then
+ red "sing-box 已在运行,请勿重复操作!"
+ return 1
+ else #启动可能需要cloudflare,此处表示cloudflare和sb有一个不在线,所以干脆先杀掉再重启。
+ chmod 755 ./killsing-box.sh
+ ./killsing-box.sh
+ fi
+
+ if chmod +x start.sh && ! ./start.sh; then
+ red "sing-box启动失败!"
+ exit 1
+ fi
+ sleep 2
+ if checkProcAlive "serv00sb"; then
+ yellow "启动成功!"
+ else
+ red "启动失败!"
+ fi
+
+}
+
+checkCronNameStatus() {
+ if checkCronName $1; then
+ green "在线"
+ else
+ red "离线"
+ fi
+}
+checkCronName() {
+ local name=$1
+ if crontab -l | grep -q "$name"; then
+ return 0
+ else
+ return 1
+ fi
}
diff --git a/wxsend.sh b/wxsend.sh
old mode 100755
new mode 100644
index 40adade3..5211f57c
--- a/wxsend.sh
+++ b/wxsend.sh
@@ -3,22 +3,48 @@
text=$1
sendKey=${WXSENDKEY}
+wx_push_url=${WXPUSH_URL}
+wx_token=${WX_TOKEN}
title="msg_from_serv00-play"
URL="https://sctapi.ftqq.com/$sendKey.send?"
-if [[ -z ${sendKey} ]]; then
- echo "未配置微信推送的sendKey,通过 https://sct.ftqq.com/r/13223 注册并登录server酱,取得sendKey"
+if [[ -z "$1" ]]; then
+ echo "错误:未提供要发送的消息内容。"
+ echo "用法: $0 \"你的消息\""
+ exit 1
+fi
+
+if [[ -z "${wx_push_url}" ]]; then
+ if [[ -z ${sendKey} ]]; then
+ echo "未配置微信推送的sendKey,通过 https://sct.ftqq.com/r/13223 注册并登录server酱,取得sendKey"
+ else
+ res=$(timeout 20s curl -s -X POST $URL -d title=${title} -d desp="${text}")
+ if [ $? == 124 ]; then
+ echo "发送消息超时"
+ exit 1
+ fi
+
+ err=$(echo "$res" | jq -r ".data.error")
+ if [ "$err" == "SUCCESS" ]; then
+ echo "微信推送成功"
+ else
+ echo "微信推送失败, error:$err"
+ fi
+ fi
else
- res=$(timeout 20s curl -s -X POST $URL -d title=${title} -d desp="${text}")
- if [ $? == 124 ]; then
- echo "发送消息超时"
- exit 1
- fi
+ if [[ -z ${wx_token} ]]; then
+ echo "未配置wxpush微信推送的wx_token,请参考https://github.com/frankiejun/wxpush 获取wx_token"
+ else
+ res=$(timeout 20s curl -s -X POST "${wx_push_url}" -H "Authorization: $wx_token" -H "Content-Type: application/json" -d "{\"token\":\"${wx_token}\",\"title\":\"${title}\",\"content\":\"${text}\",\"contentType\":1,\"uids\":[],\"topicIds\":[]}")
+ if [ $? == 124 ]; then
+ echo "发送消息超时"
+ exit 1
+ fi
- err=$(echo "$res" | jq -r ".data.error")
- if [ "$err" == "SUCCESS" ]; then
- echo "微信推送成功"
- else
- echo "微信推送失败, error:$err"
- fi
+ if echo "$res" | grep -q "Successfully"; then
+ echo "微信推送成功"
+ else
+ echo "微信推送失败, res:$res"
+ fi
+ fi
fi