mirror of
http://bgp.hk.skcks.cn:10088/github.com/oneclickvirt/ecs
synced 2026-04-21 13:20:41 +08:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85a0b30950 | ||
|
|
21100fd949 | ||
|
|
d2878dd705 | ||
|
|
a80ce40739 | ||
|
|
a1b5691179 | ||
|
|
6cf35680d5 | ||
|
|
7b74cbe1e7 | ||
|
|
8137a7ac6a | ||
|
|
04725fef54 | ||
|
|
4e868a384a | ||
|
|
7a4885346b | ||
|
|
21b85b0176 | ||
|
|
8756224376 | ||
|
|
3a4b76ddcd | ||
|
|
a741e293b2 | ||
|
|
e3ca989aac | ||
|
|
0f06aa587d | ||
|
|
f7519a0307 | ||
|
|
6953182cb4 | ||
|
|
22c9eb7611 | ||
|
|
f4d6fe1a8a | ||
|
|
90f7b9a94b | ||
|
|
e5f8f87f7e | ||
|
|
0b87d169a3 | ||
|
|
b8fe9d3d98 | ||
|
|
8f46bd3f4f | ||
|
|
e8c4b2b4a7 | ||
|
|
8016a8fe93 | ||
|
|
bf0030dc49 | ||
|
|
6d02103aba | ||
|
|
5ffb48dcdc | ||
|
|
7c19502950 | ||
|
|
3c434781f5 | ||
|
|
f62636ca3e | ||
|
|
c4b11ae37d | ||
|
|
8f2fe236d5 | ||
|
|
347a0faa7a | ||
|
|
74640e3066 | ||
|
|
3b646eeeda | ||
|
|
eaad433395 |
@@ -233,8 +233,8 @@ def modify_readme(filepath, is_english=False):
|
||||
|
||||
# Update security status
|
||||
content = re.sub(
|
||||
r'but binary files compiled in \[securityCheck\][^\)]*\)',
|
||||
'but open sourced',
|
||||
r', binary files compiled in \[securityCheck\][^\)]*\)',
|
||||
', but open sourced',
|
||||
content
|
||||
)
|
||||
|
||||
@@ -254,7 +254,7 @@ def modify_readme(filepath, is_english=False):
|
||||
|
||||
# Update security status
|
||||
content = re.sub(
|
||||
r'但二进制文件编译至 \[securityCheck\][^\)]*\)',
|
||||
r'二进制文件编译至 \[securityCheck\][^\)]*\)',
|
||||
'但已开源',
|
||||
content
|
||||
)
|
||||
@@ -294,8 +294,8 @@ def main():
|
||||
|
||||
# Modify README files
|
||||
print("Modifying README files...")
|
||||
modify_readme('README.md', is_english=False)
|
||||
modify_readme('README_EN.md', is_english=True)
|
||||
modify_readme('README_ZH.md', is_english=False)
|
||||
modify_readme('README.md', is_english=True)
|
||||
print()
|
||||
|
||||
print("✓ All modifications completed successfully!")
|
||||
|
||||
4
.github/workflows/build_binary.yaml
vendored
4
.github/workflows/build_binary.yaml
vendored
@@ -40,6 +40,10 @@ jobs:
|
||||
with:
|
||||
go-version: 1.25.4
|
||||
|
||||
# - name: Install UPX
|
||||
# run: |
|
||||
# apk add --no-cache upx
|
||||
|
||||
- name: Configure Git for Private Modules
|
||||
run: |
|
||||
git config --global url."https://${{ secrets.GHT }}@github.com/".insteadOf "https://github.com/"
|
||||
|
||||
3
.github/workflows/build_public.yml
vendored
3
.github/workflows/build_public.yml
vendored
@@ -40,7 +40,8 @@ jobs:
|
||||
sed -i 's|security.*Enable/Disable security test (default true)|security Enable/Disable security test (default false)|g' README_EN.md
|
||||
echo "已更新 README_EN.md"
|
||||
fi
|
||||
git add README.md README_EN.md
|
||||
git add README.md
|
||||
[ -f "README_EN.md" ] && git add README_EN.md || true
|
||||
git commit -m "Auto update README files" || echo "No changes to commit"
|
||||
git push origin ${{ github.ref_name }}
|
||||
else
|
||||
|
||||
3
.github/workflows/sync.yaml
vendored
3
.github/workflows/sync.yaml
vendored
@@ -32,8 +32,9 @@ jobs:
|
||||
- name: Copy repository files
|
||||
run: |
|
||||
cp goecs.sh temp_repo/
|
||||
cp README_EN.md temp_repo/
|
||||
cp README.md temp_repo/
|
||||
[ -f "README_EN.md" ] && cp README_EN.md temp_repo/ || true
|
||||
[ -f "README_ZH.md" ] && cp README_ZH.md temp_repo/ || true
|
||||
cp LICENSE temp_repo/
|
||||
|
||||
- name: Download release assets
|
||||
|
||||
@@ -3,7 +3,6 @@ before:
|
||||
- go mod tidy -v
|
||||
- go clean -cache
|
||||
|
||||
# 添加并行构建限制以减少磁盘占用
|
||||
project_name: goecs
|
||||
|
||||
builds:
|
||||
@@ -36,6 +35,7 @@ builds:
|
||||
goarch: arm
|
||||
main: ./
|
||||
binary: goecs
|
||||
|
||||
- id: darwin-amd64
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
@@ -49,6 +49,7 @@ builds:
|
||||
- amd64
|
||||
main: ./
|
||||
binary: goecs
|
||||
|
||||
- id: darwin-arm64
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
@@ -62,18 +63,23 @@ builds:
|
||||
- arm64
|
||||
main: ./
|
||||
binary: goecs
|
||||
|
||||
universal_binaries:
|
||||
- name_template: "goecs"
|
||||
replace: false
|
||||
|
||||
checksum:
|
||||
name_template: "checksums.txt"
|
||||
|
||||
snapshot:
|
||||
name_template: "goecs"
|
||||
|
||||
archives:
|
||||
- name_template: "goecs_{{ .Os }}_{{ .Arch }}"
|
||||
format: zip
|
||||
files:
|
||||
- none*
|
||||
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
@@ -84,4 +90,18 @@ changelog:
|
||||
- Merge pull request
|
||||
- Merge branch
|
||||
- go mod tidy
|
||||
- New translations
|
||||
- New translations
|
||||
|
||||
upx:
|
||||
- enabled: true
|
||||
brute: true
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm64
|
||||
- ppc64le
|
||||
- s390x
|
||||
- riscv64
|
||||
|
||||
267
README.md
267
README.md
@@ -6,185 +6,184 @@
|
||||
|
||||
[](https://hits.spiritlhl.net) [](https://github.com/oneclickvirt/ecs/releases)
|
||||
|
||||
融合怪测评项目 - GO版本
|
||||
Fusion Monster Evaluation Project - GO Version
|
||||
|
||||
(仅环境安装[非必须]使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖安装也可全测项目)
|
||||
(No additional shell file dependencies unless necessary to install the environment using the shell, the environment is installed just to measure more accurately, in extreme cases no environment dependencies can also be fully measured project)
|
||||
|
||||
如有问题请 [issues](https://github.com/oneclickvirt/ecs/issues) 反馈。
|
||||
Please report any issues via [issues](https://github.com/oneclickvirt/ecs/issues).
|
||||
|
||||
Go 版本:[https://github.com/oneclickvirt/ecs](https://github.com/oneclickvirt/ecs)
|
||||
Go version: [https://github.com/oneclickvirt/ecs](https://github.com/oneclickvirt/ecs)
|
||||
|
||||
Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS/ecs)
|
||||
Shell version: [https://github.com/spiritLHLS/ecs/blob/main/README_EN.md](https://github.com/spiritLHLS/ecs/blob/main/README_EN.md)
|
||||
|
||||
---
|
||||
|
||||
## **语言**
|
||||
## **Language**
|
||||
|
||||
[中文文档](README.md) | [English Docs](README_EN.md)
|
||||
[English Docs](README.md) | [中文文档](README_ZH.md)
|
||||
|
||||
---
|
||||
|
||||
## **适配系统和架构**
|
||||
## **Supported Systems and Architectures**
|
||||
|
||||
### **编译与测试支持情况**
|
||||
| 编译支持的架构 | 测试支持的架构 | 编译支持的系统 | 测试支持的系统 |
|
||||
|---------------------------|--------------|---------------------------|---------------|
|
||||
| amd64 | amd64 | Linux | Linux |
|
||||
| arm64 | arm64 | Windows | Windows |
|
||||
| arm | | MacOS(Darwin) | MacOS |
|
||||
| 386 | | FreeBSD | |
|
||||
| mips,mipsle | | Android | |
|
||||
| mips64,mips64le | | | |
|
||||
| ppc64,ppc64le | | | |
|
||||
| s390x | s390x | | |
|
||||
| riscv64 | | | |
|
||||
### **Compilation and Testing Support**
|
||||
| Supported for Compilation | Tested on | Supported OS for Compilation | Tested OS |
|
||||
|---------------------------|-----------|------------------------------|-----------|
|
||||
| amd64 | amd64 | Linux | Linux |
|
||||
| arm64 | arm64 | Windows | Windows |
|
||||
| arm | | MacOS(Darwin) | MacOS |
|
||||
| 386 | | FreeBSD | |
|
||||
| mips,mipsle | | Android | |
|
||||
| mips64,mips64le | | | |
|
||||
| ppc64,ppc64le | | | |
|
||||
| s390x | s390x | | |
|
||||
| riscv64 | | | |
|
||||
|
||||
> 更多架构与系统请自行测试或编译,如有问题请开 issues。
|
||||
> For more information about the architecture and system, please test or compile it yourself, and open issues if you have any questions.
|
||||
|
||||
### **待支持的系统**
|
||||
### **Systems Pending Support**
|
||||
|
||||
| 系统 | 说明 |
|
||||
|----------------|---------------------------|
|
||||
| OpenBSD/NetBSD | 部分Goalng的官方库未支持本系统(尤其是net相关项目) |
|
||||
| OS | Notes |
|
||||
|--------|-------------------------------------------------------------------------------------------------|
|
||||
| OpenBSD/NetBSD | Some of Golang's official libraries do not support this system (especially net-related items) |
|
||||
|
||||
---
|
||||
|
||||
## **功能**
|
||||
## **Features**
|
||||
|
||||
- 系统基础信息查询,IP基础信息并发查询:[basics](https://github.com/oneclickvirt/basics)、[gostun](https://github.com/oneclickvirt/gostun)
|
||||
- CPU 测试:[cputest](https://github.com/oneclickvirt/cputest),支持 sysbench(lua/golang版本)、geekbench、winsat
|
||||
- 内存测试:[memorytest](https://github.com/oneclickvirt/memorytest),支持 sysbench、dd、winsat、mbw、stream
|
||||
- 硬盘测试:[disktest](https://github.com/oneclickvirt/disktest),支持 dd、fio、winsat
|
||||
- 流媒体平台解锁测试并发查询:[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)
|
||||
- 三网路由测试:基于 [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)
|
||||
- 支持root或admin环境下测试,支持非root或非admin环境下测试,支持离线环境下进行测试,**暂未**支持无DNS的在线环境下进行测试
|
||||
- System basic information query and concurrent IP basic information query: Self-developed [basics](https://github.com/oneclickvirt/basics), [gostun](https://github.com/oneclickvirt/gostun)
|
||||
- CPU test: Self-developed [cputest](https://github.com/oneclickvirt/cputest) supporting sysbench(lua/golang version), geekbench, winsat
|
||||
- Memory test: Self-developed [memorytest](https://github.com/oneclickvirt/memorytest) supporting sysbench, dd, winsat, mbw, stream
|
||||
- Disk test: Self-developed [disktest](https://github.com/oneclickvirt/disktest) supporting dd, fio, winsat
|
||||
- Streaming platform unlock tests concurrent query: Self-developed to [UnlockTests](https://github.com/oneclickvirt/UnlockTests), logic modified from [RegionRestrictionCheck](https://github.com/lmc999/RegionRestrictionCheck) and others
|
||||
- IP quality/security information concurrent query: Self-developed, binary files compiled in [securityCheck](https://github.com/oneclickvirt/securityCheck)
|
||||
- Email port test: Self-developed [portchecker](https://github.com/oneclickvirt/portchecker)
|
||||
- Three-network return path test: Modified from [zhanghanyun/backtrace](https://github.com/zhanghanyun/backtrace) to [oneclickvirt/backtrace](https://github.com/oneclickvirt/backtrace)
|
||||
- Three-network route test: Modified from [NTrace-core](https://github.com/nxtrace/NTrace-core) to [nt3](https://github.com/oneclickvirt/nt3)
|
||||
- Speed test: Based on data from [speedtest.net](https://github.com/spiritLHLS/speedtest.net-CN-ID) and [speedtest.cn](https://github.com/spiritLHLS/speedtest.cn-CN-ID), developed to [oneclickvirt/speedtest](https://github.com/oneclickvirt/speedtest)
|
||||
- Three-network Ping test: Modified from [ecsspeed](https://github.com/spiritLHLS/ecsspeed) to [pingtest](https://github.com/oneclickvirt/pingtest)
|
||||
- Support root or admin environment testing, support non-root or non-admin environment testing, support offline environment for testing, **not yet** support no DNS online environment for testing
|
||||
|
||||
**本项目初次使用建议查看说明:[跳转](https://github.com/oneclickvirt/ecs/blob/master/README_NEW_USER.md)**
|
||||
**For first-time users of this project, it is recommended to check the instructions: [Jump to](https://github.com/oneclickvirt/ecs/blob/master/README_NEW_USER.md)**
|
||||
|
||||
---
|
||||
|
||||
## **使用说明**
|
||||
## **Instructions for Use**
|
||||
|
||||
### **Linux/FreeBSD/MacOS**
|
||||
|
||||
#### **一键命令**
|
||||
#### **One-click command**
|
||||
|
||||
**一键命令**将默认**不安装依赖**,默认**不更新包管理器**,默认**非互动模式**
|
||||
**One-Click Command** will **Not install Dependencies** by Default, **Not update Package Manager** by Default, **Non-Interactive Mode** by Default.
|
||||
|
||||
- **国际用户无加速:**
|
||||
- **International users without acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs -l=en
|
||||
```
|
||||
|
||||
- **国际/国内使用 CDN 加速:**
|
||||
- **International/domestic users with CDN acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs -l=en
|
||||
```
|
||||
|
||||
- **国内用户使用 CNB 加速:**
|
||||
- **Domestic users with CNB acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
export noninteractive=true && export CN=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs -l=en
|
||||
```
|
||||
|
||||
- **短链接:**
|
||||
- **Short Link:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && bash goecs.sh install && goecs -l=en
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
OR
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs -l=en
|
||||
```
|
||||
|
||||
**如果需要测试更准确,请按照下面的详细说明进行安装,添加非必需的依赖**
|
||||
**For more accurate testing, please follow the detailed instructions below to install and add non-essential dependencies**
|
||||
|
||||
#### **详细说明**
|
||||
#### **Detailed instructions**
|
||||
|
||||
以下命令可控制**是否安装依赖**,**是否更新包管理器**,**互动模式和非交互模式**
|
||||
The following commands control whether dependencies are installed, whether the package manager is updated, and whether interactive or non-interactive mode is used.
|
||||
|
||||
<details>
|
||||
<summary>展开查看详细说明</summary>
|
||||
<summary>Expand to view detailed instructions</summary>
|
||||
|
||||
1. **下载脚本**
|
||||
1. **Download the script**
|
||||
|
||||
**国际用户无加速:**
|
||||
**International users without acceleration:**
|
||||
|
||||
```bash
|
||||
curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
**国际/国内使用 CDN 加速:**
|
||||
**International/domestic users with CDN acceleration:**
|
||||
|
||||
```bash
|
||||
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
**国内用户使用 CNB 加速:**
|
||||
**Domestic users with CNB acceleration:**
|
||||
|
||||
```bash
|
||||
curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
export CN=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
2. **更新包管理器(可选择)并安装环境**
|
||||
2. **Update package manager (optional) and install environment**
|
||||
|
||||
```bash
|
||||
./goecs.sh env
|
||||
```
|
||||
|
||||
**非互动模式:**
|
||||
**Non-interactive mode:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && ./goecs.sh env
|
||||
```
|
||||
|
||||
3. **安装 `goecs` 本体(仅下载二进制文件无依赖安装)**
|
||||
3. **Install `goecs`**
|
||||
|
||||
```bash
|
||||
./goecs.sh install
|
||||
```
|
||||
|
||||
4. **升级 `goecs` 本体**
|
||||
4. **Upgrade `goecs`**
|
||||
|
||||
```bash
|
||||
./goecs.sh upgrade
|
||||
```
|
||||
|
||||
5. **卸载 `goecs` 本体**
|
||||
5. **Uninstall `goecs`**
|
||||
|
||||
```bash
|
||||
./goecs.sh uninstall
|
||||
```
|
||||
|
||||
6. **帮助命令**
|
||||
6. **help command**
|
||||
|
||||
```bash
|
||||
./goecs.sh -h
|
||||
```
|
||||
|
||||
7. **唤起菜单**
|
||||
7. **Invoke the menu**
|
||||
|
||||
```bash
|
||||
goecs
|
||||
goecs -l=en
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
#### **命令参数化**
|
||||
#### **Command parameterization**
|
||||
|
||||
<details>
|
||||
<summary>展开查看各参数说明</summary>
|
||||
<summary>Expand to view parameter descriptions</summary>
|
||||
|
||||
```bash
|
||||
Usage: goecs [options]
|
||||
@@ -267,97 +266,95 @@ Usage: goecs [options]
|
||||
|
||||
### **Windows**
|
||||
|
||||
1. 下载带 exe 文件的压缩包:[Releases](https://github.com/oneclickvirt/ecs/releases)
|
||||
2. 解压后,右键以管理员模式运行。
|
||||
1. Download the compressed file with the .exe file: [Releases](https://github.com/oneclickvirt/ecs/releases)
|
||||
2. After unzipping, right-click and run as administrator.
|
||||
|
||||
PS:如果是虚拟机环境,不以管理员模式运行也行,因为虚拟机无原生的测试工具,将自动启用替代方法测试。
|
||||
PPS: 暂时不要下载带GUI标签的exe文件,未完整适配,CI版本的压缩包是没问题的。
|
||||
PS: If it's a VM environment, it's OK not to run it in administrator mode, because VMs have no native testing tools and will automatically enable alternative methods for testing.
|
||||
PPS: Please refrain from downloading executable files labelled with a GUI for the time being, as they have not been fully adapted. The compressed packages for the CI version are unaffected.
|
||||
|
||||
---
|
||||
|
||||
### **Docker**
|
||||
|
||||
<details>
|
||||
<summary>展开查看使用说明</summary>
|
||||
<summary>Expand to view how to use it</summary>
|
||||
|
||||
国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs
|
||||
International image: https://hub.docker.com/r/spiritlhl/goecs
|
||||
|
||||
请确保执行下述命令前本机已安装Docker
|
||||
Please ensure Docker is installed on your machine before executing the following commands
|
||||
|
||||
特权模式+host网络
|
||||
Privileged mode + host network
|
||||
|
||||
```shell
|
||||
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh
|
||||
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l=en
|
||||
```
|
||||
|
||||
非特权模式+非host网络
|
||||
Unprivileged mode + non-host network
|
||||
|
||||
```shell
|
||||
docker run --rm spiritlhl/goecs:latest -menu=false -l zh
|
||||
docker run --rm spiritlhl/goecs:latest -menu=false -l=en
|
||||
```
|
||||
|
||||
使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。
|
||||
Using Docker to execute tests will result in some hardware testing bias and virtualization architecture detection failure. Direct testing is recommended over Docker testing.
|
||||
|
||||
国内阿里云镜像加速
|
||||
Mirror image: https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs
|
||||
|
||||
请确保执行下述命令前本机已安装Docker
|
||||
Please ensure Docker is installed on your machine before executing the following commands
|
||||
|
||||
特权模式+host网络
|
||||
Privileged mode + host network
|
||||
|
||||
```shell
|
||||
docker run --rm --privileged --network host crpi-8tmognxgyb86bm61.cn-guangzhou.personal.cr.aliyuncs.com/oneclickvirt/ecs:latest -menu=false -l zh
|
||||
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l=en
|
||||
```
|
||||
|
||||
非特权模式+非host网络
|
||||
Unprivileged mode + non-host network
|
||||
|
||||
```shell
|
||||
docker run --rm crpi-8tmognxgyb86bm61.cn-guangzhou.personal.cr.aliyuncs.com/oneclickvirt/ecs:latest -menu=false -l zh
|
||||
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l=en
|
||||
```
|
||||
|
||||
实际上还有CNB镜像地址 https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs 但很可惜组织空间不足无法推送了,更推荐使用阿里云镜像加速
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
### 从源码进行编译
|
||||
### Compiling from source code
|
||||
|
||||
<details>
|
||||
<summary>展开查看编译说明</summary>
|
||||
<summary>Expand to view compilation instructions</summary>
|
||||
|
||||
1. 克隆仓库的 public 分支(不含私有依赖)
|
||||
1. Clone the public branch of the repository (without private dependencies)
|
||||
```bash
|
||||
git clone -b public https://github.com/oneclickvirt/ecs.git
|
||||
cd ecs
|
||||
```
|
||||
|
||||
2. 安装 Go 环境(如已安装可跳过)
|
||||
2. Install Go environment (skip if already installed)
|
||||
|
||||
选择 go 1.25.4 的版本进行安装
|
||||
Select go 1.25.4 version to install
|
||||
|
||||
```bash
|
||||
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh
|
||||
```
|
||||
|
||||
3. 编译
|
||||
3. Compile
|
||||
```bash
|
||||
go build -o goecs
|
||||
```
|
||||
|
||||
4. 运行测试
|
||||
4. Run test
|
||||
```bash
|
||||
./goecs -menu=false -l zh
|
||||
./goecs -menu=false -l=en
|
||||
```
|
||||
|
||||
支持的编译参数:
|
||||
- GOOS:支持 linux、windows、darwin、freebsd、openbsd
|
||||
- GOARCH:支持 amd64、arm、arm64、386、mips、mipsle、s390x、riscv64
|
||||
Supported compilation parameters:
|
||||
- GOOS: supports linux, windows, darwin, freebsd, openbsd
|
||||
- GOARCH: supports amd64, arm, arm64, 386, mips, mipsle, s390x, riscv64
|
||||
|
||||
跨平台编译示例:
|
||||
Cross-platform compilation examples:
|
||||
```bash
|
||||
# 编译 Windows 版本
|
||||
# Compile Windows version
|
||||
GOOS=windows GOARCH=amd64 go build -o goecs.exe
|
||||
# 编译 MacOS 版本
|
||||
# Compile MacOS version
|
||||
GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
|
||||
```
|
||||
</details>
|
||||
@@ -366,57 +363,55 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
|
||||
|
||||
## QA
|
||||
|
||||
#### Q: 为什么默认使用sysbench而不是geekbench
|
||||
#### Q: Why is sysbench used by default instead of geekbench?
|
||||
|
||||
#### A: 比较二者特点
|
||||
#### A: Comparing the characteristics of both:
|
||||
|
||||
| 比较项 | sysbench | geekbench |
|
||||
|------------------|----------|-----------|
|
||||
| 适用范围 | 轻量级,几乎可在任何服务器上运行 | 重量级,小型机器无法运行 |
|
||||
| 测试要求 | 无需网络,无特殊硬件需求 | 需联网,IPV4环境,至少1G内存 |
|
||||
| 开源情况 | 基于LUA,开源,可自行编译各架构版本 | 官方二进制闭源代码,不支持自行编译 |
|
||||
| 测试稳定性 | 核心测试组件10年以上未变 | 每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU) |
|
||||
| 测试内容 | 仅测试计算性能 | 覆盖多种性能测试,分数加权计算,但部分测试实际不常用 |
|
||||
| 适用场景 | 适合快速测试,仅测试计算性能 | 适合综合全面的测试 |
|
||||
| 排行榜 | [sysbench.spiritlhl.net](https://sysbench.spiritlhl.net/) | [browser.geekbench.com](https://browser.geekbench.com/) |
|
||||
| Comparison | sysbench | geekbench |
|
||||
|------------|----------|-----------|
|
||||
| Application scope | Lightweight, runs on almost any server | Heavyweight, won't run on small machines |
|
||||
| Test requirements | No network needed, no special hardware requirements | Requires internet, IPv4 environment, minimum 1GB memory |
|
||||
| Open source status | Based on LUA, open source, can compile for various architectures | Official binaries are closed source, cannot compile your own version |
|
||||
| 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/) |
|
||||
|
||||
且```goecs```测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求
|
||||
Note that `goecs` allows you to specify CPU test method via parameters. The default is chosen for faster testing across more systems.
|
||||
|
||||
#### Q: 为什么使用Golang而不是Rust重构
|
||||
#### Q: Why use Golang instead of Rust for refactoring?
|
||||
|
||||
#### A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,~~我懒得搞~~我没那个技术力
|
||||
#### A: Because network-related projects currently trend toward Golang, with many components maintained by open source communities. Many Rust components would require building from scratch, ~~I'm too lazy~~ I don't have that technical capability.
|
||||
|
||||
#### Q: 为什么不继续开发Shell版本而是选择重构
|
||||
#### Q: Why not continue developing the Shell version instead of refactoring?
|
||||
|
||||
#### A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)
|
||||
#### A: Because there were too many varied environment issues. Pre-compiled binary files are easier for solving environment problems (better generalization).
|
||||
|
||||
#### Q: 每个测试项目的说明有吗?
|
||||
#### Q: Are there explanations for each test item?
|
||||
|
||||
#### A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明
|
||||
#### A: Each test project has its own maintenance repository. Click through to view the repository description.
|
||||
|
||||
#### Q: 测试进行到一半如何手动终止?
|
||||
#### Q: How do I manually terminate a test halfway through?
|
||||
|
||||
#### A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。
|
||||
#### A: Press Ctrl+C to terminate the program. After termination, a goecs.txt file and share link will still be generated in the current directory containing information tested so far.
|
||||
|
||||
#### Q: 非Root环境如何进行测试?
|
||||
#### Q: How do I test in a non-Root environment?
|
||||
|
||||
#### A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。
|
||||
#### A: Execute the installation command manually. If you can't install it, simply download the appropriate architecture package from releases, extract it, and run the file if you have execution permissions. Alternatively, use Docker if you can.
|
||||
|
||||
## 致谢
|
||||
## Thanks
|
||||
|
||||
感谢
|
||||
[DKLYDataHub - IP Geolocation Data](https://data.dkly.net)
|
||||
[he.net](https://he.net) [bgp.tools](https://bgp.tools) [ipinfo.io](https://ipinfo.io) [maxmind.com](https://www.maxmind.com/en/home) [cloudflare.com](https://www.cloudflare.com/) [ip.sb](https://ip.sb) [scamalytics.com](https://scamalytics.com) [abuseipdb.com](https://www.abuseipdb.com/) [ip2location.com](https://ip2location.com/) [ip-api.com](https://ip-api.com) [ipregistry.co](https://ipregistry.co/) [ipdata.co](https://ipdata.co/) [ipgeolocation.io](https://ipgeolocation.io) [ipwhois.io](https://ipwhois.io) [ipapi.com](https://ipapi.com/) [ipapi.is](https://ipapi.is/) [ipqualityscore.com](https://www.ipqualityscore.com/) [bigdatacloud.com](https://www.bigdatacloud.com/) [virustotal.com](https://www.virustotal.com/) [ipfighter.com](https://ipfighter.com/) [getipintel.net](http://check.getipintel.net/) [fraudlogix.com](https://fraudlogix.com) 等网站提供的API进行检测,感谢互联网各网站提供的查询资源
|
||||
Thank [he.net](https://he.net) [bgp.tools](https://bgp.tools) [ipinfo.io](https://ipinfo.io) [maxmind.com](https://www.maxmind.com/en/home) [cloudflare.com](https://www.cloudflare.com/) [ip.sb](https://ip.sb) [scamalytics.com](https://scamalytics.com) [abuseipdb.com](https://www.abuseipdb.com/) [ip2location.com](https://ip2location.com/) [ip-api.com](https://ip-api.com) [ipregistry.co](https://ipregistry.co/) [ipdata.co](https://ipdata.co/) [ipgeolocation.io](https://ipgeolocation.io) [ipwhois.io](https://ipwhois.io) [ipapi.com](https://ipapi.com/) [ipapi.is](https://ipapi.is/) [ipqualityscore.com](https://www.ipqualityscore.com/) [bigdatacloud.com](https://www.bigdatacloud.com/) [dkly.net](https://data.dkly.net) [virustotal.com](https://www.virustotal.com/) [ipfighter.com](https://ipfighter.com/) [getipintel.net](http://check.getipintel.net/) [fraudlogix.com](https://fraudlogix.com) and others for providing APIs for testing, and thanks to various websites on the Internet for providing query resources.
|
||||
|
||||
感谢
|
||||
Thank
|
||||
|
||||
<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" style="height: 50px;">
|
||||
</a>
|
||||
|
||||
提供的免费托管支持本开源项目的共享测试结果存储
|
||||
provided free hosting support for this open source project's shared test results storage
|
||||
|
||||
同时感谢以下平台提供编辑和测试支持
|
||||
Thanks also to the following platforms for editorial and testing support
|
||||
|
||||
<a href="https://www.jetbrains.com/go/" target="_blank">
|
||||
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland" style="height: 50px;">
|
||||
|
||||
437
README_EN.md
437
README_EN.md
@@ -1,437 +0,0 @@
|
||||
# ECS
|
||||
|
||||
[](https://github.com/oneclickvirt/ecs/actions/workflows/build_binary.yaml)
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_shield)
|
||||
|
||||
[](https://hits.spiritlhl.net) [](https://github.com/oneclickvirt/ecs/releases)
|
||||
|
||||
Fusion Monster Evaluation Project - GO Version
|
||||
|
||||
(No additional shell file dependencies unless necessary to install the environment using the shell, the environment is installed just to measure more accurately, in extreme cases no environment dependencies can also be fully measured project)
|
||||
|
||||
Please report any issues via [issues](https://github.com/oneclickvirt/ecs/issues).
|
||||
|
||||
Go version: [https://github.com/oneclickvirt/ecs](https://github.com/oneclickvirt/ecs)
|
||||
|
||||
Shell version: [https://github.com/spiritLHLS/ecs/blob/main/README_EN.md](https://github.com/spiritLHLS/ecs/blob/main/README_EN.md)
|
||||
|
||||
---
|
||||
|
||||
## **Language**
|
||||
|
||||
[中文文档](README.md) | [English Docs](README_EN.md)
|
||||
|
||||
---
|
||||
|
||||
## **Supported Systems and Architectures**
|
||||
|
||||
### **Compilation and Testing Support**
|
||||
| Supported for Compilation | Tested on | Supported OS for Compilation | Tested OS |
|
||||
|---------------------------|-----------|------------------------------|-----------|
|
||||
| amd64 | amd64 | Linux | Linux |
|
||||
| arm64 | arm64 | Windows | Windows |
|
||||
| arm | | MacOS(Darwin) | MacOS |
|
||||
| 386 | | FreeBSD | |
|
||||
| mips,mipsle | | Android | |
|
||||
| mips64,mips64le | | | |
|
||||
| ppc64,ppc64le | | | |
|
||||
| s390x | s390x | | |
|
||||
| riscv64 | | | |
|
||||
|
||||
> For more information about the architecture and system, please test or compile it yourself, and open issues if you have any questions.
|
||||
|
||||
### **Systems Pending Support**
|
||||
|
||||
| OS | Notes |
|
||||
|--------|-------------------------------------------------------------------------------------------------|
|
||||
| OpenBSD/NetBSD | Some of Goalng's official libraries do not support this system (especially net-related items) |
|
||||
|
||||
---
|
||||
|
||||
## **Features**
|
||||
|
||||
- System basic information query and concurrent IP basic information query: Self-developed [basics](https://github.com/oneclickvirt/basics), [gostun](https://github.com/oneclickvirt/gostun)
|
||||
- CPU test: Self-developed [cputest](https://github.com/oneclickvirt/cputest) supporting sysbench(lua/golang version), geekbench, winsat
|
||||
- Memory test: Self-developed [memorytest](https://github.com/oneclickvirt/memorytest) supporting sysbench, dd, winsat, mbw, stream
|
||||
- Disk test: Self-developed [disktest](https://github.com/oneclickvirt/disktest) supporting dd, fio, winsat
|
||||
- Streaming platform unlock tests concurrent query: Self-developed to [UnlockTests](https://github.com/oneclickvirt/UnlockTests), logic modified from [RegionRestrictionCheck](https://github.com/lmc999/RegionRestrictionCheck) and others
|
||||
- IP quality/security information concurrent query: Self-developed, binary files compiled in [securityCheck](https://github.com/oneclickvirt/securityCheck)
|
||||
- Email port test: Self-developed [portchecker](https://github.com/oneclickvirt/portchecker)
|
||||
- Three-network return path test: Modified from [zhanghanyun/backtrace](https://github.com/zhanghanyun/backtrace) to [oneclickvirt/backtrace](https://github.com/oneclickvirt/backtrace)
|
||||
- Three-network route test: Modified from [NTrace-core](https://github.com/nxtrace/NTrace-core) to [nt3](https://github.com/oneclickvirt/nt3)
|
||||
- Speed test: Based on data from [speedtest.net](https://github.com/spiritLHLS/speedtest.net-CN-ID) and [speedtest.cn](https://github.com/spiritLHLS/speedtest.cn-CN-ID), developed to [oneclickvirt/speedtest](https://github.com/oneclickvirt/speedtest)
|
||||
- Three-network Ping test: Modified from [ecsspeed](https://github.com/spiritLHLS/ecsspeed) to [pingtest](https://github.com/oneclickvirt/pingtest)
|
||||
- Support root or admin environment testing, support non-root or non-admin environment testing, support offline environment for testing, **not yet** support no DNS online environment for testing
|
||||
|
||||
**For first-time users of this project, it is recommended to check the instructions: [Jump to](https://github.com/oneclickvirt/ecs/blob/master/README_NEW_USER.md)**
|
||||
|
||||
---
|
||||
|
||||
## **Instructions for Use**
|
||||
|
||||
### **Linux/FreeBSD/MacOS**
|
||||
|
||||
#### **One-click command**
|
||||
|
||||
**One-Click Command** will **Not install Dependencies** by Default, **Not update Package Manager** by Default, **Non-Interactive Mode** by Default.
|
||||
|
||||
- **International users without acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **International/domestic users with CDN acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **Domestic users with CNB acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **Short Link:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && bash goecs.sh install && goecs
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
**For more accurate testing, please follow the detailed instructions below to install and add non-essential dependencies**
|
||||
|
||||
#### **Detailed instructions**
|
||||
|
||||
The following commands control whether dependencies are installed, whether the package manager is updated, and whether interactive or non-interactive mode is used.
|
||||
|
||||
<details>
|
||||
<summary>Expand to view detailed instructions</summary>
|
||||
|
||||
1. **Download the script**
|
||||
|
||||
**International users without acceleration:**
|
||||
|
||||
```bash
|
||||
curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
**International/domestic users with CDN acceleration:**
|
||||
|
||||
```bash
|
||||
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
**Domestic users with CNB acceleration:**
|
||||
|
||||
```bash
|
||||
curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
2. **Update package manager (optional) and install environment**
|
||||
|
||||
```bash
|
||||
./goecs.sh env
|
||||
```
|
||||
|
||||
**Non-interactive mode:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && ./goecs.sh env
|
||||
```
|
||||
|
||||
3. **Install `goecs`**
|
||||
|
||||
```bash
|
||||
./goecs.sh install
|
||||
```
|
||||
|
||||
4. **Upgrade `goecs`**
|
||||
|
||||
```bash
|
||||
./goecs.sh upgrade
|
||||
```
|
||||
|
||||
5. **Uninstall `goecs`**
|
||||
|
||||
```bash
|
||||
./goecs.sh uninstall
|
||||
|
||||
6. **help command**
|
||||
|
||||
```bash
|
||||
./goecs.sh -h
|
||||
```
|
||||
|
||||
7. **Invoke the menu**
|
||||
|
||||
```bash
|
||||
goecs -l en
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
#### **Command parameterization**
|
||||
|
||||
<details>
|
||||
<summary>Expand to view parameter descriptions</summary>
|
||||
|
||||
```bash
|
||||
Usage: goecs [options]
|
||||
-backtrace
|
||||
Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
|
||||
-basic
|
||||
Enable/Disable basic test (default true)
|
||||
-ut
|
||||
Enable/Disable unlock media test (default true)
|
||||
-cpu
|
||||
Enable/Disable CPU test (default true)
|
||||
-cpum string
|
||||
Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
|
||||
-cpu-method string
|
||||
Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
|
||||
-cput string
|
||||
Set CPU test thread mode (supported: single, multi) (default "multi")
|
||||
-cpu-thread string
|
||||
Set CPU test thread mode (supported: single, multi) (default "multi")
|
||||
-disk
|
||||
Enable/Disable disk test (default true)
|
||||
-diskm string
|
||||
Set disk test method (supported: fio, dd, winsat) (default "fio")
|
||||
-disk-method string
|
||||
Set disk test method (supported: fio, dd, winsat) (default "fio")
|
||||
-diskmc
|
||||
Enable/Disable multiple disk checks, e.g., -diskmc=false
|
||||
-diskp string
|
||||
Set disk test path, e.g., -diskp /root
|
||||
-email
|
||||
Enable/Disable email port test (default true)
|
||||
-h Show help information
|
||||
-help
|
||||
Show help information
|
||||
-l string
|
||||
Set language (supported: en, zh) (default "zh")
|
||||
-lang string
|
||||
Set language (supported: en, zh) (default "zh")
|
||||
-log
|
||||
Enable/Disable logging in the current path
|
||||
-memory
|
||||
Enable/Disable memory test (default true)
|
||||
-memorym string
|
||||
Set memory test method (supported: stream, sysbench, dd, winsat, auto) (default "stream")
|
||||
-memory-method string
|
||||
Set memory test method (supported: stream, sysbench, dd, winsat, auto) (default "stream")
|
||||
-menu
|
||||
Enable/Disable menu mode, disable example: -menu=false (default true)
|
||||
-nt3
|
||||
Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
|
||||
-nt3loc string
|
||||
Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all) (default "GZ")
|
||||
-nt3-location string
|
||||
Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all) (default "GZ")
|
||||
-nt3t string
|
||||
Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
|
||||
-nt3-type string
|
||||
Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
|
||||
-ping
|
||||
Enable/Disable ping test
|
||||
-security
|
||||
Enable/Disable security test (default true)
|
||||
-speed
|
||||
Enable/Disable speed test (default true)
|
||||
-spnum int
|
||||
Set the number of servers per operator for speed test (default 2)
|
||||
-tgdc
|
||||
Enable/Disable Telegram DC test
|
||||
-upload
|
||||
Enable/Disable upload the result (default true)
|
||||
-v Display version information
|
||||
-version
|
||||
Display version information
|
||||
-web
|
||||
Enable/Disable popular websites test
|
||||
```
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
### **Windows**
|
||||
|
||||
1. Download the compressed file with the .exe file: [Releases](https://github.com/oneclickvirt/ecs/releases)
|
||||
2. After unzipping, right-click and run as administrator.
|
||||
|
||||
PS: If it's a VM environment, it's OK not to run it in administrator mode, because VMs have no native testing tools and will automatically enable alternative methods for testing.
|
||||
PPS: Please refrain from downloading executable files labelled with a GUI for the time being, as they have not been fully adapted. The compressed packages for the CI version are unaffected.
|
||||
|
||||
---
|
||||
|
||||
### **Docker**
|
||||
|
||||
<details>
|
||||
<summary>Expand to view how to use it</summary>
|
||||
|
||||
International image: https://hub.docker.com/r/spiritlhl/goecs
|
||||
|
||||
Please ensure Docker is installed on your machine before executing the following commands
|
||||
|
||||
Privileged mode + host network
|
||||
|
||||
```shell
|
||||
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l en
|
||||
```
|
||||
|
||||
Unprivileged mode + non-host network
|
||||
|
||||
```shell
|
||||
docker run --rm spiritlhl/goecs:latest -menu=false -l en
|
||||
```
|
||||
|
||||
Using Docker to execute tests will result in some hardware testing bias and virtualization architecture detection failure. Direct testing is recommended over Docker testing.
|
||||
|
||||
Mirror image: https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs
|
||||
|
||||
Please ensure Docker is installed on your machine before executing the following commands
|
||||
|
||||
Privileged mode + host network
|
||||
|
||||
```shell
|
||||
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l en
|
||||
```
|
||||
|
||||
Unprivileged mode + non-host network
|
||||
|
||||
```shell
|
||||
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l en
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
### Compiling from source code
|
||||
|
||||
<details>
|
||||
<summary>Expand to view compilation instructions</summary>
|
||||
|
||||
1. Clone the public branch of the repository (without private dependencies)
|
||||
```bash
|
||||
git clone -b public https://github.com/oneclickvirt/ecs.git
|
||||
cd ecs
|
||||
```
|
||||
|
||||
2. Install Go environment (skip if already installed)
|
||||
|
||||
Select go 1.25.4 version to install
|
||||
|
||||
```bash
|
||||
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh
|
||||
```
|
||||
|
||||
3. Compile
|
||||
```bash
|
||||
go build -o goecs
|
||||
```
|
||||
|
||||
4. Run test
|
||||
```bash
|
||||
./goecs -menu=false -l en
|
||||
```
|
||||
|
||||
Supported compilation parameters:
|
||||
- GOOS: supports linux, windows, darwin, freebsd, openbsd
|
||||
- GOARCH: supports amd64, arm, arm64, 386, mips, mipsle, s390x, riscv64
|
||||
|
||||
Cross-platform compilation examples:
|
||||
```bash
|
||||
# Compile Windows version
|
||||
GOOS=windows GOARCH=amd64 go build -o goecs.exe
|
||||
# Compile MacOS version
|
||||
GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
|
||||
```
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## QA
|
||||
|
||||
#### Q: Why is sysbench used by default instead of geekbench?
|
||||
|
||||
#### A: Comparing the characteristics of both:
|
||||
|
||||
| Comparison | sysbench | geekbench |
|
||||
|------------|----------|-----------|
|
||||
| Application scope | Lightweight, runs on almost any server | Heavyweight, won't run on small machines |
|
||||
| Test requirements | No network needed, no special hardware requirements | Requires internet, IPv4 environment, minimum 1GB memory |
|
||||
| Open source status | Based on LUA, open source, can compile for various architectures | Official binaries are closed source, cannot compile your own version |
|
||||
| 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.
|
||||
|
||||
#### Q: Why use Golang instead of Rust for refactoring?
|
||||
|
||||
#### A: Because network-related projects currently trend toward Golang, with many components maintained by open source communities. Many Rust components would require building from scratch, ~~I'm too lazy~~ I don't have that technical capability.
|
||||
|
||||
#### Q: Why not continue developing the Shell version instead of refactoring?
|
||||
|
||||
#### A: Because there were too many varied environment issues. Pre-compiled binary files are easier for solving environment problems (better generalization).
|
||||
|
||||
#### Q: Are there explanations for each test item?
|
||||
|
||||
#### A: Each test project has its own maintenance repository. Click through to view the repository description.
|
||||
|
||||
#### Q: How do I manually terminate a test halfway through?
|
||||
|
||||
#### A: Press Ctrl+C to terminate the program. After termination, a goecs.txt file and share link will still be generated in the current directory containing information tested so far.
|
||||
|
||||
#### Q: How do I test in a non-Root environment?
|
||||
|
||||
#### A: Execute the installation command manually. If you can't install it, simply download the appropriate architecture package from releases, extract it, and run the file if you have execution permissions. Alternatively, use Docker if you can.
|
||||
|
||||
## Thanks
|
||||
|
||||
Thank [he.net](https://he.net) [bgp.tools](https://bgp.tools) [ipinfo.io](https://ipinfo.io) [maxmind.com](https://www.maxmind.com/en/home) [cloudflare.com](https://www.cloudflare.com/) [ip.sb](https://ip.sb) [scamalytics.com](https://scamalytics.com) [abuseipdb.com](https://www.abuseipdb.com/) [ip2location.com](https://ip2location.com/) [ip-api.com](https://ip-api.com) [ipregistry.co](https://ipregistry.co/) [ipdata.co](https://ipdata.co/) [ipgeolocation.io](https://ipgeolocation.io) [ipwhois.io](https://ipwhois.io) [ipapi.com](https://ipapi.com/) [ipapi.is](https://ipapi.is/) [ipqualityscore.com](https://www.ipqualityscore.com/) [bigdatacloud.com](https://www.bigdatacloud.com/) [dkly.net](https://data.dkly.net) [virustotal.com](https://www.virustotal.com/) [ipfighter.com](https://ipfighter.com/) [getipintel.net](http://check.getipintel.net/) [fraudlogix.com](https://fraudlogix.com) and others for providing APIs for testing, and thanks to various websites on the Internet for providing query resources.
|
||||
|
||||
Thank
|
||||
|
||||
<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" style="height: 50px;">
|
||||
</a>
|
||||
|
||||
provided free hosting support for this open source project's shared test results storage
|
||||
|
||||
Thanks also to the following platforms for editorial and testing support
|
||||
|
||||
<a href="https://www.jetbrains.com/go/" target="_blank">
|
||||
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland" style="height: 50px;">
|
||||
</a>
|
||||
|
||||
<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" 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>
|
||||
|
||||
## History Usage
|
||||
|
||||

|
||||
|
||||
## Stargazers over time
|
||||
|
||||
[](https://www.spiritlhl.net)
|
||||
|
||||
## License
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_large)
|
||||
@@ -3,11 +3,13 @@
|
||||
[](https://hits.spiritlhl.net) [](https://github.com/oneclickvirt/ecs/releases)
|
||||
|
||||
## 语言 / Languages / 言語
|
||||
|
||||
- [中文](#中文)
|
||||
- [English](#English)
|
||||
- [日本語](#日本語)
|
||||
|
||||
## 中文
|
||||
|
||||
- [系统基础信息](#系统基础信息)
|
||||
- [CPU测试](#CPU测试)
|
||||
- [内存测试](#内存测试)
|
||||
@@ -21,6 +23,7 @@
|
||||
- [就近测速](#就近测速)
|
||||
|
||||
## English
|
||||
|
||||
- [Basic System Information](#Basic-System-Information)
|
||||
- [CPU Testing](#CPU-Testing)
|
||||
- [Memory Testing](#Memory-Testing)
|
||||
@@ -32,6 +35,7 @@
|
||||
- [Nearby Speed Testing](#Nearby-Speed-Testing)
|
||||
|
||||
## 日本語
|
||||
|
||||
- [システム基本情報](#システム基本情報)
|
||||
- [CPUテスト](#CPUテスト)
|
||||
- [メモリテスト](#メモリテスト)
|
||||
|
||||
442
README_ZH.md
Normal file
442
README_ZH.md
Normal file
@@ -0,0 +1,442 @@
|
||||
# ECS
|
||||
|
||||
[](https://github.com/oneclickvirt/ecs/actions/workflows/build_binary.yaml)
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_shield)
|
||||
|
||||
[](https://hits.spiritlhl.net) [](https://github.com/oneclickvirt/ecs/releases)
|
||||
|
||||
融合怪测评项目 - GO版本
|
||||
|
||||
(仅环境安装[非必须]使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖安装也可全测项目)
|
||||
|
||||
如有问题请 [issues](https://github.com/oneclickvirt/ecs/issues) 反馈。
|
||||
|
||||
Go 版本:[https://github.com/oneclickvirt/ecs](https://github.com/oneclickvirt/ecs)
|
||||
|
||||
Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS/ecs)
|
||||
|
||||
---
|
||||
|
||||
## **语言**
|
||||
|
||||
[English Docs](README.md) | [中文文档](README_ZH.md)
|
||||
|
||||
---
|
||||
|
||||
## **适配系统和架构**
|
||||
|
||||
### **编译与测试支持情况**
|
||||
| 编译支持的架构 | 测试支持的架构 | 编译支持的系统 | 测试支持的系统 |
|
||||
|---------------------------|--------------|---------------------------|---------------|
|
||||
| amd64 | amd64 | Linux | Linux |
|
||||
| arm64 | arm64 | Windows | Windows |
|
||||
| arm | | MacOS(Darwin) | MacOS |
|
||||
| 386 | | FreeBSD | |
|
||||
| mips,mipsle | | Android | |
|
||||
| mips64,mips64le | | | |
|
||||
| ppc64,ppc64le | | | |
|
||||
| s390x | s390x | | |
|
||||
| riscv64 | | | |
|
||||
|
||||
> 更多架构与系统请自行测试或编译,如有问题请开 issues。
|
||||
|
||||
### **待支持的系统**
|
||||
|
||||
| 系统 | 说明 |
|
||||
|----------------|---------------------------|
|
||||
| OpenBSD/NetBSD | 部分Golang的官方库未支持本系统(尤其是net相关项目) |
|
||||
|
||||
---
|
||||
|
||||
## **功能**
|
||||
|
||||
- 系统基础信息查询,IP基础信息并发查询:[basics](https://github.com/oneclickvirt/basics)、[gostun](https://github.com/oneclickvirt/gostun)
|
||||
- CPU 测试:[cputest](https://github.com/oneclickvirt/cputest),支持 sysbench(lua/golang版本)、geekbench、winsat
|
||||
- 内存测试:[memorytest](https://github.com/oneclickvirt/memorytest),支持 sysbench、dd、winsat、mbw、stream
|
||||
- 硬盘测试:[disktest](https://github.com/oneclickvirt/disktest),支持 dd、fio、winsat
|
||||
- 流媒体平台解锁测试并发查询:[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)
|
||||
- 三网路由测试:基于 [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)
|
||||
- 支持root或admin环境下测试,支持非root或非admin环境下测试,支持离线环境下进行测试,**暂未**支持无DNS的在线环境下进行测试
|
||||
|
||||
**本项目初次使用建议查看说明:[跳转](https://github.com/oneclickvirt/ecs/blob/master/README_NEW_USER.md)**
|
||||
|
||||
---
|
||||
|
||||
## **使用说明**
|
||||
|
||||
### **Linux/FreeBSD/MacOS**
|
||||
|
||||
#### **一键命令**
|
||||
|
||||
**一键命令**将默认**不安装依赖**,默认**不更新包管理器**,默认**非互动模式**
|
||||
|
||||
- **国际用户无加速:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **国际/国内使用 CDN 加速:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **国内用户使用 CNB 加速:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && export CN=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **短链接:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
**如果需要测试更准确,请按照下面的详细说明进行安装,添加非必需的依赖**
|
||||
|
||||
#### **详细说明**
|
||||
|
||||
以下命令可控制**是否安装依赖**,**是否更新包管理器**,**互动模式和非交互模式**
|
||||
|
||||
<details>
|
||||
<summary>展开查看详细说明</summary>
|
||||
|
||||
1. **下载脚本**
|
||||
|
||||
**国际用户无加速:**
|
||||
|
||||
```bash
|
||||
curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
**国际/国内使用 CDN 加速:**
|
||||
|
||||
```bash
|
||||
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
**国内用户使用 CNB 加速:**
|
||||
|
||||
```bash
|
||||
export CN=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||
```
|
||||
|
||||
2. **更新包管理器(可选择)并安装环境**
|
||||
|
||||
```bash
|
||||
./goecs.sh env
|
||||
```
|
||||
|
||||
**非互动模式:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && ./goecs.sh env
|
||||
```
|
||||
|
||||
3. **安装 `goecs` 本体(仅下载二进制文件无依赖安装)**
|
||||
|
||||
```bash
|
||||
./goecs.sh install
|
||||
```
|
||||
|
||||
4. **升级 `goecs` 本体**
|
||||
|
||||
```bash
|
||||
./goecs.sh upgrade
|
||||
```
|
||||
|
||||
5. **卸载 `goecs` 本体**
|
||||
|
||||
```bash
|
||||
./goecs.sh uninstall
|
||||
```
|
||||
|
||||
6. **帮助命令**
|
||||
|
||||
```bash
|
||||
./goecs.sh -h
|
||||
```
|
||||
|
||||
7. **唤起菜单**
|
||||
|
||||
```bash
|
||||
goecs
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
#### **命令参数化**
|
||||
|
||||
<details>
|
||||
<summary>展开查看各参数说明</summary>
|
||||
|
||||
```bash
|
||||
Usage: goecs [options]
|
||||
-backtrace
|
||||
Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
|
||||
-basic
|
||||
Enable/Disable basic test (default true)
|
||||
-ut
|
||||
Enable/Disable unlock media test (default true)
|
||||
-cpu
|
||||
Enable/Disable CPU test (default true)
|
||||
-cpum string
|
||||
Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
|
||||
-cpu-method string
|
||||
Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
|
||||
-cput string
|
||||
Set CPU test thread mode (supported: single, multi) (default "multi")
|
||||
-cpu-thread string
|
||||
Set CPU test thread mode (supported: single, multi) (default "multi")
|
||||
-disk
|
||||
Enable/Disable disk test (default true)
|
||||
-diskm string
|
||||
Set disk test method (supported: fio, dd, winsat) (default "fio")
|
||||
-disk-method string
|
||||
Set disk test method (supported: fio, dd, winsat) (default "fio")
|
||||
-diskmc
|
||||
Enable/Disable multiple disk checks, e.g., -diskmc=false
|
||||
-diskp string
|
||||
Set disk test path, e.g., -diskp /root
|
||||
-email
|
||||
Enable/Disable email port test (default true)
|
||||
-h Show help information
|
||||
-help
|
||||
Show help information
|
||||
-l string
|
||||
Set language (supported: en, zh) (default "zh")
|
||||
-lang string
|
||||
Set language (supported: en, zh) (default "zh")
|
||||
-log
|
||||
Enable/Disable logging in the current path
|
||||
-memory
|
||||
Enable/Disable memory test (default true)
|
||||
-memorym string
|
||||
Set memory test method (supported: stream, sysbench, dd, winsat, auto) (default "stream")
|
||||
-memory-method string
|
||||
Set memory test method (supported: stream, sysbench, dd, winsat, auto) (default "stream")
|
||||
-menu
|
||||
Enable/Disable menu mode, disable example: -menu=false (default true)
|
||||
-nt3
|
||||
Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
|
||||
-nt3loc string
|
||||
Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all) (default "GZ")
|
||||
-nt3-location string
|
||||
Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all) (default "GZ")
|
||||
-nt3t string
|
||||
Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
|
||||
-nt3-type string
|
||||
Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
|
||||
-ping
|
||||
Enable/Disable ping test
|
||||
-security
|
||||
Enable/Disable security test (default true)
|
||||
-speed
|
||||
Enable/Disable speed test (default true)
|
||||
-spnum int
|
||||
Set the number of servers per operator for speed test (default 2)
|
||||
-tgdc
|
||||
Enable/Disable Telegram DC test
|
||||
-upload
|
||||
Enable/Disable upload the result (default true)
|
||||
-v Display version information
|
||||
-version
|
||||
Display version information
|
||||
-web
|
||||
Enable/Disable popular websites test
|
||||
```
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
### **Windows**
|
||||
|
||||
1. 下载带 exe 文件的压缩包:[Releases](https://github.com/oneclickvirt/ecs/releases)
|
||||
2. 解压后,右键以管理员模式运行。
|
||||
|
||||
PS:如果是虚拟机环境,不以管理员模式运行也行,因为虚拟机无原生的测试工具,将自动启用替代方法测试。
|
||||
PPS: 暂时不要下载带GUI标签的exe文件,未完整适配,CI版本的压缩包是没问题的。
|
||||
|
||||
---
|
||||
|
||||
### **Docker**
|
||||
|
||||
<details>
|
||||
<summary>展开查看使用说明</summary>
|
||||
|
||||
国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs
|
||||
|
||||
请确保执行下述命令前本机已安装Docker
|
||||
|
||||
特权模式+host网络
|
||||
|
||||
```shell
|
||||
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh
|
||||
```
|
||||
|
||||
非特权模式+非host网络
|
||||
|
||||
```shell
|
||||
docker run --rm spiritlhl/goecs:latest -menu=false -l zh
|
||||
```
|
||||
|
||||
使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。
|
||||
|
||||
国内阿里云镜像加速
|
||||
|
||||
请确保执行下述命令前本机已安装Docker
|
||||
|
||||
特权模式+host网络
|
||||
|
||||
```shell
|
||||
docker run --rm --privileged --network host crpi-8tmognxgyb86bm61.cn-guangzhou.personal.cr.aliyuncs.com/oneclickvirt/ecs:latest -menu=false -l zh
|
||||
```
|
||||
|
||||
非特权模式+非host网络
|
||||
|
||||
```shell
|
||||
docker run --rm crpi-8tmognxgyb86bm61.cn-guangzhou.personal.cr.aliyuncs.com/oneclickvirt/ecs:latest -menu=false -l zh
|
||||
```
|
||||
|
||||
实际上还有CNB镜像地址 https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs 但很可惜组织空间不足无法推送了,更推荐使用阿里云镜像加速
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
### 从源码进行编译
|
||||
|
||||
<details>
|
||||
<summary>展开查看编译说明</summary>
|
||||
|
||||
1. 克隆仓库的 public 分支(不含私有依赖)
|
||||
```bash
|
||||
git clone -b public https://github.com/oneclickvirt/ecs.git
|
||||
cd ecs
|
||||
```
|
||||
|
||||
2. 安装 Go 环境(如已安装可跳过)
|
||||
|
||||
选择 go 1.25.4 的版本进行安装
|
||||
|
||||
```bash
|
||||
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/go.sh -o go.sh && chmod +x go.sh && bash go.sh
|
||||
```
|
||||
|
||||
3. 编译
|
||||
```bash
|
||||
go build -o goecs
|
||||
```
|
||||
|
||||
4. 运行测试
|
||||
```bash
|
||||
./goecs -menu=false -l zh
|
||||
```
|
||||
|
||||
支持的编译参数:
|
||||
- GOOS:支持 linux、windows、darwin、freebsd、openbsd
|
||||
- GOARCH:支持 amd64、arm、arm64、386、mips、mipsle、s390x、riscv64
|
||||
|
||||
跨平台编译示例:
|
||||
```bash
|
||||
# 编译 Windows 版本
|
||||
GOOS=windows GOARCH=amd64 go build -o goecs.exe
|
||||
# 编译 MacOS 版本
|
||||
GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
|
||||
```
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## QA
|
||||
|
||||
#### Q: 为什么默认使用sysbench而不是geekbench
|
||||
|
||||
#### A: 比较二者特点
|
||||
|
||||
| 比较项 | sysbench | geekbench |
|
||||
|------------------|----------|-----------|
|
||||
| 适用范围 | 轻量级,几乎可在任何服务器上运行 | 重量级,小型机器无法运行 |
|
||||
| 测试要求 | 无需网络,无特殊硬件需求 | 需联网,IPV4环境,至少1G内存 |
|
||||
| 开源情况 | 基于LUA,开源,可自行编译各架构版本 | 官方二进制闭源代码,不支持自行编译 |
|
||||
| 测试稳定性 | 核心测试组件10年以上未变 | 每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU) |
|
||||
| 测试内容 | 仅测试计算性能 | 覆盖多种性能测试,分数加权计算,但部分测试实际不常用 |
|
||||
| 适用场景 | 适合快速测试,仅测试计算性能 | 适合综合全面的测试 |
|
||||
| 排行榜 | [sysbench.spiritlhl.net](https://sysbench.spiritlhl.net/) | [browser.geekbench.com](https://browser.geekbench.com/) |
|
||||
|
||||
且```goecs```测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求
|
||||
|
||||
#### Q: 为什么使用Golang而不是Rust重构
|
||||
|
||||
#### A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,~~我懒得搞~~我没那个技术力
|
||||
|
||||
#### Q: 为什么不继续开发Shell版本而是选择重构
|
||||
|
||||
#### A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)
|
||||
|
||||
#### Q: 每个测试项目的说明有吗?
|
||||
|
||||
#### A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明
|
||||
|
||||
#### Q: 测试进行到一半如何手动终止?
|
||||
|
||||
#### A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。
|
||||
|
||||
#### Q: 非Root环境如何进行测试?
|
||||
|
||||
#### A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。
|
||||
|
||||
## 致谢
|
||||
|
||||
感谢
|
||||
[DKLYDataHub - IP Geolocation Data](https://data.dkly.net)
|
||||
[he.net](https://he.net) [bgp.tools](https://bgp.tools) [ipinfo.io](https://ipinfo.io) [maxmind.com](https://www.maxmind.com/en/home) [cloudflare.com](https://www.cloudflare.com/) [ip.sb](https://ip.sb) [scamalytics.com](https://scamalytics.com) [abuseipdb.com](https://www.abuseipdb.com/) [ip2location.com](https://ip2location.com/) [ip-api.com](https://ip-api.com) [ipregistry.co](https://ipregistry.co/) [ipdata.co](https://ipdata.co/) [ipgeolocation.io](https://ipgeolocation.io) [ipwhois.io](https://ipwhois.io) [ipapi.com](https://ipapi.com/) [ipapi.is](https://ipapi.is/) [ipqualityscore.com](https://www.ipqualityscore.com/) [bigdatacloud.com](https://www.bigdatacloud.com/) [virustotal.com](https://www.virustotal.com/) [ipfighter.com](https://ipfighter.com/) [getipintel.net](http://check.getipintel.net/) [fraudlogix.com](https://fraudlogix.com) 等网站提供的API进行检测,感谢互联网各网站提供的查询资源
|
||||
|
||||
感谢
|
||||
|
||||
<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" style="height: 50px;">
|
||||
</a>
|
||||
|
||||
提供的免费托管支持本开源项目的共享测试结果存储
|
||||
|
||||
同时感谢以下平台提供编辑和测试支持
|
||||
|
||||
<a href="https://www.jetbrains.com/go/" target="_blank">
|
||||
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand.png" alt="goland" style="height: 50px;">
|
||||
</a>
|
||||
|
||||
<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" 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>
|
||||
|
||||
## History Usage
|
||||
|
||||

|
||||
|
||||
## Stargazers over time
|
||||
|
||||
[](https://www.spiritlhl.net)
|
||||
|
||||
## License
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Foneclickvirt%2Fecs?ref=badge_large)
|
||||
56
api/api.go
Normal file
56
api/api.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package api
|
||||
|
||||
const (
|
||||
// Version API版本号
|
||||
Version = "v1.0.0"
|
||||
|
||||
// DefaultVersion 默认的ECS版本号
|
||||
DefaultVersion = "v0.1.114"
|
||||
)
|
||||
|
||||
// 测试方法常量
|
||||
const (
|
||||
// CPU测试方法
|
||||
CpuMethodSysbench = "sysbench"
|
||||
CpuMethodGeekbench = "geekbench"
|
||||
CpuMethodWinsat = "winsat"
|
||||
|
||||
// 内存测试方法
|
||||
MemoryMethodStream = "stream"
|
||||
MemoryMethodSysbench = "sysbench"
|
||||
MemoryMethodDD = "dd"
|
||||
MemoryMethodWinsat = "winsat"
|
||||
|
||||
// 硬盘测试方法
|
||||
DiskMethodFio = "fio"
|
||||
DiskMethodDD = "dd"
|
||||
DiskMethodWinsat = "winsat"
|
||||
|
||||
// 线程模式
|
||||
ThreadModeSingle = "single"
|
||||
ThreadModeMulti = "multi"
|
||||
|
||||
// 语言选项
|
||||
LanguageZH = "zh"
|
||||
LanguageEN = "en"
|
||||
|
||||
// IP检测类型
|
||||
CheckTypeIPv4 = "ipv4"
|
||||
CheckTypeIPv6 = "ipv6"
|
||||
CheckTypeAuto = "auto"
|
||||
|
||||
// 测速平台
|
||||
PlatformCN = "cn"
|
||||
PlatformNet = "net"
|
||||
|
||||
// 运营商类型
|
||||
OperatorCMCC = "cmcc" // 中国移动
|
||||
OperatorCU = "cu" // 中国联通
|
||||
OperatorCT = "ct" // 中国电信
|
||||
OperatorGlobal = "global" // 全球节点
|
||||
OperatorOther = "other" // 其他
|
||||
OperatorHK = "hk" // 香港
|
||||
OperatorTW = "tw" // 台湾
|
||||
OperatorJP = "jp" // 日本
|
||||
OperatorSG = "sg" // 新加坡
|
||||
)
|
||||
266
api/config.go
Normal file
266
api/config.go
Normal file
@@ -0,0 +1,266 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/oneclickvirt/ecs/internal/params"
|
||||
)
|
||||
|
||||
// Config 配置接口,导出用于外部调用
|
||||
type Config = params.Config
|
||||
|
||||
// NewConfig 创建默认配置
|
||||
// version: 版本号字符串
|
||||
func NewConfig(version string) *Config {
|
||||
return params.NewConfig(version)
|
||||
}
|
||||
|
||||
// NewDefaultConfig 创建默认配置(使用默认版本号)
|
||||
func NewDefaultConfig() *Config {
|
||||
return params.NewConfig("v0.1.114")
|
||||
}
|
||||
|
||||
// ConfigOption 配置选项函数类型
|
||||
type ConfigOption func(*Config)
|
||||
|
||||
// WithLanguage 设置语言
|
||||
func WithLanguage(lang string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.Language = lang
|
||||
}
|
||||
}
|
||||
|
||||
// WithCpuTestMethod 设置CPU测试方法
|
||||
// method: "sysbench" 或 "geekbench"
|
||||
func WithCpuTestMethod(method string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.CpuTestMethod = method
|
||||
}
|
||||
}
|
||||
|
||||
// WithCpuTestThreadMode 设置CPU测试线程模式
|
||||
// mode: "single" 或 "multi"
|
||||
func WithCpuTestThreadMode(mode string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.CpuTestThreadMode = mode
|
||||
}
|
||||
}
|
||||
|
||||
// WithMemoryTestMethod 设置内存测试方法
|
||||
// method: "stream", "sysbench", "dd"
|
||||
func WithMemoryTestMethod(method string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.MemoryTestMethod = method
|
||||
}
|
||||
}
|
||||
|
||||
// WithDiskTestMethod 设置硬盘测试方法
|
||||
// method: "fio" 或 "dd"
|
||||
func WithDiskTestMethod(method string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.DiskTestMethod = method
|
||||
}
|
||||
}
|
||||
|
||||
// WithDiskTestPath 设置硬盘测试路径
|
||||
func WithDiskTestPath(path string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.DiskTestPath = path
|
||||
}
|
||||
}
|
||||
|
||||
// WithDiskMultiCheck 设置是否进行硬盘多路径检测
|
||||
func WithDiskMultiCheck(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.DiskMultiCheck = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithSpeedTestNum 设置测速节点数量
|
||||
func WithSpeedTestNum(num int) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.SpNum = num
|
||||
}
|
||||
}
|
||||
|
||||
// WithWidth 设置输出宽度
|
||||
func WithWidth(width int) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.Width = width
|
||||
}
|
||||
}
|
||||
|
||||
// WithFilePath 设置输出文件路径
|
||||
func WithFilePath(path string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.FilePath = path
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnableUpload 设置是否启用上传
|
||||
func WithEnableUpload(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.EnableUpload = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithAnalyzeResult 设置是否启用测试后结果总结分析
|
||||
func WithAnalyzeResult(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.AnalyzeResult = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnableLogger 设置是否启用日志
|
||||
func WithEnableLogger(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.EnableLogger = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithBasicTest 设置是否执行基础信息测试
|
||||
func WithBasicTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.BasicStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithCpuTest 设置是否执行CPU测试
|
||||
func WithCpuTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.CpuTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithMemoryTest 设置是否执行内存测试
|
||||
func WithMemoryTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.MemoryTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithDiskTest 设置是否执行硬盘测试
|
||||
func WithDiskTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.DiskTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithUnlockTest 设置是否执行流媒体解锁测试
|
||||
func WithUnlockTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.UtTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithSecurityTest 设置是否执行IP质量测试
|
||||
func WithSecurityTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.SecurityTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithEmailTest 设置是否执行邮件端口测试
|
||||
func WithEmailTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.EmailTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithBacktraceTest 设置是否执行回程路由测试
|
||||
func WithBacktraceTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.BacktraceStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithNt3Test 设置是否执行三网路由测试
|
||||
func WithNt3Test(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.Nt3Status = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithSpeedTest 设置是否执行测速测试
|
||||
func WithSpeedTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.SpeedTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithPingTest 设置是否执行PING测试
|
||||
func WithPingTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.PingTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithTgdcTest 设置是否执行Telegram DC测试
|
||||
func WithTgdcTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.TgdcTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithWebTest 设置是否执行网站测试
|
||||
func WithWebTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.WebTestStatus = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithNt3CheckType 设置三网路由检测类型
|
||||
// checkType: "ipv4", "ipv6" 或 "auto"
|
||||
func WithNt3CheckType(checkType string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.Nt3CheckType = checkType
|
||||
}
|
||||
}
|
||||
|
||||
// WithNt3Location 设置三网路由检测位置
|
||||
func WithNt3Location(location string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.Nt3Location = location
|
||||
}
|
||||
}
|
||||
|
||||
// WithAutoChangeDiskMethod 设置是否自动切换硬盘测试方法
|
||||
func WithAutoChangeDiskMethod(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.AutoChangeDiskMethod = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithOnlyChinaTest 设置是否只进行国内测试
|
||||
func WithOnlyChinaTest(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.OnlyChinaTest = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithMenuMode 设置是否启用菜单模式
|
||||
func WithMenuMode(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.MenuMode = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithOnlyIpInfoCheck 设置是否只进行IP信息检测
|
||||
func WithOnlyIpInfoCheck(enable bool) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.OnlyIpInfoCheck = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithChoice 设置菜单选择
|
||||
func WithChoice(choice string) ConfigOption {
|
||||
return func(c *Config) {
|
||||
c.Choice = choice
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyOptions 应用配置选项
|
||||
func ApplyOptions(config *Config, options ...ConfigOption) *Config {
|
||||
for _, opt := range options {
|
||||
opt(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
27
api/menu.go
Normal file
27
api/menu.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/oneclickvirt/ecs/internal/menu"
|
||||
"github.com/oneclickvirt/ecs/utils"
|
||||
)
|
||||
|
||||
// GetMenuChoice 获取用户菜单选择
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// 返回: 用户选择的选项
|
||||
func GetMenuChoice(language string) string {
|
||||
return menu.GetMenuChoice(language)
|
||||
}
|
||||
|
||||
// PrintMenuOptions 打印菜单选项
|
||||
// preCheck: 网络检查结果
|
||||
// config: 配置对象
|
||||
func PrintMenuOptions(preCheck utils.NetCheckResult, config *Config) {
|
||||
menu.PrintMenuOptions(preCheck, config)
|
||||
}
|
||||
|
||||
// HandleMenuMode 处理菜单模式
|
||||
// preCheck: 网络检查结果
|
||||
// config: 配置对象
|
||||
func HandleMenuMode(preCheck utils.NetCheckResult, config *Config) {
|
||||
menu.HandleMenuMode(preCheck, config)
|
||||
}
|
||||
190
api/runner.go
Normal file
190
api/runner.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/oneclickvirt/ecs/internal/runner"
|
||||
"github.com/oneclickvirt/ecs/utils"
|
||||
)
|
||||
|
||||
// RunResult 运行结果
|
||||
type RunResult struct {
|
||||
Output string // 完整输出
|
||||
Duration time.Duration // 运行时长
|
||||
StartTime time.Time // 开始时间
|
||||
EndTime time.Time // 结束时间
|
||||
}
|
||||
|
||||
// RunAllTests 执行所有测试(高级接口)
|
||||
// preCheck: 网络检查结果
|
||||
// config: 配置对象
|
||||
// 返回: 运行结果
|
||||
func RunAllTests(preCheck utils.NetCheckResult, config *Config) *RunResult {
|
||||
var (
|
||||
wg1, wg2, wg3 sync.WaitGroup
|
||||
basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo string
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
infoMutex sync.Mutex
|
||||
)
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
switch config.Language {
|
||||
case "zh":
|
||||
runner.RunChineseTests(preCheck, config, &wg1, &wg2, &wg3,
|
||||
&basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo,
|
||||
&output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
case "en":
|
||||
runner.RunEnglishTests(preCheck, config, &wg1, &wg2, &wg3,
|
||||
&basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo,
|
||||
&output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
default:
|
||||
runner.RunChineseTests(preCheck, config, &wg1, &wg2, &wg3,
|
||||
&basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo,
|
||||
&output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
}
|
||||
if config.AnalyzeResult {
|
||||
output = runner.AppendAnalysisSummary(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
endTime := time.Now()
|
||||
|
||||
return &RunResult{
|
||||
Output: output,
|
||||
Duration: endTime.Sub(startTime),
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
}
|
||||
}
|
||||
|
||||
// RunBasicTests 运行基础信息测试
|
||||
func RunBasicTests(preCheck utils.NetCheckResult, config *Config) string {
|
||||
var (
|
||||
basicInfo, securityInfo string
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunBasicTests(preCheck, config, &basicInfo, &securityInfo, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunCPUTest 运行CPU测试
|
||||
func RunCPUTest(config *Config) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunCPUTest(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunMemoryTest 运行内存测试
|
||||
func RunMemoryTest(config *Config) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunMemoryTest(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunDiskTest 运行硬盘测试
|
||||
func RunDiskTest(config *Config) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunDiskTest(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunIpInfoCheck 执行IP信息检测
|
||||
func RunIpInfoCheck(config *Config) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunIpInfoCheck(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunStreamingTests 运行流媒体测试
|
||||
func RunStreamingTests(config *Config, mediaInfo string) string {
|
||||
var (
|
||||
wg1 sync.WaitGroup
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
infoMutex sync.Mutex
|
||||
)
|
||||
return runner.RunStreamingTests(config, &wg1, &mediaInfo, output, tempOutput, &outputMutex, &infoMutex)
|
||||
}
|
||||
|
||||
// RunSecurityTests 运行安全测试
|
||||
func RunSecurityTests(config *Config, securityInfo string) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunSecurityTests(config, securityInfo, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunEmailTests 运行邮件端口测试
|
||||
func RunEmailTests(config *Config, emailInfo string) string {
|
||||
var (
|
||||
wg2 sync.WaitGroup
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
infoMutex sync.Mutex
|
||||
)
|
||||
return runner.RunEmailTests(config, &wg2, &emailInfo, output, tempOutput, &outputMutex, &infoMutex)
|
||||
}
|
||||
|
||||
// RunNetworkTests 运行网络测试(中文模式)
|
||||
func RunNetworkTests(config *Config, ptInfo string) string {
|
||||
var (
|
||||
wg3 sync.WaitGroup
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
infoMutex sync.Mutex
|
||||
)
|
||||
return runner.RunNetworkTests(config, &wg3, &ptInfo, output, tempOutput, &outputMutex, &infoMutex)
|
||||
}
|
||||
|
||||
// RunSpeedTests 运行测速测试(中文模式)
|
||||
func RunSpeedTests(config *Config) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunSpeedTests(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunEnglishNetworkTests 运行网络测试(英文模式)
|
||||
func RunEnglishNetworkTests(config *Config, ptInfo string) string {
|
||||
var (
|
||||
wg3 sync.WaitGroup
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunEnglishNetworkTests(config, &wg3, &ptInfo, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// RunEnglishSpeedTests 运行测速测试(英文模式)
|
||||
func RunEnglishSpeedTests(config *Config) string {
|
||||
var (
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.RunEnglishSpeedTests(config, output, tempOutput, &outputMutex)
|
||||
}
|
||||
|
||||
// AppendTimeInfo 添加时间信息
|
||||
func AppendTimeInfo(config *Config, output string, startTime time.Time) string {
|
||||
var (
|
||||
tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
)
|
||||
return runner.AppendTimeInfo(config, output, tempOutput, startTime, &outputMutex)
|
||||
}
|
||||
|
||||
// HandleUploadResults 处理上传结果
|
||||
func HandleUploadResults(config *Config, output string) {
|
||||
runner.HandleUploadResults(config, output)
|
||||
}
|
||||
101
api/tests.go
Normal file
101
api/tests.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/oneclickvirt/ecs/internal/tests"
|
||||
)
|
||||
|
||||
// TestResult 测试结果结构
|
||||
type TestResult struct {
|
||||
TestMethod string // 实际使用的测试方法
|
||||
Output string // 测试输出结果
|
||||
Success bool // 是否成功
|
||||
Error error // 错误信息
|
||||
}
|
||||
|
||||
// CpuTest CPU测试公共接口
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// testMethod: 测试方法 ("sysbench" 或 "geekbench")
|
||||
// testThread: 线程模式 ("single" 或 "multi")
|
||||
// 返回: (实际测试方法, 测试结果)
|
||||
func CpuTest(language, testMethod, testThread string) (string, string) {
|
||||
return tests.CpuTest(language, testMethod, testThread)
|
||||
}
|
||||
|
||||
// MemoryTest 内存测试公共接口
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// testMethod: 测试方法 ("stream", "sysbench", "dd")
|
||||
// 返回: (实际测试方法, 测试结果)
|
||||
func MemoryTest(language, testMethod string) (string, string) {
|
||||
return tests.MemoryTest(language, testMethod)
|
||||
}
|
||||
|
||||
// DiskTest 硬盘测试公共接口
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// testMethod: 测试方法 ("fio" 或 "dd")
|
||||
// testPath: 测试路径
|
||||
// isMultiCheck: 是否多路径检测
|
||||
// autoChange: 是否自动切换方法
|
||||
// 返回: (实际测试方法, 测试结果)
|
||||
func DiskTest(language, testMethod, testPath string, isMultiCheck, autoChange bool) (string, string) {
|
||||
return tests.DiskTest(language, testMethod, testPath, isMultiCheck, autoChange)
|
||||
}
|
||||
|
||||
// MediaTest 流媒体解锁测试公共接口
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// 返回: 测试结果
|
||||
func MediaTest(language string) string {
|
||||
return tests.MediaTest(language)
|
||||
}
|
||||
|
||||
// SpeedTestShowHead 显示测速表头
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
func SpeedTestShowHead(language string) {
|
||||
tests.ShowHead(language)
|
||||
}
|
||||
|
||||
// SpeedTestNearby 就近节点测速
|
||||
func SpeedTestNearby() {
|
||||
tests.NearbySP()
|
||||
}
|
||||
|
||||
// SpeedTestCustom 自定义测速
|
||||
// platform: 平台 ("cn" 或 "net")
|
||||
// operator: 运营商 ("cmcc", "cu", "ct", "global", "other" 等)
|
||||
// num: 测试节点数量
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
func SpeedTestCustom(platform, operator string, num int, language string) {
|
||||
tests.CustomSP(platform, operator, num, language)
|
||||
}
|
||||
|
||||
// NextTrace3Check 三网路由追踪测试
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// location: 位置
|
||||
// checkType: 检测类型 ("ipv4", "ipv6")
|
||||
func NextTrace3Check(language, location, checkType string) {
|
||||
tests.NextTrace3Check(language, location, checkType)
|
||||
}
|
||||
|
||||
// UpstreamsCheck 上游及回程线路检测
|
||||
func UpstreamsCheck(language string) {
|
||||
tests.UpstreamsCheck(language)
|
||||
}
|
||||
|
||||
// GetIPv4Address 获取当前IPv4地址
|
||||
func GetIPv4Address() string {
|
||||
return tests.IPV4
|
||||
}
|
||||
|
||||
// GetIPv6Address 获取当前IPv6地址
|
||||
func GetIPv6Address() string {
|
||||
return tests.IPV6
|
||||
}
|
||||
|
||||
// SetIPv4Address 设置IPv4地址(用于测试)
|
||||
func SetIPv4Address(ipv4 string) {
|
||||
tests.IPV4 = ipv4
|
||||
}
|
||||
|
||||
// SetIPv6Address 设置IPv6地址(用于测试)
|
||||
func SetIPv6Address(ipv6 string) {
|
||||
tests.IPV6 = ipv6
|
||||
}
|
||||
91
api/utils.go
Normal file
91
api/utils.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/oneclickvirt/ecs/utils"
|
||||
)
|
||||
|
||||
// NetCheckResult 网络检查结果
|
||||
type NetCheckResult = utils.NetCheckResult
|
||||
|
||||
// StatsResponse 统计信息响应
|
||||
type StatsResponse = utils.StatsResponse
|
||||
|
||||
// GitHubRelease GitHub发布信息
|
||||
type GitHubRelease = utils.GitHubRelease
|
||||
|
||||
// CheckPublicAccess 检查公网访问能力
|
||||
// timeout: 超时时间
|
||||
// 返回: 网络检查结果
|
||||
func CheckPublicAccess(timeout time.Duration) NetCheckResult {
|
||||
return utils.CheckPublicAccess(timeout)
|
||||
}
|
||||
|
||||
// GetGoescStats 获取goecs统计信息
|
||||
// 返回: (统计响应, 错误)
|
||||
func GetGoescStats() (*StatsResponse, error) {
|
||||
return utils.GetGoescStats()
|
||||
}
|
||||
|
||||
// GetLatestEcsRelease 获取最新的ECS版本信息
|
||||
// 返回: (GitHub发布信息, 错误)
|
||||
func GetLatestEcsRelease() (*GitHubRelease, error) {
|
||||
return utils.GetLatestEcsRelease()
|
||||
}
|
||||
|
||||
// PrintHead 打印程序头部信息
|
||||
// language: 语言 ("zh" 或 "en")
|
||||
// width: 显示宽度
|
||||
// version: 版本号
|
||||
func PrintHead(language string, width int, version string) {
|
||||
utils.PrintHead(language, width, version)
|
||||
}
|
||||
|
||||
// PrintCenteredTitle 打印居中标题
|
||||
// title: 标题文本
|
||||
// width: 显示宽度
|
||||
func PrintCenteredTitle(title string, width int) {
|
||||
utils.PrintCenteredTitle(title, width)
|
||||
}
|
||||
|
||||
// ProcessAndUpload 处理并上传结果
|
||||
// output: 输出内容
|
||||
// filePath: 文件路径
|
||||
// enableUpload: 是否启用上传
|
||||
// 返回: (HTTP URL, HTTPS URL)
|
||||
func ProcessAndUpload(output, filePath string, enableUpload bool, language string) (string, string) {
|
||||
return utils.ProcessAndUpload(output, filePath, enableUpload, language)
|
||||
}
|
||||
|
||||
// BasicsAndSecurityCheck 基础信息和安全检查
|
||||
// language: 语言
|
||||
// checkType: 检查类型
|
||||
// securityTestStatus: 是否执行安全测试
|
||||
// 返回: (IPv4地址, IPv6地址, 基础信息, 安全信息, 检查类型)
|
||||
func BasicsAndSecurityCheck(language, checkType string, securityTestStatus bool) (string, string, string, string, string) {
|
||||
return utils.BasicsAndSecurityCheck(language, checkType, securityTestStatus)
|
||||
}
|
||||
|
||||
// OnlyBasicsIpInfo 仅获取基础IP信息
|
||||
// language: 语言
|
||||
// 返回: (IPv4地址, IPv6地址, IP信息)
|
||||
func OnlyBasicsIpInfo(language string) (string, string, string) {
|
||||
return utils.OnlyBasicsIpInfo(language)
|
||||
}
|
||||
|
||||
// FormatGoecsNumber 格式化数字显示
|
||||
// num: 数字
|
||||
// 返回: 格式化后的字符串
|
||||
func FormatGoecsNumber(num int) string {
|
||||
return utils.FormatGoecsNumber(num)
|
||||
}
|
||||
|
||||
// PrintAndCapture 打印并捕获输出
|
||||
// fn: 执行的函数
|
||||
// tempOutput: 临时输出
|
||||
// existingOutput: 现有输出
|
||||
// 返回: 捕获的输出
|
||||
func PrintAndCapture(fn func(), tempOutput, existingOutput string) string {
|
||||
return utils.PrintAndCapture(fn, tempOutput, existingOutput)
|
||||
}
|
||||
35
go.mod
35
go.mod
@@ -3,8 +3,11 @@ module github.com/oneclickvirt/ecs
|
||||
go 1.25.4
|
||||
|
||||
require (
|
||||
github.com/charmbracelet/bubbles v1.0.0
|
||||
github.com/charmbracelet/bubbletea v1.3.10
|
||||
github.com/charmbracelet/lipgloss v1.1.0
|
||||
github.com/imroc/req/v3 v3.54.0
|
||||
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725
|
||||
github.com/oneclickvirt/UnlockTests v0.0.35-20260207053956
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457
|
||||
github.com/oneclickvirt/basics v0.0.16-20251112033526
|
||||
github.com/oneclickvirt/cputest v0.0.12-20251111095842
|
||||
@@ -15,7 +18,8 @@ require (
|
||||
github.com/oneclickvirt/nt3 v0.0.11-20260112140912
|
||||
github.com/oneclickvirt/pingtest v0.0.9-20251104112920
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900
|
||||
github.com/oneclickvirt/security v0.0.8-20251112080734
|
||||
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218
|
||||
github.com/oneclickvirt/security v0.0.8-20260202071316
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740
|
||||
)
|
||||
|
||||
@@ -24,11 +28,21 @@ require (
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.4.1 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.6 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/ebitengine/purego v0.8.4 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-ole/go-ole v1.3.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
|
||||
@@ -41,26 +55,30 @@ require (
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jaypipes/ghw v0.17.0 // indirect
|
||||
github.com/jaypipes/pcidb v1.0.1 // indirect
|
||||
github.com/jsdelivr/globalping-cli v1.5.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // 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
|
||||
github.com/lionsoul2014/ip2region v2.11.2+incompatible // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||
github.com/miekg/dns v1.1.61 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/nxtrace/NTrace-core v1.5.0 // indirect
|
||||
github.com/oneclickvirt/dd v0.0.2-20250808062818 // indirect
|
||||
github.com/oneclickvirt/fio v0.0.2-20250808045755 // indirect
|
||||
github.com/oneclickvirt/mbw v0.0.1-20250808061222 // indirect
|
||||
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218 // indirect
|
||||
github.com/oneclickvirt/stream v0.0.2-20250924154001 // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.13.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
@@ -82,7 +100,6 @@ require (
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
|
||||
github.com/showwin/speedtest-go v1.7.10 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
@@ -92,11 +109,11 @@ require (
|
||||
github.com/tidwall/match v1.2.0 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.8.0 // indirect
|
||||
github.com/tklauser/numcpus v0.9.0 // indirect
|
||||
github.com/tsosunchia/powclient v0.2.0 // indirect
|
||||
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
|
||||
111
go.sum
111
go.sum
@@ -6,6 +6,40 @@ github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwTo
|
||||
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/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
|
||||
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
|
||||
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
|
||||
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
|
||||
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
||||
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
|
||||
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
|
||||
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
|
||||
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
|
||||
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
|
||||
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
||||
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||
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=
|
||||
@@ -14,6 +48,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||
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/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
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=
|
||||
@@ -21,8 +57,9 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
|
||||
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/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-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
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=
|
||||
@@ -56,9 +93,10 @@ github.com/jaypipes/ghw v0.17.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51M
|
||||
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/jsdelivr/globalping-cli v1.5.1 h1:7RZNmIljSBXe0xBeOoGQHXZNwHo6zDuQ0BI9hF12gLY=
|
||||
github.com/jsdelivr/globalping-cli v1.5.1/go.mod h1:Gw70OWvN6hIt0t4hftyUhcHuJQMTn4CvoobJiaTU0qg=
|
||||
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.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=
|
||||
@@ -71,16 +109,22 @@ github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
|
||||
github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
|
||||
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
|
||||
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
|
||||
github.com/lionsoul2014/ip2region v2.11.2+incompatible h1:+VRsGcrHz8ewXI/2UzTptJlACsxD/p4xCxuql4u2nKU=
|
||||
github.com/lionsoul2014/ip2region v2.11.2+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
|
||||
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
@@ -92,12 +136,16 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
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/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||
github.com/nxtrace/NTrace-core v1.5.0 h1:n+a/FObw/+CcqvhuSQiWcm1q+ODtfo7Wt3VmaIx504I=
|
||||
github.com/nxtrace/NTrace-core v1.5.0/go.mod h1:/jME48iJ7QaVTzsrTPQyTJ+yExhjeWjax2L6uBd4ckk=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725 h1:VaaK2v17nLGU8FQmJRXPe2bEESzRePbGws0bfq7s/2o=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.35-20260207053956 h1:yccGrw/sYOHZMaFJghPVN3Xn6JyTOXsEQc9v0I92k3M=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.35-20260207053956/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-20251112033526 h1:bgoLaqStV3a6mbPiM++0mYizd278GVa6J6yeIiusV+A=
|
||||
@@ -118,20 +166,16 @@ 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-20251218032900 h1:SmRFfPLyGfTVWIgC50lEGgOpbqahtMHIlyOMSbrhj9Y=
|
||||
github.com/oneclickvirt/memorytest v0.0.10-20251218032900/go.mod h1:4kiHsEWkW9r3/1ZcV5xIweU0smiKP0IRfQj74AUIiVI=
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251111095706 h1:GEdgL6oAWXY80NIq23mLjcTR3gvLGh9iusFzJK6SoDo=
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251111095706/go.mod h1:yo1ufkduFt9QjqG7nqSUf1D3YlQOmFpdlTYniJfclQI=
|
||||
github.com/oneclickvirt/nt3 v0.0.11-20260112140912 h1:e3tgkEmydsML6ziOdWwsVGwysTRYS82SuWrP0HnIw9g=
|
||||
github.com/oneclickvirt/nt3 v0.0.11-20260112140912/go.mod h1:u/y3sMhyt4wiQlR7yS68CudwjXCa/4V6ozWI7awsCws=
|
||||
github.com/oneclickvirt/pingtest v0.0.9-20251104112920 h1:j3Fjhy0YHT/VF7iuAVVELaRXkquvRd64tWWfFLJs01o=
|
||||
github.com/oneclickvirt/pingtest v0.0.9-20251104112920/go.mod h1:gxwsxxwitNQiGq2OI0ZogYoOLwc8DtuOdSRe6/EvRqs=
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900 h1:AomzdppSOFB70AJESQhlp0IPbsHTTJGimAWDk2TzCWM=
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900/go.mod h1:9sjMDPCd4Z40wkYB0S9gQPGH8YPtnNE1ZJthVIuHUzA=
|
||||
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112095218 h1:VcglFz85LVPo8wE8AkBhgXHHUUVI2Ae9ng6+hY6ewx4=
|
||||
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112095218/go.mod h1:IXOlKKX4DUNqxOaW/K9bcdrBiWxo0jGSLXeBeo7NrTo=
|
||||
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218 h1:h2k2fHtrsIIP/x/apEWkQGlTKuIumz8GrUR/df41YhE=
|
||||
github.com/oneclickvirt/privatespeedtest v0.0.1-20260112130218/go.mod h1:IXOlKKX4DUNqxOaW/K9bcdrBiWxo0jGSLXeBeo7NrTo=
|
||||
github.com/oneclickvirt/security v0.0.8-20251112080734 h1:WpwdGbwpiBP2YA1lNsymati5uvBbWFlN9CXHYgd3/fE=
|
||||
github.com/oneclickvirt/security v0.0.8-20251112080734/go.mod h1:aPMIwqsz7wiUH1cqvtRr9+QcQRkKzlUWecDM6SGVddc=
|
||||
github.com/oneclickvirt/security v0.0.8-20260202071316 h1:ULZWXC99IzrdFEG05D2/MQklKAhztQNc6UYCE3fEQeU=
|
||||
github.com/oneclickvirt/security v0.0.8-20260202071316/go.mod h1:aPMIwqsz7wiUH1cqvtRr9+QcQRkKzlUWecDM6SGVddc=
|
||||
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=
|
||||
@@ -161,8 +205,6 @@ 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.53.0 h1:QHX46sISpG2S03dPeZBgVIZp8dGagIaiu2FiVYvpCZI=
|
||||
github.com/quic-go/quic-go v0.53.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
|
||||
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
|
||||
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
|
||||
@@ -174,12 +216,8 @@ github.com/rodaine/table v1.3.0 h1:4/3S3SVkHnVZX91EHFvAMV7K42AnJ0XuymRR2C5HlGE=
|
||||
github.com/rodaine/table v1.3.0/go.mod h1:47zRsHar4zw0jgxGxL9YtFfs7EGN6B/TaS+/Dmk4WxU=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
|
||||
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
|
||||
github.com/schollz/progressbar/v3 v3.14.4 h1:W9ZrDSJk7eqmQhd3uxFNNcTr0QL+xuGNI9dEMrw0r74=
|
||||
github.com/schollz/progressbar/v3 v3.14.4/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
|
||||
github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
|
||||
github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
@@ -188,8 +226,6 @@ github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dI
|
||||
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.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
@@ -214,7 +250,6 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
|
||||
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
@@ -223,12 +258,14 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
|
||||
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
|
||||
github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI=
|
||||
github.com/tsosunchia/powclient v0.2.0 h1:BDrI3O69CbzarbD+CnnY10Kuwn8xlmtQR0m5tBp+BG8=
|
||||
github.com/tsosunchia/powclient v0.2.0/go.mod h1:fkb7tTW+HMH3ZWZzQUgwvvFKMj/8Ys+C8Sm/uGQzDA0=
|
||||
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f h1:glX3VZCYwW1/OmFxOjazfCtBLxXB3YNZk9LF2lYx+Lw=
|
||||
github.com/xjasonlyu/windivert-go v0.0.0-20201010013527-4239d0afa76f/go.mod h1:gh//RKyt2Gesx3eOj3ulzrSQ60ySj2UA4qnOdrtarvg=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
@@ -236,8 +273,6 @@ 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.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -251,16 +286,14 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -271,16 +304,12 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -290,16 +319,15 @@ golang.org/x/sys v0.0.0-20201008064518-c1f3e3309c71/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -308,9 +336,6 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -319,8 +344,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -328,8 +351,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
6
goecs.go
6
goecs.go
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ecsVersion = "v0.1.110" // 融合怪版本号
|
||||
ecsVersion = "v0.1.121" // 融合怪版本号
|
||||
configs = params.NewConfig(ecsVersion) // 全局配置实例
|
||||
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
|
||||
)
|
||||
@@ -63,6 +63,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
initLogger()
|
||||
utils.CheckAndFixAndroidDNS(configs.Language)
|
||||
preCheck := utils.CheckPublicAccess(3 * time.Second)
|
||||
go func() {
|
||||
if preCheck.Connected {
|
||||
@@ -98,6 +99,9 @@ func main() {
|
||||
default:
|
||||
fmt.Println("Unsupported language")
|
||||
}
|
||||
if configs.AnalyzeResult {
|
||||
output = runner.AppendAnalysisSummary(configs, output, tempOutput, &outputMutex)
|
||||
}
|
||||
if preCheck.Connected {
|
||||
runner.HandleUploadResults(configs, output)
|
||||
}
|
||||
|
||||
47
goecs.sh
47
goecs.sh
@@ -66,28 +66,28 @@ download_file() {
|
||||
}
|
||||
|
||||
check_china() {
|
||||
_yellow "正在检测IP所在区域......"
|
||||
_yellow "Detecting IP region......"
|
||||
if [ -z "${CN}" ]; then
|
||||
if curl -m 6 -s https://ipapi.co/json | grep -q 'China'; then
|
||||
_yellow "根据ipapi.co提供的信息,当前IP可能在中国"
|
||||
_yellow "According to ipapi.co, this IP may be located in China"
|
||||
if [ "$noninteractive" != "true" ]; then
|
||||
reading "是否使用中国镜像完成安装? ([y]/n) " input
|
||||
reading "Use China mirror for installation? ([y]/n) " input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY] | "")
|
||||
_green "已选择使用中国镜像"
|
||||
_green "China mirror selected"
|
||||
CN=true
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
_yellow "已选择不使用中国镜像"
|
||||
_yellow "China mirror not selected"
|
||||
CN=false
|
||||
;;
|
||||
*)
|
||||
_green "已选择使用中国镜像"
|
||||
_green "China mirror selected"
|
||||
CN=true
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# 在非交互模式下默认不使用中国镜像
|
||||
# In non-interactive mode, default to not using China mirror
|
||||
CN=false
|
||||
fi
|
||||
else
|
||||
@@ -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.108"
|
||||
ECS_VERSION="0.1.120"
|
||||
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.108"
|
||||
ECS_VERSION="0.1.108"
|
||||
_yellow "Unable to get version info, using default version 0.1.120"
|
||||
ECS_VERSION="0.1.120"
|
||||
fi
|
||||
version_output=""
|
||||
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do
|
||||
@@ -260,29 +260,36 @@ goecs_check() {
|
||||
fi
|
||||
rm -f goecs.zip README.md LICENSE README_EN.md
|
||||
chmod 777 goecs
|
||||
installed_to_system=false
|
||||
for install_path in "/usr/bin" "/usr/local/bin"; do
|
||||
if [ -d "$install_path" ]; then
|
||||
cp -f goecs "$install_path/"
|
||||
break
|
||||
if cp -f goecs "$install_path/" 2>/dev/null; then
|
||||
installed_to_system=true
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$installed_to_system" = "false" ]; then
|
||||
_yellow "Insufficient permissions to install to system path, goecs is kept in the current directory"
|
||||
_yellow "Please use the following command to run: ./goecs"
|
||||
fi
|
||||
if [ "$os" != "Darwin" ]; then
|
||||
PARAM="net.ipv4.ping_group_range"
|
||||
NEW_VALUE="0 2147483647"
|
||||
if [ -f /etc/sysctl.conf ]; then
|
||||
if grep -q "^$PARAM" /etc/sysctl.conf; then
|
||||
sed -i "s/^$PARAM.*/$PARAM = $NEW_VALUE/" /etc/sysctl.conf
|
||||
if grep -q "^$PARAM" /etc/sysctl.conf 2>/dev/null; then
|
||||
sed -i "s/^$PARAM.*/$PARAM = $NEW_VALUE/" /etc/sysctl.conf 2>/dev/null || true
|
||||
else
|
||||
echo "$PARAM = $NEW_VALUE" >> /etc/sysctl.conf
|
||||
echo "$PARAM = $NEW_VALUE" >> /etc/sysctl.conf 2>/dev/null || true
|
||||
fi
|
||||
sysctl -p >/dev/null 2>&1
|
||||
sysctl -p >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
setcap cap_net_raw=+ep goecs 2>/dev/null
|
||||
setcap cap_net_raw=+ep /usr/bin/goecs 2>/dev/null
|
||||
setcap cap_net_raw=+ep /usr/local/bin/goecs 2>/dev/null
|
||||
setcap cap_net_raw=+ep goecs 2>/dev/null || true
|
||||
setcap cap_net_raw=+ep /usr/bin/goecs 2>/dev/null || true
|
||||
setcap cap_net_raw=+ep /usr/local/bin/goecs 2>/dev/null || true
|
||||
_green "goecs installation complete, current version:"
|
||||
goecs -v || ./goecs -v
|
||||
goecs -v 2>/dev/null || ./goecs -v
|
||||
}
|
||||
|
||||
InstallSysbench() {
|
||||
|
||||
1024
internal/analysis/summary.go
Normal file
1024
internal/analysis/summary.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,24 +21,32 @@ func GetMenuChoice(language string) string {
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer signal.Stop(sigChan)
|
||||
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-sigChan:
|
||||
fmt.Println("\n程序在选择过程中被用户中断")
|
||||
if language == "zh" {
|
||||
fmt.Println("\n程序在选择过程中被用户中断")
|
||||
} else {
|
||||
fmt.Println("\nProgram interrupted by user during selection")
|
||||
}
|
||||
os.Exit(0)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
for {
|
||||
var input string
|
||||
fmt.Print("请输入选项 / Please enter your choice: ")
|
||||
if language == "zh" {
|
||||
fmt.Print("请输入选项: ")
|
||||
} else {
|
||||
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
|
||||
@@ -117,13 +125,13 @@ func PrintMenuOptions(preCheck utils.NetCheckResult, config *params.Config) {
|
||||
}
|
||||
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质量检测+上游及三网回程+广州三网回程详细路由+全国延迟+TGDC+网站延迟+测速节点11个)")
|
||||
fmt.Println("7. 解锁单项(跨国平台解锁)")
|
||||
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质量检测+上游及三网回程+广州三网回程详细路由+全国延迟+TGDC+网站延迟+测速节点11个)")
|
||||
fmt.Println("7. 解锁单项(跨国平台解锁)")
|
||||
fmt.Println("8. 硬件单项(系统信息+CPU+dd磁盘测试+fio磁盘测试)")
|
||||
fmt.Println("9. IP质量检测(15个数据库的IP质量检测+邮件端口检测)")
|
||||
fmt.Println("10. 三网回程线路检测+三网回程详细路由(北京上海广州成都)+全国延迟+TGDC+网站延迟")
|
||||
@@ -137,20 +145,20 @@ func PrintMenuOptions(preCheck utils.NetCheckResult, config *params.Config) {
|
||||
}
|
||||
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 + International Platform Unlock + Routing + 5 Speed Test Nodes)")
|
||||
fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + Backtrace + Routing + 5 Speed Test Nodes)")
|
||||
fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + International Platform Unlock + 5 Speed Test Nodes)")
|
||||
fmt.Println("6. Network-Only Test (IP Quality Test + Upstream & 3-Network Backtrace + Guangzhou 3-Network Detailed Routing + National Latency + TGDC + Websites + 11 Speed Test Nodes)")
|
||||
fmt.Println("7. Unlock-Only Test (International Platform 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")
|
||||
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 + International Platform Unlock + Routing + 5 Speed Test Nodes)")
|
||||
fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + Backtrace + Routing + 5 Speed Test Nodes)")
|
||||
fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + International Platform Unlock + 5 Speed Test Nodes)")
|
||||
fmt.Println("6. Network-Only Test (IP Quality Test + Upstream & 3-Network Backtrace + Guangzhou 3-Network Detailed Routing + National Latency + TGDC + Websites + 11 Speed Test Nodes)")
|
||||
fmt.Println("7. Unlock-Only Test (International Platform 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")
|
||||
}
|
||||
}
|
||||
|
||||
// HandleMenuMode handles menu selection
|
||||
// HandleMenuMode handles menu selection using the interactive TUI
|
||||
func HandleMenuMode(preCheck utils.NetCheckResult, config *params.Config) {
|
||||
savedParams := config.SaveUserSetParams()
|
||||
config.BasicStatus = false
|
||||
@@ -166,64 +174,52 @@ func HandleMenuMode(preCheck utils.NetCheckResult, config *params.Config) {
|
||||
config.TgdcTestStatus = false
|
||||
config.WebTestStatus = false
|
||||
config.AutoChangeDiskMethod = true
|
||||
PrintMenuOptions(preCheck, config)
|
||||
Loop:
|
||||
for {
|
||||
config.Choice = GetMenuChoice(config.Language)
|
||||
switch config.Choice {
|
||||
|
||||
result := RunTuiMenu(preCheck, config)
|
||||
if result.quit {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Update language if changed by TUI selection
|
||||
config.Language = result.language
|
||||
|
||||
if result.custom {
|
||||
config.Choice = "custom"
|
||||
applyCustomResult(result, preCheck, config)
|
||||
if config.SpeedTestStatus {
|
||||
config.OnlyChinaTest = utils.CheckChina(config.EnableLogger, config.Language)
|
||||
}
|
||||
} else {
|
||||
config.Choice = result.choice
|
||||
switch result.choice {
|
||||
case "0":
|
||||
os.Exit(0)
|
||||
case "1":
|
||||
SetFullTestStatus(preCheck, config)
|
||||
config.OnlyChinaTest = utils.CheckChina(config.EnableLogger)
|
||||
break Loop
|
||||
config.OnlyChinaTest = utils.CheckChina(config.EnableLogger, config.Language)
|
||||
case "2":
|
||||
SetMinimalTestStatus(preCheck, config)
|
||||
break Loop
|
||||
case "3":
|
||||
SetStandardTestStatus(preCheck, config)
|
||||
break Loop
|
||||
case "4":
|
||||
SetNetworkFocusedTestStatus(preCheck, config)
|
||||
break Loop
|
||||
case "5":
|
||||
SetUnlockFocusedTestStatus(preCheck, config)
|
||||
break Loop
|
||||
case "6":
|
||||
if !preCheck.Connected {
|
||||
fmt.Println("Can not test without network connection!")
|
||||
return
|
||||
}
|
||||
SetNetworkOnlyTestStatus(config)
|
||||
break Loop
|
||||
case "7":
|
||||
if !preCheck.Connected {
|
||||
fmt.Println("Can not test without network connection!")
|
||||
return
|
||||
}
|
||||
SetUnlockOnlyTestStatus(config)
|
||||
break Loop
|
||||
case "8":
|
||||
SetHardwareOnlyTestStatus(preCheck, config)
|
||||
break Loop
|
||||
case "9":
|
||||
if !preCheck.Connected {
|
||||
fmt.Println("Can not test without network connection!")
|
||||
return
|
||||
}
|
||||
SetIPQualityTestStatus(config)
|
||||
break Loop
|
||||
case "10":
|
||||
if !preCheck.Connected {
|
||||
fmt.Println("Can not test without network connection!")
|
||||
return
|
||||
}
|
||||
config.Nt3Location = "ALL"
|
||||
SetRouteTestStatus(config)
|
||||
break Loop
|
||||
default:
|
||||
PrintInvalidChoice(config.Language)
|
||||
}
|
||||
// Apply quick options set on the main menu page
|
||||
config.AnalyzeResult = result.mainAnalyze
|
||||
config.EnableUpload = result.mainUpload
|
||||
}
|
||||
config.RestoreUserSetParams(savedParams)
|
||||
}
|
||||
|
||||
1151
internal/menu/tui.go
Normal file
1151
internal/menu/tui.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ package params
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Config holds all configuration parameters
|
||||
@@ -41,6 +42,7 @@ type Config struct {
|
||||
AutoChangeDiskMethod bool
|
||||
FilePath string
|
||||
EnableUpload bool
|
||||
AnalyzeResult bool
|
||||
OnlyIpInfoCheck bool
|
||||
Help bool
|
||||
Finish bool
|
||||
@@ -64,7 +66,7 @@ func NewConfig(version string) *Config {
|
||||
MemoryTestMethod: "stream",
|
||||
DiskTestMethod: "fio",
|
||||
DiskTestPath: "",
|
||||
DiskMultiCheck: false,
|
||||
DiskMultiCheck: false,
|
||||
Nt3CheckType: "ipv4",
|
||||
SpNum: 2,
|
||||
Width: 82,
|
||||
@@ -84,6 +86,7 @@ func NewConfig(version string) *Config {
|
||||
AutoChangeDiskMethod: true,
|
||||
FilePath: "goecs.txt",
|
||||
EnableUpload: true,
|
||||
AnalyzeResult: false,
|
||||
OnlyIpInfoCheck: false,
|
||||
Help: false,
|
||||
Finish: false,
|
||||
@@ -92,8 +95,57 @@ func NewConfig(version string) *Config {
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeBoolArgs preprocesses args so that bool flags written as
|
||||
// "-flag true" or "-flag false" (space-separated) are converted to
|
||||
// "-flag=true" / "-flag=false" that the standard flag package understands.
|
||||
// This also strips any duplicate spaces that may appear between tokens when
|
||||
// args have been assembled by shell scripts or other callers.
|
||||
func normalizeBoolArgs(args []string) []string {
|
||||
// All known boolean flag names (without leading dash).
|
||||
boolFlags := map[string]bool{
|
||||
"h": true, "help": true, "v": true, "version": true,
|
||||
"menu": true, "basic": true, "cpu": true, "memory": true,
|
||||
"disk": true, "ut": true, "security": true, "email": true,
|
||||
"backtrace": true, "nt3": true, "speed": true, "ping": true,
|
||||
"tgdc": true, "web": true, "log": true, "upload": true,
|
||||
"analysis": true, "analyze": true,
|
||||
"diskmc": true,
|
||||
}
|
||||
|
||||
out := make([]string, 0, len(args))
|
||||
i := 0
|
||||
for i < len(args) {
|
||||
arg := args[i]
|
||||
// Skip empty tokens that can appear from split on multiple spaces.
|
||||
if arg == "" {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// Detect flag tokens: -flag or --flag (without embedded =).
|
||||
if strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") {
|
||||
name := strings.TrimLeft(arg, "-")
|
||||
if boolFlags[name] {
|
||||
// Peek at next token: if it is "true" or "false", merge.
|
||||
if i+1 < len(args) {
|
||||
next := strings.ToLower(strings.TrimSpace(args[i+1]))
|
||||
if next == "true" || next == "false" {
|
||||
out = append(out, arg+"="+next)
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out = append(out, arg)
|
||||
i++
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ParseFlags parses command line flags
|
||||
func (c *Config) ParseFlags(args []string) {
|
||||
args = normalizeBoolArgs(args)
|
||||
c.GoecsFlag.BoolVar(&c.Help, "h", false, "Show help information")
|
||||
c.GoecsFlag.BoolVar(&c.Help, "help", false, "Show help information")
|
||||
c.GoecsFlag.BoolVar(&c.ShowVersion, "v", false, "Display version information")
|
||||
@@ -131,6 +183,8 @@ func (c *Config) ParseFlags(args []string) {
|
||||
c.GoecsFlag.IntVar(&c.SpNum, "spnum", 2, "Set the number of servers per operator for speed test")
|
||||
c.GoecsFlag.BoolVar(&c.EnableLogger, "log", false, "Enable/Disable logging in the current path")
|
||||
c.GoecsFlag.BoolVar(&c.EnableUpload, "upload", true, "Enable/Disable upload the result")
|
||||
c.GoecsFlag.BoolVar(&c.AnalyzeResult, "analysis", false, "Enable/Disable post-test concise summary analysis")
|
||||
c.GoecsFlag.BoolVar(&c.AnalyzeResult, "analyze", false, "Enable/Disable post-test concise summary analysis")
|
||||
c.GoecsFlag.Parse(args)
|
||||
|
||||
c.GoecsFlag.Visit(func(f *flag.Flag) {
|
||||
@@ -222,6 +276,9 @@ func (c *Config) SaveUserSetParams() map[string]interface{} {
|
||||
if c.UserSetFlags["spnum"] {
|
||||
saved["spnum"] = c.SpNum
|
||||
}
|
||||
if c.UserSetFlags["analysis"] || c.UserSetFlags["analyze"] {
|
||||
saved["analysis"] = c.AnalyzeResult
|
||||
}
|
||||
|
||||
return saved
|
||||
}
|
||||
@@ -340,6 +397,11 @@ func (c *Config) RestoreUserSetParams(saved map[string]interface{}) {
|
||||
c.SpNum = intVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["analysis"]; ok {
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.AnalyzeResult = boolVal
|
||||
}
|
||||
}
|
||||
|
||||
c.ValidateParams()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/oneclickvirt/ecs/internal/analysis"
|
||||
"github.com/oneclickvirt/ecs/internal/params"
|
||||
"github.com/oneclickvirt/ecs/internal/tests"
|
||||
"github.com/oneclickvirt/ecs/utils"
|
||||
@@ -153,7 +154,7 @@ func RunBasicTests(preCheck utils.NetCheckResult, config *params.Config, basicIn
|
||||
}
|
||||
if config.BasicStatus {
|
||||
fmt.Printf("%s", *basicInfo)
|
||||
} else if (config.Input == "6" || config.Input == "9") && config.SecurityTestStatus {
|
||||
} else if (config.Choice == "6" || config.Choice == "9") && config.SecurityTestStatus {
|
||||
scanner := bufio.NewScanner(strings.NewReader(*basicInfo))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
@@ -296,7 +297,7 @@ func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string,
|
||||
return utils.PrintAndCapture(func() {
|
||||
if config.BacktraceStatus && !config.OnlyChinaTest {
|
||||
utils.PrintCenteredTitle("上游及回程线路检测", config.Width)
|
||||
tests.UpstreamsCheck()
|
||||
tests.UpstreamsCheck(config.Language)
|
||||
}
|
||||
if config.Nt3Status && !config.OnlyChinaTest {
|
||||
utils.PrintCenteredTitle("三网回程路由检测", config.Width)
|
||||
@@ -330,6 +331,8 @@ func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string,
|
||||
fmt.Println(pt.WebsiteTest())
|
||||
}
|
||||
}
|
||||
// 等待第三方库的输出完全刷新到标准输出
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}, tempOutput, output)
|
||||
}
|
||||
|
||||
@@ -361,7 +364,15 @@ func RunSpeedTests(config *params.Config, output, tempOutput string, outputMutex
|
||||
}
|
||||
} else if config.Choice == "6" {
|
||||
tests.CustomSP("net", "global", 11, config.Language)
|
||||
} else {
|
||||
// Custom menu mode and any other fallback choices.
|
||||
tests.NearbySP()
|
||||
tests.CustomSP("net", "cu", config.SpNum, config.Language)
|
||||
tests.CustomSP("net", "ct", config.SpNum, config.Language)
|
||||
tests.CustomSP("net", "cmcc", config.SpNum, config.Language)
|
||||
}
|
||||
// 等待第三方库的输出完全刷新到标准输出
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}, tempOutput, output)
|
||||
}
|
||||
@@ -380,6 +391,8 @@ func RunEnglishNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *
|
||||
fmt.Println(pt.WebsiteTest())
|
||||
}
|
||||
}
|
||||
// 等待第三方库的输出完全刷新到标准输出
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
}, tempOutput, output)
|
||||
}
|
||||
|
||||
@@ -393,6 +406,8 @@ func RunEnglishSpeedTests(config *params.Config, output, tempOutput string, outp
|
||||
tests.ShowHead(config.Language)
|
||||
tests.NearbySP()
|
||||
tests.CustomSP("net", "global", -1, config.Language)
|
||||
// 等待第三方库的输出完全刷新到标准输出
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}, tempOutput, output)
|
||||
}
|
||||
@@ -419,6 +434,25 @@ func AppendTimeInfo(config *params.Config, output, tempOutput string, startTime
|
||||
}, tempOutput, output)
|
||||
}
|
||||
|
||||
// AppendAnalysisSummary appends a concise bilingual summary for easier interpretation.
|
||||
func AppendAnalysisSummary(config *params.Config, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
finalOutput := output
|
||||
return utils.PrintAndCapture(func() {
|
||||
summary := analysis.GenerateSummary(config, finalOutput)
|
||||
if strings.TrimSpace(summary) == "" {
|
||||
return
|
||||
}
|
||||
if config.Language == "zh" {
|
||||
utils.PrintCenteredTitle("测试总结分析", config.Width)
|
||||
} else {
|
||||
utils.PrintCenteredTitle("Result Summary Analysis", config.Width)
|
||||
}
|
||||
fmt.Println(summary)
|
||||
}, tempOutput, output)
|
||||
}
|
||||
|
||||
// HandleSignalInterrupt handles interrupt signals
|
||||
func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime *time.Time, output *string, tempOutput string, uploadDone chan bool, outputMutex *sync.Mutex) {
|
||||
select {
|
||||
@@ -454,7 +488,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
|
||||
defer uploadCancel()
|
||||
|
||||
go func() {
|
||||
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload)
|
||||
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload, config.Language)
|
||||
select {
|
||||
case resultChan <- struct {
|
||||
httpURL string
|
||||
@@ -508,7 +542,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
|
||||
|
||||
// HandleUploadResults handles uploading results
|
||||
func HandleUploadResults(config *params.Config, output string) {
|
||||
httpURL, httpsURL := utils.ProcessAndUpload(output, config.FilePath, config.EnableUpload)
|
||||
httpURL, httpsURL := utils.ProcessAndUpload(output, config.FilePath, config.EnableUpload, config.Language)
|
||||
if httpURL != "" || httpsURL != "" {
|
||||
if config.Language == "en" {
|
||||
fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", httpURL, httpsURL)
|
||||
|
||||
@@ -56,8 +56,8 @@ func printTableRow(result pst.SpeedTestResult) {
|
||||
}
|
||||
location = fmt.Sprintf("%s%s", carrier, result.City)
|
||||
}
|
||||
if len(location) > 14 {
|
||||
location = location[:14] + "..."
|
||||
if len(location) > 15 {
|
||||
location = location[:15]
|
||||
}
|
||||
upload := "N/A"
|
||||
if result.UploadMbps > 0 {
|
||||
@@ -135,6 +135,8 @@ func privateSpeedTest(num int, operator string) (int, error) {
|
||||
// 去重:确保同一运营商内城市不重复
|
||||
seenCities := make(map[string]bool)
|
||||
var bestServers []pst.ServerWithLatencyInfo
|
||||
// 保留更多备用节点,以应对测速失败的情况(保留 serversPerISP * 2 个备用节点)
|
||||
maxBackupServers := serversPerISP * 2
|
||||
for _, serverInfo := range candidateServers {
|
||||
city := serverInfo.Server.City
|
||||
if city == "" {
|
||||
@@ -143,8 +145,8 @@ func privateSpeedTest(num int, operator string) (int, error) {
|
||||
if !seenCities[city] {
|
||||
seenCities[city] = true
|
||||
bestServers = append(bestServers, serverInfo)
|
||||
// 去重后取前 serversPerISP 个
|
||||
if len(bestServers) >= serversPerISP {
|
||||
// 去重后保留足够的备用节点
|
||||
if len(bestServers) >= maxBackupServers {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -153,7 +155,13 @@ func privateSpeedTest(num int, operator string) (int, error) {
|
||||
return 0, fmt.Errorf("去重后没有可用的服务器")
|
||||
}
|
||||
// 执行测速并逐个打印结果(不打印表头)
|
||||
// 统计成功输出的节点数
|
||||
successCount := 0
|
||||
for i, serverInfo := range bestServers {
|
||||
// 如果已经成功输出了足够的节点,则停止测试
|
||||
if successCount >= serversPerISP {
|
||||
break
|
||||
}
|
||||
result := pst.RunSpeedTest(
|
||||
serverInfo.Server,
|
||||
false, // 不禁用下载测试
|
||||
@@ -163,16 +171,21 @@ func privateSpeedTest(num int, operator string) (int, error) {
|
||||
&serverInfo,
|
||||
false, // 不显示进度条
|
||||
)
|
||||
if result.Success {
|
||||
// 只要测试成功且有任意一个速度值有效,就输出结果(部分成功也显示)
|
||||
if result.Success && (result.UploadMbps > 0 || result.DownloadMbps > 0) {
|
||||
printTableRow(result)
|
||||
// 只有上传和下载都成功时才计入成功数
|
||||
if result.UploadMbps > 0 && result.DownloadMbps > 0 {
|
||||
successCount++
|
||||
}
|
||||
}
|
||||
// 在测试之间暂停(除了最后一个)
|
||||
if i < len(bestServers)-1 {
|
||||
// 在测试之间暂停(如果还需要继续测试的话)
|
||||
if successCount < serversPerISP && i < len(bestServers)-1 {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
// 返回实际测试的节点数量
|
||||
return len(bestServers), nil
|
||||
// 返回实际成功输出的节点数量
|
||||
return successCount, nil
|
||||
}
|
||||
|
||||
// privateSpeedTestWithFallback 使用私有测速,如果失败则回退到 global 节点
|
||||
|
||||
@@ -29,11 +29,15 @@ type ConcurrentResults struct {
|
||||
|
||||
var IPV4, IPV6 string
|
||||
|
||||
func UpstreamsCheck() {
|
||||
func UpstreamsCheck(language string) {
|
||||
// 添加panic恢复机制
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("\n上游检测出现错误,已跳过")
|
||||
if language == "zh" {
|
||||
fmt.Println("\n上游检测出现错误,已跳过")
|
||||
} else {
|
||||
fmt.Println("\nUpstream check failed, skipped")
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Upstream check panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
@@ -80,6 +84,11 @@ func UpstreamsCheck() {
|
||||
if results.backtraceResult != "" {
|
||||
fmt.Printf("%s\n", results.backtraceResult)
|
||||
}
|
||||
fmt.Println(Yellow("准确线路自行查看详细路由,本测试结果仅作参考"))
|
||||
fmt.Println(Yellow("同一目标地址多个线路时,检测可能已越过汇聚层,除第一个线路外,后续信息可能无效"))
|
||||
if language == "zh" {
|
||||
fmt.Println(Yellow("准确线路自行查看详细路由,本测试结果仅作参考"))
|
||||
fmt.Println(Yellow("同一目标地址多个线路时,检测可能已越过汇聚层,除第一个线路外,后续信息可能无效"))
|
||||
} else {
|
||||
fmt.Println(Yellow("For accurate routing, check the detailed routes yourself. This result is for reference only."))
|
||||
fmt.Println(Yellow("When multiple routes share the same destination, detection may have passed the aggregation layer; only the first route is reliable."))
|
||||
}
|
||||
}
|
||||
|
||||
168
utils/utils.go
168
utils/utils.go
@@ -26,6 +26,88 @@ import (
|
||||
"github.com/oneclickvirt/security/network"
|
||||
)
|
||||
|
||||
// IsAndroid 检测当前是否在 Android (Termux) 环境下运行
|
||||
func IsAndroid() bool {
|
||||
// Termux 会设置 TERMUX_VERSION 或 PREFIX 环境变量
|
||||
if os.Getenv("TERMUX_VERSION") != "" {
|
||||
return true
|
||||
}
|
||||
if prefix := os.Getenv("PREFIX"); strings.Contains(prefix, "termux") {
|
||||
return true
|
||||
}
|
||||
// Android 系统标志文件
|
||||
if _, err := os.Stat("/system/build.prop"); err == nil {
|
||||
return true
|
||||
}
|
||||
// ANDROID_ROOT 环境变量 (Android 系统设置为 /system)
|
||||
if os.Getenv("ANDROID_ROOT") != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// androidDNSServers 是用于修复 Android/Termux 下 DNS 问题的备用服务器列表
|
||||
var androidDNSServers = []string{
|
||||
"nameserver 8.8.8.8",
|
||||
"nameserver 8.8.4.4",
|
||||
"nameserver 1.1.1.1",
|
||||
"nameserver 223.5.5.5",
|
||||
}
|
||||
|
||||
// CheckAndFixAndroidDNS 检测并尝试修复 Android Termux 下的 DNS 解析问题。
|
||||
// 仅在检测到 Android 环境下调用。不出现问题时无任何输出。
|
||||
// language: "zh" 或 "en"
|
||||
func CheckAndFixAndroidDNS(language string) {
|
||||
if !IsAndroid() {
|
||||
return
|
||||
}
|
||||
resolvPath := "/etc/resolv.conf"
|
||||
hasValidDNS := false
|
||||
if data, err := os.ReadFile(resolvPath); err == nil {
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "nameserver") && len(strings.Fields(line)) >= 2 {
|
||||
hasValidDNS = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if hasValidDNS {
|
||||
// DNS 配置正常,无需处理
|
||||
return
|
||||
}
|
||||
// /etc/resolv.conf 缺失或无有效 nameserver,尝试自动创建
|
||||
content := strings.Join(androidDNSServers, "\n") + "\n"
|
||||
err := os.WriteFile(resolvPath, []byte(content), 0644)
|
||||
if err != nil {
|
||||
// 写入失败(权限不足),给出双语提示和修复建议
|
||||
fmt.Println("-----------------------------------------------------")
|
||||
fmt.Println("[Android/Termux] 检测到 DNS 解析配置缺失!")
|
||||
fmt.Println("这将导致依赖系统 DNS 的测试项目无法正常运行。")
|
||||
fmt.Println("解决方案(推荐):")
|
||||
fmt.Println(" 通过 Magisk / KernelSU 刷入以下模块后重启手机:")
|
||||
fmt.Println(" https://github.com/weigui404/resolv.conf")
|
||||
fmt.Println("解决方案(临时):")
|
||||
fmt.Println(" 以 root 身份执行: echo 'nameserver 8.8.8.8' > /etc/resolv.conf")
|
||||
fmt.Println("-----------------------------------------------------")
|
||||
fmt.Println("[Android/Termux] DNS resolver config is missing!")
|
||||
fmt.Println("This will cause DNS-dependent tests to fail.")
|
||||
fmt.Println("Fix (recommended):")
|
||||
fmt.Println(" Flash the following module via Magisk / KernelSU and reboot:")
|
||||
fmt.Println(" https://github.com/weigui404/resolv.conf")
|
||||
fmt.Println("Fix (temporary):")
|
||||
fmt.Println(" Run as root: echo 'nameserver 8.8.8.8' > /etc/resolv.conf")
|
||||
fmt.Println("-----------------------------------------------------")
|
||||
} else {
|
||||
// 写入成功
|
||||
if language == "zh" {
|
||||
fmt.Println("[Android/Termux] DNS 配置缺失,已自动写入 /etc/resolv.conf,DNS 解析已恢复。")
|
||||
} else {
|
||||
fmt.Println("[Android/Termux] DNS config was missing; auto-written to /etc/resolv.conf, DNS resolution restored.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取本程序本日及总执行的统计信息
|
||||
type StatsResponse struct {
|
||||
Counter string `json:"counter"`
|
||||
@@ -68,7 +150,7 @@ func PrintHead(language string, width int, ecsVersion string) {
|
||||
}
|
||||
}
|
||||
|
||||
func CheckChina(enableLogger bool) bool {
|
||||
func CheckChina(enableLogger bool, language string) bool {
|
||||
if enableLogger {
|
||||
InitLogger()
|
||||
defer Logger.Sync()
|
||||
@@ -84,7 +166,7 @@ func CheckChina(enableLogger bool) bool {
|
||||
ipapiResp, err := client.R().Get(ipapiURL)
|
||||
if err != nil {
|
||||
if enableLogger {
|
||||
Logger.Info("无法获取IP信息:" + err.Error())
|
||||
Logger.Info("Failed to get IP info: " + err.Error())
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -92,24 +174,41 @@ func CheckChina(enableLogger bool) bool {
|
||||
ipapiBody, err := ipapiResp.ToString()
|
||||
if err != nil {
|
||||
if enableLogger {
|
||||
Logger.Info("无法读取IP信息响应:" + err.Error())
|
||||
Logger.Info("Failed to read IP info response: " + err.Error())
|
||||
}
|
||||
return false
|
||||
}
|
||||
isInChina := strings.Contains(ipapiBody, "China")
|
||||
if isInChina {
|
||||
fmt.Println("根据 ipapi.co 提供的信息,当前IP可能在中国")
|
||||
var input string
|
||||
fmt.Print("是否选用中国专项测试(无平台解锁测试,有三网Ping值测试)? ([y]/n) ")
|
||||
if language == "zh" {
|
||||
fmt.Println("根据 ipapi.co 提供的信息,当前IP可能在中国")
|
||||
fmt.Print("是否选用中国专项测试(无平台解锁测试,有三网Ping值测试)? ([y]/n) ")
|
||||
} else {
|
||||
fmt.Println("According to ipapi.co, this IP may be located in China")
|
||||
fmt.Print("Use China-specific test (no platform unlock test, includes 3-network ping test)? ([y]/n) ")
|
||||
}
|
||||
fmt.Scanln(&input)
|
||||
switch strings.ToLower(input) {
|
||||
case "yes", "y":
|
||||
fmt.Println("使用中国专项测试")
|
||||
if language == "zh" {
|
||||
fmt.Println("使用中国专项测试")
|
||||
} else {
|
||||
fmt.Println("Using China-specific test")
|
||||
}
|
||||
selectChina = true
|
||||
case "no", "n":
|
||||
fmt.Println("不使用中国专项测试")
|
||||
if language == "zh" {
|
||||
fmt.Println("不使用中国专项测试")
|
||||
} else {
|
||||
fmt.Println("Not using China-specific test")
|
||||
}
|
||||
default:
|
||||
fmt.Println("使用中国专项测试")
|
||||
if language == "zh" {
|
||||
fmt.Println("使用中国专项测试")
|
||||
} else {
|
||||
fmt.Println("Using China-specific test")
|
||||
}
|
||||
selectChina = true
|
||||
}
|
||||
}
|
||||
@@ -219,6 +318,11 @@ func CaptureOutput(f func()) string {
|
||||
}()
|
||||
// 执行函数
|
||||
f()
|
||||
// 确保所有输出都已经刷新
|
||||
os.Stdout.Sync()
|
||||
os.Stderr.Sync()
|
||||
// 等待一小段时间,确保后台goroutine的输出完成
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
// 关闭管道写入端,让管道读取端可以读取所有数据
|
||||
stdoutPipeW.Close()
|
||||
stderrPipeW.Close()
|
||||
@@ -309,13 +413,11 @@ func UploadText(absPath string) (string, string, error) {
|
||||
}
|
||||
|
||||
// ProcessAndUpload 创建结果文件并上传文件
|
||||
func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string, string) {
|
||||
func ProcessAndUpload(output string, filePath string, enableUplaod bool, language string) (string, string) {
|
||||
// 使用 defer 来处理 panic
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[ERROR] 处理上传时发生严重错误: %v\n", r)
|
||||
// 可以选择打印堆栈信息以便调试
|
||||
// debug.PrintStack()
|
||||
fmt.Fprintf(os.Stderr, "[ERROR] Fatal error during upload: %v\n", r)
|
||||
}
|
||||
}()
|
||||
// 检查文件是否存在
|
||||
@@ -323,14 +425,22 @@ func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string
|
||||
// 文件存在,删除文件
|
||||
err = os.Remove(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("无法删除文件:", err)
|
||||
if language == "zh" {
|
||||
fmt.Println("无法删除文件:", err)
|
||||
} else {
|
||||
fmt.Println("Failed to delete file:", err)
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
// 创建文件
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("无法创建文件:", err)
|
||||
if language == "zh" {
|
||||
fmt.Println("无法创建文件:", err)
|
||||
} else {
|
||||
fmt.Println("Failed to create file:", err)
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
defer file.Close()
|
||||
@@ -342,27 +452,47 @@ func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string
|
||||
writer := bufio.NewWriter(file)
|
||||
_, err = writer.WriteString(cleanedOutput)
|
||||
if err != nil {
|
||||
fmt.Println("无法写入文件:", err)
|
||||
if language == "zh" {
|
||||
fmt.Println("无法写入文件:", err)
|
||||
} else {
|
||||
fmt.Println("Failed to write file:", err)
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
// 确保写入缓冲区的数据都刷新到文件中
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
fmt.Println("无法刷新文件缓冲:", err)
|
||||
if language == "zh" {
|
||||
fmt.Println("无法刷新文件缓冲:", err)
|
||||
} else {
|
||||
fmt.Println("Failed to flush file buffer:", err)
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
fmt.Printf("测试结果已写入 %s\n", filePath)
|
||||
if language == "zh" {
|
||||
fmt.Printf("测试结果已写入 %s\n", filePath)
|
||||
} else {
|
||||
fmt.Printf("Test results written to %s\n", filePath)
|
||||
}
|
||||
if enableUplaod {
|
||||
// 获取文件的绝对路径
|
||||
absPath, err := filepath.Abs(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("无法获取文件绝对路径:", err)
|
||||
if language == "zh" {
|
||||
fmt.Println("无法获取文件绝对路径:", err)
|
||||
} else {
|
||||
fmt.Println("Failed to get absolute file path:", err)
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
// 上传文件并生成短链接
|
||||
http_url, https_url, err := UploadText(absPath)
|
||||
if err != nil {
|
||||
fmt.Println("上传失败,无法生成链接")
|
||||
if language == "zh" {
|
||||
fmt.Println("上传失败,无法生成链接")
|
||||
} else {
|
||||
fmt.Println("Upload failed, unable to generate link")
|
||||
}
|
||||
fmt.Println(err.Error())
|
||||
return "", ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user