Compare commits

...

9 Commits

Author SHA1 Message Date
spiritlhl
3bac30edc2 fix: 修复协程部分等待位置错误的问题 2025-06-29 07:02:10 +00:00
github-actions[bot]
9ef2ec4a9e chore: update ECS_VERSION to 0.1.38 in goecs.sh 2025-06-29 06:39:24 +00:00
spiritlhl
ac33e00e0a fix: 拆分main函数,分函数方便后续维护,添加前置检测自动切换离线模式 2025-06-29 06:27:59 +00:00
spiritlhl
7a439f7095 fix: 优化编译文件的大小 2025-06-29 10:55:39 +08:00
spiritlhl
e3bfa65f66 Merge pull request #12 from fossabot/add-license-scan-badge
Add license scan report and status
2025-06-29 09:36:58 +08:00
fossabot
74e33a212c Add license scan report and status
Signed off by: fossabot <badges@fossa.com>
2025-06-28 21:22:21 -04:00
spiritlhl
bba8595033 fix: 统一致谢图标大小 2025-06-29 01:00:05 +00:00
spiritlhl
530181be87 feat: 添加zmto对本开源项目的支持 2025-06-29 00:57:46 +00:00
github-actions[bot]
7deb986209 chore: update ECS_VERSION to 0.1.37 in goecs.sh 2025-06-28 14:02:18 +00:00
13 changed files with 787 additions and 449 deletions

View File

@@ -6,7 +6,9 @@ builds:
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
ldflags: ldflags:
- -s -w -X main.version={{.Version}} -X main.arch={{.Arch}} -checklinkname=0 - -s -w -X main.version={{.Version}} -X main.arch={{.Arch}} -checklinkname=0 -extldflags=-static
flags:
- -trimpath
goos: goos:
- linux - linux
- windows - windows
@@ -34,6 +36,8 @@ builds:
- CXX=o64-clang++ - CXX=o64-clang++
ldflags: ldflags:
- -s -w -X main.version={{.Version}} -X main.arch={{.Arch}} -checklinkname=0 - -s -w -X main.version={{.Version}} -X main.arch={{.Arch}} -checklinkname=0
flags:
- -trimpath
goos: goos:
- darwin - darwin
goarch: goarch:
@@ -47,6 +51,8 @@ builds:
- CXX=oa64-clang++ - CXX=oa64-clang++
ldflags: ldflags:
- -s -w -X main.version={{.Version}} -X main.arch={{.Arch}} -checklinkname=0 - -s -w -X main.version={{.Version}} -X main.arch={{.Arch}} -checklinkname=0
flags:
- -trimpath
goos: goos:
- darwin - darwin
goarch: goarch:

View File

@@ -2,6 +2,8 @@
[![release](https://github.com/oneclickvirt/ecs/actions/workflows/main.yaml/badge.svg)](https://github.com/oneclickvirt/ecs/actions/workflows/main.yaml) [![release](https://github.com/oneclickvirt/ecs/actions/workflows/main.yaml/badge.svg)](https://github.com/oneclickvirt/ecs/actions/workflows/main.yaml)
[![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)
融合怪测评项目 - GO版本 融合怪测评项目 - GO版本
@@ -137,19 +139,19 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
export noninteractive=true && ./goecs.sh env export noninteractive=true && ./goecs.sh env
``` ```
3. **安装 `goecs`** 3. **安装 `goecs` 本体(仅下载二进制文件无依赖安装)**
```bash ```bash
./goecs.sh install ./goecs.sh install
``` ```
4. **升级 `goecs`** 4. **升级 `goecs` 本体**
```bash ```bash
./goecs.sh upgrade ./goecs.sh upgrade
``` ```
5. **卸载 `goecs`** 5. **卸载 `goecs` 本体**
```bash ```bash
./goecs.sh uninstall ./goecs.sh uninstall
@@ -341,6 +343,7 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
| 测试稳定性 | 核心测试组件10年以上未变 | 每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU) | | 测试稳定性 | 核心测试组件10年以上未变 | 每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU) |
| 测试内容 | 仅测试计算性能 | 覆盖多种性能测试,分数加权计算,但部分测试实际不常用 | | 测试内容 | 仅测试计算性能 | 覆盖多种性能测试,分数加权计算,但部分测试实际不常用 |
| 适用场景 | 适合快速测试,仅测试计算性能 | 适合综合全面的测试 | | 适用场景 | 适合快速测试,仅测试计算性能 | 适合综合全面的测试 |
| 排行榜 | [sysbench.spiritlhl.net](https://sysbench.spiritlhl.net/) | [browser.geekbench.com](https://browser.geekbench.com/) |
且```goecs```测试使用何种CPU测试方式可使用参数指定默认只是为了更多用户快速测试的需求 且```goecs```测试使用何种CPU测试方式可使用参数指定默认只是为了更多用户快速测试的需求
@@ -371,7 +374,7 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
感谢 感谢
<a href="https://h501.io/?from=69" target="_blank"> <a href="https://h501.io/?from=69" target="_blank">
<img src="https://github.com/spiritLHLS/ecs/assets/103393591/dfd47230-2747-4112-be69-b5636b34f07f" alt="h501"> <img src="https://github.com/spiritLHLS/ecs/assets/103393591/dfd47230-2747-4112-be69-b5636b34f07f" alt="h501" style="height: 50px;">
</a> </a>
提供的免费托管支持本开源项目的共享测试结果存储 提供的免费托管支持本开源项目的共享测试结果存储
@@ -379,13 +382,20 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
同时感谢以下平台提供编辑和测试支持 同时感谢以下平台提供编辑和测试支持
<a href="https://www.jetbrains.com/go/" target="_blank"> <a href="https://www.jetbrains.com/go/" target="_blank">
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland"> <img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland" style="height: 50px;">
</a> </a>
<a href="https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/" target="_blank"> <a href="https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/" target="_blank">
<img src="https://linuxone.cloud.marist.edu/oss/resources/images/linuxonelogo03.png" alt="ibm"> <img src="https://linuxone.cloud.marist.edu/oss/resources/images/linuxonelogo03.png" alt="ibm" style="height: 50px;">
</a>
<a href="https://console.zmto.com/?affid=1524" target="_blank">
<img src="https://console.zmto.com/templates/2019/dist/images/logo_dark.svg" alt="zmto" style="height: 50px;">
</a> </a>
## Stargazers over time ## Stargazers over time
[![Stargazers over time](https://starchart.cc/oneclickvirt/ecs.svg?variant=adaptive)](https://www.spiritlhl.net) [![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

@@ -368,7 +368,7 @@ Thank [he.net](https://he.net) [bgp.tools](https://bgp.tools) [ipinfo.io](https:
Thank Thank
<a href="https://h501.io/?from=69" target="_blank"> <a href="https://h501.io/?from=69" target="_blank">
<img src="https://github.com/spiritLHLS/ecs/assets/103393591/dfd47230-2747-4112-be69-b5636b34f07f" alt="h501"> <img src="https://github.com/spiritLHLS/ecs/assets/103393591/dfd47230-2747-4112-be69-b5636b34f07f" alt="h501" style="height: 50px;">
</a> </a>
provided free hosting support for this open source project's shared test results storage provided free hosting support for this open source project's shared test results storage
@@ -376,11 +376,15 @@ provided free hosting support for this open source project's shared test results
Thanks also to the following platforms for editorial and testing support Thanks also to the following platforms for editorial and testing support
<a href="https://www.jetbrains.com/go/" target="_blank"> <a href="https://www.jetbrains.com/go/" target="_blank">
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland"> <img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland" style="height: 50px;">
</a> </a>
<a href="https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/" target="_blank"> <a href="https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/" target="_blank">
<img src="https://linuxone.cloud.marist.edu/oss/resources/images/linuxonelogo03.png" alt="ibm"> <img src="https://linuxone.cloud.marist.edu/oss/resources/images/linuxonelogo03.png" alt="ibm" style="height: 50px;">
</a>
<a href="https://console.zmto.com/?affid=1524" target="_blank">
<img src="https://console.zmto.com/templates/2019/dist/images/logo_dark.svg" alt="zmto" style="height: 50px;">
</a> </a>
## Stargazers over time ## Stargazers over time

View File

@@ -36,6 +36,6 @@ func DiskTest(language, testMethod, testPath string, isMultiCheck bool, autoChan
if !strings.Contains(res, "\n") && res != "" { if !strings.Contains(res, "\n") && res != "" {
res += "\n" res += "\n"
} }
fmt.Printf(res) fmt.Printf("%s", res)
//fmt.Println("--------------------------------------------------") //fmt.Println("--------------------------------------------------")
} }

View File

@@ -3,5 +3,5 @@ package disktest
import "testing" import "testing"
func TestDiskIoTest(t *testing.T) { func TestDiskIoTest(t *testing.T) {
DiskTest("zh", "sysbench", "", false) DiskTest("zh", "sysbench", "", false, false)
} }

6
go.mod
View File

@@ -8,8 +8,8 @@ require (
github.com/imroc/req/v3 v3.50.0 github.com/imroc/req/v3 v3.50.0
github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841 github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841
github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053 github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053
github.com/oneclickvirt/backtrace v0.0.5-20250517095024 github.com/oneclickvirt/backtrace v0.0.5-20250629024536
github.com/oneclickvirt/basics v0.0.13-20250628134234 github.com/oneclickvirt/basics v0.0.13-20250629023612
github.com/oneclickvirt/cputest v0.0.10-20250404151448 github.com/oneclickvirt/cputest v0.0.10-20250404151448
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 github.com/oneclickvirt/defaultset v0.0.2-20240624082446
github.com/oneclickvirt/disktest v0.0.8-20250425015826 github.com/oneclickvirt/disktest v0.0.8-20250425015826
@@ -18,7 +18,7 @@ require (
github.com/oneclickvirt/nt3 v0.0.5-20250416131047 github.com/oneclickvirt/nt3 v0.0.5-20250416131047
github.com/oneclickvirt/pingtest v0.0.7-20250413051539 github.com/oneclickvirt/pingtest v0.0.7-20250413051539
github.com/oneclickvirt/portchecker v0.0.3-20250329125750 github.com/oneclickvirt/portchecker v0.0.3-20250329125750
github.com/oneclickvirt/security v0.0.4-20250522031128 github.com/oneclickvirt/security v0.0.4-20250629033626
github.com/oneclickvirt/speedtest v0.0.9-20250521034111 github.com/oneclickvirt/speedtest v0.0.9-20250521034111
) )

12
go.sum
View File

@@ -101,10 +101,10 @@ github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841 h1:Zef93z9UiZQwRA
github.com/oneclickvirt/CommonMediaTests v0.0.4-20250329123841/go.mod h1:DAmFPRjFV5p9fEzUUSml5jJGn2f1NZJQCzTxITHDjc4= 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 h1:Ug8kySZR1weRUcsnGOv+f3HAl791AfkA7EWV3JmiMQA=
github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053/go.mod h1:yXWIZB6iLS88pEd9m4QJi1GENn+7I91zA72y5ONz2Oc= github.com/oneclickvirt/UnlockTests v0.0.27-20250628125053/go.mod h1:yXWIZB6iLS88pEd9m4QJi1GENn+7I91zA72y5ONz2Oc=
github.com/oneclickvirt/backtrace v0.0.5-20250517095024 h1:j912aga/17znOqMB2VAxWOQYa4GL6YMFBhv+6c7jkvA= github.com/oneclickvirt/backtrace v0.0.5-20250629024536 h1:caHCa0DHmbYWBFN1bqKxpvPnN0wOxDEqJv1VDvDdLWs=
github.com/oneclickvirt/backtrace v0.0.5-20250517095024/go.mod h1:5AH00bo41hH3d2/JVuCTlBkZUs3AXX4nlKVXb6piZcI= github.com/oneclickvirt/backtrace v0.0.5-20250629024536/go.mod h1:5AH00bo41hH3d2/JVuCTlBkZUs3AXX4nlKVXb6piZcI=
github.com/oneclickvirt/basics v0.0.13-20250628134234 h1:ykbtiheQsN/lPc6z4X6oMYco4ZpDwQZ7z98jWnKi8oU= github.com/oneclickvirt/basics v0.0.13-20250629023612 h1:cQg+cGBt2NMRrjhJPH+CbevZrwtMU8pIZIY2Lp6zmt4=
github.com/oneclickvirt/basics v0.0.13-20250628134234/go.mod h1:yN1IEOXN6v/GJqJSA70Pooo6nXBI/6rq72vTY72wJMQ= github.com/oneclickvirt/basics v0.0.13-20250629023612/go.mod h1:yN1IEOXN6v/GJqJSA70Pooo6nXBI/6rq72vTY72wJMQ=
github.com/oneclickvirt/cputest v0.0.10-20250404151448 h1:ovGtCwFXG0qmpyNDRqcNDIiAmhrtemCjIUXTJ1fPH0o= github.com/oneclickvirt/cputest v0.0.10-20250404151448 h1:ovGtCwFXG0qmpyNDRqcNDIiAmhrtemCjIUXTJ1fPH0o=
github.com/oneclickvirt/cputest v0.0.10-20250404151448/go.mod h1:MmaHN9+XMntI3rLycwj8Ne31fG18IfNoa8N2utDK1CY= github.com/oneclickvirt/cputest v0.0.10-20250404151448/go.mod h1:MmaHN9+XMntI3rLycwj8Ne31fG18IfNoa8N2utDK1CY=
github.com/oneclickvirt/dd v0.0.1-20250406062523 h1:jegTww4fuoFEqwFozvGJEqUNI/5ew3QJ0XcKZZ/zuTs= github.com/oneclickvirt/dd v0.0.1-20250406062523 h1:jegTww4fuoFEqwFozvGJEqUNI/5ew3QJ0XcKZZ/zuTs=
@@ -125,8 +125,8 @@ github.com/oneclickvirt/pingtest v0.0.7-20250413051539 h1:mYOsEmMtwKr40hwM2NimVL
github.com/oneclickvirt/pingtest v0.0.7-20250413051539/go.mod h1:d3Ntx5m9lMll3a/k3+2B+5emj//vgDh4/NHTxs2qQE8= github.com/oneclickvirt/pingtest v0.0.7-20250413051539/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 h1:TTNL0pnQlRsn046kW59I/9UWRpihttFHWnU7Ixycggk=
github.com/oneclickvirt/portchecker v0.0.3-20250329125750/go.mod h1:HQxSTrqM8/QFqHMTBZ7S8H9eEO5FkUXU1eb7ZX5Mk+k= github.com/oneclickvirt/portchecker v0.0.3-20250329125750/go.mod h1:HQxSTrqM8/QFqHMTBZ7S8H9eEO5FkUXU1eb7ZX5Mk+k=
github.com/oneclickvirt/security v0.0.4-20250522031128 h1:k/zpiES/W0lW6Rumlmo4i7zp2ncimfeOUKadrylde8M= github.com/oneclickvirt/security v0.0.4-20250629033626 h1:DEchQ7WKKz4CzQpMlweoqA993BGncvmp1rL1ICNDJ2g=
github.com/oneclickvirt/security v0.0.4-20250522031128/go.mod h1:hdCr9UFkJ0tQfFP4mIycZehF5v7VfzSQwNn2qkY0bGo= github.com/oneclickvirt/security v0.0.4-20250629033626/go.mod h1:/5eVnZLvP7RUjwhoI6d8iIMP7msbkHC5So3ZxM+A7Zg=
github.com/oneclickvirt/speedtest v0.0.9-20250521034111 h1:yygDk+s5qFhPMDRzdMfyopm1xU512peNqY6WYyvYcfY= github.com/oneclickvirt/speedtest v0.0.9-20250521034111 h1:yygDk+s5qFhPMDRzdMfyopm1xU512peNqY6WYyvYcfY=
github.com/oneclickvirt/speedtest v0.0.9-20250521034111/go.mod h1:zd5ZgIGslmtQLQehEfRjyumlvgDHTpCSMchKfKXoASI= github.com/oneclickvirt/speedtest v0.0.9-20250521034111/go.mod h1:zd5ZgIGslmtQLQehEfRjyumlvgDHTpCSMchKfKXoASI=
github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=

565
goecs.go
View File

@@ -5,9 +5,19 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"net/http"
"os"
"os/signal"
"regexp"
"runtime"
"strings"
"sync"
"syscall"
"time"
"github.com/oneclickvirt/CommonMediaTests/commediatests" "github.com/oneclickvirt/CommonMediaTests/commediatests"
unlocktestmodel "github.com/oneclickvirt/UnlockTests/model" unlocktestmodel "github.com/oneclickvirt/UnlockTests/model"
"github.com/oneclickvirt/backtrace/bk" backtrace "github.com/oneclickvirt/backtrace/bk"
backtracemodel "github.com/oneclickvirt/backtrace/model" backtracemodel "github.com/oneclickvirt/backtrace/model"
basicmodel "github.com/oneclickvirt/basics/model" basicmodel "github.com/oneclickvirt/basics/model"
cputestmodel "github.com/oneclickvirt/cputest/model" cputestmodel "github.com/oneclickvirt/cputest/model"
@@ -26,19 +36,10 @@ import (
"github.com/oneclickvirt/pingtest/pt" "github.com/oneclickvirt/pingtest/pt"
"github.com/oneclickvirt/portchecker/email" "github.com/oneclickvirt/portchecker/email"
speedtestmodel "github.com/oneclickvirt/speedtest/model" speedtestmodel "github.com/oneclickvirt/speedtest/model"
"net/http"
"os"
"os/signal"
"regexp"
"runtime"
"strings"
"sync"
"syscall"
"time"
) )
var ( var (
ecsVersion = "v0.1.37" ecsVersion = "v0.1.38"
menuMode bool menuMode bool
onlyChinaTest bool onlyChinaTest bool
input, choice string input, choice string
@@ -79,7 +80,6 @@ func getMenuChoice(language string) string {
return return
} }
}() }()
for { for {
go func() { go func() {
var input string var input string
@@ -95,7 +95,7 @@ func getMenuChoice(language string) string {
}() }()
select { select {
case input := <-inputChan: case input := <-inputChan:
re := regexp.MustCompile(`^\d+$`) // 正则表达式匹配纯数字 re := regexp.MustCompile(`^\d+$`)
if re.MatchString(input) { if re.MatchString(input) {
inChoice := input inChoice := input
switch inChoice { switch inChoice {
@@ -121,7 +121,7 @@ func getMenuChoice(language string) string {
} }
} }
func main() { func parseFlags() {
goecsFlag.BoolVar(&help, "h", false, "Show help information") goecsFlag.BoolVar(&help, "h", false, "Show help information")
goecsFlag.BoolVar(&showVersion, "v", false, "Display version information") goecsFlag.BoolVar(&showVersion, "v", false, "Display version information")
goecsFlag.BoolVar(&menuMode, "menu", true, "Enable/Disable menu mode, disable example: -menu=false") // true 默认启用菜单栏模式 goecsFlag.BoolVar(&menuMode, "menu", true, "Enable/Disable menu mode, disable example: -menu=false") // true 默认启用菜单栏模式
@@ -149,15 +149,22 @@ func main() {
goecsFlag.BoolVar(&enableLogger, "log", false, "Enable/Disable logging in the current path") goecsFlag.BoolVar(&enableLogger, "log", false, "Enable/Disable logging in the current path")
goecsFlag.BoolVar(&enabelUpload, "upload", true, "Enable/Disable upload the result") goecsFlag.BoolVar(&enabelUpload, "upload", true, "Enable/Disable upload the result")
goecsFlag.Parse(os.Args[1:]) goecsFlag.Parse(os.Args[1:])
}
func handleHelpAndVersion() bool {
if help { if help {
fmt.Printf("Usage: %s [options]\n", os.Args[0]) fmt.Printf("Usage: %s [options]\n", os.Args[0])
goecsFlag.PrintDefaults() goecsFlag.PrintDefaults()
return return true
} }
if showVersion { if showVersion {
fmt.Println(ecsVersion) fmt.Println(ecsVersion)
return return true
} }
return false
}
func initLogger() {
if enableLogger { if enableLogger {
gostunmodel.EnableLoger = true gostunmodel.EnableLoger = true
basicmodel.EnableLoger = true basicmodel.EnableLoger = true
@@ -171,14 +178,72 @@ func main() {
nt3model.EnableLoger = true nt3model.EnableLoger = true
speedtestmodel.EnableLoger = true speedtestmodel.EnableLoger = true
} }
go func() { }
http.Get("https://hits.spiritlhl.net/goecs.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
}() func handleMenuMode(preCheck utils.NetCheckResult) {
if menuMode {
basicStatus, cpuTestStatus, memoryTestStatus, diskTestStatus = false, false, false, false basicStatus, cpuTestStatus, memoryTestStatus, diskTestStatus = false, false, false, false
commTestStatus, utTestStatus, securityTestStatus, emailTestStatus = false, false, false, false commTestStatus, utTestStatus, securityTestStatus, emailTestStatus = false, false, false, false
backtraceStatus, nt3Status, speedTestStatus = false, false, false backtraceStatus, nt3Status, speedTestStatus = false, false, false
autoChangeDiskTestMethod = true autoChangeDiskTestMethod = true
printMenuOptions()
Loop:
for {
choice = getMenuChoice(language)
switch choice {
case "1":
setFullTestStatus(preCheck)
onlyChinaTest = utils.CheckChina(enableLogger)
break Loop
case "2":
setMinimalTestStatus(preCheck)
break Loop
case "3":
setStandardTestStatus(preCheck)
break Loop
case "4":
setNetworkFocusedTestStatus(preCheck)
break Loop
case "5":
setUnlockFocusedTestStatus(preCheck)
break Loop
case "6":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
setNetworkOnlyTestStatus()
break Loop
case "7":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
setUnlockOnlyTestStatus()
break Loop
case "8":
setHardwareOnlyTestStatus(preCheck)
break Loop
case "9":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
setIPQualityTestStatus()
break Loop
case "10":
if !preCheck.Connected {
fmt.Println("Can not test without network connection!")
return
}
setRouteTestStatus()
break Loop
default:
printInvalidChoice()
}
}
}
func printMenuOptions() {
switch language { switch language {
case "zh": case "zh":
fmt.Println("VPS融合怪版本: ", ecsVersion) fmt.Println("VPS融合怪版本: ", ecsVersion)
@@ -204,15 +269,14 @@ func main() {
fmt.Println("8. Hardware-Only Test (System Info + CPU + Memory + dd Disk Test + fio Disk Test)") 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("9. IP Quality Test (IP Test with 15 Databases + Email Port Test)")
} }
Loop: }
for {
choice = getMenuChoice(language) func setFullTestStatus(preCheck utils.NetCheckResult) {
switch choice {
case "1":
basicStatus = true basicStatus = true
cpuTestStatus = true cpuTestStatus = true
memoryTestStatus = true memoryTestStatus = true
diskTestStatus = true diskTestStatus = true
if preCheck.Connected {
commTestStatus = true commTestStatus = true
utTestStatus = true utTestStatus = true
securityTestStatus = true securityTestStatus = true
@@ -220,80 +284,100 @@ func main() {
backtraceStatus = true backtraceStatus = true
nt3Status = true nt3Status = true
speedTestStatus = true speedTestStatus = true
onlyChinaTest = utils.CheckChina(enableLogger) }
break Loop }
case "2":
func setMinimalTestStatus(preCheck utils.NetCheckResult) {
basicStatus = true basicStatus = true
cpuTestStatus = true cpuTestStatus = true
memoryTestStatus = true memoryTestStatus = true
diskTestStatus = true diskTestStatus = true
if preCheck.Connected {
speedTestStatus = true speedTestStatus = true
break Loop }
case "3": }
func setStandardTestStatus(preCheck utils.NetCheckResult) {
basicStatus = true basicStatus = true
cpuTestStatus = true cpuTestStatus = true
memoryTestStatus = true memoryTestStatus = true
diskTestStatus = true diskTestStatus = true
if preCheck.Connected {
utTestStatus = true utTestStatus = true
nt3Status = true nt3Status = true
speedTestStatus = true speedTestStatus = true
break Loop }
case "4": }
func setNetworkFocusedTestStatus(preCheck utils.NetCheckResult) {
basicStatus = true basicStatus = true
cpuTestStatus = true cpuTestStatus = true
memoryTestStatus = true memoryTestStatus = true
diskTestStatus = true diskTestStatus = true
if preCheck.Connected {
backtraceStatus = true backtraceStatus = true
nt3Status = true nt3Status = true
speedTestStatus = true speedTestStatus = true
break Loop }
case "5": }
func setUnlockFocusedTestStatus(preCheck utils.NetCheckResult) {
basicStatus = true basicStatus = true
cpuTestStatus = true cpuTestStatus = true
memoryTestStatus = true memoryTestStatus = true
diskTestStatus = true diskTestStatus = true
if preCheck.Connected {
commTestStatus = true commTestStatus = true
utTestStatus = true utTestStatus = true
speedTestStatus = true speedTestStatus = true
break Loop }
case "6": }
func setNetworkOnlyTestStatus() {
securityTestStatus = true securityTestStatus = true
speedTestStatus = true speedTestStatus = true
backtraceStatus = true backtraceStatus = true
nt3Status = true nt3Status = true
break Loop }
case "7":
func setUnlockOnlyTestStatus() {
commTestStatus = true commTestStatus = true
utTestStatus = true utTestStatus = true
enabelUpload = false enabelUpload = false
break Loop }
case "8":
func setHardwareOnlyTestStatus(preCheck utils.NetCheckResult) {
basicStatus = true basicStatus = true
cpuTestStatus = true cpuTestStatus = true
memoryTestStatus = true memoryTestStatus = true
diskTestStatus = true diskTestStatus = true
if preCheck.Connected {
securityTestStatus = false securityTestStatus = false
autoChangeDiskTestMethod = false autoChangeDiskTestMethod = false
break Loop }
case "9": }
func setIPQualityTestStatus() {
securityTestStatus = true securityTestStatus = true
emailTestStatus = true emailTestStatus = true
break Loop }
case "10":
func setRouteTestStatus() {
backtraceStatus = true backtraceStatus = true
nt3Status = true nt3Status = true
pingTestStatus = true pingTestStatus = true
enabelUpload = false enabelUpload = false
break Loop }
default:
func printInvalidChoice() {
if language == "zh" { if language == "zh" {
fmt.Println("无效的选项") fmt.Println("无效的选项")
} else { } else {
fmt.Println("Invalid choice") fmt.Println("Invalid choice")
} }
} }
}
} func handleLanguageSpecificSettings() {
if language == "en" { if language == "en" {
backtraceStatus = false backtraceStatus = false
nt3Status = false nt3Status = false
@@ -301,51 +385,39 @@ func main() {
if !enabelUpload { if !enabelUpload {
securityTestStatus = false securityTestStatus = false
} }
var ( }
startTime time.Time
wg1, wg2, wg3 sync.WaitGroup func handleSignalInterrupt(sig chan os.Signal, startTime *time.Time, output *string, tempOutput string, uploadDone chan bool) {
basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo string *startTime = time.Now()
output, tempOutput string
)
// 信号处理部分
uploadDone := make(chan bool, 1)
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
// 启动一个goroutine来等待信号
go func() {
startTime = time.Now()
select { select {
case <-sig: case <-sig:
if !finish { if !finish {
endTime := time.Now() endTime := time.Now()
duration := endTime.Sub(startTime) duration := endTime.Sub(*startTime)
minutes := int(duration.Minutes()) minutes := int(duration.Minutes())
seconds := int(duration.Seconds()) % 60 seconds := int(duration.Seconds()) % 60
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
var mu sync.Mutex var mu sync.Mutex
mu.Lock() mu.Lock()
output = utils.PrintAndCapture(func() { *output = utils.PrintAndCapture(func() {
utils.PrintCenteredTitle("", width) utils.PrintCenteredTitle("", width)
fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds) fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds)
fmt.Printf("Current Time : %s\n", currentTime) fmt.Printf("Current Time : %s\n", currentTime)
utils.PrintCenteredTitle("", width) utils.PrintCenteredTitle("", width)
}, tempOutput, output) }, tempOutput, *output)
mu.Unlock() mu.Unlock()
// 创建一个通道来传递上传结果
resultChan := make(chan struct { resultChan := make(chan struct {
httpURL string httpURL string
httpsURL string httpsURL string
}, 1) // 使用带缓冲的通道,避免可能的阻塞 }, 1)
// 启动上传
go func() { go func() {
httpURL, httpsURL := utils.ProcessAndUpload(output, filePath, enabelUpload) httpURL, httpsURL := utils.ProcessAndUpload(*output, filePath, enabelUpload)
resultChan <- struct { resultChan <- struct {
httpURL string httpURL string
httpsURL string httpsURL string
}{httpURL, httpsURL} }{httpURL, httpsURL}
uploadDone <- true uploadDone <- true
}() }()
// 等待上传完成或超时
select { select {
case result := <-resultChan: case result := <-resultChan:
if result.httpURL != "" || result.httpsURL != "" { if result.httpURL != "" || result.httpsURL != "" {
@@ -355,7 +427,6 @@ func main() {
fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL) fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL)
} }
} }
// 给打印操作一些时间完成
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
fmt.Println("Press Enter to exit...") fmt.Println("Press Enter to exit...")
@@ -373,20 +444,101 @@ func main() {
} }
os.Exit(0) os.Exit(0)
} }
}
func runChineseTests(preCheck utils.NetCheckResult, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output, tempOutput string, startTime time.Time) string {
output = runBasicTests(preCheck, basicInfo, securityInfo, output, tempOutput)
output = runCPUTest(output, tempOutput)
output = runMemoryTest(output, tempOutput)
output = runDiskTest(output, tempOutput)
if (onlyChinaTest || pingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
wg3.Add(1)
go func() {
defer wg3.Done()
*ptInfo = pt.PingTest()
}() }()
switch language { }
case "zh": if emailTestStatus {
output = utils.PrintAndCapture(func() { wg2.Add(1)
go func() {
defer wg2.Done()
*emailInfo = email.EmailCheck()
}()
}
if utTestStatus && !onlyChinaTest {
wg1.Add(1)
go func() {
defer wg1.Done()
*mediaInfo = unlocktest.MediaTest(language)
}()
}
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
output = runStreamingTests(wg1, *mediaInfo, output, tempOutput)
output = runSecurityTests(*securityInfo, output, tempOutput)
output = runEmailTests(wg2, *emailInfo, output, tempOutput)
}
if runtime.GOOS != "windows" && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
output = runNetworkTests(wg3, *ptInfo, output, tempOutput)
}
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
output = runSpeedTests(output, tempOutput)
}
return appendTimeInfo(output, tempOutput, startTime)
}
func runEnglishTests(preCheck utils.NetCheckResult, wg1, wg2 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo *string, output, tempOutput string, startTime time.Time) string {
output = runBasicTests(preCheck, basicInfo, securityInfo, output, tempOutput)
output = runCPUTest(output, tempOutput)
output = runMemoryTest(output, tempOutput)
output = runDiskTest(output, tempOutput)
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
if utTestStatus {
wg1.Add(1)
go func() {
defer wg1.Done()
*mediaInfo = unlocktest.MediaTest(language)
}()
}
if emailTestStatus {
wg2.Add(1)
go func() {
defer wg2.Done()
*emailInfo = email.EmailCheck()
}()
}
output = runStreamingTests(wg1, *mediaInfo, output, tempOutput)
output = runSecurityTests(*securityInfo, output, tempOutput)
output = runEmailTests(wg2, *emailInfo, output, tempOutput)
output = runEnglishSpeedTests(output, tempOutput)
}
return appendTimeInfo(output, tempOutput, startTime)
}
func runBasicTests(preCheck utils.NetCheckResult, basicInfo, securityInfo *string, output, tempOutput string) string {
return utils.PrintAndCapture(func() {
utils.PrintHead(language, width, ecsVersion) utils.PrintHead(language, width, ecsVersion)
if basicStatus || securityTestStatus { if basicStatus || securityTestStatus {
if basicStatus { if basicStatus {
if language == "zh" {
utils.PrintCenteredTitle("系统基础信息", width) utils.PrintCenteredTitle("系统基础信息", width)
} else {
utils.PrintCenteredTitle("System-Basic-Information", width)
}
}
if preCheck.Connected && preCheck.StackType == "DualStack" {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, nt3CheckType, securityTestStatus)
} else if preCheck.Connected && preCheck.StackType == "IPv4" {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv4", securityTestStatus)
} else if preCheck.Connected && preCheck.StackType == "IPv6" {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "ipv6", securityTestStatus)
} else {
*basicInfo, *securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, "", false)
securityTestStatus = false
} }
basicInfo, securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, nt3CheckType, securityTestStatus)
if basicStatus { if basicStatus {
fmt.Printf(basicInfo) fmt.Printf("%s", *basicInfo)
} else if (input == "6" || input == "9") && securityTestStatus { } else if (input == "6" || input == "9") && securityTestStatus {
scanner := bufio.NewScanner(strings.NewReader(basicInfo)) scanner := bufio.NewScanner(strings.NewReader(*basicInfo))
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
if strings.Contains(line, "IPV") { if strings.Contains(line, "IPV") {
@@ -396,77 +548,107 @@ func main() {
} }
} }
}, tempOutput, output) }, tempOutput, output)
output = utils.PrintAndCapture(func() { }
func runCPUTest(output, tempOutput string) string {
return utils.PrintAndCapture(func() {
if cpuTestStatus { if cpuTestStatus {
if language == "zh" {
utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", cpuTestMethod), width) utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", cpuTestMethod), width)
} else {
utils.PrintCenteredTitle(fmt.Sprintf("CPU-Test--%s-Method", cpuTestMethod), width)
}
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode) cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
} }
}, tempOutput, output) }, tempOutput, output)
output = utils.PrintAndCapture(func() { }
func runMemoryTest(output, tempOutput string) string {
return utils.PrintAndCapture(func() {
if memoryTestStatus { if memoryTestStatus {
if language == "zh" {
utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", memoryTestMethod), width) utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", memoryTestMethod), width)
} else {
utils.PrintCenteredTitle(fmt.Sprintf("Memory-Test--%s-Method", memoryTestMethod), width)
}
memorytest.MemoryTest(language, memoryTestMethod) memorytest.MemoryTest(language, memoryTestMethod)
} }
}, tempOutput, output) }, tempOutput, output)
output = utils.PrintAndCapture(func() { }
func runDiskTest(output, tempOutput string) string {
return utils.PrintAndCapture(func() {
if diskTestStatus && autoChangeDiskTestMethod { if diskTestStatus && autoChangeDiskTestMethod {
if language == "zh" {
utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", diskTestMethod), width) utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", diskTestMethod), width)
} else {
utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", diskTestMethod), width)
}
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
} else if diskTestStatus && !autoChangeDiskTestMethod { } else if diskTestStatus && !autoChangeDiskTestMethod {
if language == "zh" {
utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "dd"), width) utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "dd"), width)
disktest.DiskTest(language, "dd", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) disktest.DiskTest(language, "dd", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "fio"), width) utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", "fio"), width)
disktest.DiskTest(language, "fio", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod) disktest.DiskTest(language, "fio", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
} else {
utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "dd"), width)
disktest.DiskTest(language, "dd", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "fio"), width)
disktest.DiskTest(language, "fio", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
}
} }
}, tempOutput, output) }, tempOutput, output)
if onlyChinaTest || pingTestStatus { }
wg3.Add(1)
go func() { func runStreamingTests(wg1 *sync.WaitGroup, mediaInfo string, output, tempOutput string) string {
defer wg3.Done() return utils.PrintAndCapture(func() {
ptInfo = pt.PingTest() if language == "zh" {
}()
}
if emailTestStatus {
wg2.Add(1)
go func() {
defer wg2.Done()
emailInfo = email.EmailCheck()
}()
}
if utTestStatus && !onlyChinaTest {
wg1.Add(1)
go func() {
defer wg1.Done()
mediaInfo = unlocktest.MediaTest(language)
}()
}
output = utils.PrintAndCapture(func() {
if commTestStatus && !onlyChinaTest { if commTestStatus && !onlyChinaTest {
utils.PrintCenteredTitle("御三家流媒体解锁", width) utils.PrintCenteredTitle("御三家流媒体解锁", width)
fmt.Printf(commediatests.MediaTests(language)) fmt.Printf("%s", commediatests.MediaTests(language))
} }
}, tempOutput, output) }
output = utils.PrintAndCapture(func() { if utTestStatus && (language == "zh" && !onlyChinaTest || language == "en") {
if utTestStatus && !onlyChinaTest { if language == "zh" {
utils.PrintCenteredTitle("跨国流媒体解锁", width) utils.PrintCenteredTitle("跨国流媒体解锁", width)
} else {
utils.PrintCenteredTitle("Cross-Border-Streaming-Media-Unlock", width)
}
fmt.Printf("%s", mediaInfo)
}
wg1.Wait() wg1.Wait()
fmt.Printf(mediaInfo)
}
}, tempOutput, output) }, tempOutput, output)
output = utils.PrintAndCapture(func() { }
func runSecurityTests(securityInfo string, output, tempOutput string) string {
return utils.PrintAndCapture(func() {
if securityTestStatus { if securityTestStatus {
if language == "zh" {
utils.PrintCenteredTitle("IP质量检测", width) utils.PrintCenteredTitle("IP质量检测", width)
fmt.Printf(securityInfo) } else {
utils.PrintCenteredTitle("IP-Quality-Check", width)
}
fmt.Printf("%s", securityInfo)
} }
}, tempOutput, output) }, tempOutput, output)
output = utils.PrintAndCapture(func() { }
func runEmailTests(wg2 *sync.WaitGroup, emailInfo string, output, tempOutput string) string {
return utils.PrintAndCapture(func() {
if emailTestStatus { if emailTestStatus {
if language == "zh" {
utils.PrintCenteredTitle("邮件端口检测", width) utils.PrintCenteredTitle("邮件端口检测", width)
wg2.Wait() } else {
utils.PrintCenteredTitle("Email-Port-Check", width)
}
fmt.Println(emailInfo) fmt.Println(emailInfo)
} }
wg2.Wait()
}, tempOutput, output) }, tempOutput, output)
if runtime.GOOS != "windows" { }
func runNetworkTests(wg3 *sync.WaitGroup, ptInfo string, output, tempOutput string) string {
output = utils.PrintAndCapture(func() { output = utils.PrintAndCapture(func() {
if backtraceStatus && !onlyChinaTest { if backtraceStatus && !onlyChinaTest {
utils.PrintCenteredTitle("三网回程线路检测", width) utils.PrintCenteredTitle("三网回程线路检测", width)
@@ -477,22 +659,23 @@ func main() {
} }
} }
}, tempOutput, output) }, tempOutput, output)
// nexttrace 在win上不支持检测报错 bind: An invalid argument was supplied.
output = utils.PrintAndCapture(func() { output = utils.PrintAndCapture(func() {
if nt3Status && !onlyChinaTest { if nt3Status && !onlyChinaTest {
utils.PrintCenteredTitle("三网回程路由检测", width) utils.PrintCenteredTitle("三网回程路由检测", width)
nt.TraceRoute(language, nt3Location, nt3CheckType) nt.TraceRoute(language, nt3Location, nt3CheckType)
} }
}, tempOutput, output) }, tempOutput, output)
output = utils.PrintAndCapture(func() { return utils.PrintAndCapture(func() {
if onlyChinaTest || pingTestStatus { if onlyChinaTest || pingTestStatus {
utils.PrintCenteredTitle("三网ICMP的PING值检测", width) utils.PrintCenteredTitle("三网ICMP的PING值检测", width)
wg3.Wait()
fmt.Println(ptInfo) fmt.Println(ptInfo)
} }
wg3.Wait()
}, tempOutput, output) }, tempOutput, output)
} }
output = utils.PrintAndCapture(func() {
func runSpeedTests(output, tempOutput string) string {
return utils.PrintAndCapture(func() {
if speedTestStatus { if speedTestStatus {
utils.PrintCenteredTitle("就近节点测速", width) utils.PrintCenteredTitle("就近节点测速", width)
speedtest.ShowHead(language) speedtest.ShowHead(language)
@@ -509,96 +692,10 @@ func main() {
} }
} }
}, tempOutput, output) }, tempOutput, output)
endTime := time.Now() }
duration := endTime.Sub(startTime)
minutes := int(duration.Minutes()) func runEnglishSpeedTests(output, tempOutput string) string {
seconds := int(duration.Seconds()) % 60 return utils.PrintAndCapture(func() {
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
output = utils.PrintAndCapture(func() {
utils.PrintCenteredTitle("", width)
fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds)
fmt.Printf("时间 : %s\n", currentTime)
utils.PrintCenteredTitle("", width)
}, tempOutput, output)
case "en":
output = utils.PrintAndCapture(func() {
utils.PrintHead(language, width, ecsVersion)
if basicStatus || securityTestStatus {
if basicStatus {
utils.PrintCenteredTitle("System-Basic-Information", width)
}
basicInfo, securityInfo, nt3CheckType = utils.BasicsAndSecurityCheck(language, nt3CheckType, securityTestStatus)
if basicStatus {
fmt.Printf(basicInfo)
} else if (input == "6" || input == "9") && securityTestStatus {
scanner := bufio.NewScanner(strings.NewReader(basicInfo))
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "IPV") {
fmt.Println(line)
}
}
}
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if cpuTestStatus {
utils.PrintCenteredTitle(fmt.Sprintf("CPU-Test--%s-Method", cpuTestMethod), width)
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if memoryTestStatus {
utils.PrintCenteredTitle(fmt.Sprintf("Memory-Test--%s-Method", memoryTestMethod), width)
memorytest.MemoryTest(language, memoryTestMethod)
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if diskTestStatus && autoChangeDiskTestMethod {
utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", diskTestMethod), width)
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
} else if diskTestStatus && !autoChangeDiskTestMethod {
utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "dd"), width)
disktest.DiskTest(language, "dd", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
utils.PrintCenteredTitle(fmt.Sprintf("Disk-Test--%s-Method", "fio"), width)
disktest.DiskTest(language, "fio", diskTestPath, diskMultiCheck, autoChangeDiskTestMethod)
}
}, tempOutput, output)
if utTestStatus {
wg1.Add(1)
go func() {
defer wg1.Done()
mediaInfo = unlocktest.MediaTest(language)
}()
}
if emailTestStatus {
wg2.Add(1)
go func() {
defer wg2.Done()
emailInfo = email.EmailCheck()
}()
}
output = utils.PrintAndCapture(func() {
if utTestStatus {
utils.PrintCenteredTitle("Cross-Border-Streaming-Media-Unlock", width)
wg1.Wait()
fmt.Printf(mediaInfo)
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if securityTestStatus {
utils.PrintCenteredTitle("IP-Quality-Check", width)
fmt.Printf(securityInfo)
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if emailTestStatus {
utils.PrintCenteredTitle("Email-Port-Check", width)
wg2.Wait()
fmt.Println(emailInfo)
}
}, tempOutput, output)
output = utils.PrintAndCapture(func() {
if speedTestStatus { if speedTestStatus {
utils.PrintCenteredTitle("Speed-Test", width) utils.PrintCenteredTitle("Speed-Test", width)
speedtest.ShowHead(language) speedtest.ShowHead(language)
@@ -606,20 +703,28 @@ func main() {
speedtest.CustomSP("net", "global", -1, language) speedtest.CustomSP("net", "global", -1, language)
} }
}, tempOutput, output) }, tempOutput, output)
}
func appendTimeInfo(output, tempOutput string, startTime time.Time) string {
endTime := time.Now() endTime := time.Now()
duration := endTime.Sub(startTime) duration := endTime.Sub(startTime)
minutes := int(duration.Minutes()) minutes := int(duration.Minutes())
seconds := int(duration.Seconds()) % 60 seconds := int(duration.Seconds()) % 60
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
output = utils.PrintAndCapture(func() { return utils.PrintAndCapture(func() {
utils.PrintCenteredTitle("", width) utils.PrintCenteredTitle("", width)
if language == "zh" {
fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds)
fmt.Printf("时间 : %s\n", currentTime)
} else {
fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds) fmt.Printf("Cost Time : %d min %d sec\n", minutes, seconds)
fmt.Printf("Current Time : %s\n", currentTime) fmt.Printf("Current Time : %s\n", currentTime)
}
utils.PrintCenteredTitle("", width) utils.PrintCenteredTitle("", width)
}, tempOutput, output) }, tempOutput, output)
default: }
fmt.Println("Unsupported language")
} func handleUploadResults(output string) {
httpURL, httpsURL := utils.ProcessAndUpload(output, filePath, enabelUpload) httpURL, httpsURL := utils.ProcessAndUpload(output, filePath, enabelUpload)
if httpURL != "" || httpsURL != "" { if httpURL != "" || httpsURL != "" {
if language == "en" { if language == "en" {
@@ -628,6 +733,42 @@ func main() {
fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL) fmt.Printf("上传成功!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL)
} }
} }
}
func main() {
parseFlags()
if handleHelpAndVersion() {
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)
if menuMode {
handleMenuMode(preCheck)
}
handleLanguageSpecificSettings()
var (
startTime time.Time
wg1, wg2, wg3 sync.WaitGroup
basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo string
output, tempOutput string
)
uploadDone := make(chan bool, 1)
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go handleSignalInterrupt(sig, &startTime, &output, tempOutput, uploadDone)
startTime = time.Now()
switch language {
case "zh":
output = runChineseTests(preCheck, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, output, tempOutput, startTime)
case "en":
output = runEnglishTests(preCheck, &wg1, &wg2, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, output, tempOutput, startTime)
default:
fmt.Println("Unsupported language")
}
handleUploadResults(output)
finish = true finish = true
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
fmt.Println("Press Enter to exit...") fmt.Println("Press Enter to exit...")

View File

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

View File

@@ -31,5 +31,5 @@ func MemoryTest(language, testMethod string) {
if !strings.Contains(res, "\n") && res != "" { if !strings.Contains(res, "\n") && res != "" {
res += "\n" res += "\n"
} }
fmt.Printf(res) fmt.Printf("%s", res)
} }

View File

@@ -6,5 +6,5 @@ import (
) )
func Test(t *testing.T) { func Test(t *testing.T) {
fmt.Printf(MediaTest("zh")) fmt.Printf("%s", MediaTest("zh"))
} }

View File

@@ -3,13 +3,11 @@ package utils
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"context"
"fmt" "fmt"
"github.com/imroc/req/v3"
"github.com/oneclickvirt/UnlockTests/uts"
"github.com/oneclickvirt/basics/system"
. "github.com/oneclickvirt/defaultset"
"github.com/oneclickvirt/security/network"
"io" "io"
"net"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@@ -17,6 +15,12 @@ import (
"sync" "sync"
"time" "time"
"unicode/utf8" "unicode/utf8"
"github.com/imroc/req/v3"
"github.com/oneclickvirt/UnlockTests/uts"
"github.com/oneclickvirt/basics/system"
. "github.com/oneclickvirt/defaultset"
"github.com/oneclickvirt/security/network"
) )
// PrintCenteredTitle 根据指定的宽度打印居中标题 // PrintCenteredTitle 根据指定的宽度打印居中标题
@@ -95,14 +99,14 @@ func CheckChina(enableLogger bool) bool {
} }
// BasicsAndSecurityCheck 执行安全检查 // BasicsAndSecurityCheck 执行安全检查
func BasicsAndSecurityCheck(language, nt3CheckType string, securtyCheckStatus bool) (string, string, string) { func BasicsAndSecurityCheck(language, nt3CheckType string, securityCheckStatus bool) (string, string, string) {
var wgt sync.WaitGroup var wgt sync.WaitGroup
var ipInfo, securityInfo, systemInfo string var ipInfo, securityInfo, systemInfo string
var err error var err error
wgt.Add(1) wgt.Add(1)
go func() { go func() {
defer wgt.Done() defer wgt.Done()
ipInfo, securityInfo, err = network.NetworkCheck("both", securtyCheckStatus, language) ipInfo, securityInfo, err = network.NetworkCheck("both", securityCheckStatus, language)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
@@ -330,3 +334,159 @@ func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string
} }
return "", "" return "", ""
} }
// ============================= 前置联网能力检测 =============================
var StackType string
type NetCheckResult struct {
HasIPv4 bool
HasIPv6 bool
Connected bool
StackType string // "IPv4", "IPv6", "DualStack", "None"
}
func makeResolver(proto, dnsAddr string) *net.Resolver {
return &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: 5 * time.Second,
}
return d.DialContext(ctx, proto, dnsAddr)
},
}
}
func CheckPublicAccess(timeout time.Duration) NetCheckResult {
if timeout < 2*time.Second {
timeout = 2 * time.Second
}
var wg sync.WaitGroup
resultChan := make(chan string, 8)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
checks := []struct {
Tag string
Addr string
Kind string // udp4, udp6, http4, http6
}{
// UDP DNS
{"IPv4", "223.5.5.5:53", "udp4"}, // 阿里 DNS
{"IPv4", "8.8.8.8:53", "udp4"}, // Google DNS
{"IPv6", "[2400:3200::1]:53", "udp6"}, // 阿里 IPv6 DNS
{"IPv6", "[2001:4860:4860::8888]:53", "udp6"}, // Google IPv6 DNS
// HTTP HEAD
{"IPv4", "https://www.baidu.com", "http4"}, // 百度
{"IPv4", "https://1.1.1.1", "http4"}, // Cloudflare
{"IPv6", "https://[2400:3200::1]", "http6"}, // 阿里 IPv6
{"IPv6", "https://[2606:4700::1111]", "http6"}, // Cloudflare IPv6
}
for _, check := range checks {
wg.Add(1)
go func(tag, addr, kind string) {
defer wg.Done()
defer func() {
if r := recover(); r != nil {
}
}()
switch kind {
case "udp4", "udp6":
dialer := &net.Dialer{
Timeout: timeout / 4,
}
conn, err := dialer.DialContext(ctx, kind, addr)
if err == nil && conn != nil {
conn.Close()
select {
case resultChan <- tag:
case <-ctx.Done():
return
}
}
case "http4", "http6":
var resolver *net.Resolver
if kind == "http4" {
resolver = makeResolver("udp4", "223.5.5.5:53")
} else {
resolver = makeResolver("udp6", "[2400:3200::1]:53")
}
dialer := &net.Dialer{
Timeout: timeout / 4,
Resolver: resolver,
}
transport := &http.Transport{
DialContext: dialer.DialContext,
MaxIdleConns: 1,
MaxIdleConnsPerHost: 1,
IdleConnTimeout: time.Second,
TLSHandshakeTimeout: timeout / 4,
ResponseHeaderTimeout: timeout / 4,
DisableKeepAlives: true,
}
client := &http.Client{
Timeout: timeout / 4,
Transport: transport,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
req, err := http.NewRequestWithContext(ctx, "HEAD", addr, nil)
if err != nil {
return
}
resp, err := client.Do(req)
if err == nil && resp != nil {
if resp.Body != nil {
resp.Body.Close()
}
if resp.StatusCode < 500 {
select {
case resultChan <- tag:
case <-ctx.Done():
return
}
}
}
}
}(check.Tag, check.Addr, check.Kind)
}
go func() {
wg.Wait()
close(resultChan)
}()
hasV4 := false
hasV6 := false
for {
select {
case res, ok := <-resultChan:
if !ok {
goto result
}
if res == "IPv4" {
hasV4 = true
}
if res == "IPv6" {
hasV6 = true
}
case <-ctx.Done():
goto result
}
}
result:
stack := "None"
if hasV4 && hasV6 {
stack = "DualStack"
} else if hasV4 {
stack = "IPv4"
} else if hasV6 {
stack = "IPv6"
}
StackType = stack
return NetCheckResult{
HasIPv4: hasV4,
HasIPv6: hasV6,
Connected: hasV4 || hasV6,
StackType: stack,
}
}

17
utils/utils_test.go Normal file
View File

@@ -0,0 +1,17 @@
package utils
import (
"fmt"
"testing"
"time"
)
func TestCheckPublicAccess(t *testing.T) {
timeout := 3 * time.Second
result := CheckPublicAccess(timeout)
if result.Connected {
fmt.Printf("✅ 本机有公网连接,类型: %s\n", result.StackType)
} else {
fmt.Println("❌ 本机未检测到公网连接")
}
}