mirror of
https://github.com/oneclickvirt/ecs.git
synced 2025-09-29 04:32:11 +08:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9565248f95 | ||
![]() |
1d6cd5984b | ||
![]() |
63b857c915 | ||
![]() |
6811f19db4 | ||
![]() |
847e1c0d6e | ||
![]() |
99a8448d53 | ||
![]() |
4fe9cd21ef | ||
![]() |
bdb53ac436 | ||
![]() |
01b9ee4505 | ||
![]() |
fadbf9c6aa | ||
![]() |
60e235e4d7 | ||
![]() |
da4b431761 | ||
![]() |
7fff30521e | ||
![]() |
e7c78774ca | ||
![]() |
fb6f9da14c | ||
![]() |
7b1773c5f0 | ||
![]() |
7b15a74448 | ||
![]() |
956f65941e | ||
![]() |
6d1f806e94 | ||
![]() |
d727d6b778 | ||
![]() |
ea891861b3 | ||
![]() |
e0826a80c8 | ||
![]() |
74868a918e | ||
![]() |
889ecee3f3 | ||
![]() |
f6dd0bbb56 | ||
![]() |
01686f3e9d | ||
![]() |
5a6cd7d671 | ||
![]() |
35e183b640 | ||
![]() |
a684052966 | ||
![]() |
2beb74c319 | ||
![]() |
5218c95162 | ||
![]() |
83be2066c8 | ||
![]() |
975bcbfc00 | ||
![]() |
dbddbc29a3 |
124
README.md
124
README.md
@@ -27,4 +27,126 @@ Shell版本: https://github.com/spiritLHLS/ecs
|
|||||||
|
|
||||||
## 说明
|
## 说明
|
||||||
|
|
||||||
开发中,勿要使用
|
开发中,勿要使用
|
||||||
|
|
||||||
|
下载脚本
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
或
|
||||||
|
|
||||||
|
```
|
||||||
|
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
|
||||||
|
|
||||||
|
```
|
||||||
|
./goecs.sh install
|
||||||
|
```
|
||||||
|
|
||||||
|
升级goecs
|
||||||
|
|
||||||
|
```
|
||||||
|
./goecs.sh upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
卸载goecs
|
||||||
|
|
||||||
|
```
|
||||||
|
./goecs.sh delete
|
||||||
|
```
|
||||||
|
|
||||||
|
shell脚本的说明
|
||||||
|
|
||||||
|
```
|
||||||
|
Available commands:
|
||||||
|
|
||||||
|
./goecs.sh env Check and Install package:
|
||||||
|
tar (Almost all unix-like systems have it.)
|
||||||
|
unzip (Almost all unix-like systems have it.)
|
||||||
|
dd (Almost all unix-like systems have it.)
|
||||||
|
fio (Almost all unix-like systems can be installed through the system's package manager.)
|
||||||
|
sysbench (Almost all unix-like systems can be installed through the system's package manager.)
|
||||||
|
geekbench (geekbench5)(Only support IPV4 environment, and memory greater than 1GB network detection, only support amd64 and arm64 architecture.)
|
||||||
|
speedtest (Use the officially provided binaries for more accurate test results.)
|
||||||
|
In fact, sysbench/geekbench is the only one of the above dependencies that must be installed, without which the CPU score cannot be tested.
|
||||||
|
./goecs.sh install Install goecs command
|
||||||
|
./goecs.sh upgrade Upgrade goecs command
|
||||||
|
./goecs.sh delete Uninstall goecs command
|
||||||
|
./goecs.sh help Show this message
|
||||||
|
```
|
||||||
|
|
||||||
|
goecs唤起菜单
|
||||||
|
|
||||||
|
```
|
||||||
|
goecs
|
||||||
|
```
|
||||||
|
|
||||||
|
或
|
||||||
|
|
||||||
|
```
|
||||||
|
./goecs
|
||||||
|
```
|
||||||
|
|
||||||
|
goecs命令参数化
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: goecs [options]
|
||||||
|
-backtrace
|
||||||
|
Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
|
||||||
|
-basic
|
||||||
|
Enable/Disable basic test (default true)
|
||||||
|
-comm
|
||||||
|
Enable/Disable common media test (default true)
|
||||||
|
-cpu
|
||||||
|
Enable/Disable CPU test (default true)
|
||||||
|
-cpum string
|
||||||
|
Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
|
||||||
|
-cput 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")
|
||||||
|
-diskmc
|
||||||
|
Enable/Disable multiple disk checks, e.g., -diskmc=false
|
||||||
|
-diskp string
|
||||||
|
Set disk test path, e.g., -diskp /root
|
||||||
|
-email
|
||||||
|
Enable/Disable email port test (default true)
|
||||||
|
-h Show help information
|
||||||
|
-l 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: sysbench, dd, winsat) (default "dd")
|
||||||
|
-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 for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ")
|
||||||
|
-nt3t string
|
||||||
|
Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
|
||||||
|
-security
|
||||||
|
Enable/Disable security test (default true)
|
||||||
|
-speed
|
||||||
|
Enable/Disable speed test (default true)
|
||||||
|
-spnum int
|
||||||
|
Set the number of servers per operator for speed test (default 2)
|
||||||
|
-ut
|
||||||
|
Enable/Disable unlock media test (default true)
|
||||||
|
-v Display version information
|
||||||
|
```
|
10
go.mod
10
go.mod
@@ -7,14 +7,15 @@ require (
|
|||||||
github.com/oneclickvirt/CommonMediaTests v0.0.2-20240630023003
|
github.com/oneclickvirt/CommonMediaTests v0.0.2-20240630023003
|
||||||
github.com/oneclickvirt/UnlockTests v0.0.10-20240630044930
|
github.com/oneclickvirt/UnlockTests v0.0.10-20240630044930
|
||||||
github.com/oneclickvirt/backtrace v0.0.4-20240624090335
|
github.com/oneclickvirt/backtrace v0.0.4-20240624090335
|
||||||
github.com/oneclickvirt/basics v0.0.3-20240625075226
|
github.com/oneclickvirt/basics v0.0.5-20240702021800
|
||||||
github.com/oneclickvirt/cputest v0.0.6-20240630144058
|
github.com/oneclickvirt/cputest v0.0.8-20240701113350
|
||||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
|
github.com/oneclickvirt/defaultset v0.0.2-20240624082446
|
||||||
github.com/oneclickvirt/disktest v0.0.3-20240629152513
|
github.com/oneclickvirt/disktest v0.0.3-20240629152513
|
||||||
github.com/oneclickvirt/memorytest v0.0.1-20240624151629
|
github.com/oneclickvirt/gostun v0.0.2-20240625025941
|
||||||
|
github.com/oneclickvirt/memorytest v0.0.2-20240702031042
|
||||||
github.com/oneclickvirt/nt3 v0.0.2-20240630152642
|
github.com/oneclickvirt/nt3 v0.0.2-20240630152642
|
||||||
github.com/oneclickvirt/portchecker v0.0.1-20240624155429
|
github.com/oneclickvirt/portchecker v0.0.1-20240624155429
|
||||||
github.com/oneclickvirt/security v0.0.2-20240630142358
|
github.com/oneclickvirt/security v0.0.4-20240702031253
|
||||||
github.com/oneclickvirt/speedtest v0.0.6-20240630114816
|
github.com/oneclickvirt/speedtest v0.0.6-20240630114816
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,7 +48,6 @@ require (
|
|||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/nxtrace/NTrace-core v1.3.1 // indirect
|
github.com/nxtrace/NTrace-core v1.3.1 // indirect
|
||||||
github.com/oneclickvirt/gostun v0.0.2-20240625025941 // indirect
|
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
|
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
16
go.sum
16
go.sum
@@ -81,24 +81,24 @@ github.com/oneclickvirt/UnlockTests v0.0.10-20240630044930 h1:/Sc4Eas1Pso18ak93w
|
|||||||
github.com/oneclickvirt/UnlockTests v0.0.10-20240630044930/go.mod h1:HP3CvAS+AJWxxY+BVbxIOlvaQ87YOSge89vAMG52b5o=
|
github.com/oneclickvirt/UnlockTests v0.0.10-20240630044930/go.mod h1:HP3CvAS+AJWxxY+BVbxIOlvaQ87YOSge89vAMG52b5o=
|
||||||
github.com/oneclickvirt/backtrace v0.0.4-20240624090335 h1:0LP5KyA6GLlqQAtOF0uyBSAykHJrzOA96Eb87qUhGQw=
|
github.com/oneclickvirt/backtrace v0.0.4-20240624090335 h1:0LP5KyA6GLlqQAtOF0uyBSAykHJrzOA96Eb87qUhGQw=
|
||||||
github.com/oneclickvirt/backtrace v0.0.4-20240624090335/go.mod h1:zvsC7xY/WZqs5KL2JB967OVnuqjNbxu9bW6wXRLo5h8=
|
github.com/oneclickvirt/backtrace v0.0.4-20240624090335/go.mod h1:zvsC7xY/WZqs5KL2JB967OVnuqjNbxu9bW6wXRLo5h8=
|
||||||
github.com/oneclickvirt/basics v0.0.3-20240625075226 h1:K9VriCHIYnXPZXBSn9PRQX+jBS6AIFH8tBVb/i8VGAw=
|
github.com/oneclickvirt/basics v0.0.5-20240702021800 h1:+iiT/5pF/xsn1iah1q7tdfm1hnAUgYXutRaJUUbNNWo=
|
||||||
github.com/oneclickvirt/basics v0.0.3-20240625075226/go.mod h1:dTB+/oyFQYfTYX55rFJVWatum5F9g62zjfmHCM6Vj1s=
|
github.com/oneclickvirt/basics v0.0.5-20240702021800/go.mod h1:ZuBHalTH6J8fO2cL+ZH4SeFLAt32WRW74H9htwNTGhc=
|
||||||
github.com/oneclickvirt/cputest v0.0.6-20240630144058 h1:bFOM4MS+uaU7slFaZR91/bJ57AFM23RWPEik+GTFS2w=
|
github.com/oneclickvirt/cputest v0.0.8-20240701113350 h1:OMIKQSvcqCmDuVCL2y8V1GI0/YSFmUs9Ikw6WalWsS0=
|
||||||
github.com/oneclickvirt/cputest v0.0.6-20240630144058/go.mod h1:MmaHN9+XMntI3rLycwj8Ne31fG18IfNoa8N2utDK1CY=
|
github.com/oneclickvirt/cputest v0.0.8-20240701113350/go.mod h1:MmaHN9+XMntI3rLycwj8Ne31fG18IfNoa8N2utDK1CY=
|
||||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 h1:5Pg3mK/u/vQvSz7anu0nxzrNdELi/AcDAU1mMsmPzyc=
|
github.com/oneclickvirt/defaultset v0.0.2-20240624082446 h1:5Pg3mK/u/vQvSz7anu0nxzrNdELi/AcDAU1mMsmPzyc=
|
||||||
github.com/oneclickvirt/defaultset v0.0.2-20240624082446/go.mod h1:e9Jt4tf2sbemCtc84/XgKcHy9EZ2jkc5x2sW1NiJS+E=
|
github.com/oneclickvirt/defaultset v0.0.2-20240624082446/go.mod h1:e9Jt4tf2sbemCtc84/XgKcHy9EZ2jkc5x2sW1NiJS+E=
|
||||||
github.com/oneclickvirt/disktest v0.0.3-20240629152513 h1:ZW7MBMd2HxQi1ktg/ztVI2A10JzF4ZI6I7ATZvcK9w8=
|
github.com/oneclickvirt/disktest v0.0.3-20240629152513 h1:ZW7MBMd2HxQi1ktg/ztVI2A10JzF4ZI6I7ATZvcK9w8=
|
||||||
github.com/oneclickvirt/disktest v0.0.3-20240629152513/go.mod h1:x7VAJF0Ks05FyE4BI5xedXNKmwbeXfp8GCRALAIlueI=
|
github.com/oneclickvirt/disktest v0.0.3-20240629152513/go.mod h1:x7VAJF0Ks05FyE4BI5xedXNKmwbeXfp8GCRALAIlueI=
|
||||||
github.com/oneclickvirt/gostun v0.0.2-20240625025941 h1:h+ZL8jkjXR6QE0qEX34FjWTv89+lNj2fEkWx5Agpgzc=
|
github.com/oneclickvirt/gostun v0.0.2-20240625025941 h1:h+ZL8jkjXR6QE0qEX34FjWTv89+lNj2fEkWx5Agpgzc=
|
||||||
github.com/oneclickvirt/gostun v0.0.2-20240625025941/go.mod h1:f7DPEXAxbmwXSW33dbxtb0/KzqvOBWhTs2Or5xBerQA=
|
github.com/oneclickvirt/gostun v0.0.2-20240625025941/go.mod h1:f7DPEXAxbmwXSW33dbxtb0/KzqvOBWhTs2Or5xBerQA=
|
||||||
github.com/oneclickvirt/memorytest v0.0.1-20240624151629 h1:2rJAB3gFGlFPocIb/WRVWYqs4nr2jGYokfDOgqFicD4=
|
github.com/oneclickvirt/memorytest v0.0.2-20240702031042 h1:j+LsjOh5glYiidqtSqjZJRw694LYW1PHLMh6AovluTQ=
|
||||||
github.com/oneclickvirt/memorytest v0.0.1-20240624151629/go.mod h1:+YNzy+NeVg61d0kNwSyVDqHyVtKzjuRe1NvMzsDLg0I=
|
github.com/oneclickvirt/memorytest v0.0.2-20240702031042/go.mod h1:+YNzy+NeVg61d0kNwSyVDqHyVtKzjuRe1NvMzsDLg0I=
|
||||||
github.com/oneclickvirt/nt3 v0.0.2-20240630152642 h1:BkpR1j9JaDxMzx7iIwtsnFDxSldjYr2TUYpZE7m8z/Y=
|
github.com/oneclickvirt/nt3 v0.0.2-20240630152642 h1:BkpR1j9JaDxMzx7iIwtsnFDxSldjYr2TUYpZE7m8z/Y=
|
||||||
github.com/oneclickvirt/nt3 v0.0.2-20240630152642/go.mod h1:UojPmtangn17TiQaDccVrZbn6sZwJOtzBgg3idp68cA=
|
github.com/oneclickvirt/nt3 v0.0.2-20240630152642/go.mod h1:UojPmtangn17TiQaDccVrZbn6sZwJOtzBgg3idp68cA=
|
||||||
github.com/oneclickvirt/portchecker v0.0.1-20240624155429 h1:+wapaOcFrg1iWJDhBKThDzppyIMY7hWxK7F5RBkZg4o=
|
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/portchecker v0.0.1-20240624155429/go.mod h1:HQxSTrqM8/QFqHMTBZ7S8H9eEO5FkUXU1eb7ZX5Mk+k=
|
||||||
github.com/oneclickvirt/security v0.0.2-20240630142358 h1:yioMtHuW9wbJ7payL8GCPnj1ScEqNoqbNHt3+4Z4VAg=
|
github.com/oneclickvirt/security v0.0.4-20240702031253 h1:jUr+lfXTg+Gqrt+SQNeVIObMDZYVjUo1kH+O1q6DSEU=
|
||||||
github.com/oneclickvirt/security v0.0.2-20240630142358/go.mod h1:cUNNOldoVQuovyc0EtAVAZlAT4y2xA1e0uA80aj1ly8=
|
github.com/oneclickvirt/security v0.0.4-20240702031253/go.mod h1:lONKUorS4lMjXI+5sqD9aq0eNOO6z1QhZylQ7M3wx2s=
|
||||||
github.com/oneclickvirt/speedtest v0.0.6-20240630114816 h1:gI2hqV0IwcvGqYzLhlt4w2oZvYhCL+73jftUuJYBsuI=
|
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/oneclickvirt/speedtest v0.0.6-20240630114816/go.mod h1:zd5ZgIGslmtQLQehEfRjyumlvgDHTpCSMchKfKXoASI=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||||
|
520
goecs.go
520
goecs.go
@@ -3,6 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/oneclickvirt/CommonMediaTests/commediatests"
|
||||||
|
backtraceori "github.com/oneclickvirt/backtrace/bk"
|
||||||
|
basicmodel "github.com/oneclickvirt/basics/model"
|
||||||
|
cputestmodel "github.com/oneclickvirt/cputest/model"
|
||||||
"github.com/oneclickvirt/ecs/backtrace"
|
"github.com/oneclickvirt/ecs/backtrace"
|
||||||
"github.com/oneclickvirt/ecs/commediatest"
|
"github.com/oneclickvirt/ecs/commediatest"
|
||||||
"github.com/oneclickvirt/ecs/cputest"
|
"github.com/oneclickvirt/ecs/cputest"
|
||||||
@@ -12,176 +16,434 @@ import (
|
|||||||
"github.com/oneclickvirt/ecs/speedtest"
|
"github.com/oneclickvirt/ecs/speedtest"
|
||||||
"github.com/oneclickvirt/ecs/unlocktest"
|
"github.com/oneclickvirt/ecs/unlocktest"
|
||||||
"github.com/oneclickvirt/ecs/utils"
|
"github.com/oneclickvirt/ecs/utils"
|
||||||
|
gostunmodel "github.com/oneclickvirt/gostun/model"
|
||||||
"github.com/oneclickvirt/portchecker/email"
|
"github.com/oneclickvirt/portchecker/email"
|
||||||
|
speedtestmodel "github.com/oneclickvirt/speedtest/model"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"os/signal"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ecsVersion = "2024.06.30"
|
ecsVersion = "v0.0.29"
|
||||||
showVersion bool
|
menuMode bool
|
||||||
language string
|
input, choice string
|
||||||
cpuTestMethod, cpuTestThreadMode string
|
showVersion bool
|
||||||
memoryTestMethod string
|
enableLogger bool
|
||||||
diskTestMethod, diskTestPath string
|
language string
|
||||||
diskMultiCheck bool
|
cpuTestMethod, cpuTestThreadMode string
|
||||||
nt3CheckType, nt3Location string
|
memoryTestMethod string
|
||||||
spNum int
|
diskTestMethod, diskTestPath string
|
||||||
width = 84
|
diskMultiCheck bool
|
||||||
|
nt3CheckType, nt3Location string
|
||||||
|
spNum int
|
||||||
|
width = 82
|
||||||
|
basicStatus, cpuTestStatus, memoryTestStatus, diskTestStatus bool
|
||||||
|
commTestStatus, utTestStatus, securityTestStatus, emailTestStatus bool
|
||||||
|
backtraceStatus, nt3Status, speedTestStatus bool
|
||||||
|
filePath = "goecs.txt"
|
||||||
|
enabelUpload = true
|
||||||
|
help bool
|
||||||
|
goecsFlag = flag.NewFlagSet("goecs", flag.ContinueOnError)
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.BoolVar(&showVersion, "v", false, "Show version information")
|
goecsFlag.BoolVar(&help, "h", false, "Show help information")
|
||||||
flag.StringVar(&language, "l", "zh", "Specify language (supported: en, zh)")
|
goecsFlag.BoolVar(&showVersion, "v", false, "Display version information")
|
||||||
flag.StringVar(&cpuTestMethod, "cpum", "sysbench", "Specify CPU test method (supported: sysbench, geekbench, winsat)")
|
goecsFlag.BoolVar(&menuMode, "menu", true, "Enable/Disable menu mode, disable example: -menu=false") // true 默认启用菜单栏模式
|
||||||
flag.StringVar(&cpuTestThreadMode, "cput", "multi", "Specify CPU test thread mode (supported: single multi)")
|
goecsFlag.StringVar(&language, "l", "zh", "Set language (supported: en, zh)")
|
||||||
flag.StringVar(&memoryTestMethod, "memorym", "dd", "Specify Memory test method (supported: sysbench, dd, winsat)")
|
goecsFlag.BoolVar(&basicStatus, "basic", true, "Enable/Disable basic test")
|
||||||
flag.StringVar(&diskTestMethod, "diskm", "fio", "Specify Disk test method (supported: fio, dd, winsat)")
|
goecsFlag.BoolVar(&cpuTestStatus, "cpu", true, "Enable/Disable CPU test")
|
||||||
flag.StringVar(&diskTestPath, "diskp", "", "Specify Disk test path, example: -diskp /root")
|
goecsFlag.BoolVar(&memoryTestStatus, "memory", true, "Enable/Disable memory test")
|
||||||
flag.BoolVar(&diskMultiCheck, "diskmc", false, "Enable multiple disk checks, example: -diskmc=false")
|
goecsFlag.BoolVar(&diskTestStatus, "disk", true, "Enable/Disable disk test")
|
||||||
flag.StringVar(&nt3Location, "nt3loc", "GZ", "指定三网回程路由检测的地址,支持 GZ, SH, BJ, CD 对应 广州,上海,北京,成都")
|
goecsFlag.BoolVar(&commTestStatus, "comm", true, "Enable/Disable common media test")
|
||||||
flag.StringVar(&nt3CheckType, "nt3t", "ipv4", "指定三网回程路由检测的类型,支持 both, ipv4, ipv6")
|
goecsFlag.BoolVar(&utTestStatus, "ut", true, "Enable/Disable unlock media test")
|
||||||
flag.IntVar(&spNum, "spnum", 2, "Specify speedtest each operator servers num")
|
goecsFlag.BoolVar(&securityTestStatus, "security", true, "Enable/Disable security test")
|
||||||
flag.Parse()
|
goecsFlag.BoolVar(&emailTestStatus, "email", true, "Enable/Disable email port test")
|
||||||
|
goecsFlag.BoolVar(&backtraceStatus, "backtrace", true, "Enable/Disable backtrace test (in 'en' language or on windows it always false)")
|
||||||
|
goecsFlag.BoolVar(&nt3Status, "nt3", true, "Enable/Disable NT3 test (in 'en' language or on windows it always false)")
|
||||||
|
goecsFlag.BoolVar(&speedTestStatus, "speed", true, "Enable/Disable speed test")
|
||||||
|
goecsFlag.StringVar(&cpuTestMethod, "cpum", "sysbench", "Set CPU test method (supported: sysbench, geekbench, winsat)")
|
||||||
|
goecsFlag.StringVar(&cpuTestThreadMode, "cput", "multi", "Set CPU test thread mode (supported: single, multi)")
|
||||||
|
goecsFlag.StringVar(&memoryTestMethod, "memorym", "dd", "Set memory test method (supported: sysbench, dd, winsat)")
|
||||||
|
goecsFlag.StringVar(&diskTestMethod, "diskm", "fio", "Set disk test method (supported: fio, dd, winsat)")
|
||||||
|
goecsFlag.StringVar(&diskTestPath, "diskp", "", "Set disk test path, e.g., -diskp /root")
|
||||||
|
goecsFlag.BoolVar(&diskMultiCheck, "diskmc", false, "Enable/Disable multiple disk checks, e.g., -diskmc=false")
|
||||||
|
goecsFlag.StringVar(&nt3Location, "nt3loc", "GZ", "Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu)")
|
||||||
|
goecsFlag.StringVar(&nt3CheckType, "nt3t", "ipv4", "Set NT3 test type (supported: both, ipv4, ipv6)")
|
||||||
|
goecsFlag.IntVar(&spNum, "spnum", 2, "Set the number of servers per operator for speed test")
|
||||||
|
goecsFlag.BoolVar(&enableLogger, "log", false, "Enable/Disable logging in the current path")
|
||||||
|
goecsFlag.Parse(os.Args[1:])
|
||||||
|
if help {
|
||||||
|
fmt.Printf("Usage: %s [options]\n", os.Args[0])
|
||||||
|
goecsFlag.PrintDefaults()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sig := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
if showVersion {
|
if showVersion {
|
||||||
fmt.Println(ecsVersion)
|
fmt.Println(ecsVersion)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if enableLogger {
|
||||||
|
basicmodel.EnableLoger = true
|
||||||
|
cputestmodel.EnableLoger = true
|
||||||
|
speedtestmodel.EnableLoger = true
|
||||||
|
gostunmodel.EnableLoger = true
|
||||||
|
commediatests.EnableLoger = true
|
||||||
|
backtraceori.EnableLoger = true
|
||||||
|
}
|
||||||
|
if menuMode {
|
||||||
|
basicStatus, cpuTestStatus, memoryTestStatus, diskTestStatus = false, false, false, false
|
||||||
|
commTestStatus, utTestStatus, securityTestStatus, emailTestStatus = false, false, false, false
|
||||||
|
backtraceStatus, nt3Status, speedTestStatus = false, false, false
|
||||||
|
switch language {
|
||||||
|
case "zh":
|
||||||
|
fmt.Println("VPS融合怪版本: ", ecsVersion)
|
||||||
|
fmt.Println("1. 融合怪完全体")
|
||||||
|
fmt.Println("2. 极简版(系统信息+CPU+内存+磁盘+测速节点5个)")
|
||||||
|
fmt.Println("3. 精简版(系统信息+CPU+内存+磁盘+御三家+常用流媒体+回程+路由+测速节点5个)")
|
||||||
|
fmt.Println("4. 精简网络版(系统信息+CPU+内存+磁盘+回程+路由+测速节点5个)")
|
||||||
|
fmt.Println("5. 精简解锁版(系统信息+CPU+内存+磁盘IO+御三家+常用流媒体+测速节点5个)")
|
||||||
|
fmt.Println("6. 网络单项(IP质量检测+三网回程+三网路由与延迟+测速节点11个)")
|
||||||
|
fmt.Println("7. 解锁单项(御三家解锁+常用流媒体解锁)")
|
||||||
|
fmt.Println("8. 硬件单项(基础系统信息+CPU+内存+dd磁盘测试+fio磁盘测试)")
|
||||||
|
fmt.Println("9. IP质量检测(15个数据库的IP检测+邮件端口检测)")
|
||||||
|
fmt.Println("10. 三网回程线路+广州三网路由+全国三网延迟")
|
||||||
|
case "en":
|
||||||
|
fmt.Println("VPS Fusion Monster Test Version: ", ecsVersion)
|
||||||
|
fmt.Println("1. VPS Fusion Monster Test Comprehensive Test Suite")
|
||||||
|
fmt.Println("2. Minimal Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)")
|
||||||
|
fmt.Println("3. Standard Test Suite (System Info + CPU + Memory + Disk + Basic Unlock Tests + Common Streaming Services + 5 Speed Test Nodes)")
|
||||||
|
fmt.Println("4. Network-Focused Test Suite (System Info + CPU + Memory + Disk + 5 Speed Test Nodes)")
|
||||||
|
fmt.Println("5. Unlock-Focused Test Suite (System Info + CPU + Memory + Disk IO + Basic Unlock Tests + Common Streaming Services + 5 Speed Test Nodes)")
|
||||||
|
fmt.Println("6. Network-Only Test (IP Quality Test + 5 Speed Test Nodes)")
|
||||||
|
fmt.Println("7. Unlock-Only Test (Basic Unlock Tests + Common Streaming Services Unlock)")
|
||||||
|
fmt.Println("8. Hardware-Only Test (Basic System Info + CPU + Memory + dd Disk Test + fio Disk Test)")
|
||||||
|
fmt.Println("9. IP Quality Test (IP Test with 15 Databases + Email Port Test)")
|
||||||
|
}
|
||||||
|
Loop:
|
||||||
|
for {
|
||||||
|
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) {
|
||||||
|
choice = input
|
||||||
|
switch choice {
|
||||||
|
case "1":
|
||||||
|
basicStatus = true
|
||||||
|
cpuTestStatus = true
|
||||||
|
memoryTestStatus = true
|
||||||
|
diskTestStatus = true
|
||||||
|
commTestStatus = true
|
||||||
|
utTestStatus = true
|
||||||
|
securityTestStatus = true
|
||||||
|
emailTestStatus = true
|
||||||
|
backtraceStatus = true
|
||||||
|
nt3Status = true
|
||||||
|
speedTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "2":
|
||||||
|
basicStatus = true
|
||||||
|
cpuTestStatus = true
|
||||||
|
memoryTestStatus = true
|
||||||
|
diskTestStatus = true
|
||||||
|
speedTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "3":
|
||||||
|
basicStatus = true
|
||||||
|
cpuTestStatus = true
|
||||||
|
memoryTestStatus = true
|
||||||
|
diskTestStatus = true
|
||||||
|
commTestStatus = true
|
||||||
|
utTestStatus = true
|
||||||
|
securityTestStatus = true
|
||||||
|
backtraceStatus = true
|
||||||
|
nt3Status = true
|
||||||
|
speedTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "4":
|
||||||
|
basicStatus = true
|
||||||
|
cpuTestStatus = true
|
||||||
|
memoryTestStatus = true
|
||||||
|
diskTestStatus = true
|
||||||
|
backtraceStatus = true
|
||||||
|
nt3Status = true
|
||||||
|
speedTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "5":
|
||||||
|
basicStatus = true
|
||||||
|
cpuTestStatus = true
|
||||||
|
memoryTestStatus = true
|
||||||
|
diskTestStatus = true
|
||||||
|
securityTestStatus = true
|
||||||
|
speedTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "6":
|
||||||
|
speedTestStatus = true
|
||||||
|
backtraceStatus = true
|
||||||
|
nt3Status = true
|
||||||
|
break Loop
|
||||||
|
case "7":
|
||||||
|
securityTestStatus = true
|
||||||
|
commTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "8":
|
||||||
|
basicStatus = true
|
||||||
|
cpuTestStatus = true
|
||||||
|
memoryTestStatus = true
|
||||||
|
diskTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "9":
|
||||||
|
emailTestStatus = true
|
||||||
|
break Loop
|
||||||
|
case "10":
|
||||||
|
backtraceStatus = true
|
||||||
|
nt3Status = true
|
||||||
|
speedTestStatus = true
|
||||||
|
break Loop
|
||||||
|
default:
|
||||||
|
if language == "zh" {
|
||||||
|
fmt.Println("无效的选项")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Invalid choice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if language == "zh" {
|
||||||
|
fmt.Println("输入错误,请输入一个纯数字")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Invalid input, please enter a number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if language == "en" {
|
||||||
|
backtraceStatus = false
|
||||||
|
nt3Status = false
|
||||||
|
}
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
var (
|
var (
|
||||||
wg sync.WaitGroup
|
wg1, wg2 sync.WaitGroup
|
||||||
basicInfo, securityInfo, emailInfo, mediaInfo string
|
basicInfo, securityInfo, emailInfo, mediaInfo string
|
||||||
output, tempOutput string
|
output, tempOutput string
|
||||||
)
|
)
|
||||||
output = utils.PrintAndCapture(func() {
|
// 启动一个goroutine来等待信号
|
||||||
switch language {
|
go func() {
|
||||||
case "zh":
|
// 等待信号
|
||||||
|
<-sig
|
||||||
|
utils.ProcessAndUpload(output, filePath, enabelUpload)
|
||||||
|
os.Exit(1) // 使用非零状态码退出,表示意外退出
|
||||||
|
}()
|
||||||
|
switch language {
|
||||||
|
case "zh":
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
utils.PrintHead(language, width, ecsVersion)
|
utils.PrintHead(language, width, ecsVersion)
|
||||||
utils.PrintCenteredTitle("基础信息", width)
|
if basicStatus || securityTestStatus {
|
||||||
basicInfo, securityInfo, nt3CheckType = utils.SecurityCheck(language, nt3CheckType)
|
if basicStatus {
|
||||||
fmt.Printf(basicInfo)
|
utils.PrintCenteredTitle("系统基础信息", width)
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", cpuTestMethod), width)
|
}
|
||||||
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
|
basicInfo, securityInfo, nt3CheckType = utils.SecurityCheck(language, nt3CheckType, securityTestStatus)
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", cpuTestMethod), width)
|
if basicStatus {
|
||||||
memorytest.MemoryTest(language, memoryTestMethod)
|
fmt.Printf(basicInfo)
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", diskTestMethod), width)
|
}
|
||||||
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
|
}
|
||||||
utils.PrintCenteredTitle("御三家流媒体解锁", width)
|
}, tempOutput, output)
|
||||||
wg.Add(2)
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if cpuTestStatus {
|
||||||
|
utils.PrintCenteredTitle(fmt.Sprintf("CPU测试-通过%s测试", cpuTestMethod), width)
|
||||||
|
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if memoryTestStatus {
|
||||||
|
utils.PrintCenteredTitle(fmt.Sprintf("内存测试-通过%s测试", cpuTestMethod), width)
|
||||||
|
memorytest.MemoryTest(language, memoryTestMethod)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if diskTestStatus {
|
||||||
|
utils.PrintCenteredTitle(fmt.Sprintf("硬盘测试-通过%s测试", diskTestMethod), width)
|
||||||
|
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
if emailTestStatus {
|
||||||
|
wg2.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg2.Done()
|
||||||
emailInfo = email.EmailCheck()
|
emailInfo = email.EmailCheck()
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
if utTestStatus {
|
||||||
|
wg1.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg1.Done()
|
||||||
mediaInfo = unlocktest.MediaTest(language)
|
mediaInfo = unlocktest.MediaTest(language)
|
||||||
}()
|
}()
|
||||||
commediatest.ComMediaTest(language)
|
}
|
||||||
utils.PrintCenteredTitle("跨国流媒体解锁", width)
|
output = utils.PrintAndCapture(func() {
|
||||||
wg.Wait() // 后台任务含流媒体测试和邮件测试
|
if commTestStatus {
|
||||||
fmt.Printf(mediaInfo)
|
utils.PrintCenteredTitle("御三家流媒体解锁", width)
|
||||||
utils.PrintCenteredTitle("IP质量检测", width)
|
commediatest.ComMediaTest(language)
|
||||||
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)
|
}, tempOutput, output)
|
||||||
speedtest.ShowHead(language)
|
output = utils.PrintAndCapture(func() {
|
||||||
speedtest.NearbySP()
|
if utTestStatus {
|
||||||
speedtest.CustomSP("net", "global", 4)
|
utils.PrintCenteredTitle("跨国流媒体解锁", width)
|
||||||
speedtest.CustomSP("net", "cu", spNum)
|
wg1.Wait()
|
||||||
speedtest.CustomSP("net", "ct", spNum)
|
fmt.Printf(mediaInfo)
|
||||||
speedtest.CustomSP("net", "cmcc", spNum)
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if securityTestStatus {
|
||||||
|
utils.PrintCenteredTitle("IP质量检测", width)
|
||||||
|
fmt.Printf(securityInfo)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if emailTestStatus {
|
||||||
|
utils.PrintCenteredTitle("邮件端口检测", width)
|
||||||
|
wg2.Wait()
|
||||||
|
fmt.Println(emailInfo)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if backtraceStatus {
|
||||||
|
utils.PrintCenteredTitle("三网回程线路检测", width)
|
||||||
|
backtrace.BackTrace()
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
// nexttrace 在win上不支持检测,报错 bind: An invalid argument was supplied.
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if nt3Status {
|
||||||
|
utils.PrintCenteredTitle("三网回程路由检测", width)
|
||||||
|
ntrace.TraceRoute3(language, nt3Location, nt3CheckType)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
}
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if speedTestStatus {
|
||||||
|
utils.PrintCenteredTitle("就近节点测速", width)
|
||||||
|
speedtest.ShowHead(language)
|
||||||
|
if (menuMode && choice == "1") || !menuMode {
|
||||||
|
speedtest.NearbySP()
|
||||||
|
speedtest.CustomSP("net", "global", 2)
|
||||||
|
speedtest.CustomSP("net", "cu", spNum)
|
||||||
|
speedtest.CustomSP("net", "ct", spNum)
|
||||||
|
speedtest.CustomSP("net", "cmcc", spNum)
|
||||||
|
} else if menuMode && choice == "2" || choice == "3" || choice == "4" || choice == "5" {
|
||||||
|
speedtest.CustomSP("net", "global", 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
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")
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
utils.PrintCenteredTitle("", width)
|
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("花费 : %d 分 %d 秒\n", minutes, seconds)
|
||||||
fmt.Printf("时间 : %s\n", currentTime)
|
fmt.Printf("时间 : %s\n", currentTime)
|
||||||
utils.PrintCenteredTitle("", width)
|
utils.PrintCenteredTitle("", width)
|
||||||
case "en":
|
}, tempOutput, output)
|
||||||
|
case "en":
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
utils.PrintHead(language, width, ecsVersion)
|
utils.PrintHead(language, width, ecsVersion)
|
||||||
utils.PrintCenteredTitle("Basic Information", width)
|
if basicStatus || securityTestStatus {
|
||||||
basicInfo, securityInfo, nt3CheckType = utils.SecurityCheck(language, nt3CheckType)
|
if basicStatus {
|
||||||
fmt.Printf(basicInfo)
|
utils.PrintCenteredTitle("System Basic Information", width)
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("CPU Test - %s Method", cpuTestMethod), width)
|
}
|
||||||
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
|
basicInfo, securityInfo, nt3CheckType = utils.SecurityCheck(language, nt3CheckType, securityTestStatus)
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("Memory Test - %s Method", memoryTestMethod), width)
|
if basicStatus {
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("Disk Test - %s Method", diskTestMethod), width)
|
fmt.Printf(basicInfo)
|
||||||
utils.PrintCenteredTitle(fmt.Sprintf("Disk Test - %s Method", diskTestMethod), width)
|
}
|
||||||
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
|
}
|
||||||
wg.Add(1)
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if cpuTestStatus {
|
||||||
|
utils.PrintCenteredTitle(fmt.Sprintf("CPU Test - %s Method", cpuTestMethod), width)
|
||||||
|
cputest.CpuTest(language, cpuTestMethod, cpuTestThreadMode)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if memoryTestStatus {
|
||||||
|
utils.PrintCenteredTitle(fmt.Sprintf("Memory Test - %s Method", memoryTestMethod), width)
|
||||||
|
memorytest.MemoryTest(language, memoryTestMethod)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if diskTestStatus {
|
||||||
|
utils.PrintCenteredTitle(fmt.Sprintf("Disk Test - %s Method", diskTestMethod), width)
|
||||||
|
disktest.DiskTest(language, diskTestMethod, diskTestPath, diskMultiCheck)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
if emailTestStatus {
|
||||||
|
wg1.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg1.Done()
|
||||||
emailInfo = email.EmailCheck()
|
emailInfo = email.EmailCheck()
|
||||||
}()
|
}()
|
||||||
utils.PrintCenteredTitle("The Three Families Streaming Media Unlock", width)
|
}
|
||||||
commediatest.ComMediaTest(language)
|
output = utils.PrintAndCapture(func() {
|
||||||
utils.PrintCenteredTitle("Cross-Border Streaming Media Unlock", width)
|
if commTestStatus {
|
||||||
unlocktest.MediaTest(language)
|
utils.PrintCenteredTitle("The Three Main Streaming Media Unlock", width)
|
||||||
utils.PrintCenteredTitle("IP Quality Check", width)
|
commediatest.ComMediaTest(language)
|
||||||
fmt.Printf(securityInfo)
|
}
|
||||||
utils.PrintCenteredTitle("Email Port Check", width)
|
}, tempOutput, output)
|
||||||
wg.Wait()
|
output = utils.PrintAndCapture(func() {
|
||||||
fmt.Println(emailInfo)
|
if utTestStatus {
|
||||||
//utils.PrintCenteredTitle("Return Path Routing", width)
|
utils.PrintCenteredTitle("Cross-Border Streaming Media Unlock", width)
|
||||||
utils.PrintCenteredTitle("Nearby Node Speed Test", width)
|
unlocktest.MediaTest(language)
|
||||||
speedtest.ShowHead(language)
|
}
|
||||||
speedtest.NearbySP()
|
}, tempOutput, output)
|
||||||
speedtest.CustomSP("net", "global", -1)
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if securityTestStatus {
|
||||||
|
utils.PrintCenteredTitle("IP Quality Check", width)
|
||||||
|
fmt.Printf(securityInfo)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if emailTestStatus {
|
||||||
|
utils.PrintCenteredTitle("Email Port Check", width)
|
||||||
|
wg1.Wait()
|
||||||
|
fmt.Println(emailInfo)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
|
if speedTestStatus {
|
||||||
|
utils.PrintCenteredTitle("Nearby Node Speed Test", width)
|
||||||
|
speedtest.ShowHead(language)
|
||||||
|
speedtest.NearbySP()
|
||||||
|
speedtest.CustomSP("net", "global", -1)
|
||||||
|
}
|
||||||
|
}, tempOutput, output)
|
||||||
|
|
||||||
|
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")
|
||||||
|
output = utils.PrintAndCapture(func() {
|
||||||
utils.PrintCenteredTitle("", width)
|
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("Cost Time : %d 分 %d 秒\n", minutes, seconds)
|
||||||
fmt.Printf("Current Time : %s\n", currentTime)
|
fmt.Printf("Current Time : %s\n", currentTime)
|
||||||
utils.PrintCenteredTitle("", width)
|
utils.PrintCenteredTitle("", width)
|
||||||
default:
|
}, tempOutput, output)
|
||||||
fmt.Println("Unsupported language")
|
default:
|
||||||
}
|
fmt.Println("Unsupported language")
|
||||||
}, tempOutput, output)
|
|
||||||
// 创建文件
|
|
||||||
filePath := "goecs.txt"
|
|
||||||
file, err := os.Create(filePath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Can not make file:", err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
defer file.Close()
|
utils.ProcessAndUpload(output, filePath, enabelUpload)
|
||||||
// 将 output 写入文件
|
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
|
||||||
// 匹配 ANSI 转义序列
|
fmt.Println("Press Enter to exit...")
|
||||||
ansiRegex := regexp.MustCompile("\x1B\\[[0-9;]+[a-zA-Z]")
|
fmt.Scanln()
|
||||||
// 移除 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)
|
|
||||||
}
|
}
|
||||||
|
56
goecs.sh
56
goecs.sh
@@ -59,17 +59,16 @@ goecs_check() {
|
|||||||
ECS_VERSION=$(curl -m 6 -sSL "https://githubapi.spiritlhl.top/repos/oneclickvirt/ecs/releases/latest" | awk -F \" '/tag_name/{gsub(/^v/,"",$4); print $4}')
|
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
|
fi
|
||||||
# 检测原始goecs命令是否存在,若存在则升级,不存在则安装
|
# 检测原始goecs命令是否存在,若存在则升级,不存在则安装
|
||||||
version_output=$(goecs -v || ./goecs -v)
|
version_output=$(goecs -v command 2>/dev/null || ./goecs -v command 2>/dev/null)
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
extracted_version=$(echo "$version_output" | grep -oP '^v\d+(\.\d+)+')
|
extracted_version=$(echo "${version_output//v/}")
|
||||||
if [ -n "$extracted_version" ]; then
|
if [ -n "$extracted_version" ]; then
|
||||||
current_version=$(echo "$extracted_version" | cut -c 2-)
|
|
||||||
ecs_version=$ECS_VERSION
|
ecs_version=$ECS_VERSION
|
||||||
if [[ "$(echo -e "$current_version\n$ecs_version" | sort -V | tail -n 1)" == "$current_version" ]]; then
|
if [[ "$(echo -e "$extracted_version\n$ecs_version" | sort -V | tail -n 1)" == "$extracted_version" ]]; then
|
||||||
echo "goecs version ($current_version) is latest, no need to upgrade."
|
echo "goecs version ($extracted_version) is latest, no need to upgrade."
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
echo "goecs version ($current_version) < $ecs_version, need to upgrade, 5 seconds later will start to upgrade"
|
echo "goecs version ($extracted_version) < $ecs_version, need to upgrade, 5 seconds later will start to upgrade"
|
||||||
rm -rf /usr/bin/goecs
|
rm -rf /usr/bin/goecs
|
||||||
rm -rf goecs
|
rm -rf goecs
|
||||||
fi
|
fi
|
||||||
@@ -163,7 +162,7 @@ InstallSysbench() {
|
|||||||
arch) pacman -S --needed --noconfirm sysbench && pacman -S --needed --noconfirm libaio && ldconfig ;;
|
arch) pacman -S --needed --noconfirm sysbench && pacman -S --needed --noconfirm libaio && ldconfig ;;
|
||||||
freebsd) pkg install -y sysbench ;;
|
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" ;;
|
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 ;;
|
*) echo "Error: Unknown OS release: $os_release" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +229,7 @@ prepare_compile_env() {
|
|||||||
env_check() {
|
env_check() {
|
||||||
REGEX=("debian|astra" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora" "arch" "freebsd" "alpine" "openbsd")
|
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")
|
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_UPDATE=("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_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_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")
|
PACKAGE_UNINSTALL=("apt-get -y autoremove" "apt-get -y autoremove" "yum -y autoremove" "yum -y autoremove" "yum -y autoremove" "" "pkg autoremove" "apk autoremove")
|
||||||
@@ -245,6 +244,16 @@ env_check() {
|
|||||||
done
|
done
|
||||||
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "http://cdn2.spiritlhl.net/")
|
cdn_urls=("https://cdn0.spiritlhl.top/" "http://cdn3.spiritlhl.net/" "http://cdn1.spiritlhl.net/" "http://cdn2.spiritlhl.net/")
|
||||||
check_cdn_file
|
check_cdn_file
|
||||||
|
_green "Update system manager."
|
||||||
|
$PACKAGE_UPDATE command 2>/dev/null
|
||||||
|
if ! command -v tar >/dev/null 2>&1; then
|
||||||
|
_green "Installing tar"
|
||||||
|
$PACKAGE_INSTALL tar
|
||||||
|
fi
|
||||||
|
if ! command -v unzip >/dev/null 2>&1; then
|
||||||
|
_green "Installing unzip"
|
||||||
|
$PACKAGE_INSTALL unzip
|
||||||
|
fi
|
||||||
if ! command -v dd >/dev/null 2>&1; then
|
if ! command -v dd >/dev/null 2>&1; then
|
||||||
_green "Installing dd"
|
_green "Installing dd"
|
||||||
$PACKAGE_INSTALL dd
|
$PACKAGE_INSTALL dd
|
||||||
@@ -291,16 +300,36 @@ env_check() {
|
|||||||
echo "rm -rf /usr/bin/speedtest-go"
|
echo "rm -rf /usr/bin/speedtest-go"
|
||||||
_blue "to uninstall speedtest and speedtest-go"
|
_blue "to uninstall speedtest and speedtest-go"
|
||||||
fi
|
fi
|
||||||
|
if [ "$(uname -s)" = "Darwin" ]; then
|
||||||
|
echo "Detected MacOS. Installing sysbench and fio..."
|
||||||
|
# 使用Homebrew安装sysbench和fio(免交互)
|
||||||
|
brew install --force sysbench fio
|
||||||
|
fi
|
||||||
|
_green "The environment is ready."
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_goecs() {
|
||||||
|
rm -rf /root/goecs
|
||||||
|
rm -rf /usr/bin/goecs
|
||||||
}
|
}
|
||||||
|
|
||||||
show_help() {
|
show_help() {
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
Available commands:
|
Available commands:
|
||||||
|
|
||||||
env Check and Install package: dd fio sysbench geekbench5 speedtest
|
./goecs.sh env Check and Install package:
|
||||||
install Install goecs command
|
tar (Almost all unix-like systems have it.)
|
||||||
upgrade Upgrade goecs command
|
unzip (Almost all unix-like systems have it.)
|
||||||
help Show this message
|
dd (Almost all unix-like systems have it.)
|
||||||
|
fio (Almost all unix-like systems can be installed through the system's package manager.)
|
||||||
|
sysbench (Almost all unix-like systems can be installed through the system's package manager.)
|
||||||
|
geekbench (geekbench5)(Only support IPV4 environment, and memory greater than 1GB network detection, only support amd64 and arm64 architecture.)
|
||||||
|
speedtest (Use the officially provided binaries for more accurate test results.)
|
||||||
|
In fact, sysbench/geekbench is the only one of the above dependencies that must be installed, without which the CPU score cannot be tested.
|
||||||
|
./goecs.sh install Install goecs command
|
||||||
|
./goecs.sh upgrade Upgrade goecs command
|
||||||
|
./goecs.sh delete Uninstall goecs command
|
||||||
|
./goecs.sh help Show this message
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@@ -315,6 +344,9 @@ case "$1" in
|
|||||||
"install" | "upgrade")
|
"install" | "upgrade")
|
||||||
goecs_check
|
goecs_check
|
||||||
;;
|
;;
|
||||||
|
"delete")
|
||||||
|
delete_goecs
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "No command found."
|
echo "No command found."
|
||||||
echo
|
echo
|
||||||
|
@@ -9,8 +9,11 @@ import (
|
|||||||
"github.com/oneclickvirt/security/network"
|
"github.com/oneclickvirt/security/network"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,13 +30,13 @@ func PrintCenteredTitle(title string, width int) {
|
|||||||
// PrintHead 根据语言打印头部信息
|
// PrintHead 根据语言打印头部信息
|
||||||
func PrintHead(language string, width int, ecsVersion string) {
|
func PrintHead(language string, width int, ecsVersion string) {
|
||||||
if language == "zh" {
|
if language == "zh" {
|
||||||
PrintCenteredTitle("融合怪测试", width)
|
PrintCenteredTitle("VPS融合怪测试", width)
|
||||||
fmt.Printf("版本:%s\n", ecsVersion)
|
fmt.Printf("版本:%s\n", ecsVersion)
|
||||||
fmt.Println("测评频道: https://t.me/vps_reviews\n" +
|
fmt.Println("测评频道: https://t.me/vps_reviews\n" +
|
||||||
"Go项目地址:https://github.com/oneclickvirt/ecs\n" +
|
"Go项目地址:https://github.com/oneclickvirt/ecs\n" +
|
||||||
"Shell项目地址:https://github.com/spiritLHLS/ecs")
|
"Shell项目地址:https://github.com/spiritLHLS/ecs")
|
||||||
} else {
|
} else {
|
||||||
PrintCenteredTitle("Fusion Monster Test", width)
|
PrintCenteredTitle("VPS Fusion Monster Test", width)
|
||||||
fmt.Printf("Version: %s\n", ecsVersion)
|
fmt.Printf("Version: %s\n", ecsVersion)
|
||||||
fmt.Println("Review Channel: https://t.me/vps_reviews\n" +
|
fmt.Println("Review Channel: https://t.me/vps_reviews\n" +
|
||||||
"Go Project URL: https://github.com/oneclickvirt/ecs\n" +
|
"Go Project URL: https://github.com/oneclickvirt/ecs\n" +
|
||||||
@@ -42,14 +45,14 @@ func PrintHead(language string, width int, ecsVersion string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SecurityCheck 执行安全检查
|
// SecurityCheck 执行安全检查
|
||||||
func SecurityCheck(language, nt3CheckType string) (string, string, string) {
|
func SecurityCheck(language, nt3CheckType string, securtyCheckStatus bool) (string, string, string) {
|
||||||
var wgt sync.WaitGroup
|
var wgt sync.WaitGroup
|
||||||
var ipInfo, securityInfo, systemInfo string
|
var ipInfo, securityInfo, systemInfo string
|
||||||
var err error
|
var err error
|
||||||
wgt.Add(2)
|
wgt.Add(2)
|
||||||
go func() {
|
go func() {
|
||||||
defer wgt.Done()
|
defer wgt.Done()
|
||||||
ipInfo, securityInfo, err = network.NetworkCheck("both", true, language)
|
ipInfo, securityInfo, err = network.NetworkCheck("both", securtyCheckStatus, language)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
}
|
}
|
||||||
@@ -88,7 +91,7 @@ func SecurityCheck(language, nt3CheckType string) (string, string, string) {
|
|||||||
return basicInfo, securityInfo, nt3CheckType
|
return basicInfo, securityInfo, nt3CheckType
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureOutput 捕获函数输出和错误输出并返回字符串
|
// CaptureOutput 捕获函数输出和错误输出,实时输出,并返回字符串
|
||||||
func CaptureOutput(f func()) string {
|
func CaptureOutput(f func()) string {
|
||||||
// 保存旧的 stdout 和 stderr
|
// 保存旧的 stdout 和 stderr
|
||||||
oldStdout := os.Stdout
|
oldStdout := os.Stdout
|
||||||
@@ -139,7 +142,8 @@ func CaptureOutput(f func()) string {
|
|||||||
<-done
|
<-done
|
||||||
<-done
|
<-done
|
||||||
// 返回捕获的输出字符串
|
// 返回捕获的输出字符串
|
||||||
return stdoutBuf.String() + stderrBuf.String()
|
// stderrBuf.String()
|
||||||
|
return stdoutBuf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintAndCapture 捕获函数输出的同时打印内容
|
// PrintAndCapture 捕获函数输出的同时打印内容
|
||||||
@@ -154,6 +158,11 @@ func UploadText(absPath string) (string, error) {
|
|||||||
url := "https://paste.spiritlhl.net/api/upload"
|
url := "https://paste.spiritlhl.net/api/upload"
|
||||||
token := network.SecurityUploadToken
|
token := network.SecurityUploadToken
|
||||||
client := req.DefaultClient()
|
client := req.DefaultClient()
|
||||||
|
client.SetTimeout(6 * time.Second)
|
||||||
|
client.R().
|
||||||
|
SetRetryCount(2).
|
||||||
|
SetRetryBackoffInterval(1*time.Second, 5*time.Second).
|
||||||
|
SetRetryFixedInterval(2 * time.Second)
|
||||||
file, _ := os.Open(absPath)
|
file, _ := os.Open(absPath)
|
||||||
resp, err := client.R().
|
resp, err := client.R().
|
||||||
SetHeader("Authorization", token).
|
SetHeader("Authorization", token).
|
||||||
@@ -173,3 +182,51 @@ func UploadText(absPath string) (string, error) {
|
|||||||
return "", fmt.Errorf("upload failed with status code: %d", resp.StatusCode)
|
return "", fmt.Errorf("upload failed with status code: %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProcessAndUpload 创建结果文件并上传文件
|
||||||
|
func ProcessAndUpload(output string, filePath string, enableUplaod bool) {
|
||||||
|
// 检查文件是否存在
|
||||||
|
if _, err := os.Stat(filePath); err == nil {
|
||||||
|
// 文件存在,删除文件
|
||||||
|
err = os.Remove(filePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Cannot delete file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 创建文件
|
||||||
|
file, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Cannot create file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
// 匹配 ANSI 转义序列
|
||||||
|
ansiRegex := regexp.MustCompile("\x1B\\[[0-9;]+[a-zA-Z]")
|
||||||
|
// 移除 ANSI 转义序列
|
||||||
|
cleanedOutput := ansiRegex.ReplaceAllString(output, "")
|
||||||
|
// 写入文件
|
||||||
|
_, err = file.WriteString(cleanedOutput)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Cannot write to file:", err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
fmt.Println("Write test result in ", filePath)
|
||||||
|
}
|
||||||
|
if enableUplaod {
|
||||||
|
// 获取文件的绝对路径
|
||||||
|
absPath, err2 := filepath.Abs(filePath)
|
||||||
|
if err2 != nil {
|
||||||
|
fmt.Println("Failed to get absolute file path:", err2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 上传文件并生成短链接
|
||||||
|
shorturl, err3 := UploadText(absPath)
|
||||||
|
if err3 != nil {
|
||||||
|
fmt.Println("Upload failed, cannot generate short URL.")
|
||||||
|
fmt.Println(err3.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("Upload successful, short URL:", shorturl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
发布版本.bat
1
发布版本.bat
@@ -24,6 +24,7 @@ REM 提示用户输入版本号
|
|||||||
set /p version="Enter the version number (e.g., v1.0.0): "
|
set /p version="Enter the version number (e.g., v1.0.0): "
|
||||||
|
|
||||||
REM 创建并推送标签
|
REM 创建并推送标签
|
||||||
|
:push_tag
|
||||||
git tag %version%
|
git tag %version%
|
||||||
git push origin %version%
|
git push origin %version%
|
||||||
if errorlevel 1 (
|
if errorlevel 1 (
|
||||||
|
Reference in New Issue
Block a user