package op import ( "agent-wdd/config" "agent-wdd/log" "encoding/json" "fmt" "io" "net/http" "time" ) type PackageOperator struct { installPrefix []string // 安装前缀 removePrefix []string // 移除前缀 upgradePrefix []string // 升级前缀 initCommand []string } var ( AgentPackOperator = &PackageOperator{} aptPackageOperator = &PackageOperator{ installPrefix: []string{ "apt-get", "install", "--allow-downgrades", "-y", }, removePrefix: []string{ "apt", "remove", "-y", }, upgradePrefix: []string{}, initCommand: []string{ "apt-get", "update", }, } yumPackageOperator = &PackageOperator{ installPrefix: []string{ "yum", "install", "-y", }, removePrefix: []string{ "yum", "remove", "-y", }, upgradePrefix: []string{}, initCommand: []string{ "yum", "makecache", }, } ) func (op *PackageOperator) Install(tools []string) bool { // 判定本机的包管理Operator ok := generatePackageOperator() if !ok { log.Error("PackageOperator init failed! 无法执行安装操作 %s", tools) return false } // install seperately for _, tool := range tools { ok, result := SingleLineCommandExecutor(append(AgentPackOperator.installPrefix, tool)) if !ok { log.Error("[install] failed! => %s", tool) } // 打印安装的过程内容 beautifulPrintListWithTitle(result, fmt.Sprintf("安装 %s 的过程内容", tool)) } return true } // PackageInit 初始化包管理器, 同样会判定主机是否可以联网,如果本机是ubuntu或者debian, 则使用apt, 否则使用yum func (op *PackageOperator) PackageInit() bool { log.Info("PackageInit !") // beautifulPrintListWithTitle(config.ConfigCache) // package init os := config.ConfigCache.Agent.OS if os.PackInit { log.Info("PackageInit already done! skip!") return true } // 判定本机的包管理Operator ok := generatePackageOperator() if !ok { return false } os.PackInit = true os.SaveConfig() if os.IsUbuntuType { ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand) if !ok { log.Error("APT init failed! please check ! %s", resultLog) } } return true } func (op *PackageOperator) PackageInitForce() bool { log.Info("PackageInitForce !") os := config.ConfigCache.Agent.OS if os.IsUbuntuType { ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand) if !ok { log.Error("APT init failed! please check ! %s", resultLog) } log.Info("APT init success! %s", resultLog) } return true } func (op *PackageOperator) Remove(tools []string) { // 判定本机的包管理Operator generatePackageOperator() // install seperately for _, tool := range tools { ok, result := SingleLineCommandExecutor(append(AgentPackOperator.removePrefix, tool)) if !ok { log.Error("[remove] failed! => %s", tool) beautifulPrintListWithTitle(result, fmt.Sprintf("移除 %s 的过程内容", tool)) } } } func generatePackageOperator() bool { // cache return if AgentPackOperator.initCommand != nil { log.Info("PackageOperator init success! %v", AgentPackOperator.initCommand) return true } // 检查是否可以连接互联网 if config.CanConnectInternet() <= 1 { log.Error("服务器无法连接互联网,无法初始化包管理器") return false } // 检查本机是否存在OS的信息 os := config.ConfigCache.Agent.OS if os.Hostname == "" { os.Gather() os.SaveConfig() } if os.IsUbuntuType { log.Info("Ubuntu type detected! use apt package operator!") AgentPackOperator = aptPackageOperator } else { log.Info("Other type detected! use yum package operator!") 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 } func beautifulPrintListWithTitle(contend []string, title string) { fmt.Println() fmt.Println(">>>>>>>> " + title + " <<<<<<<<") for _, line := range contend { fmt.Println(line) } fmt.Println(">>>>>>>> end <<<<<<<<") }