package cmd import ( "agent-wdd/cmd/beans" "agent-wdd/host_info" "agent-wdd/log" "agent-wdd/op" "agent-wdd/utils" "fmt" "os" "runtime" "strings" "time" "github.com/spf13/cobra" ) var ( ubuntuCommonTools = []string{ "iputils-ping", "net-tools", "dnsutils", "lsof", "curl", "wget", "mtr-tiny", "vim", "htop", "lrzsz", } centosCommonTools = []string{ "deltarpm", "net-tools", "iputils", "bind-utils", "lsof", "curl", "wget", "vim", "mtr", "htop", } dockerLocalInstallPath = "/root/wdd/docker-amd64-20.10.15.tgz" // 本地安装docker的文件路径 dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-amd64" // 本地安装docker compose的文件路径 harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0.tgz" // 本地安装harbor的文件路径 ) func init() { switch runtime.GOARCH { case "amd64": dockerLocalInstallPath = "/root/wdd/docker-amd64-20.10.15.tgz" // 本地安装docker的文件路径 dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-amd64" // 本地安装docker compose的文件路径 harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0.tgz" // 本地安装harbor的文件路径 case "arm64": dockerLocalInstallPath = "/root/wdd/docker-arm64-20.10.15.tgz" // 本地安装docker的文件路径 dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-arm64" // 本地安装docker compose的文件路径 harborLocalInstallPath = "/root/wdd/harbor-offline-installer-v2.9.0-arm64.tgz" // 本地安装harbor的文件路径 } } // 添加base子命令 func addBaseSubcommands(cmd *cobra.Command) { // 1.1 docker dockerCmd := &cobra.Command{ Use: "docker", Short: "Docker相关操作", } addDockerSubcommands(dockerCmd) // 1.2 dockercompose dockerComposeCmd := &cobra.Command{ Use: "dockercompose", Short: "Docker Compose相关操作", } addDockerComposeSubcommands(dockerComposeCmd) // 其他base子命令... swapCmd := &cobra.Command{ Use: "swap", Short: "关闭系统的Swap", Run: func(cmd *cobra.Command, args []string) { log.Info("Swap 关闭!") // 实现这个函数,能够关闭centos或者ubuntu系统的swap // 备份文件存在,pass if !utils.FileExistAndNotNull("/etc/fstab_back_wdd_swap") { utils.AppendOverwriteContentToFile( "/etc/fstab", "/etc/fstab_back_wdd_swap", ) } // 执行关闭操作 op.SingleLineCommandExecutor([]string{ "swapoff", "-a", }) op.SingleLineCommandExecutor([]string{ "sed", "-i", "/swap/d", "/etc/fstab", }) log.Info("Swap 关闭成功!") }, } selinuxCmd := &cobra.Command{ Use: "selinux", Short: "关闭selinux", Run: func(cmd *cobra.Command, args []string) { log.Info("Selinux 关闭!") // 如果configCache的OS为空,则收集OS信息 if host_info.ConfigCache.Agent.OS.Hostname == "" { log.Warning("ConfigCache OS is nil") host_info.ConfigCache.Agent.OS.Gather() host_info.ConfigCache.Agent.OS.SaveConfig() } os := host_info.ConfigCache.Agent.OS if os.IsUbuntuType { log.Info("Ubuntu 系统,跳过关闭selinux!") return } else { op.SingleLineCommandExecutor([]string{ "setenforce", "0", }) // 备份一下/etc/selinux/config if !utils.FileExistAndNotNull("/etc/selinux/config_back_wdd_selinux") { utils.AppendOverwriteContentToFile( "/etc/selinux/config", "/etc/selinux/config_back_wdd_selinux", ) } // 持久化关闭selinux utils.FindAndDeleteContentInFile("SELINUX=enforcing", "/etc/selinux/config") utils.FindAndDeleteContentInFile("SELINUX=permissive", "/etc/selinux/config") utils.FindAndDeleteContentInFile("SELINUX=disabled", "/etc/selinux/config") utils.AppendContentToFile("SELINUX=disabled", "/etc/selinux/config") } log.Info("Selinux 关闭成功!") }, } firewallCmd := &cobra.Command{ Use: "firewall", Short: "关闭防火墙", Run: func(cmd *cobra.Command, args []string) { log.Info("Firewall 关闭!") // 调用systemd关闭firewalld op.SystemdDown("firewalld") op.SystemdDisable("firewalld") // 调用systemd关闭ufw op.SystemdDown("ufw") op.SystemdDisable("ufw") // 清空路由表 log.Info("清空路由表...") commandExecutor := [][]string{ { "iptables", "-F", }, { "iptables", "-t", "nat", "-F", }, { "iptables", "-t", "mangle", "-F", }, { "iptables", "-t", "raw", "-F", }, { "ip6tables", "-F", }, { "ip6tables", "-t", "nat", "-F", }, { "ip6tables", "-t", "mangle", "-F", }, { "ip6tables", "-t", "raw", "-F", }, } for _, command := range commandExecutor { op.SingleLineCommandExecutor(command) } log.Info("Firewall 关闭成功!") }, } sysconfigCmd := &cobra.Command{ Use: "sysconfig", Short: "修改系统的sysconfig", Run: func(cmd *cobra.Command, args []string) { log.Info("Sysconfig 修改!") // 修改系统的sysconfig sysctlConfigFile := "/etc/sysctl.d/wdd-k8s.conf" if !utils.AppendOverwriteContentToFile(beans.SysctlConfig, sysctlConfigFile) { log.Error("[ModifySysConfigBastion] - error appending sysctl config to sysctl.d !") return } op.SingleLineCommandExecutor([]string{ "sysctl", "-p", sysctlConfigFile, }) log.Info("Sysconfig 修改成功!") }, } // 通用工具安装 commonToolsInstall := &cobra.Command{ Use: "tools", Short: "通用工具安装 利用本机的yum,apt等从网络安装常用的软件", Run: func(cmd *cobra.Command, args []string) { log.Info("Common tool installation!") // Whether It can connect to internet if host_info.CanConnectInternet() <= 1 { log.Error("服务器无法连接互联网,无法执行tools") return } // package install // only support ubuntu(debian) centos(debian openEuler) packOperator := op.AgentPackOperator packOperator.PackageInit() os := host_info.ConfigCache.Agent.OS if os.IsUbuntuType { packOperator.Install(ubuntuCommonTools) } else { packOperator.Install(centosCommonTools) } }, } sshCmd := &cobra.Command{ Use: "ssh", Short: "修改ssh配置", } addSSHSubcommands(sshCmd) // harbor 相关的函数 harborCmd := &cobra.Command{ Use: "harbor", Short: "harbor相关的操作", } addHarborSubcommands(harborCmd) cmd.AddCommand( dockerCmd, dockerComposeCmd, harborCmd, swapCmd, commonToolsInstall, selinuxCmd, firewallCmd, sysconfigCmd, sshCmd, // 其他命令... ) } // addHarborSubcommands 添加harbor子命令 func addHarborSubcommands(harborCmd *cobra.Command) { harborInstallCmd := &cobra.Command{ Use: "install", Short: "安装harbor 从本地安装 " + harborLocalInstallPath, Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("安装harbor") // 检查是否存在harbor目录 if utils.FileExistAndNotNull("/root/wdd/harbor/harbor.yml") { log.Info("harbor已存在,无需安装!") return } // 解压harbor utils.UnzipFile(harborLocalInstallPath, "/root/wdd/") // 获取本机的内网IPv4地址 configCache := host_info.ConfigCache if len(configCache.Agent.Network.Interfaces) == 0 { log.Error("没有获取到本机的ipv4地址,无法安装harbor! 请执行 info all !") } ip := configCache.Agent.Network.Interfaces[0].IPv4 if ip == "" { log.Error("没有获取到本机的ipv4地址,无法安装harbor! 请执行 info all !") return } // 修改harbor的配置 utils.AppendOverwriteContentToFile(beans.HarborYamlConfig, "/root/wdd/harbor/harbor.yml") utils.FindAndReplaceContentInFile("HarborHostName", ip, "/root/wdd/harbor/harbor.yml") if !utils.FileExistAndNotNull("/root/wdd/harbor/harbor.yml") { log.Error("修改harbor的配置失败! 请检查文件是否存在!") return } // 运行install.sh op.SingleLineCommandExecutor([]string{"cd", "/root/wdd/harbor"}) ok, log1 := op.RealTimeCommandExecutor([]string{"/bin/bash", "/root/wdd/harbor/install.sh"}) if !ok { log.Error("安装harbor失败: %s", log1) return } // wait to see the harbor is running log.Info("等待10秒 harbor启动...") time.Sleep(10 * time.Second) // 执行docker ps -a 查看 harbor名称的容器是否存在 Exit 或者 Restarting 则表示有错误! if !checkHarborIsRunning() { log.Error("harbor启动失败! 请检查日志!") return } log.Info("安装harbor成功!") }, } harborUninstallCmd := &cobra.Command{ Use: "uninstall", Short: "卸载harbor", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("暂未实现harbor卸载!") }, } harborStartCmd := &cobra.Command{ Use: "start", Short: "启动harbor", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("启动harbor") // 检查harbor是否存在 if !utils.FileExistAndNotNull("/root/wdd/harbor/docker-compose.yml") { log.Error("harbor不存在! 请先安装harbor!") return } // 启动harbor op.SingleLineCommandExecutor([]string{"cd", "/root/wdd/harbor"}) ok, log1 := op.SingleLineCommandExecutor([]string{"docker-compose", "up", "-d"}) if !ok { log.Error("启动harbor失败: %s", log1) return } // 等待10秒 time.Sleep(10 * time.Second) // 检查harbor是否启动成功 if !checkHarborIsRunning() { log.Error("harbor启动失败! 请检查日志!") return } log.Info("启动harbor成功!") fmt.Println("") fmt.Println("") }, } // 停止harbor harborStopCmd := &cobra.Command{ Use: "stop", Short: "停止harbor", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("停止harbor") // 检查harbor是否存在 if !utils.FileExistAndNotNull("/root/wdd/harbor/docker-compose.yml") { log.Error("harbor不存在! 请先安装harbor!") return } // 进入harbor目录 os.Chdir("/root/wdd/harbor") // 停止harbor ok, log1 := op.SingleLineCommandExecutor([]string{"docker-compose", "down"}) if !ok { log.Error("停止harbor失败: %s", log1) return } log.Info("停止harbor成功!") fmt.Println("") fmt.Println("") }, } harborCmd.AddCommand(harborInstallCmd, harborUninstallCmd, harborStartCmd, harborStopCmd) } // checkHarborIsRunning 检查harbor是否运行 如果存在Exit 或者 Restarting 则表示有错误! func checkHarborIsRunning() bool { _, resultLog := op.PipeLineCommandExecutor([][]string{ { "docker", "ps", "-a", }, { "grep", "goharbor/", }, { "grep", "-E", "'Exit|Restarting'", }, { "wc", "-l", }, }) if strings.TrimSpace(resultLog[0]) != "0" { log.Error("harbor启动失败! 请检查日志!") return false } return true } func addSSHSubcommands(sshCmd *cobra.Command) { keyCmd := &cobra.Command{ Use: "key", Short: "安装默认的ssh-key", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("安装默认的ssh-key!") // 创建.ssh目录 utils.CreateFolder("/root/.ssh") // 检查密钥是否存在 if utils.FileExistAndNotNull("/root/.ssh/id_ed25519") && utils.FileExistAndNotNull("/root/.ssh/id_ed25519.pub") && utils.FindContentInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") { log.Info("SSH密钥已存在,无需重新安装。") return } // 下载标准的私钥和公钥 if !utils.AppendOverwriteContentToFile(beans.Ed25519PrivateKey, "/root/.ssh/id_ed25519") { log.Error("[InstallDefaultSSHKey] - error appending private ssh key to authorized_keys !") return } if !utils.AppendOverwriteContentToFile(beans.Ed25519PublicKey, "/root/.ssh/id_ed25519.pub") { log.Error("[InstallDefaultSSHKey] - error appending public ssh key to authorized_keys !") return } // 写入到authorized_keys if !utils.AppendFileToFile("/root/.ssh/id_ed25519.pub", "/root/.ssh/authorized_keys") { log.Error("[InstallDefaultSSHKey] - error appending ssh key to authorized_keys !") return } // 设置权限 op.SingleLineCommandExecutor([]string{ "chmod", "600", "/root/.ssh/id_ed25519", }) // 检查 if utils.FindContentInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") { log.Info("[InstallDefaultSSHKey] - install success !") fmt.Println("") } else { log.Error("[InstallDefaultSSHKey] - authorized_keys don't contain the ssh-pub key !") } fmt.Println("") fmt.Println("") }, } portCmd := &cobra.Command{ Use: "port", Short: "修改ssh端口", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("修改ssh端口!") // 检查参数 if len(args) > 0 { fmt.Printf("modify ssh port to: %s\n", args[0]) } // 没有传递参数,使用默认参数 port := "22333" log.Info("[ModifySSHPort] modify ssh port to: %s", port) // 文件中已经包含了Port 22333 则pass sshdPortString := fmt.Sprintf("Port %s", port) if utils.FindContentInFile(sshdPortString, "/etc/ssh/sshd_config") { log.Info("[ModifySSHPort] ssh port already modified to: %s", port) } else { // 修改ssh端口 utils.AppendContentToFile(sshdPortString, "/etc/ssh/sshd_config") } // 重启ssh服务 ok, resultLog := op.SystemdRestart("sshd") if !ok { log.Error("[ModifySSHPort] restart sshd error: %s", resultLog) return } log.Info("[ModifySSHPort] modify ssh port to: %s success!", port) fmt.Println("") fmt.Println("") }, } configCmd := &cobra.Command{ Use: "config", Short: "修改ssh配置 为wdd默认配置!", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("修改ssh配置 为wdd默认配置!") // 备份文件 if !utils.FileExistAndNotNull("/etc/ssh/sshd_config_back_wdd_ssh") { utils.AppendOverwriteContentToFile("/etc/ssh/sshd_config", "/etc/ssh/sshd_config_back_wdd_ssh") } // 修改ssh配置 utils.AppendOverwriteContentToFile(beans.DefaultSshdConfig, "/etc/ssh/sshd_config") // 重启ssh服务 ok, resultLog := op.SystemdRestart("sshd") if !ok { log.Error("sshd 重启失败: %s", resultLog) return } log.Info("[sshd配置修改] 成功!") fmt.Println("") fmt.Println("") }, } sshCmd.AddCommand(keyCmd, portCmd, configCmd) } // 添加docker子命令 func addDockerSubcommands(cmd *cobra.Command) { onlineCmd := &cobra.Command{ Use: "online [version]", Short: "网络安装Docker, 如果不指定参数默认安装20.10.24版本", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("网络安装Docker, 如果不指定参数默认安装20.10.24版本") // 检查参数 if len(args) > 0 { fmt.Printf("Installing Docker version: %s\n", args[0]) } // 安装docker packOperator := op.AgentPackOperator packOperator.PackageInit() configCache := host_info.ConfigCache if configCache.Agent.OS.IsUbuntuType { // 安装apt-transport-https ca-certificates curl gnupg software-properties-common 依赖部分 packOperator.Install([]string{"apt-transport-https", "ca-certificates", "curl", "gnupg", "software-properties-common"}) // 安装docker的 gpg key dockerGPGFilePath := "/etc/apt/keyrings/docker.gpg" dockerAPTFilePath := "/etc/apt/sources.list.d/docker.list" dockerGPGSource := "https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg" dockerAPTSource := "https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu" // 创建docker的 gpg key 文件 utils.CreateFolder("/etc/apt/keyrings") // 删除docker的 gpg key 文件 utils.RemoveFile(dockerGPGFilePath) utils.RemoveFile(dockerAPTFilePath) // 如果可以访问外网,则使用外网源 if configCache.Agent.Network.Internet == 9 { dockerGPGSource = "https://download.docker.com/linux/ubuntu/gpg" dockerAPTSource = "https://download.docker.com/linux/ubuntu" } ok, l2 := op.PipeLineCommandExecutor([][]string{ { "curl", "-fsSL", dockerGPGSource, }, { "gpg", "--dearmor", "-o", dockerGPGFilePath, }, }) if !ok { log.Error("下载docker gpg文件失败: %s", l2) return } if !utils.FileExistAndNotNull(dockerGPGFilePath) { log.Error("添加gpg失败!") return } op.SingleLineCommandExecutor([]string{ "chmod", "a+r", dockerGPGFilePath, }, ) if configCache.Agent.OS.OSReleaseCode == "" { log.Error("获取系统发行版代号失败! 无法安装docker!") return } dockerAPTSourceCommand := "deb [arch=" + configCache.Agent.OS.Arch + " signed-by=" + dockerGPGFilePath + "] " + dockerAPTSource + " " + configCache.Agent.OS.OSReleaseCode + " stable" log.Info("dockerAPTSourceCommand is => %s ", dockerAPTSourceCommand) utils.AppendOverwriteContentToFile(dockerAPTSourceCommand, dockerAPTFilePath) // 强制初始化APT update packOperator.PackageInitForce() // 20.04 default specificDockerVersion := "5:20.10.24~3-0~ubuntu-" + configCache.Agent.OS.OSReleaseCode // apt-cache madison docker-ce | grep 20.10.20 | awk '{print$3}' // get by method ok, log4 := op.PipeLineCommandExecutor([][]string{ { "apt-cache", "madison", "docker-ce", }, { "grep", "20.10.20", }, { "awk", "'{print$3}'", }, }) if ok && log4 != nil && len(log4) > 0 { specificDockerVersion = strings.TrimSpace(log4[0]) fmt.Println("get docker version from online => " + specificDockerVersion) } log.Info("需要安装的docker版本为 => %s", specificDockerVersion) dockerStaffList := []string{ "docker-ce=" + specificDockerVersion, "docker-ce-cli=" + specificDockerVersion, "containerd.io", "docker-compose-plugin", } ok = packOperator.Install(dockerStaffList) if !ok { log.Error("安装docker存在问题,请检查!") return } } else { log.Error("当前系统不是ubuntu系统,暂时无法安装docker! 请使用local的方式安装") return } log.Info("安装docker成功!") // 启动docker op.SystemdUp("docker") op.SystemdEnable("docker") // 检查docker是否启动成功 ok, resultLog := op.SystemIsRunning("docker") if !ok { log.Error("docker启动失败: %s", resultLog) return } log.Info("docker启动成功! ") fmt.Println("") fmt.Println("") }, } removeCmd := &cobra.Command{ Use: "remove", Short: "卸载Docker", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Removing Docker...") // 检查docker是二进制安装还是通过包安装的 dockerExists := op.CommandExistsByPath("docker") if !dockerExists { log.Info("Docker 未安装,无需卸载!") return } // 卸载docker packOperator := op.AgentPackOperator packOperator.PackageInit() packOperator.Remove([]string{"docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin", "docker-compose-plugin"}) // 删除docker目录 utils.RemoveFile("/usr/bin/docker") utils.RemoveFile("/usr/bin/docker-compose") utils.RemoveFile("/usr/bin/docker-buildx") utils.RemoveFile("/usr/bin/docker-compose-plugin") utils.RemoveFile("/usr/bin/containerd") // 删除docker的配置文件 systemd utils.RemoveFile("/etc/systemd/system/docker.service") utils.RemoveFile("/etc/systemd/system/docker.socket") utils.RemoveFile("/etc/systemd/system/containerd.service") utils.RemoveFile(beans.ContainerdServiceFile) utils.RemoveFile(beans.DockerSocketFile) utils.RemoveFile(beans.DockerServiceFile) // 删除docker的日志文件 utils.RemoveFile("/var/log/docker") log.Info("Docker 卸载成功!") }, } localCmd := &cobra.Command{ Use: "local", Short: "本地安装Docker, 默认安装20.10.15版本, 安装文件应该为 " + dockerLocalInstallPath, Run: func(cmd *cobra.Command, args []string) { log.Info("Installing Docker from local file: %s", dockerLocalInstallPath) exist := utils.FileExistAndNotNull(dockerLocalInstallPath) if !exist { log.Error("Docker local install file not found: %s", dockerLocalInstallPath) return } // 解压文件 utils.UnzipFile(dockerLocalInstallPath, "/root/wdd/") // 设置权限 dockerBinList := []string{ "docker-init", "containerd", "ctr", "runc", "dockerd", "docker-proxy", "containerd-shim", "docker", "containerd-shim-runc-v2", } // 删除旧的docker 二进制文件 for _, bin := range dockerBinList { utils.RemoveFile("/usr/bin/" + bin) } // 安装docker err := utils.MoveFolerToAnother("/root/wdd/docker/", "/usr/bin") if err != nil { log.Error("Failed to move Docker binaries: %s", err.Error()) return } for _, bin := range dockerBinList { ok, resultLog := op.SingleLineCommandExecutor([]string{"chmod", "777", "/usr/bin/" + bin}) if !ok { log.Error("Failed to set permissions for Docker binaries: %s", resultLog) } } // 配置并启动Docker服务 // systemd daemonize docker utils.AppendOverwriteContentToFile(beans.ContainerdDaemonService, beans.ContainerdServiceFile) if !utils.FileExistAndNotNull(beans.ContainerdServiceFile) { log.Error("docker deamon file not exists !") } utils.AppendOverwriteContentToFile(beans.DockerSocketDaemonService, beans.DockerSocketFile) if !utils.FileExistAndNotNull(beans.DockerSocketFile) { log.Error("docker deamon file not exists !") } utils.AppendOverwriteContentToFile(beans.DockerDaemonService, beans.DockerServiceFile) if !utils.FileExistAndNotNull(beans.DockerServiceFile) { log.Error("docker deamon file not exists !") } log.Info("docker dameon file append success !") ok, resultLog := op.SystemdDaemonReload() if !ok { log.Error("daemon reload error ! %s", resultLog) return } op.SingleLineCommandExecutor([]string{"systemctl", "unmask", "containerd"}) op.SingleLineCommandExecutor([]string{"systemctl", "unmask", "docker.socket"}) op.SingleLineCommandExecutor([]string{"systemctl", "unmask", "docker"}) op.SingleLineCommandExecutor([]string{"groupadd", "docker"}) op.SingleLineCommandExecutor([]string{"usermod", "-aG", "docker", "root"}) op.SingleLineCommandExecutor([]string{"newgrp", "docker"}) systemdUp, resultLog := op.SystemdUp("containerd") if !systemdUp { log.Error("[InstallDockerBastion] - start containerd service error ! %s", resultLog) return } ok, resultLog = op.SystemdUp("docker.socket") if !ok { log.Error("[InstallDockerBastion] - start docker.socket error ! %s", resultLog) return } ok, resultLog = op.SystemdUp("docker") if !ok { log.Error("[InstallDockerBastion] - start docker service error ! %s", resultLog) return } log.Info("Docker installed successfully from local file!") }, } configCmd := &cobra.Command{ Use: "config", Short: "配置Docker", Run: func(cmd *cobra.Command, args []string) { fmt.Println("") log.Info("配置Docker-此命令仅在主节点执行即可") // 检查docker是否安装 dockerExists := op.CommandExistsByPath("docker") if !dockerExists { log.Error("Docker 未安装,请先安装 Docker") return } // 获取当前内网IP ip := host_info.ConfigCache.Agent.Network.Interfaces[0].IPv4 if ip == "" { log.Error("获取当前内网IP失败, 无法进行docker config配置!") return } // 配置docker的daemon.json if !utils.AppendOverwriteContentToFile(beans.DockerDeamonConfig, "/etc/docker/daemon.json") { log.Error("配置docker的daemon.json失败!") return } // 替换其中的字段 utils.FindAndReplaceContentInFile("DockerRegisterDomain", ip, "/etc/docker/daemon.json") // 重启docker op.SystemdRestart("docker") // 检查docker是否重启成功 ok, resultLog := op.SystemIsRunning("docker") if !ok { log.Error("docker daemon config 失败, docker重启失败: %s", resultLog) return } daemonJsonContent := utils.ReadAllContentFromFile("/etc/docker/daemon.json") log.Info("修改daemon config 成功, docker重启成功!") utils.BeautifulPrintListWithTitle(daemonJsonContent, "docker daemon.json") fmt.Println("") fmt.Println("") }, } cmd.AddCommand(onlineCmd, removeCmd, localCmd, configCmd) } 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 host_info.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 := utils.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{"/usr/local/bin/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...") if utils.RemoveFile("/usr/local/bin/docker-compose") { log.Info("Docker Compose removed successfully!") } else { log.Error("Failed to remove Docker Compose!") } }, } localCmd := &cobra.Command{ Use: "local", Short: "本地安装DockerCompose 安装文件应该为 " + dockerComposeLocalInstallPath, Run: func(cmd *cobra.Command, args []string) { log.Info("Installing Docker Compose from local file...") exist := utils.FileExistAndNotNull(dockerComposeLocalInstallPath) if !exist { log.Error("Docker local install file not found: %s", dockerComposeLocalInstallPath) return } // move file to /usr/local/bin err := utils.MoveFileToAnother(dockerComposeLocalInstallPath, "/usr/local/bin/docker-compose") if err != nil { log.Error("Failed to move Docker Compose binaries: %s", err.Error()) return } // set permission chmodCmd := []string{"chmod", "+x", "/usr/local/bin/docker-compose"} ok, resultLog := op.SingleLineCommandExecutor(chmodCmd) if !ok { log.Error("Failed to set permissions for Docker Compose binaries: %s", resultLog) return } // 创建软链接 linkCmd := []string{"ln", "-sf", "/usr/local/bin/docker-compose", "/usr/bin/docker-compose"} op.SingleLineCommandExecutor(linkCmd) // 验证安装 verifyCmd := []string{"/usr/local/bin/docker-compose", "version"} ok, resultLog = op.SingleLineCommandExecutor(verifyCmd) if !ok { log.Error("Docker Compose 安装验证失败: %s", resultLog) return } log.Info("Docker Compose installed successfully from local file!") }, } versionCmd := &cobra.Command{ Use: "version", Short: "查看Docker Compose版本", Run: func(cmd *cobra.Command, args []string) { log.Info("Docker Compose version...") ok, resultLog := op.SingleLineCommandExecutor([]string{"docker-compose", "--version"}) if !ok { log.Error("Failed to get Docker Compose version: %s", resultLog) return } log.Info("Docker Compose version: %s", resultLog) }, } cmd.AddCommand( installCmd, removeCmd, localCmd, versionCmd, ) }