mirror of
https://github.com/oneclickvirt/ecs.git
synced 2025-12-19 07:48:11 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39c2607b42 | ||
|
|
519c0f3e86 | ||
|
|
3b5b8a348e | ||
|
|
858585b4ff | ||
|
|
b891416147 | ||
|
|
8e79568895 | ||
|
|
01aa051c96 | ||
|
|
628a380122 | ||
|
|
2b94d289f3 | ||
|
|
e3676760da |
@@ -276,20 +276,19 @@ AMD的7950x单核满血性能得分在6500左右,AMD的5950x单核满血性能
|
||||
| ----------- | ---------- |
|
||||
| hosting | 数据中心网络(IDC) |
|
||||
| residential | 家庭/住宅网络(家宽) |
|
||||
| FixedLineISP,ISP | 固定线路互联网服务提供商(家宽) |
|
||||
| isp | 固定线路互联网服务提供商(家宽) |
|
||||
| business | 企业办公网络(商宽) |
|
||||
| cellular | 移动运营商网络(家宽) |
|
||||
| education | 教育机构网络(教育网) |
|
||||
| government | 政府机构网络(政府网) |
|
||||
| military | 军事网络(政府网) |
|
||||
| DataCenter/WebHosting/Transit | 数据中心网络(IDC) |
|
||||
| CDN | 内容分发网络(IDC) |
|
||||
|
||||
| 公司类型 | 说明 |
|
||||
| ------------ | ------------ |
|
||||
| business | 企业公司(商宽) |
|
||||
| hosting | 主机/数据中心公司(IDC) |
|
||||
| FixedLineISP,ISP | 固定线路互联网服务提供商(家宽) |
|
||||
| business | 企业公司(商宽) |
|
||||
| isp | 固定线路互联网服务提供商(家宽) |
|
||||
| education | 教育机构(教育网) |
|
||||
| government | 政府机构(政府网) |
|
||||
|
||||
@@ -399,8 +398,7 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
|
||||
| 中国电信 | 163 | ChinaNet (原163骨干网) | 普通国际出口,延迟高易绕路 | 一般 |
|
||||
| 中国电信 | CN2 GT | ChinaNet Next Carrying Network (GT) | 较优于163,偶有拥堵 | 良好 |
|
||||
| 中国电信 | CN2 GIA | Global Internet Access(GT) | 直连国际POP,低延迟低丢包 | 优质(最好) |
|
||||
| 中国联通 | 169 | China169骨干网 | 老主干网,常经港美出口 | 一般(少部分优质) |
|
||||
| 中国联通 | 4837 | Unicom International (AS4837) | 常见国际出口,覆盖广 | 良好 |
|
||||
| 中国联通 | 4837 | Unicom International (AS4837) | 常见国际出口,覆盖广 | 一般到良好 |
|
||||
| 中国联通 | 9929 | Unicom Premium / CU-IX | 精品网,直连主要IXP,延迟低 | 优质 |
|
||||
| 中国移动 | CMI (AS58453) | China Mobile International | 节点多,对两广(广东广西)优化好 | 两广良好,其他一般 |
|
||||
| 中国移动 | CMIN2 (AS58807) | China Mobile International N2 | 高质量专线,低延迟低丢包,对标CN2 | 优质 |
|
||||
@@ -429,7 +427,7 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
|
||||
| 中国电信 | CN2 BGP | CN2混合BGP(GIA+GT) | 混合路由,性能略低于纯GIA | 良好至优质 |
|
||||
| 中国电信 | CUII | ChinaNet United International Internet | 面向直连美国的专线 | 优质 |
|
||||
| 中国电信 | 163+CUII混线 | 163国内段+国际专线出口 | 价格低,性能一般 | 一般 |
|
||||
| 中国联通 | 169 | China169骨干网 | 老主干网,常经港美出口 | 一般(少部分优质) |
|
||||
| 中国联通 | 169 | China169骨干网 | 老主干网,一般对接4837 | 一般(少部分优质) |
|
||||
| 中国联通 | 4837 | Unicom International (AS4837) | 常见国际出口,覆盖广 | 良好 |
|
||||
| 中国联通 | 9929 | Unicom Premium / CU-IX | 精品网,直连IXP,低延迟 | 优质 |
|
||||
| 中国联通 | 9929+4837混BGP | 混合出口(IDC常见优化) | 性能平衡 | 良好 |
|
||||
@@ -716,20 +714,19 @@ Generally speaking, checking the usage type, company type, and security informat
|
||||
| ----------- | ---------- |
|
||||
| hosting | Data center network (IDC) |
|
||||
| residential | Home/Residential network (Home broadband) |
|
||||
| FixedLineISP, ISP | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| isp | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| business | Enterprise office network (Business broadband) |
|
||||
| cellular | Mobile carrier network (Home broadband) |
|
||||
| education | Educational institution network (Education network) |
|
||||
| government | Government institution network (Government network) |
|
||||
| military | Military network (Government network) |
|
||||
| DataCenter/WebHosting/Transit | Data center network (IDC) |
|
||||
| CDN | Content Delivery Network (IDC) |
|
||||
|
||||
| Company Type | Description |
|
||||
| ------------ | ------------ |
|
||||
| business | Business company (Business broadband) |
|
||||
| hosting | Hosting/Data center company (IDC) |
|
||||
| FixedLineISP, ISP | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| business | Business company (Business broadband) |
|
||||
| isp | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| education | Educational institution (Education network) |
|
||||
| government | Government institution (Government network) |
|
||||
|
||||
@@ -1050,20 +1047,19 @@ IP品質によるアクセス制限に敏感なのは、実際には主要なAI
|
||||
| ----------- | ---------- |
|
||||
| hosting | データセンターネットワーク(IDC) |
|
||||
| residential | 家庭/住宅ネットワーク(家庭用回線) |
|
||||
| FixedLineISP、ISP | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| isp | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| business | 企業オフィスネットワーク(ビジネス回線) |
|
||||
| cellular | モバイル通信事業者ネットワーク(家庭用回線) |
|
||||
| education | 教育機関ネットワーク(教育ネットワーク) |
|
||||
| government | 政府機関ネットワーク(政府ネットワーク) |
|
||||
| military | 軍事ネットワーク(政府ネットワーク) |
|
||||
| DataCenter/WebHosting/Transit | データセンターネットワーク(IDC) |
|
||||
| CDN | コンテンツ配信ネットワーク(IDC) |
|
||||
|
||||
| 会社タイプ | 説明 |
|
||||
| ------------ | ------------ |
|
||||
| business | 企業会社(ビジネス回線) |
|
||||
| hosting | ホスト/データセンター会社(IDC) |
|
||||
| FixedLineISP、ISP | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| business | 企業会社(ビジネス回線) |
|
||||
| isp | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| education | 教育機関(教育ネットワーク) |
|
||||
| government | 政府機関(政府ネットワーク) |
|
||||
|
||||
|
||||
10
go.mod
10
go.mod
@@ -4,18 +4,18 @@ go 1.25.3
|
||||
|
||||
require (
|
||||
github.com/imroc/req/v3 v3.54.0
|
||||
github.com/oneclickvirt/UnlockTests v0.0.30-20251109035206
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251102140847
|
||||
github.com/oneclickvirt/UnlockTests v0.0.31-20251111095646
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457
|
||||
github.com/oneclickvirt/basics v0.0.16-20251030093657
|
||||
github.com/oneclickvirt/cputest v0.0.12-20250720122317
|
||||
github.com/oneclickvirt/cputest v0.0.12-20251111095842
|
||||
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-20251104114914
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251111095706
|
||||
github.com/oneclickvirt/pingtest v0.0.9-20251104112920
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900
|
||||
github.com/oneclickvirt/security v0.0.7-20251106060213
|
||||
github.com/oneclickvirt/security v0.0.7-20251109090041
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740
|
||||
)
|
||||
|
||||
|
||||
20
go.sum
20
go.sum
@@ -94,14 +94,14 @@ 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/oneclickvirt/UnlockTests v0.0.30-20251109035206 h1:c5mUPst0P0K54N5bNbNdme8C2wajSCJxZ/5+p42s7ZY=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.30-20251109035206/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251102140847 h1:OiwD06+Mql3pYP8jJFFdP3OUlCrx/qJT7y2YCd/OMiI=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251102140847/go.mod h1:mj9TSow7FNszBb3bQj2Hhm41LwBo7HQP6sgaPtovKdM=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.31-20251111095646 h1:GXwimPara6aY88GNYnTkFQfr/aLPsFATT4aDTRDdVsU=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.31-20251111095646/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457 h1:599/R/qMAtfPCPG1bPoi6KbjNJzVkKtxm8dvVIdtn5o=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457/go.mod h1:mj9TSow7FNszBb3bQj2Hhm41LwBo7HQP6sgaPtovKdM=
|
||||
github.com/oneclickvirt/basics v0.0.16-20251030093657 h1:6SWWILNjJfMTXbspqYRpktUEOe/QIVhGonKO8ODC7n4=
|
||||
github.com/oneclickvirt/basics v0.0.16-20251030093657/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/cputest v0.0.12-20251111095842 h1:ixZUvIkSlsIZfsg+dNDKq/FTofEtUjfA2LtpTrNr/6s=
|
||||
github.com/oneclickvirt/cputest v0.0.12-20251111095842/go.mod h1:vjlH8tkPFft1tlLOpeNskXVvurxkHaJ3+dgFxQGLXY4=
|
||||
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=
|
||||
@@ -116,14 +116,14 @@ github.com/oneclickvirt/mbw v0.0.1-20250808061222 h1:WGXOe6QvHiDRhPVMI0VcctjzW08
|
||||
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/nt3 v0.0.10-20251104114914 h1:P4nbdKcIA7+FH4feLLxfiJVf1f3ENi/oo37EsdyX9oI=
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251104114914/go.mod h1:yo1ufkduFt9QjqG7nqSUf1D3YlQOmFpdlTYniJfclQI=
|
||||
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/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/security v0.0.7-20251106060213 h1:vBCEFvuWpScXZ9O7Y7cW1zp1V2AfjzMN+YSBcYfpjYs=
|
||||
github.com/oneclickvirt/security v0.0.7-20251106060213/go.mod h1:YfDilPFW22szjdUNgv4VOuSwHnZzsFsdPOfRYiMoc3I=
|
||||
github.com/oneclickvirt/security v0.0.7-20251109090041 h1:H5Brkx2pKNRZAnvk1wABFcg+krXAygHgWV9R3+LU7xE=
|
||||
github.com/oneclickvirt/security v0.0.7-20251109090041/go.mod h1:YfDilPFW22szjdUNgv4VOuSwHnZzsFsdPOfRYiMoc3I=
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740 h1:1NUrNt5ay6/xVNC5x62UrQjPqK8jgbKtyjBml/3boZg=
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740/go.mod h1:fy0II2Wo7kDWVBKTwcHdodZwyfmJo0g8N9V02EwQDZE=
|
||||
github.com/oneclickvirt/stream v0.0.2-20250924154001 h1:GuJWdiPkoK84+y/+oHKr2Ghl3c/MzS9Z5m1nM+lMmy4=
|
||||
|
||||
7
goecs.go
7
goecs.go
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ecsVersion = "v0.1.101" // 融合怪版本号
|
||||
ecsVersion = "v0.1.103" // 融合怪版本号
|
||||
configs = params.NewConfig(ecsVersion) // 全局配置实例
|
||||
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
|
||||
)
|
||||
@@ -83,6 +83,7 @@ func main() {
|
||||
basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo string
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
infoMutex sync.Mutex // 保护并发字符串写入
|
||||
)
|
||||
startTime := time.Now()
|
||||
uploadDone := make(chan bool, 1)
|
||||
@@ -91,9 +92,9 @@ func main() {
|
||||
go runner.HandleSignalInterrupt(sig, configs, &startTime, &output, tempOutput, uploadDone, &outputMutex)
|
||||
switch configs.Language {
|
||||
case "zh":
|
||||
runner.RunChineseTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex)
|
||||
runner.RunChineseTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
case "en":
|
||||
runner.RunEnglishTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex)
|
||||
runner.RunEnglishTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
default:
|
||||
fmt.Println("Unsupported language")
|
||||
}
|
||||
|
||||
6
goecs.sh
6
goecs.sh
@@ -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.100"
|
||||
ECS_VERSION="0.1.102"
|
||||
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.100"
|
||||
ECS_VERSION="0.1.100"
|
||||
_yellow "Unable to get version info, using default version 0.1.102"
|
||||
ECS_VERSION="0.1.102"
|
||||
fi
|
||||
version_output=""
|
||||
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do
|
||||
|
||||
@@ -21,7 +21,7 @@ func GetMenuChoice(language string) string {
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer signal.Stop(sigChan)
|
||||
inputChan := make(chan string, 1)
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-sigChan:
|
||||
@@ -31,43 +31,33 @@ func GetMenuChoice(language string) string {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
go func() {
|
||||
var input string
|
||||
fmt.Print("请输入选项 / Please enter your choice: ")
|
||||
fmt.Scanln(&input)
|
||||
input = strings.TrimSpace(input)
|
||||
input = strings.TrimRight(input, "\n")
|
||||
select {
|
||||
case inputChan <- input:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case input := <-inputChan:
|
||||
re := regexp.MustCompile(`^\d+$`)
|
||||
if re.MatchString(input) {
|
||||
inChoice := input
|
||||
switch inChoice {
|
||||
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10":
|
||||
return inChoice
|
||||
default:
|
||||
if language == "zh" {
|
||||
fmt.Println("无效的选项")
|
||||
} else {
|
||||
fmt.Println("Invalid choice")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var input string
|
||||
fmt.Print("请输入选项 / Please enter your choice: ")
|
||||
fmt.Scanln(&input)
|
||||
input = strings.TrimSpace(input)
|
||||
input = strings.TrimRight(input, "\n")
|
||||
|
||||
re := regexp.MustCompile(`^\d+$`)
|
||||
if re.MatchString(input) {
|
||||
inChoice := input
|
||||
switch inChoice {
|
||||
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10":
|
||||
return inChoice
|
||||
default:
|
||||
if language == "zh" {
|
||||
fmt.Println("输入错误,请输入一个纯数字")
|
||||
fmt.Println("无效的选项")
|
||||
} else {
|
||||
fmt.Println("Invalid input, please enter a number")
|
||||
fmt.Println("Invalid choice")
|
||||
}
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ""
|
||||
} else {
|
||||
if language == "zh" {
|
||||
fmt.Println("输入错误,请输入一个纯数字")
|
||||
} else {
|
||||
fmt.Println("Invalid input, please enter a number")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,72 +210,116 @@ func (c *Config) SaveUserSetParams() map[string]interface{} {
|
||||
// RestoreUserSetParams restores user-set parameters
|
||||
func (c *Config) RestoreUserSetParams(saved map[string]interface{}) {
|
||||
if val, ok := saved["basic"]; ok {
|
||||
c.BasicStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.BasicStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["cpu"]; ok {
|
||||
c.CpuTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.CpuTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["memory"]; ok {
|
||||
c.MemoryTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.MemoryTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["disk"]; ok {
|
||||
c.DiskTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.DiskTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["ut"]; ok {
|
||||
c.UtTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.UtTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["security"]; ok {
|
||||
c.SecurityTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.SecurityTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["email"]; ok {
|
||||
c.EmailTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.EmailTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["backtrace"]; ok {
|
||||
c.BacktraceStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.BacktraceStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["nt3"]; ok {
|
||||
c.Nt3Status = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.Nt3Status = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["speed"]; ok {
|
||||
c.SpeedTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.SpeedTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["ping"]; ok {
|
||||
c.PingTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.PingTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["tgdc"]; ok {
|
||||
c.TgdcTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.TgdcTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["web"]; ok {
|
||||
c.WebTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.WebTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["cpum"]; ok {
|
||||
c.CpuTestMethod = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.CpuTestMethod = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["cput"]; ok {
|
||||
c.CpuTestThreadMode = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.CpuTestThreadMode = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["memorym"]; ok {
|
||||
c.MemoryTestMethod = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.MemoryTestMethod = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["diskm"]; ok {
|
||||
c.DiskTestMethod = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.DiskTestMethod = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["diskp"]; ok {
|
||||
c.DiskTestPath = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.DiskTestPath = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["diskmc"]; ok {
|
||||
c.DiskMultiCheck = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.DiskMultiCheck = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["nt3loc"]; ok {
|
||||
if c.Choice != "10" {
|
||||
c.Nt3Location = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.Nt3Location = strVal
|
||||
}
|
||||
}
|
||||
}
|
||||
if val, ok := saved["nt3t"]; ok {
|
||||
c.Nt3CheckType = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.Nt3CheckType = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["spnum"]; ok {
|
||||
c.SpNum = val.(int)
|
||||
if intVal, ok := val.(int); ok {
|
||||
c.SpNum = intVal
|
||||
}
|
||||
}
|
||||
|
||||
c.ValidateParams()
|
||||
|
||||
@@ -2,6 +2,7 @@ package runner
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// RunChineseTests runs all tests in Chinese mode
|
||||
func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) {
|
||||
func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex, infoMutex *sync.Mutex) {
|
||||
*output = RunBasicTests(preCheck, config, basicInfo, securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunCPUTest(config, *output, tempOutput, outputMutex)
|
||||
*output = RunMemoryTest(config, *output, tempOutput, outputMutex)
|
||||
@@ -29,30 +30,39 @@ func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1,
|
||||
wg1.Add(1)
|
||||
go func() {
|
||||
defer wg1.Done()
|
||||
*mediaInfo = tests.MediaTest(config.Language)
|
||||
result := tests.MediaTest(config.Language)
|
||||
infoMutex.Lock()
|
||||
*mediaInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if config.EmailTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
wg2.Add(1)
|
||||
go func() {
|
||||
defer wg2.Done()
|
||||
*emailInfo = email.EmailCheck()
|
||||
result := email.EmailCheck()
|
||||
infoMutex.Lock()
|
||||
*emailInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if (config.OnlyChinaTest || config.PingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
wg3.Add(1)
|
||||
go func() {
|
||||
defer wg3.Done()
|
||||
*ptInfo = pt.PingTest()
|
||||
result := pt.PingTest()
|
||||
infoMutex.Lock()
|
||||
*ptInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
*output = RunSecurityTests(config, *securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
}
|
||||
if runtime.GOOS != "windows" && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
*output = RunNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
}
|
||||
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
*output = RunSpeedTests(config, *output, tempOutput, outputMutex)
|
||||
@@ -61,7 +71,7 @@ func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1,
|
||||
}
|
||||
|
||||
// RunEnglishTests runs all tests in English mode
|
||||
func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) {
|
||||
func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex, infoMutex *sync.Mutex) {
|
||||
*output = RunBasicTests(preCheck, config, basicInfo, securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunCPUTest(config, *output, tempOutput, outputMutex)
|
||||
*output = RunMemoryTest(config, *output, tempOutput, outputMutex)
|
||||
@@ -74,19 +84,25 @@ func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1,
|
||||
wg1.Add(1)
|
||||
go func() {
|
||||
defer wg1.Done()
|
||||
*mediaInfo = tests.MediaTest(config.Language)
|
||||
result := tests.MediaTest(config.Language)
|
||||
infoMutex.Lock()
|
||||
*mediaInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if config.EmailTestStatus {
|
||||
wg2.Add(1)
|
||||
go func() {
|
||||
defer wg2.Done()
|
||||
*emailInfo = email.EmailCheck()
|
||||
result := email.EmailCheck()
|
||||
infoMutex.Lock()
|
||||
*emailInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
*output = RunSecurityTests(config, *securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
*output = RunEnglishNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEnglishSpeedTests(config, *output, tempOutput, outputMutex)
|
||||
}
|
||||
@@ -218,7 +234,7 @@ func RunDiskTest(config *params.Config, output, tempOutput string, outputMutex *
|
||||
}
|
||||
|
||||
// RunStreamingTests runs platform unlock tests
|
||||
func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *string, output, tempOutput string, outputMutex *sync.Mutex, infoMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
return utils.PrintAndCapture(func() {
|
||||
@@ -229,7 +245,10 @@ func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *st
|
||||
} else {
|
||||
utils.PrintCenteredTitle("Cross-Border-Platform-Unlock", config.Width)
|
||||
}
|
||||
fmt.Printf("%s", *mediaInfo)
|
||||
infoMutex.Lock()
|
||||
info := *mediaInfo
|
||||
infoMutex.Unlock()
|
||||
fmt.Printf("%s", info)
|
||||
}
|
||||
}, tempOutput, output)
|
||||
}
|
||||
@@ -251,7 +270,7 @@ func RunSecurityTests(config *params.Config, securityInfo, output, tempOutput st
|
||||
}
|
||||
|
||||
// RunEmailTests runs email port tests
|
||||
func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput string, outputMutex *sync.Mutex, infoMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
return utils.PrintAndCapture(func() {
|
||||
@@ -262,13 +281,16 @@ func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string
|
||||
} else {
|
||||
utils.PrintCenteredTitle("Email-Port-Check", config.Width)
|
||||
}
|
||||
fmt.Println(*emailInfo)
|
||||
infoMutex.Lock()
|
||||
info := *emailInfo
|
||||
infoMutex.Unlock()
|
||||
fmt.Println(info)
|
||||
}
|
||||
}, tempOutput, output)
|
||||
}
|
||||
|
||||
// RunNetworkTests runs network tests (Chinese mode)
|
||||
func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex, infoMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
return utils.PrintAndCapture(func() {
|
||||
@@ -280,15 +302,18 @@ func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string,
|
||||
utils.PrintCenteredTitle("三网回程路由检测", config.Width)
|
||||
tests.NextTrace3Check(config.Language, config.Nt3Location, config.Nt3CheckType)
|
||||
}
|
||||
if config.OnlyChinaTest && *ptInfo != "" {
|
||||
infoMutex.Lock()
|
||||
info := *ptInfo
|
||||
infoMutex.Unlock()
|
||||
if config.OnlyChinaTest && info != "" {
|
||||
wg3.Wait()
|
||||
utils.PrintCenteredTitle("PING值检测", config.Width)
|
||||
fmt.Println(*ptInfo)
|
||||
fmt.Println(info)
|
||||
}
|
||||
if config.PingTestStatus && *ptInfo != "" {
|
||||
if config.PingTestStatus && info != "" {
|
||||
wg3.Wait()
|
||||
utils.PrintCenteredTitle("PING值检测", config.Width)
|
||||
fmt.Println(*ptInfo)
|
||||
fmt.Println(info)
|
||||
if config.TgdcTestStatus {
|
||||
fmt.Println(pt.TelegramDCTest())
|
||||
}
|
||||
@@ -414,16 +439,26 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
|
||||
httpsURL string
|
||||
}, 1)
|
||||
if config.EnableUpload {
|
||||
// 使用context来控制上传goroutine
|
||||
uploadCtx, uploadCancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer uploadCancel()
|
||||
|
||||
go func() {
|
||||
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload)
|
||||
resultChan <- struct {
|
||||
select {
|
||||
case resultChan <- struct {
|
||||
httpURL string
|
||||
httpsURL string
|
||||
}{httpURL, httpsURL}
|
||||
uploadDone <- true
|
||||
}{httpURL, httpsURL}:
|
||||
case <-uploadCtx.Done():
|
||||
// 上传被取消或超时,直接返回
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case result := <-resultChan:
|
||||
uploadCancel() // 成功完成,取消context
|
||||
if result.httpURL != "" || result.httpsURL != "" {
|
||||
if config.Language == "en" {
|
||||
fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL)
|
||||
@@ -437,7 +472,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
|
||||
fmt.Scanln()
|
||||
}
|
||||
os.Exit(0)
|
||||
case <-time.After(30 * time.Second):
|
||||
case <-uploadCtx.Done():
|
||||
if config.Language == "en" {
|
||||
fmt.Println("Upload timeout, program exit")
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -8,6 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func CpuTest(language, testMethod, testThread string) (realTestMethod, res string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] CpuTest panic: %v\n", r)
|
||||
res = fmt.Sprintf("\nCPU test failed: %v\n", r)
|
||||
realTestMethod = "error"
|
||||
}
|
||||
}()
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
if testMethod != "winsat" && testMethod != "" {
|
||||
// res = "Detected host is Windows, using Winsat for testing.\n"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -8,6 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func DiskTest(language, testMethod, testPath string, isMultiCheck bool, autoChange bool) (realTestMethod, res string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] DiskTest panic: %v\n", r)
|
||||
res = fmt.Sprintf("\nDisk test failed: %v\n", r)
|
||||
realTestMethod = "error"
|
||||
}
|
||||
}()
|
||||
|
||||
switch testMethod {
|
||||
case "fio":
|
||||
res = disk.FioTest(language, isMultiCheck, testPath)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -8,6 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func MemoryTest(language, testMethod string) (realTestMethod, res string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] MemoryTest panic: %v\n", r)
|
||||
res = fmt.Sprintf("\nMemory test failed: %v\n", r)
|
||||
realTestMethod = "error"
|
||||
}
|
||||
}()
|
||||
|
||||
testMethod = strings.ToLower(testMethod)
|
||||
if testMethod == "" {
|
||||
testMethod = "auto"
|
||||
|
||||
@@ -2,14 +2,55 @@ package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/oneclickvirt/nt3/nt"
|
||||
)
|
||||
|
||||
func NextTrace3Check(language, nt3Location, nt3CheckType string) {
|
||||
// 先检查 ICMP 权限
|
||||
conn, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
// 没有权限,显示友好提示并跳过
|
||||
if language == "zh" {
|
||||
fmt.Println("路由追踪测试需要 root 权限或 CAP_NET_RAW 能力,已跳过")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] ICMP权限不足: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("Route tracing test requires root privileges or CAP_NET_RAW capability, skipped")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Insufficient ICMP permission: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
conn.Close()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if language == "zh" {
|
||||
fmt.Println("路由追踪测试出现错误,已跳过")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] 路由追踪panic: %v\n", r)
|
||||
} else {
|
||||
fmt.Println("Route tracing test failed, skipped")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Route tracing panic: %v\n", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
resultChan := make(chan nt.TraceResult, 100)
|
||||
go nt.TraceRoute(language, nt3Location, nt3CheckType, resultChan)
|
||||
errorOccurred := false
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errorOccurred = true
|
||||
resultChan <- nt.TraceResult{
|
||||
Index: -1,
|
||||
ISPName: "Error",
|
||||
Output: []string{fmt.Sprintf("Route tracing error: %v", r)},
|
||||
}
|
||||
close(resultChan)
|
||||
}
|
||||
}()
|
||||
nt.TraceRoute(language, nt3Location, nt3CheckType, resultChan)
|
||||
}()
|
||||
for result := range resultChan {
|
||||
if result.Index == -1 {
|
||||
for index, res := range result.Output {
|
||||
@@ -21,12 +62,18 @@ func NextTrace3Check(language, nt3Location, nt3CheckType string) {
|
||||
continue
|
||||
}
|
||||
if result.ISPName == "Error" {
|
||||
if language == "zh" {
|
||||
fmt.Println("路由追踪测试失败(可能因为权限不足),已跳过")
|
||||
} else {
|
||||
fmt.Println("Route tracing test failed (possibly due to insufficient permissions), skipped")
|
||||
}
|
||||
for _, res := range result.Output {
|
||||
res = strings.TrimSpace(res)
|
||||
if res != "" {
|
||||
fmt.Println(res)
|
||||
fmt.Fprintf(os.Stderr, "[WARN] %s\n", res)
|
||||
}
|
||||
}
|
||||
errorOccurred = true
|
||||
continue
|
||||
}
|
||||
for _, res := range result.Output {
|
||||
@@ -41,4 +88,11 @@ func NextTrace3Check(language, nt3Location, nt3CheckType string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if errorOccurred {
|
||||
if language == "zh" {
|
||||
fmt.Println("提示: 路由追踪需要 root 权限或 CAP_NET_RAW 能力")
|
||||
} else {
|
||||
fmt.Println("Hint: Route tracing requires root privileges or CAP_NET_RAW capability")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -9,10 +11,20 @@ import (
|
||||
)
|
||||
|
||||
func ShowHead(language string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] ShowHead panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
sp.ShowHead(language)
|
||||
}
|
||||
|
||||
func NearbySP() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] NearbySP panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
|
||||
sp.NearbySpeedTest()
|
||||
} else {
|
||||
@@ -21,6 +33,11 @@ func NearbySP() {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}()
|
||||
var url, parseType string
|
||||
if strings.ToLower(platform) == "cn" {
|
||||
if strings.ToLower(operator) == "cmcc" {
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/oneclickvirt/UnlockTests/executor"
|
||||
"github.com/oneclickvirt/UnlockTests/utils"
|
||||
"github.com/oneclickvirt/defaultset"
|
||||
)
|
||||
|
||||
func MediaTest(language string) string {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] MediaTest panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
var res string
|
||||
readStatus := executor.ReadSelect(language, "0")
|
||||
if !readStatus {
|
||||
|
||||
@@ -2,6 +2,7 @@ package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -29,12 +30,25 @@ type ConcurrentResults struct {
|
||||
var IPV4, IPV6 string
|
||||
|
||||
func UpstreamsCheck() {
|
||||
// 添加panic恢复机制
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("\n上游检测出现错误,已跳过")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Upstream check panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
results := ConcurrentResults{}
|
||||
var wg sync.WaitGroup
|
||||
if IPV4 != "" {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] BGP info panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
for i := 0; i < 2; i++ {
|
||||
result, err := bgptools.GetPoPInfo(IPV4)
|
||||
results.bgpError = err
|
||||
@@ -51,6 +65,11 @@ func UpstreamsCheck() {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Backtrace panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
result := backtrace.BackTrace(executor.IPV6)
|
||||
results.backtraceResult = result
|
||||
}()
|
||||
|
||||
@@ -203,19 +203,10 @@ func CaptureOutput(f func()) string {
|
||||
// 替换标准输出和标准错误输出为管道写入端
|
||||
os.Stdout = stdoutPipeW
|
||||
os.Stderr = stderrPipeW
|
||||
// 恢复标准输出和标准错误输出
|
||||
defer func() {
|
||||
os.Stdout = oldStdout
|
||||
os.Stderr = oldStderr
|
||||
stdoutPipeW.Close()
|
||||
stderrPipeW.Close()
|
||||
stdoutPipeR.Close()
|
||||
stderrPipeR.Close()
|
||||
}()
|
||||
// 缓冲区
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
// 并发读取 stdout 和 stderr
|
||||
done := make(chan struct{})
|
||||
done := make(chan struct{}, 2)
|
||||
go func() {
|
||||
multiWriter := io.MultiWriter(&stdoutBuf, oldStdout)
|
||||
io.Copy(multiWriter, stdoutPipeR)
|
||||
@@ -234,6 +225,11 @@ func CaptureOutput(f func()) string {
|
||||
// 等待两个 goroutine 完成
|
||||
<-done
|
||||
<-done
|
||||
// 恢复标准输出和标准错误输出,并关闭管道读取端
|
||||
os.Stdout = oldStdout
|
||||
os.Stderr = oldStderr
|
||||
stdoutPipeR.Close()
|
||||
stderrPipeR.Close()
|
||||
// 返回捕获的输出字符串
|
||||
// stderrBuf.String()
|
||||
return stdoutBuf.String()
|
||||
@@ -317,7 +313,9 @@ func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string
|
||||
// 使用 defer 来处理 panic
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Printf("处理上传时发生错误: %v\n", r)
|
||||
fmt.Fprintf(os.Stderr, "[ERROR] 处理上传时发生严重错误: %v\n", r)
|
||||
// 可以选择打印堆栈信息以便调试
|
||||
// debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
// 检查文件是否存在
|
||||
@@ -425,6 +423,8 @@ func CheckPublicAccess(timeout time.Duration) NetCheckResult {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// 记录panic但不影响其他检查,输出到stderr避免污染主输出
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Panic in network check for %s (%s): %v\n", tag, addr, r)
|
||||
}
|
||||
}()
|
||||
switch kind {
|
||||
|
||||
Reference in New Issue
Block a user