Compare commits

...

57 Commits

Author SHA1 Message Date
spiritlhl
04ce926582 fix: 更新主版本 2025-08-23 03:35:33 +00:00
spiritlhl
73eb38eed1 fix: 删除无效包导入 2025-08-23 03:34:51 +00:00
spiritlhl
9bc8a934b1 fix: 修复标识输出 2025-08-23 03:19:32 +00:00
spiritlhl
7b729e073b fix: 移动弃用的文件 2025-08-23 03:17:05 +00:00
spiritlhl
111126ae90 fix: 添加内存测试项基准说明,修复部分比较含糊的说明。 2025-08-23 03:15:54 +00:00
spiritlhl
9397f789be fix: 同步securitycheck上游更新,更新主程序版本号,去除默认的清屏操作 2025-08-23 03:02:13 +00:00
spiritlhl
5a1dda6483 fix: 添加额外的ASN获取方式,当查询失败时回落尝试修复查询(虽然出现问题的概率极小) 2025-08-23 02:56:02 +00:00
spiritlhl
e322c717c0 fix: 安装依赖去除sysbench编译尝试,主程序已自带sysbench回落机制,没必要强求依赖安装 2025-08-23 02:52:55 +00:00
spiritlhl
778b33142b fix: 自行编译的分支添加标识为非官方编译 2025-08-23 02:51:32 +00:00
spiritlhl
aa9f361380 feat: 添加Release的下载量统计 2025-08-19 13:00:05 +00:00
github-actions[bot]
3236c60359 chore: update ECS_VERSION to 0.1.83 in goecs.sh 2025-08-11 13:45:39 +00:00
spiritlhl
73b0f30ddc fix: 删除无效文件,去除无效重定向 2025-08-11 13:31:18 +00:00
spiritlhl
825da78bd5 fix: 外部重定向已捕捉无需重复捕捉 2025-08-11 13:16:46 +00:00
spiritlhl
5d2f3c7f96 fix: 更新版本 2025-08-11 13:14:33 +00:00
spiritlhl
61247a206e fix: 删除无效的并发 2025-08-11 13:08:20 +00:00
spiritlhl
f0daad1360 fix: 修复重定向冲突问题,由于nexttrace上层捕获了输出,无法再在融合怪中再次捕获进行重定向 2025-08-11 13:04:25 +00:00
github-actions[bot]
2d23fb55a0 chore: update ECS_VERSION to 0.1.79 in goecs.sh 2025-08-11 12:13:04 +00:00
spiritlhl
a73dbf2d0b fix: 修复部分单项测试说明错位 2025-08-11 12:08:51 +00:00
spiritlhl
b38dd713d9 fix: 修复退出选项被筛选逻辑拦截的问题 2025-08-11 20:02:20 +08:00
github-actions[bot]
e66ef1f106 chore: update ECS_VERSION to 0.1.77 in goecs.sh 2025-08-11 11:52:15 +00:00
spiritlhl
f6ee1e40ec fix: 添加退出程序的选项,添加开始执行前的清屏逻辑 2025-08-11 11:37:43 +00:00
spiritlhl
cb2bf0a7e5 fix: 主体逻辑将backtrace和三网路由详情检测加入整体的并发检测 2025-08-11 11:25:32 +00:00
spiritlhl
ad017db5a6 fix: 更新版本 2025-08-11 11:15:13 +00:00
spiritlhl
a99f58518a fix: 升级backtrace依赖,支持多重路由测试取平均结果,避免单次路由波动分析失败 2025-08-11 11:13:07 +00:00
spiritlhl
2e59bac322 fix: 提取三网详细路由的测试逻辑至于单独的包,添加单项测试 2025-08-11 10:59:17 +00:00
spiritlhl
4132b1daff feat: 详细三网路由测试支持并发测试,大幅缩短测试所需时间 2025-08-11 10:53:48 +00:00
github-actions[bot]
53296b745a chore: update ECS_VERSION to 0.1.76 in goecs.sh 2025-08-08 14:53:41 +00:00
spiritlhl
74630e9615 fix: 更新说明 2025-08-08 14:31:09 +00:00
spiritlhl
5ec7924214 fix: 更新版本(mbw已回落可用但未能测出真实性能) 2025-08-08 14:26:31 +00:00
spiritlhl
7a7fdc26a0 fix: memorytest更新依赖 2025-08-08 14:23:16 +00:00
spiritlhl
d4c855de92 fix: disktest去除无效的条件筛选 2025-08-08 14:16:50 +00:00
spiritlhl
7c22dee443 fix: 修复windows系统非Admin权限下的硬盘测试(FIO测试无误,DD测试缺少C依赖) 2025-08-08 14:15:59 +00:00
github-actions[bot]
797496b640 chore: update ECS_VERSION to 0.1.75 in goecs.sh 2025-08-06 09:12:25 +00:00
spiritlhl
5b686abdc8 fix: 规范输出 2025-08-06 09:06:48 +00:00
spiritlhl
f99a37edbe fix: 更新版本 2025-08-06 09:04:38 +00:00
spiritlhl
4ff49c8b90 fix: 离线模式下不检测程序版本,不统计使用次数 2025-08-06 09:02:57 +00:00
spiritlhl
1d9257beb3 fix: 合并缓存IP的存储位置 2025-08-06 08:51:50 +00:00
spiritlhl
fc6ccb9f92 fix: 修复无系统信息检测时无对应IP信息检测导致后续依赖IP信息查询的函数异常输出的问题 2025-08-06 08:45:00 +00:00
github-actions[bot]
88a2a7fdc9 chore: update ECS_VERSION to 0.1.74 in goecs.sh 2025-08-05 14:28:15 +00:00
spiritlhl
5ff18ed7c7 feat: 更新版本 2025-08-05 14:13:46 +00:00
spiritlhl
df897db244 feat: 添加支持如非最新版本使用时提示版本更新,添加使用统计 2025-08-05 14:13:20 +00:00
spiritlhl
9a8680491c fix: 支持三网回程详细路可指定ALL对四个主要城市全测 2025-08-05 13:37:43 +00:00
spiritlhl
33f81fd6aa fix: 修复笔误 2025-08-05 21:02:05 +08:00
github-actions[bot]
940703c3f9 chore: update ECS_VERSION to 0.1.73 in goecs.sh 2025-08-05 09:42:55 +00:00
spiritlhl
1c2e9cdab9 fix: 修复上游识别,支持直接导入basics识别到的IP地址,而不再重新获取IP地址减少等待时间 2025-08-05 09:28:26 +00:00
spiritlhl
3e6524fa0e fix: 修复和添加上游线路说明 2025-08-02 05:41:17 +00:00
spiritlhl
026f40dc4c fix: 添加额外的本地获取方式 2025-08-01 17:34:56 +00:00
github-actions[bot]
110c58d401 chore: update ECS_VERSION to 0.1.72 in goecs.sh 2025-08-01 17:00:53 +00:00
spiritlhl
06e76a9c33 fix: 更新disktest,支持自动启用多盘IO检测,支持更严苛的过滤规则 2025-08-01 16:46:18 +00:00
spiritlhl
6b88a81c02 fix: 更新版本 2025-08-01 16:43:21 +00:00
spiritlhl
5482506bab fix: 优化请求添加限时和并发拓展 2025-08-01 16:42:46 +00:00
spiritlhl
b7130db8ce fix: backtrace添加上游检测和线路分析 2025-08-01 16:38:01 +00:00
github-actions[bot]
dc5e3b7852 chore: update ECS_VERSION to 0.1.71 in goecs.sh 2025-07-28 02:28:29 +00:00
spiritlhl
6937e69a0a fix: 更新依赖版本,修复GooglePlayStore检测 2025-07-28 02:14:33 +00:00
github-actions[bot]
a68d33739c chore: update ECS_VERSION to 0.1.70 in goecs.sh 2025-07-27 02:47:27 +00:00
spiritlhl
94e0441801 fix: 更新修复backtrace线路检测的IPV6路由检测启用的判断条件 2025-07-27 02:32:33 +00:00
github-actions[bot]
39be183fda chore: update ECS_VERSION to 0.1.69 in goecs.sh 2025-07-26 15:26:32 +00:00
26 changed files with 683 additions and 364 deletions

14
.back/OldFunction.go Normal file
View File

@@ -0,0 +1,14 @@
// clearScreen 清屏
func clearScreen() {
var cmd *exec.Cmd
switch runtime.GOOS {
case "windows":
cmd = exec.Command("cmd", "/c", "cls")
case "darwin":
cmd = exec.Command("clear")
default:
cmd = exec.Command("clear")
}
cmd.Stdout = os.Stdout
_ = cmd.Run()
}

View File

@@ -1,9 +0,0 @@
package backtrace
import (
"github.com/oneclickvirt/backtrace/bk"
)
func BackTrace(enableIpv6 bool) {
backtrace.BackTrace(enableIpv6)
}

View File

@@ -1,21 +0,0 @@
package backtrace
import (
"testing"
)
//func TestGeneratePrefixMap(t *testing.T) {
// prefix := "223.119.8.0/21"
// prefixList := GeneratePrefixList(prefix)
// if prefixList != nil {
// // 打印生成的IP地址前缀列表
// for _, ip := range prefixList {
// fmt.Println(ip)
// }
// }
//}
// 本包仅测试,无实际使用
func TestBackTrace(t *testing.T) {
BackTrace(false)
}

View File

@@ -12,5 +12,5 @@ func Basic(language string) {
ipInfo, _, _ := network.NetworkCheck("both", false, language)
systemInfo := system.CheckSystemInfo(language)
basicInfo := strings.ReplaceAll(systemInfo+ipInfo, "\n\n", "\n")
fmt.Printf(basicInfo)
fmt.Print(basicInfo)
}

View File

@@ -7,5 +7,5 @@ import (
func ComMediaTest(language string) {
res := commediatests.MediaTests(language)
fmt.Printf(res)
fmt.Print(res)
}

View File

@@ -15,8 +15,8 @@ func TestIpv4SecurityCheck(t *testing.T) {
// 全项测试
ipInfo, securityInfo, _ := NetworkCheck("both", true, "zh")
fmt.Println("--------------------------------------------------")
fmt.Printf(ipInfo)
fmt.Print(ipInfo)
fmt.Println("--------------------------------------------------")
fmt.Printf(securityInfo)
fmt.Print(securityInfo)
fmt.Println("--------------------------------------------------")
}

View File

@@ -1,9 +0,0 @@
package ntrace
import (
"github.com/oneclickvirt/nt3/nt"
)
func TraceRoute3(language, location, checkType string) {
nt.TraceRoute(language, location, checkType)
}

View File

@@ -1,9 +0,0 @@
package ntrace
import "testing"
// https://github.com/nxtrace/NTrace-core/blob/main/fast_trace/fast_trace.go
// 本包仅测试无实际使用
func TestTraceRoute(t *testing.T) {
TraceRoute3("en", "GZ", "ipv4")
}

View File

@@ -36,6 +36,8 @@ jobs:
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
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
@@ -52,4 +54,4 @@ jobs:
run: |
git add .
git commit -m "Auto update public version (no security package)" || echo "No changes to commit"
git push -f origin public
git push -f origin public

View File

@@ -4,7 +4,7 @@
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_shield)
[![Hits](https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false)](https://hits.spiritlhl.net)
[![Hits](https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false)](https://hits.spiritlhl.net) [![Downloads](https://ghdownload.spiritlhl.net/oneclickvirt/ecs?color=36c600)](https://github.com/oneclickvirt/ecs/releases)
融合怪测评项目 - GO版本
@@ -47,8 +47,8 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
|----------------|---------------------------|
| Android(arm64) | 存在权限问题未修复非安卓系统的ARM架构无问题 |
| OpenBSD/NetBSD | 部分Goalng的官方库未支持本系统(尤其是net相关项目) |
| Windows虚拟机 | 非物理机器不支持winsat测试硬件性能(硬盘和内存测试) |
| Windows物理机(非Admin下) | 无Admin权限不支持winsat测试硬件性能(硬盘和内存测试) |
| Windows虚拟机 | 无Admin权限的mbw测试性能不准确(内存测试) |
| Windows物理机(非Admin下) | 无Admin权限的mbw测试性能不准确(内存测试) |
---
## **功能**
@@ -61,7 +61,7 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
- 常见流媒体测试并发查询:[UnlockTests](https://github.com/oneclickvirt/UnlockTests),逻辑借鉴 [RegionRestrictionCheck](https://github.com/lmc999/RegionRestrictionCheck) 等
- IP 质量/安全信息并发查询:二进制文件编译至 [securityCheck](https://github.com/oneclickvirt/securityCheck)
- 邮件端口测试:[portchecker](https://github.com/oneclickvirt/portchecker)
- 三网回程测试:借鉴 [zhanghanyun/backtrace](https://github.com/zhanghanyun/backtrace),二次开发至 [oneclickvirt/backtrace](https://github.com/oneclickvirt/backtrace)
- 上游及回程路由线路检测:借鉴 [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)
- 三网 Ping 值测试:借鉴 [ecsspeed](https://github.com/spiritLHLS/ecsspeed),二次开发至 [pingtest](https://github.com/oneclickvirt/pingtest)
@@ -398,6 +398,10 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
<img src="https://console.zmto.com/templates/2019/dist/images/logo_dark.svg" alt="zmto" style="height: 50px;">
</a>
## History Usage
![goecs](https://hits.spiritlhl.net/chart/goecs.svg)
## Stargazers over time
[![Stargazers over time](https://starchart.cc/oneclickvirt/ecs.svg?variant=adaptive)](https://www.spiritlhl.net)

View File

@@ -1,8 +1,10 @@
# ecs
# ECS
[![Build and Release](https://github.com/oneclickvirt/ecs/actions/workflows/build_binary.yaml/badge.svg)](https://github.com/oneclickvirt/ecs/actions/workflows/build_binary.yaml)
[![Hits](https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false)](https://hits.spiritlhl.net)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_shield)
[![Hits](https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false)](https://hits.spiritlhl.net) [![Downloads](https://ghdownload.spiritlhl.net/oneclickvirt/ecs?color=36c600)](https://github.com/oneclickvirt/ecs/releases)
Fusion Monster Evaluation Project - GO Version
@@ -45,8 +47,8 @@ Shell version: [https://github.com/spiritLHLS/ecs/blob/main/README_EN.md](https:
|--------|-------------------------------------------------------------------------------------------------|
| Android(arm64) | Permission issues that are not fixed, no problems with ARM architecture for non-Android systems |
| OpenBSD/NetBSD | Some of Goalng's official libraries do not support this system (especially net-related items) |
| Windows(Virtual Machines) | Non-Physical Machines do not support winsat to test hardware performance (hard disk and memory tests) |
| Windows(Physical Machines)(not under Admin) | No Admin privileges do not support winsat to test hardware performance (hard disk and memory tests) |
| Windows(Virtual Machines) | Inaccurate mbw test performance without Admin rights (memory tests) |
| Windows(Physical Machines)(not under Admin) | Inaccurate mbw test performance without Admin rights (memory tests) |
---
@@ -344,6 +346,7 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
| Test stability | Core test components unchanged for 10+ years | Each major version updates test items, making scores hard to compare between versions (each version benchmarks against current best CPUs) |
| Test content | Only tests computing performance | Covers multiple performance aspects with weighted scores, though some tests aren't commonly used |
| Suitable scenarios | Good for quick tests, focuses on computing performance | Good for comprehensive testing |
| Ranking | [sysbench.spiritlhl.net](https://sysbench.spiritlhl.net/) | [browser.geekbench.com](https://browser.geekbench.com/) |
Note that `goecs` allows you to specify CPU test method via parameters. The default is chosen for faster testing across more systems.
@@ -393,6 +396,13 @@ Thanks also to the following platforms for editorial and testing support
<img src="https://console.zmto.com/templates/2019/dist/images/logo_dark.svg" alt="zmto" style="height: 50px;">
</a>
## History Usage
![goecs](https://hits.spiritlhl.net/chart/goecs.svg)
## Stargazers over time
[![Stargazers over time](https://starchart.cc/oneclickvirt/ecs.svg?variant=adaptive)](https://www.spiritlhl.net)
## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_large)

View File

@@ -1,6 +1,6 @@
## 目录 / Table of Contents / 目次
[![Hits](https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false)](https://hits.spiritlhl.net)
[![Hits](https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false)](https://hits.spiritlhl.net) [![Downloads](https://ghdownload.spiritlhl.net/oneclickvirt/ecs?color=36c600)](https://github.com/oneclickvirt/ecs/releases)
## 语言 / Languages / 言語
- [中文](#中文)
@@ -15,7 +15,7 @@
- [流媒体解锁](#流媒体解锁)
- [IP质量检测](#IP质量检测)
- [邮件端口检测](#邮件端口检测)
- [三网回城线路检测](#三网回城线路检测)
- [上游及回程线路检测](#上游及回程线路检测)
- [三网回程路由检测](#三网回程路由检测)
- [就近测速](#就近测速)
@@ -77,7 +77,7 @@ VM-x/AMD-V/Hyper-V: 是当前测试宿主机是否支持嵌套虚拟化的指标
虚拟化架构: 显示宿主机来自什么虚拟化架构,一般来说推荐```Dedicated > KVM > Xen```虚拟化,其他虚拟化都会存在性能损耗,导致使用的时候存在性能共享/损耗,但这个也说不准,独立服务器才拥有完全独立的资源占用,其他虚拟化基本都会有资源共享,取决于宿主机的售卖者是否有良心,具体性能优劣还是得看后面的专项测试。
NAT类型: 显示NAT类型具体推荐```Full Cone > Restricted Cone > Port Restricted Cone > Symmetric```,测不出来会显示```Inconclusive```,一般来说不拿来做特殊用途(有关于特殊的代理实时通讯需求的)都不用关注本指标。
NAT类型: 显示NAT类型具体推荐```Full Cone > Restricted Cone > Port Restricted Cone > Symmetric```,测不出来或者非正规协议的类型会显示```Inconclusive```,一般来说只有特殊用途,比如有特殊的代理实时通讯、做FRP内穿端口等需求才需要特别关注其他一般情况下都不用关注本指标。
TCP加速方式一般是```cubic/bbr```拥塞控制协议一般来说做代理服务器用bbr可以改善网速普通用途不必关注此指标。
@@ -101,6 +101,7 @@ IPV6 子网掩码根据宿主机信息查询的本机IPV6子网大小
| 测试稳定性 | 核心测试组件10年以上未变 | 每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU) |
| 测试内容 | 仅测试计算性能,基于素数计算 | 覆盖多种性能测试,分数加权计算,但部分测试实际不常用 |
| 适用场景 | 适合快速测试,仅测试计算性能 | 适合综合全面的测试 |
| 排行榜 | [sysbench.spiritlhl.net](https://sysbench.spiritlhl.net/) | [browser.geekbench.com](https://browser.geekbench.com/) |
默认使用```Sysbench```进行测试,基准大致如下:
@@ -116,13 +117,33 @@ AMD的7950x单核满血性能得分在6500左右AMD的5950x单核满血性能
多说一句,```GeekBench```测的很多内容,实际在服务器使用过程中根本用不到,测试仅供参考。当然```Sysbench```非常不全面但它基于最基础的计算性能可以大致比较CPU的性能。
实际上CPU性能测试够用就行除非是科学计算以及视频转码一般不需要特别追求高性能CPU。
实际上CPU性能测试够用就行除非是科学计算以及视频转码一般不需要特别追求高性能CPU。如果有性能需求,那么需要关注程序本身吃的是多核还是单核,对应看多核还是单核得分。
### **内存测试**
一般来说只需要判断IO速度是否低于```10240MB/s```,如果低于这个值那么证明内存性能不佳,极大概率存在超售超卖问题。
一般来说,只需要判断 IO 速度是否低于 `10240 MB/s (≈10 GB/s)`
如果低于这个值,那么证明内存性能不佳,极大概率存在超售超卖问题。
至于超开的原因可能是开了虚拟内存(硬盘当内存用)、可能是开了ZRAM(牺牲CPU性能)、可能是开了气球驱动、可能是开了KSM内存融合原因多种多样。
至于超开的原因可能是
* 开了虚拟内存 (硬盘当内存用)
* 开了 ZRAM (牺牲 CPU 性能)
* 开了气球驱动 (Balloon Driver)
* 开了 KSM 内存融合
原因多种多样。
| 内存类型 | 典型频率 (MHz) | 单通道带宽 | 双通道带宽 |
| ---- | ------------ | ------------------------------------- | --------------------------------------- |
| DDR3 | 1333 \~ 2133 | 10 \~ 17 GB/s (≈ 10240 \~ 17408 MB/s) | 20 \~ 34 GB/s (≈ 20480 \~ 34816 MB/s) |
| DDR4 | 2133 \~ 3200 | 17 \~ 25 GB/s (≈ 17408 \~ 25600 MB/s) | 34 \~ 50 GB/s (≈ 34816 \~ 51200 MB/s) |
| DDR5 | 4800 \~ 7200 | 38 \~ 57 GB/s (≈ 38912 \~ 58368 MB/s) | 76 \~ 114 GB/s (≈ 77824 \~ 116736 MB/s) |
根据上表内容,本项目测试的粗略判断方法:
* **< 20 GB/s (20480 MB/s)** → 可能是 DDR3或 DDR4 单通道 / 低频)
* **20 \~ 40 GB/s (20480 \~ 40960 MB/s)** → 大概率 DDR4
* **≈ 50 GB/s (≈ 51200 MB/s)** → 基本就是 DDR5
### **硬盘测试**
@@ -186,11 +207,39 @@ AMD的7950x单核满血性能得分在6500左右AMD的5950x单核满血性能
具体当前宿主机不做邮局或者不收电子邮件,那么该项目指标不用理会。
### **三网回程线路检测**
### **上游及回程线路检测**
检测当前的宿主机的IP地址 到 四个主要POP点城市的三个主要运营商的接入点的IP地址 的线路,具体来说
#### 上游类型与运营商等级说明
电信163、联通4837、移动CMI 是常见的线路
- **直接上游Direct Upstream**
当前运营商直接购买网络服务的上级运营商,通常是 BGP 邻居。
- **间接上游Indirect Upstream**
直接上游的上级,形成层层向上的关系链。可通过 BGP 路由路径中的多跳信息识别。
| 等级 | 描述 |
|------|------|
| **Tier 1 Global** | 全球顶级运营商(如 AT&T、Verizon、NTT、Telia 等之间免费互联Settlement-Free Peering不依赖他人即可访问全球任意网络。 |
| **Tier 1 Regional** | 区域性顶级运营商,在特定区域具有一级能力,但在全球范围互联性稍弱。 |
| **Tier 1 Indirect** | 间接连接的 Tier 1非直接购买通过中间上游间接接入 Tier 1 网络。 |
| **Tier 2** | 需要向 Tier 1 付费购买上网能力的二级运营商,通常是各国主流电信商或 ISP。 |
| **CDN Provider** | 内容分发网络提供商,如 Cloudflare、Akamai、Fastly 等,主要用于内容加速而非传统上游。 |
| **Direct/Indirect Others** | 其他类型的直接或间接连接,如 IXInternet Exchange成员、私有对等互联等。 |
上游质量判断:直接接入的高等级上游(特别是 Tier 1 Global越多通常网络连通性越好。但实际网络质量也受到以下因素影响
- 上下游之间的商业结算关系;
- 购买的带宽套餐和服务质量;
- 对等端口Peering Ports大小和负载
- 网络拥塞、路由策略、延迟路径等。
无法完全从 BGP 路由中判断。
一般来说,**接入高质量上游越多,网络连通性越优**。但由于存在诸多不可见的商业和技术因素,**无法仅凭上游等级准确判断网络质量**上游检测约等于图一乐实际得看对应的路由情况和长时间Ping的情况。
然后是检测当前的宿主机的IP地址 到 四个主要POP点城市的三个主要运营商的接入点的IP地址 的线路,具体来说
电信163、联通4837、移动CMI 是常见的线路移动CMI对两广地区的移动运营商特供延迟低也能算优质仅限两广移动。
电信CN2GIA > 电信CN2GT 移动CMIN2 联通9929 算优质的线路
@@ -198,9 +247,9 @@ AMD的7950x单核满血性能得分在6500左右AMD的5950x单核满血性能
### **三网回程路由检测**
默认检测广州为目的地,实际可使用命令行参数指定目的地,见对应的说明。
默认检测广州为目的地,实际可使用命令行参数指定目的地,见对应的参数说明。
主要就是看是不是直连,是不是延迟低,是不是没有隐藏路由信息。如果路由全球跑,延迟起飞,那么线路自然不会好到哪里去。
主要就是看是不是直连,是不是延迟低,是不是没有隐藏路由信息。如果路由全球跑,延迟起飞,那么线路自然不会好到哪里去。有时候路由信息完全藏起来了,只知道实际使用的延迟低,实际可能也是优质线路只是查不到信息,这就没办法直接识别了。
### **就近测速**
@@ -250,7 +299,7 @@ Load: Displays system load.
Virtualization Architecture: Shows what virtualization architecture the host machine uses. Generally speaking, the recommended order is `Dedicated > KVM > Xen` virtualization. Other virtualization will have performance losses, leading to shared/degraded performance during use. However, this is not definitive. Only dedicated servers have completely independent resource usage; other virtualization methods basically all have resource sharing, depending on whether the host machine seller has a conscience. The specific performance merits still depend on the specialized tests that follow.
NAT Type: Displays NAT type. Specifically recommended in order: ```Full Cone > Restricted Cone > Port Restricted Cone > Symmetric```. When not detectable, it will show ```Inconclusive```. Generally speaking, if you're not using it for special purposes (related to special proxy and real-time communication needs), you don't need to pay attention to this metric.
NAT Type: Displays the NAT type, with the following specific recommendations: ```Full Cone > Restricted Cone > Port Restricted Cone > Symmetric``` . If the type cannot be determined or is an irregular protocol, it will display ```Inconclusive``` . Generally, this metric only requires special attention for specific purposes, such as using special proxies, real-time communication, or FRP port forwarding. In most other cases, this metric does not need to be monitored.
TCP Acceleration Method: Generally this is the ```cubic/bbr``` congestion control protocol. Generally speaking, using bbr for proxy servers can improve network speed; for ordinary purposes, you don't need to pay attention to this indicator.
@@ -272,6 +321,7 @@ Supports selecting `GeekBench` and `Sysbench` for testing through command line p
| Test Stability | Core test components unchanged for over 10 years | Test items updated with each major version, scores difficult to compare between different versions (each version benchmarks against current best CPUs) |
| Test Content | Only tests computational performance, based on prime number calculation | Covers multiple performance tests, weighted score calculation, but some tests are not commonly used in practice |
| Applicable Scenarios | Suitable for quick testing, only tests computational performance | Suitable for comprehensive testing |
| Ranking | [sysbench.spiritlhl.net](https://sysbench.spiritlhl.net/) | [browser.geekbench.com](https://browser.geekbench.com/) |
By default, ```Sysbench``` is used for testing, with the baseline roughly as follows:
@@ -287,13 +337,33 @@ For ```GeekBench``` baselines, see the [official website](https://browser.geekbe
As an additional note, many things tested by `GeekBench` are not actually used in server usage processes, so the test is for reference only. Of course, `Sysbench` is very incomplete, but it can roughly compare CPU performance based on the most basic computational performance.
In practice, CPU performance just needs to be sufficient. Unless you're doing scientific computing or video transcoding, you generally don't need to pursue high-performance CPUs.
In fact, CPU performance testing is sufficient as long as it meets basic requirements. Unless you are engaged in scientific computing or video transcoding, there is generally no need to pursue high-performance CPUs. If performance is a requirement, then you need to pay attention to whether the program itself is multi-core or single-core, and correspondingly look at the multi-core or single-core scores.
### **Memory Testing**
### **Memory Test**
Generally speaking, you only need to determine whether the IO speed is below `10240MB/s`. If it's below this value, it proves that memory performance is poor, with an extremely high probability of overselling issues.
Generally speaking, you only need to determine whether the IO speed is lower than `10240 MB/s (≈10 GB/s)`.
If it is lower than this value, then it proves that the memory performance is poor, and there is a high probability of overselling.
As for the reasons for oversubscription, it could be that virtual memory is enabled (using disk as memory), ZRAM might be enabled (sacrificing CPU performance), balloon drivers might be enabled, or KSM memory fusion might be enabled - there are various possible reasons.
The reasons for overselling may be:
* Virtual memory is enabled (using the hard drive as memory)
* ZRAM enabled (sacrificing CPU performance)
* Balloon Driver enabled
* KSM memory fusion enabled
There are various possible causes.
| Memory Type | Typical Frequency (MHz) | Single-Channel Bandwidth | Dual-Channel Bandwidth |
| ---- | ----------- - | ------------------------------------- | -------------------------------------- - |
| DDR3 | 1333 \~ 2133 | 10 \~ 17 GB/s (≈ 10240 \~ 17408 MB/s) | 20 \~ 34 GB/s (≈ 20480 \~ 34816 MB/s) |
| DDR4 | 21333200 | 1725 GB/s (≈ 1740825600 MB/s) | 3450 GB/s (≈ 3481651200 MB/s) |
| DDR5 | 48007200 | 3857 GB/s (≈ 3891258368 MB/s) | 76114 GB/s (≈ 77824116736 MB/s) |
Based on the content of the above table, the rough judgment method for this project's testing is as follows:
* **< 20 GB/s (20480 MB/s)** → May be DDR3 (or DDR4 single-channel / low-frequency)
* **2040 GB/s (2048040960 MB/s)** → Likely DDR4
* **≈ 50 GB/s (≈ 51200 MB/s)** → Essentially DDR5
### **Disk Testing**
@@ -397,7 +467,7 @@ OS: システム名とアーキテクチャを表示します
仮想化アーキテクチャ: ホストマシンがどの仮想化アーキテクチャから来ているかを表示します。一般的に ```Dedicated > KVM > Xen``` 仮想化が推奨されます。他の仮想化はパフォーマンス低下を引き起こし、使用時にパフォーマンス共有/損失が発生しますが、これも確実ではありません。専用サーバーのみが完全に独立したリソース占有を持ち、他の仮想化はほとんどリソース共有があります。これはホストマシンの販売者が良心的かどうかによって異なります。具体的なパフォーマンスの優劣は、後の専門テストを見る必要があります。
NAT種類: NAT種類を表示します。具体的には ```Full Cone > Restricted Cone > Port Restricted Cone > Symmetric``` が推奨されます。検出できない場合は ```Inconclusive``` と表示されます。一般的に特別な用途(特殊なプロキシリアルタイム通信の要件に関連する)に使用しない限り、この指標を気にする必要はありません。
NATタイプ: NATタイプを表示します。具体的な推奨順序は```Full Cone > Restricted Cone > Port Restricted Cone > Symmetric```です。測定不能または非標準プロトコルのタイプの場合は```Inconclusive```と表示されます。通常は特別な用途、例えば特別なプロキシの使用、リアルタイム通信、FRPによるポート転送などが必要な場合を除き、この指標は特に注目する必要はありません。
TCP加速方式一般的に ```cubic/bbr``` 輻輳制御プロトコルです。一般的にプロキシサーバーとして使用する場合、bbrを使用するとネットワーク速度が改善されますが、通常の用途ではこの指標に注目する必要はありません。
@@ -434,13 +504,33 @@ Sysbenchのベンチマークは[CPU Performance Ladder For Sysbench](https://sy
補足ですが、```GeekBench```がテストする多くの内容は、サーバー使用過程で実際には必要ないことが多いです。テストは参考程度にしてください。もちろん```Sysbench```は非常に包括的ではありませんが、基本的な計算性能に基づいてCPUのパフォーマンスを大まかに比較できます。
実際にはCPUパフォーマンスは十分であれば良く、科学計算やビデオエンコード以外では、特に高性能CPUを追求する必要はありません。
実際にはCPUの性能テストは十分な性能があれば十分です。科学計算や動画変換のような特殊な用途を除けば、一般的に高性能CPUを特別に追求する必要はありません。もし性能要件がある場合、プログラム自体がマルチコアかシングルコアのどちらを主に利用しているかを確認し、それに応じてマルチコアかシングルコアのスコアを比較する必要があります。
### **メモリテスト**
一般的に、IO速度が```10240MB/s```未満かどうかを判断するだけで十分です。この値を下回る場合、メモリパフォーマンスが良くなく、オーバーセリング/オーバーコミットの問題がある可能性が非常に高いです。
一般的に、IO速度が`10240 MB/s (≈10 GB/s)`未満かどうかを判断するだけで十分です。
この値を下回る場合、メモリ性能が不十分であり、ほぼ確実にオーバープロビジョニングの問題が存在します。
オーバーコミットの原因は、仮想メモリの使用ディスクをメモリとして使用、ZRAMCPUパフォーマンスを犠牲、バルーンドライバの使用、KSMメモリマージの使用など、様々な可能性があります
オーバープロビジョニングの原因としては、以下の可能性が考えられます
* 仮想メモリを有効にしている(ハードディスクをメモリとして使用)
* ZRAMを有効にしているCPU性能を犠牲にしている
* バルーンドライバーBalloon Driverを有効にしている
* KSMメモリ融合を有効にしている
原因は多岐にわたります。
| メモリタイプ | 典型的な周波数 (MHz) | シングルチャネル帯域幅 | ダブルチャネル帯域幅 |
| ---- | ----------- - | ------------------------------------- | -------------------------------------- - |
| DDR3 | 1333 \~ 2133 | 10 \~ 17 GB/s (≈ 10240 \~ 17408 MB/s) | 20 \~ 34 GB/s (≈ 20480 \~ 34816 MB/s) |
| DDR4 | 2133 3200 | 17 25 GB/s (≈ 17408 25600 MB/s) | 34 50 GB/s (≈ 34816 51200 MB/s) |
| DDR5 | 4800 7200 | 38 57 GB/s (≈ 38912 58368 MB/s) | 76 114 GB/s (≈ 77824 116736 MB/s) |
上記の表の内容に基づき、本プロジェクトのテストにおける粗略な判断方法:
* **< 20 GB/s (20480 MB/s)** → 可能是 DDR3または DDR4 シングルチャネル / 低周波数)
* **20 40 GB/s (20480 40960 MB/s)** → ほぼ確実にDDR4
* **≈ 50 GB/s (≈ 51200 MB/s)** → ほぼ確実にDDR5
### **ディスクテスト**

View File

@@ -8,36 +8,30 @@ import (
)
func DiskTest(language, testMethod, testPath string, isMultiCheck bool, autoChange bool) (realTestMethod, res string) {
if runtime.GOOS == "windows" {
if testMethod != "winsat" && testMethod != "" {
// res = "Detected host is Windows, using Winsat for testing.\n"
realTestMethod = "winsat"
}
res = disk.WinsatTest(language, isMultiCheck, testPath)
} else {
switch testMethod {
case "fio":
res = disk.FioTest(language, isMultiCheck, testPath)
if res == "" && autoChange {
// res = "Fio test failed, switching to DD for testing.\n"
res += disk.DDTest(language, isMultiCheck, testPath)
realTestMethod = "dd"
} else {
realTestMethod = "fio"
}
case "dd":
res = disk.DDTest(language, isMultiCheck, testPath)
if res == "" && autoChange {
// res = "DD test failed, switching to Fio for testing.\n"
res += disk.FioTest(language, isMultiCheck, testPath)
realTestMethod = "fio"
} else {
realTestMethod = "dd"
}
default:
// res = "Unsupported test method specified, switching to DD for testing.\n"
switch testMethod {
case "fio":
res = disk.FioTest(language, isMultiCheck, testPath)
if res == "" && autoChange {
res += disk.DDTest(language, isMultiCheck, testPath)
realTestMethod = "dd"
} else {
realTestMethod = "fio"
}
case "dd":
res = disk.DDTest(language, isMultiCheck, testPath)
if res == "" && autoChange {
res += disk.FioTest(language, isMultiCheck, testPath)
realTestMethod = "fio"
} else {
realTestMethod = "dd"
}
default:
if runtime.GOOS == "windows" {
realTestMethod = "winsat"
res = disk.WinsatTest(language, isMultiCheck, testPath)
} else {
res = disk.DDTest(language, isMultiCheck, testPath)
realTestMethod = "dd"
}
}
if !strings.Contains(res, "\n") && res != "" {

59
go.mod
View File

@@ -3,48 +3,47 @@ module github.com/oneclickvirt/ecs
go 1.24.5
require (
github.com/imroc/req/v3 v3.50.0
github.com/imroc/req/v3 v3.54.0
github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841
github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053
github.com/oneclickvirt/backtrace v0.0.5-20250629024536
github.com/oneclickvirt/basics v0.0.15-20250726093106
github.com/oneclickvirt/UnlockTests v0.0.28-20250727155204
github.com/oneclickvirt/backtrace v0.0.7-20250811023541
github.com/oneclickvirt/basics v0.0.15-20250812130523
github.com/oneclickvirt/cputest v0.0.12-20250720122317
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
github.com/oneclickvirt/disktest v0.0.8-20250701092629
github.com/oneclickvirt/gostun v0.0.5-20250722144757
github.com/oneclickvirt/memorytest v0.0.9-20250720135728
github.com/oneclickvirt/nt3 v0.0.6-20250726150925
github.com/oneclickvirt/pingtest v0.0.8-20250701125637
github.com/oneclickvirt/portchecker v0.0.3-20250329125750
github.com/oneclickvirt/security v0.0.6-20250726094444
github.com/oneclickvirt/speedtest v0.0.10-20250701123931
github.com/oneclickvirt/disktest v0.0.10-20250808140407
github.com/oneclickvirt/gostun v0.0.5-20250727155022
github.com/oneclickvirt/memorytest v0.0.9-20250808065154
github.com/oneclickvirt/nt3 v0.0.8-20250811123903
github.com/oneclickvirt/pingtest v0.0.8-20250728015259
github.com/oneclickvirt/portchecker v0.0.3-20250728015900
github.com/oneclickvirt/security v0.0.6-20250823030124
github.com/oneclickvirt/speedtest v0.0.10-20250728015734
)
require (
github.com/PuerkitoBio/goquery v1.9.2 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gofrs/uuid/v5 v5.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/icholy/digest v1.1.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jaypipes/ghw v0.12.0 // indirect
github.com/jaypipes/pcidb v1.0.0 // indirect
github.com/jaypipes/ghw v0.17.0 // indirect
github.com/jaypipes/pcidb v1.0.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
@@ -59,10 +58,9 @@ require (
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.2 // indirect
github.com/oneclickvirt/dd v0.0.2-20250701085922 // indirect
github.com/oneclickvirt/fio v0.0.2-20250701085933 // indirect
github.com/oneclickvirt/mbw v0.0.1-20250630140849 // indirect
github.com/onsi/ginkgo/v2 v2.22.1 // 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/oschwald/maxminddb-golang v1.13.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pion/dtls/v2 v2.2.7 // indirect
@@ -74,16 +72,15 @@ 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.48.2 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/quic-go/quic-go v0.53.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.9.0 // indirect
github.com/schollz/progressbar/v3 v3.14.4 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v4 v4.24.5 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/showwin/speedtest-go v1.7.7 // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/showwin/speedtest-go v1.7.10 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.14.0 // indirect
github.com/spf13/cast v1.9.2 // indirect
@@ -97,11 +94,10 @@ require (
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/tsosunchia/powclient v0.1.5 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.5.0 // indirect
go.uber.org/mock v0.5.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect
@@ -109,7 +105,6 @@ require (
golang.org/x/term v0.33.0 // indirect
golang.org/x/text v0.27.0 // indirect
golang.org/x/tools v0.34.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.0 // indirect
)

133
go.sum
View File

@@ -2,43 +2,38 @@ github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM=
github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
@@ -50,20 +45,22 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/imroc/req/v3 v3.50.0 h1:n3BVnZiTRpvkN5T1IB79LC/THhFU9iXksNRMH4ZNVaY=
github.com/imroc/req/v3 v3.50.0/go.mod h1:tsOk8K7zI6cU4xu/VWCZVtq9Djw9IWm4MslKzme5woU=
github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
github.com/imroc/req/v3 v3.54.0 h1:kwWJSpT7OvjJ/Q8ykp+69Ye5H486RKDcgEoepw1Ren4=
github.com/imroc/req/v3 v3.54.0/go.mod h1:P8gCJjG/XNUFeP6WOi40VAXfYwT+uPM00xvoBWiwzUQ=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho=
github.com/jaypipes/ghw v0.12.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g=
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
github.com/jaypipes/ghw v0.17.0 h1:EVLJeNcy5z6GK/Lqby0EhBpynZo+ayl8iJWY0kbEUJA=
github.com/jaypipes/ghw v0.17.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8=
github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic=
github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -99,42 +96,38 @@ github.com/nxtrace/NTrace-core v1.4.2 h1:dSRP18Bn3VGf5CZBzKt8gQWW9mDkq62Np9TCF9R
github.com/nxtrace/NTrace-core v1.4.2/go.mod h1:wIDOlccuYzY3wBqU89pv2KGHT41i3JA0eRqJU/x9eX4=
github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841 h1:Zef93z9UiZQwRAKnnZYALmpBKvvuVaq34MEsuWwk6nc=
github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841/go.mod h1:DAmFPRjFV5p9fEzUUSml5jJGn2f1NZJQCzTxITHDjc4=
github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053 h1:Ug8kySZR1weRUcsnGOv+f3HAl791AfkA7EWV3JmiMQA=
github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053/go.mod h1:yXWIZB6iLS88pEd9m4QJi1GENn+7I91zA72y5ONz2Oc=
github.com/oneclickvirt/backtrace v0.0.5-20250629024536 h1:caHCa0DHmbYWBFN1bqKxpvPnN0wOxDEqJv1VDvDdLWs=
github.com/oneclickvirt/backtrace v0.0.5-20250629024536/go.mod h1:5AH00bo41hH3d2/JVuCTlBkZUs3AXX4nlKVXb6piZcI=
github.com/oneclickvirt/basics v0.0.15-20250726093106 h1:FXCBa3xJLf0eotMoOghEEicRjsHuWFn4AePDt3NBpls=
github.com/oneclickvirt/basics v0.0.15-20250726093106/go.mod h1:vAUF4VBvMUf1Uy4DBMa2Zim3x4BUN1KYzqTuec2O53I=
github.com/oneclickvirt/UnlockTests v0.0.28-20250727155204 h1:apFaEbHGKflYMZzK17nXzEai4GG873mTd+d9hCO/KdY=
github.com/oneclickvirt/UnlockTests v0.0.28-20250727155204/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
github.com/oneclickvirt/backtrace v0.0.7-20250811023541 h1:GzkzvUC6U9b6Dkz/Bl4JRPeQ7XBGoW7Qw1aWqzhF+MQ=
github.com/oneclickvirt/backtrace v0.0.7-20250811023541/go.mod h1:/+KUtOWz48TyiTTbhVTsp3D6b5WY+4pCgvFBYtUGtns=
github.com/oneclickvirt/basics v0.0.15-20250812130523 h1:nPNTVq8d9N1rdshkMAbnhZxTb7L2Yt7NlIg6rY10YRQ=
github.com/oneclickvirt/basics v0.0.15-20250812130523/go.mod h1:2PV+1ge01zb0Sqzj2V2I7P0wAdFSLF1XgAiumchJJbg=
github.com/oneclickvirt/cputest v0.0.12-20250720122317 h1:toiwAK1hZE5b8klu2mOQ7J4sv5yV9lpPKwgPahfRYBQ=
github.com/oneclickvirt/cputest v0.0.12-20250720122317/go.mod h1:vjlH8tkPFft1tlLOpeNskXVvurxkHaJ3+dgFxQGLXY4=
github.com/oneclickvirt/dd v0.0.2-20250701085922 h1:WiWZwcnCPhRc8hLZdvkjD2kOEpnqn1S31z1j0x3V4l0=
github.com/oneclickvirt/dd v0.0.2-20250701085922/go.mod h1:tImu9sPTkLWo2tf1dEN1xQzrylWKauj9hbU8PHfyAeU=
github.com/oneclickvirt/dd v0.0.2-20250808062818 h1:0KHrKkdpL5oBE1OHsrRd2siRw4/2k6f9LBaP7T4JpOc=
github.com/oneclickvirt/dd v0.0.2-20250808062818/go.mod h1:tImu9sPTkLWo2tf1dEN1xQzrylWKauj9hbU8PHfyAeU=
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 h1:5Pg3mK/u/vQvSz7anu0nxzrNdELi/AcDAU1mMsmPzyc=
github.com/oneclickvirt/defaultset v0.0.2-20240624082446/go.mod h1:e9Jt4tf2sbemCtc84/XgKcHy9EZ2jkc5x2sW1NiJS+E=
github.com/oneclickvirt/disktest v0.0.8-20250701092629 h1:B/gA6SOr4qL5pQmVpHl9m5bn3paDcL7wJ1SZ7aY66M8=
github.com/oneclickvirt/disktest v0.0.8-20250701092629/go.mod h1:6YCvGr+Z0tvcP4Ue8bezZqm/GqS/dSyEnSUhvS3Q03o=
github.com/oneclickvirt/fio v0.0.2-20250701085933 h1:4P7QcOTxbqyx5DhHdFvyeRSsdNajSo9l/H2XK0vICIc=
github.com/oneclickvirt/fio v0.0.2-20250701085933/go.mod h1:NIq+XYTey68KNERGIy/oRDlzpwLzBVoHOCiqX8didsE=
github.com/oneclickvirt/gostun v0.0.5-20250722144757 h1:RCEouk5WIJoF52JfsC60Zkqz66JY0JQKrhfd9kqP1OI=
github.com/oneclickvirt/gostun v0.0.5-20250722144757/go.mod h1:f7DPEXAxbmwXSW33dbxtb0/KzqvOBWhTs2Or5xBerQA=
github.com/oneclickvirt/mbw v0.0.1-20250630140849 h1:p6RMhOPBnQKAm9+VEQ2axAFsidrdSdrhXMyheIyv2a8=
github.com/oneclickvirt/mbw v0.0.1-20250630140849/go.mod h1:0Vq6NRpyLmGUdfHfL3uDcFsuZhi7KlG+OCs5ky2757Y=
github.com/oneclickvirt/memorytest v0.0.9-20250720135728 h1:RusZfaESDXK+k5YYfVXTCW5zLeQEd/dYY80a6xievE0=
github.com/oneclickvirt/memorytest v0.0.9-20250720135728/go.mod h1:7xMacjQobvFAtODht2hxTsB9hM2IFS7vZk3gxx+bsjo=
github.com/oneclickvirt/nt3 v0.0.6-20250726150925 h1:M+9kEpMp+O2a//yp9zJ11DleK7hxEmFd5jOWKNrSlmY=
github.com/oneclickvirt/nt3 v0.0.6-20250726150925/go.mod h1:O7YkaOMFihB8hwQiD74WTbDlyoTieDwTDBR6jbkZaP0=
github.com/oneclickvirt/pingtest v0.0.8-20250701125637 h1:J28Ai5miTq1J0I4gdT8rewJSd3LwzD90L/bNiiaKfHM=
github.com/oneclickvirt/pingtest v0.0.8-20250701125637/go.mod h1:d3Ntx5m9lMll3a/k3+2B+5emj//vgDh4/NHTxs2qQE8=
github.com/oneclickvirt/portchecker v0.0.3-20250329125750 h1:TTNL0pnQlRsn046kW59I/9UWRpihttFHWnU7Ixycggk=
github.com/oneclickvirt/portchecker v0.0.3-20250329125750/go.mod h1:HQxSTrqM8/QFqHMTBZ7S8H9eEO5FkUXU1eb7ZX5Mk+k=
github.com/oneclickvirt/security v0.0.6-20250726094444 h1:a4xhcTiBlG9Z3AuQm8PtXfBkd+4+QeytW/MuTQvUTeI=
github.com/oneclickvirt/security v0.0.6-20250726094444/go.mod h1:klmmfTFlIw/6rs1PXVRnX16+JG5TPaAMCjxLrCe0Ef8=
github.com/oneclickvirt/speedtest v0.0.10-20250701123931 h1:IMUM0F3trrlCdl9JTO+FBIJ9zc8mbi+oyd66IkO/8mI=
github.com/oneclickvirt/speedtest v0.0.10-20250701123931/go.mod h1:zd5ZgIGslmtQLQehEfRjyumlvgDHTpCSMchKfKXoASI=
github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=
github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/oneclickvirt/disktest v0.0.10-20250808140407 h1:oUfi5zF3htUTB1ZJuClmK0o74ufP7icbu8LYCnxEOxE=
github.com/oneclickvirt/disktest v0.0.10-20250808140407/go.mod h1:Vp3iMVBD4ccReDJz5n5SlzUdq0kDuVhpRklQk21KT+8=
github.com/oneclickvirt/fio v0.0.2-20250808045755 h1:eWihCRWcalJjPIdrF8dMe68ZiPnMkSfHC8ENvElp/xE=
github.com/oneclickvirt/fio v0.0.2-20250808045755/go.mod h1:NIq+XYTey68KNERGIy/oRDlzpwLzBVoHOCiqX8didsE=
github.com/oneclickvirt/gostun v0.0.5-20250727155022 h1:/e3gSUrOp1tg/1NTRx+P8B51OGcP26Q6//5EoSIjOvk=
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.9-20250808065154 h1:mjYOvpFz2mpDU9MNjj66oIDcc2r6+zoW8veP616/+4Q=
github.com/oneclickvirt/memorytest v0.0.9-20250808065154/go.mod h1:DBxiVZX7mWCe0Fy+qu57ENheLo00sLfjKzvxiICrUtU=
github.com/oneclickvirt/nt3 v0.0.8-20250811123903 h1:ubSPLh/DSrXj+tOgmRABgi2vrVmbmjjSne+NrVFNmNc=
github.com/oneclickvirt/nt3 v0.0.8-20250811123903/go.mod h1:F1v+6xInBKnbUa8gV1M40R1HOzxg+obtduNhx3CTnmA=
github.com/oneclickvirt/pingtest v0.0.8-20250728015259 h1:egoxZRZBOWN3JqBwqEsULDyRo2/dpGMeWcmV3U87zig=
github.com/oneclickvirt/pingtest v0.0.8-20250728015259/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/security v0.0.6-20250823030124 h1:3RjpJNfKV7anN6GJs0ky2BfXFHPUVrDxUomEqoB0x7I=
github.com/oneclickvirt/security v0.0.6-20250823030124/go.mod h1:RSMooIlb4H/kLrGWNvUyOgdzQKgYKVv+LzWGlsPsLW4=
github.com/oneclickvirt/speedtest v0.0.10-20250728015734 h1:HKO7/JQ74ueXA8Wo8NIvcK9DphbEG/YTfAAVz/akSiY=
github.com/oneclickvirt/speedtest v0.0.10-20250728015734/go.mod h1:0W8vnMbA3iucXLXFdGfe9Ia6RPS0izRO7jvu/SnH1P8=
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
@@ -160,10 +153,10 @@ github.com/prometheus-community/pro-bing v0.4.1 h1:aMaJwyifHZO0y+h8+icUz0xbToHbi
github.com/prometheus-community/pro-bing v0.4.1/go.mod h1:aLsw+zqCaDoa2RLVVSX3+UiCkBBXTMtZC3c7EkfWnAE=
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.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
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/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=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@@ -177,14 +170,10 @@ github.com/schollz/progressbar/v3 v3.14.4 h1:W9ZrDSJk7eqmQhd3uxFNNcTr0QL+xuGNI9d
github.com/schollz/progressbar/v3 v3.14.4/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
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.24.5 h1:gGsArG5K6vmsh5hcFOHaPm87UD003CaDMkAOweSQjhM=
github.com/shirou/gopsutil/v4 v4.24.5/go.mod h1:aoebb2vxetJ/yIDZISmduFvVNPHqXQ9SEJwRXxkf0RA=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/showwin/speedtest-go v1.7.7 h1:VmK75SZOTKiuWjIVrs+mo7ZoKEw0utiGCvpnurS0olU=
github.com/showwin/speedtest-go v1.7.7/go.mod h1:uLgdWCNarXxlYsL2E5TOZpCIwpgSWnEANZp7gfHXHu0=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/showwin/speedtest-go v1.7.10 h1:9o5zb7KsuzZKn+IE2//z5btLKJ870JwO6ETayUkqRFw=
github.com/showwin/speedtest-go v1.7.10/go.mod h1:Ei7OCTmNPdWofMadzcfgq1rUO7mvJy9Jycj//G7vyfA=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
@@ -229,8 +218,8 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
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.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
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=
@@ -242,8 +231,6 @@ 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.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
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=
@@ -299,8 +286,6 @@ 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.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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=
@@ -311,16 +296,14 @@ golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg
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=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=

181
goecs.go
View File

@@ -17,7 +17,6 @@ import (
"github.com/oneclickvirt/CommonMediaTests/commediatests"
unlocktestmodel "github.com/oneclickvirt/UnlockTests/model"
backtrace "github.com/oneclickvirt/backtrace/bk"
backtracemodel "github.com/oneclickvirt/backtrace/model"
basicmodel "github.com/oneclickvirt/basics/model"
cputestmodel "github.com/oneclickvirt/cputest/model"
@@ -25,13 +24,14 @@ import (
"github.com/oneclickvirt/ecs/cputest"
"github.com/oneclickvirt/ecs/disktest"
"github.com/oneclickvirt/ecs/memorytest"
"github.com/oneclickvirt/ecs/nexttrace"
"github.com/oneclickvirt/ecs/speedtest"
"github.com/oneclickvirt/ecs/unlocktest"
"github.com/oneclickvirt/ecs/upstreams"
"github.com/oneclickvirt/ecs/utils"
gostunmodel "github.com/oneclickvirt/gostun/model"
memorytestmodel "github.com/oneclickvirt/memorytest/memory"
nt3model "github.com/oneclickvirt/nt3/model"
"github.com/oneclickvirt/nt3/nt"
ptmodel "github.com/oneclickvirt/pingtest/model"
"github.com/oneclickvirt/pingtest/pt"
"github.com/oneclickvirt/portchecker/email"
@@ -39,7 +39,7 @@ import (
)
var (
ecsVersion = "v0.1.69"
ecsVersion = "v0.1.85"
menuMode bool
onlyChinaTest bool
input, choice string
@@ -59,7 +59,7 @@ var (
autoChangeDiskTestMethod = true
filePath = "goecs.txt"
enabelUpload = true
help bool
onlyIpInfoCheckStatus, help bool
goecsFlag = flag.NewFlagSet("goecs", flag.ContinueOnError)
finish bool
)
@@ -99,7 +99,7 @@ func getMenuChoice(language string) string {
if re.MatchString(input) {
inChoice := input
switch inChoice {
case "1", "2", "3", "4", "5", "6", "7", "8", "9", "10":
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10":
return inChoice
default:
if language == "zh" {
@@ -143,7 +143,7 @@ func parseFlags() {
goecsFlag.StringVar(&diskTestMethod, "diskm", "fio", "Set disk test method (supported: fio, dd, winsat)")
goecsFlag.StringVar(&diskTestPath, "diskp", "", "Set disk test path, e.g., -diskp /root")
goecsFlag.BoolVar(&diskMultiCheck, "diskmc", false, "Enable/Disable multiple disk checks, e.g., -diskmc=false")
goecsFlag.StringVar(&nt3Location, "nt3loc", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu)")
goecsFlag.StringVar(&nt3Location, "nt3loc", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all)")
goecsFlag.StringVar(&nt3CheckType, "nt3t", "ipv4", "Set NT3 test type (supported: both, ipv4, ipv6)")
goecsFlag.IntVar(&spNum, "spnum", 2, "Set the number of servers per operator for speed test")
goecsFlag.BoolVar(&enableLogger, "log", false, "Enable/Disable logging in the current path")
@@ -185,11 +185,13 @@ func handleMenuMode(preCheck utils.NetCheckResult) {
commTestStatus, utTestStatus, securityTestStatus, emailTestStatus = false, false, false, false
backtraceStatus, nt3Status, speedTestStatus = false, false, false
autoChangeDiskTestMethod = true
printMenuOptions()
printMenuOptions(preCheck)
Loop:
for {
choice = getMenuChoice(language)
switch choice {
case "0":
os.Exit(0)
case "1":
setFullTestStatus(preCheck)
onlyChinaTest = utils.CheckChina(enableLogger)
@@ -235,6 +237,7 @@ Loop:
fmt.Println("Can not test without network connection!")
return
}
nt3Location = "ALL"
setRouteTestStatus()
break Loop
default:
@@ -243,23 +246,83 @@ Loop:
}
}
func printMenuOptions() {
func printMenuOptions(preCheck utils.NetCheckResult) {
var stats *utils.StatsResponse
var statsErr error
var githubInfo *utils.GitHubRelease
var githubErr error
// 只有在网络连接正常时才获取统计信息和版本信息
if preCheck.Connected {
var pwg sync.WaitGroup
pwg.Add(2)
go func() {
defer pwg.Done()
stats, statsErr = utils.GetGoescStats()
}()
go func() {
defer pwg.Done()
githubInfo, githubErr = utils.GetLatestEcsRelease()
}()
pwg.Wait()
} else {
statsErr = fmt.Errorf("network not connected")
githubErr = fmt.Errorf("network not connected")
}
var statsInfo string
var cmp int
if preCheck.Connected {
// 网络连接正常时处理统计信息和版本比较
if statsErr != nil {
statsInfo = "NULL"
} else {
switch language {
case "zh":
statsInfo = fmt.Sprintf("总使用量: %s | 今日使用: %s",
utils.FormatGoecsNumber(stats.Total),
utils.FormatGoecsNumber(stats.Daily))
case "en":
statsInfo = fmt.Sprintf("Total Usage: %s | Daily Usage: %s",
utils.FormatGoecsNumber(stats.Total),
utils.FormatGoecsNumber(stats.Daily))
}
}
if githubErr == nil {
cmp = utils.CompareVersions(ecsVersion, githubInfo.TagName)
} else {
cmp = 0
}
}
switch language {
case "zh":
fmt.Println("VPS融合怪版本: ", ecsVersion)
fmt.Println("1. 融合怪完全体")
fmt.Printf("VPS融合怪版本: %s\n", ecsVersion)
if preCheck.Connected {
switch cmp {
case -1:
fmt.Printf("检测到新版本 %s 如有必要请更新!\n", githubInfo.TagName)
}
fmt.Printf("使用统计: %s\n", statsInfo)
}
fmt.Println("1. 融合怪完全体(能测全测)")
fmt.Println("2. 极简版(系统信息+CPU+内存+磁盘+测速节点5个)")
fmt.Println("3. 精简版(系统信息+CPU+内存+磁盘+常用流媒体+路由+测速节点5个)")
fmt.Println("4. 精简网络版(系统信息+CPU+内存+磁盘+回程+路由+测速节点5个)")
fmt.Println("5. 精简解锁版(系统信息+CPU+内存+磁盘IO+御三家+常用流媒体+测速节点5个)")
fmt.Println("6. 网络单项(IP质量检测+三网回程+三网路由与延迟+测速节点11个)")
fmt.Println("6. 网络单项(IP质量检测+上游及三网回程+广州三网回程详细路由+全国延迟+测速节点11个)")
fmt.Println("7. 解锁单项(御三家解锁+常用流媒体解锁)")
fmt.Println("8. 硬件单项(系统信息+CPU+内存+dd磁盘测试+fio磁盘测试)")
fmt.Println("9. IP质量检测(15个数据库的IP检测+邮件端口检测)")
fmt.Println("10. 三网回程线路+广州三网路由+全国三网延迟")
fmt.Println("8. 硬件单项(系统信息+CPU+dd磁盘测试+fio磁盘测试)")
fmt.Println("9. IP质量检测(15个数据库的IP质量检测+邮件端口检测)")
fmt.Println("10. 三网回程线路检测+三网回程详细路由(北京上海广州成都)+三网延迟测试(全国)")
fmt.Println("0. 退出程序")
case "en":
fmt.Println("VPS Fusion Monster Test Version: ", ecsVersion)
fmt.Println("1. VPS Fusion Monster Test Comprehensive Test Suite")
fmt.Printf("VPS Fusion Monster Test Version: %s\n", ecsVersion)
if preCheck.Connected {
switch cmp {
case -1:
fmt.Printf("New version detected %s update if necessary!\n", githubInfo.TagName)
}
fmt.Printf("%s\n", statsInfo)
}
fmt.Println("1. VPS Fusion Monster Test (Full Test)")
fmt.Println("2. Minimal Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)")
fmt.Println("3. Standard Test Suite (System Info + CPU + Memory + Disk + Basic Unlock Tests + 5 Speed Test Nodes)")
fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)")
@@ -268,6 +331,7 @@ func printMenuOptions() {
fmt.Println("7. Unlock-Only Test (Basic Unlock Tests + Common Streaming Services Unlock)")
fmt.Println("8. Hardware-Only Test (System Info + CPU + Memory + dd Disk Test + fio Disk Test)")
fmt.Println("9. IP Quality Test (IP Test with 15 Databases + Email Port Test)")
fmt.Println("0. Exit Program")
}
}
@@ -334,16 +398,18 @@ func setUnlockFocusedTestStatus(preCheck utils.NetCheckResult) {
}
func setNetworkOnlyTestStatus() {
onlyIpInfoCheckStatus = true
securityTestStatus = true
speedTestStatus = true
backtraceStatus = true
nt3Status = true
pingTestStatus = true
}
func setUnlockOnlyTestStatus() {
onlyIpInfoCheckStatus = true
commTestStatus = true
utTestStatus = true
enabelUpload = false
}
func setHardwareOnlyTestStatus(preCheck utils.NetCheckResult) {
@@ -357,15 +423,16 @@ func setHardwareOnlyTestStatus(preCheck utils.NetCheckResult) {
}
func setIPQualityTestStatus() {
onlyIpInfoCheckStatus = true
securityTestStatus = true
emailTestStatus = true
}
func setRouteTestStatus() {
onlyIpInfoCheckStatus = true
backtraceStatus = true
nt3Status = true
pingTestStatus = true
enabelUpload = false
}
func printInvalidChoice() {
@@ -386,7 +453,7 @@ func handleLanguageSpecificSettings() {
}
}
func handleSignalInterrupt(sig chan os.Signal, startTime *time.Time, output *string, tempOutput string, uploadDone chan bool, outputMutex *sync.Mutex) {
func handleSignalInterrupt(sig chan os.Signal, startTime *time.Time, output *string, _ string, uploadDone chan bool, outputMutex *sync.Mutex) {
select {
case <-sig:
if !finish {
@@ -467,11 +534,14 @@ func runChineseTests(preCheck utils.NetCheckResult, wg1, wg2, wg3 *sync.WaitGrou
*output = runCPUTest(*output, tempOutput, outputMutex)
*output = runMemoryTest(*output, tempOutput, outputMutex)
*output = runDiskTest(*output, tempOutput, outputMutex)
if (onlyChinaTest || pingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
wg3.Add(1)
if onlyIpInfoCheckStatus && !basicStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
*output = runIpInfoCheck(*output, tempOutput, outputMutex)
}
if utTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" && !onlyChinaTest {
wg1.Add(1)
go func() {
defer wg3.Done()
*ptInfo = pt.PingTest()
defer wg1.Done()
*mediaInfo = unlocktest.MediaTest(language)
}()
}
if emailTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
@@ -481,11 +551,11 @@ func runChineseTests(preCheck utils.NetCheckResult, wg1, wg2, wg3 *sync.WaitGrou
*emailInfo = email.EmailCheck()
}()
}
if utTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" && !onlyChinaTest {
wg1.Add(1)
if (onlyChinaTest || pingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
wg3.Add(1)
go func() {
defer wg1.Done()
*mediaInfo = unlocktest.MediaTest(language)
defer wg3.Done()
*ptInfo = pt.PingTest()
}()
}
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
@@ -507,6 +577,9 @@ func runEnglishTests(preCheck utils.NetCheckResult, wg1, wg2 *sync.WaitGroup, ba
*output = runCPUTest(*output, tempOutput, outputMutex)
*output = runMemoryTest(*output, tempOutput, outputMutex)
*output = runDiskTest(*output, tempOutput, outputMutex)
if onlyIpInfoCheckStatus && !basicStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
*output = runIpInfoCheck(*output, tempOutput, outputMutex)
}
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
if utTestStatus {
wg1.Add(1)
@@ -530,6 +603,24 @@ func runEnglishTests(preCheck utils.NetCheckResult, wg1, wg2 *sync.WaitGroup, ba
*output = appendTimeInfo(*output, tempOutput, startTime, outputMutex)
}
// runIpInfoCheck 系统和网络基础信息检测不进行测试的时候该函数检测取得本机IP信息并显示(单项测试中输出)
func runIpInfoCheck(output, tempOutput string, outputMutex *sync.Mutex) string {
outputMutex.Lock()
defer outputMutex.Unlock()
return utils.PrintAndCapture(func() {
var ipinfo string
upstreams.IPV4, upstreams.IPV6, ipinfo = utils.OnlyBasicsIpInfo(language)
if ipinfo != "" {
if language == "zh" {
utils.PrintCenteredTitle("IP信息", width)
} else {
utils.PrintCenteredTitle("IP-Information", width)
}
fmt.Printf("%s", ipinfo)
}
}, tempOutput, output)
}
func runBasicTests(preCheck utils.NetCheckResult, basicInfo, securityInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
outputMutex.Lock()
defer outputMutex.Unlock()
@@ -544,13 +635,13 @@ func runBasicTests(preCheck utils.NetCheckResult, basicInfo, securityInfo *strin
}
}
if preCheck.Connected && preCheck.StackType == "DualStack" {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, nt3CheckType, securityTestStatus)
upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, nt3CheckType, securityTestStatus)
} else if preCheck.Connected && preCheck.StackType == "IPv4" {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv4", securityTestStatus)
upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv4", securityTestStatus)
} else if preCheck.Connected && preCheck.StackType == "IPv6" {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv6", securityTestStatus)
upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv6", securityTestStatus)
} else {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "", false)
upstreams.IPV4, upstreams.IPV6, *basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "", false)
securityTestStatus = false
}
if basicStatus {
@@ -688,24 +779,16 @@ func runEmailTests(wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput st
func runNetworkTests(wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
outputMutex.Lock()
defer outputMutex.Unlock()
output = utils.PrintAndCapture(func() {
return utils.PrintAndCapture(func() {
if backtraceStatus && !onlyChinaTest {
utils.PrintCenteredTitle("三网回程线路检测", width)
if strings.Contains(output, "IPV6") {
backtrace.BackTrace(true)
} else {
backtrace.BackTrace(false)
}
utils.PrintCenteredTitle("上游及回程线路检测", width)
upstreams.UpstreamsCheck() // 不能在重定向的同时外部并发,此处仅可以顺序执行
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if nt3Status && !onlyChinaTest {
utils.PrintCenteredTitle("三网回程路由检测", width)
nt.TraceRoute(language, nt3Location, nt3CheckType)
nexttrace.NextTrace3Check(language, nt3Location, nt3CheckType) // 不能在重定向的同时外部并发,此处仅可以顺序执行
}
}, tempOutput, output)
return utils.PrintAndCapture(func() {
if onlyChinaTest || pingTestStatus {
if (onlyChinaTest || pingTestStatus) && *ptInfo != "" {
wg3.Wait()
utils.PrintCenteredTitle("三网ICMP的PING值检测", width)
fmt.Println(*ptInfo)
@@ -786,12 +869,16 @@ func main() {
return
}
initLogger()
go func() {
http.Get("https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
}()
preCheck := utils.CheckPublicAccess(3 * time.Second)
go func() {
if preCheck.Connected {
http.Get("https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
}
}()
if menuMode {
handleMenuMode(preCheck)
} else {
onlyIpInfoCheckStatus = true
}
handleLanguageSpecificSettings()
if !preCheck.Connected {

102
goecs.sh
View File

@@ -1,21 +1,24 @@
#!/bin/bash
# From https://github.com/oneclickvirt/ecs
# 2025.06.29
# 2025.08.23
# curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
# 或
# curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
CYAN='\033[96m'
BOLD='\033[1m'
RESET='\033[0m'
echo -e "${CYAN}${BOLD}"
cat <<"EOF"
,ad8888ba, ,ad8888ba, 88888888888 ,ad8888ba, ad88888ba
d8"' `"8b d8"' `"8b 88 d8"' `"8b d8" "8b
d8' d8' `8b 88 d8' Y8a
88 88 88 88aaaaa 88 `"Y8aaaaa,
88 88888 88 88 88""""" 88 `"""""8b,
Y8, 88 Y8, ,8P 88 Y8, `8b
Y8a. .a88 Y8a. .a8P 88 Y8a. .a8P Y8a a8P
`"Y88888P" `"Y8888Y"' 88888888888 `"Y8888Y"' "Y88888P"
██████╗ ██████╗ ███████╗ ██████╗███████╗
██╔════╝ ██╔═══██╗██╔════╝██╔════╝██╔════╝
██║ ███╗██║ ██║█████╗ ██║ ███████╗
██║ ██║██║ ██║██╔══╝ ██║ ██║
╚██████╔╝╚██████╔╝███████╗╚██████╗███████║
╚═════╝ ╚═════╝ ╚══════╝ ╚═════╝╚══════╝
EOF
echo -e "${RESET}"
cd /root >/dev/null 2>&1
if [ ! -d "/usr/bin/" ]; then
mkdir -p "/usr/bin/"
@@ -63,7 +66,6 @@ download_file() {
check_china() {
_yellow "正在检测IP所在区域......"
if [[ -z "${CN}" ]]; then
# 首先尝试通过 ipapi.co 检测
if curl -m 6 -s https://ipapi.co/json | grep -q 'China'; then
_yellow "根据ipapi.co提供的信息当前IP可能在中国"
if [ "$noninteractive" != "true" ]; then
@@ -143,7 +145,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.68"
ECS_VERSION="0.1.83"
for api in \
"https://api.github.com/repos/oneclickvirt/ecs/releases/latest" \
"https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest" \
@@ -155,8 +157,8 @@ goecs_check() {
sleep 1
done
if [ -z "$ECS_VERSION" ]; then
_yellow "Unable to get version info, using default version 0.1.68"
ECS_VERSION="0.1.68"
_yellow "Unable to get version info, using default version 0.1.83"
ECS_VERSION="0.1.83"
fi
version_output=""
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do
@@ -367,68 +369,6 @@ InstallSysbench() {
fi
}
Check_SysBench() {
if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
InstallSysbench
fi
# 尝试编译安装
if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
echo -e "${Msg_Warning}Sysbench Module install Failure, trying compile modules ..."
Check_Sysbench_InstantBuild
fi
source ~/.bashrc
# 最终检测
if [ "$(command -v sysbench)" ] || [ -f "/usr/bin/sysbench" ] || [ -f "/usr/local/bin/sysbench" ]; then
_yellow "Install sysbench successfully!"
else
_red "SysBench Moudle install Failure! Try Restart Bench or Manually install it! (/usr/bin/sysbench)"
_blue "Will try to test with geekbench5 instead later."
fi
sleep 3
}
Check_Sysbench_InstantBuild() {
if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ] || [ "${Var_OSRelease}" = "almalinux" ] || [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ] || [ "${Var_OSRelease}" = "fedora" ] || [ "${Var_OSRelease}" = "arch" ] || [ "${Var_OSRelease}" = "astra" ]; then
local os_sysbench=${Var_OSRelease}
if [ "$os_sysbench" = "astra" ]; then
os_sysbench="debian"
fi
if [ "$os_sysbench" = "opencloudos" ]; then
os_sysbench="centos"
fi
echo -e "${Msg_Info}Release Detected: ${os_sysbench}"
echo -e "${Msg_Info}Preparing compile enviorment ..."
prepare_compile_env "${os_sysbench}"
echo -e "${Msg_Info}Downloading Source code (Version 1.0.20)..."
mkdir -p /tmp/sysbench_install/src/
mv /tmp/sysbench-1.0.20 /tmp/sysbench_install/src/
echo -e "${Msg_Info}Compiling Sysbench Module ..."
cd /tmp/sysbench_install/src/sysbench-1.0.20
./autogen.sh && ./configure --without-mysql && make -j8 && make install
echo -e "${Msg_Info}Cleaning up ..."
cd /tmp && rm -rf /tmp/sysbench_install/src/sysbench*
else
echo -e "${Msg_Warning}Unsupported operating system: ${Var_OSRelease}"
fi
}
prepare_compile_env() {
local system="$1"
if [ "${system}" = "centos" ] || [ "${system}" = "rhel" ] || [ "${system}" = "almalinux" ]; then
yum install -y epel-release
yum install -y wget curl make gcc gcc-c++ make automake libtool pkgconfig libaio-devel
elif [ "${system}" = "ubuntu" ] || [ "${system}" = "debian" ]; then
! apt-get update && apt-get --fix-broken install -y && apt-get update
! apt-get -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip && apt-get --fix-broken install -y && apt-get -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip
elif [ "${system}" = "fedora" ]; then
dnf install -y wget curl gcc gcc-c++ make automake libtool pkgconfig libaio-devel
elif [ "${system}" = "arch" ]; then
pacman -S --needed --noconfirm wget curl gcc gcc make automake libtool pkgconfig libaio lib32-libaio
else
echo -e "${Msg_Warning}Unsupported operating system: ${system}"
fi
}
env_check() {
REGEX=("debian|astra" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora" "arch" "freebsd" "alpine" "openbsd" "opencloudos")
RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Fedora" "Arch" "FreeBSD" "Alpine" "OpenBSD" "OpenCloudOS")
@@ -540,14 +480,8 @@ env_check() {
_green "Installing sysbench"
${INSTALL_CMD} sysbench
if [ $? -ne 0 ]; then
echo "Unable to download sysbench through package manager, attempting compilation..."
wget -O /tmp/sysbench.zip "${cdn_success_url}https://github.com/akopytov/sysbench/archive/1.0.20.zip" || curl -Lk -o /tmp/sysbench.zip "${cdn_success_url}https://github.com/akopytov/sysbench/archive/1.0.20.zip"
if [ ! -f /tmp/sysbench.zip ]; then
wget -q -O /tmp/sysbench.zip "https://hub.fgit.cf/akopytov/sysbench/archive/1.0.20.zip"
fi
chmod +x /tmp/sysbench.zip
unzip /tmp/sysbench.zip -d /tmp
Check_SysBench
_red "Unable to install sysbench through package manager"
_yellow "Sysbench installation skipped"
fi
fi
if ! command -v geekbench >/dev/null 2>&1; then
@@ -663,4 +597,4 @@ case "$1" in
echo
show_help
;;
esac
esac

View File

@@ -10,7 +10,6 @@ import (
func MemoryTest(language, testMethod string) (realTestMethod, res string) {
if runtime.GOOS == "windows" {
if testMethod != "winsat" && testMethod != "" {
// res = "Detected host is Windows, using Winsat for testing.\n"
realTestMethod = "winsat"
}
res += memory.WinsatTest(language)
@@ -19,7 +18,6 @@ func MemoryTest(language, testMethod string) (realTestMethod, res string) {
case "sysbench":
res = memory.SysBenchTest(language)
if res == "" {
// res = "sysbench test failed, switch to use dd test.\n"
res += memory.DDTest(language)
realTestMethod = "dd"
} else {
@@ -29,7 +27,6 @@ func MemoryTest(language, testMethod string) (realTestMethod, res string) {
res = memory.DDTest(language)
realTestMethod = "dd"
default:
// res = "Unsupported test method, switch to use dd test.\n"
res += memory.DDTest(language)
realTestMethod = "dd"
}

44
nexttrace/nexttrace.go Normal file
View File

@@ -0,0 +1,44 @@
package nexttrace
import (
"fmt"
"strings"
"github.com/oneclickvirt/nt3/nt"
)
func NextTrace3Check(language, nt3Location, nt3CheckType string) {
resultChan := make(chan nt.TraceResult, 100)
go nt.TraceRoute(language, nt3Location, nt3CheckType, resultChan)
for result := range resultChan {
if result.Index == -1 {
for index, res := range result.Output {
res = strings.TrimSpace(res)
if res != "" && index == 0 {
fmt.Println(res)
}
}
continue
}
if result.ISPName == "Error" {
for _, res := range result.Output {
res = strings.TrimSpace(res)
if res != "" {
fmt.Println(res)
}
}
return
}
for _, res := range result.Output {
res = strings.TrimSpace(res)
if res == "" {
continue
}
if strings.Contains(res, "ICMP") {
fmt.Print(res)
} else {
fmt.Println(res)
}
}
}
}

View File

@@ -0,0 +1,13 @@
package nexttrace
import (
"testing"
"time"
)
func TestNextTrace3Check(t *testing.T) {
start := time.Now()
NextTrace3Check("zh", "ALL", "ipv4")
duration := time.Since(start)
t.Logf("执行耗时: %s", duration)
}

66
upstreams/upstreams.go Normal file
View File

@@ -0,0 +1,66 @@
package upstreams
import (
"fmt"
"sync"
"time"
"github.com/oneclickvirt/UnlockTests/uts"
bgptools "github.com/oneclickvirt/backtrace/bgptools"
backtrace "github.com/oneclickvirt/backtrace/bk"
. "github.com/oneclickvirt/defaultset"
)
type IpInfo struct {
Ip string `json:"ip"`
City string `json:"city"`
Region string `json:"region"`
Country string `json:"country"`
Org string `json:"org"`
}
type ConcurrentResults struct {
bgpResult string
backtraceResult string
bgpError error
// backtraceError error
}
var IPV4, IPV6 string
func UpstreamsCheck() {
results := ConcurrentResults{}
var wg sync.WaitGroup
if IPV4 != "" {
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 2; i++ {
result, err := bgptools.GetPoPInfo(IPV4)
results.bgpError = err
if err == nil && result.Result != "" {
results.bgpResult = result.Result
return
}
if i == 0 {
time.Sleep(3 * time.Second)
}
}
}()
}
wg.Add(1)
go func() {
defer wg.Done()
result := backtrace.BackTrace(uts.IPV6)
results.backtraceResult = result
}()
wg.Wait()
if results.bgpResult != "" {
fmt.Print(results.bgpResult)
}
if results.backtraceResult != "" {
fmt.Printf("%s\n", results.backtraceResult)
}
fmt.Println(Yellow("准确线路自行查看详细路由,本测试结果仅作参考"))
fmt.Println(Yellow("同一目标地址多个线路时,检测可能已越过汇聚层,除第一个线路外,后续信息可能无效"))
}

View File

@@ -0,0 +1,8 @@
package upstreams
import "testing"
func TestUpstreamsCheck(t *testing.T) {
IPV4 = "148.100.85.25"
UpstreamsCheck()
}

View File

@@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
"time"
@@ -18,11 +19,28 @@ import (
"github.com/imroc/req/v3"
"github.com/oneclickvirt/UnlockTests/uts"
bnetwork "github.com/oneclickvirt/basics/network"
"github.com/oneclickvirt/basics/system"
butils "github.com/oneclickvirt/basics/utils"
. "github.com/oneclickvirt/defaultset"
"github.com/oneclickvirt/security/network"
)
// 获取本程序本日及总执行的统计信息
type StatsResponse struct {
Counter string `json:"counter"`
Action string `json:"action"`
Total int `json:"total"`
Daily int `json:"daily"`
Date string `json:"date"`
Timestamp string `json:"timestamp"`
}
// 获取最新的Github的仓库中的版本
type GitHubRelease struct {
TagName string `json:"tag_name"`
}
// PrintCenteredTitle 根据指定的宽度打印居中标题
func PrintCenteredTitle(title string, width int) {
// 计算字符串的字符数
@@ -98,18 +116,38 @@ func CheckChina(enableLogger bool) bool {
return selectChina
}
// OnlyBasicsIpInfo 仅检查和输出IP信息
func OnlyBasicsIpInfo(language string) (string, string, string) {
ipv4, ipv6, ipInfo, _, err := bnetwork.NetworkCheck("both", false, language)
if err != nil {
return "", "", ""
}
basicInfo := ipInfo
if strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") && ipv4 != "" && ipv6 != "" {
uts.IPV4 = true
uts.IPV6 = true
} else if strings.Contains(ipInfo, "IPV4") && ipv4 != "" {
uts.IPV4 = true
uts.IPV6 = false
} else if strings.Contains(ipInfo, "IPV6") && ipv6 != "" {
uts.IPV6 = true
uts.IPV4 = false
}
basicInfo = strings.ReplaceAll(basicInfo, "\n\n", "\n")
return ipv4, ipv6, basicInfo
}
// BasicsAndSecurityCheck 执行安全检查
func BasicsAndSecurityCheck(language, nt3CheckType string, securityCheckStatus bool) (string, string, string) {
func BasicsAndSecurityCheck(language, nt3CheckType string, securityCheckStatus bool) (string, string, string, string, string) {
var wgt sync.WaitGroup
var ipInfo, securityInfo, systemInfo string
var err error
var ipv4, ipv6, ipInfo, securityInfo, systemInfo string
wgt.Add(1)
go func() {
defer wgt.Done()
ipInfo, securityInfo, err = network.NetworkCheck("both", securityCheckStatus, language)
if err != nil {
fmt.Println(err.Error())
}
ipv4, ipv6, ipInfo, securityInfo, _ = network.NetworkCheck("both", securityCheckStatus, language)
// if err != nil {
// fmt.Println(err.Error())
// }
}()
wgt.Add(1)
go func() {
@@ -118,19 +156,19 @@ func BasicsAndSecurityCheck(language, nt3CheckType string, securityCheckStatus b
}()
wgt.Wait()
basicInfo := systemInfo + ipInfo
if strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") {
if strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") && ipv4 != "" && ipv6 != "" {
uts.IPV4 = true
uts.IPV6 = true
if nt3CheckType == "" {
nt3CheckType = "ipv4"
}
} else if strings.Contains(ipInfo, "IPV4") {
} else if strings.Contains(ipInfo, "IPV4") && ipv4 != "" {
uts.IPV4 = true
uts.IPV6 = false
if nt3CheckType == "" {
nt3CheckType = "ipv4"
}
} else if strings.Contains(ipInfo, "IPV6") {
} else if strings.Contains(ipInfo, "IPV6") && ipv6 != "" {
uts.IPV6 = true
uts.IPV4 = false
if nt3CheckType == "" {
@@ -143,7 +181,7 @@ func BasicsAndSecurityCheck(language, nt3CheckType string, securityCheckStatus b
nt3CheckType = "ipv4"
}
basicInfo = strings.ReplaceAll(basicInfo, "\n\n", "\n")
return basicInfo, securityInfo, nt3CheckType
return ipv4, ipv6, basicInfo, securityInfo, nt3CheckType
}
// CaptureOutput 捕获函数输出和错误输出,实时输出,并返回字符串
@@ -335,8 +373,6 @@ func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string
return "", ""
}
// ============================= 前置联网能力检测 =============================
var StackType string
type NetCheckResult struct {
@@ -358,6 +394,7 @@ func makeResolver(proto, dnsAddr string) *net.Resolver {
}
}
// 前置联网能力检测
func CheckPublicAccess(timeout time.Duration) NetCheckResult {
if timeout < 2*time.Second {
timeout = 2 * time.Second
@@ -483,6 +520,7 @@ result:
stack = "IPv6"
}
StackType = stack
butils.CheckPublicAccess(3 * time.Second) // 设置basics检测避免部分测试未启用
return NetCheckResult{
HasIPv4: hasV4,
HasIPv6: hasV6,
@@ -490,3 +528,77 @@ result:
StackType: stack,
}
}
// 获取每日/总的程序执行统计信息
func GetGoescStats() (*StatsResponse, error) {
client := req.C().SetTimeout(5 * time.Second)
var stats StatsResponse
resp, err := client.R().
SetSuccessResult(&stats).
Get("https://hits.spiritlhl.net/goecs")
if err != nil {
return nil, err
}
if !resp.IsSuccessState() {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
return &stats, nil
}
// 统计结果单位转换
func FormatGoecsNumber(num int) string {
if num >= 1000000 {
return fmt.Sprintf("%.1fM", float64(num)/1000000)
} else if num >= 1000 {
return fmt.Sprintf("%.1fK", float64(num)/1000)
}
return fmt.Sprintf("%d", num)
}
// 通过Github的API检索仓库最新TAG的版本
func GetLatestEcsRelease() (*GitHubRelease, error) {
urls := []string{
"https://api.github.com/repos/oneclickvirt/ecs/releases/latest",
"https://fd.spiritlhl.top/https://api.github.com/repos/oneclickvirt/ecs/releases/latest",
"https://githubapi.spiritlhl.top/repos/oneclickvirt/ecs/releases/latest",
"https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest",
}
client := req.C().SetTimeout(3 * time.Second)
for _, url := range urls {
var release GitHubRelease
resp, err := client.R().
SetSuccessResult(&release).
Get(url)
if err != nil {
continue
}
if resp.IsSuccessState() && release.TagName != "" {
return &release, nil
}
}
return nil, fmt.Errorf("failed to fetch release from all sources")
}
// 比较程序版本是否需要升级
func CompareVersions(v1, v2 string) int {
normalize := func(s string) []int {
s = strings.TrimPrefix(strings.ToLower(s), "v")
parts := strings.Split(s, ".")
result := make([]int, 3)
for i := 0; i < 3 && i < len(parts); i++ {
n, _ := strconv.Atoi(parts[i])
result[i] = n
}
return result
}
a := normalize(v1)
b := normalize(v2)
for i := 0; i < 3; i++ {
if a[i] < b[i] {
return -1
} else if a[i] > b[i] {
return 1
}
}
return 0
}

View File

@@ -6,7 +6,17 @@ import (
"time"
)
func TestCheckPublicAccess(t *testing.T) {
// func TestCheckPublicAccess(t *testing.T) {
// timeout := 3 * time.Second
// result := CheckPublicAccess(timeout)
// if result.Connected {
// fmt.Print("✅ 本机有公网连接,类型: %s\n", result.StackType)
// } else {
// fmt.Println("❌ 本机未检测到公网连接")
// }
// }
func TestBasicsAndSecurityCheck(t *testing.T) {
timeout := 3 * time.Second
result := CheckPublicAccess(timeout)
if result.Connected {
@@ -14,4 +24,8 @@ func TestCheckPublicAccess(t *testing.T) {
} else {
fmt.Println("❌ 本机未检测到公网连接")
}
_, _, basicInfo, securityInfo, nt3CheckType := BasicsAndSecurityCheck("zh", "ipv4", false)
fmt.Println(basicInfo)
fmt.Println(securityInfo)
fmt.Println(nt3CheckType)
}