Files
ProjectOctopus/agent-wdd/cmd/Base.go
zeaslity 5c2325b7e4 优化Docker和SSH命令,增强系统配置和安装流程
- 更新Docker安装命令,默认版本升级到20.10.24
- 新增Docker配置命令,支持主节点配置daemon.json
- 修改SSH相关命令,增加输出换行以提高可读性
- 优化Zsh插件安装,使用完整git路径
- 改进系统配置中的主机名生成逻辑,增加内网IP最后一段标识
- 完善操作系统类型检测,扩展Ubuntu类型系统识别
- 调整包管理操作中的输出格式
2025-03-05 16:47:14 +08:00

826 lines
23 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"agent-wdd/cmd/beans"
"agent-wdd/config"
"agent-wdd/log"
"agent-wdd/op"
"agent-wdd/utils"
"fmt"
"runtime"
"strings"
"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的文件路径
)
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的文件路径
case "arm64":
dockerLocalInstallPath = "/root/wdd/docker-arm64-20.10.15.tgz" // 本地安装docker的文件路径
dockerComposeLocalInstallPath = "/root/wdd/docker-compose-v2.18.0-linux-arm64" // 本地安装docker compose的文件路径
}
}
// 添加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 config.ConfigCache.Agent.OS.Hostname == "" {
log.Warning("ConfigCache OS is nil")
config.ConfigCache.Agent.OS.Gather()
config.ConfigCache.Agent.OS.SaveConfig()
}
os := config.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("清空路由表...")
op.HardCodeCommandExecutor("iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -t raw -F")
op.HardCodeCommandExecutor("ip6tables -F && ip6tables -t nat -F && ip6tables -t mangle -F && ip6tables -t raw -F")
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: "通用工具安装 利用本机的yumapt等从网络安装常用的软件",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Common tool installation!")
// Whether It can connect to internet
if config.CanConnectInternet() <= 1 {
log.Error("服务器无法连接互联网无法执行tools")
return
}
// package install
// only support ubuntu(debian) centos(debian openEuler)
packOperator := op.AgentPackOperator
packOperator.PackageInit()
os := config.ConfigCache.Agent.OS
if os.IsUbuntuType {
packOperator.Install(ubuntuCommonTools)
} else {
packOperator.Install(centosCommonTools)
}
},
}
sshCmd := &cobra.Command{
Use: "ssh",
Short: "修改ssh配置",
}
addSSHSubcommands(sshCmd)
cmd.AddCommand(
dockerCmd,
dockerComposeCmd,
swapCmd,
commonToolsInstall,
selinuxCmd,
firewallCmd,
sysconfigCmd,
sshCmd,
// 其他命令...
)
}
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 := config.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.HardCodeCommandExecutor("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")
// 安装docker
err := utils.MoveFolerToAnother("/root/wdd/docker", "/usr/bin")
if err != nil {
log.Error("Failed to move Docker binaries: %s", err.Error())
return
}
// 设置权限
dockerBinList := []string{
"docker-init",
"containerd",
"ctr",
"runc",
"dockerd",
"docker-proxy",
"containerd-shim",
"docker",
"containerd-shim-runc-v2",
}
for _, bin := range dockerBinList {
ok, resultLog := op.HardCodeCommandExecutor("chmod 777 /usr/bin/" + bin)
if !ok {
log.Error("Failed to set permissions for Docker binaries: %s", resultLog)
return
}
}
// 配置并启动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 := config.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 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 := 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{"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 [path]",
Short: "本地安装DockerCompose 安装文件应该为 " + dockerComposeLocalInstallPath,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
log.Info("Installing Docker Compose from local file...")
exist := utils.FileExistAndNotNull(dockerLocalInstallPath)
if !exist {
log.Error("Docker local install file not found: %s", dockerLocalInstallPath)
return
}
// move file to /usr/local/bin
err := utils.MoveFolerToAnother(dockerComposeLocalInstallPath, "/usr/local/bin")
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
}
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,
)
}