├── .github
└── workflows
│ └── main.yml
├── README.md
├── SFW电脑网页版(V1.11.7).7z
├── SSH.yml
├── app.js
├── index.html
├── kp.sh
├── sb.sh
├── sbwpph_amd64
├── sbwpph_arm64
├── sb官方客户端配置说明.txt
├── serv00.sh
├── serv00.yml
├── serv00keep.sh
├── sversion
├── version
└── workers_keep.js
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Parallel URL Fetch
2 |
3 | on:
4 | schedule:
5 | - cron: '*/10 * * * *' # 每10分钟执行一次(公开库每月2000分钟运行时长,每天64分钟)
6 | workflow_dispatch:
7 |
8 | jobs:
9 | fetch-urls:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch URLs in parallel
17 | # secrets设置,变量名称:http
18 | # 变量值要求:每个保活/up网页或每个重启/re网页之间用空格或者,或者,间隔开,网页前带http://
19 | # 变量值填写示例:http://保活或重启网页1 http://保活或重启网页2 http://保活或重启网页3 ………
20 | run: |
21 | IFS=$',, ' read -r -a http <<< "${{ secrets.http }}"
22 | echo "*****************************************************"
23 | echo "甬哥Github项目 :github.com/yonggekkk"
24 | echo "甬哥Blogger博客 :ygkkk.blogspot.com"
25 | echo "甬哥YouTube频道 :www.youtube.com/@ygkkk"
26 | echo "🎉Github定时运行serv00保活网页🎉"
27 | echo "请先确认已成功安装甬哥的serv00的SSH脚本或者Github/VPS/软路由脚本"
28 | echo "脚本地址:https://github.com/yonggekkk/sing-box-yg"
29 | echo "*****************************************************"
30 | for url in "${http[@]}"; do
31 | response=$(curl -sk "$url" || true)
32 | if [[ "$response" == *"网页保活启动"* ]]; then
33 | echo "🎉恭喜!$url ✅运行正常,成功拉起一次保活"
34 | elif [[ "$response" == *"主程序重启成功"* ]]; then
35 | echo "🎉恭喜!$url ✅运行正常,成功重启一次主程序"
36 | else
37 | echo "💥杯具!$url ❌运行失败,⚠️网页变量是否填写正确?或者Serv00炸了"
38 | fi
39 | done
40 | wait
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### 一、Sing-box-yg精装桶一键四协议共存脚本(VPS专用)
2 | ### 二、Serv00/Hostuno-sb-yg多平台一键三协议共存脚本(Serv00/Hostuno专用)
3 |
4 | ### 注:本项目分享订阅节点都为本地化生成,不使用节点转换、订阅器等第三方外链引用,无需担心节点订阅被外链作者查看
5 |
6 | ### 交流平台:[甬哥博客地址](https://ygkkk.blogspot.com)、[甬哥YouTube频道](https://www.youtube.com/@ygkkk)、[甬哥TG电报群组](https://t.me/+jZHc6-A-1QQ5ZGVl)、[甬哥TG电报频道](https://t.me/+DkC9ZZUgEFQzMTZl)
7 | --------------------------------------------------------------
8 |
9 | ### 一、Sing-box-yg精装桶小白专享一键四协议共存脚本(VPS专用)
10 |
11 | * 支持人气最高的四大协议:Vless-reality-vision、Vmess-ws(tls)/Argo、Hysteria-2、Tuic-v5
12 |
13 | * 支持纯IPV6、纯IPV4、双栈VPS,支持amd与arm架构,支持alpine系统,推荐使用最新的Ubuntu系统
14 |
15 | * 小白简单模式:无需域名证书,回车三次就安装完成,复制、扫描你要的节点配置
16 |
17 | #### 相关说明及注意点请查看[甬哥博客说明与Sing-box视频教程](https://ygkkk.blogspot.com/2023/10/sing-box-yg.html)
18 |
19 | #### 视频教程:
20 |
21 | [Sing-box精装桶小白一键脚本(一):配置文件通吃SFA/SFI/SFW三平台客户端,Argo隧道、双证书切换、域名分流](https://youtu.be/QwTapeVPeB0)
22 |
23 | [Sing-box精装桶小白一键脚本(二):纯IPV6 VPS搭建,CDN优选IP设置汇总,全平台多种客户端一个脚本全套带走](https://youtu.be/kmTgj1DundU)
24 |
25 | [Sing-box精装桶小白一键脚本(三):自建gitlab私有订阅链接一键同步推送全平台,WARP分流ChatGPT,SFW电脑客户端支持订阅链接](https://youtu.be/by7C2HU6-fU)
26 |
27 | [Sing-box精装桶小白一键脚本(四):vmess协议CDN优选IP多形态设置(详见说明图)](https://youtu.be/Qfm8DbLeb6w)
28 |
29 | [Sing-box精装桶小白一键脚本(五):集成oblivion warp免费vpn功能,本地WARP+赛风VPN切换分流(30个国家IP)](https://youtu.be/5Y6NPsYPws0)
30 |
31 | ### VPS专用一键脚本如下:快捷方式:```sb```
32 |
33 | ```
34 | bash <(wget -qO- https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/sb.sh)
35 | ```
36 | 或者
37 | ```
38 | bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/sb.sh)
39 | ```
40 |
41 | 更新中的ArgoSB脚本,专为Google IDX VPS设计:https://github.com/yonggekkk/ArgoSB
42 |
43 | ### Sing-box-yg脚本界面预览图(注:相关参数随意填写,仅供围观)
44 |
45 | 
46 |
47 | -----------------------------------------------------
48 |
49 | ### 二、Serv00/Hostuno一键三协议共存脚本(Serv00/Hostuno专用):
50 |
51 | * 目前免费Serv00使用代理脚本有被封账号的风险,收费版Hostuno不受影响,可正常使用
52 |
53 | * 切勿与其他Serv00脚本混用!!!
54 |
55 | * 修改自Serv00老王sing-box安装脚本,支持一键三协议:vless-reality、vmess-ws(argo)、hysteria2
56 |
57 | * 主要增加reality协议默认支持 CF vless/trojan 节点的proxyip以及非标端口的优选反代IP功能
58 |
59 | * 聚合通用节点分享,支持到22个节点:三协议各自三个IP,argo全覆盖13个端口节点,已添加不死优选IP
60 |
61 | #### 相关说明及注意点请查看[甬哥博客说明与Serv00视频教程](https://ygkkk.blogspot.com/2025/01/serv00.html)
62 |
63 | #### 视频教程:
64 |
65 | [Serv00免费代理脚本最终教程(一):独家支持三个IP自定义安装,支持Proxyip+反代IP、支持Argo临时/固定隧道+CDN回源;支持五个节点的Sing-box与Clash订阅配置输出](https://youtu.be/2VF9D6z2z7w)
66 |
67 | [Serv00免费代理脚本最终教程(二):Serv00不必再登录SSH了,部署保活融为一体,独家支持Github、VPS、软路由多平台多账户通用部署,四大方案总有一款适合你](https://youtu.be/rYeX1iU_iZ0)
68 |
69 | [Serv00免费代理脚本最终教程(三):多功能网页生成【保活+重启+重置端口+查看订阅节点】、随意重置端口功能;Github+Workers自动执行保活功能任你选!](https://youtu.be/9uCfFNnjNc0)
70 |
71 | [Serv00免费代理脚本最终教程(四):重大更新!支持Argo临时/固定隧道相互切换,实时更新节点信息;完美适配Serv00收费版Hostuno.com](https://youtu.be/XN6_vpz1NhE)
72 |
73 | [Serv00免费代理脚本最终教程(五):Github、VPS、软路由多平台脚本大更新!支持多功能网页,Cron内射保活+网页外射保活,任你选](https://youtu.be/tKaBdbU4G4s)
74 |
75 | ### Serv00/Hostuno-sb-yg一键脚本
76 |
77 | * Argo高度自定义:可以重置临时隧道; 可以继续使用上回的固定隧道; 也可以更换固定隧道的域名或token
78 |
79 | ```
80 | bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00.sh)
81 | ```
82 |
83 | #### Serv00/Hostuno-sb-yg脚本界面预览图,仅限方案一的SSH端安装脚本(注:仅供围观)
84 | 
85 |
86 |
87 | -----------------------------------------------------
88 | ### 感谢支持!微信打赏甬哥侃侃侃ygkkk
89 | 
90 |
91 | ---------------------------------------
92 | ### 感谢你右上角的star🌟
93 | [](https://starchart.cc/yonggekkk/sing-box-yg)
94 |
95 | ---------------------------------------
96 | #### 声明:所有代码来源于Github社区与ChatGPT的整合,[老王eooce](https://github.com/eooce/Sing-box/blob/test/sb_00.sh)、[frankiejun](https://github.com/frankiejun/serv00-play/blob/main/start.sh)
97 |
--------------------------------------------------------------------------------
/SFW电脑网页版(V1.11.7).7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonggekkk/sing-box-yg/03a0ecc9c7e97b5e86e1a35b800d06889503ac17/SFW电脑网页版(V1.11.7).7z
--------------------------------------------------------------------------------
/SSH.yml:
--------------------------------------------------------------------------------
1 | name: Keep Servers serv00
2 | on:
3 | schedule:
4 | - cron: '0 15 */8 * *'
5 | workflow_dispatch:
6 |
7 | jobs:
8 | keep_servers_alive:
9 | runs-on: ubuntu-latest
10 | env:
11 | ACCOUNTS: >
12 | [
13 | {"SSH_USER":"123456789", "SSH_PASS":"123456", "HOST":"sxxx.serv00.com"}
14 | ]
15 | steps:
16 | - name: Checkout Repository
17 | uses: actions/checkout@v4.2.2
18 |
19 | - name: Install required packages
20 | run: |
21 | sudo apt-get update
22 | sudo apt-get install -y sshpass jq
23 |
24 | - name: Process each account
25 | run: |
26 | echo "*****************************************************"
27 | echo "*****************************************************"
28 | echo "甬哥Github项目 :github.com/yonggekkk"
29 | echo "甬哥Blogger博客 :ygkkk.blogspot.com"
30 | echo "甬哥YouTube频道 :www.youtube.com/@ygkkk"
31 | echo "vps服务器远程登录一次SSH脚本【Github】"
32 | echo "*****************************************************"
33 | echo "*****************************************************"
34 | count=0
35 | for account in $(echo "${ACCOUNTS}" | jq -c '.[]'); do
36 | count=$((count+1))
37 | SSH_USER=$(echo $account | jq -r '.SSH_USER')
38 | SSH_PASS=$(echo $account | jq -r '.SSH_PASS')
39 | HOST=$(echo $account | jq -r '.HOST')
40 | if sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" -q exit; then
41 | echo "🎉恭喜!✅第【$count】台服务器连接成功!🚀服务器地址:$HOST ,账户名:$SSH_USER"
42 | else
43 | echo "===================================================="
44 | echo "💥杯具!❌第【$count】台服务器连接失败!🚀服务器地址:$HOST ,账户名:$SSH_USER"
45 | echo "⚠️可能账号名、密码、服务器名称输入错误,或者当前服务器在维护中"
46 | echo "===================================================="
47 | fi
48 | sleep 10
49 | done
50 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | const express = require("express");
3 | const { spawn, exec } = require("child_process");
4 | const app = express();
5 | app.use(express.json());
6 | const commandToRun = "cd ~ && bash serv00keep.sh";
7 | function runCustomCommand() {
8 | exec(commandToRun, (err, stdout, stderr) => {
9 | if (err) console.error("执行错误:", err);
10 | else console.log("执行成功:", stdout);
11 | });
12 | }
13 | app.get("/up", (req, res) => {
14 | runCustomCommand();
15 | res.type("html").send("
Serv00-name服务器网页保活启动:Serv00-name!UP!UP!UP!
");
16 | });
17 | app.get("/re", (req, res) => {
18 | const additionalCommands = `
19 | USERNAME=$(whoami | tr '[:upper:]' '[:lower:]')
20 | FULL_PATH="/home/\${USERNAME}/domains/\${USERNAME}.serv00.net/logs"
21 | cd "\$FULL_PATH"
22 | pkill -f 'run -c con' || echo "无进程可终止,准备执行重启……"
23 | sbb="\$(cat sb.txt 2>/dev/null)"
24 | nohup ./"\$sbb" run -c config.json >/dev/null 2>&1 &
25 | sleep 2
26 | (cd ~ && bash serv00keep.sh >/dev/null 2>&1) &
27 | echo '主程序重启成功,请检测三个主节点是否可用,如不可用,可再次刷新重启网页或者重置端口'
28 | `;
29 | exec(additionalCommands, (err, stdout, stderr) => {
30 | console.log('stdout:', stdout);
31 | console.error('stderr:', stderr);
32 | if (err) {
33 | return res.status(500).send(`错误:${stderr || stdout}`);
34 | }
35 | res.type('text').send(stdout);
36 | });
37 | });
38 |
39 | const changeportCommands = "cd ~ && bash webport.sh";
40 | function runportCommand() {
41 | exec(changeportCommands, { maxBuffer: 1024 * 1024 * 10 }, (err, stdout, stderr) => {
42 | console.log('stdout:', stdout);
43 | console.error('stderr:', stderr);
44 | if (err) {
45 | console.error('Execution error:', err);
46 | return res.status(500).send(`错误:${stderr || stdout}`);
47 | }
48 | if (stderr) {
49 | console.error('stderr output:', stderr);
50 | return res.status(500).send(`stderr: ${stderr}`);
51 | }
52 | res.type('text').send(stdout);
53 | });
54 | }
55 | app.get("/rp", (req, res) => {
56 | runportCommand();
57 | res.type("html").send("重置三个节点端口完成!请立即关闭本网页并稍等20秒,将主页后缀改为 /list/你的uuid 可查看更新端口后的节点及订阅信息
");
58 | });
59 | app.get("/list/key", (req, res) => {
60 | const listCommands = `
61 | USERNAME=$(whoami | tr '[:upper:]' '[:lower:]')
62 | USERNAME1=$(whoami)
63 | FULL_PATH="/home/\${USERNAME1}/domains/\${USERNAME}.serv00.net/logs/list.txt"
64 | cat "\$FULL_PATH"
65 | `;
66 | exec(listCommands, (err, stdout, stderr) => {
67 | if (err) {
68 | console.error(`路径验证失败: ${stderr}`);
69 | return res.status(404).send(stderr);
70 | }
71 | res.type('text').send(stdout);
72 | });
73 | });
74 |
75 | app.get("/jc", (req, res) => {
76 | const ps = spawn("ps", ["aux"]);
77 | res.type("text");
78 | ps.stdout.on("data", (data) => res.write(data));
79 | ps.stderr.on("data", (data) => res.write(`Error: ${data}`));
80 | ps.on("close", (code) => {
81 | if (code !== 0) {
82 | res.status(500).send(`ps aux 进程退出,错误码: ${code}`);
83 | } else {
84 | res.end();
85 | }
86 | });
87 | });
88 |
89 | app.use((req, res) => {
90 | res.status(404).send('请在浏览器地址:http://where.name.serv00.net 后面加三种路径功能:/up是保活,/re是重启,/rp是重置节点端口,/jc是查看当前系统进程,/list/你的uuid 是节点及订阅信息');
91 | });
92 | setInterval(runCustomCommand, (2 * 60 + 15) * 60 * 1000);
93 | app.listen(3000, () => {
94 | console.log("服务器运行在端口 3000");
95 | runCustomCommand();
96 | });
97 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Serv00-sb-yg本地SSH专用一键脚本:https://github.com/yonggekkk/sing-box-yg
6 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
===========================================
76 |
甬哥侃侃侃ygkkk Serv00-sb-yg一键三协议共存脚本
77 |
===========================================
78 |
YouTubu视频教程 点击进入.
79 |
Github项目地址 点击进入.
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/kp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 定时设置:*/10 * * * * /bin/bash /root/kp.sh 每10分钟运行一次
3 | # 如果你已安装了Serv00本地SSH脚本,不要再运行此脚本部署了,这样会造成进程爆满,必须二选一!
4 | # serv00变量添加规则:
5 | # 如使用保活网页,请不要启用cron,以防止cron与网页保活重复运行造成进程爆满
6 | # RES(必填):n表示每次不重置部署,y表示每次重置部署。REP(必填):n表示不重置随机端口(三个端口留空),y表示重置端口(三个端口留空)。SSH_USER(必填)表示serv00账号名。SSH_PASS(必填)表示serv00密码。REALITY表示reality域名(留空表示serv00官方域名:你serv00账号名.serv00.net)。SUUID表示uuid(留空表示随机uuid)。TCP1_PORT表示vless的tcp端口(留空表示随机tcp端口)。TCP2_PORT表示vmess的tcp端口(留空表示随机tcp端口)。UDP_PORT表示hy2的udp端口(留空表示随机udp端口)。HOST(必填)表示登录serv00服务器域名。ARGO_DOMAIN表示argo固定域名(留空表示临时域名)。ARGO_AUTH表示argo固定域名token(留空表示临时域名)。
7 | # 必填变量:RES、REP、SSH_USER、SSH_PASS、HOST
8 | # 注意[]"",:这些符号不要乱删,按规律对齐
9 | # 每行一个{serv00服务器},一个服务也可,末尾用,间隔,最后一个服务器末尾无需用,间隔
10 | ACCOUNTS='[
11 | {"RES":"n", "REP":"n", "SSH_USER":"你的serv00账号名", "SSH_PASS":"你的serv00账号密码", "REALITY":"你serv00账号名.serv00.net", "SUUID":"自设UUID", "TCP1_PORT":"vless的tcp端口", "TCP2_PORT":"vmess的tcp端口", "UDP_PORT":"hy2的udp端口", "HOST":"s1.serv00.com", "ARGO_DOMAIN":"", "ARGO_AUTH":""},
12 | {"RES":"y", "REP":"y", "SSH_USER":"123456", "SSH_PASS":"7890000", "REALITY":"time.is", "SUUID":"73203ee6-b3fa-4a3d-b5df-6bb2f55073ad", "TCP1_PORT":"", "TCP2_PORT":"", "UDP_PORT":"", "HOST":"s16.serv00.com", "ARGO_DOMAIN":"你的argo固定域名", "ARGO_AUTH":"eyJhIjoiOTM3YzFjYWI88552NTFiYTM4ZTY0ZDQzRmlNelF0TkRBd1pUQTRNVEJqTUdVeCJ9"}
13 | ]'
14 | run_remote_command() {
15 | local RES=$1
16 | local REP=$2
17 | local SSH_USER=$3
18 | local SSH_PASS=$4
19 | local REALITY=${5}
20 | local SUUID=$6
21 | local TCP1_PORT=$7
22 | local TCP2_PORT=$8
23 | local UDP_PORT=$9
24 | local HOST=${10}
25 | local ARGO_DOMAIN=${11}
26 | local ARGO_AUTH=${12}
27 | if [ -z "${ARGO_DOMAIN}" ]; then
28 | echo "Argo域名为空,申请Argo临时域名"
29 | else
30 | echo "Argo已设置固定域名:${ARGO_DOMAIN}"
31 | fi
32 | remote_command="export reym=$REALITY UUID=$SUUID vless_port=$TCP1_PORT vmess_port=$TCP2_PORT hy2_port=$UDP_PORT reset=$RES resport=$REP ARGO_DOMAIN=${ARGO_DOMAIN} ARGO_AUTH=${ARGO_AUTH} && bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00keep.sh)"
33 | echo "Executing remote command on $HOST as $SSH_USER with command: $remote_command"
34 | sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" "$remote_command"
35 | }
36 | if cat /etc/issue /proc/version /etc/os-release 2>/dev/null | grep -q -E -i "openwrt"; then
37 | opkg update
38 | opkg install sshpass curl jq
39 | else
40 | if [ -f /etc/debian_version ]; then
41 | package_manager="apt-get install -y"
42 | apt-get update >/dev/null 2>&1
43 | elif [ -f /etc/redhat-release ]; then
44 | package_manager="yum install -y"
45 | elif [ -f /etc/fedora-release ]; then
46 | package_manager="dnf install -y"
47 | elif [ -f /etc/alpine-release ]; then
48 | package_manager="apk add"
49 | fi
50 | $package_manager sshpass curl jq cron >/dev/null 2>&1 &
51 | fi
52 | echo "*****************************************************"
53 | echo "*****************************************************"
54 | echo "甬哥Github项目 :github.com/yonggekkk"
55 | echo "甬哥Blogger博客 :ygkkk.blogspot.com"
56 | echo "甬哥YouTube频道 :www.youtube.com/@ygkkk"
57 | echo "自动远程部署Serv00三合一协议脚本【VPS+软路由】"
58 | echo "版本:V25.3.26"
59 | echo "*****************************************************"
60 | echo "*****************************************************"
61 | count=0
62 | for account in $(echo "${ACCOUNTS}" | jq -c '.[]'); do
63 | count=$((count+1))
64 | RES=$(echo $account | jq -r '.RES')
65 | REP=$(echo $account | jq -r '.REP')
66 | SSH_USER=$(echo $account | jq -r '.SSH_USER')
67 | SSH_PASS=$(echo $account | jq -r '.SSH_PASS')
68 | REALITY=$(echo $account | jq -r '.REALITY')
69 | SUUID=$(echo $account | jq -r '.SUUID')
70 | TCP1_PORT=$(echo $account | jq -r '.TCP1_PORT')
71 | TCP2_PORT=$(echo $account | jq -r '.TCP2_PORT')
72 | UDP_PORT=$(echo $account | jq -r '.UDP_PORT')
73 | HOST=$(echo $account | jq -r '.HOST')
74 | ARGO_DOMAIN=$(echo $account | jq -r '.ARGO_DOMAIN')
75 | ARGO_AUTH=$(echo $account | jq -r '.ARGO_AUTH')
76 | if sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" -q exit; then
77 | echo "🎉恭喜!✅第【$count】台服务器连接成功!🚀服务器地址:$HOST ,账户名:$SSH_USER"
78 | if [ -z "${ARGO_DOMAIN}" ]; then
79 | check_process="ps aux | grep '[c]onfig' > /dev/null && ps aux | grep [l]ocalhost:$TCP2_PORT > /dev/null"
80 | else
81 | check_process="ps aux | grep '[c]onfig' > /dev/null && ps aux | grep '[t]oken $ARGO_AUTH' > /dev/null"
82 | fi
83 | if ! sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" "$check_process" || [[ "$RES" =~ ^[Yy]$ ]]; then
84 | echo "⚠️检测到主进程或者argo进程未启动,或者执行重置"
85 | echo "⚠️现在开始修复或重置部署……请稍等"
86 | output=$(run_remote_command "$RES" "$REP" "$SSH_USER" "$SSH_PASS" "${REALITY}" "$SUUID" "$TCP1_PORT" "$TCP2_PORT" "$UDP_PORT" "$HOST" "${ARGO_DOMAIN}" "${ARGO_AUTH}")
87 | echo "远程命令执行结果:$output"
88 | else
89 | echo "🎉恭喜!✅检测到所有进程正常运行中 "
90 | SSH_USER_LOWER=$(echo "$SSH_USER" | tr '[:upper:]' '[:lower:]')
91 | sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" "
92 | echo \"配置显示如下:\"
93 | cat domains/${SSH_USER_LOWER}.serv00.net/logs/list.txt
94 | echo \"====================================================\""
95 | fi
96 | else
97 | echo "===================================================="
98 | echo "💥杯具!❌第【$count】台服务器连接失败!🚀服务器地址:$HOST ,账户名:$SSH_USER"
99 | echo "⚠️可能账号名、密码、服务器名称输入错误,或者当前服务器在维护中"
100 | echo "===================================================="
101 | fi
102 | done
103 |
--------------------------------------------------------------------------------
/sbwpph_amd64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonggekkk/sing-box-yg/03a0ecc9c7e97b5e86e1a35b800d06889503ac17/sbwpph_amd64
--------------------------------------------------------------------------------
/sbwpph_arm64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonggekkk/sing-box-yg/03a0ecc9c7e97b5e86e1a35b800d06889503ac17/sbwpph_arm64
--------------------------------------------------------------------------------
/sb官方客户端配置说明.txt:
--------------------------------------------------------------------------------
1 | sing-box官方SFA/SFI/SFW客户端配置简要说明
2 | 小白关键点操作指南 V23.11.15(不定时更新)
3 |
4 | 注意:小白在自己的sing-box配置文件中,只要改动节点区与分流组这两块区域即可
5 | ------------------------------------------------------------------------------------
6 | 节点区
7 | ------------------------------------------------------------------------------------
8 | 一、vless-reality-vision节点
9 | ------------------------------------------------------------------------------------
10 | {
11 | "type": "vless",
12 | "tag": "vless-sb", 自定义节点名称
13 | "server": "1.2.3.4", 服务器本地ip
14 | "server_port": 12345, 自定义的端口
15 | "uuid": "658ff7f4-0448-4368-a104-c3108517f56a", 自定义的uuid
16 | "flow": "xtls-rprx-vision",
17 | "tls": {
18 | "enabled": true,
19 | "server_name": "www.yahoo.com", 自定义的第三方偷域名
20 | "utls": {
21 | "enabled": true,
22 | "fingerprint": "chrome"
23 | },
24 | "reality": {
25 | "enabled": true,
26 | "public_key": "oBwBeiq8MjOqHS0fTXm39gRM_fdXgbAvtEWfAaW", 自定义的public-key
27 | "short_id": "91b4db47" 自定义的short-id
28 | }
29 | }
30 | },
31 |
32 |
33 | ------------------------------------------------------------------------------------
34 | 二、vmess-ws(tls)+argo节点
35 | ------------------------------------------------------------------------------------
36 | {
37 | "server": "1.2.3.4", 服务器本地ip、解析的域名、优选IP、优选域名
38 | "server_port": 12345, 自定义的端口,vps-cdn与argo-cdn,注意13个端口变化
39 | "tag": "vmess-sb", 自定义节点名称
40 | "tls": {
41 | "enabled": true, tls开启:true tls关闭:false
42 | "server_name": "yg.ygkkk.eu.org", tls开启:解析的域名或者argo域名
43 | "insecure": false,
44 | "utls": {
45 | "enabled": true,
46 | "fingerprint": "chrome"
47 | }
48 | },
49 | "transport": {
50 | "headers": {
51 | "Host": [
52 | "yg.ygkkk.eu.org" 解析的域名或者argo域名
53 | ]
54 | },
55 | "path": "658ff7f4-0448-4368-a104-c3108517f56a-vm", 自定义的uuid值-vm
56 | "type": "ws"
57 | },
58 | "type": "vmess",
59 | "security": "auto",
60 | "uuid": "658ff7f4-0448-4368-a104-c3108517f56a" 自定义的uuid
61 | },
62 |
63 | ------------------------------------------------------------------------------------
64 | 三、hysteria2节点
65 | ------------------------------------------------------------------------------------
66 | {
67 | "type": "hysteria2",
68 | "tag": "hy2-sb", 自定义节点名称
69 | "server": "1.2.3.4", 自签证书:服务器本地ip 域名证书:解析的域名
70 | "server_port": 12345, 自定义的端口
71 | "password": "658ff7f4-0448-4368-a104-c3108517f56a", 自定义的uuid
72 | "tls": {
73 | "enabled": true,
74 | "server_name": "www.bing.com", 自签证书:www.bing.com 域名证书:解析的域名
75 | "insecure": true, 自签证书:true 域名证书:false
76 | "alpn": [
77 | "h3"
78 | ]
79 | }
80 | },
81 |
82 |
83 | ------------------------------------------------------------------------------------
84 | 四、tuic5节点
85 | ------------------------------------------------------------------------------------
86 | {
87 | "type":"tuic",
88 | "tag": "tuic5-sb", 自定义节点名称
89 | "server": "1.2.3.4", 自签证书:服务器本地ip 域名证书:解析的域名
90 | "server_port": 12345, 自定义的端口
91 | "uuid": "658ff7f4-0448-4368-a104-c3108517f56a", 自定义的uuid
92 | "password": "658ff7f4-0448-4368-a104-c3108517f56a", 自定义的uuid
93 | "congestion_control": "bbr",
94 | "udp_relay_mode": "native",
95 | "udp_over_stream": false,
96 | "zero_rtt_handshake": false,
97 | "heartbeat": "10s",
98 | "tls":{
99 | "enabled": true,
100 | "server_name": "www.bing.com", 自签证书:www.bing.com 域名证书:解析的域名
101 | "insecure": true, 自签证书:true 域名证书:false
102 | "alpn": [
103 | "h3"
104 | ]
105 | }
106 | },
107 |
108 | ------------------------------------------------------------------------------------
109 | 五、cf-vless(tls)节点
110 | ------------------------------------------------------------------------------------
111 | {
112 | "server": "1.2.3.4", 优选IP、优选域名
113 | "server_port": 12345, 自定义的端口,注意13个端口变化
114 | "tag": "cf-vless-sb", 自定义节点名称
115 | "tls": {
116 | "enabled": true, tls开启:true tls关闭:false
117 | "server_name": "yg.ygkkk.eu.org", tls开启:pages域名或者自定义域名
118 | "insecure": false,
119 | "utls": {
120 | "enabled": true,
121 | "fingerprint": "chrome"
122 | }
123 | },
124 | "transport": {
125 | "headers": {
126 | "Host": [
127 | "yg.ygkkk.eu.org" workers、pages域名或者自定义域名
128 | ]
129 | },
130 | "path": "/?ed=2048", path路径:/?ed=2048
131 | "type": "ws"
132 | },
133 | "type": "vless",
134 | "uuid": "658ff7f4-0448-4368-a104-c3108517f56a" 自定义的uuid
135 | },
136 |
137 |
138 |
139 | ------------------------------------------------------------------------------------
140 | 分流组:共两组,分为手动选择select与自动选择auto,每组节点可按需求自行增减,确保出现的自定义节点名称可以在节点区中查找到
141 | ------------------------------------------------------------------------------------
142 | 手动选择select
143 | {
144 | "tag": "select",
145 | "type": "selector",
146 | "default": "auto",
147 | "outbounds": [
148 | "auto",
149 | "vless-sb", 自定义节点名称
150 | "vmess-sb", 自定义节点名称
151 | "hy2-sb", 自定义节点名称
152 | "tuic5-sb", 自定义节点名称
153 | "cf-vless-sb" 自定义节点名称
154 | ………… …………
155 | ]
156 | },
157 | ------------------------------------------------------------------------------------
158 | 自动选择auto
159 | {
160 | "tag": "auto",
161 | "type": "urltest",
162 | "outbounds": [
163 | "vless-sb", 自定义节点名称
164 | "vmess-sb", 自定义节点名称
165 | "hy2-sb", 自定义节点名称
166 | "tuic5-sb", 自定义节点名称
167 | "cf-vless-sb" 自定义节点名称
168 | ……………… …………
169 | ]
170 | },
171 | ------------------------------------------------------------------------------------
172 |
--------------------------------------------------------------------------------
/serv00.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | re="\033[0m"
3 | red="\033[1;91m"
4 | green="\e[1;32m"
5 | yellow="\e[1;33m"
6 | purple="\e[1;35m"
7 | red() { echo -e "\e[1;91m$1\033[0m"; }
8 | green() { echo -e "\e[1;32m$1\033[0m"; }
9 | yellow() { echo -e "\e[1;33m$1\033[0m"; }
10 | purple() { echo -e "\e[1;35m$1\033[0m"; }
11 | reading() { read -p "$(red "$1")" "$2"; }
12 | USERNAME=$(whoami | tr '[:upper:]' '[:lower:]')
13 | snb=$(hostname | cut -d. -f1)
14 | nb=$(hostname | cut -d '.' -f 1 | tr -d 's')
15 | HOSTNAME=$(hostname)
16 | hona=$(hostname | cut -d. -f2)
17 | if [ "$hona" = "serv00" ]; then
18 | address="serv00.net"
19 | keep_path="${HOME}/domains/${snb}.${USERNAME}.serv00.net/public_nodejs"
20 | [ -d "$keep_path" ] || mkdir -p "$keep_path"
21 | else
22 | address="useruno.com"
23 | fi
24 | WORKDIR="${HOME}/domains/${USERNAME}.${address}/logs"
25 | devil www add ${USERNAME}.${address} php > /dev/null 2>&1
26 | FILE_PATH="${HOME}/domains/${USERNAME}.${address}/public_html"
27 | [ -d "$FILE_PATH" ] || mkdir -p "$FILE_PATH"
28 | [ -d "$WORKDIR" ] || (mkdir -p "$WORKDIR" && chmod 777 "$WORKDIR")
29 | devil binexec on >/dev/null 2>&1
30 | curl -sk "http://${snb}.${USERNAME}.${hona}.net/up" > /dev/null 2>&1
31 |
32 | read_ip() {
33 | cat ip.txt
34 | reading "请输入上面三个IP中的任意一个 (建议默认回车自动选择可用IP): " IP
35 | if [[ -z "$IP" ]]; then
36 | IP=$(grep -m 1 "可用" ip.txt | awk -F ':' '{print $1}')
37 | if [ -z "$IP" ]; then
38 | IP=$(okip)
39 | if [ -z "$IP" ]; then
40 | IP=$(head -n 1 ip.txt | awk -F ':' '{print $1}')
41 | fi
42 | fi
43 | fi
44 | echo "$IP" > $WORKDIR/ipone.txt
45 | IP=$(<$WORKDIR/ipone.txt)
46 | green "你选择的IP为: $IP"
47 | }
48 |
49 | read_uuid() {
50 | reading "请输入统一的uuid密码 (建议回车默认随机): " UUID
51 | if [[ -z "$UUID" ]]; then
52 | UUID=$(uuidgen -r)
53 | fi
54 | echo "$UUID" > $WORKDIR/UUID.txt
55 | UUID=$(<$WORKDIR/UUID.txt)
56 | green "你的uuid为: $UUID"
57 | }
58 |
59 | read_reym() {
60 | yellow "方式一:(推荐)使用Serv00/Hostuno自带域名,不支持proxyip功能:输入回车"
61 | yellow "方式二:使用CF域名(blog.cloudflare.com),支持proxyip+非标端口反代ip功能:输入s"
62 | yellow "方式三:支持其他域名,注意要符合reality域名规则:输入域名"
63 | reading "请输入reality域名 【请选择 回车 或者 s 或者 输入域名】: " reym
64 | if [[ -z "$reym" ]]; then
65 | reym=$USERNAME.${address}
66 | elif [[ "$reym" == "s" || "$reym" == "S" ]]; then
67 | reym=blog.cloudflare.com
68 | fi
69 | echo "$reym" > $WORKDIR/reym.txt
70 | reym=$(<$WORKDIR/reym.txt)
71 | green "你的reality域名为: $reym"
72 | }
73 |
74 | resallport(){
75 | portlist=$(devil port list | grep -E '^[0-9]+[[:space:]]+[a-zA-Z]+' | sed 's/^[[:space:]]*//')
76 | if [[ -z "$portlist" ]]; then
77 | yellow "无端口"
78 | else
79 | while read -r line; do
80 | port=$(echo "$line" | awk '{print $1}')
81 | port_type=$(echo "$line" | awk '{print $2}')
82 | yellow "删除端口 $port ($port_type)"
83 | devil port del "$port_type" "$port"
84 | done <<< "$portlist"
85 | fi
86 | check_port
87 | if [[ -e $WORKDIR/config.json ]]; then
88 | hyp=$(jq -r '.inbounds[0].listen_port' $WORKDIR/config.json)
89 | vlp=$(jq -r '.inbounds[3].listen_port' $WORKDIR/config.json)
90 | vmp=$(jq -r '.inbounds[4].listen_port' $WORKDIR/config.json)
91 | purple "检测到Serv00/Hostuno-sb-yg脚本已安装,执行端口替换,请稍等……"
92 | sed -i '' "12s/$hyp/$hy2_port/g" $WORKDIR/config.json
93 | sed -i '' "33s/$hyp/$hy2_port/g" $WORKDIR/config.json
94 | sed -i '' "54s/$hyp/$hy2_port/g" $WORKDIR/config.json
95 | sed -i '' "75s/$vlp/$vless_port/g" $WORKDIR/config.json
96 | sed -i '' "102s/$vmp/$vmess_port/g" $WORKDIR/config.json
97 | if [ "$hona" = "serv00" ]; then
98 | sed -i '' -e "17s|'$vlp'|'$vless_port'|" serv00keep.sh
99 | sed -i '' -e "18s|'$vmp'|'$vmess_port'|" serv00keep.sh
100 | sed -i '' -e "19s|'$hyp'|'$hy2_port'|" serv00keep.sh
101 | fi
102 | resservsb
103 | green "端口替换完成!"
104 | ps aux | grep '[r]un -c con' > /dev/null && green "主进程启动成功,单节点用户修改下客户端三协议端口" || yellow "Sing-box主进程启动失败"
105 | if [ -f "$WORKDIR/boot.log" ]; then
106 | ps aux | grep '[t]unnel --u' > /dev/null && green "Argo临时隧道已启动,临时域名可能已变更" || yellow "Argo临时隧道启动失败"
107 | else
108 | ps aux | grep '[t]unnel --n' > /dev/null && green "Argo固定隧道已启动" || yellow "Argo固定隧道启动失败,请先在CF更改隧道端口:$vmess_port,再重启下Argo隧道"
109 | fi
110 | cd $WORKDIR
111 | showchangelist
112 | cd
113 | fi
114 | }
115 |
116 | check_port () {
117 | port_list=$(devil port list)
118 | tcp_ports=$(echo "$port_list" | grep -c "tcp")
119 | udp_ports=$(echo "$port_list" | grep -c "udp")
120 | if [[ $tcp_ports -ne 2 || $udp_ports -ne 1 ]]; then
121 | red "端口数量不符合要求,正在调整..."
122 |
123 | if [[ $tcp_ports -gt 2 ]]; then
124 | tcp_to_delete=$((tcp_ports - 2))
125 | echo "$port_list" | awk '/tcp/ {print $1, $2}' | head -n $tcp_to_delete | while read port type; do
126 | devil port del $type $port
127 | green "已删除TCP端口: $port"
128 | done
129 | fi
130 | if [[ $udp_ports -gt 1 ]]; then
131 | udp_to_delete=$((udp_ports - 1))
132 | echo "$port_list" | awk '/udp/ {print $1, $2}' | head -n $udp_to_delete | while read port type; do
133 | devil port del $type $port
134 | green "已删除UDP端口: $port"
135 | done
136 | fi
137 | if [[ $tcp_ports -lt 2 ]]; then
138 | tcp_ports_to_add=$((2 - tcp_ports))
139 | tcp_ports_added=0
140 | while [[ $tcp_ports_added -lt $tcp_ports_to_add ]]; do
141 | tcp_port=$(shuf -i 10000-65535 -n 1)
142 | result=$(devil port add tcp $tcp_port 2>&1)
143 | if [[ $result == *"succesfully"* ]]; then
144 | green "已添加TCP端口: $tcp_port"
145 | if [[ $tcp_ports_added -eq 0 ]]; then
146 | tcp_port1=$tcp_port
147 | else
148 | tcp_port2=$tcp_port
149 | fi
150 | tcp_ports_added=$((tcp_ports_added + 1))
151 | else
152 | yellow "端口 $tcp_port 不可用,尝试其他端口..."
153 | fi
154 | done
155 | fi
156 | if [[ $udp_ports -lt 1 ]]; then
157 | while true; do
158 | udp_port=$(shuf -i 10000-65535 -n 1)
159 | result=$(devil port add udp $udp_port 2>&1)
160 | if [[ $result == *"succesfully"* ]]; then
161 | green "已添加UDP端口: $udp_port"
162 | break
163 | else
164 | yellow "端口 $udp_port 不可用,尝试其他端口..."
165 | fi
166 | done
167 | fi
168 | #green "端口已调整完成,将断开ssh连接,请重新连接shh重新执行脚本"
169 | #devil binexec on >/dev/null 2>&1
170 | #kill -9 $(ps -o ppid= -p $$) >/dev/null 2>&1
171 | sleep 3
172 | port_list=$(devil port list)
173 | tcp_ports=$(echo "$port_list" | grep -c "tcp")
174 | udp_ports=$(echo "$port_list" | grep -c "udp")
175 | tcp_ports=$(echo "$port_list" | awk '/tcp/ {print $1}')
176 | tcp_port1=$(echo "$tcp_ports" | sed -n '1p')
177 | tcp_port2=$(echo "$tcp_ports" | sed -n '2p')
178 | udp_port=$(echo "$port_list" | awk '/udp/ {print $1}')
179 | purple "当前TCP端口: $tcp_port1 和 $tcp_port2"
180 | purple "当前UDP端口: $udp_port"
181 | else
182 | tcp_ports=$(echo "$port_list" | awk '/tcp/ {print $1}')
183 | tcp_port1=$(echo "$tcp_ports" | sed -n '1p')
184 | tcp_port2=$(echo "$tcp_ports" | sed -n '2p')
185 | udp_port=$(echo "$port_list" | awk '/udp/ {print $1}')
186 | purple "当前TCP端口: $tcp_port1 和 $tcp_port2"
187 | purple "当前UDP端口: $udp_port"
188 | fi
189 | export vless_port=$tcp_port1
190 | export vmess_port=$tcp_port2
191 | export hy2_port=$udp_port
192 | green "你的vless-reality端口: $vless_port"
193 | green "你的vmess-ws端口(设置Argo固定域名端口): $vmess_port"
194 | green "你的hysteria2端口: $hy2_port"
195 | }
196 |
197 | install_singbox() {
198 | if [[ -e $WORKDIR/list.txt ]]; then
199 | yellow "已安装sing-box,请先选择2卸载,再执行安装" && exit
200 | fi
201 | sleep 2
202 | cd $WORKDIR
203 | echo
204 | read_ip
205 | echo
206 | read_reym
207 | echo
208 | read_uuid
209 | echo
210 | check_port
211 | echo
212 | sleep 2
213 | argo_configure
214 | echo
215 | download_and_run_singbox
216 | cd
217 | fastrun
218 | green "创建快捷方式:sb"
219 | echo
220 | if [ "$hona" = "serv00" ]; then
221 | servkeep
222 | fi
223 | cd $WORKDIR
224 | echo
225 | get_links
226 | cd
227 | purple "************************************************************"
228 | purple "Serv00/Hostuno-sb-yg脚本安装结束"
229 | purple "退出SSH"
230 | purple "请再次连接SSH,查看主菜单,请输入快捷方式:sb"
231 | purple "************************************************************"
232 | sleep 2
233 | kill -9 $(ps -o ppid= -p $$) >/dev/null 2>&1
234 | }
235 |
236 | uninstall_singbox() {
237 | reading "\n确定要卸载吗?【y/n】: " choice
238 | case "$choice" in
239 | [Yy])
240 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1
241 | rm -rf bin domains serv00keep.sh webport.sh
242 | devil www list | awk 'NR > 1 && NF {print $1}' | xargs -I {} devil www del {} > /dev/null 2>&1
243 | sed -i '' '/export PATH="\$HOME\/bin:\$PATH"/d' ~/.bashrc
244 | source ~/.bashrc
245 | purple "************************************************************"
246 | purple "Serv00/Hostuno-sb-yg卸载完成!"
247 | purple "欢迎继续使用脚本:bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00.sh)"
248 | purple "************************************************************"
249 | ;;
250 | [Nn]) exit 0 ;;
251 | *) red "无效的选择,请输入y或n" && menu ;;
252 | esac
253 | }
254 |
255 | kill_all_tasks() {
256 | reading "\n注意!!!清理所有进程并清空所有安装内容,将退出ssh连接,确定继续清理吗?【y/n】: " choice
257 | case "$choice" in
258 | [Yy])
259 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1
260 | devil www list | awk 'NR > 1 && NF {print $1}' | xargs -I {} devil www del {} > /dev/null 2>&1
261 | sed -i '' '/export PATH="\$HOME\/bin:\$PATH"/d' ~/.bashrc
262 | source ~/.bashrc
263 | purple "************************************************************"
264 | purple "Serv00/Hostuno-sb-yg清理重置完成!"
265 | purple "欢迎继续使用脚本:bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00.sh)"
266 | purple "************************************************************"
267 | find ~ -type f -exec chmod 644 {} \; 2>/dev/null
268 | find ~ -type d -exec chmod 755 {} \; 2>/dev/null
269 | find ~ -type f -exec rm -f {} \; 2>/dev/null
270 | find ~ -type d -empty -exec rmdir {} \; 2>/dev/null
271 | find ~ -exec rm -rf {} \; 2>/dev/null
272 | killall -9 -u $(whoami)
273 | ;;
274 | *) menu ;;
275 | esac
276 | }
277 |
278 | argo_configure() {
279 | while true; do
280 | yellow "方式一:(推荐)无需域名的Argo临时隧道:输入回车"
281 | yellow "方式二:需要域名的Argo固定隧道(需要CF设置提取Token):输入g"
282 | reading "【请选择 g 或者 回车】: " argo_choice
283 | if [[ "$argo_choice" != "g" && "$argo_choice" != "G" && -n "$argo_choice" ]]; then
284 | red "无效的选择,请输入 g 或回车"
285 | continue
286 | fi
287 | if [[ "$argo_choice" == "g" || "$argo_choice" == "G" ]]; then
288 | reading "请输入argo固定隧道域名: " ARGO_DOMAIN
289 | echo "$ARGO_DOMAIN" | tee ARGO_DOMAIN.log ARGO_DOMAIN_show.log > /dev/null
290 | green "你的argo固定隧道域名为: $ARGO_DOMAIN"
291 | reading "请输入argo固定隧道密钥(当你粘贴Token时,必须以ey开头): " ARGO_AUTH
292 | echo "$ARGO_AUTH" | tee ARGO_AUTH.log ARGO_AUTH_show.log > /dev/null
293 | green "你的argo固定隧道密钥为: $ARGO_AUTH"
294 | rm -rf boot.log
295 | else
296 | green "使用Argo临时隧道"
297 | rm -rf ARGO_AUTH.log ARGO_DOMAIN.log
298 | fi
299 | break
300 | done
301 | }
302 |
303 | download_and_run_singbox() {
304 | if [ ! -s sb.txt ] && [ ! -s ag.txt ]; then
305 | DOWNLOAD_DIR="." && mkdir -p "$DOWNLOAD_DIR" && FILE_INFO=()
306 | FILE_INFO=("https://github.com/yonggekkk/Cloudflare_vless_trojan/releases/download/serv00/sb web" "https://github.com/yonggekkk/Cloudflare_vless_trojan/releases/download/serv00/server bot")
307 | declare -A FILE_MAP
308 | generate_random_name() {
309 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
310 | local name=""
311 | for i in {1..6}; do
312 | name="$name${chars:RANDOM%${#chars}:1}"
313 | done
314 | echo "$name"
315 | }
316 |
317 | download_with_fallback() {
318 | local URL=$1
319 | local NEW_FILENAME=$2
320 |
321 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" &
322 | CURL_PID=$!
323 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0)
324 |
325 | sleep 1
326 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0)
327 |
328 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then
329 | kill $CURL_PID 2>/dev/null
330 | wait $CURL_PID 2>/dev/null
331 | wget -q -O "$NEW_FILENAME" "$URL"
332 | echo -e "\e[1;32mDownloading $NEW_FILENAME by wget\e[0m"
333 | else
334 | wait $CURL_PID
335 | echo -e "\e[1;32mDownloading $NEW_FILENAME by curl\e[0m"
336 | fi
337 | }
338 |
339 | for entry in "${FILE_INFO[@]}"; do
340 | URL=$(echo "$entry" | cut -d ' ' -f 1)
341 | RANDOM_NAME=$(generate_random_name)
342 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME"
343 |
344 | if [ -e "$NEW_FILENAME" ]; then
345 | echo -e "\e[1;32m$NEW_FILENAME already exists, Skipping download\e[0m"
346 | else
347 | download_with_fallback "$URL" "$NEW_FILENAME"
348 | fi
349 |
350 | chmod +x "$NEW_FILENAME"
351 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME"
352 | done
353 | wait
354 | fi
355 |
356 | if [ ! -e private_key.txt ]; then
357 | output=$(./"$(basename ${FILE_MAP[web]})" generate reality-keypair)
358 | private_key=$(echo "${output}" | awk '/PrivateKey:/ {print $2}')
359 | public_key=$(echo "${output}" | awk '/PublicKey:/ {print $2}')
360 | echo "${private_key}" > private_key.txt
361 | echo "${public_key}" > public_key.txt
362 | fi
363 | private_key=$( config.json << EOF
368 | {
369 | "log": {
370 | "disabled": true,
371 | "level": "info",
372 | "timestamp": true
373 | },
374 | "inbounds": [
375 | {
376 | "tag": "hysteria-in1",
377 | "type": "hysteria2",
378 | "listen": "$(dig @8.8.8.8 +time=5 +short "web$nb.${hona}.com" | sort -u)",
379 | "listen_port": $hy2_port,
380 | "users": [
381 | {
382 | "password": "$UUID"
383 | }
384 | ],
385 | "masquerade": "https://www.bing.com",
386 | "ignore_client_bandwidth":false,
387 | "tls": {
388 | "enabled": true,
389 | "alpn": [
390 | "h3"
391 | ],
392 | "certificate_path": "cert.pem",
393 | "key_path": "private.key"
394 | }
395 | },
396 | {
397 | "tag": "hysteria-in2",
398 | "type": "hysteria2",
399 | "listen": "$(dig @8.8.8.8 +time=5 +short "$HOSTNAME" | sort -u)",
400 | "listen_port": $hy2_port,
401 | "users": [
402 | {
403 | "password": "$UUID"
404 | }
405 | ],
406 | "masquerade": "https://www.bing.com",
407 | "ignore_client_bandwidth":false,
408 | "tls": {
409 | "enabled": true,
410 | "alpn": [
411 | "h3"
412 | ],
413 | "certificate_path": "cert.pem",
414 | "key_path": "private.key"
415 | }
416 | },
417 | {
418 | "tag": "hysteria-in3",
419 | "type": "hysteria2",
420 | "listen": "$(dig @8.8.8.8 +time=5 +short "cache$nb.${hona}.com" | sort -u)",
421 | "listen_port": $hy2_port,
422 | "users": [
423 | {
424 | "password": "$UUID"
425 | }
426 | ],
427 | "masquerade": "https://www.bing.com",
428 | "ignore_client_bandwidth":false,
429 | "tls": {
430 | "enabled": true,
431 | "alpn": [
432 | "h3"
433 | ],
434 | "certificate_path": "cert.pem",
435 | "key_path": "private.key"
436 | }
437 | },
438 | {
439 | "tag": "vless-reality-vesion",
440 | "type": "vless",
441 | "listen": "::",
442 | "listen_port": $vless_port,
443 | "users": [
444 | {
445 | "uuid": "$UUID",
446 | "flow": "xtls-rprx-vision"
447 | }
448 | ],
449 | "tls": {
450 | "enabled": true,
451 | "server_name": "$reym",
452 | "reality": {
453 | "enabled": true,
454 | "handshake": {
455 | "server": "$reym",
456 | "server_port": 443
457 | },
458 | "private_key": "$private_key",
459 | "short_id": [
460 | ""
461 | ]
462 | }
463 | }
464 | },
465 | {
466 | "tag": "vmess-ws-in",
467 | "type": "vmess",
468 | "listen": "::",
469 | "listen_port": $vmess_port,
470 | "users": [
471 | {
472 | "uuid": "$UUID"
473 | }
474 | ],
475 | "transport": {
476 | "type": "ws",
477 | "path": "$UUID-vm",
478 | "early_data_header_name": "Sec-WebSocket-Protocol"
479 | }
480 | }
481 | ],
482 | "outbounds": [
483 | {
484 | "type": "wireguard",
485 | "tag": "wg",
486 | "server": "162.159.192.200",
487 | "server_port": 4500,
488 | "local_address": [
489 | "172.16.0.2/32",
490 | "2606:4700:110:8f77:1ca9:f086:846c:5f9e/128"
491 | ],
492 | "private_key": "wIxszdR2nMdA7a2Ul3XQcniSfSZqdqjPb6w6opvf5AU=",
493 | "peer_public_key": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
494 | "reserved": [
495 | 126,
496 | 246,
497 | 173
498 | ]
499 | },
500 | {
501 | "type": "direct",
502 | "tag": "direct"
503 | }
504 | ],
505 | "route": {
506 | "rule_set": [
507 | {
508 | "tag": "google-gemini",
509 | "type": "remote",
510 | "format": "binary",
511 | "url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/google-gemini.srs",
512 | "download_detour": "direct"
513 | }
514 | ],
515 | EOF
516 | if [[ "$nb" =~ 14|15 ]]; then
517 | cat >> config.json <> config.json < /dev/null; then
545 | ps aux | grep '[r]un -c con' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
546 | if [ -e "$(basename "${FILE_MAP[web]}")" ]; then
547 | echo "$(basename "${FILE_MAP[web]}")" > sb.txt
548 | sbb=$(cat sb.txt)
549 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
550 | sleep 5
551 | if pgrep -x "$sbb" > /dev/null; then
552 | green "$sbb 主进程已启动"
553 | else
554 | red "$sbb 主进程未启动, 重启中..."
555 | pkill -x "$sbb"
556 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
557 | sleep 2
558 | purple "$sbb 主进程已重启"
559 | fi
560 | else
561 | sbb=$(cat sb.txt)
562 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
563 | sleep 5
564 | if pgrep -x "$sbb" > /dev/null; then
565 | green "$sbb 主进程已启动"
566 | else
567 | red "$sbb 主进程未启动, 重启中..."
568 | pkill -x "$sbb"
569 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
570 | sleep 2
571 | purple "$sbb 主进程已重启"
572 | fi
573 | fi
574 | else
575 | green "主进程已启动"
576 | fi
577 | cfgo() {
578 | rm -rf boot.log
579 | if [ -e "$(basename "${FILE_MAP[bot]}")" ]; then
580 | echo "$(basename "${FILE_MAP[bot]}")" > ag.txt
581 | agg=$(cat ag.txt)
582 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then
583 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}"
584 | args="tunnel --no-autoupdate run --token ${ARGO_AUTH}"
585 | else
586 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$vmess_port"
587 | args="tunnel --url http://localhost:$vmess_port --no-autoupdate --logfile boot.log --loglevel info"
588 | fi
589 | nohup ./"$agg" $args >/dev/null 2>&1 &
590 | sleep 10
591 | if pgrep -x "$agg" > /dev/null; then
592 | green "$agg Arog进程已启动"
593 | else
594 | red "$agg Argo进程未启动, 重启中..."
595 | pkill -x "$agg"
596 | nohup ./"$agg" "${args}" >/dev/null 2>&1 &
597 | sleep 5
598 | purple "$agg Argo进程已重启"
599 | fi
600 | else
601 | agg=$(cat ag.txt)
602 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then
603 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}"
604 | args="tunnel --no-autoupdate run --token ${ARGO_AUTH}"
605 | else
606 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$vmess_port"
607 | args="tunnel --url http://localhost:$vmess_port --no-autoupdate --logfile boot.log --loglevel info"
608 | fi
609 | pkill -x "$agg"
610 | nohup ./"$agg" $args >/dev/null 2>&1 &
611 | sleep 10
612 | if pgrep -x "$agg" > /dev/null; then
613 | green "$agg Arog进程已启动"
614 | else
615 | red "$agg Argo进程未启动, 重启中..."
616 | pkill -x "$agg"
617 | nohup ./"$agg" "${args}" >/dev/null 2>&1 &
618 | sleep 5
619 | purple "$agg Argo进程已重启"
620 | fi
621 | fi
622 | }
623 |
624 | if [ -f "$WORKDIR/boot.log" ]; then
625 | argosl=$(cat "$WORKDIR/boot.log" 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
626 | checkhttp=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argosl")
627 | else
628 | argogd=$(cat $WORKDIR/ARGO_DOMAIN.log 2>/dev/null)
629 | checkhttp=$(curl --max-time 2 -o /dev/null -s -w "%{http_code}\n" "https://$argogd")
630 | fi
631 | if ([ -z "$ARGO_DOMAIN" ] && ! ps aux | grep '[t]unnel --u' > /dev/null) || [ "$checkhttp" -ne 404 ]; then
632 | ps aux | grep '[t]unnel --u' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
633 | cfgo
634 | elif ([ -n "$ARGO_DOMAIN" ] && ! ps aux | grep '[t]unnel --n' > /dev/null) || [ "$checkhttp" -ne 404 ]; then
635 | ps aux | grep '[t]unnel --n' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
636 | cfgo
637 | else
638 | green "Arog进程已启动"
639 | fi
640 | sleep 2
641 | if ! pgrep -x "$(cat sb.txt)" > /dev/null; then
642 | red "主进程未启动,根据以下情况一一排查"
643 | yellow "1、选择8重置端口,自动生成随机可用端口(重要)"
644 | yellow "2、选择9重置"
645 | yellow "3、当前Serv00/Hostuno服务器炸了?等会再试"
646 | red "4、以上都试了,哥直接躺平,交给进程保活,过会再来看"
647 | sleep 6
648 | fi
649 | }
650 |
651 | get_argodomain() {
652 | if [[ -n $ARGO_AUTH ]]; then
653 | echo "$ARGO_DOMAIN"
654 | else
655 | local retry=0
656 | local max_retries=6
657 | local argodomain=""
658 | while [[ $retry -lt $max_retries ]]; do
659 | ((retry++))
660 | argodomain=$(cat boot.log 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
661 | if [[ -n $argodomain ]]; then
662 | break
663 | fi
664 | sleep 2
665 | done
666 | if [ -z ${argodomain} ]; then
667 | argodomain="Argo临时域名暂时获取失败,Argo节点暂不可用(保活过程中会自动恢复),其他节点依旧可用"
668 | fi
669 | echo "$argodomain"
670 | fi
671 | }
672 |
673 | get_links(){
674 | argodomain=$(get_argodomain)
675 | echo -e "\e[1;32mArgo域名:\e[1;35m${argodomain}\e[0m\n"
676 | a=$(dig @8.8.8.8 +time=5 +short "web$nb.${hona}.com" | sort -u)
677 | b=$(dig @8.8.8.8 +time=5 +short "$HOSTNAME" | sort -u)
678 | c=$(dig @8.8.8.8 +time=5 +short "cache$nb.${hona}.com" | sort -u)
679 | if [[ "$IP" == "$a" ]]; then
680 | CIP1=$b; CIP2=$c
681 | elif [[ "$IP" == "$b" ]]; then
682 | CIP1=$a; CIP2=$c
683 | elif [[ "$IP" == "$c" ]]; then
684 | CIP1=$a; CIP2=$b
685 | else
686 | red "执行出错,请卸载脚本再重装一次"
687 | fi
688 | vl_link="vless://$UUID@$IP:$vless_port?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$reym&fp=chrome&pbk=$public_key&type=tcp&headerType=none#$snb-reality-$USERNAME"
689 | echo "$vl_link" > jh.txt
690 | vmws_link="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-$USERNAME\", \"add\": \"$IP\", \"port\": \"$vmess_port\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\", \"sni\": \"\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
691 | echo "$vmws_link" >> jh.txt
692 | vmatls_link="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME\", \"add\": \"www.visa.com.hk\", \"port\": \"8443\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
693 | echo "$vmatls_link" >> jh.txt
694 | vma_link="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME\", \"add\": \"www.visa.com.hk\", \"port\": \"8880\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
695 | echo "$vma_link" >> jh.txt
696 | hy2_link="hysteria2://$UUID@$IP:$hy2_port?security=tls&sni=www.bing.com&alpn=h3&insecure=1#$snb-hy2-$USERNAME"
697 | echo "$hy2_link" >> jh.txt
698 | vl_link1="vless://$UUID@$CIP1:$vless_port?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$reym&fp=chrome&pbk=$public_key&type=tcp&headerType=none#$snb-reality-$USERNAME-$CIP1"
699 | echo "$vl_link1" >> jh.txt
700 | vmws_link1="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-$USERNAME-$CIP1\", \"add\": \"$CIP1\", \"port\": \"$vmess_port\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\", \"sni\": \"\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
701 | echo "$vmws_link1" >> jh.txt
702 | hy2_link1="hysteria2://$UUID@$CIP1:$hy2_port?security=tls&sni=www.bing.com&alpn=h3&insecure=1#$snb-hy2-$USERNAME-$CIP1"
703 | echo "$hy2_link1" >> jh.txt
704 | vl_link2="vless://$UUID@$CIP2:$vless_port?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$reym&fp=chrome&pbk=$public_key&type=tcp&headerType=none#$snb-reality-$USERNAME-$CIP2"
705 | echo "$vl_link2" >> jh.txt
706 | vmws_link2="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-$USERNAME-$CIP2\", \"add\": \"$CIP2\", \"port\": \"$vmess_port\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\", \"sni\": \"\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
707 | echo "$vmws_link2" >> jh.txt
708 | hy2_link2="hysteria2://$UUID@$CIP2:$hy2_port?security=tls&sni=www.bing.com&alpn=h3&insecure=1#$snb-hy2-$USERNAME-$CIP2"
709 | echo "$hy2_link2" >> jh.txt
710 |
711 | argosl=$(cat "$WORKDIR/boot.log" 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
712 | checkhttp1=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argosl")
713 | argogd=$(cat $WORKDIR/ARGO_DOMAIN.log 2>/dev/null)
714 | checkhttp2=$(curl --max-time 2 -o /dev/null -s -w "%{http_code}\n" "https://$argogd")
715 | if [[ "$checkhttp1" == 404 ]] || [[ "$checkhttp2" == 404 ]]; then
716 | vmatls_link1="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-443\", \"add\": \"104.16.0.0\", \"port\": \"443\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
717 | echo "$vmatls_link1" >> jh.txt
718 | vmatls_link2="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2053\", \"add\": \"104.17.0.0\", \"port\": \"2053\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
719 | echo "$vmatls_link2" >> jh.txt
720 | vmatls_link3="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2083\", \"add\": \"104.18.0.0\", \"port\": \"2083\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
721 | echo "$vmatls_link3" >> jh.txt
722 | vmatls_link4="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2087\", \"add\": \"104.19.0.0\", \"port\": \"2087\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
723 | echo "$vmatls_link4" >> jh.txt
724 | vmatls_link5="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2096\", \"add\": \"104.20.0.0\", \"port\": \"2096\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
725 | echo "$vmatls_link5" >> jh.txt
726 | vma_link6="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-80\", \"add\": \"104.21.0.0\", \"port\": \"80\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
727 | echo "$vma_link6" >> jh.txt
728 | vma_link7="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-8080\", \"add\": \"104.22.0.0\", \"port\": \"8080\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
729 | echo "$vma_link7" >> jh.txt
730 | vma_link8="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2052\", \"add\": \"104.24.0.0\", \"port\": \"2052\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
731 | echo "$vma_link8" >> jh.txt
732 | vma_link9="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2082\", \"add\": \"104.25.0.0\", \"port\": \"2082\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
733 | echo "$vma_link9" >> jh.txt
734 | vma_link10="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2086\", \"add\": \"104.26.0.0\", \"port\": \"2086\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
735 | echo "$vma_link10" >> jh.txt
736 | vma_link11="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2095\", \"add\": \"104.27.0.0\", \"port\": \"2095\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
737 | echo "$vma_link11" >> jh.txt
738 | fi
739 | v2sub=$(cat jh.txt)
740 | echo "$v2sub" > ${FILE_PATH}/${UUID}_v2sub.txt
741 | baseurl=$(base64 -w 0 < jh.txt)
742 |
743 | cat > sing_box.json < clash_meta.yaml < ${FILE_PATH}/${UUID}_clashmeta.txt
1214 | cat sing_box.json > ${FILE_PATH}/${UUID}_singbox.txt
1215 | V2rayN_LINK="https://${USERNAME}.${address}/${UUID}_v2sub.txt"
1216 | Clashmeta_LINK="https://${USERNAME}.${address}/${UUID}_clashmeta.txt"
1217 | Singbox_LINK="https://${USERNAME}.${address}/${UUID}_singbox.txt"
1218 | hyp=$(jq -r '.inbounds[0].listen_port' config.json)
1219 | vlp=$(jq -r '.inbounds[3].listen_port' config.json)
1220 | vmp=$(jq -r '.inbounds[4].listen_port' config.json)
1221 | showuuid=$(jq -r '.inbounds[0].users[0].password' config.json)
1222 | cat > list.txt < webport.sh
1363 | declare -f resallport >> webport.sh
1364 | declare -f check_port >> webport.sh
1365 | declare -f resservsb >> webport.sh
1366 | echo 'resallport' >> webport.sh
1367 | chmod +x webport.sh
1368 | green "开始安装多功能主页,请稍等……"
1369 | devil www del ${snb}.${USERNAME}.${hona}.net > /dev/null 2>&1
1370 | devil www add ${USERNAME}.${hona}.net php > /dev/null 2>&1
1371 | devil www add ${snb}.${USERNAME}.${hona}.net nodejs /usr/local/bin/node18 > /dev/null 2>&1
1372 | ln -fs /usr/local/bin/node18 ~/bin/node > /dev/null 2>&1
1373 | ln -fs /usr/local/bin/npm18 ~/bin/npm > /dev/null 2>&1
1374 | mkdir -p ~/.npm-global
1375 | npm config set prefix '~/.npm-global'
1376 | echo 'export PATH=~/.npm-global/bin:~/bin:$PATH' >> $HOME/.bash_profile && source $HOME/.bash_profile
1377 | rm -rf $HOME/.npmrc > /dev/null 2>&1
1378 | cd "$keep_path"
1379 | npm install basic-auth express dotenv axios --silent > /dev/null 2>&1
1380 | rm $HOME/domains/${snb}.${USERNAME}.${hona}.net/public_nodejs/public/index.html > /dev/null 2>&1
1381 | devil www restart ${snb}.${USERNAME}.${hona}.net
1382 | curl -sk "http://${snb}.${USERNAME}.${hona}.net/up" > /dev/null 2>&1
1383 | green "安装完毕,多功能主页地址:http://${snb}.${USERNAME}.${hona}.net" && sleep 2
1384 | }
1385 |
1386 | okip(){
1387 | IP_LIST=($(devil vhost list | awk '/^[0-9]+/ {print $1}'))
1388 | API_URL="https://status.eooce.com/api"
1389 | IP=""
1390 | THIRD_IP=${IP_LIST[2]}
1391 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${THIRD_IP}")
1392 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then
1393 | IP=$THIRD_IP
1394 | else
1395 | FIRST_IP=${IP_LIST[0]}
1396 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${FIRST_IP}")
1397 |
1398 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then
1399 | IP=$FIRST_IP
1400 | else
1401 | IP=${IP_LIST[1]}
1402 | fi
1403 | fi
1404 | echo "$IP"
1405 | }
1406 |
1407 | fastrun(){
1408 | if [[ -e $WORKDIR/config.json ]]; then
1409 | COMMAND="sb"
1410 | SCRIPT_PATH="$HOME/bin/$COMMAND"
1411 | mkdir -p "$HOME/bin"
1412 | curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00.sh > "$SCRIPT_PATH"
1413 | chmod +x "$SCRIPT_PATH"
1414 | if [[ ":$PATH:" != *":$HOME/bin:"* ]]; then
1415 | echo 'export PATH="$HOME/bin:$PATH"' >> "$HOME/.bashrc"
1416 | grep -qxF 'source ~/.bashrc' ~/.bash_profile 2>/dev/null || echo 'source ~/.bashrc' >> ~/.bash_profile
1417 | source ~/.bashrc
1418 | fi
1419 | if [ "$hona" = "serv00" ]; then
1420 | curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/app.js -o "$keep_path"/app.js
1421 | sed -i '' "15s/name/$snb/g" "$keep_path"/app.js
1422 | sed -i '' "59s/key/$UUID/g" "$keep_path"/app.js
1423 | sed -i '' "90s/name/$USERNAME/g" "$keep_path"/app.js
1424 | sed -i '' "90s/where/$snb/g" "$keep_path"/app.js
1425 | curl -sSL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00keep.sh -o serv00keep.sh && chmod +x serv00keep.sh
1426 | fi
1427 | curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/index.html -o "$FILE_PATH"/index.html
1428 | curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/sversion | awk -F "更新内容" '{print $1}' | head -n 1 > $WORKDIR/v
1429 | else
1430 | red "未安装脚本,请选择1进行安装" && exit
1431 | fi
1432 | }
1433 |
1434 | resservsb(){
1435 | if [[ -e $WORKDIR/config.json ]]; then
1436 | yellow "重启中……请稍后……"
1437 | cd $WORKDIR
1438 | ps aux | grep '[r]un -c con' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
1439 | if [ "$hona" = "serv00" ]; then
1440 | curl -sk "http://${snb}.${USERNAME}.${hona}.net/up" > /dev/null 2>&1
1441 | sleep 5
1442 | else
1443 | sbb=$(cat sb.txt)
1444 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
1445 | sleep 1
1446 | fi
1447 | if pgrep -x "$sbb" > /dev/null; then
1448 | green "$sbb 主进程重启成功"
1449 | else
1450 | red "$sbb 主进程重启失败"
1451 | fi
1452 | cd
1453 | else
1454 | red "未安装脚本,请选择1进行安装" && exit
1455 | fi
1456 | }
1457 |
1458 | resargo(){
1459 | if [[ -e $WORKDIR/config.json ]]; then
1460 | cd $WORKDIR
1461 | argoport=$(jq -r '.inbounds[4].listen_port' config.json)
1462 | yellow "你可以重置临时隧道; 可以继续使用上回的固定隧道; 也可以更换固定隧道的域名或token"
1463 | argogdshow(){
1464 | echo
1465 | if [ -f ARGO_AUTH_show.log ]; then
1466 | purple "上回设置的Argo固定域名:$(cat ARGO_DOMAIN_show.log 2>/dev/null)"
1467 | purple "上回固定隧道的Token:$(cat ARGO_AUTH_show.log 2>/dev/null)"
1468 | purple "目前检查CF官网的Argo固定隧道端口:$argoport"
1469 | fi
1470 | echo
1471 | }
1472 | if [ -f boot.log ]; then
1473 | green "当前正在使用Argo临时隧道"
1474 | argogdshow
1475 | else
1476 | green "当前正在使用Argo固定隧道"
1477 | argogdshow
1478 | fi
1479 | argo_configure
1480 | ps aux | grep '[t]unnel --u' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
1481 | ps aux | grep '[t]unnel --n' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
1482 | agg=$(cat ag.txt)
1483 | if [[ "$argo_choice" =~ (G|g) ]]; then
1484 | if [ "$hona" = "serv00" ]; then
1485 | sed -i '' -e "15s|''|'$(cat ARGO_DOMAIN_show.log 2>/dev/null)'|" ~/serv00keep.sh
1486 | sed -i '' -e "16s|''|'$(cat ARGO_AUTH_show.log 2>/dev/null)'|" ~/serv00keep.sh
1487 | fi
1488 | args="tunnel --no-autoupdate run --token $(cat ARGO_AUTH_show.log)"
1489 | else
1490 | rm -rf boot.log
1491 | if [ "$hona" = "serv00" ]; then
1492 | sed -i '' -e "15s|'$(cat ARGO_DOMAIN_show.log 2>/dev/null)'|''|" ~/serv00keep.sh
1493 | sed -i '' -e "16s|'$(cat ARGO_AUTH_show.log 2>/dev/null)'|''|" ~/serv00keep.sh
1494 | fi
1495 | args="tunnel --url http://localhost:$argoport --no-autoupdate --logfile boot.log --loglevel info"
1496 | fi
1497 | nohup ./"$agg" $args >/dev/null 2>&1 &
1498 | sleep 10
1499 | if pgrep -x "$agg" > /dev/null; then
1500 | green "$agg Argo进程已启动"
1501 | else
1502 | red "$agg Argo进程未启动, 重启中..."
1503 | pkill -x "$agg"
1504 | nohup ./"$agg" "${args}" >/dev/null 2>&1 &
1505 | sleep 5
1506 | purple "$agg Argo进程已重启"
1507 | fi
1508 | showchangelist
1509 | cd
1510 | else
1511 | red "未安装脚本,请选择1进行安装" && exit
1512 | fi
1513 | }
1514 |
1515 | showchangelist(){
1516 | IP=$(<$WORKDIR/ipone.txt)
1517 | UUID=$(<$WORKDIR/UUID.txt)
1518 | reym=$(<$WORKDIR/reym.txt)
1519 | ARGO_DOMAIN=$(cat "$WORKDIR/ARGO_DOMAIN.log" 2>/dev/null)
1520 | ARGO_AUTH=$(cat "$WORKDIR/ARGO_AUTH.log" 2>/dev/null)
1521 | check_port >/dev/null 2>&1
1522 | download_and_run_singbox >/dev/null 2>&1
1523 | get_links
1524 | }
1525 |
1526 | menu() {
1527 | clear
1528 | echo "============================================================"
1529 | green "甬哥Github项目 :github.com/yonggekkk"
1530 | green "甬哥Blogger博客 :ygkkk.blogspot.com"
1531 | green "甬哥YouTube频道 :www.youtube.com/@ygkkk"
1532 | green "Serv00/Hostuno三协议共存脚本:vless-reality/Vmess-ws(Argo)/Hy2"
1533 | green "脚本快捷方式:sb"
1534 | echo "============================================================"
1535 | green "1. 一键安装 Serv00/Hostuno-sb-yg"
1536 | echo "------------------------------------------------------------"
1537 | yellow "2. 卸载删除 Serv00/Hostuno-sb-yg"
1538 | echo "------------------------------------------------------------"
1539 | green "3. 重启主进程 (修复主节点)"
1540 | echo "------------------------------------------------------------"
1541 | green "4. Argo重置(临时隧道与固定隧道相互切换、更换固定域名)"
1542 | echo "------------------------------------------------------------"
1543 | green "5. 更新脚本"
1544 | echo "------------------------------------------------------------"
1545 | green "6. 查看各节点分享/sing-box与clash订阅链接/反代IP/ProxyIP"
1546 | echo "------------------------------------------------------------"
1547 | green "7. 查看sing-box与clash配置文件"
1548 | echo "------------------------------------------------------------"
1549 | yellow "8. 端口重置并随机生成新端口"
1550 | echo "------------------------------------------------------------"
1551 | red "9. 清理所有服务进程与文件 (系统初始化)"
1552 | echo "------------------------------------------------------------"
1553 | red "0. 退出脚本"
1554 | echo "============================================================"
1555 | ym=("$HOSTNAME" "cache$nb.${hona}.com" "web$nb.${hona}.com")
1556 | rm -rf $WORKDIR/ip.txt
1557 | for host in "${ym[@]}"; do
1558 | response=$(curl -sL --connect-timeout 5 --max-time 7 "https://ss.fkj.pp.ua/api/getip?host=$host")
1559 | if [[ "$response" =~ (unknown|not|error) ]]; then
1560 | dig @8.8.8.8 +time=5 +short $host | sort -u >> $WORKDIR/ip.txt
1561 | sleep 1
1562 | else
1563 | while IFS='|' read -r ip status; do
1564 | if [[ $status == "Accessible" ]]; then
1565 | echo "$ip: 可用" >> $WORKDIR/ip.txt
1566 | else
1567 | echo "$ip: 被墙 (Argo与CDN回源节点、proxyip依旧有效)" >> $WORKDIR/ip.txt
1568 | fi
1569 | done <<< "$response"
1570 | fi
1571 | done
1572 | if [[ ! "$response" =~ (unknown|not|error) ]]; then
1573 | grep ':' $WORKDIR/ip.txt | sort -u -o $WORKDIR/ip.txt
1574 | fi
1575 | if [ "$hona" = "serv00" ]; then
1576 | red "目前免费Serv00使用代理脚本会有被封账号的风险,请知晓!!!"
1577 | fi
1578 | green "${hona}服务器名称:${snb}"
1579 | echo
1580 | green "当前可选择的IP如下:"
1581 | cat $WORKDIR/ip.txt
1582 | echo
1583 | portlist=$(devil port list | grep -E '^[0-9]+[[:space:]]+[a-zA-Z]+' | sed 's/^[[:space:]]*//')
1584 | if [[ -n $portlist ]]; then
1585 | green "已设置的端口如下:"
1586 | echo -e "$portlist"
1587 | else
1588 | yellow "未设置端口"
1589 | fi
1590 | echo
1591 | insV=$(cat $WORKDIR/v 2>/dev/null)
1592 | latestV=$(curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/sversion | awk -F "更新内容" '{print $1}' | head -n 1)
1593 | if [ -f $WORKDIR/v ]; then
1594 | if [ "$insV" = "$latestV" ]; then
1595 | echo -e "当前 Serv00/Hostuno-sb-yg 脚本最新版:${purple}${insV}${re} (已安装)"
1596 | else
1597 | echo -e "当前 Serv00/Hostuno-sb-yg 脚本版本号:${purple}${insV}${re}"
1598 | echo -e "检测到最新 Serv00/Hostuno-sb-yg 脚本版本号:${yellow}${latestV}${re} (可选择5进行更新)"
1599 | echo -e "${yellow}$(curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/sversion)${re}"
1600 | fi
1601 | echo -e "========================================================="
1602 | sbb=$(cat $WORKDIR/sb.txt 2>/dev/null)
1603 | if pgrep -x "$sbb" > /dev/null; then
1604 | green "Sing-box主进程运行正常"
1605 | else
1606 | yellow "Sing-box主进程启动失败,建议先选择3重启,依旧失败就选择8重置端口,再选择9卸载重装"
1607 | fi
1608 | if [ -f "$WORKDIR/boot.log" ]; then
1609 | argosl=$(cat "$WORKDIR/boot.log" 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
1610 | checkhttp=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argosl")
1611 | [[ "$checkhttp" == 404 ]] && check="域名有效" || check="临时域名暂时无效,如已启用保活,后续会自动恢复有效"
1612 | green "Argo临时域名:$argosl $check"
1613 | else
1614 | argogd=$(cat $WORKDIR/ARGO_DOMAIN.log 2>/dev/null)
1615 | checkhttp=$(curl --max-time 2 -o /dev/null -s -w "%{http_code}\n" "https://$argogd")
1616 | if [[ "$checkhttp" == 404 ]]; then
1617 | check="域名有效"
1618 | elif [[ "$argogd" =~ ddns|cloudns|dynamic|cloud-ip ]]; then
1619 | check="域名可能有效,请自行检测argo节点是否可用"
1620 | else
1621 | check="固定域名无效,请检查域名、端口、密钥token是否输入有误"
1622 | fi
1623 | green "Argo固定域名:$argogd $check"
1624 | fi
1625 | if [ "$hona" = "serv00" ]; then
1626 | green "多功能主页如下 (支持保活、重启、重置端口、进程查看、节点查询)"
1627 | purple "http://${snb}.${USERNAME}.${hona}.net"
1628 | fi
1629 | else
1630 | echo -e "当前 Serv00/Hostuno-sb-yg 脚本版本号:${purple}${latestV}${re}"
1631 | yellow "未安装 Serv00/Hostuno-sb-yg 脚本!请选择 1 安装"
1632 | fi
1633 | echo -e "========================================================="
1634 | reading "请输入选择【0-9】: " choice
1635 | echo
1636 | case "${choice}" in
1637 | 1) install_singbox ;;
1638 | 2) uninstall_singbox ;;
1639 | 3) resservsb ;;
1640 | 4) resargo ;;
1641 | 5) fastrun && green "脚本已更新成功" && sleep 2 && sb ;;
1642 | 6) showlist ;;
1643 | 7) showsbclash ;;
1644 | 8) resallport ;;
1645 | 9) kill_all_tasks ;;
1646 | 0) exit 0 ;;
1647 | *) red "无效的选项,请输入 0 到 9" ;;
1648 | esac
1649 | }
1650 | menu
1651 |
--------------------------------------------------------------------------------
/serv00.yml:
--------------------------------------------------------------------------------
1 | name: Keep Servers Alive
2 | # 如果你已安装了Serv00本地SSH脚本,不要再运行此github部署了,这样会造成进程爆满,必须二选一!
3 | on:
4 | #如使用保活网页,请禁用cron,保持下面两行开头的#符号,以防止cron与网页保活重复运行造成进程爆满
5 | #schedule:
6 | # - cron: '0 */4 * * *' # 每4小时执行一次(私库每月500分钟运行时长,每天16分钟)
7 | workflow_dispatch:
8 |
9 | jobs:
10 | keep_servers_alive:
11 | runs-on: ubuntu-latest
12 | env:
13 | # serv00变量添加规则:
14 | # RES(必填):n表示每次不重置部署,y表示每次重置部署。REP(必填):n表示不重置随机端口(三个端口留空),y表示重置端口(三个端口留空)。SSH_USER(必填)表示serv00账号名。SSH_PASS(必填)表示serv00密码。REALITY表示reality域名(留空表示serv00官方域名:你serv00账号名.serv00.net)。SUUID表示uuid(留空表示随机uuid)。TCP1_PORT表示vless的tcp端口(留空表示随机tcp端口)。TCP2_PORT表示vmess的tcp端口(留空表示随机tcp端口)。UDP_PORT表示hy2的udp端口(留空表示随机udp端口)。HOST(必填)表示登录serv00服务器域名。ARGO_DOMAIN表示argo固定域名(留空表示临时域名)。ARGO_AUTH表示argo固定域名token(留空表示临时域名)。
15 | # 必填变量:RES、REP、SSH_USER、SSH_PASS、HOST
16 | # 注意[]"",:这些符号不要乱删,按规律对齐
17 | # 每行一个{serv00服务器},一个服务也可,末尾用,间隔,最后一个服务器末尾无需用,间隔
18 | ACCOUNTS: >
19 | [
20 | {"RES":"n", "REP":"n", "SSH_USER":"你的serv00账号名", "SSH_PASS":"你的serv00账号密码", "REALITY":"你serv00账号名.serv00.net", "SUUID":"自设UUID", "TCP1_PORT":"vless的tcp端口", "TCP2_PORT":"vmess的tcp端口", "UDP_PORT":"hy2的udp端口", "HOST":"s1.serv00.com", "ARGO_DOMAIN":"", "ARGO_AUTH":""},
21 | {"RES":"y", "REP":"y", "SSH_USER":"123456", "SSH_PASS":"7890000", "REALITY":"time.is", "SUUID":"73203ee6-b3fa-4a3d-b5df-6bb2f55073ad", "TCP1_PORT":"", "TCP2_PORT":"", "UDP_PORT":"", "HOST":"s16.serv00.com", "ARGO_DOMAIN":"你的argo固定域名", "ARGO_AUTH":"eyJhIjoiOTM3YzFjYWI88552NTFiYTM4ZTY0ZDQzRmlNelF0TkRBd1pUQTRNVEJqTUdVeCJ9"}
22 | ]
23 | steps:
24 | - name: Checkout Repository
25 | uses: actions/checkout@v2
26 |
27 | - name: Install required packages
28 | run: |
29 | sudo apt-get update
30 | sudo apt-get install -y sshpass curl jq
31 |
32 | - name: Process each account
33 | run: |
34 | run_remote_command() {
35 | local RES=$1
36 | local REP=$2
37 | local SSH_USER=$3
38 | local SSH_PASS=$4
39 | local REALITY=${5}
40 | local SUUID=$6
41 | local TCP1_PORT=$7
42 | local TCP2_PORT=$8
43 | local UDP_PORT=$9
44 | local HOST=${10}
45 | local ARGO_DOMAIN=${11}
46 | local ARGO_AUTH=${12}
47 | if [ -z "${ARGO_DOMAIN}" ]; then
48 | echo "Argo域名为空,申请Argo临时域名"
49 | else
50 | echo "Argo已设置固定域名:${ARGO_DOMAIN}"
51 | fi
52 | remote_command="export reym=$REALITY UUID=$SUUID vless_port=$TCP1_PORT vmess_port=$TCP2_PORT hy2_port=$UDP_PORT reset=$RES resport=$REP ARGO_DOMAIN=${ARGO_DOMAIN} ARGO_AUTH=${ARGO_AUTH} && bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00keep.sh)"
53 | echo "Executing remote command on $HOST as $SSH_USER with command: $remote_command"
54 | sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" "$remote_command"
55 | }
56 | echo "*****************************************************"
57 | echo "*****************************************************"
58 | echo "甬哥Github项目 :github.com/yonggekkk"
59 | echo "甬哥Blogger博客 :ygkkk.blogspot.com"
60 | echo "甬哥YouTube频道 :www.youtube.com/@ygkkk"
61 | echo "自动远程部署并保活Serv00三合一协议脚本【Github】"
62 | echo "版本:V25.3.26"
63 | echo "*****************************************************"
64 | echo "*****************************************************"
65 | count=0
66 | for account in $(echo "${ACCOUNTS}" | jq -c '.[]'); do
67 | count=$((count+1))
68 | RES=$(echo $account | jq -r '.RES')
69 | REP=$(echo $account | jq -r '.REP')
70 | SSH_USER=$(echo $account | jq -r '.SSH_USER')
71 | SSH_PASS=$(echo $account | jq -r '.SSH_PASS')
72 | REALITY=$(echo $account | jq -r '.REALITY')
73 | SUUID=$(echo $account | jq -r '.SUUID')
74 | TCP1_PORT=$(echo $account | jq -r '.TCP1_PORT')
75 | TCP2_PORT=$(echo $account | jq -r '.TCP2_PORT')
76 | UDP_PORT=$(echo $account | jq -r '.UDP_PORT')
77 | HOST=$(echo $account | jq -r '.HOST')
78 | ARGO_DOMAIN=$(echo $account | jq -r '.ARGO_DOMAIN')
79 | ARGO_AUTH=$(echo $account | jq -r '.ARGO_AUTH')
80 | if sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" -q exit; then
81 | echo "🎉恭喜!✅第【$count】台服务器连接成功!🚀服务器地址:$HOST ,账户名:$SSH_USER"
82 | if [ -z "${ARGO_DOMAIN}" ]; then
83 | check_process="ps aux | grep '[c]onfig' > /dev/null && ps aux | grep [l]ocalhost:$TCP2_PORT > /dev/null"
84 | else
85 | check_process="ps aux | grep '[c]onfig' > /dev/null && ps aux | grep '[t]oken $ARGO_AUTH' > /dev/null"
86 | fi
87 | if ! sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" "$check_process" || [[ "$RES" =~ ^[Yy]$ ]]; then
88 | echo "⚠️检测到主进程或者argo进程未启动,或者执行重置"
89 | echo "⚠️现在开始修复或重置部署……请稍等"
90 | output=$(run_remote_command "$RES" "$REP" "$SSH_USER" "$SSH_PASS" "${REALITY}" "$SUUID" "$TCP1_PORT" "$TCP2_PORT" "$UDP_PORT" "$HOST" "${ARGO_DOMAIN}" "${ARGO_AUTH}")
91 | echo "远程命令执行结果:$output"
92 | else
93 | echo "🎉恭喜!✅检测到所有进程正常运行中 "
94 | SSH_USER_LOWER=$(echo "$SSH_USER" | tr '[:upper:]' '[:lower:]')
95 | sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no "$SSH_USER@$HOST" "
96 | echo \"配置显示如下:\"
97 | cat domains/${SSH_USER_LOWER}.serv00.net/logs/list.txt
98 | echo \"====================================================\"
99 | "
100 | fi
101 | else
102 | echo "===================================================="
103 | echo "💥杯具!❌第【$count】台服务器连接失败!🚀服务器地址:$HOST ,账户名:$SSH_USER"
104 | echo "⚠️可能账号名、密码、服务器名称输入错误,或者当前服务器在维护中"
105 | echo "===================================================="
106 | fi
107 | done
108 |
--------------------------------------------------------------------------------
/serv00keep.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 定义颜色
3 | re="\033[0m"
4 | red="\033[1;91m"
5 | green="\e[1;32m"
6 | yellow="\e[1;33m"
7 | purple="\e[1;35m"
8 | red() { echo -e "\e[1;91m$1\033[0m"; }
9 | green() { echo -e "\e[1;32m$1\033[0m"; }
10 | yellow() { echo -e "\e[1;33m$1\033[0m"; }
11 | purple() { echo -e "\e[1;35m$1\033[0m"; }
12 | reading() { read -p "$(red "$1")" "$2"; }
13 | export LC_ALL=C
14 | export UUID=${UUID:-''}
15 | export ARGO_DOMAIN=${ARGO_DOMAIN:-''}
16 | export ARGO_AUTH=${ARGO_AUTH:-''}
17 | export vless_port=${vless_port:-''}
18 | export vmess_port=${vmess_port:-''}
19 | export hy2_port=${hy2_port:-''}
20 | export IP=${IP:-''}
21 | export reym=${reym:-''}
22 | export reset=${reset:-''}
23 | export resport=${resport:-''}
24 | devil binexec on >/dev/null 2>&1
25 | USERNAME=$(whoami | tr '[:upper:]' '[:lower:]')
26 | HOSTNAME=$(hostname)
27 | snb=$(hostname | cut -d. -f1)
28 | nb=$(hostname | cut -d '.' -f 1 | tr -d 's')
29 | if [[ "$reset" =~ ^[Yy]$ ]]; then
30 | bash -c 'ps aux | grep $(whoami) | grep -v "sshd\|bash\|grep" | awk "{print \$2}" | xargs -r kill -9 >/dev/null 2>&1' >/dev/null 2>&1
31 | devil www list | awk 'NR > 1 && NF {print $1}' | xargs -I {} devil www del {} > /dev/null 2>&1
32 | sed -i '/export PATH="\$HOME\/bin:\$PATH"/d' "${HOME}/.bashrc" >/dev/null 2>&1
33 | source "${HOME}/.bashrc" >/dev/null 2>&1
34 | find ~ -type f -exec chmod 644 {} \; 2>/dev/null
35 | find ~ -type d -exec chmod 755 {} \; 2>/dev/null
36 | find ~ -type f -exec rm -f {} \; 2>/dev/null
37 | find ~ -type d -empty -exec rmdir {} \; 2>/dev/null
38 | find ~ -exec rm -rf {} \; 2>/dev/null
39 | echo "重置系统完成"
40 | fi
41 | devil www add ${USERNAME}.serv00.net php > /dev/null 2>&1
42 | FILE_PATH="${HOME}/domains/${USERNAME}.serv00.net/public_html"
43 | WORKDIR="${HOME}/domains/${USERNAME}.serv00.net/logs"
44 | [ -d "$FILE_PATH" ] || mkdir -p "$FILE_PATH"
45 | [ -d "$WORKDIR" ] || (mkdir -p "$WORKDIR" && chmod 777 "$WORKDIR")
46 | keep_path="${HOME}/domains/${snb}.${USERNAME}.serv00.net/public_nodejs"
47 | [ -d "$keep_path" ] || mkdir -p "$keep_path"
48 |
49 | if [[ -z "$ARGO_AUTH" ]] && [[ -f "$WORKDIR/ARGO_AUTH.log" ]]; then
50 | ARGO_AUTH=$(cat "$WORKDIR/ARGO_AUTH.log" 2>/dev/null)
51 | elif [[ -z "$ARGO_AUTH" ]] && [[ ! -f "$WORKDIR/ARGO_AUTH.log" ]]; then
52 | echo "$ARGO_AUTH" > $WORKDIR/ARGO_AUTH.log
53 | else
54 | echo "$ARGO_AUTH" > $WORKDIR/ARGO_AUTH.log
55 | ARGO_AUTH=$(cat "$WORKDIR/ARGO_AUTH.log" 2>/dev/null)
56 | fi
57 | if [[ -z "$ARGO_DOMAIN" ]] && [[ -f "$WORKDIR/ARGO_DOMAIN.log" ]]; then
58 | ARGO_DOMAIN=$(cat "$WORKDIR/ARGO_DOMAIN.log" 2>/dev/null)
59 | elif [[ -z "$ARGO_DOMAIN" ]] && [[ ! -f "$WORKDIR/ARGO_DOMAIN.log" ]]; then
60 | echo "$ARGO_DOMAIN" > $WORKDIR/ARGO_DOMAIN.log
61 | else
62 | echo "$ARGO_DOMAIN" > $WORKDIR/ARGO_DOMAIN.log
63 | ARGO_DOMAIN=$(cat "$WORKDIR/ARGO_DOMAIN.log" 2>/dev/null)
64 | fi
65 |
66 | if [[ -z "$UUID" ]] && [[ -f "$WORKDIR/UUID.txt" ]]; then
67 | UUID=$(cat "$WORKDIR/UUID.txt" 2>/dev/null)
68 | elif [[ -z "$UUID" ]] && [[ ! -f "$WORKDIR/UUID.txt" ]]; then
69 | UUID=$(uuidgen -r)
70 | echo "$UUID" > $WORKDIR/UUID.txt
71 | else
72 | echo "$UUID" > $WORKDIR/UUID.txt
73 | UUID=$(cat "$WORKDIR/UUID.txt" 2>/dev/null)
74 | fi
75 | curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/app.js -o "$keep_path"/app.js
76 | sed -i '' "15s/name/$snb/g" "$keep_path"/app.js
77 | sed -i '' "59s/key/$UUID/g" "$keep_path"/app.js
78 | sed -i '' "90s/name/$USERNAME/g" "$keep_path"/app.js
79 | sed -i '' "90s/where/$snb/g" "$keep_path"/app.js
80 | if [[ -z "$reym" ]] && [[ -f "$WORKDIR/reym.txt" ]]; then
81 | reym=$(cat "$WORKDIR/reym.txt" 2>/dev/null)
82 | elif [[ -z "$reym" ]] && [[ ! -f "$WORKDIR/reym.txt" ]]; then
83 | reym=$USERNAME.serv00.net
84 | echo "$reym" > $WORKDIR/reym.txt
85 | else
86 | echo "$reym" > $WORKDIR/reym.txt
87 | reym=$(cat "$WORKDIR/reym.txt" 2>/dev/null)
88 | fi
89 |
90 | resallport(){
91 | portlist=$(devil port list | grep -E '^[0-9]+[[:space:]]+[a-zA-Z]+' | sed 's/^[[:space:]]*//')
92 | if [[ -z "$portlist" ]]; then
93 | yellow "无端口"
94 | else
95 | while read -r line; do
96 | port=$(echo "$line" | awk '{print $1}')
97 | port_type=$(echo "$line" | awk '{print $2}')
98 | yellow "删除端口 $port ($port_type)"
99 | devil port del "$port_type" "$port"
100 | done <<< "$portlist"
101 | fi
102 | check_port
103 | hyp=$(jq -r '.inbounds[0].listen_port' $WORKDIR/config.json)
104 | vlp=$(jq -r '.inbounds[3].listen_port' $WORKDIR/config.json)
105 | vmp=$(jq -r '.inbounds[4].listen_port' $WORKDIR/config.json)
106 | sed -i '' "12s/$hyp/$hy2_port/g" $WORKDIR/config.json
107 | sed -i '' "33s/$hyp/$hy2_port/g" $WORKDIR/config.json
108 | sed -i '' "54s/$hyp/$hy2_port/g" $WORKDIR/config.json
109 | sed -i '' "75s/$vlp/$vless_port/g" $WORKDIR/config.json
110 | sed -i '' "102s/$vmp/$vmess_port/g" $WORKDIR/config.json
111 | sed -i '' -e "17s|'$vlp'|'$vless_port'|" serv00keep.sh
112 | sed -i '' -e "18s|'$vmp'|'$vmess_port'|" serv00keep.sh
113 | sed -i '' -e "19s|'$hyp'|'$hy2_port'|" serv00keep.sh
114 | ps aux | grep '[r]un -c con' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
115 | sleep 1
116 | curl -sk "http://${snb}.${USERNAME}.serv00.net/up" > /dev/null 2>&1
117 | sleep 5
118 | }
119 |
120 | okip(){
121 | IP_LIST=($(devil vhost list | awk '/^[0-9]+/ {print $1}'))
122 | API_URL="https://status.eooce.com/api"
123 | IP=""
124 | THIRD_IP=${IP_LIST[2]}
125 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${THIRD_IP}")
126 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then
127 | IP=$THIRD_IP
128 | else
129 | FIRST_IP=${IP_LIST[0]}
130 | RESPONSE=$(curl -s --max-time 2 "${API_URL}/${FIRST_IP}")
131 |
132 | if [[ $(echo "$RESPONSE" | jq -r '.status') == "Available" ]]; then
133 | IP=$FIRST_IP
134 | else
135 | IP=${IP_LIST[1]}
136 | fi
137 | fi
138 | echo "$IP"
139 | }
140 |
141 | check_port(){
142 | port_list=$(devil port list)
143 | tcp_ports=$(echo "$port_list" | grep -c "tcp")
144 | udp_ports=$(echo "$port_list" | grep -c "udp")
145 | if [[ $tcp_ports -ne 2 || $udp_ports -ne 1 ]]; then
146 | echo "端口数量不符合要求,正在调整..."
147 |
148 | if [[ $tcp_ports -gt 2 ]]; then
149 | tcp_to_delete=$((tcp_ports - 2))
150 | echo "$port_list" | awk '/tcp/ {print $1, $2}' | head -n $tcp_to_delete | while read port type; do
151 | devil port del $type $port
152 | echo "已删除TCP端口: $port"
153 | done
154 | fi
155 |
156 | if [[ $udp_ports -gt 1 ]]; then
157 | udp_to_delete=$((udp_ports - 1))
158 | echo "$port_list" | awk '/udp/ {print $1, $2}' | head -n $udp_to_delete | while read port type; do
159 | devil port del $type $port
160 | echo "已删除UDP端口: $port"
161 | done
162 | fi
163 |
164 | if [[ $tcp_ports -lt 2 ]]; then
165 | tcp_ports_to_add=$((2 - tcp_ports))
166 | tcp_ports_added=0
167 | while [[ $tcp_ports_added -lt $tcp_ports_to_add ]]; do
168 | tcp_port=$(shuf -i 10000-65535 -n 1)
169 | result=$(devil port add tcp $tcp_port 2>&1)
170 | if [[ $result == *"succesfully"* ]]; then
171 | echo "已添加TCP端口: $tcp_port"
172 | if [[ $tcp_ports_added -eq 0 ]]; then
173 | tcp_port1=$tcp_port
174 | else
175 | tcp_port2=$tcp_port
176 | fi
177 | tcp_ports_added=$((tcp_ports_added + 1))
178 | else
179 | echo "端口 $tcp_port 不可用,尝试其他端口..."
180 | fi
181 | done
182 | fi
183 |
184 | if [[ $udp_ports -lt 1 ]]; then
185 | while true; do
186 | udp_port=$(shuf -i 10000-65535 -n 1)
187 | result=$(devil port add udp $udp_port 2>&1)
188 | if [[ $result == *"succesfully"* ]]; then
189 | echo "已添加UDP端口: $udp_port"
190 | break
191 | else
192 | echo "端口 $udp_port 不可用,尝试其他端口..."
193 | fi
194 | done
195 | fi
196 | #echo "端口已调整完成,将断开ssh连接"
197 | sleep 3
198 | #devil binexec on >/dev/null 2>&1
199 | #kill -9 $(ps -o ppid= -p $$) >/dev/null 2>&1
200 | port_list=$(devil port list)
201 | tcp_ports=$(echo "$port_list" | grep -c "tcp")
202 | udp_ports=$(echo "$port_list" | grep -c "udp")
203 | tcp_ports=$(echo "$port_list" | awk '/tcp/ {print $1}')
204 | tcp_port1=$(echo "$tcp_ports" | sed -n '1p')
205 | tcp_port2=$(echo "$tcp_ports" | sed -n '2p')
206 | udp_port=$(echo "$port_list" | awk '/udp/ {print $1}')
207 | purple "当前TCP端口: $tcp_port1 和 $tcp_port2"
208 | purple "当前UDP端口: $udp_port"
209 | else
210 | tcp_ports=$(echo "$port_list" | awk '/tcp/ {print $1}')
211 | tcp_port1=$(echo "$tcp_ports" | sed -n '1p')
212 | tcp_port2=$(echo "$tcp_ports" | sed -n '2p')
213 | udp_port=$(echo "$port_list" | awk '/udp/ {print $1}')
214 | echo "你的vless-reality的TCP端口: $tcp_port1"
215 | echo "你的vmess的TCP端口(设置Argo固定域名端口):$tcp_port2"
216 | echo "你的hysteria2的UDP端口: $udp_port"
217 | fi
218 | export vless_port=$tcp_port1
219 | export vmess_port=$tcp_port2
220 | export hy2_port=$udp_port
221 | }
222 |
223 | get_argodomain() {
224 | if [[ -n $ARGO_AUTH ]]; then
225 | echo "$ARGO_DOMAIN" > ARGO_DOMAIN.log
226 | echo "$ARGO_DOMAIN"
227 | else
228 | local retry=0
229 | local max_retries=6
230 | local argodomain=""
231 | while [[ $retry -lt $max_retries ]]; do
232 | ((retry++))
233 | argodomain=$(cat boot.log 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
234 | if [[ -n $argodomain ]]; then
235 | break
236 | fi
237 | sleep 2
238 | done
239 | if [ -z ${argodomain} ]; then
240 | argodomain="Argo临时域名暂时获取失败,Argo节点暂不可用(保活过程中会自动恢复),其他节点依旧可用"
241 | fi
242 | echo "$argodomain"
243 | fi
244 | }
245 |
246 | if [ ! -f serv00keep.sh ]; then
247 | curl -sSL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/serv00keep.sh -o serv00keep.sh && chmod +x serv00keep.sh
248 | echo '#!/bin/bash
249 | red() { echo -e "\e[1;91m$1\033[0m"; }
250 | green() { echo -e "\e[1;32m$1\033[0m"; }
251 | yellow() { echo -e "\e[1;33m$1\033[0m"; }
252 | purple() { echo -e "\e[1;35m$1\033[0m"; }
253 | USERNAME=$(whoami | tr '\''[:upper:]'\'' '\''[:lower:]'\'')
254 | WORKDIR="${HOME}/domains/${USERNAME}.serv00.net/logs"
255 | snb=$(hostname | cut -d. -f1)
256 | ' > webport.sh
257 | declare -f resallport >> webport.sh
258 | declare -f check_port >> webport.sh
259 | echo 'resallport' >> webport.sh
260 | chmod +x webport.sh
261 | green "开始安装多功能主页,请稍等……"
262 | devil www del ${snb}.${USERNAME}.serv00.net > /dev/null 2>&1
263 | devil www add ${USERNAME}.serv00.net php > /dev/null 2>&1
264 | devil www add ${snb}.${USERNAME}.serv00.net nodejs /usr/local/bin/node18 > /dev/null 2>&1
265 | ln -fs /usr/local/bin/node18 ~/bin/node > /dev/null 2>&1
266 | ln -fs /usr/local/bin/npm18 ~/bin/npm > /dev/null 2>&1
267 | mkdir -p ~/.npm-global
268 | npm config set prefix '~/.npm-global'
269 | echo 'export PATH=~/.npm-global/bin:~/bin:$PATH' >> $HOME/.bash_profile && source $HOME/.bash_profile
270 | rm -rf $HOME/.npmrc > /dev/null 2>&1
271 | cd "$keep_path"
272 | npm install basic-auth express dotenv axios --silent > /dev/null 2>&1
273 | rm $HOME/domains/${snb}.${USERNAME}.serv00.net/public_nodejs/public/index.html > /dev/null 2>&1
274 | devil www restart ${snb}.${USERNAME}.serv00.net
275 | green "安装完毕,多功能主页地址:http://${snb}.${USERNAME}.serv00.net"
276 | fi
277 |
278 | if [[ "$resport" =~ ^[Yy]$ ]]; then
279 | portlist=$(devil port list | grep -E '^[0-9]+[[:space:]]+[a-zA-Z]+' | sed 's/^[[:space:]]*//')
280 | if [[ -z "$portlist" ]]; then
281 | yellow "无端口"
282 | else
283 | while read -r line; do
284 | port=$(echo "$line" | awk '{print $1}')
285 | port_type=$(echo "$line" | awk '{print $2}')
286 | yellow "删除端口 $port ($port_type)"
287 | devil port del "$port_type" "$port"
288 | done <<< "$portlist"
289 | fi
290 | check_port
291 | fi
292 | rm -rf $HOME/domains/${snb}.${USERNAME}.serv00.net/logs/*
293 |
294 | cd $WORKDIR
295 | ym=("$HOSTNAME" "cache$nb.serv00.com" "web$nb.serv00.com")
296 | rm -rf ip.txt
297 | for host in "${ym[@]}"; do
298 | response=$(curl -sL --connect-timeout 5 --max-time 7 "https://ss.fkj.pp.ua/api/getip?host=$host")
299 | if [[ "$response" =~ (unknown|not|error) ]]; then
300 | dig @8.8.8.8 +time=5 +short $host | sort -u >> ip.txt
301 | sleep 1
302 | else
303 | while IFS='|' read -r ip status; do
304 | if [[ $status == "Accessible" ]]; then
305 | echo "$ip: 可用" >> ip.txt
306 | else
307 | echo "$ip: 被墙 (Argo与CDN回源节点、proxyip依旧有效)" >> ip.txt
308 | fi
309 | done <<< "$response"
310 | fi
311 | done
312 | if [[ ! "$response" =~ (unknown|not|error) ]]; then
313 | grep ':' $WORKDIR/ip.txt | sort -u -o $WORKDIR/ip.txt
314 | fi
315 | if [[ -z "$IP" ]]; then
316 | IP=$(grep -m 1 "可用" ip.txt | awk -F ':' '{print $1}')
317 | if [ -z "$IP" ]; then
318 | IP=$(okip)
319 | if [ -z "$IP" ]; then
320 | IP=$(head -n 1 ip.txt | awk -F ':' '{print $1}')
321 | fi
322 | fi
323 | fi
324 |
325 | if [[ -z "$vless_port" ]] || [[ -z "$vmess_port" ]] || [[ -z "$hy2_port" ]]; then
326 | check_port
327 | fi
328 | if [ ! -s sb.txt ] && [ ! -s ag.txt ]; then
329 | DOWNLOAD_DIR="." && mkdir -p "$DOWNLOAD_DIR" && FILE_INFO=()
330 | FILE_INFO=("https://github.com/yonggekkk/Cloudflare_vless_trojan/releases/download/serv00/sb web" "https://github.com/yonggekkk/Cloudflare_vless_trojan/releases/download/serv00/server bot")
331 | declare -A FILE_MAP
332 | generate_random_name() {
333 | local chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
334 | local name=""
335 | for i in {1..6}; do
336 | name="$name${chars:RANDOM%${#chars}:1}"
337 | done
338 | echo "$name"
339 | }
340 |
341 | download_with_fallback() {
342 | local URL=$1
343 | local NEW_FILENAME=$2
344 |
345 | curl -L -sS --max-time 2 -o "$NEW_FILENAME" "$URL" &
346 | CURL_PID=$!
347 | CURL_START_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0)
348 |
349 | sleep 1
350 | CURL_CURRENT_SIZE=$(stat -c%s "$NEW_FILENAME" 2>/dev/null || echo 0)
351 |
352 | if [ "$CURL_CURRENT_SIZE" -le "$CURL_START_SIZE" ]; then
353 | kill $CURL_PID 2>/dev/null
354 | wait $CURL_PID 2>/dev/null
355 | wget -q -O "$NEW_FILENAME" "$URL"
356 | echo -e "\e[1;32mDownloading $NEW_FILENAME by wget\e[0m"
357 | else
358 | wait $CURL_PID
359 | echo -e "\e[1;32mDownloading $NEW_FILENAME by curl\e[0m"
360 | fi
361 | }
362 |
363 | for entry in "${FILE_INFO[@]}"; do
364 | URL=$(echo "$entry" | cut -d ' ' -f 1)
365 | RANDOM_NAME=$(generate_random_name)
366 | NEW_FILENAME="$DOWNLOAD_DIR/$RANDOM_NAME"
367 |
368 | if [ -e "$NEW_FILENAME" ]; then
369 | echo -e "\e[1;32m$NEW_FILENAME already exists, Skipping download\e[0m"
370 | else
371 | download_with_fallback "$URL" "$NEW_FILENAME"
372 | fi
373 |
374 | chmod +x "$NEW_FILENAME"
375 | FILE_MAP[$(echo "$entry" | cut -d ' ' -f 2)]="$NEW_FILENAME"
376 | done
377 | wait
378 | fi
379 |
380 | if [ ! -e private_key.txt ]; then
381 | output=$(./"$(basename ${FILE_MAP[web]})" generate reality-keypair)
382 | private_key=$(echo "${output}" | awk '/PrivateKey:/ {print $2}')
383 | public_key=$(echo "${output}" | awk '/PublicKey:/ {print $2}')
384 | echo "${private_key}" > private_key.txt
385 | echo "${public_key}" > public_key.txt
386 | fi
387 | private_key=$( config.json << EOF
392 | {
393 | "log": {
394 | "disabled": true,
395 | "level": "info",
396 | "timestamp": true
397 | },
398 | "inbounds": [
399 | {
400 | "tag": "hysteria-in1",
401 | "type": "hysteria2",
402 | "listen": "$(dig @8.8.8.8 +time=5 +short "web$nb.serv00.com" | sort -u)",
403 | "listen_port": $hy2_port,
404 | "users": [
405 | {
406 | "password": "$UUID"
407 | }
408 | ],
409 | "masquerade": "https://www.bing.com",
410 | "ignore_client_bandwidth":false,
411 | "tls": {
412 | "enabled": true,
413 | "alpn": [
414 | "h3"
415 | ],
416 | "certificate_path": "cert.pem",
417 | "key_path": "private.key"
418 | }
419 | },
420 | {
421 | "tag": "hysteria-in2",
422 | "type": "hysteria2",
423 | "listen": "$(dig @8.8.8.8 +time=5 +short "$HOSTNAME" | sort -u)",
424 | "listen_port": $hy2_port,
425 | "users": [
426 | {
427 | "password": "$UUID"
428 | }
429 | ],
430 | "masquerade": "https://www.bing.com",
431 | "ignore_client_bandwidth":false,
432 | "tls": {
433 | "enabled": true,
434 | "alpn": [
435 | "h3"
436 | ],
437 | "certificate_path": "cert.pem",
438 | "key_path": "private.key"
439 | }
440 | },
441 | {
442 | "tag": "hysteria-in3",
443 | "type": "hysteria2",
444 | "listen": "$(dig @8.8.8.8 +time=5 +short "cache$nb.serv00.com" | sort -u)",
445 | "listen_port": $hy2_port,
446 | "users": [
447 | {
448 | "password": "$UUID"
449 | }
450 | ],
451 | "masquerade": "https://www.bing.com",
452 | "ignore_client_bandwidth":false,
453 | "tls": {
454 | "enabled": true,
455 | "alpn": [
456 | "h3"
457 | ],
458 | "certificate_path": "cert.pem",
459 | "key_path": "private.key"
460 | }
461 | },
462 | {
463 | "tag": "vless-reality-vesion",
464 | "type": "vless",
465 | "listen": "::",
466 | "listen_port": $vless_port,
467 | "users": [
468 | {
469 | "uuid": "$UUID",
470 | "flow": "xtls-rprx-vision"
471 | }
472 | ],
473 | "tls": {
474 | "enabled": true,
475 | "server_name": "$reym",
476 | "reality": {
477 | "enabled": true,
478 | "handshake": {
479 | "server": "$reym",
480 | "server_port": 443
481 | },
482 | "private_key": "$private_key",
483 | "short_id": [
484 | ""
485 | ]
486 | }
487 | }
488 | },
489 | {
490 | "tag": "vmess-ws-in",
491 | "type": "vmess",
492 | "listen": "::",
493 | "listen_port": $vmess_port,
494 | "users": [
495 | {
496 | "uuid": "$UUID"
497 | }
498 | ],
499 | "transport": {
500 | "type": "ws",
501 | "path": "$UUID-vm",
502 | "early_data_header_name": "Sec-WebSocket-Protocol"
503 | }
504 | }
505 | ],
506 | "outbounds": [
507 | {
508 | "type": "wireguard",
509 | "tag": "wg",
510 | "server": "162.159.192.200",
511 | "server_port": 4500,
512 | "local_address": [
513 | "172.16.0.2/32",
514 | "2606:4700:110:8f77:1ca9:f086:846c:5f9e/128"
515 | ],
516 | "private_key": "wIxszdR2nMdA7a2Ul3XQcniSfSZqdqjPb6w6opvf5AU=",
517 | "peer_public_key": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
518 | "reserved": [
519 | 126,
520 | 246,
521 | 173
522 | ]
523 | },
524 | {
525 | "type": "direct",
526 | "tag": "direct"
527 | }
528 | ],
529 | "route": {
530 | "rule_set": [
531 | {
532 | "tag": "google-gemini",
533 | "type": "remote",
534 | "format": "binary",
535 | "url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/google-gemini.srs",
536 | "download_detour": "direct"
537 | }
538 | ],
539 | EOF
540 | if [[ "$nb" =~ 14|15 ]]; then
541 | cat >> config.json <> config.json < /dev/null; then
569 | ps aux | grep '[r]un -c con' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
570 | if [ -e "$(basename "${FILE_MAP[web]}")" ]; then
571 | echo "$(basename "${FILE_MAP[web]}")" > sb.txt
572 | sbb=$(cat sb.txt)
573 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
574 | sleep 5
575 | if pgrep -x "$sbb" > /dev/null; then
576 | green "$sbb 主进程已启动"
577 | else
578 | red "$sbb 主进程未启动, 重启中..."
579 | pkill -x "$sbb"
580 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
581 | sleep 2
582 | purple "$sbb 主进程已重启"
583 | fi
584 | else
585 | sbb=$(cat sb.txt)
586 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
587 | sleep 5
588 | if pgrep -x "$sbb" > /dev/null; then
589 | green "$sbb 主进程已启动"
590 | else
591 | red "$sbb 主进程未启动, 重启中..."
592 | pkill -x "$sbb"
593 | nohup ./"$sbb" run -c config.json >/dev/null 2>&1 &
594 | sleep 2
595 | purple "$sbb 主进程已重启"
596 | fi
597 | fi
598 | else
599 | green "主进程已启动"
600 | fi
601 | cfgo() {
602 | rm -rf boot.log
603 | if [ -e "$(basename "${FILE_MAP[bot]}")" ]; then
604 | echo "$(basename "${FILE_MAP[bot]}")" > ag.txt
605 | agg=$(cat ag.txt)
606 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then
607 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}"
608 | args="tunnel --no-autoupdate run --token ${ARGO_AUTH}"
609 | else
610 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$vmess_port"
611 | args="tunnel --url http://localhost:$vmess_port --no-autoupdate --logfile boot.log --loglevel info"
612 | fi
613 | nohup ./"$agg" $args >/dev/null 2>&1 &
614 | sleep 10
615 | if pgrep -x "$agg" > /dev/null; then
616 | green "$agg Arog进程已启动"
617 | else
618 | red "$agg Argo进程未启动, 重启中..."
619 | pkill -x "$agg"
620 | nohup ./"$agg" "${args}" >/dev/null 2>&1 &
621 | sleep 5
622 | purple "$agg Argo进程已重启"
623 | fi
624 | else
625 | agg=$(cat ag.txt)
626 | if [[ $ARGO_AUTH =~ ^[A-Z0-9a-z=]{120,250}$ ]]; then
627 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 run --token ${ARGO_AUTH}"
628 | args="tunnel --no-autoupdate run --token ${ARGO_AUTH}"
629 | else
630 | #args="tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile boot.log --loglevel info --url http://localhost:$vmess_port"
631 | args="tunnel --url http://localhost:$vmess_port --no-autoupdate --logfile boot.log --loglevel info"
632 | fi
633 | pkill -x "$agg"
634 | nohup ./"$agg" $args >/dev/null 2>&1 &
635 | sleep 10
636 | if pgrep -x "$agg" > /dev/null; then
637 | green "$agg Arog进程已启动"
638 | else
639 | red "$agg Argo进程未启动, 重启中..."
640 | pkill -x "$agg"
641 | nohup ./"$agg" "${args}" >/dev/null 2>&1 &
642 | sleep 5
643 | purple "$agg Argo进程已重启"
644 | fi
645 | fi
646 | }
647 |
648 | if [ -f "$WORKDIR/boot.log" ]; then
649 | argosl=$(cat "$WORKDIR/boot.log" 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
650 | checkhttp=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argosl")
651 | fi
652 | if ([ -z "$ARGO_DOMAIN" ] && ! ps aux | grep '[t]unnel --u' > /dev/null) || [[ "$checkhttp" != 404 ]]; then
653 | ps aux | grep '[t]unnel --u' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
654 | cfgo
655 | elif [ -n "$ARGO_DOMAIN" ] && ! ps aux | grep '[t]unnel --n' > /dev/null; then
656 | ps aux | grep '[t]unnel --n' | awk '{print $2}' | xargs -r kill -9 > /dev/null 2>&1
657 | cfgo
658 | else
659 | green "Arog进程已启动"
660 | fi
661 | sleep 2
662 | if ! pgrep -x "$(cat sb.txt)" > /dev/null; then
663 | red "主进程未启动,根据以下情况一一排查"
664 | yellow "1、REP选择y重置一次随机端口,三个端口参数留空不填,再改为n(重要)"
665 | yellow "2、RES选择y运行一次重置系统,再改为n(重要)"
666 | yellow "3、当前Serv00服务器炸了?等会再试"
667 | red "4、以上都试了,哥直接躺平,交给进程保活,过会再来看"
668 | fi
669 |
670 |
671 | argodomain=$(get_argodomain)
672 | rm -rf ${FILE_PATH}/*.txt
673 | echo -e "\e[1;32mArgo域名:\e[1;35m${argodomain}\e[0m\n"
674 | a=$(dig @8.8.8.8 +time=5 +short "web$nb.serv00.com" | sort -u)
675 | b=$(dig @8.8.8.8 +time=5 +short "$HOSTNAME" | sort -u)
676 | c=$(dig @8.8.8.8 +time=5 +short "cache$nb.serv00.com" | sort -u)
677 | if [[ "$IP" == "$a" ]]; then
678 | CIP1=$b; CIP2=$c
679 | elif [[ "$IP" == "$b" ]]; then
680 | CIP1=$a; CIP2=$c
681 | elif [[ "$IP" == "$c" ]]; then
682 | CIP1=$a; CIP2=$b
683 | else
684 | red "执行出错,请卸载脚本再重装一次"
685 | fi
686 | vl_link="vless://$UUID@$IP:$vless_port?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$reym&fp=chrome&pbk=$public_key&type=tcp&headerType=none#$snb-reality-$USERNAME"
687 | echo "$vl_link" > jh.txt
688 | vmws_link="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-$USERNAME\", \"add\": \"$IP\", \"port\": \"$vmess_port\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\", \"sni\": \"\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
689 | echo "$vmws_link" >> jh.txt
690 | vmatls_link="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME\", \"add\": \"www.visa.com.hk\", \"port\": \"8443\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
691 | echo "$vmatls_link" >> jh.txt
692 | vma_link="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME\", \"add\": \"www.visa.com.hk\", \"port\": \"8880\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
693 | echo "$vma_link" >> jh.txt
694 | hy2_link="hysteria2://$UUID@$IP:$hy2_port?security=tls&sni=www.bing.com&alpn=h3&insecure=1#$snb-hy2-$USERNAME"
695 | echo "$hy2_link" >> jh.txt
696 | vl_link1="vless://$UUID@$CIP1:$vless_port?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$reym&fp=chrome&pbk=$public_key&type=tcp&headerType=none#$snb-reality-$USERNAME-$CIP1"
697 | echo "$vl_link1" >> jh.txt
698 | vmws_link1="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-$USERNAME-$CIP1\", \"add\": \"$CIP1\", \"port\": \"$vmess_port\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\", \"sni\": \"\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
699 | echo "$vmws_link1" >> jh.txt
700 | hy2_link1="hysteria2://$UUID@$CIP1:$hy2_port?security=tls&sni=www.bing.com&alpn=h3&insecure=1#$snb-hy2-$USERNAME-$CIP1"
701 | echo "$hy2_link1" >> jh.txt
702 | vl_link2="vless://$UUID@$CIP2:$vless_port?encryption=none&flow=xtls-rprx-vision&security=reality&sni=$reym&fp=chrome&pbk=$public_key&type=tcp&headerType=none#$snb-reality-$USERNAME-$CIP2"
703 | echo "$vl_link2" >> jh.txt
704 | vmws_link2="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-$USERNAME-$CIP2\", \"add\": \"$CIP2\", \"port\": \"$vmess_port\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\", \"sni\": \"\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
705 | echo "$vmws_link2" >> jh.txt
706 | hy2_link2="hysteria2://$UUID@$CIP2:$hy2_port?security=tls&sni=www.bing.com&alpn=h3&insecure=1#$snb-hy2-$USERNAME-$CIP2"
707 | echo "$hy2_link2" >> jh.txt
708 |
709 | argosl=$(cat "$WORKDIR/boot.log" 2>/dev/null | grep -a trycloudflare.com | awk 'NR==2{print}' | awk -F// '{print $2}' | awk '{print $1}')
710 | checkhttp1=$(curl -o /dev/null -s -w "%{http_code}\n" "https://$argosl")
711 | argogd=$(cat $WORKDIR/ARGO_DOMAIN.log 2>/dev/null)
712 | checkhttp2=$(curl --max-time 2 -o /dev/null -s -w "%{http_code}\n" "https://$argogd")
713 | if [[ "$checkhttp1" == 404 ]] || [[ "$checkhttp2" == 404 ]]; then
714 | vmatls_link1="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-443\", \"add\": \"104.16.0.0\", \"port\": \"443\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
715 | echo "$vmatls_link1" >> jh.txt
716 | vmatls_link2="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2053\", \"add\": \"104.17.0.0\", \"port\": \"2053\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
717 | echo "$vmatls_link2" >> jh.txt
718 | vmatls_link3="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2083\", \"add\": \"104.18.0.0\", \"port\": \"2083\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
719 | echo "$vmatls_link3" >> jh.txt
720 | vmatls_link4="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2087\", \"add\": \"104.19.0.0\", \"port\": \"2087\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
721 | echo "$vmatls_link4" >> jh.txt
722 | vmatls_link5="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-tls-argo-$USERNAME-2096\", \"add\": \"104.20.0.0\", \"port\": \"2096\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"tls\", \"sni\": \"$argodomain\", \"alpn\": \"\", \"fp\": \"\"}" | base64 -w0)"
723 | echo "$vmatls_link5" >> jh.txt
724 | vma_link6="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-80\", \"add\": \"104.21.0.0\", \"port\": \"80\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
725 | echo "$vma_link6" >> jh.txt
726 | vma_link7="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-8080\", \"add\": \"104.22.0.0\", \"port\": \"8080\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
727 | echo "$vma_link7" >> jh.txt
728 | vma_link8="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2052\", \"add\": \"104.24.0.0\", \"port\": \"2052\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
729 | echo "$vma_link8" >> jh.txt
730 | vma_link9="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2082\", \"add\": \"104.25.0.0\", \"port\": \"2082\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
731 | echo "$vma_link9" >> jh.txt
732 | vma_link10="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2086\", \"add\": \"104.26.0.0\", \"port\": \"2086\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
733 | echo "$vma_link10" >> jh.txt
734 | vma_link11="vmess://$(echo "{ \"v\": \"2\", \"ps\": \"$snb-vmess-ws-argo-$USERNAME-2095\", \"add\": \"104.27.0.0\", \"port\": \"2095\", \"id\": \"$UUID\", \"aid\": \"0\", \"scy\": \"auto\", \"net\": \"ws\", \"type\": \"none\", \"host\": \"$argodomain\", \"path\": \"/$UUID-vm?ed=2048\", \"tls\": \"\"}" | base64 -w0)"
735 | echo "$vma_link11" >> jh.txt
736 | fi
737 | v2sub=$(cat jh.txt)
738 | echo "$v2sub" > ${FILE_PATH}/${UUID}_v2sub.txt
739 | baseurl=$(base64 -w 0 < jh.txt)
740 |
741 | cat > sing_box.json < clash_meta.yaml < ${FILE_PATH}/${UUID}_clashmeta.txt
1212 | cat sing_box.json > ${FILE_PATH}/${UUID}_singbox.txt
1213 | curl -sL https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/index.html -o "$FILE_PATH"/index.html
1214 | V2rayN_LINK="https://${USERNAME}.serv00.net/${UUID}_v2sub.txt"
1215 | Clashmeta_LINK="https://${USERNAME}.serv00.net/${UUID}_clashmeta.txt"
1216 | Singbox_LINK="https://${USERNAME}.serv00.net/${UUID}_singbox.txt"
1217 | hyp=$(jq -r '.inbounds[0].listen_port' config.json)
1218 | vlp=$(jq -r '.inbounds[3].listen_port' config.json)
1219 | vmp=$(jq -r '.inbounds[4].listen_port' config.json)
1220 | showuuid=$(jq -r '.inbounds[0].users[0].password' config.json)
1221 | cat > list.txt < event.waitUntil(handleScheduled()));
2 | // 配合甬哥的serv00的SSH脚本或者Github/VPS/软路由脚本,生成保活网页与重启网页
3 | // 每个保活/up网页或每个重启/re网页之间用空格或者,或者,间隔开,网页前带http://
4 | const urlString = 'http://保活或重启网页1 http://保活或重启网页2 http://保活或重启网页3 ………';
5 | const urls = urlString.split(/[\s,,]+/);
6 | const TIMEOUT = 5000;
7 | async function fetchWithTimeout(url) {
8 | const controller = new AbortController();
9 | const timeout = setTimeout(() => controller.abort(), TIMEOUT);
10 | try {
11 | await fetch(url, { signal: controller.signal });
12 | console.log(`✅ 成功: ${url}`);
13 | } catch (error) {
14 | console.warn(`❌ 访问失败: ${url}, 错误: ${error.message}`);
15 | } finally {
16 | clearTimeout(timeout);
17 | }
18 | }
19 | async function handleScheduled() {
20 | console.log('⏳ 任务开始');
21 | await Promise.all(urls.map(fetchWithTimeout));
22 | console.log('📊 任务结束');
23 | }
24 |
--------------------------------------------------------------------------------