Compare commits

..

36 Commits

Author SHA1 Message Date
spiritlhl
7c19502950 fix:部分测速成功也输出,但补充节点测速 2026-01-16 14:02:42 +08:00
spiritlhl
3c434781f5 fix:修复私有测速节点可能存在部分上传下载测速失败的问题,自动轮换 2026-01-16 14:00:53 +08:00
spiritlhl
f62636ca3e fix:回退upx安装步骤,实际受限于编译的镜像不可直接进行安装 2026-01-13 20:00:59 +08:00
spiritlhl
c4b11ae37d fix: Install UPX in build workflow
Added step to install UPX for binary compression.
2026-01-13 19:57:55 +08:00
github-actions[bot]
8f2fe236d5 chore: update ECS_VERSION to 0.1.111 in goecs.sh 2026-01-13 11:56:25 +00:00
spiritlhl
347a0faa7a fix:添加UPX操作压缩减小产物大小 2026-01-13 19:42:41 +08:00
spiritlhl
74640e3066 fix:更新版本 2026-01-13 19:36:24 +08:00
spiritlhl
3b646eeeda fix:修复错误的格式化字符 2026-01-13 19:35:39 +08:00
github-actions[bot]
eaad433395 chore: update ECS_VERSION to 0.1.110 in goecs.sh 2026-01-13 04:28:12 +00:00
spiritlhl
03af7c423b Bump ecsVersion to v0.1.110 2026-01-13 12:12:40 +08:00
spiritlhl
0e96a6499b Update build_binary.yaml to disable certain options
Disable large packages, Docker images, and swap storage in the build workflow.
2026-01-13 12:03:44 +08:00
spiritlhl
5b44f5f651 fix:修复编译占用的磁盘过大的问题 2026-01-13 11:49:57 +08:00
spiritlhl
e4a759fceb fix:修改非选项1时的测速逻辑,区分中英文测速使用不同的节点逻辑 2026-01-13 11:23:21 +08:00
spiritlhl
e5c4b0ce8e Clean up newlines in create_public_branch.py
Remove unnecessary newlines around specific strings in content.
2026-01-12 23:48:03 +08:00
spiritsoul
188a1153e6 fix:删除对应的依赖 2026-01-12 23:40:58 +08:00
spiritsoul
4c4887f487 fix:以文本结构匹配避免正则匹配越界 2026-01-12 23:31:27 +08:00
spiritsoul
feac73a427 fix:修复正则匹配 2026-01-12 23:28:45 +08:00
spiritlhl
f3048d074c Clean up Go module cache and remove go.sum 2026-01-12 23:19:18 +08:00
spiritlhl
58702b54e7 Remove privatespeedtest code from speed.go
Brutally remove privatespeedtest-related code from speed.go, ensuring the file remains syntactically correct.
2026-01-12 23:16:49 +08:00
spiritlhl
1e4d63ef57 Update Go version to 1.25.4 in workflow 2026-01-12 23:08:23 +08:00
spiritlhl
9f3acacae0 Disable modify_go_mod function and related calls
Comment out the modify_go_mod function and its calls.
2026-01-12 23:07:43 +08:00
spiritlhl
e9755f0c20 Refine speed test description in README.md 2026-01-12 23:01:19 +08:00
GitHub Actions
d8b397b31b Auto update README files 2026-01-12 14:41:00 +00:00
github-actions[bot]
9e22d1bc23 chore: update ECS_VERSION to 0.1.108 in goecs.sh 2026-01-12 14:37:10 +00:00
spiritlhl
284f6b8ba7 fix: 修复误删除的md文件 2026-01-12 14:22:34 +00:00
spiritlhl
27203cf850 fix:修复公共分支生成的Action,使用更完善的python脚本完成修复 2026-01-12 14:21:43 +00:00
spiritlhl
9b6922f55a fix:升级回程测试的nexttrace核心版本 2026-01-12 14:15:13 +00:00
spiritlhl
447b25989e fix:修复预设 2026-01-12 14:13:29 +00:00
github-actions[bot]
a50b68d184 chore: update ECS_VERSION to 0.1.107 in goecs.sh 2026-01-12 13:36:44 +00:00
spiritlhl
6b68e643c7 fix:更新主程序版本 2026-01-12 13:22:47 +00:00
spiritlhl
14c79b9a89 feat:添加私有测速平台节点测速,原测速平台节点仅作为备用方式 2026-01-12 13:21:29 +00:00
github-actions[bot]
60ae7ec3c3 chore: update ECS_VERSION to 0.1.106 in goecs.sh 2025-12-18 04:23:44 +00:00
spiritlhl
3d78128f6a fix:更新版本 2025-12-18 03:39:23 +00:00
spiritlhl
9c67a8d446 fix: 更新内存测试方法逻辑,增强对不同测试方法的支持 2025-12-18 03:35:45 +00:00
spiritlhl
014dba0ce6 feat: 添加更短的短链链接,默认不再进行任何环境安装 2025-11-29 02:49:56 +00:00
github-actions[bot]
b5fdab4b27 chore: update ECS_VERSION to 0.1.105 in goecs.sh 2025-11-26 07:43:20 +00:00
15 changed files with 852 additions and 109 deletions

310
.back/create_public_branch.py Executable file
View File

@@ -0,0 +1,310 @@
#!/usr/bin/env python3
"""
Script to create public branch by removing security dependencies and references.
This script properly handles Go file modifications to ensure the code can compile.
"""
import re
import os
import sys
import shutil
def read_file(filepath):
"""Read file content."""
with open(filepath, 'r', encoding='utf-8') as f:
return f.read()
def write_file(filepath, content):
"""Write content to file."""
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
def modify_go_mod(filepath):
"""
Modify go.mod to remove privatespeedtest (and optional security) dependencies.
Automatically matches module names regardless of version or indirect comment.
"""
content = read_file(filepath)
# Modules to remove
remove_modules = [
r'github\.com/oneclickvirt/privatespeedtest',
r'github\.com/oneclickvirt/security',
]
for mod in remove_modules:
# Remove full require line (with or without // indirect)
content = re.sub(
rf'^[ \t]*{mod}[ \t]+v[^\s]+(?:[ \t]+// indirect)?[ \t]*\n',
'',
content,
flags=re.MULTILINE
)
write_file(filepath, content)
print(f"✓ Removed privatespeedtest/security from {filepath}")
def remove_code_block(lines, start_marker, end_condition='empty_line'):
"""
Remove code block from lines starting with start_marker.
Args:
lines: List of file lines
start_marker: String or list of strings to identify block start
end_condition: 'empty_line' (default) or 'closing_brace' or custom function
Returns:
Modified lines with the block removed
"""
if isinstance(start_marker, str):
start_marker = [start_marker]
result = []
skip_mode = False
brace_depth = 0
i = 0
while i < len(lines):
line = lines[i]
# Check if we should start skipping
if not skip_mode:
for marker in start_marker:
if marker in line:
skip_mode = True
if end_condition == 'closing_brace':
# Count opening braces on the function declaration line
brace_depth = line.count('{') - line.count('}')
break
if not skip_mode:
result.append(line)
else:
# We're in skip mode
if end_condition == 'empty_line':
# Skip until we find an empty line
if line.strip() == '':
skip_mode = False
# Don't add the empty line, continue to next
elif end_condition == 'closing_brace':
# Track brace depth
brace_depth += line.count('{') - line.count('}')
if brace_depth == 0 and '}' in line:
# Function ended, skip until next empty line
end_condition = 'empty_line'
i += 1
return result
def modify_speed_go(filepath):
"""
Remove privatespeedtest-related code from speed.go.
Uses line-by-line processing for reliability.
"""
content = read_file(filepath)
lines = content.split('\n')
# Remove specific code blocks by their comment markers
blocks_to_remove = [
'// formatString 格式化字符串到指定宽度',
'// printTableRow 打印表格行',
'// privateSpeedTest 使用 privatespeedtest 进行单个运营商测速',
'// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点',
'// 对于三网测速cmcc、cu、ct和 other优先使用 privatespeedtest 进行私有测速',
]
for block_marker in blocks_to_remove:
lines = remove_code_block(lines, block_marker)
# Reconstruct content
content = '\n'.join(lines)
# Remove privatespeedtest import
content = re.sub(
r'\n\s*"github\.com/oneclickvirt/privatespeedtest/pst"\s*\n',
'\n',
content,
flags=re.MULTILINE
)
# Remove time import (only used by privatespeedtest)
content = re.sub(
r'\n\s*"time"\s*\n',
'\n',
content,
flags=re.MULTILINE
)
# Clean up multiple consecutive empty lines (optional)
content = re.sub(r'\n{3,}', '\n\n', content)
write_file(filepath, content)
print(f"✓ Removed privatespeedtest from {filepath}")
def modify_utils_go(filepath):
"""
Modify utils/utils.go to:
1. Replace security/network import with basics/network
2. Replace SecurityUploadToken usage with hardcoded token
"""
content = read_file(filepath)
# Replace import
content = re.sub(
r'"github\.com/oneclickvirt/security/network"',
r'"github.com/oneclickvirt/basics/network"',
content
)
# Replace token usage - find the exact line and replace it
content = re.sub(
r'\ttoken := network\.SecurityUploadToken',
r'\ttoken := "OvwKx5qgJtf7PZgCKbtyojSU.MTcwMTUxNzY1MTgwMw"',
content
)
# Update title for public version
content = re.sub(
r'VPS融合怪测试',
r'VPS融合怪测试(非官方编译)',
content
)
content = re.sub(
r'VPS Fusion Monster Test',
r'VPS Fusion Monster Test (Unofficial)',
content
)
write_file(filepath, content)
print(f"✓ Modified {filepath}")
def modify_params_go(filepath):
"""
Modify internal/params/params.go to change security flag default to false.
"""
content = read_file(filepath)
# Change default value in struct initialization
content = re.sub(
r'(\s+SecurityTestStatus:\s+)true,',
r'\1false,',
content
)
# Change flag default value
content = re.sub(
r'(c\.GoecsFlag\.BoolVar\(&c\.SecurityTestStatus, "security", )true(, "Enable/Disable security test"\))',
r'\1false\2',
content
)
write_file(filepath, content)
print(f"✓ Modified {filepath}")
def modify_readme(filepath, is_english=False):
"""
Modify README files to update Go version and security status.
"""
content = read_file(filepath)
# Extract Go version from go.mod
go_mod_content = read_file('go.mod')
go_version_match = re.search(r'^go (\d+\.\d+(?:\.\d+)?)', go_mod_content, re.MULTILINE)
if not go_version_match:
print(f"⚠ Warning: Could not extract Go version from go.mod")
return
go_version = go_version_match.group(1)
if is_english:
# Update Go version in English README
content = re.sub(
r'Select go \d+\.\d+\.\d+ version to install',
f'Select go {go_version} version to install',
content
)
# Update security status
content = re.sub(
r'but binary files compiled in \[securityCheck\][^\)]*\)',
'but open sourced',
content
)
# Update help text for security flag
content = re.sub(
r'security\s+Enable/Disable security test \(default true\)',
'security Enable/Disable security test (default false)',
content
)
else:
# Update Go version in Chinese README
content = re.sub(
r'选择 go \d+\.\d+\.\d+ 的版本进行安装',
f'选择 go {go_version} 的版本进行安装',
content
)
# Update security status
content = re.sub(
r'但二进制文件编译至 \[securityCheck\][^\)]*\)',
'但已开源',
content
)
# Update help text for security flag
content = re.sub(
r'security\s+Enable/Disable security test \(default true\)',
'security Enable/Disable security test (default false)',
content
)
write_file(filepath, content)
print(f"✓ Modified {filepath}")
def main():
"""Main function to process all files."""
print("Starting public branch creation process...")
print()
# Check if we're in the right directory
if not os.path.exists('go.mod'):
print("Error: go.mod not found. Please run this script from the project root.")
sys.exit(1)
# Modify Go source files
print("Modifying Go source files...")
modify_speed_go('internal/tests/speed.go')
modify_utils_go('utils/utils.go')
modify_params_go('internal/params/params.go')
print()
# Modify go.mod
print("Modifying go.mod...")
modify_go_mod('go.mod')
print()
# Modify README files
print("Modifying README files...")
modify_readme('README.md', is_english=False)
modify_readme('README_EN.md', is_english=True)
print()
print("✓ All modifications completed successfully!")
print()
print("Next steps:")
print("1. Run 'go mod tidy' to clean up dependencies")
print("2. Run 'go build -o maintest' to verify compilation")
print("3. Test the binary with: ./maintest -menu=false -l en -security=false -upload=false")
if __name__ == '__main__':
main()

View File

@@ -19,11 +19,31 @@ jobs:
with:
fetch-depth: 0
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
# all of these default to true, but feel free to set to
# "false" if necessary for your workflow
android: true
dotnet: true
haskell: true
large-packages: false
docker-images: false
swap-storage: false
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.25.3
go-version: 1.25.4
# - name: Install UPX
# run: |
# apk add --no-cache upx
- name: Configure Git for Private Modules
run: |
git config --global url."https://${{ secrets.GHT }}@github.com/".insteadOf "https://github.com/"
@@ -31,16 +51,21 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GHT }}
- name: Clean Go cache before build
run: |
go clean -cache -modcache -testcache
df -h
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
# version: latest
version: '~> v2'
args: release
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GHT }}
GOPRIVATE: github.com/oneclickvirt/security
GOPRIVATE: github.com/oneclickvirt/security,github.com/oneclickvirt/privatespeedtest
- name: Update goecs.sh with new version
run: |

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25.3'
go-version: '1.25.4'
- name: Update master branch README files
run: |
@@ -61,42 +61,15 @@ jobs:
- name: Remove security package references
run: |
find . -type f -name "*.go" -exec sed -i 's|"github.com/oneclickvirt/security/network"|"github.com/oneclickvirt/basics/network"|g' {} +
sed -i '/SecurityUploadToken/d' utils/utils.go
sed -i 's|"github.com/oneclickvirt/security/network"|"github.com/oneclickvirt/basics/network"|g' utils/utils.go
sed -i '/^import/,/^)/{/^)/a\'$'\n''const token = "OvwKx5qgJtf7PZgCKbtyojSU.MTcwMTUxNzY1MTgwMw"'$'\n''}' utils/utils.go
sed -i '/github.com\/oneclickvirt\/security/d' go.mod
sed -i 's|var securityFlag = flag.Bool("security", true,|var securityFlag = flag.Bool("security", false,|g' goecs.go
sed -i 's|VPS融合怪测试|VPS融合怪测试(非官方编译)|g' utils/utils.go
sed -i 's|VPS Fusion Monster Test|VPS Fusion Monster Test (Unofficial)|g' utils/utils.go
python3 .back/create_public_branch.py
rm -f go.sum
go clean -modcache
go clean -cache -testcache -fuzzcache
go mod tidy
sed -i 's|但二进制文件编译至 \[securityCheck\].*)|但已开源|g' README.md
sed -i 's|but binary files compiled in \[securityCheck\].*)|but open sourced|g' README_EN.md
sed -i 's|security.*Enable/Disable security test (default true)|security Enable/Disable security test (default false)|g' README.md
sed -i 's|security.*Enable/Disable security test (default true)|security Enable/Disable security test (default false)|g' README_EN.md
- name: Update Go version in README files
run: |
if [ -f "go.mod" ]; then
GO_VERSION=$(grep "^go " go.mod | head -n 1 | awk '{print $2}')
echo "提取到的 Go 版本: $GO_VERSION"
if [ -n "$GO_VERSION" ] && [[ "$GO_VERSION" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
echo "版本验证成功,开始替换..."
if [ -f "README.md" ]; then
sed -i "s/选择 go [0-9]\+\.[0-9]\+\.[0-9]\+ 的版本进行安装/选择 go $GO_VERSION 的版本进行安装/g" README.md
echo "已更新 README.md"
fi
if [ -f "README_EN.md" ]; then
sed -i "s/Select go [0-9]\+\.[0-9]\+\.[0-9]\+ version to install/Select go $GO_VERSION version to install/g" README_EN.md
echo "已更新 README_EN.md"
fi
else
echo "错误:未能提取到有效的 Go 版本号或版本号格式不正确"
exit 1
fi
else
echo "错误:未找到 go.mod 文件"
exit 1
fi
# This step is now handled by the Python script
echo "README files already updated by create_public_branch.py"
- name: Build and Test
run: |
go build -o maintest

View File

@@ -1,6 +1,10 @@
before:
hooks:
- go mod tidy -v
- go clean -cache
project_name: goecs
builds:
- id: universal
env:
@@ -31,6 +35,7 @@ builds:
goarch: arm
main: ./
binary: goecs
- id: darwin-amd64
env:
- CGO_ENABLED=1
@@ -44,6 +49,7 @@ builds:
- amd64
main: ./
binary: goecs
- id: darwin-arm64
env:
- CGO_ENABLED=1
@@ -57,18 +63,23 @@ builds:
- arm64
main: ./
binary: goecs
universal_binaries:
- name_template: "goecs"
replace: false
checksum:
name_template: "checksums.txt"
snapshot:
name_template: "goecs"
archives:
- name_template: "goecs_{{ .Os }}_{{ .Arch }}"
format: zip
files:
- none*
changelog:
sort: asc
filters:
@@ -79,4 +90,18 @@ changelog:
- Merge pull request
- Merge branch
- go mod tidy
- New translations
- New translations
upx:
- enabled: true
brute: true
goos:
- linux
- windows
goarch:
- amd64
- 386
- arm64
- ppc64le
- s390x
- riscv64

View File

@@ -60,7 +60,7 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
- 邮件端口测试:[portchecker](https://github.com/oneclickvirt/portchecker)
- 上游及回程路由线路检测:借鉴 [zhanghanyun/backtrace](https://github.com/zhanghanyun/backtrace),二次开发至 [oneclickvirt/backtrace](https://github.com/oneclickvirt/backtrace)
- 三网路由测试:基于 [NTrace-core](https://github.com/nxtrace/NTrace-core),二次开发至 [nt3](https://github.com/oneclickvirt/nt3)
- 网速测试:基于 [speedtest.net](https://github.com/spiritLHLS/speedtest.net-CN-ID) 和 [speedtest.cn](https://github.com/spiritLHLS/speedtest.cn-CN-ID) 数据,开发 [oneclickvirt/speedtest](https://github.com/oneclickvirt/speedtest)
- 网速测试:基于 [speedtest.net](https://github.com/spiritLHLS/speedtest.net-CN-ID) 和 [speedtest.cn](https://github.com/spiritLHLS/speedtest.cn-CN-ID) 数据,开发 [oneclickvirt/speedtest](https://github.com/oneclickvirt/speedtest),同时融合私有国内测速节点
- 三网 Ping 值测试:借鉴 [ecsspeed](https://github.com/spiritLHLS/ecsspeed),二次开发至 [pingtest](https://github.com/oneclickvirt/pingtest)
- 支持root或admin环境下测试支持非root或非admin环境下测试支持离线环境下进行测试**暂未**支持无DNS的在线环境下进行测试
@@ -74,35 +74,43 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
#### **一键命令**
**一键命令**将**默认安装依赖****默认更新包管理器****默认非互动模式**
**一键命令**将默认**不安装依赖**,默认**不更新包管理器**,默认**非互动模式**
- **国际用户无加速:**
```bash
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
- **国际/国内使用 CDN 加速:**
```bash
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
- **国内用户使用 CNB 加速:**
```bash
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
- **短链接:**
```bash
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
```bash
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
**如果需要测试更准确,请按照下面的详细说明进行安装,添加非必需的依赖**
#### **详细说明**
**详细说明**中的命令**可控制是否安装依赖****是否更新包管理器****默认互动模式可进行选择**
以下命令可控制**是否安装依赖****是否更新包管理器****互动模式和非交互模式**
<details>
<summary>展开查看详细说明</summary>
@@ -325,7 +333,7 @@ cd ecs
2. 安装 Go 环境(如已安装可跳过)
选择 go 1.25.3 的版本进行安装
选择 go 1.25.4 的版本进行安装
```bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh

View File

@@ -74,35 +74,43 @@ Shell version: [https://github.com/spiritLHLS/ecs/blob/main/README_EN.md](https:
#### **One-click command**
**One-Click Command** will **Install Dependencies by Default**, **Update Package Manager by Default**, **Default Non-Interactive Mode***
**One-Click Command** will **Not install Dependencies** by Default, **Not update Package Manager** by Default, **Non-Interactive Mode** by Default.
- **International users without acceleration:**
```bash
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
- **International/domestic users with CDN acceleration:**
```bash
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
- **Domestic users with CNB acceleration:**
```bash
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
- **Short Link:**
```bash
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
``
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && bash goecs.sh install && goecs
```
OR
```bash
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
```
**For more accurate testing, please follow the detailed instructions below to install and add non-essential dependencies**
#### **Detailed instructions**
**Detailed description** of the commands in **Command **Controls whether to install dependencies**, **Whether to update the package manager**, **Default interaction mode can be selected***
The following commands control whether dependencies are installed, whether the package manager is updated, and whether interactive or non-interactive mode is used.
<details>
<summary>Expand to view detailed instructions</summary>
@@ -322,7 +330,7 @@ cd ecs
2. Install Go environment (skip if already installed)
Select go 1.25.3 version to install
Select go 1.25.4 version to install
```bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh

View File

@@ -482,6 +482,8 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
先测的官方推荐的测速点然后测有代表性的国际测速点最后测国内三大运营商ping值最低的测速点。
由于 speedtest.net 和 speedtest.cn 平台公开的测速节点被刷BTPT的刷烂了(他们为了对等上传PCDN的流量狂刷下载)所以这块本人独家融合的境内私有测速节点不再公开优先使用私有的境内运营商测速节点进行测速且写死限制每个IP每日仅支持获取测速数据10次超限自动降级为使用公共测速节点进行测速
境内使用为主就看境内测速即可,境外使用看境外测速,官方测速点可以代表受测的宿主机本地带宽基准。
一般来说中国境外的服务器的带宽100Mbps起步中国境内的服务器1Mbps带宽起步具体看线路优劣带宽特别大有时候未必用得上够用就行了。

35
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/oneclickvirt/ecs
go 1.25.3
go 1.25.4
require (
github.com/imroc/req/v3 v3.54.0
@@ -11,8 +11,8 @@ require (
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
github.com/oneclickvirt/disktest v0.0.10-20250924030424
github.com/oneclickvirt/gostun v0.0.5-20250727155022
github.com/oneclickvirt/memorytest v0.0.10-20250924154648
github.com/oneclickvirt/nt3 v0.0.10-20251111095706
github.com/oneclickvirt/memorytest v0.0.10-20251218032900
github.com/oneclickvirt/nt3 v0.0.11-20260112140912
github.com/oneclickvirt/pingtest v0.0.9-20251104112920
github.com/oneclickvirt/portchecker v0.0.3-20250728015900
github.com/oneclickvirt/security v0.0.8-20251112080734
@@ -56,10 +56,11 @@ require (
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nxtrace/NTrace-core v1.4.3-rc.1 // indirect
github.com/nxtrace/NTrace-core v1.5.0 // indirect
github.com/oneclickvirt/dd v0.0.2-20250808062818 // indirect
github.com/oneclickvirt/fio v0.0.2-20250808045755 // indirect
github.com/oneclickvirt/mbw v0.0.1-20250808061222 // indirect
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218 // indirect
github.com/oneclickvirt/stream v0.0.2-20250924154001 // indirect
github.com/oschwald/maxminddb-golang v1.13.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
@@ -72,12 +73,12 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus-community/pro-bing v0.4.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.53.0 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/refraction-networking/utls v1.7.3 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rodaine/table v1.3.0 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/schollz/progressbar/v3 v3.14.4 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/schollz/progressbar/v3 v3.17.1 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/showwin/speedtest-go v1.7.10 // indirect
@@ -88,25 +89,25 @@ require (
github.com/spf13/viper v1.21.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/tsosunchia/powclient v0.2.0 // indirect
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.5.2 // indirect
go.uber.org/mock v0.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.44.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/tools v0.38.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.0 // indirect
)

38
go.sum
View File

@@ -94,6 +94,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nxtrace/NTrace-core v1.4.3-rc.1 h1:V19tkw3kKAMQOOh7Ibb/jZFBk4kMUfQYmpxxtsOfYWo=
github.com/nxtrace/NTrace-core v1.4.3-rc.1/go.mod h1:lGhfZ916pEUJh+VzWZTYu7bKBo06pAn+/gXb0A/7gGg=
github.com/nxtrace/NTrace-core v1.5.0 h1:n+a/FObw/+CcqvhuSQiWcm1q+ODtfo7Wt3VmaIx504I=
github.com/nxtrace/NTrace-core v1.5.0/go.mod h1:/jME48iJ7QaVTzsrTPQyTJ+yExhjeWjax2L6uBd4ckk=
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725 h1:VaaK2v17nLGU8FQmJRXPe2bEESzRePbGws0bfq7s/2o=
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
github.com/oneclickvirt/backtrace v0.0.8-20251109090457 h1:599/R/qMAtfPCPG1bPoi6KbjNJzVkKtxm8dvVIdtn5o=
@@ -114,14 +116,20 @@ github.com/oneclickvirt/gostun v0.0.5-20250727155022 h1:/e3gSUrOp1tg/1NTRx+P8B51
github.com/oneclickvirt/gostun v0.0.5-20250727155022/go.mod h1:pfp7MFZJK9n/KTLAVqqFcCAns4xqMykmjI+1UeF/vdE=
github.com/oneclickvirt/mbw v0.0.1-20250808061222 h1:WGXOe6QvHiDRhPVMI0VcctjzW08kGvJf50yq5YeZCtw=
github.com/oneclickvirt/mbw v0.0.1-20250808061222/go.mod h1:0Vq6NRpyLmGUdfHfL3uDcFsuZhi7KlG+OCs5ky2757Y=
github.com/oneclickvirt/memorytest v0.0.10-20250924154648 h1:trk6oZ7xs1eVtr+6oIv5IX8LDVtEMG+E6GVzQ810BtU=
github.com/oneclickvirt/memorytest v0.0.10-20250924154648/go.mod h1:4kiHsEWkW9r3/1ZcV5xIweU0smiKP0IRfQj74AUIiVI=
github.com/oneclickvirt/memorytest v0.0.10-20251218032900 h1:SmRFfPLyGfTVWIgC50lEGgOpbqahtMHIlyOMSbrhj9Y=
github.com/oneclickvirt/memorytest v0.0.10-20251218032900/go.mod h1:4kiHsEWkW9r3/1ZcV5xIweU0smiKP0IRfQj74AUIiVI=
github.com/oneclickvirt/nt3 v0.0.10-20251111095706 h1:GEdgL6oAWXY80NIq23mLjcTR3gvLGh9iusFzJK6SoDo=
github.com/oneclickvirt/nt3 v0.0.10-20251111095706/go.mod h1:yo1ufkduFt9QjqG7nqSUf1D3YlQOmFpdlTYniJfclQI=
github.com/oneclickvirt/nt3 v0.0.11-20260112140912 h1:e3tgkEmydsML6ziOdWwsVGwysTRYS82SuWrP0HnIw9g=
github.com/oneclickvirt/nt3 v0.0.11-20260112140912/go.mod h1:u/y3sMhyt4wiQlR7yS68CudwjXCa/4V6ozWI7awsCws=
github.com/oneclickvirt/pingtest v0.0.9-20251104112920 h1:j3Fjhy0YHT/VF7iuAVVELaRXkquvRd64tWWfFLJs01o=
github.com/oneclickvirt/pingtest v0.0.9-20251104112920/go.mod h1:gxwsxxwitNQiGq2OI0ZogYoOLwc8DtuOdSRe6/EvRqs=
github.com/oneclickvirt/portchecker v0.0.3-20250728015900 h1:AomzdppSOFB70AJESQhlp0IPbsHTTJGimAWDk2TzCWM=
github.com/oneclickvirt/portchecker v0.0.3-20250728015900/go.mod h1:9sjMDPCd4Z40wkYB0S9gQPGH8YPtnNE1ZJthVIuHUzA=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112095218 h1:VcglFz85LVPo8wE8AkBhgXHHUUVI2Ae9ng6+hY6ewx4=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112095218/go.mod h1:IXOlKKX4DUNqxOaW/K9bcdrBiWxo0jGSLXeBeo7NrTo=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218 h1:h2k2fHtrsIIP/x/apEWkQGlTKuIumz8GrUR/df41YhE=
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218/go.mod h1:IXOlKKX4DUNqxOaW/K9bcdrBiWxo0jGSLXeBeo7NrTo=
github.com/oneclickvirt/security v0.0.8-20251112080734 h1:WpwdGbwpiBP2YA1lNsymati5uvBbWFlN9CXHYgd3/fE=
github.com/oneclickvirt/security v0.0.8-20251112080734/go.mod h1:aPMIwqsz7wiUH1cqvtRr9+QcQRkKzlUWecDM6SGVddc=
github.com/oneclickvirt/speedtest v0.0.11-20251102151740 h1:1NUrNt5ay6/xVNC5x62UrQjPqK8jgbKtyjBml/3boZg=
@@ -155,6 +163,8 @@ github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.53.0 h1:QHX46sISpG2S03dPeZBgVIZp8dGagIaiu2FiVYvpCZI=
github.com/quic-go/quic-go v0.53.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -166,8 +176,12 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/schollz/progressbar/v3 v3.14.4 h1:W9ZrDSJk7eqmQhd3uxFNNcTr0QL+xuGNI9dEMrw0r74=
github.com/schollz/progressbar/v3 v3.14.4/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
@@ -202,6 +216,8 @@ github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
@@ -222,6 +238,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
@@ -235,12 +253,16 @@ golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -251,12 +273,16 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -274,6 +300,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -283,6 +311,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -291,6 +321,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@@ -298,6 +330,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -27,7 +27,7 @@ import (
)
var (
ecsVersion = "v0.1.105" // 融合怪版本号
ecsVersion = "v0.1.112" // 融合怪版本号
configs = params.NewConfig(ecsVersion) // 全局配置实例
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
)

View File

@@ -152,7 +152,7 @@ goecs_check() {
os=$(uname -s 2>/dev/null || echo "Unknown")
arch=$(uname -m 2>/dev/null || echo "Unknown")
check_china
ECS_VERSION="0.1.104"
ECS_VERSION="0.1.111"
for api in \
"https://api.github.com/repos/oneclickvirt/ecs/releases/latest" \
"https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest" \
@@ -164,8 +164,8 @@ goecs_check() {
sleep 1
done
if [ -z "$ECS_VERSION" ]; then
_yellow "Unable to get version info, using default version 0.1.104"
ECS_VERSION="0.1.104"
_yellow "Unable to get version info, using default version 0.1.111"
ECS_VERSION="0.1.111"
fi
version_output=""
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do

View File

@@ -330,6 +330,8 @@ func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string,
fmt.Println(pt.WebsiteTest())
}
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(300 * time.Millisecond)
}, tempOutput, output)
}
@@ -348,10 +350,22 @@ func RunSpeedTests(config *params.Config, output, tempOutput string, outputMutex
tests.CustomSP("net", "ct", config.SpNum, config.Language)
tests.CustomSP("net", "cmcc", config.SpNum, config.Language)
} else if config.Choice == "2" || config.Choice == "3" || config.Choice == "4" || config.Choice == "5" {
tests.CustomSP("net", "global", 4, config.Language)
// 中文模式:就近测速 + 三网各1个 + Other 1个带回退
if config.Language == "zh" {
tests.NearbySP()
tests.CustomSP("net", "other", 1, config.Language)
tests.CustomSP("net", "cu", 1, config.Language)
tests.CustomSP("net", "ct", 1, config.Language)
tests.CustomSP("net", "cmcc", 1, config.Language)
} else {
// 英文模式保持原有逻辑测4个global节点
tests.CustomSP("net", "global", 4, config.Language)
}
} else if config.Choice == "6" {
tests.CustomSP("net", "global", 11, config.Language)
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(500 * time.Millisecond)
}
}, tempOutput, output)
}
@@ -370,6 +384,8 @@ func RunEnglishNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *
fmt.Println(pt.WebsiteTest())
}
}
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(300 * time.Millisecond)
}, tempOutput, output)
}
@@ -383,6 +399,8 @@ func RunEnglishSpeedTests(config *params.Config, output, tempOutput string, outp
tests.ShowHead(config.Language)
tests.NearbySP()
tests.CustomSP("net", "global", -1, config.Language)
// 等待第三方库的输出完全刷新到标准输出
time.Sleep(500 * time.Millisecond)
}
}, tempOutput, output)
}
@@ -442,7 +460,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
// 使用context来控制上传goroutine
uploadCtx, uploadCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer uploadCancel()
go func() {
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload)
select {
@@ -455,7 +473,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
return
}
}()
select {
case result := <-resultChan:
uploadCancel() // 成功完成取消context

View File

@@ -25,51 +25,132 @@ func MemoryTest(language, testMethod string) (realTestMethod, res string) {
if runtime.GOOS == "windows" {
switch testMethod {
case "stream":
res = memory.WinsatTest(language)
realTestMethod = "winsat"
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WinsatTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WindowsDDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "winsat"
}
} else {
realTestMethod = "stream"
}
case "dd":
res = memory.WindowsDDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res += memory.WinsatTest(language)
realTestMethod = "winsat"
res = memory.WinsatTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "stream"
}
} else {
realTestMethod = "winsat"
}
} else {
realTestMethod = "dd"
}
case "sysbench":
// Windows下不支持sysbench使用stream → winsat → dd
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WinsatTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WindowsDDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "winsat"
}
} else {
realTestMethod = "stream"
}
case "auto":
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WinsatTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WindowsDDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "winsat"
}
} else {
realTestMethod = "stream"
}
case "winsat":
res = memory.WinsatTest(language)
realTestMethod = "winsat"
case "auto", "winsat":
res = memory.WinsatTest(language)
realTestMethod = "winsat"
if res == "" || strings.TrimSpace(res) == "" {
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WindowsDDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "stream"
}
} else {
realTestMethod = "winsat"
}
default:
res = memory.WinsatTest(language)
realTestMethod = "winsat"
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WinsatTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.WindowsDDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "winsat"
}
} else {
realTestMethod = "stream"
}
}
} else {
switch testMethod {
case "stream":
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res += memory.DDTest(language)
realTestMethod = "dd"
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.DDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "sysbench"
}
} else {
realTestMethod = "stream"
}
case "dd":
res = memory.DDTest(language)
realTestMethod = "dd"
case "sysbench":
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res += memory.DDTest(language)
realTestMethod = "dd"
} else {
realTestMethod = "sysbench"
}
case "auto":
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.DDTest(language)
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
@@ -78,15 +159,68 @@ func MemoryTest(language, testMethod string) (realTestMethod, res string) {
realTestMethod = "sysbench"
}
} else {
realTestMethod = "dd"
realTestMethod = "stream"
}
} else {
realTestMethod = "dd"
}
case "sysbench":
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.DDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "sysbench"
}
} else {
realTestMethod = "stream"
}
} else {
realTestMethod = "sysbench"
}
case "auto":
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.DDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "sysbench"
}
} else {
realTestMethod = "stream"
}
case "winsat":
// winsat 仅 Windows 支持,非 Windows fallback 到 dd
res = memory.DDTest(language)
realTestMethod = "dd"
// winsat 仅 Windows 支持,非 Windows fallback 到 stream → sysbench → dd
res = memory.StreamTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.SysBenchTest(language)
if res == "" || strings.TrimSpace(res) == "" {
res = memory.DDTest(language)
if res == "" || strings.TrimSpace(res) == "" {
realTestMethod = ""
} else {
realTestMethod = "dd"
}
} else {
realTestMethod = "sysbench"
}
} else {
realTestMethod = "stream"
}
default:
res = "Unsupported test method"
realTestMethod = ""

View File

@@ -5,7 +5,9 @@ import (
"os"
"runtime"
"strings"
"time"
"github.com/oneclickvirt/privatespeedtest/pst"
"github.com/oneclickvirt/speedtest/model"
"github.com/oneclickvirt/speedtest/sp"
)
@@ -32,12 +34,209 @@ func NearbySP() {
}
}
// formatString 格式化字符串到指定宽度
func formatString(s string, width int) string {
return fmt.Sprintf("%-*s", width, s)
}
// printTableRow 打印表格行
func printTableRow(result pst.SpeedTestResult) {
location := result.City
if result.CarrierType != "" {
carrier := result.CarrierType
switch carrier {
case "Telecom":
carrier = "电信"
case "Unicom":
carrier = "联通"
case "Mobile":
carrier = "移动"
case "Other":
carrier = "其他"
}
location = fmt.Sprintf("%s%s", carrier, result.City)
}
if len(location) > 15 {
location = location[:15]
}
upload := "N/A"
if result.UploadMbps > 0 {
upload = fmt.Sprintf("%.2f Mbps", result.UploadMbps)
}
download := "N/A"
if result.DownloadMbps > 0 {
download = fmt.Sprintf("%.2f Mbps", result.DownloadMbps)
}
latency := fmt.Sprintf("%.2f ms", result.PingLatency.Seconds()*1000)
packetLoss := "N/A"
fmt.Print(formatString(location, 15))
fmt.Print(formatString(upload, 16))
fmt.Print(formatString(download, 16))
fmt.Print(formatString(latency, 16))
fmt.Print(formatString(packetLoss, 16))
fmt.Println()
}
// privateSpeedTest 使用 privatespeedtest 进行单个运营商测速
// operator 参数:只支持 "cmcc"、"cu"、"ct"、"other"
// 返回值:实际测试的节点数量和错误信息
func privateSpeedTest(num int, operator string) (int, error) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "[WARN] privateSpeedTest panic: %v\n", r)
}
}()
*pst.NoProgress = true
*pst.Quiet = true
*pst.NoHeader = true
*pst.NoProjectURL = true
// 加载服务器列表
serverList, err := pst.LoadServerList()
if err != nil {
return 0, fmt.Errorf("加载自定义服务器列表失败")
}
// 使用三网测速模式(每个运营商选择指定数量的最低延迟节点)
serversPerISP := num
if serversPerISP <= 0 || serversPerISP > 5 {
serversPerISP = 2
}
// 单个运营商测速:先过滤服务器列表
var carrierType string
switch strings.ToLower(operator) {
case "cmcc":
carrierType = "Mobile"
case "cu":
carrierType = "Unicom"
case "ct":
carrierType = "Telecom"
case "other":
carrierType = "Other"
default:
return 0, fmt.Errorf("不支持的运营商类型: %s", operator)
}
// 过滤出指定运营商的服务器
filteredServers := pst.FilterServersByISP(serverList.Servers, carrierType)
// 先找足够多的候选服务器用于去重(找 serversPerISP * 3 个,确保去重后还能剩下足够的服务器)
candidateCount := serversPerISP * 3
if candidateCount > len(filteredServers) {
candidateCount = len(filteredServers)
}
// 使用 FindBestServers 选择最佳服务器
candidateServers, err := pst.FindBestServers(
filteredServers,
candidateCount, // 选择更多候选节点用于去重
5*time.Second, // ping 超时
true, // 显示进度条
true, // 静默
)
if err != nil {
return 0, fmt.Errorf("分组查找失败")
}
// 去重:确保同一运营商内城市不重复
seenCities := make(map[string]bool)
var bestServers []pst.ServerWithLatencyInfo
// 保留更多备用节点,以应对测速失败的情况(保留 serversPerISP * 2 个备用节点)
maxBackupServers := serversPerISP * 2
for _, serverInfo := range candidateServers {
city := serverInfo.Server.City
if city == "" {
city = "Unknown"
}
if !seenCities[city] {
seenCities[city] = true
bestServers = append(bestServers, serverInfo)
// 去重后保留足够的备用节点
if len(bestServers) >= maxBackupServers {
break
}
}
}
if len(bestServers) == 0 {
return 0, fmt.Errorf("去重后没有可用的服务器")
}
// 执行测速并逐个打印结果(不打印表头)
// 统计成功输出的节点数
successCount := 0
for i, serverInfo := range bestServers {
// 如果已经成功输出了足够的节点,则停止测试
if successCount >= serversPerISP {
break
}
result := pst.RunSpeedTest(
serverInfo.Server,
false, // 不禁用下载测试
false, // 不禁用上传测试
6, // 并发线程数
12*time.Second, // 超时时间
&serverInfo,
false, // 不显示进度条
)
// 只要测试成功且有任意一个速度值有效,就输出结果(部分成功也显示)
if result.Success && (result.UploadMbps > 0 || result.DownloadMbps > 0) {
printTableRow(result)
// 只有上传和下载都成功时才计入成功数
if result.UploadMbps > 0 && result.DownloadMbps > 0 {
successCount++
}
}
// 在测试之间暂停(如果还需要继续测试的话)
if successCount < serversPerISP && i < len(bestServers)-1 {
time.Sleep(1 * time.Second)
}
}
// 返回实际成功输出的节点数量
return successCount, nil
}
// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点
// 主要用于 Other 类型的测速
func privateSpeedTestWithFallback(num int, operator, language string) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "[WARN] privateSpeedTestWithFallback panic: %v\n", r)
}
}()
// 先尝试私有节点测速
testedCount, err := privateSpeedTest(num, operator)
if err != nil || testedCount == 0 {
// 私有节点失败,回退到 global 节点
var url, parseType string
url = model.NetGlobal
parseType = "id"
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
sp.CustomSpeedTest(url, parseType, num, language)
} else {
sp.OfficialCustomSpeedTest(url, parseType, num, language)
}
}
}
func CustomSP(platform, operator string, num int, language string) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "[WARN] CustomSP panic: %v\n", r)
}
}()
// 对于三网测速cmcc、cu、ct和 other优先使用 privatespeedtest 进行私有测速
opLower := strings.ToLower(operator)
if opLower == "cmcc" || opLower == "cu" || opLower == "ct" || opLower == "other" {
testedCount, err := privateSpeedTest(num, opLower)
if err != nil {
fmt.Fprintf(os.Stderr, "[WARN] privatespeedtest failed: %v\n", err)
// 全部失败,继续使用原有的公共节点兜底方案
} else if testedCount >= num {
// 私有节点测速成功且数量达标,直接返回
return
} else if testedCount > 0 {
// 部分私有节点测速成功,但数量不足,用公共节点补充
fmt.Fprintf(os.Stderr, "[INFO] 私有节点仅测试了 %d 个,补充 %d 个公共节点\n", testedCount, num-testedCount)
num = num - testedCount // 只测剩余数量的公共节点
// 继续执行下面的公共节点测速逻辑
} else {
// testedCount == 0继续使用公共节点
}
}
var url, parseType string
if strings.ToLower(platform) == "cn" {
if strings.ToLower(operator) == "cmcc" {
@@ -71,7 +270,8 @@ func CustomSP(platform, operator string, num int, language string) {
url = model.NetJP
} else if strings.ToLower(operator) == "sg" {
url = model.NetSG
} else if strings.ToLower(operator) == "global" {
} else if strings.ToLower(operator) == "global" || strings.ToLower(operator) == "other" {
// other 类型回退到 global 节点
url = model.NetGlobal
}
parseType = "id"

View File

@@ -219,6 +219,11 @@ func CaptureOutput(f func()) string {
}()
// 执行函数
f()
// 确保所有输出都已经刷新
os.Stdout.Sync()
os.Stderr.Sync()
// 等待一小段时间确保后台goroutine的输出完成
time.Sleep(100 * time.Millisecond)
// 关闭管道写入端,让管道读取端可以读取所有数据
stdoutPipeW.Close()
stderrPipeW.Close()