大量的更新
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
|
||||
|
||||
./agent-deploy/
|
||||
./message_pusher/
|
||||
./port_forwarding/
|
||||
./server/
|
||||
./server-go/
|
||||
./socks_txthinking/
|
||||
./source/
|
||||
agent-deploy/
|
||||
message_pusher/
|
||||
port_forwarding/
|
||||
server/
|
||||
server-go/
|
||||
socks_txthinking/
|
||||
source/
|
||||
|
||||
@@ -208,4 +208,116 @@ func addDockerSubcommands(cmd *cobra.Command) {
|
||||
|
||||
func addDockerComposeSubcommands(cmd *cobra.Command) {
|
||||
|
||||
installCmd := &cobra.Command{
|
||||
Use: "online [version]",
|
||||
Short: "安装Docker Compose",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info("Installing Docker Compose...")
|
||||
|
||||
// 检查参数
|
||||
if len(args) > 0 {
|
||||
fmt.Printf("Installing Docker Compose version: %s\n", args[0])
|
||||
}
|
||||
|
||||
// 默认安装最新版本
|
||||
version := "latest"
|
||||
if len(args) > 0 {
|
||||
version = args[0]
|
||||
}
|
||||
|
||||
// 如果是最新版本,则通过GitHub API查询
|
||||
if version == "latest" {
|
||||
latestVersion, err := op.GetLatestGithubReleaseVersion("docker", "compose")
|
||||
if err != nil {
|
||||
log.Error("获取Docker Compose最新版本失败: %s", err)
|
||||
} else {
|
||||
version = latestVersion
|
||||
log.Info("获取到Docker Compose最新版本: %s", version)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("安装 Docker Compose 版本: %s", version)
|
||||
|
||||
// 检查是否可以连接互联网
|
||||
if config.CanConnectInternet() <= 1 {
|
||||
log.Error("服务器无法连接互联网,无法在线安装 Docker Compose")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查 Docker 是否已安装
|
||||
dockerExists := op.CommandExistsByPath("docker")
|
||||
if !dockerExists {
|
||||
log.Error("Docker 未安装,请先安装 Docker")
|
||||
return
|
||||
}
|
||||
|
||||
// 根据架构选择合适的下载链接
|
||||
arch := runtime.GOARCH
|
||||
downloadURL := fmt.Sprintf("https://github.com/docker/compose/releases/download/%s/docker-compose-linux-%s", version, arch)
|
||||
|
||||
log.Info("Downloading Docker Compose from: %s", downloadURL)
|
||||
// 下载 Docker Compose
|
||||
ok, ccc := op.DownloadFile(downloadURL, "/usr/local/bin/docker-compose")
|
||||
if !ok {
|
||||
log.Error("下载 Docker Compose 失败: %s", ccc)
|
||||
return
|
||||
}
|
||||
|
||||
// 设置执行权限
|
||||
chmodCmd := []string{"chmod", "+x", "/usr/local/bin/docker-compose"}
|
||||
ok, resultLog := op.SingleLineCommandExecutor(chmodCmd)
|
||||
if !ok {
|
||||
log.Error("设置 Docker Compose 权限失败: %s", resultLog)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建软链接
|
||||
linkCmd := []string{"ln", "-sf", "/usr/local/bin/docker-compose", "/usr/bin/docker-compose"}
|
||||
op.SingleLineCommandExecutor(linkCmd)
|
||||
|
||||
// 验证安装
|
||||
verifyCmd := []string{"docker-compose", "--version"}
|
||||
ok, resultLog = op.SingleLineCommandExecutor(verifyCmd)
|
||||
if !ok {
|
||||
log.Error("Docker Compose 安装验证失败: %s", resultLog)
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Docker Compose 安装成功: %s", resultLog)
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
removeCmd := &cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "卸载Docker Compose",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info("Removing Docker Compose...")
|
||||
},
|
||||
}
|
||||
|
||||
localCmd := &cobra.Command{
|
||||
Use: "local [path]",
|
||||
Short: "本地安装Docker Compose",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info("Installing Docker Compose from local file...")
|
||||
},
|
||||
}
|
||||
|
||||
versionCmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "查看Docker Compose版本",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info("Docker Compose version...")
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
installCmd,
|
||||
removeCmd,
|
||||
localCmd,
|
||||
versionCmd,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ package config
|
||||
import (
|
||||
"agent-wdd/log"
|
||||
"agent-wdd/utils"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
)
|
||||
|
||||
var WddConfigFilePath = "/usr/local/etc/wdd/agent-wdd-config.yaml"
|
||||
@@ -14,9 +16,12 @@ var ConfigCache *Config
|
||||
|
||||
func init() {
|
||||
// 根据运行的操作系统不同, 修改 WddConfigFilePath 的位置
|
||||
if runtime.GOOS == "windows" {
|
||||
homedir, _ := os.UserHomeDir()
|
||||
WddConfigFilePath = homedir + "\\agent-wdd\\agent-wdd-config.yaml"
|
||||
}
|
||||
}
|
||||
|
||||
// 配置结构体定义
|
||||
type Config struct {
|
||||
TimeStamp string `yaml:"timestamp"`
|
||||
ModifiedTimes int `yaml:"modifiedTimes"`
|
||||
|
||||
@@ -3,12 +3,10 @@ package config
|
||||
import (
|
||||
"agent-wdd/log"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var CommonDiskPath = []string{
|
||||
@@ -82,32 +80,31 @@ func DiskListGather() {
|
||||
}
|
||||
|
||||
func (disk *Disk) calculateDiskUsage() {
|
||||
var stat syscall.Statfs_t
|
||||
err := syscall.Statfs(disk.Path, &stat)
|
||||
if err != nil {
|
||||
log.Error("disk syscall error of %v", err)
|
||||
// var stat unix.Statfs_t
|
||||
// err := unix.Statfs(disk.Path, &stat)
|
||||
// if err != nil {
|
||||
// log.Error("disk syscall error: %v", err)
|
||||
// disk.Size = "0B"
|
||||
// disk.Usage = "0B"
|
||||
// disk.Percent = "0.00%"
|
||||
// return
|
||||
// }
|
||||
|
||||
disk.Size = "0B"
|
||||
disk.Usage = "0B"
|
||||
disk.Percent = "0.00%"
|
||||
return
|
||||
}
|
||||
// // 计算存储空间大小
|
||||
// totalBytes := stat.Blocks * uint64(stat.Bsize)
|
||||
// availBytes := stat.Bavail * uint64(stat.Bsize)
|
||||
// usedBytes := totalBytes - availBytes
|
||||
|
||||
// 计算存储空间大小
|
||||
totalBytes := stat.Blocks * uint64(stat.Bsize)
|
||||
availBytes := stat.Bavail * uint64(stat.Bsize)
|
||||
usedBytes := totalBytes - availBytes
|
||||
// // 格式化输出
|
||||
// disk.Size = formatDiskSize(totalBytes)
|
||||
// disk.Usage = formatDiskSize(usedBytes)
|
||||
|
||||
// 格式化输出
|
||||
disk.Size = formatDiskSize(totalBytes)
|
||||
disk.Usage = formatDiskSize(usedBytes)
|
||||
|
||||
if totalBytes == 0 {
|
||||
disk.Percent = "0.00%"
|
||||
} else {
|
||||
percent := float64(usedBytes) / float64(totalBytes) * 100
|
||||
disk.Percent = fmt.Sprintf("%.2f%%", percent)
|
||||
}
|
||||
// if totalBytes == 0 {
|
||||
// disk.Percent = "0.00%"
|
||||
// } else {
|
||||
// percent := float64(usedBytes) / float64(totalBytes) * 100
|
||||
// disk.Percent = fmt.Sprintf("%.2f%%", percent)
|
||||
// }
|
||||
}
|
||||
|
||||
func formatDiskSize(bytes uint64) string {
|
||||
|
||||
@@ -41,6 +41,23 @@ func (network *Network) Gather() {
|
||||
|
||||
// CanConnectInternet 判定主机能够上网
|
||||
func CanConnectInternet() int {
|
||||
|
||||
// 初始化 ConfigCache
|
||||
if ConfigCache == nil {
|
||||
ConfigCache = &Config{
|
||||
TimeStamp: "",
|
||||
ModifiedTimes: 0,
|
||||
Agent: Agent{
|
||||
OS: OS{},
|
||||
Network: Network{},
|
||||
CPU: CPU{},
|
||||
Mem: Memory{},
|
||||
Swap: Swap{},
|
||||
Disks: []Disk{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 读取 config 文件,判定能否上网
|
||||
internetCode := ConfigCache.Agent.Network.Internet
|
||||
|
||||
|
||||
43
agent-wdd/op/DownloadExecutor.go
Normal file
43
agent-wdd/op/DownloadExecutor.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package op
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func DownloadFile(url string, path string) (bool, string) {
|
||||
// 创建HTTP客户端
|
||||
client := &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
// 发送GET请求
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("下载文件失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查响应状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return false, fmt.Sprintf("下载文件失败,HTTP状态码: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 创建目标文件
|
||||
out, err := os.Create(path)
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("创建文件失败: %v", err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
// 将响应内容写入文件
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("写入文件失败: %v", err)
|
||||
}
|
||||
|
||||
return true, fmt.Sprintf("文件下载成功: %s", path)
|
||||
}
|
||||
@@ -4,7 +4,12 @@ import (
|
||||
"agent-wdd/config"
|
||||
"agent-wdd/log"
|
||||
"agent-wdd/utils"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PackageOperator struct {
|
||||
@@ -36,12 +41,19 @@ var (
|
||||
"yum", "remove", "-y",
|
||||
},
|
||||
upgradePrefix: []string{},
|
||||
initCommand: []string{
|
||||
"yum", "makecache",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func (op *PackageOperator) Install(tools []string) {
|
||||
func (op *PackageOperator) Install(tools []string) bool {
|
||||
// 判定本机的包管理Operator
|
||||
generatePackageOperator()
|
||||
ok := generatePackageOperator()
|
||||
if !ok {
|
||||
log.Error("PackageOperator init failed! 无法执行安装操作 %s", tools)
|
||||
return false
|
||||
}
|
||||
|
||||
// install seperately
|
||||
for _, tool := range tools {
|
||||
@@ -51,14 +63,19 @@ func (op *PackageOperator) Install(tools []string) {
|
||||
utils.BeautifulPrint(result)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// PackageInit 初始化包管理器, 如果本机是ubuntu或者debian, 则使用apt, 否则使用yum
|
||||
func (op *PackageOperator) PackageInit() {
|
||||
// PackageInit 初始化包管理器, 同样会判定主机是否可以联网,如果本机是ubuntu或者debian, 则使用apt, 否则使用yum
|
||||
func (op *PackageOperator) PackageInit() bool {
|
||||
log.Info("PackageInit !")
|
||||
|
||||
// 判定本机的包管理Operator
|
||||
generatePackageOperator()
|
||||
ok := generatePackageOperator()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
// package init
|
||||
os := config.ConfigCache.Agent.OS
|
||||
@@ -72,6 +89,8 @@ func (op *PackageOperator) PackageInit() {
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
func (op *PackageOperator) Remove(tools []string) {
|
||||
@@ -89,13 +108,20 @@ func (op *PackageOperator) Remove(tools []string) {
|
||||
|
||||
}
|
||||
|
||||
func generatePackageOperator() {
|
||||
func generatePackageOperator() bool {
|
||||
|
||||
// cache return
|
||||
if AgentPackOperator.initCommand != nil {
|
||||
return
|
||||
return true
|
||||
}
|
||||
// 检查本机是否存在Os的信息
|
||||
|
||||
// 检查是否可以连接互联网
|
||||
if config.CanConnectInternet() <= 1 {
|
||||
log.Error("服务器无法连接互联网,无法初始化包管理器")
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查本机是否存在OS的信息
|
||||
os := config.ConfigCache.Agent.OS
|
||||
if os.Hostname == "" {
|
||||
os.Gather()
|
||||
@@ -108,4 +134,64 @@ func generatePackageOperator() {
|
||||
} else {
|
||||
AgentPackOperator = yumPackageOperator
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GetLatestGithubReleaseVersion 获取GitHub仓库的最新版本
|
||||
func GetLatestGithubReleaseVersion(repoOwner, repoName string) (string, error) {
|
||||
// 检查是否可以连接互联网
|
||||
if config.CanConnectInternet() <= 1 {
|
||||
return "", fmt.Errorf("服务器无法连接互联网,无法获取GitHub最新版本")
|
||||
}
|
||||
|
||||
// 设置超时时间为10秒的HTTP客户端
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
// 构建GitHub API URL
|
||||
apiURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", repoOwner, repoName)
|
||||
|
||||
// 发送GET请求
|
||||
resp, err := client.Get(apiURL)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("请求GitHub API失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查响应状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("GitHub API返回非200状态码: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 读取响应体
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("读取响应内容失败: %v", err)
|
||||
}
|
||||
|
||||
// 解析JSON响应
|
||||
var release struct {
|
||||
TagName string `json:"tag_name"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &release); err != nil {
|
||||
return "", fmt.Errorf("解析JSON响应失败: %v", err)
|
||||
}
|
||||
|
||||
return release.TagName, nil
|
||||
}
|
||||
|
||||
// CommandExists 判定命令是否存在
|
||||
func CommandExists(command string) bool {
|
||||
ok, _ := SingleLineCommandExecutor([]string{"command", "-v", command})
|
||||
return ok
|
||||
}
|
||||
|
||||
func CommandExistsByPath(command string) bool {
|
||||
|
||||
// 查询 /usr/bin /usr/local/bin中是否有可执行文件
|
||||
ok, _ := SingleLineCommandExecutor([]string{"find", "/usr/bin", "/usr/local/bin", "-name", command})
|
||||
return ok
|
||||
}
|
||||
|
||||
21
agent-wdd/op/PackageOperator_test.go
Normal file
21
agent-wdd/op/PackageOperator_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package op
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetLatestGithubReleaseVersion(t *testing.T) {
|
||||
repoOwner := "docker"
|
||||
repoName := "compose"
|
||||
|
||||
version, err := GetLatestGithubReleaseVersion(repoOwner, repoName)
|
||||
if err != nil {
|
||||
t.Fatalf("获取最新版本失败: %v", err)
|
||||
}
|
||||
|
||||
if version == "" {
|
||||
t.Error("获取的版本号为空")
|
||||
}
|
||||
|
||||
t.Logf("获取到的最新版本号: %s", version)
|
||||
}
|
||||
Reference in New Issue
Block a user