Compare commits

..

12 Commits

Author SHA1 Message Date
spiritysdx
ecd61fd51b update 2024-06-30 21:13:26 +08:00
spiritysdx
3c800b5193 update 2024-06-30 20:51:03 +08:00
spiritysdx
861a8f46e4 update 2024-06-30 20:28:53 +08:00
spiritysdx
6f0b1556bb update 2024-06-30 20:15:55 +08:00
spiritysdx
ab91735695 update 2024-06-30 19:49:25 +08:00
spiritysdx
c611946a9c update 2024-06-30 18:43:33 +08:00
spiritysdx
6a0fe661fa update 2024-06-30 17:19:33 +08:00
spiritysdx
dd20c72910 update 2024-06-30 17:10:03 +08:00
spiritysdx
0de20a290f update 2024-06-30 14:00:56 +08:00
spiritysdx
b4ba95b3f6 update 2024-06-30 13:59:07 +08:00
spiritysdx
b33b588ea4 update 2024-06-30 13:44:21 +08:00
spiritysdx
9d214e2b8f update 2024-06-30 13:42:54 +08:00
12 changed files with 604 additions and 961 deletions

View File

@@ -1,4 +1,4 @@
package basic
package basic1
import "testing"

View File

@@ -1,4 +1,4 @@
package basic
package basic1
import (
"fmt"
@@ -10,7 +10,7 @@ import (
// 使用gopsutil查询可能会特别慢执行命令查询反而更快
// TODO
// 迁移Shell的完整检测逻辑使用执行命令的方式查询最后都失败才使用gopsutil查询
// 本包在main中
// 本包在main中使
func Basic(language string) {
ipInfo, _, _ := network.NetworkCheck("both", false, language)
systemInfo := system.CheckSystemInfo(language)

6
go.mod
View File

@@ -11,10 +11,10 @@ require (
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
github.com/oneclickvirt/disktest v0.0.3-20240629152513
github.com/oneclickvirt/memorytest v0.0.1-20240624151629
github.com/oneclickvirt/nt3 v0.0.1-20240627070009
github.com/oneclickvirt/nt3 v0.0.1-20240630131017
github.com/oneclickvirt/portchecker v0.0.1-20240624155429
github.com/oneclickvirt/security v0.0.1-20240625075931
github.com/oneclickvirt/speedtest v0.0.5-20240630045424
github.com/oneclickvirt/security v0.0.1-20240630101628
github.com/oneclickvirt/speedtest v0.0.6-20240630114816
)
require (

6
go.sum
View File

@@ -111,14 +111,20 @@ github.com/oneclickvirt/memorytest v0.0.1-20240624151629 h1:2rJAB3gFGlFPocIb/WRV
github.com/oneclickvirt/memorytest v0.0.1-20240624151629/go.mod h1:+YNzy+NeVg61d0kNwSyVDqHyVtKzjuRe1NvMzsDLg0I=
github.com/oneclickvirt/nt3 v0.0.1-20240627070009 h1:020pqkdGDnkIIpyNbbS1sjG1uIl3GgjeNgVqJzAw0ng=
github.com/oneclickvirt/nt3 v0.0.1-20240627070009/go.mod h1:Vb724PgpP17W09mLw5I2UZZAuYbY8WwGlKZdxRDFr0Y=
github.com/oneclickvirt/nt3 v0.0.1-20240630131017 h1:L9PkTk8ij7J/aN6WZ4VPRc6hALfre/HyHnHj1vVNAZw=
github.com/oneclickvirt/nt3 v0.0.1-20240630131017/go.mod h1:Vb724PgpP17W09mLw5I2UZZAuYbY8WwGlKZdxRDFr0Y=
github.com/oneclickvirt/portchecker v0.0.1-20240624155429 h1:+wapaOcFrg1iWJDhBKThDzppyIMY7hWxK7F5RBkZg4o=
github.com/oneclickvirt/portchecker v0.0.1-20240624155429/go.mod h1:HQxSTrqM8/QFqHMTBZ7S8H9eEO5FkUXU1eb7ZX5Mk+k=
github.com/oneclickvirt/security v0.0.1-20240625075931 h1:Vj1Wq/JVcqYpfqUWRtsITbz3zM4HxnLC0iPxxA6akP0=
github.com/oneclickvirt/security v0.0.1-20240625075931/go.mod h1:6bjZjpYJ8M3aRIcLP61b0mjYRwvtWbYkvoGjS28Bdy4=
github.com/oneclickvirt/security v0.0.1-20240630101628 h1:Ain+TvrWo22ex9CGc1Z2seOX32XIXW8ajs2K3sfd+JY=
github.com/oneclickvirt/security v0.0.1-20240630101628/go.mod h1:6bjZjpYJ8M3aRIcLP61b0mjYRwvtWbYkvoGjS28Bdy4=
github.com/oneclickvirt/speedtest v0.0.4-20240629100548 h1:DQA0R/EdtmLJrQBb9JvQBaBpcMgiGDvIHq+0quNZQQM=
github.com/oneclickvirt/speedtest v0.0.4-20240629100548/go.mod h1:JNIxUbEJD12w81b7754RLHD55fsH6wHj+fCV2PqBDhk=
github.com/oneclickvirt/speedtest v0.0.5-20240630045424 h1:LXvoAgCAJVGci0Tzm3cDgvNaezncS8R5nOn8s+p+kNA=
github.com/oneclickvirt/speedtest v0.0.5-20240630045424/go.mod h1:zd5ZgIGslmtQLQehEfRjyumlvgDHTpCSMchKfKXoASI=
github.com/oneclickvirt/speedtest v0.0.6-20240630114816 h1:gI2hqV0IwcvGqYzLhlt4w2oZvYhCL+73jftUuJYBsuI=
github.com/oneclickvirt/speedtest v0.0.6-20240630114816/go.mod h1:zd5ZgIGslmtQLQehEfRjyumlvgDHTpCSMchKfKXoASI=
github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM=
github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=

302
goecs.go
View File

@@ -3,23 +3,22 @@ package main
import (
"flag"
"fmt"
"github.com/oneclickvirt/UnlockTests/uts"
"github.com/oneclickvirt/basics/system"
"github.com/oneclickvirt/ecs/backtrace"
"github.com/oneclickvirt/ecs/commediatest"
"github.com/oneclickvirt/ecs/cputest"
"github.com/oneclickvirt/ecs/disktest"
"github.com/oneclickvirt/ecs/memorytest"
"github.com/oneclickvirt/ecs/network"
"github.com/oneclickvirt/ecs/ntrace"
"github.com/oneclickvirt/ecs/speedtest"
"github.com/oneclickvirt/ecs/unlocktest"
"github.com/oneclickvirt/ecs/utils"
"github.com/oneclickvirt/portchecker/email"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"time"
"unicode/utf8"
)
var (
@@ -35,73 +34,6 @@ var (
width = 84
)
func printCenteredTitle(title string, width int) {
titleLength := utf8.RuneCountInString(title) // 计算字符串的字符数
totalPadding := width - titleLength
padding := totalPadding / 2
paddingStr := strings.Repeat("-", padding)
fmt.Println(paddingStr + title + paddingStr + strings.Repeat("-", totalPadding%2))
}
func securityCheck() (string, string) {
var wgt sync.WaitGroup
var ipInfo, securityInfo, systemInfo string
go func() {
wgt.Add(1)
defer wgt.Done()
ipInfo, securityInfo, _ = network.NetworkCheck("both", true, language)
}()
go func() {
wgt.Add(1)
defer wgt.Done()
systemInfo = system.CheckSystemInfo(language)
}()
wgt.Wait()
basicInfo := systemInfo + ipInfo
if strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") {
uts.IPV4 = true
uts.IPV6 = true
if nt3CheckType == "" {
nt3CheckType = "ipv4"
}
} else if strings.Contains(ipInfo, "IPV4") {
uts.IPV4 = true
uts.IPV6 = false
if nt3CheckType == "" {
nt3CheckType = "ipv4"
}
} else if strings.Contains(ipInfo, "IPV6") {
uts.IPV6 = true
uts.IPV4 = false
if nt3CheckType == "" {
nt3CheckType = "ipv6"
}
}
if nt3CheckType == "ipv4" && !strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") {
nt3CheckType = "ipv6"
} else if nt3CheckType == "ipv6" && !strings.Contains(ipInfo, "IPV6") && strings.Contains(ipInfo, "IPV4") {
nt3CheckType = "ipv4"
}
basicInfo = strings.ReplaceAll(basicInfo, "\n\n", "\n")
return basicInfo, securityInfo
}
func printHead() {
if language == "zh" {
printCenteredTitle("融合怪测试", width)
fmt.Printf("版本:%s\n", ecsVersion)
fmt.Println("测评频道: https://t.me/vps_reviews\n" +
"Go项目地址https://github.com/oneclickvirt/ecs\n" +
"Shell项目地址https://github.com/spiritLHLS/ecs")
} else {
printCenteredTitle("Fusion Monster Test", width)
fmt.Printf("Version: %s\n", ecsVersion)
fmt.Println("Review Channel: https://t.me/vps_reviews\n" +
"Go Project URL: https://github.com/oneclickvirt/ecs\n" +
"Shell Project URL: https://github.com/spiritLHLS/ecs")
}
}
func main() {
flag.BoolVar(&showVersion, "v", false, "Show version information")
flag.StringVar(&language, "l", "zh", "Specify language (supported: en, zh)")
@@ -120,104 +52,136 @@ func main() {
return
}
startTime := time.Now()
var wg sync.WaitGroup
var basicInfo, securityInfo, emailInfo, mediaInfo string
if language == "zh" {
printHead()
printCenteredTitle("基础信息", width)
basicInfo, securityInfo = securityCheck()
fmt.Println(basicInfo)
printCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", cpuTestMethod), width)
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
printCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", cpuTestMethod), width)
memorytest.MemoryTest(language, memoryTestMethod)
printCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", diskTestMethod), width)
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
go func() {
var (
wg sync.WaitGroup
basicInfo, securityInfo, emailInfo, mediaInfo string
output, tempOutput string
)
output = utils.PrintAndCapture(func() {
switch language {
case "zh":
utils.PrintHead(language, width, ecsVersion)
utils.PrintCenteredTitle("基础信息", width)
basicInfo, securityInfo, nt3CheckType = utils.SecurityCheck(language, nt3CheckType)
fmt.Printf(basicInfo)
utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", cpuTestMethod), width)
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", cpuTestMethod), width)
memorytest.MemoryTest(language, memoryTestMethod)
utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", diskTestMethod), width)
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
utils.PrintCenteredTitle("御三家流媒体解锁", width)
wg.Add(2)
go func() {
defer wg.Done()
emailInfo = email.EmailCheck()
}()
go func() {
defer wg.Done()
mediaInfo = unlocktest.MediaTest(language)
}()
commediatest.ComMediaTest(language)
utils.PrintCenteredTitle("跨国流媒体解锁", width)
wg.Wait() // 后台任务含流媒体测试和邮件测试
fmt.Printf(mediaInfo)
utils.PrintCenteredTitle("IP质量检测", width)
fmt.Printf(securityInfo)
utils.PrintCenteredTitle("邮件端口检测", width)
fmt.Println(emailInfo)
if runtime.GOOS != "windows" {
utils.PrintCenteredTitle("三网回程", width)
backtrace.BackTrace()
// nexttrace 在win上不支持检测报错 bind: An invalid argument was supplied.
utils.PrintCenteredTitle("路由检测", width)
ntrace.TraceRoute3(language, nt3Location, nt3CheckType)
}
utils.PrintCenteredTitle("就近节点测速", width)
speedtest.ShowHead(language)
speedtest.NearbySP()
speedtest.CustomSP("net", "global", 4)
speedtest.CustomSP("net", "cu", spNum)
speedtest.CustomSP("net", "ct", spNum)
speedtest.CustomSP("net", "cmcc", spNum)
utils.PrintCenteredTitle("", width)
endTime := time.Now()
duration := endTime.Sub(startTime)
minutes := int(duration.Minutes())
seconds := int(duration.Seconds()) % 60
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds)
fmt.Printf("时间 : %s\n", currentTime)
utils.PrintCenteredTitle("", width)
case "en":
utils.PrintHead(language, width, ecsVersion)
utils.PrintCenteredTitle("Basic Information", width)
basicInfo, securityInfo, nt3CheckType = utils.SecurityCheck(language, nt3CheckType)
fmt.Printf(basicInfo)
utils.PrintCenteredTitle(fmt.Sprintf("CPU Test - %s Method", cpuTestMethod), width)
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
utils.PrintCenteredTitle(fmt.Sprintf("Memory Test - %s Method", memoryTestMethod), width)
utils.PrintCenteredTitle(fmt.Sprintf("Disk Test - %s Method", diskTestMethod), width)
utils.PrintCenteredTitle(fmt.Sprintf("Disk Test - %s Method", diskTestMethod), width)
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
wg.Add(1)
defer wg.Done()
emailInfo = email.EmailCheck()
}()
go func() {
wg.Add(1)
defer wg.Done()
mediaInfo = unlocktest.MediaTest(language)
}()
printCenteredTitle("御三家流媒体解锁", width)
commediatest.ComMediaTest(language)
printCenteredTitle("跨国流媒体解锁", width)
wg.Wait()
fmt.Printf(mediaInfo)
printCenteredTitle("IP质量检测", width)
fmt.Printf(securityInfo)
printCenteredTitle("邮件端口检测", width)
fmt.Println(emailInfo)
printCenteredTitle("三网回程", width)
backtrace.BackTrace()
if runtime.GOOS != "windows" {
// nexttrace 在win上不支持检测报错 bind: An invalid argument was supplied.
printCenteredTitle("路由检测", width)
ntrace.TraceRoute3(language, nt3Location, nt3CheckType)
go func() {
defer wg.Done()
emailInfo = email.EmailCheck()
}()
utils.PrintCenteredTitle("The Three Families Streaming Media Unlock", width)
commediatest.ComMediaTest(language)
utils.PrintCenteredTitle("Cross-Border Streaming Media Unlock", width)
unlocktest.MediaTest(language)
utils.PrintCenteredTitle("IP Quality Check", width)
fmt.Printf(securityInfo)
utils.PrintCenteredTitle("Email Port Check", width)
wg.Wait()
fmt.Println(emailInfo)
//utils.PrintCenteredTitle("Return Path Routing", width)
utils.PrintCenteredTitle("Nearby Node Speed Test", width)
speedtest.ShowHead(language)
speedtest.NearbySP()
speedtest.CustomSP("net", "global", -1)
utils.PrintCenteredTitle("", width)
endTime := time.Now()
duration := endTime.Sub(startTime)
minutes := int(duration.Minutes())
seconds := int(duration.Seconds()) % 60
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
fmt.Printf("Cost Time : %d 分 %d 秒\n", minutes, seconds)
fmt.Printf("Current Time : %s\n", currentTime)
utils.PrintCenteredTitle("", width)
default:
fmt.Println("Unsupported language")
}
printCenteredTitle("就近节点测速", width)
speedtest.ShowHead(language)
speedtest.NearbySP()
speedtest.CustomSP("net", "global", 4)
speedtest.CustomSP("net", "cu", spNum)
speedtest.CustomSP("net", "ct", spNum)
speedtest.CustomSP("net", "cmcc", spNum)
printCenteredTitle("", width)
endTime := time.Now()
duration := endTime.Sub(startTime)
minutes := int(duration.Minutes())
seconds := int(duration.Seconds()) % 60
fmt.Printf("花费 : %d 分 %d 秒\n", minutes, seconds)
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
fmt.Printf("时间 : %s\n", currentTime)
printCenteredTitle("", width)
} else if language == "en" {
printHead()
printCenteredTitle("Basic Information", width)
go func() {
wg.Add(1)
defer wg.Done()
basicInfo, securityInfo = securityCheck()
}()
wg.Wait()
fmt.Printf(basicInfo)
printCenteredTitle(fmt.Sprintf("CPU Test - %s Method", cpuTestMethod), width)
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
printCenteredTitle(fmt.Sprintf("Memory Test - %s Method", memoryTestMethod), width)
memorytest.MemoryTest(language, memoryTestMethod)
printCenteredTitle(fmt.Sprintf("Disk Test - %s Method", diskTestMethod), width)
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
wg.Add(1)
go func() {
defer wg.Done()
emailInfo = email.EmailCheck()
}()
printCenteredTitle("The Three Families Streaming Media Unlock", width)
commediatest.ComMediaTest(language)
printCenteredTitle("Cross-Border Streaming Media Unlock", width)
unlocktest.MediaTest(language)
printCenteredTitle("IP Quality Check", width)
fmt.Printf(securityInfo)
printCenteredTitle("Email Port Check", width)
wg.Wait()
fmt.Println(emailInfo)
//printCenteredTitle("Return Path Routing", width)
printCenteredTitle("Nearby Node Speed Test", width)
speedtest.ShowHead(language)
speedtest.NearbySP()
speedtest.CustomSP("net", "global", -1)
printCenteredTitle("", width)
endTime := time.Now()
duration := endTime.Sub(startTime)
minutes := int(duration.Minutes())
seconds := int(duration.Seconds()) % 60
fmt.Printf("Cost Time : %d 分 %d 秒\n", minutes, seconds)
currentTime := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
fmt.Printf("Current Time : %s\n", currentTime)
printCenteredTitle("", width)
}, tempOutput, output)
// 创建文件
filePath := "goecs.txt"
file, err := os.Create(filePath)
if err != nil {
fmt.Println("Can not make file:", err)
return
}
defer file.Close()
// 将 output 写入文件
// 匹配 ANSI 转义序列
ansiRegex := regexp.MustCompile("\x1B\\[[0-9;]+[a-zA-Z]")
// 移除 ANSI 转义序列
cleanedOutput := ansiRegex.ReplaceAllString(output, "")
_, err = file.WriteString(cleanedOutput)
if err != nil {
fmt.Println("Can not write file:", err)
return
}
// 获取文件的绝对路径
absPath, err := filepath.Abs(filePath)
if err != nil {
fmt.Println("Get file absPath failed:", err)
return
}
shorturl, err := utils.UploadText(absPath)
if err != nil {
fmt.Println("Upload failed, can not generate short URL.")
fmt.Println(err.Error())
}
fmt.Println("Upload successful, short URL:", shorturl)
}

508
goecs.sh
View File

@@ -5,278 +5,301 @@
# curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
cat <<"EOF"
GGG OOO EEEE CCCC SSS
G G O O E C S
G O O EEE C SSS
G GG O O E C S
GGG OOO EEEE CCCC SSS
GGGGGGGG OOOOOOO EEEEEEEE CCCCCCCCC SSSSSSSSSS
GG GG OO OO EE CC SS
GG OO OO EE CC SS
GG OO OO EE CC SS
GG OO OO EEEEEEEE CC SSSSSSSSSS
GG GGGGGG OO OO EE CC SS
GG GG OO OO EE CC SS
GG GG OO OO EE CC SS
GGGGGGGG OOOOOOO EEEEEEEE CCCCCCCCC SSSSSSSSSS
EOF
cd /root >/dev/null 2>&1
cd /root >/dev/null 2>&1
if [ ! -d "/usr/bin/" ]; then
mkdir -p "/usr/bin/"
fi
_red() { echo -e "\033[31m\033[01m$@\033[0m"; }
_green() { echo -e "\033[32m\033[01m$@\033[0m"; }
_yellow() { echo -e "\033[33m\033[01m$@\033[0m"; }
_blue() { echo -e "\033[36m\033[01m$@\033[0m"; }
check_cdn() {
local o_url=$1
for cdn_url in "${cdn_urls[@]}"; do
if curl -sL -k "$cdn_url$o_url" --max-time 6 | grep -q "success" >/dev/null 2>&1; then
export cdn_success_url="$cdn_url"
return
fi
sleep 0.5
done
export cdn_success_url=""
local o_url=$1
for cdn_url in "${cdn_urls[@]}"; do
if curl -sL -k "$cdn_url$o_url" --max-time 6 | grep -q "success" >/dev/null 2>&1; then
export cdn_success_url="$cdn_url"
return
fi
sleep 0.5
done
export cdn_success_url=""
}
check_cdn_file() {
check_cdn "https://raw.githubusercontent.com/spiritLHLS/ecs/main/back/test"
if [ -n "$cdn_success_url" ]; then
echo "CDN available, using CDN"
else
echo "No CDN available, no use CDN"
fi
check_cdn "https://raw.githubusercontent.com/spiritLHLS/ecs/main/back/test"
if [ -n "$cdn_success_url" ]; then
echo "CDN available, using CDN"
else
echo "No CDN available, no use CDN"
fi
}
goecs_check() {
os=$(uname -s)
arch=$(uname -m)
ECS_VERSION=$(curl -m 6 -sSL "https://api.github.com/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
# 如果 https://api.github.com/ 请求失败,则使用 https://githubapi.spiritlhl.workers.dev/ 此时可能宿主机无IPV4网络
if [ -z "$ECS_VERSION" ]; then
ECS_VERSION=$(curl -m 6 -sSL "https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
fi
# 如果 https://githubapi.spiritlhl.workers.dev/ 请求失败,则使用 https://githubapi.spiritlhl.top/ ,此时可能宿主机在国内
if [ -z "$ECS_VERSION" ]; then
ECS_VERSION=$(curl -m 6 -sSL "https://githubapi.spiritlhl.top/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
fi
# 检测原始goecs命令是否存在若存在则升级不存在则安装
version_output=$(goecs -v || ./goecs -v)
if [ $? -eq 0 ]; then
extracted_version=$(echo "$version_output" | grep -oP '^v\d+(\.\d+)+')
if [ -n "$extracted_version" ]; then
current_version=$(echo "$extracted_version" | cut -c 2-)
ecs_version=$ECS_VERSION
if [[ "$(echo -e "$current_version\n$ecs_version" | sort -V | tail -n 1)" == "$current_version" ]]; then
echo "goecs version ($current_version) is latest, no need to upgrade."
return
else
echo "goecs version ($current_version) < $ecs_version, need to upgrade, 5 seconds later will start to upgrade"
rm -rf /usr/bin/goecs
rm -rf goecs
fi
os=$(uname -s)
arch=$(uname -m)
ECS_VERSION=$(curl -m 6 -sSL "https://api.github.com/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
# 如果 https://api.github.com/ 请求失败,则使用 https://githubapi.spiritlhl.workers.dev/ 此时可能宿主机无IPV4网络
if [ -z "$ECS_VERSION" ]; then
ECS_VERSION=$(curl -m 6 -sSL "https://githubapi.spiritlhl.workers.dev/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
fi
else
echo "Can not find goecs, need to download and install, 5 seconds later will start to install"
fi
sleep 5
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "http://cdn2.spiritlhl.net/")
check_cdn_file
case $os in
Linux)
case $arch in
"x86_64" | "x86" | "amd64" | "x64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_amd64.tar.gz"
;;
"i386" | "i686")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_386.tar.gz"
;;
"armv7l" | "armv8" | "armv8l" | "aarch64" | "arm64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_arm64.tar.gz"
;;
# 如果 https://githubapi.spiritlhl.workers.dev/ 请求失败,则使用 https://githubapi.spiritlhl.top/ ,此时可能宿主机在国内
if [ -z "$ECS_VERSION" ]; then
ECS_VERSION=$(curl -m 6 -sSL "https://githubapi.spiritlhl.top/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
fi
# 检测原始goecs命令是否存在若存在则升级不存在则安装
version_output=$(goecs -v || ./goecs -v)
if [ $? -eq 0 ]; then
extracted_version=$(echo "$version_output" | grep -oP '^v\d+(\.\d+)+')
if [ -n "$extracted_version" ]; then
current_version=$(echo "$extracted_version" | cut -c 2-)
ecs_version=$ECS_VERSION
if [[ "$(echo -e "$current_version\n$ecs_version" | sort -V | tail -n 1)" == "$current_version" ]]; then
echo "goecs version ($current_version) is latest, no need to upgrade."
return
else
echo "goecs version ($current_version) < $ecs_version, need to upgrade, 5 seconds later will start to upgrade"
rm -rf /usr/bin/goecs
rm -rf goecs
fi
fi
else
echo "Can not find goecs, need to download and install, 5 seconds later will start to install"
fi
sleep 5
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "http://cdn2.spiritlhl.net/")
check_cdn_file
case $os in
Linux)
case $arch in
"x86_64" | "x86" | "amd64" | "x64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_amd64.tar.gz"
;;
"i386" | "i686")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_386.tar.gz"
;;
"armv7l" | "armv8" | "armv8l" | "aarch64" | "arm64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_arm64.tar.gz"
;;
*)
echo "Unsupported architecture: $arch"
exit 1
;;
esac
;;
Darwin)
case $arch in
"x86_64" | "x86" | "amd64" | "x64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_amd64.tar.gz"
;;
"armv7l" | "armv8" | "armv8l" | "aarch64" | "arm64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_arm64.tar.gz"
;;
*)
echo "Unsupported architecture: $arch"
exit 1
;;
esac
;;
*)
echo "Unsupported architecture: $arch"
exit 1
;;
echo "Unsupported operating system: $os"
exit 1
;;
esac
;;
Darwin)
case $arch in
"x86_64" | "x86" | "amd64" | "x64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_amd64.tar.gz"
;;
"armv7l" | "armv8" | "armv8l" | "aarch64" | "arm64")
wget -O goecs.tar.gz "${cdn_success_url}https://github.com/oneclickvirt/ecs/releases/download/v${ECS_VERSION}/ecs_${ECS_VERSION}_linux_arm64.tar.gz"
;;
*)
echo "Unsupported architecture: $arch"
exit 1
;;
esac
;;
*)
echo "Unsupported operating system: $os"
exit 1
;;
esac
tar -xvf goecs.tar.gz
rm -rf goecs.tar.gz
rm -rf README.md
rm -rf LICENSE
mv ecs goecs
chmod 777 goecs
cp goecs /usr/bin/goecs
echo "goecs version:"
goecs -v || ./goecs -v
tar -xvf goecs.tar.gz
rm -rf goecs.tar.gz
rm -rf README.md
rm -rf LICENSE
mv ecs goecs
sleep 1
chmod 777 goecs
rm -rf /usr/bin/goecs
sleep 1
cp goecs /usr/bin/goecs
echo "goecs version:"
goecs -v || ./goecs -v
}
InstallSysbench() {
if [ -f "/etc/centos-release" ]; then # CentOS
Var_OSRelease="centos"
elif [ -f "/etc/fedora-release" ]; then # Fedora
Var_OSRelease="fedora"
elif [ -f "/etc/redhat-release" ]; then # RedHat
Var_OSRelease="rhel"
elif [ -f "/etc/astra_version" ]; then # Astra
Var_OSRelease="astra"
elif [ -f "/etc/lsb-release" ]; then # Ubuntu
Var_OSRelease="ubuntu"
elif [ -f "/etc/debian_version" ]; then # Debian
Var_OSRelease="debian"
elif [ -f "/etc/alpine-release" ]; then # Alpine Linux
Var_OSRelease="alpinelinux"
elif [ -f "/etc/almalinux-release" ]; then # almalinux
Var_OSRelease="almalinux"
elif [ -f "/etc/arch-release" ]; then # archlinux
Var_OSRelease="arch"
elif [ -f "/etc/freebsd-update.conf" ]; then # freebsd
Var_OSRelease="freebsd"
else
Var_OSRelease="unknown" # 未知系统分支
fi
case "$Var_OSRelease" in
ubuntu | debian | astra) ! apt-get install -y sysbench && apt-get --fix-broken install -y && apt-get install --no-install-recommends -y sysbench ;;
centos | rhel | almalinux | redhat) (yum -y install epel-release && yum -y install sysbench) || (dnf install epel-release -y && dnf install sysbench -y) ;;
fedora) dnf -y install sysbench ;;
arch) pacman -S --needed --noconfirm sysbench && pacman -S --needed --noconfirm libaio && ldconfig ;;
freebsd) pkg install -y sysbench ;;
alpinelinux) echo -e "${Msg_Warning}Sysbench Module not found, installing ..." && echo -e "${Msg_Warning}SysBench Current not support Alpine Linux, Skipping..." && Var_Skip_SysBench="1" ;;
*) echo "Error: Unknown OS release: $os_release" && exit 1 ;;
esac
if [ -f "/etc/centos-release" ]; then # CentOS
Var_OSRelease="centos"
elif [ -f "/etc/fedora-release" ]; then # Fedora
Var_OSRelease="fedora"
elif [ -f "/etc/redhat-release" ]; then # RedHat
Var_OSRelease="rhel"
elif [ -f "/etc/astra_version" ]; then # Astra
Var_OSRelease="astra"
elif [ -f "/etc/lsb-release" ]; then # Ubuntu
Var_OSRelease="ubuntu"
elif [ -f "/etc/debian_version" ]; then # Debian
Var_OSRelease="debian"
elif [ -f "/etc/alpine-release" ]; then # Alpine Linux
Var_OSRelease="alpinelinux"
elif [ -f "/etc/almalinux-release" ]; then # almalinux
Var_OSRelease="almalinux"
# rockylinux
elif [ -f "/etc/arch-release" ]; then # archlinux
Var_OSRelease="arch"
elif [ -f "/etc/freebsd-update.conf" ]; then # freebsd
Var_OSRelease="freebsd"
else
Var_OSRelease="unknown" # 未知系统分支
fi
case "$Var_OSRelease" in
ubuntu | debian | astra) ! apt-get install -y sysbench && apt-get --fix-broken install -y && apt-get install --no-install-recommends -y sysbench ;;
centos | rhel | almalinux | redhat) (yum -y install epel-release && yum -y install sysbench) || (dnf install epel-release -y && dnf install sysbench -y) ;;
fedora) dnf -y install sysbench ;;
arch) pacman -S --needed --noconfirm sysbench && pacman -S --needed --noconfirm libaio && ldconfig ;;
freebsd) pkg install -y sysbench ;;
alpinelinux) echo -e "${Msg_Warning}Sysbench Module not found, installing ..." && echo -e "${Msg_Warning}SysBench Current not support Alpine Linux, Skipping..." && Var_Skip_SysBench="1" ;;
*) echo "Error: Unknown OS release: $os_release" && exit 1 ;;
esac
}
Check_SysBench() {
if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
InstallSysbench
fi
# 尝试编译安装
if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
echo -e "${Msg_Warning}Sysbench Module install Failure, trying compile modules ..."
Check_Sysbench_InstantBuild
fi
source ~/.bashrc
# 最终检测
if [ "$(command -v sysbench)" ] || [ -f "/usr/bin/sysbench" ] || [ -f "/usr/local/bin/sysbench" ]; then
_yellow "Install sysbench successfully!"
else
_red "SysBench Moudle install Failure! Try Restart Bench or Manually install it! (/usr/bin/sysbench)"
_blue "Will try to test with geekbench5 instead later on"
test_cpu_type="gb5"
fi
sleep 3
if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
InstallSysbench
fi
# 尝试编译安装
if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
echo -e "${Msg_Warning}Sysbench Module install Failure, trying compile modules ..."
Check_Sysbench_InstantBuild
fi
source ~/.bashrc
# 最终检测
if [ "$(command -v sysbench)" ] || [ -f "/usr/bin/sysbench" ] || [ -f "/usr/local/bin/sysbench" ]; then
_yellow "Install sysbench successfully!"
else
_red "SysBench Moudle install Failure! Try Restart Bench or Manually install it! (/usr/bin/sysbench)"
_blue "Will try to test with geekbench5 instead later on"
test_cpu_type="gb5"
fi
sleep 3
}
Check_Sysbench_InstantBuild() {
if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ] || [ "${Var_OSRelease}" = "almalinux" ] || [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ] || [ "${Var_OSRelease}" = "fedora" ] || [ "${Var_OSRelease}" = "arch" ] || [ "${Var_OSRelease}" = "astra" ]; then
local os_sysbench=${Var_OSRelease}
if [ "$os_sysbench" = "astra" ]; then
os_sysbench="debian"
if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ] || [ "${Var_OSRelease}" = "almalinux" ] || [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ] || [ "${Var_OSRelease}" = "fedora" ] || [ "${Var_OSRelease}" = "arch" ] || [ "${Var_OSRelease}" = "astra" ]; then
local os_sysbench=${Var_OSRelease}
if [ "$os_sysbench" = "astra" ]; then
os_sysbench="debian"
fi
echo -e "${Msg_Info}Release Detected: ${os_sysbench}"
echo -e "${Msg_Info}Preparing compile enviorment ..."
prepare_compile_env "${os_sysbench}"
echo -e "${Msg_Info}Downloading Source code (Version 1.0.20)..."
mkdir -p /tmp/sysbench_install/src/
mv /tmp/sysbench-1.0.20 /tmp/sysbench_install/src/
echo -e "${Msg_Info}Compiling Sysbench Module ..."
cd /tmp/sysbench_install/src/sysbench-1.0.20
./autogen.sh && ./configure --without-mysql && make -j8 && make install
echo -e "${Msg_Info}Cleaning up ..."
cd /tmp && rm -rf /tmp/sysbench_install/src/sysbench*
else
echo -e "${Msg_Warning}Unsupported operating system: ${Var_OSRelease}"
fi
echo -e "${Msg_Info}Release Detected: ${os_sysbench}"
echo -e "${Msg_Info}Preparing compile enviorment ..."
prepare_compile_env "${os_sysbench}"
echo -e "${Msg_Info}Downloading Source code (Version 1.0.20)..."
mkdir -p /tmp/sysbench_install/src/
mv /tmp/sysbench-1.0.20 /tmp/sysbench_install/src/
echo -e "${Msg_Info}Compiling Sysbench Module ..."
cd /tmp/sysbench_install/src/sysbench-1.0.20
./autogen.sh && ./configure --without-mysql && make -j8 && make install
echo -e "${Msg_Info}Cleaning up ..."
cd /tmp && rm -rf /tmp/sysbench_install/src/sysbench*
else
echo -e "${Msg_Warning}Unsupported operating system: ${Var_OSRelease}"
fi
}
prepare_compile_env() {
local system="$1"
if [ "${system}" = "centos" ] || [ "${system}" = "rhel" ] || [ "${system}" = "almalinux" ]; then
yum install -y epel-release
yum install -y wget curl make gcc gcc-c++ make automake libtool pkgconfig libaio-devel
elif [ "${system}" = "ubuntu" ] || [ "${system}" = "debian" ]; then
! apt-get update && apt-get --fix-broken install -y && apt-get update
! apt-get -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip && apt-get --fix-broken install -y && apt-get -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip
elif [ "${system}" = "fedora" ]; then
dnf install -y wget curl gcc gcc-c++ make automake libtool pkgconfig libaio-devel
elif [ "${system}" = "arch" ]; then
pacman -S --needed --noconfirm wget curl gcc gcc make automake libtool pkgconfig libaio lib32-libaio
else
echo -e "${Msg_Warning}Unsupported operating system: ${system}"
fi
local system="$1"
if [ "${system}" = "centos" ] || [ "${system}" = "rhel" ] || [ "${system}" = "almalinux" ]; then
yum install -y epel-release
yum install -y wget curl make gcc gcc-c++ make automake libtool pkgconfig libaio-devel
elif [ "${system}" = "ubuntu" ] || [ "${system}" = "debian" ]; then
! apt-get update && apt-get --fix-broken install -y && apt-get update
! apt-get -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip && apt-get --fix-broken install -y && apt-get -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip
elif [ "${system}" = "fedora" ]; then
dnf install -y wget curl gcc gcc-c++ make automake libtool pkgconfig libaio-devel
elif [ "${system}" = "arch" ]; then
pacman -S --needed --noconfirm wget curl gcc gcc make automake libtool pkgconfig libaio lib32-libaio
else
echo -e "${Msg_Warning}Unsupported operating system: ${system}"
fi
}
env_check() {
REGEX=("debian|astra" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora" "arch" "freebsd" "alpine" "openbsd")
RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Fedora" "Arch" "FreeBSD" "Alpine" "OpenBSD")
PACKAGE_UPDATE=("! apt-get update && apt-get --fix-broken install -y && apt-get update" "apt-get update" "yum -y update" "yum -y update" "yum -y update" "pacman -Sy" "pkg update" "apk update" "pkg_add -u")
PACKAGE_INSTALL=("apt-get -y install" "apt-get -y install" "yum -y install" "yum -y install" "yum -y install" "pacman -Sy --noconfirm --needed" "pkg install -y" "apk add")
PACKAGE_REMOVE=("apt-get -y remove" "apt-get -y remove" "yum -y remove" "yum -y remove" "yum -y remove" "pacman -Rsc --noconfirm" "pkg delete" "apk del")
PACKAGE_UNINSTALL=("apt-get -y autoremove" "apt-get -y autoremove" "yum -y autoremove" "yum -y autoremove" "yum -y autoremove" "" "pkg autoremove" "apk autoremove")
CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')" "$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(uname -s)" "$(uname -s)")
SYS="${CMD[0]}"
[[ -n $SYS ]] || exit 1
for ((int = 0; int < ${#REGEX[@]}; int++)); do
if [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]]; then
SYSTEM="${RELEASE[int]}"
[[ -n $SYSTEM ]] && break
REGEX=("debian|astra" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora" "arch" "freebsd" "alpine" "openbsd")
RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Fedora" "Arch" "FreeBSD" "Alpine" "OpenBSD")
PACKAGE_UPDATE=("! apt-get update && apt-get --fix-broken install -y && apt-get update" "apt-get update" "yum -y update" "yum -y update" "yum -y update" "pacman -Sy" "pkg update" "apk update" "pkg_add -u")
PACKAGE_INSTALL=("apt-get -y install" "apt-get -y install" "yum -y install" "yum -y install" "yum -y install" "pacman -Sy --noconfirm --needed" "pkg install -y" "apk add")
PACKAGE_REMOVE=("apt-get -y remove" "apt-get -y remove" "yum -y remove" "yum -y remove" "yum -y remove" "pacman -Rsc --noconfirm" "pkg delete" "apk del")
PACKAGE_UNINSTALL=("apt-get -y autoremove" "apt-get -y autoremove" "yum -y autoremove" "yum -y autoremove" "yum -y autoremove" "" "pkg autoremove" "apk autoremove")
CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')" "$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(uname -s)" "$(uname -s)")
SYS="${CMD[0]}"
[[ -n $SYS ]] || exit 1
for ((int = 0; int < ${#REGEX[@]}; int++)); do
if [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]]; then
SYSTEM="${RELEASE[int]}"
[[ -n $SYSTEM ]] && break
fi
done
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "http://cdn2.spiritlhl.net/")
check_cdn_file
if ! command -v dd >/dev/null 2>&1; then
_green "Installing dd"
$PACKAGE_INSTALL dd
fi
done
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "http://cdn2.spiritlhl.net/")
check_cdn_file
if ! command -v dd >/dev/null 2>&1; then
_green "Installing dd"
$PACKAGE_INSTALL dd
if ! command -v fio >/dev/null 2>&1; then
_green "Installing fio"
$PACKAGE_INSTALL fio
fi
if ! command -v fio >/dev/null 2>&1; then
_green "Installing fio"
$PACKAGE_INSTALL fio
fi
if ! command -v sysbench >/dev/null 2>&1; then
_green "Installing sysbench"
$PACKAGE_INSTALL sysbench
if [ $? -ne 0 ]; then
echo "Unable to download sysbench through the system's package manager, speak to try compiling and installing it..."
if ! wget -O /tmp/sysbench.zip "${cdn_success_url}https://github.com/akopytov/sysbench/archive/1.0.20.zip"; then
echo "wget failed, trying with curl"
curl -Lk -o /tmp/sysbench.zip "${cdn_success_url}https://github.com/akopytov/sysbench/archive/1.0.20.zip"
fi
if [ ! -f /tmp/sysbench.zip ]; then
wget -q -O /tmp/sysbench.zip "https://hub.fgit.cf/akopytov/sysbench/archive/1.0.20.zip"
fi
chmod +x /tmp/sysbench.zip
unzip /tmp/sysbench.zip -d /tmp
if ! command -v sysbench >/dev/null 2>&1; then
_green "Installing sysbench"
$PACKAGE_INSTALL sysbench
if [ $? -ne 0 ]; then
echo "Unable to download sysbench through the system's package manager, speak to try compiling and installing it..."
if ! wget -O /tmp/sysbench.zip "${cdn_success_url}https://github.com/akopytov/sysbench/archive/1.0.20.zip"; then
echo "wget failed, trying with curl"
curl -Lk -o /tmp/sysbench.zip "${cdn_success_url}https://github.com/akopytov/sysbench/archive/1.0.20.zip"
fi
if [ ! -f /tmp/sysbench.zip ]; then
wget -q -O /tmp/sysbench.zip "https://hub.fgit.cf/akopytov/sysbench/archive/1.0.20.zip"
fi
chmod +x /tmp/sysbench.zip
unzip /tmp/sysbench.zip -d /tmp
fi
fi
if ! command -v geekbench >/dev/null 2>&1; then
_green "Installing geekbench"
curl -L "${cdn_success_url}https://raw.githubusercontent.com/oneclickvirt/cputest/main/dgb.sh" -o dgb.sh && chmod +x dgb.sh
bash dgb.sh -v gb5
_blue "If you not want to use geekbench5, you can use"
echo "bash dgb.sh -v gb6"
echo "bash dgb.sh -v gb4"
_blue "to change version, or use"
echo "rm -rf /usr/bin/geekbench*"
_blue "to uninstall geekbench"
rm -rf dgb.sh
fi
if ! command -v speedtest >/dev/null 2>&1; then
_green "Installing geekbench"
curl -L "${cdn_success_url}https://raw.githubusercontent.com/oneclickvirt/speedtest/main/dspt.sh" -o dspt.sh && chmod +x dspt.sh
bash dspt.sh
rm -rf dspt.sh
_blue "if you want to use golang origin speedtest, you can use"
echo "rm -rf /usr/bin/speedtest"
echo "rm -rf /usr/bin/speedtest-go"
_blue "to uninstall speedtest and speedtest-go"
fi
fi
if ! commadn -v geekbench >/dev/null 2>&1; then
_green "Installing geekbench"
curl -L "${cdn_success_url}https://raw.githubusercontent.com/oneclickvirt/cputest/main/dgb.sh" -o dgb.sh && chmod +x dgb.sh
bash dgb.sh -v gb5
_blue "If you not want to use geekbench5, you can use"
echo "bash dgb.sh -v gb6"
echo "bash dgb.sh -v gb4"
_blue "to change version, or use"
echo "rm -rf /usr/bin/geekbench*"
_blue "to uninstall geekbench"
fi
}
show_help() {
cat <<"EOF"
cat <<"EOF"
Available commands:
env Check and install dd fio sysbench geekbench5
env Check and Install package: dd fio sysbench geekbench5 speedtest
install Install goecs command
upgrade Upgrade goecs command
help Show this message
EOF
@@ -284,20 +307,17 @@ EOF
case "$1" in
"help")
show_help
;;
show_help
;;
"env")
env_check
;;
"install")
goecs_check
;;
"upgrade")
goecs_check
;;
env_check
;;
"install" | "upgrade")
goecs_check
;;
*)
echo "No command found."
echo
show_help
;;
echo "No command found."
echo
show_help
;;
esac

View File

@@ -1,6 +1,8 @@
package main
import "testing"
import (
"testing"
)
func Test(t *testing.T) {
main()

View File

@@ -1,542 +1,8 @@
package network
package network1
import (
"fmt"
"reflect"
"runtime"
"strings"
"sync"
import "github.com/oneclickvirt/security/network"
"github.com/oneclickvirt/basics/model"
"github.com/oneclickvirt/basics/network/baseinfo"
"github.com/oneclickvirt/basics/network/utils"
. "github.com/oneclickvirt/defaultset"
"github.com/oneclickvirt/security/network/printhead"
. "github.com/oneclickvirt/security/network/security"
)
// sortAndTranslateText 对原始文本进行排序和翻译
func sortAndTranslateText(orginList []string, language string, fields []string) string {
var result string
for _, key := range fields {
var displayKey string
if language == "zh" {
displayKey = model.TranslationMap[key]
if displayKey == "" {
displayKey = key
}
} else {
displayKey = key
}
for _, line := range orginList {
if strings.Contains(line, key) {
if displayKey == key {
result = result + line + "\n"
} else {
result = result + strings.ReplaceAll(line, key, displayKey) + "\n"
}
break
}
}
}
return result
}
// fetchAndLogInfo 子函数执行和日志记录
func fetchAndLogInfo(wg *sync.WaitGroup, ip string, scorePtr **model.SecurityScore, infoPtr **model.SecurityInfo, fetchFunc func(string) (*model.SecurityScore, *model.SecurityInfo, error)) {
defer wg.Done()
var err error
if scorePtr != nil && *scorePtr != nil && infoPtr != nil && *infoPtr != nil {
*scorePtr, *infoPtr, err = fetchFunc(ip)
} else if scorePtr == nil && infoPtr != nil && *infoPtr != nil {
_, *infoPtr, err = fetchFunc(ip)
} else if scorePtr != nil && *scorePtr != nil && infoPtr == nil {
*scorePtr, _, err = fetchFunc(ip)
}
if err != nil {
if model.EnableLoger {
Logger.Info(fmt.Sprintf("%s: %s", runtime.FuncForPC(reflect.ValueOf(fetchFunc).Pointer()).Name(), err.Error()))
}
}
}
// Ipv4SecurityCheck 检测 ipv4 安全信息和安全得分
func Ipv4SecurityCheck(ipInfo *model.IpInfo, cheervisionInfo *model.SecurityInfo, language string) (string, error) {
if model.EnableLoger {
InitLogger()
defer Logger.Sync()
}
if ipInfo == nil {
if model.EnableLoger {
Logger.Info("ipv4 is not available")
}
return "", fmt.Errorf("ipv4 is not available")
}
if cheervisionInfo == nil {
if model.EnableLoger {
Logger.Info("ipv4 cheervisionInfo nil")
}
}
var (
ip, temp, orgin, result string
wg sync.WaitGroup
iPInfoIoInfo = &model.SecurityInfo{}
scamalyticsInfo = &model.SecurityInfo{}
abuseipdbInfo = &model.SecurityInfo{}
ip2locationIoInfo = &model.SecurityInfo{}
ipapicomInfo = &model.SecurityInfo{}
ipwhoisioInfo = &model.SecurityInfo{}
ipregistryCoInfo = &model.SecurityInfo{}
ipdataCoInfo = &model.SecurityInfo{}
dbIpComInfo = &model.SecurityInfo{}
ipapiisInfo = &model.SecurityInfo{}
ipapiComInfo = &model.SecurityInfo{}
abstractapiInfo = &model.SecurityInfo{}
ipqualityscoreComInfo = &model.SecurityInfo{}
scamalyticsScore = &model.SecurityScore{}
virustotalScore = &model.SecurityScore{}
abuseipdbScore = &model.SecurityScore{}
dbIpComScore = &model.SecurityScore{}
ipapiisScore = &model.SecurityScore{}
ipdataCoScore = &model.SecurityScore{}
ipapiComScore = &model.SecurityScore{}
ipqualityscoreComScore = &model.SecurityScore{}
)
ip = ipInfo.Ip
wg.Add(14)
go fetchAndLogInfo(&wg, ip, nil, &iPInfoIoInfo, IPInfoIo)
go fetchAndLogInfo(&wg, ip, &scamalyticsScore, &scamalyticsInfo, Scamalytics)
go fetchAndLogInfo(&wg, ip, &virustotalScore, nil, Virustotal)
go fetchAndLogInfo(&wg, ip, &abuseipdbScore, &abuseipdbInfo, Abuseipdb)
go fetchAndLogInfo(&wg, ip, nil, &ip2locationIoInfo, Ip2locationIo)
go fetchAndLogInfo(&wg, ip, nil, &ipapicomInfo, IpApiCom)
go fetchAndLogInfo(&wg, ip, nil, &ipwhoisioInfo, IpwhoisIo)
go fetchAndLogInfo(&wg, ip, nil, &ipregistryCoInfo, IpregistryCo)
go fetchAndLogInfo(&wg, ip, &ipdataCoScore, &ipdataCoInfo, IpdataCo)
go fetchAndLogInfo(&wg, ip, &dbIpComScore, &dbIpComInfo, DbIpCom)
go fetchAndLogInfo(&wg, ip, &ipapiisScore, &ipapiisInfo, Ipapiis)
go fetchAndLogInfo(&wg, ip, &ipapiComScore, &ipapiComInfo, IpapiCom)
go fetchAndLogInfo(&wg, ip, nil, &abstractapiInfo, Abstractapi)
go fetchAndLogInfo(&wg, ip, &ipqualityscoreComScore, &ipqualityscoreComInfo, IpqualityscoreCom)
wg.Wait()
// 构建非空信息
var allScoreList []model.SecurityScore
scorePointers := []*model.SecurityScore{virustotalScore, scamalyticsScore, abuseipdbScore, dbIpComScore,
ipapiisScore, ipapiComScore, ipdataCoScore, ipqualityscoreComScore}
for _, score := range scorePointers {
if score != nil {
allScoreList = append(allScoreList, *score)
}
}
var allInfoList []model.SecurityInfo
infoPointers := []*model.SecurityInfo{iPInfoIoInfo, scamalyticsInfo, abuseipdbInfo, ip2locationIoInfo, ipapicomInfo,
ipwhoisioInfo, ipregistryCoInfo, ipdataCoInfo, dbIpComInfo, ipapiisInfo, ipapiComInfo, abstractapiInfo,
cheervisionInfo, ipqualityscoreComInfo}
for _, info := range infoPointers {
if info != nil {
allInfoList = append(allInfoList, *info)
}
}
// 构建回传的文本内容
temp += FormatSecurityScore(allScoreList)
temp += "\n"
temp += FormatSecurityInfo(allInfoList)
// 分割输入为行
lines := strings.Split(temp, "\n")
// 初始化一个映射用于存储冒号之前的内容及其对应的行数
contentMap := make(map[string][]int)
// 遍历每一行,提取冒号之前的内容及其行数
for i, line := range lines {
// 如果行为空则跳过
if line == "" {
continue
}
// 切割行,以冒号为分隔符
parts := strings.Split(line, ":")
// 获取冒号之前的内容
content := parts[0]
// 将当前行的行号添加到映射中
contentMap[content] = append(contentMap[content], i)
}
// 遍历映射,拼接相同内容的行
for _, lineNumbers := range contentMap {
if len(lineNumbers) > 1 { // 只对有多个行的内容进行拼接
// 初始化一个字符串切片,用于存储拼接后的行
var mergedLines []string
// 遍历相同内容的行 添加当前行到拼接后的行中
for _, lineNumber := range lineNumbers {
if lineNumber == lineNumbers[0] {
mergedLines = append(mergedLines, strings.TrimSpace(lines[lineNumber]))
} else {
mergedLines = append(mergedLines, strings.TrimSpace(strings.Split(lines[lineNumber], ":")[1]))
}
}
// 将拼接后的行以空格连接起来
mergedLine := strings.Join(mergedLines, " ")
// 替换原始行中相同内容的行为拼接后的行,仅替换一次,其他行标注要删除
isMerged := false
for _, lineNumber := range lineNumbers {
if !isMerged {
lines[lineNumber] = mergedLine
isMerged = true
} else {
lines[lineNumber] += "delete"
}
}
}
}
// 删除对应的行,构建原始文本
for _, line := range lines {
if !strings.Contains(line, "delete") {
orgin = orgin + line + "\n"
}
}
orginList := strings.Split(orgin, "\n")
// 将原始文本按要求进行排序和翻译
var score model.SecurityScore
scoreFields := utils.ExtractFieldNames(&score)
var info model.SecurityInfo
infoFields := utils.ExtractFieldNames(&info)
// 拼接安全得分
if language == "zh" {
result += Blue("安全得分:") + "\n"
} else if language == "en" {
result = Blue("Security Score:") + "\n"
}
if len(scoreFields) > 4 {
result += sortAndTranslateText(orginList, language, scoreFields[:len(scoreFields)-4])
} else {
result += sortAndTranslateText(orginList, language, scoreFields)
}
// 安全信息中前三个是字符串类型的得分
result += sortAndTranslateText(orginList, language, infoFields[:3])
// 需要确保后4个属性都为对应属性时才进行说明的拼接
if len(scoreFields) > 4 {
t := ""
foundKeys := 0
for _, key := range scoreFields[len(scoreFields)-4:] {
var displayKey string
if language == "zh" {
displayKey = model.TranslationMap[key]
if displayKey == "" {
displayKey = key
}
} else {
displayKey = key
}
found := false
for _, line := range orginList {
if strings.Contains(line, key) {
key = strings.ReplaceAll(key, ": ", "")
if displayKey == key {
t = t + line + " "
} else {
t = t + strings.ReplaceAll(line, key, displayKey) + " "
}
found = true
break
}
}
if found {
foundKeys++
}
}
if foundKeys == 4 {
if language == "zh" {
result = result + "黑名单记录统计:(有多少黑名单网站有记录):\n" + t + "\n"
} else if language == "en" {
result = result + "Blacklist_Records_Statistics(how many blacklisted websites have records):\n" + t + "\n"
}
}
}
// 拼接安全信息
if language == "zh" {
result += Blue("安全信息:") + "\n"
} else if language == "en" {
result += Blue("Security Info:") + "\n"
}
result += sortAndTranslateText(orginList, language, infoFields[3:])
return result, nil
}
// Ipv6SecurityCheck 检测 ipv4 安全信息和安全得分
func Ipv6SecurityCheck(ipInfo *model.IpInfo, cheervisionInfo *model.SecurityInfo, language string) (string, error) {
if model.EnableLoger {
InitLogger()
defer Logger.Sync()
}
if ipInfo == nil {
if model.EnableLoger {
Logger.Info("ipv6 is not available")
}
return "", fmt.Errorf("ipv6 is not available")
}
if cheervisionInfo == nil {
if model.EnableLoger {
Logger.Info("ipv6 cheervisionInfo nil")
}
}
var (
ip, temp, orgin, result string
wg sync.WaitGroup
scamalyticsInfo = &model.SecurityInfo{}
abuseipdbInfo = &model.SecurityInfo{}
ipapiisInfo = &model.SecurityInfo{}
ipapiComInfo = &model.SecurityInfo{}
scamalyticsScore = &model.SecurityScore{}
abuseipdbScore = &model.SecurityScore{}
ipapiisScore = &model.SecurityScore{}
ipapiComScore = &model.SecurityScore{}
)
ip = ipInfo.Ip
wg.Add(4)
go fetchAndLogInfo(&wg, ip, &scamalyticsScore, &scamalyticsInfo, Scamalytics)
go fetchAndLogInfo(&wg, ip, &abuseipdbScore, &abuseipdbInfo, Abuseipdb)
go fetchAndLogInfo(&wg, ip, &ipapiisScore, &ipapiisInfo, Ipapiis)
go fetchAndLogInfo(&wg, ip, &ipapiComScore, &ipapiComInfo, IpapiComIpv6)
wg.Wait()
// 构建非空信息
var allScoreList []model.SecurityScore
scorePointers := []*model.SecurityScore{scamalyticsScore, abuseipdbScore, ipapiisScore, ipapiComScore}
for _, score := range scorePointers {
if score != nil {
allScoreList = append(allScoreList, *score)
}
}
var allInfoList []model.SecurityInfo
infoPointers := []*model.SecurityInfo{scamalyticsInfo, abuseipdbInfo, ipapiisInfo, ipapiComInfo, cheervisionInfo}
for _, info := range infoPointers {
if info != nil {
allInfoList = append(allInfoList, *info)
}
}
// 构建回传的文本内容
temp += FormatSecurityScore(allScoreList)
temp += "\n"
temp += FormatSecurityInfo(allInfoList)
// 分割输入为行
lines := strings.Split(temp, "\n")
// 初始化一个映射用于存储冒号之前的内容及其对应的行数
contentMap := make(map[string][]int)
// 遍历每一行,提取冒号之前的内容及其行数
for i, line := range lines {
// 如果行为空则跳过
if line == "" {
continue
}
// 切割行,以冒号为分隔符
parts := strings.Split(line, ":")
// 获取冒号之前的内容
content := parts[0]
// 将当前行的行号添加到映射中
contentMap[content] = append(contentMap[content], i)
}
// 遍历映射,拼接相同内容的行
for _, lineNumbers := range contentMap {
if len(lineNumbers) > 1 { // 只对有多个行的内容进行拼接
// 初始化一个字符串切片,用于存储拼接后的行
var mergedLines []string
// 遍历相同内容的行 添加当前行到拼接后的行中
for _, lineNumber := range lineNumbers {
if lineNumber == lineNumbers[0] {
mergedLines = append(mergedLines, strings.TrimSpace(lines[lineNumber]))
} else {
mergedLines = append(mergedLines, strings.TrimSpace(strings.Split(lines[lineNumber], ":")[1]))
}
}
// 将拼接后的行以空格连接起来
mergedLine := strings.Join(mergedLines, " ")
// 替换原始行中相同内容的行为拼接后的行,仅替换一次,其他行标注要删除
isMerged := false
for _, lineNumber := range lineNumbers {
if !isMerged {
lines[lineNumber] = mergedLine
isMerged = true
} else {
lines[lineNumber] += "delete"
}
}
}
}
// 删除对应的行,构建原始文本
for _, line := range lines {
if !strings.Contains(line, "delete") {
orgin = orgin + line + "\n"
}
}
orginList := strings.Split(orgin, "\n")
var score model.SecurityScore
scoreFields := utils.ExtractFieldNames(&score)
var info model.SecurityInfo
infoFields := utils.ExtractFieldNames(&info)
// 拼接安全得分
if language == "zh" {
result += Blue("安全得分:") + "\n"
} else if language == "en" {
result = Blue("Security Score:") + "\n"
}
result += sortAndTranslateText(orginList, language, scoreFields)
result += sortAndTranslateText(orginList, language, infoFields[:3])
// 拼接完整安全信息
if language == "zh" {
result += Blue("安全信息:") + "\n"
} else if language == "en" {
result += Blue("Security Info:") + "\n"
}
result += sortAndTranslateText(orginList, language, infoFields[3:])
return result, nil
}
// processPrintIPInfo 处理IP信息
func processPrintIPInfo(headASNString string, headLocationString string, ipResult *model.IpInfo) string {
var info string
// 处理ASN信息
if ipResult.ASN != "" || ipResult.Org != "" {
info += headASNString
if ipResult.ASN != "" {
info += "AS" + ipResult.ASN
if ipResult.Org != "" {
info += " "
}
}
info += ipResult.Org + "\n"
}
// 处理位置信息
if ipResult.City != "" || ipResult.Region != "" || ipResult.Country != "" {
info += headLocationString
if ipResult.City != "" {
info += ipResult.City + " / "
}
if ipResult.Region != "" {
info += ipResult.Region + " / "
}
if ipResult.Country != "" {
info += ipResult.Country
}
info += "\n"
}
return info
}
// NetworkCheck 查询网络信息
// checkType 可选 both ipv4 ipv6
// enableSecurityCheck 可选 true false
// language 暂时仅支持 en 或 zh
// 回传 ipInfo securityInfo err
// 本包在main中不使用
func NetworkCheck(checkType string, enableSecurityCheck bool, language string) (string, string, error) {
var ipInfo, securityInfo string
if checkType == "both" {
ipInfoV4Result, cheervisionInfoV4, ipInfoV6Result, cheervisionInfoV6, _ := baseinfo.RunIpCheck("both")
if ipInfoV4Result != nil {
ipInfo += processPrintIPInfo(" IPV4 ASN : ", " IPV4 Location : ", ipInfoV4Result)
}
if ipInfoV6Result != nil {
ipInfo += processPrintIPInfo(" IPV6 ASN : ", " IPV6 Location : ", ipInfoV6Result)
}
// 检测是否需要查询相关安全信息
if enableSecurityCheck {
var (
wg sync.WaitGroup
ipv4Res, ipv6Res, ipv4DNSRes, ipv6DNSRes string
err1, err2 error
)
wg.Add(4)
go func() {
defer wg.Done()
ipv4DNSRes = BlackList(ipInfoV4Result, "ipv4", language)
}()
go func() {
defer wg.Done()
ipv6DNSRes = BlackList(ipInfoV6Result, "ipv6", language)
}()
go func() {
defer wg.Done()
ipv4Res, err1 = Ipv4SecurityCheck(ipInfoV4Result, cheervisionInfoV4, language)
}()
go func() {
defer wg.Done()
ipv6Res, err2 = Ipv6SecurityCheck(ipInfoV6Result, cheervisionInfoV6, language)
}()
wg.Wait()
securityHead, err3 := printhead.PrintDatabaseInfo(language)
if err1 == nil && err2 == nil && err3 == nil {
securityInfo = securityHead + Green("IPV4:") + "\n" + ipv4Res + ipv4DNSRes + Green("IPV6:") + "\n" + ipv6Res + ipv6DNSRes
return ipInfo, securityInfo, nil
} else if err1 == nil && err2 != nil && err3 == nil {
securityInfo = securityHead + Green("IPV4:") + "\n" + ipv4Res + ipv4DNSRes
return ipInfo, securityInfo, nil
} else if err1 != nil && err2 == nil && err3 == nil {
securityInfo = securityHead + Green("IPV6:") + "\n" + ipv6Res + ipv6DNSRes
return ipInfo, securityInfo, nil
} else {
return ipInfo, "", nil
}
} else {
return ipInfo, "", nil
}
} else if checkType == "ipv4" {
ipInfoV4Result, cheervisionInfoV4, _, _, _ := baseinfo.RunIpCheck("ipv4")
if ipInfoV4Result != nil {
ipInfo += processPrintIPInfo(" IPV4 ASN : ", " IPV4 Location : ", ipInfoV4Result)
}
if enableSecurityCheck {
var (
wg sync.WaitGroup
ipv4Res, ipv4DNSRes string
err1 error
)
wg.Add(2)
go func() {
defer wg.Done()
ipv4DNSRes = BlackList(ipInfoV4Result, "ipv4", language)
}()
go func() {
defer wg.Done()
ipv4Res, err1 = Ipv4SecurityCheck(ipInfoV4Result, cheervisionInfoV4, language)
}()
wg.Wait()
securityHead, err2 := printhead.PrintDatabaseInfo(language)
if err1 == nil && err2 == nil {
securityInfo = securityHead + Green("IPV4:") + "\n" + ipv4Res + ipv4DNSRes
return ipInfo, securityInfo, nil
} else {
return ipInfo, "", nil
}
} else {
return ipInfo, "", nil
}
} else if checkType == "ipv6" {
_, _, ipInfoV6Result, cheervisionInfoV6, _ := baseinfo.RunIpCheck("ipv6")
if ipInfoV6Result != nil {
ipInfo += processPrintIPInfo(" IPV6 ASN : ", " IPV6 Location : ", ipInfoV6Result)
}
if enableSecurityCheck {
var (
wg sync.WaitGroup
ipv6Res, ipv6DNSRes string
err1 error
)
wg.Add(2)
go func() {
defer wg.Done()
ipv6DNSRes = BlackList(ipInfoV6Result, "ipv6", language)
}()
go func() {
defer wg.Done()
ipv6Res, err1 = Ipv6SecurityCheck(ipInfoV6Result, cheervisionInfoV6, language)
}()
wg.Wait()
securityHead, err2 := printhead.PrintDatabaseInfo(language)
if err1 == nil && err2 == nil {
securityInfo = securityHead + Green("IPV6:") + "\n" + ipv6Res + ipv6DNSRes
return ipInfo, securityInfo, nil
} else {
return ipInfo, "", nil
}
} else {
return ipInfo, "", nil
}
}
return "", "", fmt.Errorf("wrong in NetworkCheck")
return network.NetworkCheck(checkType, enableSecurityCheck, language)
}

View File

@@ -1,4 +1,4 @@
package network
package network1
import (
"fmt"

View File

@@ -6,6 +6,7 @@ import (
)
// 常用端口阻断检测 TCP/UDP/ICMP 协议
// 本包不在main中使用
func EmailCheck() {
res := email.EmailCheck()
fmt.Println(res)

View File

@@ -3,6 +3,7 @@ package speedtest
import (
"github.com/oneclickvirt/speedtest/model"
"github.com/oneclickvirt/speedtest/sp"
"runtime"
"strings"
)
@@ -11,7 +12,11 @@ func ShowHead(language string) {
}
func NearbySP() {
sp.NearbySpeedTest()
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
sp.NearbySpeedTest()
} else {
sp.OfficialNearbySpeedTest()
}
}
func CustomSP(platform, operator string, num int) {
@@ -53,5 +58,9 @@ func CustomSP(platform, operator string, num int) {
}
parseType = "id"
}
sp.CustomSpeedTest(url, parseType, num)
if runtime.GOOS == "windows" || sp.OfficialAvailableTest() != nil {
sp.CustomSpeedTest(url, parseType, num)
} else {
sp.OfficialCustomSpeedTest(url, parseType, num)
}
}

175
utils/utils.go Normal file
View File

@@ -0,0 +1,175 @@
package utils
import (
"bytes"
"fmt"
"github.com/imroc/req/v3"
"github.com/oneclickvirt/UnlockTests/uts"
"github.com/oneclickvirt/basics/system"
"github.com/oneclickvirt/security/network"
"io"
"os"
"strings"
"sync"
"unicode/utf8"
)
// PrintCenteredTitle 根据指定的宽度打印居中标题
func PrintCenteredTitle(title string, width int) {
// 计算字符串的字符数
titleLength := utf8.RuneCountInString(title)
totalPadding := width - titleLength
padding := totalPadding / 2
paddingStr := strings.Repeat("-", padding)
fmt.Println(paddingStr + title + paddingStr + strings.Repeat("-", totalPadding%2))
}
// PrintHead 根据语言打印头部信息
func PrintHead(language string, width int, ecsVersion string) {
if language == "zh" {
PrintCenteredTitle("融合怪测试", width)
fmt.Printf("版本:%s\n", ecsVersion)
fmt.Println("测评频道: https://t.me/vps_reviews\n" +
"Go项目地址https://github.com/oneclickvirt/ecs\n" +
"Shell项目地址https://github.com/spiritLHLS/ecs")
} else {
PrintCenteredTitle("Fusion Monster Test", width)
fmt.Printf("Version: %s\n", ecsVersion)
fmt.Println("Review Channel: https://t.me/vps_reviews\n" +
"Go Project URL: https://github.com/oneclickvirt/ecs\n" +
"Shell Project URL: https://github.com/spiritLHLS/ecs")
}
}
// SecurityCheck 执行安全检查
func SecurityCheck(language, nt3CheckType string) (string, string, string) {
var wgt sync.WaitGroup
var ipInfo, securityInfo, systemInfo string
var err error
wgt.Add(2)
go func() {
defer wgt.Done()
ipInfo, securityInfo, err = network.NetworkCheck("both", true, language)
if err != nil {
fmt.Println(err.Error())
}
}()
go func() {
defer wgt.Done()
systemInfo = system.CheckSystemInfo(language)
}()
wgt.Wait()
basicInfo := systemInfo + ipInfo
if strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") {
uts.IPV4 = true
uts.IPV6 = true
if nt3CheckType == "" {
nt3CheckType = "ipv4"
}
} else if strings.Contains(ipInfo, "IPV4") {
uts.IPV4 = true
uts.IPV6 = false
if nt3CheckType == "" {
nt3CheckType = "ipv4"
}
} else if strings.Contains(ipInfo, "IPV6") {
uts.IPV6 = true
uts.IPV4 = false
if nt3CheckType == "" {
nt3CheckType = "ipv6"
}
}
if nt3CheckType == "ipv4" && !strings.Contains(ipInfo, "IPV4") && strings.Contains(ipInfo, "IPV6") {
nt3CheckType = "ipv6"
} else if nt3CheckType == "ipv6" && !strings.Contains(ipInfo, "IPV6") && strings.Contains(ipInfo, "IPV4") {
nt3CheckType = "ipv4"
}
basicInfo = strings.ReplaceAll(basicInfo, "\n\n", "\n")
return basicInfo, securityInfo, nt3CheckType
}
// CaptureOutput 捕获函数输出和错误输出并返回字符串
func CaptureOutput(f func()) string {
// 保存旧的 stdout 和 stderr
oldStdout := os.Stdout
oldStderr := os.Stderr
// 创建管道
stdoutPipeR, stdoutPipeW, err := os.Pipe()
if err != nil {
return "Error creating stdout pipe"
}
stderrPipeR, stderrPipeW, err := os.Pipe()
if err != nil {
stdoutPipeW.Close()
stdoutPipeR.Close()
return "Error creating stderr pipe"
}
// 替换标准输出和标准错误输出为管道写入端
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{})
go func() {
multiWriter := io.MultiWriter(&stdoutBuf, oldStdout)
io.Copy(multiWriter, stdoutPipeR)
done <- struct{}{}
}()
go func() {
multiWriter := io.MultiWriter(&stderrBuf, oldStderr)
io.Copy(multiWriter, stderrPipeR)
done <- struct{}{}
}()
// 执行函数
f()
// 关闭管道写入端,让管道读取端可以读取所有数据
stdoutPipeW.Close()
stderrPipeW.Close()
// 等待两个 goroutine 完成
<-done
<-done
// 返回捕获的输出字符串
return stdoutBuf.String() + stderrBuf.String()
}
// PrintAndCapture 捕获函数输出的同时打印内容
func PrintAndCapture(f func(), tempOutput, output string) string {
tempOutput = CaptureOutput(f)
output += tempOutput
return output
}
// UploadText 上传文本内容到指定URL
func UploadText(absPath string) (string, error) {
url := "https://paste.spiritlhl.net/api/upload"
token := network.SecurityUploadToken
client := req.DefaultClient()
file, _ := os.Open(absPath)
resp, err := client.R().
SetHeader("Authorization", token).
SetHeader("Format", "RANDOM").
SetHeader("Max-Views", "0").
SetHeader("UploadText", "true").
SetHeader("Content-Type", "multipart/form-data").
SetHeader("No-JSON", "true").
SetFileReader("file", "goecs.txt", file).
Post(url)
if err != nil {
return "", err
}
if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
return resp.String(), nil
} else {
return "", fmt.Errorf("upload failed with status code: %d", resp.StatusCode)
}
}