mirror of
https://github.com/oneclickvirt/ecs.git
synced 2025-12-23 11:43:09 +08:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d78128f6a | ||
|
|
9c67a8d446 | ||
|
|
014dba0ce6 | ||
|
|
b5fdab4b27 | ||
|
|
16c4c2ff92 | ||
|
|
e1991c850f | ||
|
|
0b7c7865ff | ||
|
|
238ea3eb6f | ||
|
|
b859c52ba3 | ||
|
|
f1642843dd | ||
|
|
90ba076afb | ||
|
|
d31d20e16f | ||
|
|
a4084835f9 | ||
|
|
39c2607b42 | ||
|
|
519c0f3e86 | ||
|
|
3b5b8a348e | ||
|
|
858585b4ff | ||
|
|
b891416147 | ||
|
|
8e79568895 | ||
|
|
01aa051c96 | ||
|
|
628a380122 | ||
|
|
2b94d289f3 | ||
|
|
e3676760da |
40
README.md
40
README.md
@@ -74,35 +74,43 @@ Shell 版本:[https://github.com/spiritLHLS/ecs](https://github.com/spiritLHLS
|
||||
|
||||
#### **一键命令**
|
||||
|
||||
**一键命令**将**默认安装依赖**,**默认更新包管理器**,**默认非互动模式**
|
||||
**一键命令**将默认**不安装依赖**,默认**不更新包管理器**,默认**非互动模式**
|
||||
|
||||
- **国际用户无加速:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **国际/国内使用 CDN 加速:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **国内用户使用 CNB 加速:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **短链接:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
**如果需要测试更准确,请按照下面的详细说明进行安装,添加非必需的依赖**
|
||||
|
||||
#### **详细说明**
|
||||
|
||||
**详细说明**中的命令**可控制是否安装依赖**,**是否更新包管理器**,**默认互动模式可进行选择**
|
||||
以下命令可控制**是否安装依赖**,**是否更新包管理器**,**互动模式和非交互模式**
|
||||
|
||||
<details>
|
||||
<summary>展开查看详细说明</summary>
|
||||
@@ -190,12 +198,18 @@ Usage: goecs [options]
|
||||
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
|
||||
@@ -207,20 +221,28 @@ Usage: goecs [options]
|
||||
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
|
||||
@@ -233,8 +255,6 @@ Usage: goecs [options]
|
||||
Enable/Disable Telegram DC test
|
||||
-upload
|
||||
Enable/Disable upload the result (default true)
|
||||
-ut
|
||||
Enable/Disable unlock media test (default true)
|
||||
-v Display version information
|
||||
-version
|
||||
Display version information
|
||||
@@ -384,7 +404,9 @@ GOOS=darwin GOARCH=amd64 go build -o goecs_darwin
|
||||
|
||||
## 致谢
|
||||
|
||||
感谢 [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) 等网站提供的API进行检测,感谢互联网各网站提供的查询资源
|
||||
感谢
|
||||
[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进行检测,感谢互联网各网站提供的查询资源
|
||||
|
||||
感谢
|
||||
|
||||
|
||||
38
README_EN.md
38
README_EN.md
@@ -74,35 +74,43 @@ Shell version: [https://github.com/spiritLHLS/ecs/blob/main/README_EN.md](https:
|
||||
|
||||
#### **One-click command**
|
||||
|
||||
**One-Click Command** will **Install Dependencies by Default**, **Update Package Manager by Default**, **Default Non-Interactive Mode***
|
||||
**One-Click Command** will **Not install Dependencies** by Default, **Not update Package Manager** by Default, **Non-Interactive Mode** by Default.
|
||||
|
||||
- **International users without acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **International/domestic users with CDN acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **Domestic users with CNB acceleration:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh env && ./goecs.sh install && goecs
|
||||
export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
- **Short Link:**
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
|
||||
``
|
||||
export noninteractive=true && curl -L https://bash.spiritlhl.net/goecs -o goecs.sh && chmod +x goecs.sh && bash goecs.sh install && goecs
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```bash
|
||||
export noninteractive=true && curl -L https://ba.sh/JrVa -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs
|
||||
```
|
||||
|
||||
**For more accurate testing, please follow the detailed instructions below to install and add non-essential dependencies**
|
||||
|
||||
#### **Detailed instructions**
|
||||
|
||||
**Detailed description** of the commands in **Command **Controls whether to install dependencies**, **Whether to update the package manager**, **Default interaction mode can be selected***
|
||||
The following commands control whether dependencies are installed, whether the package manager is updated, and whether interactive or non-interactive mode is used.
|
||||
|
||||
<details>
|
||||
<summary>Expand to view detailed instructions</summary>
|
||||
@@ -189,12 +197,18 @@ Usage: goecs [options]
|
||||
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
|
||||
@@ -206,20 +220,28 @@ Usage: goecs [options]
|
||||
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
|
||||
@@ -232,8 +254,6 @@ Usage: goecs [options]
|
||||
Enable/Disable Telegram DC test
|
||||
-upload
|
||||
Enable/Disable upload the result (default true)
|
||||
-ut
|
||||
Enable/Disable unlock media test (default true)
|
||||
-v Display version information
|
||||
-version
|
||||
Display version information
|
||||
|
||||
@@ -243,53 +243,55 @@ AMD的7950x单核满血性能得分在6500左右,AMD的5950x单核满血性能
|
||||
|
||||
检测18个数据库的IP相关信息,多个平台比较对应检测项目都为对应值,证明当前IP确实如此,不要仅相信一个数据库源的信息:
|
||||
|
||||
[ipinfo.io](https://ipinfo.io) [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)
|
||||
[ipinfo.io](https://ipinfo.io) [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) [cloudflare.com](https://www.cloudflare.com/)
|
||||
|
||||
以下为每个字段的对应的含义
|
||||
|
||||
| 字段类别 | 字段名称 | 字段说明 | 可能的值 | 评分规则 |
|
||||
|---------|---------|---------|---------|---------|
|
||||
| 安全得分 | 声誉(Reputation) | IP地址在安全社区中的信誉评分 | 0-100的数值 | 越高越好 |
|
||||
| | 信任得分(Trust Score) | IP地址的可信任程度评分 | 0-100的数值 | 越高越好 |
|
||||
| | VPN得分(VPN Score) | IP被识别为VPN的可能性评分 | 0-100的数值 | 越低越好 |
|
||||
| | 代理得分(Proxy Score) | IP被识别为代理的可能性评分 | 0-100的数值 | 越低越好 |
|
||||
| 安全得分 | 声誉 | IP地址在安全社区中的信誉评分 | 0-100的数值 | 越高越好 |
|
||||
| | 信任得分 | IP地址的可信任程度评分 | 0-100的数值 | 越高越好 |
|
||||
| | VPN得分 | IP被识别为VPN的可能性评分 | 0-100的数值 | 越低越好 |
|
||||
| | 代理得分 | IP被识别为代理的可能性评分 | 0-100的数值 | 越低越好 |
|
||||
| | 社区投票-无害 | 社区成员投票认为该IP无害的分数 | 非负整数 | 越高越好 |
|
||||
| | 社区投票-恶意 | 社区成员投票认为该IP恶意的分数 | 非负整数 | 越低越好 |
|
||||
| | 威胁得分(Threat Score) | IP地址的整体威胁程度评分 | 0-100的数值 | 越低越好 |
|
||||
| | 欺诈得分(Fraud Score) | IP地址涉及欺诈活动的可能性评分 | 0-100的数值 | 越低越好 |
|
||||
| | 滥用得分(Abuse Score) | IP地址被报告滥用行为的评分 | 0-100的数值 | 越低越好 |
|
||||
| | 威胁得分 | IP地址的整体威胁程度评分 | 0-100的数值 | 越低越好 |
|
||||
| | 欺诈得分 | IP地址涉及欺诈活动的可能性评分 | 0-100的数值 | 越低越好 |
|
||||
| | 滥用得分 | IP地址被报告滥用行为的评分 | 0-100的数值 | 越低越好 |
|
||||
| | ASN滥用得分 | 该IP所属ASN(自治系统)的滥用评分 | 0-1的小数,可能带有风险等级标注(Low/Medium/High) | 越低越好 |
|
||||
| | 公司滥用得分 | 该IP所属公司的滥用评分 | 0-1的小数,可能带有风险等级标注(Low/Medium/High) | 越低越好 |
|
||||
| | 威胁级别(Threat Level) | IP地址的威胁等级分类 | low/medium/high/critical等文本描述 | low为最佳 |
|
||||
| 黑名单记录 | 无害记录数(Harmless) | 在各黑名单数据库中被标记为无害的次数 | 非负整数 | 数值本身无好坏 |
|
||||
| | 恶意记录数(Malicious) | 在各黑名单数据库中被标记为恶意的次数 | 非负整数 | 越低越好 |
|
||||
| | 可疑记录数(Suspicious) | 在各黑名单数据库中被标记为可疑的次数 | 非负整数 | 越低越好 |
|
||||
| | 无记录数(Undetected) | 在各黑名单数据库中无任何记录的次数 | 非负整数 | 数值本身无好坏 |
|
||||
| | 威胁级别 | IP地址的威胁等级分类 | low/medium/high/critical等文本描述 | low为最佳 |
|
||||
| | 流量占比 | 真人和机器人在本机IP的ASN所在国家的占比 | 百分数 | 真人比越高越好 |
|
||||
| 黑名单记录 | 无害记录数 | 在各黑名单数据库中被标记为无害的次数 | 非负整数 | 数值本身无好坏 |
|
||||
| | 恶意记录数 | 在各黑名单数据库中被标记为恶意的次数 | 非负整数 | 越低越好 |
|
||||
| | 可疑记录数 | 在各黑名单数据库中被标记为可疑的次数 | 非负整数 | 越低越好 |
|
||||
| | 无记录数 | 在各黑名单数据库中无任何记录的次数 | 非负整数 | 数值本身无好坏 |
|
||||
| | DNS黑名单-总检查数 | 检查的DNS黑名单数据库总数量 | 正整数 | 数值本身无好坏 |
|
||||
| | DNS黑名单-干净 | 在DNS黑名单中显示为干净(未列入)的数量 | 非负整数 | 越高越好 |
|
||||
| | DNS黑名单-已列入 | 在DNS黑名单中已被列入的数量 | 非负整数 | 越低越好 |
|
||||
| | DNS黑名单-其他 | 在DNS黑名单检查中返回其他状态的数量 | 非负整数 | 数值本身无好坏 |
|
||||
|
||||
当本机的IP所在的ASN拥有的IP数量比较少时,流量占比可以给你提供网络邻居中有多少是真实流量的占比,目前全球的互联网流量的占比约是70%真人30%机器人(IPV4),如果需要比较你就按这个基准对比就行了,就知道是不是当前IP的ASN在本国的使用达到了互联网平均水平。如果需要具体国家的基准查询,可使用 https://trafficbenchmark.spiritlhl.net/ 自行搜索查找对比。
|
||||
|
||||
一般来说看下面的使用类型公司类型还有安全信息的判别足矣,上面的安全得分只有多个数据库确认一致才可信,不看也没啥问题。(IDC: 一般买服务器识别成这个的多,就是正常的在数据中心机房广播使用的类型)
|
||||
|
||||
| 使用类型 | 说明 |
|
||||
| ----------- | ---------- |
|
||||
| hosting | 数据中心网络(IDC) |
|
||||
| residential | 家庭/住宅网络(家宽) |
|
||||
| FixedLineISP,ISP | 固定线路互联网服务提供商(家宽) |
|
||||
| isp | 固定线路互联网服务提供商(家宽) |
|
||||
| business | 企业办公网络(商宽) |
|
||||
| cellular | 移动运营商网络(家宽) |
|
||||
| education | 教育机构网络(教育网) |
|
||||
| government | 政府机构网络(政府网) |
|
||||
| military | 军事网络(政府网) |
|
||||
| DataCenter/WebHosting/Transit | 数据中心网络(IDC) |
|
||||
| CDN | 内容分发网络(IDC) |
|
||||
|
||||
| 公司类型 | 说明 |
|
||||
| ------------ | ------------ |
|
||||
| business | 企业公司(商宽) |
|
||||
| hosting | 主机/数据中心公司(IDC) |
|
||||
| FixedLineISP,ISP | 固定线路互联网服务提供商(家宽) |
|
||||
| business | 企业公司(商宽) |
|
||||
| isp | 固定线路互联网服务提供商(家宽) |
|
||||
| education | 教育机构(教育网) |
|
||||
| government | 政府机构(政府网) |
|
||||
|
||||
@@ -297,6 +299,9 @@ AMD的7950x单核满血性能得分在6500左右,AMD的5950x单核满血性能
|
||||
|
||||
| 字段类别 | 字段名称 | 字段说明 | 可能的值 | 评分规则 |
|
||||
|---------|---------|---------|---------|---------|
|
||||
| 浏览器类型 | 是否为主流浏览器 | 本机IP的ASN所在国家的占比 | 百分比 | 主流的越多越好 |
|
||||
| 设备类型 | 是否为桌面移动设备 | 本机IP的ASN所在国家的占比 | 百分比 | 桌面移动设备占比越多越好 |
|
||||
| 操作系统类型 | 是否为主流操作系统 | 本机IP的ASN所在国家的占比 | 百分比 | 主流的越多越好 |
|
||||
| 云提供商 | 是否云提供商(Cloud Provider) | 该IP是否属于云服务提供商 | Yes/No | 无好坏之分,仅标识 |
|
||||
| 数据中心 | 是否数据中心(Data Center) | 该IP是否位于数据中心 | Yes/No | 如果关注解锁No为最佳 |
|
||||
| 移动设备 | 是否移动设备(Mobile) | 该IP是否来自移动设备网络 | Yes/No | 如果关注解锁Yes为最佳 |
|
||||
@@ -399,8 +404,7 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
|
||||
| 中国电信 | 163 | ChinaNet (原163骨干网) | 普通国际出口,延迟高易绕路 | 一般 |
|
||||
| 中国电信 | CN2 GT | ChinaNet Next Carrying Network (GT) | 较优于163,偶有拥堵 | 良好 |
|
||||
| 中国电信 | CN2 GIA | Global Internet Access(GT) | 直连国际POP,低延迟低丢包 | 优质(最好) |
|
||||
| 中国联通 | 169 | China169骨干网 | 老主干网,常经港美出口 | 一般(少部分优质) |
|
||||
| 中国联通 | 4837 | Unicom International (AS4837) | 常见国际出口,覆盖广 | 良好 |
|
||||
| 中国联通 | 4837 | Unicom International (AS4837) | 常见国际出口,覆盖广 | 一般到良好 |
|
||||
| 中国联通 | 9929 | Unicom Premium / CU-IX | 精品网,直连主要IXP,延迟低 | 优质 |
|
||||
| 中国移动 | CMI (AS58453) | China Mobile International | 节点多,对两广(广东广西)优化好 | 两广良好,其他一般 |
|
||||
| 中国移动 | CMIN2 (AS58807) | China Mobile International N2 | 高质量专线,低延迟低丢包,对标CN2 | 优质 |
|
||||
@@ -429,7 +433,7 @@ Abuser 或 Abuse 的滥用得分会直接影响机器的正常使用(中国境
|
||||
| 中国电信 | CN2 BGP | CN2混合BGP(GIA+GT) | 混合路由,性能略低于纯GIA | 良好至优质 |
|
||||
| 中国电信 | CUII | ChinaNet United International Internet | 面向直连美国的专线 | 优质 |
|
||||
| 中国电信 | 163+CUII混线 | 163国内段+国际专线出口 | 价格低,性能一般 | 一般 |
|
||||
| 中国联通 | 169 | China169骨干网 | 老主干网,常经港美出口 | 一般(少部分优质) |
|
||||
| 中国联通 | 169 | China169骨干网 | 老主干网,一般对接4837 | 一般(少部分优质) |
|
||||
| 中国联通 | 4837 | Unicom International (AS4837) | 常见国际出口,覆盖广 | 良好 |
|
||||
| 中国联通 | 9929 | Unicom Premium / CU-IX | 精品网,直连IXP,低延迟 | 优质 |
|
||||
| 中国联通 | 9929+4837混BGP | 混合出口(IDC常见优化) | 性能平衡 | 良好 |
|
||||
@@ -683,7 +687,7 @@ Dependency project: [https://github.com/oneclickvirt/securityCheck](https://gith
|
||||
|
||||
Detect IP-related information from 18 databases. Multiple platforms comparing corresponding detection items all show corresponding values, proving that the current IP is indeed as such. Do not only trust information from a single database source:
|
||||
|
||||
[ipinfo.io](https://ipinfo.io) [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)
|
||||
[ipinfo.io](https://ipinfo.io) [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) [cloudflare.com](https://www.cloudflare.com/)
|
||||
|
||||
The following are the meanings corresponding to each field
|
||||
|
||||
@@ -701,6 +705,7 @@ The following are the meanings corresponding to each field
|
||||
| | ASN Abuse Score | Abuse score of the ASN (Autonomous System) to which this IP belongs | Decimal from 0-1, may include risk level notation (Low/Medium/High) | Lower is better |
|
||||
| | Company Abuse Score | Abuse score of the company to which this IP belongs | Decimal from 0-1, may include risk level notation (Low/Medium/High) | Lower is better |
|
||||
| | Threat Level | Threat level classification of IP address | Text descriptions such as low/medium/high/critical | low is best |
|
||||
| | Traffic Proportion | Proportion of humans versus bots within the ASN country of the local IP address | Percentage | Higher human proportion is preferable |
|
||||
| Blacklist Records | Harmless Count | Number of times marked as harmless in various blacklist databases | Non-negative integer | Value itself has no good or bad |
|
||||
| | Malicious Count | Number of times marked as malicious in various blacklist databases | Non-negative integer | Lower is better |
|
||||
| | Suspicious Count | Number of times marked as suspicious in various blacklist databases | Non-negative integer | Lower is better |
|
||||
@@ -710,26 +715,27 @@ The following are the meanings corresponding to each field
|
||||
| | DNS Blacklist-Listed | Number already listed in DNS blacklists | Non-negative integer | Lower is better |
|
||||
| | DNS Blacklist-Other | Number returning other statuses in DNS blacklist checks | Non-negative integer | Value itself has no good or bad |
|
||||
|
||||
When the ASN to which this device's IP belongs has a relatively small number of IP addresses, the traffic proportion can indicate what percentage of your network neighbors constitute genuine traffic. Currently, global internet traffic is roughly 70% human and 30% bot (IPV4). If you need a comparison, use this benchmark to determine whether the ASN of your current IP has reached the internet average usage level within your country. For country-specific benchmark inquiries, you may use https://trafficbenchmark.spiritlhl.net/ to conduct your own searches and comparisons.
|
||||
|
||||
Generally speaking, checking the usage type, company type, and security information below is sufficient. The security score above is only reliable when confirmed by multiple databases, so it's not a problem to skip it. (IDC: generally buy vps identified as this much, is normal in the data center room broadcasting the type of use)
|
||||
|
||||
| Usage Type | Description |
|
||||
| ----------- | ---------- |
|
||||
| hosting | Data center network (IDC) |
|
||||
| residential | Home/Residential network (Home broadband) |
|
||||
| FixedLineISP, ISP | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| isp | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| business | Enterprise office network (Business broadband) |
|
||||
| cellular | Mobile carrier network (Home broadband) |
|
||||
| education | Educational institution network (Education network) |
|
||||
| government | Government institution network (Government network) |
|
||||
| military | Military network (Government network) |
|
||||
| DataCenter/WebHosting/Transit | Data center network (IDC) |
|
||||
| CDN | Content Delivery Network (IDC) |
|
||||
|
||||
| Company Type | Description |
|
||||
| ------------ | ------------ |
|
||||
| business | Business company (Business broadband) |
|
||||
| hosting | Hosting/Data center company (IDC) |
|
||||
| FixedLineISP, ISP | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| business | Business company (Business broadband) |
|
||||
| isp | Fixed-line Internet Service Provider (Home broadband) |
|
||||
| education | Educational institution (Education network) |
|
||||
| government | Government institution (Government network) |
|
||||
|
||||
@@ -737,6 +743,9 @@ The above type descriptions represent the original query information types. Duri
|
||||
|
||||
| Field Category | Field Name | Field Description | Possible Values | Scoring Rules |
|
||||
|---------|---------|---------|---------|---------|
|
||||
| BrowserType | Mainstream Browser | Proportion of ASN Country for Local IP | Percentage | Higher mainstream proportion preferable |
|
||||
| DeviceType | Desktop or Mobile Device | Percentage of ASN Country for Local IP | Percentage | Higher proportion of desktop/mobile devices is preferable |
|
||||
| OSType | Mainstream Operating System | Percentage of ASN Country for Local IP | Percentage | Higher proportion of mainstream systems is preferable |
|
||||
| Cloud Provider | Is Cloud Provider | Whether this IP belongs to a cloud service provider | Yes/No | No good or bad, identification only |
|
||||
| Data Center | Is Data Center | Whether this IP is located in a data center | Yes/No | No is best if concerned about unblocking |
|
||||
| Mobile | Is Mobile | Whether this IP is from a mobile device network | Yes/No | Yes is best if concerned about unblocking |
|
||||
@@ -1017,7 +1026,7 @@ IP品質によるアクセス制限に敏感なのは、実際には主要なAI
|
||||
|
||||
18個のデータベースのIP関連情報を検出し、複数のプラットフォームで対応する検出項目がすべて対応する値である場合、現在のIPが確かにそうであることを証明します。1つのデータベースソースの情報のみを信じないでください:
|
||||
|
||||
[ipinfo.io](https://ipinfo.io) [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)
|
||||
[ipinfo.io](https://ipinfo.io) [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) [cloudflare.com](https://www.cloudflare.com/)
|
||||
|
||||
以下は各フィールドの対応する意味です
|
||||
|
||||
@@ -1035,6 +1044,7 @@ IP品質によるアクセス制限に敏感なのは、実際には主要なAI
|
||||
| | ASN不正使用スコア | このIPが属するASN(自律システム)の不正使用スコア | 0-1の小数、リスクレベル表記付き(Low/Medium/High)の場合あり | 低いほど良い |
|
||||
| | 企業不正使用スコア | このIPが属する企業の不正使用スコア | 0-1の小数、リスクレベル表記付き(Low/Medium/High)の場合あり | 低いほど良い |
|
||||
| | 脅威レベル(Threat Level) | IPアドレスの脅威レベル分類 | low/medium/high/criticalなどのテキスト記述 | lowが最良 |
|
||||
| | トラフィック比率 | 本機IPのASN所在国における人間とボットの比率 | パーセンテージ | 人間比率が高いほど良い |
|
||||
| ブラックリスト記録 | 無害記録数(Harmless) | 各ブラックリストデータベースで無害とマークされた回数 | 非負整数 | 数値自体に良し悪しなし |
|
||||
| | 悪意記録数(Malicious) | 各ブラックリストデータベースで悪意があるとマークされた回数 | 非負整数 | 低いほど良い |
|
||||
| | 疑わしい記録数(Suspicious) | 各ブラックリストデータベースで疑わしいとマークされた回数 | 非負整数 | 低いほど良い |
|
||||
@@ -1044,26 +1054,27 @@ IP品質によるアクセス制限に敏感なのは、実際には主要なAI
|
||||
| | DNSブラックリスト-掲載済み | DNSブラックリストに既に掲載されている数 | 非負整数 | 低いほど良い |
|
||||
| | DNSブラックリスト-その他 | DNSブラックリストチェックで他のステータスを返した数 | 非負整数 | 数値自体に良し悪しなし |
|
||||
|
||||
本機のIPが属するASNが保有するIP数が少ない場合、トラフィック比率からネットワーク内の実際のトラフィック割合を把握できます。現在の全世界インターネットトラフィックの割合は約70%が人間、30%がボットです(IPV4)。比較が必要な場合はこの基準値を基に照らし合わせれば、当該IPのASNが自国内でインターネット平均水準に達しているか判断できます。 特定の国の基準を照会する必要がある場合は、https://trafficbenchmark.spiritlhl.net/ で自ら検索し比較することができます。
|
||||
|
||||
一般的に以下の使用タイプ、会社タイプ、そしてセキュリティ情報の判別で十分です。上記のセキュリティスコアは複数のデータベースで一致が確認された場合のみ信頼できるため、見なくても特に問題ありません。(IDC: サーバーを購入する際、一般的にこの識別されることが多い。データセンターのサーバールームでブロードキャストに使用される通常のタイプである)
|
||||
|
||||
| 使用タイプ | 説明 |
|
||||
| ----------- | ---------- |
|
||||
| hosting | データセンターネットワーク(IDC) |
|
||||
| residential | 家庭/住宅ネットワーク(家庭用回線) |
|
||||
| FixedLineISP、ISP | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| isp | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| business | 企業オフィスネットワーク(ビジネス回線) |
|
||||
| cellular | モバイル通信事業者ネットワーク(家庭用回線) |
|
||||
| education | 教育機関ネットワーク(教育ネットワーク) |
|
||||
| government | 政府機関ネットワーク(政府ネットワーク) |
|
||||
| military | 軍事ネットワーク(政府ネットワーク) |
|
||||
| DataCenter/WebHosting/Transit | データセンターネットワーク(IDC) |
|
||||
| CDN | コンテンツ配信ネットワーク(IDC) |
|
||||
|
||||
| 会社タイプ | 説明 |
|
||||
| ------------ | ------------ |
|
||||
| business | 企業会社(ビジネス回線) |
|
||||
| hosting | ホスト/データセンター会社(IDC) |
|
||||
| FixedLineISP、ISP | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| business | 企業会社(ビジネス回線) |
|
||||
| isp | 固定回線インターネットサービスプロバイダー(家庭用回線) |
|
||||
| education | 教育機関(教育ネットワーク) |
|
||||
| government | 政府機関(政府ネットワーク) |
|
||||
|
||||
@@ -1071,6 +1082,9 @@ IP品質によるアクセス制限に敏感なのは、実際には主要なAI
|
||||
|
||||
| フィールドカテゴリ | フィールド名 | フィールド説明 | 可能な値 | 評価ルール |
|
||||
|---------|---------|---------|---------|---------|
|
||||
| ブラウザタイプ | 主流ブラウザかどうか | 本機IPのASN所在国の割合 | パーセンテージ | 主流であるほど良い |
|
||||
| デバイスタイプ | デスクトップ/モバイルデバイスか | 本機IPのASN所在国の割合 | パーセンテージ | デスクトップとモバイルデバイスの割合が高いほど良い |
|
||||
| オペレーティングシステムタイプ | 主流OSか | 本機IPのASN所在国の割合 | パーセンテージ | 主流OSが多いほど良い |
|
||||
| クラウドプロバイダー | クラウドプロバイダーかどうか(Cloud Provider) | このIPがクラウドサービスプロバイダーに属しているか | Yes/No | 良し悪しはなく、識別のみ |
|
||||
| データセンター | データセンターかどうか(Data Center) | このIPがデータセンターに位置しているか | Yes/No | アンブロックを重視する場合はNoが最適 |
|
||||
| モバイルデバイス | モバイルデバイスかどうか(Mobile) | このIPがモバイルデバイスネットワークからのものか | Yes/No | アンブロックを重視する場合はYesが最適 |
|
||||
|
||||
14
go.mod
14
go.mod
@@ -4,18 +4,18 @@ go 1.25.3
|
||||
|
||||
require (
|
||||
github.com/imroc/req/v3 v3.54.0
|
||||
github.com/oneclickvirt/UnlockTests v0.0.30-20251109035206
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251102140847
|
||||
github.com/oneclickvirt/basics v0.0.16-20251030093657
|
||||
github.com/oneclickvirt/cputest v0.0.12-20250720122317
|
||||
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457
|
||||
github.com/oneclickvirt/basics v0.0.16-20251112033526
|
||||
github.com/oneclickvirt/cputest v0.0.12-20251111095842
|
||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
|
||||
github.com/oneclickvirt/disktest v0.0.10-20250924030424
|
||||
github.com/oneclickvirt/gostun v0.0.5-20250727155022
|
||||
github.com/oneclickvirt/memorytest v0.0.10-20250924154648
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251104114914
|
||||
github.com/oneclickvirt/memorytest v0.0.10-20251218032900
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251111095706
|
||||
github.com/oneclickvirt/pingtest v0.0.9-20251104112920
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900
|
||||
github.com/oneclickvirt/security v0.0.7-20251106060213
|
||||
github.com/oneclickvirt/security v0.0.8-20251112080734
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740
|
||||
)
|
||||
|
||||
|
||||
28
go.sum
28
go.sum
@@ -94,14 +94,14 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nxtrace/NTrace-core v1.4.3-rc.1 h1:V19tkw3kKAMQOOh7Ibb/jZFBk4kMUfQYmpxxtsOfYWo=
|
||||
github.com/nxtrace/NTrace-core v1.4.3-rc.1/go.mod h1:lGhfZ916pEUJh+VzWZTYu7bKBo06pAn+/gXb0A/7gGg=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.30-20251109035206 h1:c5mUPst0P0K54N5bNbNdme8C2wajSCJxZ/5+p42s7ZY=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.30-20251109035206/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251102140847 h1:OiwD06+Mql3pYP8jJFFdP3OUlCrx/qJT7y2YCd/OMiI=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251102140847/go.mod h1:mj9TSow7FNszBb3bQj2Hhm41LwBo7HQP6sgaPtovKdM=
|
||||
github.com/oneclickvirt/basics v0.0.16-20251030093657 h1:6SWWILNjJfMTXbspqYRpktUEOe/QIVhGonKO8ODC7n4=
|
||||
github.com/oneclickvirt/basics v0.0.16-20251030093657/go.mod h1:2PV+1ge01zb0Sqzj2V2I7P0wAdFSLF1XgAiumchJJbg=
|
||||
github.com/oneclickvirt/cputest v0.0.12-20250720122317 h1:toiwAK1hZE5b8klu2mOQ7J4sv5yV9lpPKwgPahfRYBQ=
|
||||
github.com/oneclickvirt/cputest v0.0.12-20250720122317/go.mod h1:vjlH8tkPFft1tlLOpeNskXVvurxkHaJ3+dgFxQGLXY4=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725 h1:VaaK2v17nLGU8FQmJRXPe2bEESzRePbGws0bfq7s/2o=
|
||||
github.com/oneclickvirt/UnlockTests v0.0.33-20251126065725/go.mod h1:oOa6wj/qECtRMxwBO6D7o0L0F0Q/5sQ747OCnFQqoGE=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457 h1:599/R/qMAtfPCPG1bPoi6KbjNJzVkKtxm8dvVIdtn5o=
|
||||
github.com/oneclickvirt/backtrace v0.0.8-20251109090457/go.mod h1:mj9TSow7FNszBb3bQj2Hhm41LwBo7HQP6sgaPtovKdM=
|
||||
github.com/oneclickvirt/basics v0.0.16-20251112033526 h1:bgoLaqStV3a6mbPiM++0mYizd278GVa6J6yeIiusV+A=
|
||||
github.com/oneclickvirt/basics v0.0.16-20251112033526/go.mod h1:2PV+1ge01zb0Sqzj2V2I7P0wAdFSLF1XgAiumchJJbg=
|
||||
github.com/oneclickvirt/cputest v0.0.12-20251111095842 h1:ixZUvIkSlsIZfsg+dNDKq/FTofEtUjfA2LtpTrNr/6s=
|
||||
github.com/oneclickvirt/cputest v0.0.12-20251111095842/go.mod h1:vjlH8tkPFft1tlLOpeNskXVvurxkHaJ3+dgFxQGLXY4=
|
||||
github.com/oneclickvirt/dd v0.0.2-20250808062818 h1:0KHrKkdpL5oBE1OHsrRd2siRw4/2k6f9LBaP7T4JpOc=
|
||||
github.com/oneclickvirt/dd v0.0.2-20250808062818/go.mod h1:tImu9sPTkLWo2tf1dEN1xQzrylWKauj9hbU8PHfyAeU=
|
||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 h1:5Pg3mK/u/vQvSz7anu0nxzrNdELi/AcDAU1mMsmPzyc=
|
||||
@@ -114,16 +114,16 @@ github.com/oneclickvirt/gostun v0.0.5-20250727155022 h1:/e3gSUrOp1tg/1NTRx+P8B51
|
||||
github.com/oneclickvirt/gostun v0.0.5-20250727155022/go.mod h1:pfp7MFZJK9n/KTLAVqqFcCAns4xqMykmjI+1UeF/vdE=
|
||||
github.com/oneclickvirt/mbw v0.0.1-20250808061222 h1:WGXOe6QvHiDRhPVMI0VcctjzW08kGvJf50yq5YeZCtw=
|
||||
github.com/oneclickvirt/mbw v0.0.1-20250808061222/go.mod h1:0Vq6NRpyLmGUdfHfL3uDcFsuZhi7KlG+OCs5ky2757Y=
|
||||
github.com/oneclickvirt/memorytest v0.0.10-20250924154648 h1:trk6oZ7xs1eVtr+6oIv5IX8LDVtEMG+E6GVzQ810BtU=
|
||||
github.com/oneclickvirt/memorytest v0.0.10-20250924154648/go.mod h1:4kiHsEWkW9r3/1ZcV5xIweU0smiKP0IRfQj74AUIiVI=
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251104114914 h1:P4nbdKcIA7+FH4feLLxfiJVf1f3ENi/oo37EsdyX9oI=
|
||||
github.com/oneclickvirt/nt3 v0.0.10-20251104114914/go.mod h1:yo1ufkduFt9QjqG7nqSUf1D3YlQOmFpdlTYniJfclQI=
|
||||
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/pingtest v0.0.9-20251104112920 h1:j3Fjhy0YHT/VF7iuAVVELaRXkquvRd64tWWfFLJs01o=
|
||||
github.com/oneclickvirt/pingtest v0.0.9-20251104112920/go.mod h1:gxwsxxwitNQiGq2OI0ZogYoOLwc8DtuOdSRe6/EvRqs=
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900 h1:AomzdppSOFB70AJESQhlp0IPbsHTTJGimAWDk2TzCWM=
|
||||
github.com/oneclickvirt/portchecker v0.0.3-20250728015900/go.mod h1:9sjMDPCd4Z40wkYB0S9gQPGH8YPtnNE1ZJthVIuHUzA=
|
||||
github.com/oneclickvirt/security v0.0.7-20251106060213 h1:vBCEFvuWpScXZ9O7Y7cW1zp1V2AfjzMN+YSBcYfpjYs=
|
||||
github.com/oneclickvirt/security v0.0.7-20251106060213/go.mod h1:YfDilPFW22szjdUNgv4VOuSwHnZzsFsdPOfRYiMoc3I=
|
||||
github.com/oneclickvirt/security v0.0.8-20251112080734 h1:WpwdGbwpiBP2YA1lNsymati5uvBbWFlN9CXHYgd3/fE=
|
||||
github.com/oneclickvirt/security v0.0.8-20251112080734/go.mod h1:aPMIwqsz7wiUH1cqvtRr9+QcQRkKzlUWecDM6SGVddc=
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740 h1:1NUrNt5ay6/xVNC5x62UrQjPqK8jgbKtyjBml/3boZg=
|
||||
github.com/oneclickvirt/speedtest v0.0.11-20251102151740/go.mod h1:fy0II2Wo7kDWVBKTwcHdodZwyfmJo0g8N9V02EwQDZE=
|
||||
github.com/oneclickvirt/stream v0.0.2-20250924154001 h1:GuJWdiPkoK84+y/+oHKr2Ghl3c/MzS9Z5m1nM+lMmy4=
|
||||
|
||||
7
goecs.go
7
goecs.go
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ecsVersion = "v0.1.101" // 融合怪版本号
|
||||
ecsVersion = "v0.1.106" // 融合怪版本号
|
||||
configs = params.NewConfig(ecsVersion) // 全局配置实例
|
||||
userSetFlags = make(map[string]bool) // 用于跟踪哪些参数是用户显式设置的
|
||||
)
|
||||
@@ -83,6 +83,7 @@ func main() {
|
||||
basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo string
|
||||
output, tempOutput string
|
||||
outputMutex sync.Mutex
|
||||
infoMutex sync.Mutex // 保护并发字符串写入
|
||||
)
|
||||
startTime := time.Now()
|
||||
uploadDone := make(chan bool, 1)
|
||||
@@ -91,9 +92,9 @@ func main() {
|
||||
go runner.HandleSignalInterrupt(sig, configs, &startTime, &output, tempOutput, uploadDone, &outputMutex)
|
||||
switch configs.Language {
|
||||
case "zh":
|
||||
runner.RunChineseTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex)
|
||||
runner.RunChineseTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
case "en":
|
||||
runner.RunEnglishTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex)
|
||||
runner.RunEnglishTests(preCheck, configs, &wg1, &wg2, &wg3, &basicInfo, &securityInfo, &emailInfo, &mediaInfo, &ptInfo, &output, tempOutput, startTime, &outputMutex, &infoMutex)
|
||||
default:
|
||||
fmt.Println("Unsupported language")
|
||||
}
|
||||
|
||||
6
goecs.sh
6
goecs.sh
@@ -152,7 +152,7 @@ goecs_check() {
|
||||
os=$(uname -s 2>/dev/null || echo "Unknown")
|
||||
arch=$(uname -m 2>/dev/null || echo "Unknown")
|
||||
check_china
|
||||
ECS_VERSION="0.1.100"
|
||||
ECS_VERSION="0.1.105"
|
||||
for api in \
|
||||
"https://api.github.com/repos/oneclickvirt/ecs/releases/latest" \
|
||||
"https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest" \
|
||||
@@ -164,8 +164,8 @@ goecs_check() {
|
||||
sleep 1
|
||||
done
|
||||
if [ -z "$ECS_VERSION" ]; then
|
||||
_yellow "Unable to get version info, using default version 0.1.100"
|
||||
ECS_VERSION="0.1.100"
|
||||
_yellow "Unable to get version info, using default version 0.1.105"
|
||||
ECS_VERSION="0.1.105"
|
||||
fi
|
||||
version_output=""
|
||||
for cmd_path in "goecs" "./goecs" "/usr/bin/goecs" "/usr/local/bin/goecs"; do
|
||||
|
||||
@@ -21,7 +21,7 @@ func GetMenuChoice(language string) string {
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer signal.Stop(sigChan)
|
||||
inputChan := make(chan string, 1)
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-sigChan:
|
||||
@@ -31,43 +31,33 @@ func GetMenuChoice(language string) string {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
go func() {
|
||||
var input string
|
||||
fmt.Print("请输入选项 / Please enter your choice: ")
|
||||
fmt.Scanln(&input)
|
||||
input = strings.TrimSpace(input)
|
||||
input = strings.TrimRight(input, "\n")
|
||||
select {
|
||||
case inputChan <- input:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case input := <-inputChan:
|
||||
re := regexp.MustCompile(`^\d+$`)
|
||||
if re.MatchString(input) {
|
||||
inChoice := input
|
||||
switch inChoice {
|
||||
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10":
|
||||
return inChoice
|
||||
default:
|
||||
if language == "zh" {
|
||||
fmt.Println("无效的选项")
|
||||
} else {
|
||||
fmt.Println("Invalid choice")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var input string
|
||||
fmt.Print("请输入选项 / Please enter your choice: ")
|
||||
fmt.Scanln(&input)
|
||||
input = strings.TrimSpace(input)
|
||||
input = strings.TrimRight(input, "\n")
|
||||
|
||||
re := regexp.MustCompile(`^\d+$`)
|
||||
if re.MatchString(input) {
|
||||
inChoice := input
|
||||
switch inChoice {
|
||||
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10":
|
||||
return inChoice
|
||||
default:
|
||||
if language == "zh" {
|
||||
fmt.Println("输入错误,请输入一个纯数字")
|
||||
fmt.Println("无效的选项")
|
||||
} else {
|
||||
fmt.Println("Invalid input, please enter a number")
|
||||
fmt.Println("Invalid choice")
|
||||
}
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ""
|
||||
} else {
|
||||
if language == "zh" {
|
||||
fmt.Println("输入错误,请输入一个纯数字")
|
||||
} else {
|
||||
fmt.Println("Invalid input, please enter a number")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,11 +53,19 @@ func NewConfig(version string) *Config {
|
||||
return &Config{
|
||||
EcsVersion: version,
|
||||
MenuMode: true,
|
||||
OnlyChinaTest: false,
|
||||
Input: "",
|
||||
Choice: "",
|
||||
ShowVersion: false,
|
||||
EnableLogger: false,
|
||||
Language: "zh",
|
||||
CpuTestMethod: "sysbench",
|
||||
CpuTestThreadMode: "multi",
|
||||
MemoryTestMethod: "stream",
|
||||
DiskTestMethod: "fio",
|
||||
DiskTestPath: "",
|
||||
DiskMultiCheck: false,
|
||||
Nt3CheckType: "ipv4",
|
||||
SpNum: 2,
|
||||
Width: 82,
|
||||
BasicStatus: true,
|
||||
@@ -70,11 +78,15 @@ func NewConfig(version string) *Config {
|
||||
BacktraceStatus: true,
|
||||
Nt3Status: true,
|
||||
SpeedTestStatus: true,
|
||||
Nt3Location: "GZ",
|
||||
Nt3CheckType: "ipv4",
|
||||
PingTestStatus: false,
|
||||
TgdcTestStatus: false,
|
||||
WebTestStatus: false,
|
||||
AutoChangeDiskMethod: true,
|
||||
FilePath: "goecs.txt",
|
||||
EnableUpload: true,
|
||||
OnlyIpInfoCheck: false,
|
||||
Help: false,
|
||||
Finish: false,
|
||||
UserSetFlags: make(map[string]bool),
|
||||
GoecsFlag: flag.NewFlagSet("goecs", flag.ContinueOnError),
|
||||
}
|
||||
@@ -87,6 +99,7 @@ func (c *Config) ParseFlags(args []string) {
|
||||
c.GoecsFlag.BoolVar(&c.ShowVersion, "v", false, "Display version information")
|
||||
c.GoecsFlag.BoolVar(&c.ShowVersion, "version", false, "Display version information")
|
||||
c.GoecsFlag.BoolVar(&c.MenuMode, "menu", true, "Enable/Disable menu mode, disable example: -menu=false")
|
||||
c.GoecsFlag.StringVar(&c.Language, "lang", "zh", "Set language (supported: en, zh)")
|
||||
c.GoecsFlag.StringVar(&c.Language, "l", "zh", "Set language (supported: en, zh)")
|
||||
c.GoecsFlag.BoolVar(&c.BasicStatus, "basic", true, "Enable/Disable basic test")
|
||||
c.GoecsFlag.BoolVar(&c.CpuTestStatus, "cpu", true, "Enable/Disable CPU test")
|
||||
@@ -102,13 +115,19 @@ func (c *Config) ParseFlags(args []string) {
|
||||
c.GoecsFlag.BoolVar(&c.TgdcTestStatus, "tgdc", false, "Enable/Disable Telegram DC test")
|
||||
c.GoecsFlag.BoolVar(&c.WebTestStatus, "web", false, "Enable/Disable popular websites test")
|
||||
c.GoecsFlag.StringVar(&c.CpuTestMethod, "cpum", "sysbench", "Set CPU test method (supported: sysbench, geekbench, winsat)")
|
||||
c.GoecsFlag.StringVar(&c.CpuTestMethod, "cpu-method", "sysbench", "Set CPU test method (supported: sysbench, geekbench, winsat)")
|
||||
c.GoecsFlag.StringVar(&c.CpuTestThreadMode, "cput", "multi", "Set CPU test thread mode (supported: single, multi)")
|
||||
c.GoecsFlag.StringVar(&c.CpuTestThreadMode, "cpu-thread", "multi", "Set CPU test thread mode (supported: single, multi)")
|
||||
c.GoecsFlag.StringVar(&c.MemoryTestMethod, "memorym", "stream", "Set memory test method (supported: stream, sysbench, dd, winsat, auto)")
|
||||
c.GoecsFlag.StringVar(&c.MemoryTestMethod, "memory-method", "stream", "Set memory test method (supported: stream, sysbench, dd, winsat, auto)")
|
||||
c.GoecsFlag.StringVar(&c.DiskTestMethod, "diskm", "fio", "Set disk test method (supported: fio, dd, winsat)")
|
||||
c.GoecsFlag.StringVar(&c.DiskTestMethod, "disk-method", "fio", "Set disk test method (supported: fio, dd, winsat)")
|
||||
c.GoecsFlag.StringVar(&c.DiskTestPath, "diskp", "", "Set disk test path, e.g., -diskp /root")
|
||||
c.GoecsFlag.BoolVar(&c.DiskMultiCheck, "diskmc", false, "Enable/Disable multiple disk checks, e.g., -diskmc=false")
|
||||
c.GoecsFlag.StringVar(&c.Nt3Location, "nt3loc", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all)")
|
||||
c.GoecsFlag.StringVar(&c.Nt3Location, "nt3-location", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD, ALL for Guangzhou, Shanghai, Beijing, Chengdu and all)")
|
||||
c.GoecsFlag.StringVar(&c.Nt3CheckType, "nt3t", "ipv4", "Set NT3 test type (supported: both, ipv4, ipv6)")
|
||||
c.GoecsFlag.StringVar(&c.Nt3CheckType, "nt3-type", "ipv4", "Set NT3 test type (supported: both, ipv4, ipv6)")
|
||||
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")
|
||||
@@ -176,16 +195,16 @@ func (c *Config) SaveUserSetParams() map[string]interface{} {
|
||||
if c.UserSetFlags["web"] {
|
||||
saved["web"] = c.WebTestStatus
|
||||
}
|
||||
if c.UserSetFlags["cpum"] {
|
||||
if c.UserSetFlags["cpum"] || c.UserSetFlags["cpu-method"] {
|
||||
saved["cpum"] = c.CpuTestMethod
|
||||
}
|
||||
if c.UserSetFlags["cput"] {
|
||||
if c.UserSetFlags["cput"] || c.UserSetFlags["cpu-thread"] {
|
||||
saved["cput"] = c.CpuTestThreadMode
|
||||
}
|
||||
if c.UserSetFlags["memorym"] {
|
||||
if c.UserSetFlags["memorym"] || c.UserSetFlags["memory-method"] {
|
||||
saved["memorym"] = c.MemoryTestMethod
|
||||
}
|
||||
if c.UserSetFlags["diskm"] {
|
||||
if c.UserSetFlags["diskm"] || c.UserSetFlags["disk-method"] {
|
||||
saved["diskm"] = c.DiskTestMethod
|
||||
}
|
||||
if c.UserSetFlags["diskp"] {
|
||||
@@ -194,10 +213,10 @@ func (c *Config) SaveUserSetParams() map[string]interface{} {
|
||||
if c.UserSetFlags["diskmc"] {
|
||||
saved["diskmc"] = c.DiskMultiCheck
|
||||
}
|
||||
if c.UserSetFlags["nt3loc"] {
|
||||
if c.UserSetFlags["nt3loc"] || c.UserSetFlags["nt3-location"] {
|
||||
saved["nt3loc"] = c.Nt3Location
|
||||
}
|
||||
if c.UserSetFlags["nt3t"] {
|
||||
if c.UserSetFlags["nt3t"] || c.UserSetFlags["nt3-type"] {
|
||||
saved["nt3t"] = c.Nt3CheckType
|
||||
}
|
||||
if c.UserSetFlags["spnum"] {
|
||||
@@ -210,72 +229,116 @@ func (c *Config) SaveUserSetParams() map[string]interface{} {
|
||||
// RestoreUserSetParams restores user-set parameters
|
||||
func (c *Config) RestoreUserSetParams(saved map[string]interface{}) {
|
||||
if val, ok := saved["basic"]; ok {
|
||||
c.BasicStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.BasicStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["cpu"]; ok {
|
||||
c.CpuTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.CpuTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["memory"]; ok {
|
||||
c.MemoryTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.MemoryTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["disk"]; ok {
|
||||
c.DiskTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.DiskTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["ut"]; ok {
|
||||
c.UtTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.UtTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["security"]; ok {
|
||||
c.SecurityTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.SecurityTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["email"]; ok {
|
||||
c.EmailTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.EmailTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["backtrace"]; ok {
|
||||
c.BacktraceStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.BacktraceStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["nt3"]; ok {
|
||||
c.Nt3Status = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.Nt3Status = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["speed"]; ok {
|
||||
c.SpeedTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.SpeedTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["ping"]; ok {
|
||||
c.PingTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.PingTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["tgdc"]; ok {
|
||||
c.TgdcTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.TgdcTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["web"]; ok {
|
||||
c.WebTestStatus = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.WebTestStatus = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["cpum"]; ok {
|
||||
c.CpuTestMethod = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.CpuTestMethod = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["cput"]; ok {
|
||||
c.CpuTestThreadMode = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.CpuTestThreadMode = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["memorym"]; ok {
|
||||
c.MemoryTestMethod = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.MemoryTestMethod = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["diskm"]; ok {
|
||||
c.DiskTestMethod = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.DiskTestMethod = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["diskp"]; ok {
|
||||
c.DiskTestPath = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.DiskTestPath = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["diskmc"]; ok {
|
||||
c.DiskMultiCheck = val.(bool)
|
||||
if boolVal, ok := val.(bool); ok {
|
||||
c.DiskMultiCheck = boolVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["nt3loc"]; ok {
|
||||
if c.Choice != "10" {
|
||||
c.Nt3Location = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.Nt3Location = strVal
|
||||
}
|
||||
}
|
||||
}
|
||||
if val, ok := saved["nt3t"]; ok {
|
||||
c.Nt3CheckType = val.(string)
|
||||
if strVal, ok := val.(string); ok {
|
||||
c.Nt3CheckType = strVal
|
||||
}
|
||||
}
|
||||
if val, ok := saved["spnum"]; ok {
|
||||
c.SpNum = val.(int)
|
||||
if intVal, ok := val.(int); ok {
|
||||
c.SpNum = intVal
|
||||
}
|
||||
}
|
||||
|
||||
c.ValidateParams()
|
||||
|
||||
@@ -2,6 +2,7 @@ package runner
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// RunChineseTests runs all tests in Chinese mode
|
||||
func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) {
|
||||
func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex, infoMutex *sync.Mutex) {
|
||||
*output = RunBasicTests(preCheck, config, basicInfo, securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunCPUTest(config, *output, tempOutput, outputMutex)
|
||||
*output = RunMemoryTest(config, *output, tempOutput, outputMutex)
|
||||
@@ -29,30 +30,39 @@ func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1,
|
||||
wg1.Add(1)
|
||||
go func() {
|
||||
defer wg1.Done()
|
||||
*mediaInfo = tests.MediaTest(config.Language)
|
||||
result := tests.MediaTest(config.Language)
|
||||
infoMutex.Lock()
|
||||
*mediaInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if config.EmailTestStatus && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
wg2.Add(1)
|
||||
go func() {
|
||||
defer wg2.Done()
|
||||
*emailInfo = email.EmailCheck()
|
||||
result := email.EmailCheck()
|
||||
infoMutex.Lock()
|
||||
*emailInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if (config.OnlyChinaTest || config.PingTestStatus) && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
wg3.Add(1)
|
||||
go func() {
|
||||
defer wg3.Done()
|
||||
*ptInfo = pt.PingTest()
|
||||
result := pt.PingTest()
|
||||
infoMutex.Lock()
|
||||
*ptInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
*output = RunSecurityTests(config, *securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
}
|
||||
if runtime.GOOS != "windows" && preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
*output = RunNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
}
|
||||
if preCheck.Connected && preCheck.StackType != "" && preCheck.StackType != "None" {
|
||||
*output = RunSpeedTests(config, *output, tempOutput, outputMutex)
|
||||
@@ -61,7 +71,7 @@ func RunChineseTests(preCheck utils.NetCheckResult, config *params.Config, wg1,
|
||||
}
|
||||
|
||||
// RunEnglishTests runs all tests in English mode
|
||||
func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex) {
|
||||
func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1, wg2, wg3 *sync.WaitGroup, basicInfo, securityInfo, emailInfo, mediaInfo, ptInfo *string, output *string, tempOutput string, startTime time.Time, outputMutex *sync.Mutex, infoMutex *sync.Mutex) {
|
||||
*output = RunBasicTests(preCheck, config, basicInfo, securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunCPUTest(config, *output, tempOutput, outputMutex)
|
||||
*output = RunMemoryTest(config, *output, tempOutput, outputMutex)
|
||||
@@ -74,19 +84,25 @@ func RunEnglishTests(preCheck utils.NetCheckResult, config *params.Config, wg1,
|
||||
wg1.Add(1)
|
||||
go func() {
|
||||
defer wg1.Done()
|
||||
*mediaInfo = tests.MediaTest(config.Language)
|
||||
result := tests.MediaTest(config.Language)
|
||||
infoMutex.Lock()
|
||||
*mediaInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
if config.EmailTestStatus {
|
||||
wg2.Add(1)
|
||||
go func() {
|
||||
defer wg2.Done()
|
||||
*emailInfo = email.EmailCheck()
|
||||
result := email.EmailCheck()
|
||||
infoMutex.Lock()
|
||||
*emailInfo = result
|
||||
infoMutex.Unlock()
|
||||
}()
|
||||
}
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunStreamingTests(config, wg1, mediaInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
*output = RunSecurityTests(config, *securityInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEmailTests(config, wg2, emailInfo, *output, tempOutput, outputMutex, infoMutex)
|
||||
*output = RunEnglishNetworkTests(config, wg3, ptInfo, *output, tempOutput, outputMutex)
|
||||
*output = RunEnglishSpeedTests(config, *output, tempOutput, outputMutex)
|
||||
}
|
||||
@@ -218,7 +234,7 @@ func RunDiskTest(config *params.Config, output, tempOutput string, outputMutex *
|
||||
}
|
||||
|
||||
// RunStreamingTests runs platform unlock tests
|
||||
func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *string, output, tempOutput string, outputMutex *sync.Mutex, infoMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
return utils.PrintAndCapture(func() {
|
||||
@@ -229,7 +245,10 @@ func RunStreamingTests(config *params.Config, wg1 *sync.WaitGroup, mediaInfo *st
|
||||
} else {
|
||||
utils.PrintCenteredTitle("Cross-Border-Platform-Unlock", config.Width)
|
||||
}
|
||||
fmt.Printf("%s", *mediaInfo)
|
||||
infoMutex.Lock()
|
||||
info := *mediaInfo
|
||||
infoMutex.Unlock()
|
||||
fmt.Printf("%s", info)
|
||||
}
|
||||
}, tempOutput, output)
|
||||
}
|
||||
@@ -251,7 +270,7 @@ func RunSecurityTests(config *params.Config, securityInfo, output, tempOutput st
|
||||
}
|
||||
|
||||
// RunEmailTests runs email port tests
|
||||
func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string, output, tempOutput string, outputMutex *sync.Mutex, infoMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
return utils.PrintAndCapture(func() {
|
||||
@@ -262,13 +281,16 @@ func RunEmailTests(config *params.Config, wg2 *sync.WaitGroup, emailInfo *string
|
||||
} else {
|
||||
utils.PrintCenteredTitle("Email-Port-Check", config.Width)
|
||||
}
|
||||
fmt.Println(*emailInfo)
|
||||
infoMutex.Lock()
|
||||
info := *emailInfo
|
||||
infoMutex.Unlock()
|
||||
fmt.Println(info)
|
||||
}
|
||||
}, tempOutput, output)
|
||||
}
|
||||
|
||||
// RunNetworkTests runs network tests (Chinese mode)
|
||||
func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex) string {
|
||||
func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string, output, tempOutput string, outputMutex *sync.Mutex, infoMutex *sync.Mutex) string {
|
||||
outputMutex.Lock()
|
||||
defer outputMutex.Unlock()
|
||||
return utils.PrintAndCapture(func() {
|
||||
@@ -280,15 +302,18 @@ func RunNetworkTests(config *params.Config, wg3 *sync.WaitGroup, ptInfo *string,
|
||||
utils.PrintCenteredTitle("三网回程路由检测", config.Width)
|
||||
tests.NextTrace3Check(config.Language, config.Nt3Location, config.Nt3CheckType)
|
||||
}
|
||||
if config.OnlyChinaTest && *ptInfo != "" {
|
||||
infoMutex.Lock()
|
||||
info := *ptInfo
|
||||
infoMutex.Unlock()
|
||||
if config.OnlyChinaTest && info != "" {
|
||||
wg3.Wait()
|
||||
utils.PrintCenteredTitle("PING值检测", config.Width)
|
||||
fmt.Println(*ptInfo)
|
||||
fmt.Println(info)
|
||||
}
|
||||
if config.PingTestStatus && *ptInfo != "" {
|
||||
if config.PingTestStatus && info != "" {
|
||||
wg3.Wait()
|
||||
utils.PrintCenteredTitle("PING值检测", config.Width)
|
||||
fmt.Println(*ptInfo)
|
||||
fmt.Println(info)
|
||||
if config.TgdcTestStatus {
|
||||
fmt.Println(pt.TelegramDCTest())
|
||||
}
|
||||
@@ -414,16 +439,26 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
|
||||
httpsURL string
|
||||
}, 1)
|
||||
if config.EnableUpload {
|
||||
// 使用context来控制上传goroutine
|
||||
uploadCtx, uploadCancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer uploadCancel()
|
||||
|
||||
go func() {
|
||||
httpURL, httpsURL := utils.ProcessAndUpload(finalOutput, config.FilePath, config.EnableUpload)
|
||||
resultChan <- struct {
|
||||
select {
|
||||
case resultChan <- struct {
|
||||
httpURL string
|
||||
httpsURL string
|
||||
}{httpURL, httpsURL}
|
||||
uploadDone <- true
|
||||
}{httpURL, httpsURL}:
|
||||
case <-uploadCtx.Done():
|
||||
// 上传被取消或超时,直接返回
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case result := <-resultChan:
|
||||
uploadCancel() // 成功完成,取消context
|
||||
if result.httpURL != "" || result.httpsURL != "" {
|
||||
if config.Language == "en" {
|
||||
fmt.Printf("Upload successfully!\nHttp URL: %s\nHttps URL: %s\n", result.httpURL, result.httpsURL)
|
||||
@@ -437,7 +472,7 @@ func HandleSignalInterrupt(sig chan os.Signal, config *params.Config, startTime
|
||||
fmt.Scanln()
|
||||
}
|
||||
os.Exit(0)
|
||||
case <-time.After(30 * time.Second):
|
||||
case <-uploadCtx.Done():
|
||||
if config.Language == "en" {
|
||||
fmt.Println("Upload timeout, program exit")
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -8,6 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func CpuTest(language, testMethod, testThread string) (realTestMethod, res string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] CpuTest panic: %v\n", r)
|
||||
res = fmt.Sprintf("\nCPU test failed: %v\n", r)
|
||||
realTestMethod = "error"
|
||||
}
|
||||
}()
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
if testMethod != "winsat" && testMethod != "" {
|
||||
// res = "Detected host is Windows, using Winsat for testing.\n"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -8,6 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func DiskTest(language, testMethod, testPath string, isMultiCheck bool, autoChange bool) (realTestMethod, res string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] DiskTest panic: %v\n", r)
|
||||
res = fmt.Sprintf("\nDisk test failed: %v\n", r)
|
||||
realTestMethod = "error"
|
||||
}
|
||||
}()
|
||||
|
||||
switch testMethod {
|
||||
case "fio":
|
||||
res = disk.FioTest(language, isMultiCheck, testPath)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -8,6 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func MemoryTest(language, testMethod string) (realTestMethod, res string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] MemoryTest panic: %v\n", r)
|
||||
res = fmt.Sprintf("\nMemory test failed: %v\n", r)
|
||||
realTestMethod = "error"
|
||||
}
|
||||
}()
|
||||
|
||||
testMethod = strings.ToLower(testMethod)
|
||||
if testMethod == "" {
|
||||
testMethod = "auto"
|
||||
@@ -15,51 +25,132 @@ func MemoryTest(language, testMethod string) (realTestMethod, res string) {
|
||||
if runtime.GOOS == "windows" {
|
||||
switch testMethod {
|
||||
case "stream":
|
||||
res = memory.WinsatTest(language)
|
||||
realTestMethod = "winsat"
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WinsatTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WindowsDDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "winsat"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
case "dd":
|
||||
res = memory.WindowsDDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res += memory.WinsatTest(language)
|
||||
realTestMethod = "winsat"
|
||||
res = memory.WinsatTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "winsat"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
case "sysbench":
|
||||
// Windows下不支持sysbench,使用stream → winsat → dd
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WinsatTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WindowsDDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "winsat"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
case "auto":
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WinsatTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WindowsDDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "winsat"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
case "winsat":
|
||||
res = memory.WinsatTest(language)
|
||||
realTestMethod = "winsat"
|
||||
case "auto", "winsat":
|
||||
res = memory.WinsatTest(language)
|
||||
realTestMethod = "winsat"
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WindowsDDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "winsat"
|
||||
}
|
||||
default:
|
||||
res = memory.WinsatTest(language)
|
||||
realTestMethod = "winsat"
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WinsatTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.WindowsDDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "winsat"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch testMethod {
|
||||
case "stream":
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res += memory.DDTest(language)
|
||||
realTestMethod = "dd"
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.DDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
case "dd":
|
||||
res = memory.DDTest(language)
|
||||
realTestMethod = "dd"
|
||||
case "sysbench":
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res += memory.DDTest(language)
|
||||
realTestMethod = "dd"
|
||||
} else {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
case "auto":
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.DDTest(language)
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
@@ -68,15 +159,68 @@ func MemoryTest(language, testMethod string) (realTestMethod, res string) {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
case "sysbench":
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.DDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
case "auto":
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.DDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
case "winsat":
|
||||
// winsat 仅 Windows 支持,非 Windows fallback 到 dd
|
||||
res = memory.DDTest(language)
|
||||
realTestMethod = "dd"
|
||||
// winsat 仅 Windows 支持,非 Windows fallback 到 stream → sysbench → dd
|
||||
res = memory.StreamTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.SysBenchTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
res = memory.DDTest(language)
|
||||
if res == "" || strings.TrimSpace(res) == "" {
|
||||
realTestMethod = ""
|
||||
} else {
|
||||
realTestMethod = "dd"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "sysbench"
|
||||
}
|
||||
} else {
|
||||
realTestMethod = "stream"
|
||||
}
|
||||
default:
|
||||
res = "Unsupported test method"
|
||||
realTestMethod = ""
|
||||
|
||||
@@ -2,14 +2,55 @@ package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/oneclickvirt/nt3/nt"
|
||||
)
|
||||
|
||||
func NextTrace3Check(language, nt3Location, nt3CheckType string) {
|
||||
// 先检查 ICMP 权限
|
||||
conn, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err != nil {
|
||||
// 没有权限,显示友好提示并跳过
|
||||
if language == "zh" {
|
||||
fmt.Println("路由追踪测试需要 root 权限或 CAP_NET_RAW 能力,已跳过")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] ICMP权限不足: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("Route tracing test requires root privileges or CAP_NET_RAW capability, skipped")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Insufficient ICMP permission: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
conn.Close()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if language == "zh" {
|
||||
fmt.Println("路由追踪测试出现错误,已跳过")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] 路由追踪panic: %v\n", r)
|
||||
} else {
|
||||
fmt.Println("Route tracing test failed, skipped")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Route tracing panic: %v\n", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
resultChan := make(chan nt.TraceResult, 100)
|
||||
go nt.TraceRoute(language, nt3Location, nt3CheckType, resultChan)
|
||||
errorOccurred := false
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errorOccurred = true
|
||||
resultChan <- nt.TraceResult{
|
||||
Index: -1,
|
||||
ISPName: "Error",
|
||||
Output: []string{fmt.Sprintf("Route tracing error: %v", r)},
|
||||
}
|
||||
close(resultChan)
|
||||
}
|
||||
}()
|
||||
nt.TraceRoute(language, nt3Location, nt3CheckType, resultChan)
|
||||
}()
|
||||
for result := range resultChan {
|
||||
if result.Index == -1 {
|
||||
for index, res := range result.Output {
|
||||
@@ -21,12 +62,18 @@ func NextTrace3Check(language, nt3Location, nt3CheckType string) {
|
||||
continue
|
||||
}
|
||||
if result.ISPName == "Error" {
|
||||
if language == "zh" {
|
||||
fmt.Println("路由追踪测试失败(可能因为权限不足),已跳过")
|
||||
} else {
|
||||
fmt.Println("Route tracing test failed (possibly due to insufficient permissions), skipped")
|
||||
}
|
||||
for _, res := range result.Output {
|
||||
res = strings.TrimSpace(res)
|
||||
if res != "" {
|
||||
fmt.Println(res)
|
||||
fmt.Fprintf(os.Stderr, "[WARN] %s\n", res)
|
||||
}
|
||||
}
|
||||
errorOccurred = true
|
||||
continue
|
||||
}
|
||||
for _, res := range result.Output {
|
||||
@@ -41,4 +88,11 @@ func NextTrace3Check(language, nt3Location, nt3CheckType string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if errorOccurred {
|
||||
if language == "zh" {
|
||||
fmt.Println("提示: 路由追踪需要 root 权限或 CAP_NET_RAW 能力")
|
||||
} else {
|
||||
fmt.Println("Hint: Route tracing requires root privileges or CAP_NET_RAW capability")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -9,10 +11,20 @@ import (
|
||||
)
|
||||
|
||||
func ShowHead(language string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] ShowHead panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
sp.ShowHead(language)
|
||||
}
|
||||
|
||||
func NearbySP() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] NearbySP panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
|
||||
sp.NearbySpeedTest()
|
||||
} else {
|
||||
@@ -21,6 +33,11 @@ func NearbySP() {
|
||||
}
|
||||
|
||||
func CustomSP(platform, operator string, num int, language string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] CustomSP panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
var url, parseType string
|
||||
if strings.ToLower(platform) == "cn" {
|
||||
if strings.ToLower(operator) == "cmcc" {
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/oneclickvirt/UnlockTests/executor"
|
||||
"github.com/oneclickvirt/UnlockTests/utils"
|
||||
"github.com/oneclickvirt/defaultset"
|
||||
)
|
||||
|
||||
func MediaTest(language string) string {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] MediaTest panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
var res string
|
||||
readStatus := executor.ReadSelect(language, "0")
|
||||
if !readStatus {
|
||||
|
||||
@@ -2,6 +2,7 @@ package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -29,12 +30,25 @@ type ConcurrentResults struct {
|
||||
var IPV4, IPV6 string
|
||||
|
||||
func UpstreamsCheck() {
|
||||
// 添加panic恢复机制
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("\n上游检测出现错误,已跳过")
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Upstream check panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
results := ConcurrentResults{}
|
||||
var wg sync.WaitGroup
|
||||
if IPV4 != "" {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] BGP info panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
for i := 0; i < 2; i++ {
|
||||
result, err := bgptools.GetPoPInfo(IPV4)
|
||||
results.bgpError = err
|
||||
@@ -51,6 +65,11 @@ func UpstreamsCheck() {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Backtrace panic: %v\n", r)
|
||||
}
|
||||
}()
|
||||
result := backtrace.BackTrace(executor.IPV6)
|
||||
results.backtraceResult = result
|
||||
}()
|
||||
|
||||
@@ -203,19 +203,10 @@ func CaptureOutput(f func()) string {
|
||||
// 替换标准输出和标准错误输出为管道写入端
|
||||
os.Stdout = stdoutPipeW
|
||||
os.Stderr = stderrPipeW
|
||||
// 恢复标准输出和标准错误输出
|
||||
defer func() {
|
||||
os.Stdout = oldStdout
|
||||
os.Stderr = oldStderr
|
||||
stdoutPipeW.Close()
|
||||
stderrPipeW.Close()
|
||||
stdoutPipeR.Close()
|
||||
stderrPipeR.Close()
|
||||
}()
|
||||
// 缓冲区
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
// 并发读取 stdout 和 stderr
|
||||
done := make(chan struct{})
|
||||
done := make(chan struct{}, 2)
|
||||
go func() {
|
||||
multiWriter := io.MultiWriter(&stdoutBuf, oldStdout)
|
||||
io.Copy(multiWriter, stdoutPipeR)
|
||||
@@ -234,6 +225,11 @@ func CaptureOutput(f func()) string {
|
||||
// 等待两个 goroutine 完成
|
||||
<-done
|
||||
<-done
|
||||
// 恢复标准输出和标准错误输出,并关闭管道读取端
|
||||
os.Stdout = oldStdout
|
||||
os.Stderr = oldStderr
|
||||
stdoutPipeR.Close()
|
||||
stderrPipeR.Close()
|
||||
// 返回捕获的输出字符串
|
||||
// stderrBuf.String()
|
||||
return stdoutBuf.String()
|
||||
@@ -317,7 +313,9 @@ func ProcessAndUpload(output string, filePath string, enableUplaod bool) (string
|
||||
// 使用 defer 来处理 panic
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Printf("处理上传时发生错误: %v\n", r)
|
||||
fmt.Fprintf(os.Stderr, "[ERROR] 处理上传时发生严重错误: %v\n", r)
|
||||
// 可以选择打印堆栈信息以便调试
|
||||
// debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
// 检查文件是否存在
|
||||
@@ -425,6 +423,8 @@ func CheckPublicAccess(timeout time.Duration) NetCheckResult {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// 记录panic但不影响其他检查,输出到stderr避免污染主输出
|
||||
fmt.Fprintf(os.Stderr, "[WARN] Panic in network check for %s (%s): %v\n", tag, addr, r)
|
||||
}
|
||||
}()
|
||||
switch kind {
|
||||
|
||||
Reference in New Issue
Block a user