Compare commits

...

23 Commits

Author SHA1 Message Date
spiritlhl
3d78128f6a fix:更新版本 2025-12-18 03:39:23 +00:00
spiritlhl
9c67a8d446 fix: 更新内存测试方法逻辑,增强对不同测试方法的支持 2025-12-18 03:35:45 +00:00
spiritlhl
014dba0ce6 feat: 添加更短的短链链接,默认不再进行任何环境安装 2025-11-29 02:49:56 +00:00
github-actions[bot]
b5fdab4b27 chore: update ECS_VERSION to 0.1.105 in goecs.sh 2025-11-26 07:43:20 +00:00
spiritlhl
16c4c2ff92 fix:统一参数解析 2025-11-26 07:20:43 +00:00
spiritlhl
e1991c850f fix:更新平台检测 2025-11-26 07:00:59 +00:00
spiritlhl
0b7c7865ff Merge pull request #15 from osscv/patch-1
Update acknowledgments in README.md
2025-11-21 20:19:02 +08:00
osscv
238ea3eb6f Update acknowledgments in README.md
Added DKLYDataHub to the list of acknowledgments.
2025-11-21 20:14:24 +08:00
spiritlhl
b859c52ba3 fix
Updated traffic proportion explanation to include IPV4 distinction.
2025-11-12 19:17:58 +08:00
spiritlhl
f1642843dd fix:添加cf的基准值比较网站 2025-11-12 17:11:12 +08:00
github-actions[bot]
90ba076afb chore: update ECS_VERSION to 0.1.104 in goecs.sh 2025-11-12 09:04:02 +00:00
spiritlhl
d31d20e16f feat:更新IP质量数据库,添加cloudflare的流量浏览器设备占比查询 2025-11-12 08:49:39 +00:00
github-actions[bot]
a4084835f9 chore: update ECS_VERSION to 0.1.103 in goecs.sh 2025-11-11 10:26:21 +00:00
spiritlhl
39c2607b42 fix:修复nexttrace权限不足时导致整个程序退出的问题 2025-11-11 10:12:27 +00:00
spiritlhl
519c0f3e86 fix:更新外部依赖库,去除可能的数据竞争 2025-11-11 10:00:19 +00:00
spiritlhl
3b5b8a348e fix:修复恶性BUG添加单项recover机制,优化整体执行的稳定性 2025-11-11 09:42:44 +00:00
spiritlhl
858585b4ff fix:处理IPV6解析不存在和不可用的两种情况,修复潜在的可能导致数组越界整个程序崩溃的问题 2025-11-11 09:04:37 +00:00
github-actions[bot]
b891416147 chore: update ECS_VERSION to 0.1.102 in goecs.sh 2025-11-09 09:21:01 +00:00
spiritlhl
8e79568895 fix:更新版本 2025-11-09 09:06:49 +00:00
spiritlhl
01aa051c96 fix:更新backtrace的IPV6检测支持更多IP段 2025-11-09 09:05:51 +00:00
spiritlhl
628a380122 fix:更新IP质量检测依赖 2025-11-09 09:03:44 +00:00
spiritlhl
2b94d289f3 fix: 更新youtube的地区识别 2025-11-09 09:02:59 +00:00
github-actions[bot]
e3676760da chore: update ECS_VERSION to 0.1.101 in goecs.sh 2025-11-09 05:15:53 +00:00
18 changed files with 612 additions and 204 deletions

View File

@@ -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进行检测感谢互联网各网站提供的查询资源
感谢

View File

@@ -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

View File

@@ -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 | 家庭/住宅网络(家宽) |
| FixedLineISPISP | 固定线路互联网服务提供商(家宽) |
| isp | 固定线路互联网服务提供商(家宽) |
| business | 企业办公网络(商宽) |
| cellular | 移动运营商网络(家宽) |
| education | 教育机构网络(教育网) |
| government | 政府机构网络(政府网) |
| military | 军事网络(政府网) |
| DataCenter/WebHosting/Transit | 数据中心网络(IDC) |
| CDN | 内容分发网络(IDC) |
| 公司类型 | 说明 |
| ------------ | ------------ |
| business | 企业公司(商宽) |
| hosting | 主机/数据中心公司(IDC) |
| FixedLineISPISP | 固定线路互联网服务提供商(家宽) |
| 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
View File

@@ -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
View File

@@ -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=

View File

@@ -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")
}

View File

@@ -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

View File

@@ -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")
}
}
}
}

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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"

View File

@@ -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)

View File

@@ -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 = ""

View File

@@ -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")
}
}
}

View File

@@ -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" {

View File

@@ -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 {

View File

@@ -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
}()

View File

@@ -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 {