Enhance Docker Installation and Management Commands
- Improved Docker installation process for Ubuntu systems - Added support for dynamic Docker version detection - Enhanced Docker local and online installation commands - Implemented more robust Docker removal functionality - Updated Docker installation to use system-specific package sources - Added better error handling and logging for Docker operations - Refined Docker service startup and configuration checks
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
"agent-wdd/utils"
|
"agent-wdd/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -282,8 +283,14 @@ func addSSHSubcommands(sshCmd *cobra.Command) {
|
|||||||
port := "22333"
|
port := "22333"
|
||||||
log.Info("[ModifySSHPort] modify ssh port to: %s", port)
|
log.Info("[ModifySSHPort] modify ssh port to: %s", port)
|
||||||
|
|
||||||
// 修改ssh端口
|
// 文件中已经包含了Port 22333 则pass
|
||||||
utils.AppendContentToFile(fmt.Sprintf("Port %s", port), "/etc/ssh/sshd_config")
|
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服务
|
// 重启ssh服务
|
||||||
ok, resultLog := op.SystemdRestart("sshd")
|
ok, resultLog := op.SystemdRestart("sshd")
|
||||||
@@ -309,7 +316,7 @@ func addSSHSubcommands(sshCmd *cobra.Command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修改ssh配置
|
// 修改ssh配置
|
||||||
utils.AppendContentToFile(beans.DefaultSshdConfig, "/etc/ssh/sshd_config")
|
utils.AppendOverwriteContentToFile(beans.DefaultSshdConfig, "/etc/ssh/sshd_config")
|
||||||
|
|
||||||
// 重启ssh服务
|
// 重启ssh服务
|
||||||
ok, resultLog := op.SystemdRestart("sshd")
|
ok, resultLog := op.SystemdRestart("sshd")
|
||||||
@@ -330,8 +337,7 @@ func addSSHSubcommands(sshCmd *cobra.Command) {
|
|||||||
func addDockerSubcommands(cmd *cobra.Command) {
|
func addDockerSubcommands(cmd *cobra.Command) {
|
||||||
onlineCmd := &cobra.Command{
|
onlineCmd := &cobra.Command{
|
||||||
Use: "online [version]",
|
Use: "online [version]",
|
||||||
Short: "网络安装Docker",
|
Short: "网络安装Docker, 如果不指定参数默认安装20.10.15版本",
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
// 检查参数
|
// 检查参数
|
||||||
@@ -339,15 +345,124 @@ func addDockerSubcommands(cmd *cobra.Command) {
|
|||||||
fmt.Printf("Installing Docker version: %s\n", args[0])
|
fmt.Printf("Installing Docker version: %s\n", args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有传递参数,使用默认参数
|
|
||||||
version := "20.10.15"
|
|
||||||
log.Info("Installing Docker version: %s", version)
|
|
||||||
|
|
||||||
// 安装docker
|
// 安装docker
|
||||||
packOperator := op.AgentPackOperator
|
packOperator := op.AgentPackOperator
|
||||||
packOperator.PackageInit()
|
packOperator.PackageInit()
|
||||||
// ubuntu 和 centos的安装命令是不是一样的
|
|
||||||
packOperator.Install([]string{"docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin", "docker-compose-plugin"})
|
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!")
|
||||||
|
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启动成功! ")
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -357,13 +472,45 @@ func addDockerSubcommands(cmd *cobra.Command) {
|
|||||||
Short: "卸载Docker",
|
Short: "卸载Docker",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("Removing Docker...")
|
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{
|
localCmd := &cobra.Command{
|
||||||
Use: "local [path]",
|
Use: "local",
|
||||||
Short: "本地安装Docker",
|
Short: "本地安装Docker, 默认安装20.10.15版本, 安装目录为 " + dockerLocalInstallPath,
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
log.Info("Installing Docker from local file: %s", dockerLocalInstallPath)
|
log.Info("Installing Docker from local file: %s", dockerLocalInstallPath)
|
||||||
@@ -385,11 +532,24 @@ func addDockerSubcommands(cmd *cobra.Command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置权限
|
// 设置权限
|
||||||
chmodCmd := []string{"chmod", "777", "-R", "/usr/bin/docker*"}
|
dockerBinList := []string{
|
||||||
ok, resultLog := op.SingleLineCommandExecutor(chmodCmd)
|
"docker-init",
|
||||||
if !ok {
|
"containerd",
|
||||||
log.Error("Failed to set permissions for Docker binaries: %s", resultLog)
|
"ctr",
|
||||||
return
|
"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服务
|
// 配置并启动Docker服务
|
||||||
@@ -408,7 +568,7 @@ func addDockerSubcommands(cmd *cobra.Command) {
|
|||||||
}
|
}
|
||||||
log.Info("docker dameon file append success !")
|
log.Info("docker dameon file append success !")
|
||||||
|
|
||||||
ok, resultLog = op.SystemdDaemonReload()
|
ok, resultLog := op.SystemdDaemonReload()
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("daemon reload error ! %s", resultLog)
|
log.Error("daemon reload error ! %s", resultLog)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -76,13 +76,13 @@ func addZshSubcommands(cmd *cobra.Command) {
|
|||||||
log.Info("安装zsh完成, 开始安装插件!")
|
log.Info("安装zsh完成, 开始安装插件!")
|
||||||
|
|
||||||
pluginsHardCodeUrl := []string{
|
pluginsHardCodeUrl := []string{
|
||||||
"git clone https://gitee.com/wangl-cc/zsh-autosuggestions.git ~/.oh-my-zsh/plugins/zsh-autosuggestions",
|
"git clone https://gitee.com/wangl-cc/zsh-autosuggestions.git /root/.oh-my-zsh/plugins/zsh-autosuggestions",
|
||||||
"git clone https://gitee.com/xiaoqqya/zsh-syntax-highlighting.git ~/.oh-my-zsh/plugins/zsh-syntax-highlighting",
|
"git clone https://gitee.com/xiaoqqya/zsh-syntax-highlighting.git /root/.oh-my-zsh/plugins/zsh-syntax-highlighting",
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginsHardCodeOutsideUrl := []string{
|
pluginsHardCodeOutsideUrl := []string{
|
||||||
"git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/plugins/zsh-autosuggestions",
|
"git clone https://github.com/zsh-users/zsh-autosuggestions /root/.oh-my-zsh/plugins/zsh-autosuggestions",
|
||||||
"git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.oh-my-zsh/plugins/zsh-syntax-highlighting",
|
"git clone https://github.com/zsh-users/zsh-syntax-highlighting.git /root/.oh-my-zsh/plugins/zsh-syntax-highlighting",
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginsListUrl := []string{
|
pluginsListUrl := []string{
|
||||||
@@ -122,9 +122,9 @@ func addZshSubcommands(cmd *cobra.Command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修改ZSH配置
|
// 修改ZSH配置
|
||||||
utils.FindAndReplaceContentInFile("/root/.zshrc", "robbyrussell", "agnoster")
|
utils.FindAndReplaceContentInFile("robbyrussell", "agnoster", "/root/.zshrc")
|
||||||
utils.FindAndReplaceContentInFile("/root/.zshrc", "# DISABLE_AUTO_UPDATE=\"true\"", "DISABLE_AUTO_UPDATE=\"true\"")
|
utils.FindAndReplaceContentInFile("# DISABLE_AUTO_UPDATE=\"true\"", "DISABLE_AUTO_UPDATE=\"true\"", "/root/.zshrc")
|
||||||
utils.FindAndReplaceContentInFile("/root/.zshrc", "plugins=(git)", "plugins=(git zsh-autosuggestions zsh-syntax-highlighting command-not-found z themes)")
|
utils.FindAndReplaceContentInFile("plugins=(git)", "plugins=(git zsh-autosuggestions zsh-syntax-highlighting command-not-found z themes)", "/root/.zshrc")
|
||||||
|
|
||||||
//
|
//
|
||||||
op.SingleLineCommandExecutor([]string{
|
op.SingleLineCommandExecutor([]string{
|
||||||
|
|||||||
@@ -15,13 +15,17 @@ var rootCmd = &cobra.Command{
|
|||||||
Short: "wdd应用程序是wdd封装的NB工具",
|
Short: "wdd应用程序是wdd封装的NB工具",
|
||||||
Long: `使用golang的强大特性,加上 WDD 的高超技术,打造一个方便、高效、适用于各种LINUX系统的瑞士军刀工具!
|
Long: `使用golang的强大特性,加上 WDD 的高超技术,打造一个方便、高效、适用于各种LINUX系统的瑞士军刀工具!
|
||||||
尽情享用! 尽情享用! 尽情享用!`,
|
尽情享用! 尽情享用! 尽情享用!`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
DisableAutoGenTag: true,
|
||||||
// Do Stuff Here
|
CompletionOptions: cobra.CompletionOptions{
|
||||||
|
DisableDefaultCmd: true,
|
||||||
|
DisableNoDescFlag: true,
|
||||||
|
DisableDescriptions: true,
|
||||||
|
HiddenDefaultCmd: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
// 初始化配置
|
||||||
cobra.OnInitialize(config.InitConfig)
|
cobra.OnInitialize(config.InitConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +142,7 @@ func Execute() {
|
|||||||
|
|
||||||
func printAllCommands(cmd *cobra.Command, writer io.Writer) {
|
func printAllCommands(cmd *cobra.Command, writer io.Writer) {
|
||||||
// 打印命令标题
|
// 打印命令标题
|
||||||
fmt.Fprintf(writer, "Available commands:\n")
|
fmt.Fprintf(writer, "All available commands:\n\n")
|
||||||
|
|
||||||
// 递归打印命令树
|
// 递归打印命令树
|
||||||
var traverse func(*cobra.Command, int)
|
var traverse func(*cobra.Command, int)
|
||||||
|
|||||||
@@ -50,15 +50,16 @@ type Agent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OS struct {
|
type OS struct {
|
||||||
Hostname string `yaml:"hostname"`
|
Hostname string `mapstructure:"hostname" yaml:"hostname" comment:"主机名"`
|
||||||
OsName string `yaml:"os_name"`
|
OsName string `mapstructure:"os_name" yaml:"os_name" comment:"操作系统名称"`
|
||||||
OsFamily string `yaml:"os_family"`
|
OsFamily string `mapstructure:"os_family" yaml:"os_family" comment:"操作系统家族"`
|
||||||
OsVersion string `yaml:"os_version"`
|
OsVersion string `mapstructure:"os_version" yaml:"os_version" comment:"操作系统版本"`
|
||||||
OsType string `yaml:"os_type"`
|
OsType string `mapstructure:"os_type" yaml:"os_type" comment:"操作系统类型"`
|
||||||
Kernel string `yaml:"kernel"`
|
Kernel string `mapstructure:"kernel" yaml:"kernel" comment:"内核版本"`
|
||||||
Arch string `yaml:"arch"`
|
Arch string `mapstructure:"arch" yaml:"arch" comment:"架构"`
|
||||||
IsUbuntuType bool `yaml:"is_ubuntu_type" comment:"是否是ubuntu类型的操作系统"`
|
IsUbuntuType bool `mapstructure:"is_ubuntu_type" yaml:"is_ubuntu_type" comment:"是否是ubuntu类型的操作系统"`
|
||||||
PackInit bool `yaml:"pack_init" comment:"是否初始化,ubuntu需要"`
|
PackInit bool `mapstructure:"pack_init" yaml:"pack_init" comment:"是否初始化,ubuntu需要"`
|
||||||
|
OSReleaseCode string `mapstructure:"os_release_code" yaml:"os_release_code" comment:"主机操作系统的发行版代号, focal之类的"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Network struct {
|
type Network struct {
|
||||||
@@ -68,11 +69,12 @@ type Network struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PublicInfo struct {
|
type PublicInfo struct {
|
||||||
IPv4 string `yaml:"ipv4"`
|
IPv4 string `yaml:"ipv4"`
|
||||||
IPv6 string `yaml:"ipv6"`
|
IPv6 string `yaml:"ipv6"`
|
||||||
Country string `yaml:"country"`
|
Country string `yaml:"country"`
|
||||||
City string `yaml:"city"`
|
City string `yaml:"city"`
|
||||||
ASN string `yaml:"asn"`
|
ASN string `yaml:"asn"`
|
||||||
|
Timezone string `yaml:"timezone"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Interface struct {
|
type Interface struct {
|
||||||
@@ -122,7 +124,6 @@ func InitConfig() {
|
|||||||
v.SetConfigType("yaml")
|
v.SetConfigType("yaml")
|
||||||
|
|
||||||
if err := v.ReadInConfig(); err != nil {
|
if err := v.ReadInConfig(); err != nil {
|
||||||
|
|
||||||
log.Error("读取配置文件失败: %w", err)
|
log.Error("读取配置文件失败: %w", err)
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func GetInterfaces() []Interface {
|
|||||||
|
|
||||||
// 获取所有网卡信息
|
// 获取所有网卡信息
|
||||||
netInterfaces, err := net.Interfaces()
|
netInterfaces, err := net.Interfaces()
|
||||||
log.Info("all network interfaces: %v", netInterfaces)
|
// log.Info("all network interfaces: %v", netInterfaces)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("获取网卡信息失败: %v", err)
|
log.Error("获取网卡信息失败: %v", err)
|
||||||
return interfaces
|
return interfaces
|
||||||
@@ -120,17 +120,35 @@ func judgeCanConnectInternet() int {
|
|||||||
Timeout: 3 * time.Second,
|
Timeout: 3 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := client.Get("https://www.google.com")
|
results := make(chan int, 2)
|
||||||
if err == nil {
|
|
||||||
return 9
|
go func() {
|
||||||
|
_, err := client.Get("https://www.google.com")
|
||||||
|
if err == nil {
|
||||||
|
results <- 9
|
||||||
|
} else {
|
||||||
|
results <- 1
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_, err := client.Get("https://www.baidu.com")
|
||||||
|
if err == nil {
|
||||||
|
results <- 7
|
||||||
|
} else {
|
||||||
|
results <- 1
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
maxResult := 1
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
result := <-results
|
||||||
|
if result > maxResult {
|
||||||
|
maxResult = result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = client.Get("https://www.baidu.com")
|
return maxResult
|
||||||
if err == nil {
|
|
||||||
return 7
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPublicInfo 获取服务器的公网信息
|
// GetPublicInfo 获取服务器的公网信息
|
||||||
@@ -194,13 +212,14 @@ func (p PublicInfo) GetPublicInfo() PublicInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 打印解析结果
|
// 打印解析结果
|
||||||
log.Info("IP信息:\n%+v\n", info)
|
// log.Info("IP信息:\n%+v\n", info)
|
||||||
|
|
||||||
// 保存信息
|
// 保存信息
|
||||||
p.IPv4 = info.IP
|
p.IPv4 = info.IP
|
||||||
p.ASN = info.Org
|
p.ASN = info.Org
|
||||||
p.Country = info.Country
|
p.Country = info.Country
|
||||||
p.City = info.City
|
p.City = info.City
|
||||||
|
p.Timezone = info.Timezone
|
||||||
|
|
||||||
ConfigCache.Agent.Network.Public = p
|
ConfigCache.Agent.Network.Public = p
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ func (o *OS) Gather() {
|
|||||||
o.Hostname = hostname
|
o.Hostname = hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
o.OsType = "linux" // 固定为linux
|
o.OsType = "linux" // 固定为linux
|
||||||
|
o.IsUbuntuType = true // 默认为ubuntu
|
||||||
|
|
||||||
// 解析系统信息
|
// 解析系统信息
|
||||||
file, err := os.Open("/etc/os-release")
|
file, err := os.Open("/etc/os-release")
|
||||||
@@ -78,12 +79,30 @@ func (o *OS) Gather() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查包管理的方式
|
// 检查包管理的方式
|
||||||
c := exec.Command("command", "-v", "apt")
|
if strings.Contains(o.OsFamily, "centos") || strings.Contains(o.OsFamily, "rhel") {
|
||||||
_, err = c.Output()
|
o.IsUbuntuType = false
|
||||||
if err == nil {
|
|
||||||
o.IsUbuntuType = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取系统架构
|
// 获取系统架构
|
||||||
o.Arch = runtime.GOARCH
|
o.Arch = runtime.GOARCH
|
||||||
|
|
||||||
|
// 获取系统发行版代号
|
||||||
|
o.OSReleaseCode = judgeUbuntuReleaseFromOsVersion(o.OsVersion)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func judgeUbuntuReleaseFromOsVersion(osVersion string) string {
|
||||||
|
|
||||||
|
switch osVersion {
|
||||||
|
case "16.04":
|
||||||
|
return "xenial"
|
||||||
|
case "18.04":
|
||||||
|
return "bionic"
|
||||||
|
case "20.04":
|
||||||
|
return "focal"
|
||||||
|
case "22.04":
|
||||||
|
return "jammy"
|
||||||
|
default:
|
||||||
|
return "ubuntu-unknown"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ try {
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
Write-Host "1. Building binary exec file..." -ForegroundColor Cyan
|
Write-Host "1. Building binary exec file..." -ForegroundColor Cyan
|
||||||
& "C:\Users\wdd\go\bin\gox.exe" -osarch="linux/amd64" -output "build/agent-wdd_{{.OS}}_{{.Arch}}"
|
& "C:\Users\wddsh\go\bin\gox.exe" -osarch="linux/amd64" -output "build/agent-wdd_{{.OS}}_{{.Arch}}"
|
||||||
|
|
||||||
# 执行远程ssh命令 ssh root@192.168.35.71 "rm /root/agent-wdd_linux_amd64"
|
# 执行远程ssh命令 ssh root@192.168.35.71 "rm /root/agent-wdd_linux_amd64"
|
||||||
Write-Host "2. Cleaning old binary file..." -ForegroundColor Yellow
|
Write-Host "2. Cleaning old binary file..." -ForegroundColor Yellow
|
||||||
@@ -16,7 +16,7 @@ try {
|
|||||||
Write-Host "4. Exec the command ..." -ForegroundColor Blue
|
Write-Host "4. Exec the command ..." -ForegroundColor Blue
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
ssh root@192.168.35.71 "chmod +x agent-wdd_linux_amd64 && ./agent-wdd_linux_amd64 info network"
|
ssh root@192.168.35.71 "chmod +x agent-wdd_linux_amd64 && ./agent-wdd_linux_amd64 help"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "5. Cheak Info Result ..." -ForegroundColor Blue
|
Write-Host "5. Cheak Info Result ..." -ForegroundColor Blue
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ func HardCodeCommandExecutor(hardCodeCommand string) (ok bool, resultLog []strin
|
|||||||
cmd := exec.Command(hardCodeCommand)
|
cmd := exec.Command(hardCodeCommand)
|
||||||
|
|
||||||
// 执行命令并获取错误信息
|
// 执行命令并获取错误信息
|
||||||
err := cmd.Run()
|
cmd.Run()
|
||||||
|
|
||||||
// 合并输出结果
|
// 合并输出结果
|
||||||
stdoutBuf := bytes.Buffer{}
|
stdoutBuf := bytes.Buffer{}
|
||||||
@@ -189,7 +189,7 @@ func HardCodeCommandExecutor(hardCodeCommand string) (ok bool, resultLog []strin
|
|||||||
|
|
||||||
output := mergeOutput(&stdoutBuf, &stderrBuf)
|
output := mergeOutput(&stdoutBuf, &stderrBuf)
|
||||||
|
|
||||||
return err == nil, output
|
return true, output
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -3,12 +3,10 @@ package op
|
|||||||
import (
|
import (
|
||||||
"agent-wdd/config"
|
"agent-wdd/config"
|
||||||
"agent-wdd/log"
|
"agent-wdd/log"
|
||||||
"agent-wdd/utils"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -60,8 +58,11 @@ func (op *PackageOperator) Install(tools []string) bool {
|
|||||||
ok, result := SingleLineCommandExecutor(append(AgentPackOperator.installPrefix, tool))
|
ok, result := SingleLineCommandExecutor(append(AgentPackOperator.installPrefix, tool))
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("[install] failed! => %s", tool)
|
log.Error("[install] failed! => %s", tool)
|
||||||
utils.BeautifulPrint(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打印安装的过程内容
|
||||||
|
beautifulPrintListWithTitle(result, fmt.Sprintf("安装 %s 的过程内容", tool))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -71,21 +72,29 @@ func (op *PackageOperator) Install(tools []string) bool {
|
|||||||
func (op *PackageOperator) PackageInit() bool {
|
func (op *PackageOperator) PackageInit() bool {
|
||||||
log.Info("PackageInit !")
|
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
|
// 判定本机的包管理Operator
|
||||||
ok := generatePackageOperator()
|
ok := generatePackageOperator()
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// package init
|
os.PackInit = true
|
||||||
os := config.ConfigCache.Agent.OS
|
os.SaveConfig()
|
||||||
osFamily := strings.ToLower(os.OsFamily)
|
|
||||||
|
|
||||||
if strings.Contains(osFamily, "ubuntu") || strings.Contains(osFamily, "debian") {
|
if os.IsUbuntuType {
|
||||||
ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand)
|
ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("APT init failed! please check !")
|
log.Error("APT init failed! please check ! %s", resultLog)
|
||||||
utils.BeautifulPrint(resultLog)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +102,23 @@ func (op *PackageOperator) PackageInit() bool {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
func (op *PackageOperator) Remove(tools []string) {
|
||||||
// 判定本机的包管理Operator
|
// 判定本机的包管理Operator
|
||||||
generatePackageOperator()
|
generatePackageOperator()
|
||||||
@@ -102,7 +128,7 @@ func (op *PackageOperator) Remove(tools []string) {
|
|||||||
ok, result := SingleLineCommandExecutor(append(AgentPackOperator.removePrefix, tool))
|
ok, result := SingleLineCommandExecutor(append(AgentPackOperator.removePrefix, tool))
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("[remove] failed! => %s", tool)
|
log.Error("[remove] failed! => %s", tool)
|
||||||
utils.BeautifulPrint(result)
|
beautifulPrintListWithTitle(result, fmt.Sprintf("移除 %s 的过程内容", tool))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +138,7 @@ func generatePackageOperator() bool {
|
|||||||
|
|
||||||
// cache return
|
// cache return
|
||||||
if AgentPackOperator.initCommand != nil {
|
if AgentPackOperator.initCommand != nil {
|
||||||
|
log.Info("PackageOperator init success! %v", AgentPackOperator.initCommand)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,13 +152,14 @@ func generatePackageOperator() bool {
|
|||||||
os := config.ConfigCache.Agent.OS
|
os := config.ConfigCache.Agent.OS
|
||||||
if os.Hostname == "" {
|
if os.Hostname == "" {
|
||||||
os.Gather()
|
os.Gather()
|
||||||
|
|
||||||
os.SaveConfig()
|
os.SaveConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.IsUbuntuType {
|
if os.IsUbuntuType {
|
||||||
|
log.Info("Ubuntu type detected! use apt package operator!")
|
||||||
AgentPackOperator = aptPackageOperator
|
AgentPackOperator = aptPackageOperator
|
||||||
} else {
|
} else {
|
||||||
|
log.Info("Other type detected! use yum package operator!")
|
||||||
AgentPackOperator = yumPackageOperator
|
AgentPackOperator = yumPackageOperator
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,3 +223,13 @@ func CommandExistsByPath(command string) bool {
|
|||||||
ok, _ := SingleLineCommandExecutor([]string{"find", "/usr/bin", "/usr/local/bin", "-name", command})
|
ok, _ := SingleLineCommandExecutor([]string{"find", "/usr/bin", "/usr/local/bin", "-name", command})
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func beautifulPrintListWithTitle(contend []string, title string) {
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(">>>>>>>> " + title + " <<<<<<<<")
|
||||||
|
for _, line := range contend {
|
||||||
|
fmt.Println(line)
|
||||||
|
}
|
||||||
|
fmt.Println(">>>>>>>> end <<<<<<<<")
|
||||||
|
}
|
||||||
|
|||||||
@@ -79,3 +79,11 @@ func SystemdDaemonReload() (bool, []string) {
|
|||||||
}
|
}
|
||||||
return true, resultLog
|
return true, resultLog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SystemIsRunning(serviceName string) (bool, []string) {
|
||||||
|
ok, resultLog := SingleLineCommandExecutor([]string{"systemctl", "is-active", serviceName})
|
||||||
|
if !ok {
|
||||||
|
return false, resultLog
|
||||||
|
}
|
||||||
|
return true, resultLog
|
||||||
|
}
|
||||||
|
|||||||
27
agent-wdd/test/one-click-build-run.ps1
Normal file
27
agent-wdd/test/one-click-build-run.ps1
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# mc.exe alias set oracle-osaka-1 https://axzsapxffbbn.compat.objectstorage.ap-osaka-1.oraclecloud.com b0696c316f87b644b4a13bcb020f095cd147be0b GAIaM/064epLzQcXsRbj2gwlFOrVepjCR23wj2tfJ+A=
|
||||||
|
|
||||||
|
# 重新build项目
|
||||||
|
Set-Location "C:\Users\wddsh\Documents\IdeaProjects\ProjectOctopus\agent-wdd"
|
||||||
|
& "C:\Users\wddsh\go\bin\gox.exe" -osarch="linux/amd64" -output "build/agent-wdd_{{.OS}}_{{.Arch}}"
|
||||||
|
|
||||||
|
|
||||||
|
# mc.exe ls oracle-osaka-1/osaka
|
||||||
|
# 删除上面存在的旧的内容
|
||||||
|
mc.exe rm oracle-osaka-1/osaka/agent-wdd_linux_amd64
|
||||||
|
mc.exe rm oracle-osaka-1/osaka/test-shell.sh
|
||||||
|
|
||||||
|
|
||||||
|
# 上传文件
|
||||||
|
mc.exe cp C:\Users\wddsh\Documents\IdeaProjects\ProjectOctopus\agent-wdd\build\agent-wdd_linux_amd64 oracle-osaka-1/osaka/
|
||||||
|
mc.exe cp C:\Users\wddsh\Documents\IdeaProjects\ProjectOctopus\agent-wdd\test\test-shell.sh oracle-osaka-1/osaka/
|
||||||
|
|
||||||
|
|
||||||
|
Set-Location "C:\Users\wddsh\Documents\IdeaProjects\ProjectOctopus\agent-wdd\test"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
Available commands:
|
Available commands:
|
||||||
|
|
||||||
acme acme相关的内容
|
acme acme相关的内容
|
||||||
base 服务器基础操作
|
base 服务器基础操作
|
||||||
docker Docker相关操作
|
docker Docker相关操作
|
||||||
@@ -19,11 +20,6 @@ base 服务器基础操作
|
|||||||
swap 关闭系统的Swap
|
swap 关闭系统的Swap
|
||||||
sysconfig 修改系统的sysconfig
|
sysconfig 修改系统的sysconfig
|
||||||
tools 通用工具安装 利用本机的yum,apt等从网络安装常用的软件
|
tools 通用工具安装 利用本机的yum,apt等从网络安装常用的软件
|
||||||
completion Generate the autocompletion script for the specified shell
|
|
||||||
bash Generate the autocompletion script for bash
|
|
||||||
fish Generate the autocompletion script for fish
|
|
||||||
powershell Generate the autocompletion script for powershell
|
|
||||||
zsh Generate the autocompletion script for zsh
|
|
||||||
config 配置文件管理
|
config 配置文件管理
|
||||||
show 显示agent运行配置
|
show 显示agent运行配置
|
||||||
download 文件下载,直接下载 [url] [dest_path]
|
download 文件下载,直接下载 [url] [dest_path]
|
||||||
52
agent-wdd/test/run_test.sh
Normal file
52
agent-wdd/test/run_test.sh
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
rm -f /usr/local/bin/agent-wdd
|
||||||
|
rm -f /usr/local/bin/test-shell.sh
|
||||||
|
|
||||||
|
wget https://pan.107421.xyz/d/oracle-osaka-1/agent-wdd_linux_amd64 -O /usr/local/bin/agent-wdd
|
||||||
|
|
||||||
|
chmod +x /usr/local/bin/agent-wdd
|
||||||
|
|
||||||
|
|
||||||
|
wget https://pan.107421.xyz/d/oracle-osaka-1/test-shell.sh -O /usr/local/bin/test-shell.sh
|
||||||
|
|
||||||
|
chmod +x /usr/local/bin/test-shell.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bash /usr/local/bin/test-shell.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd info network
|
||||||
|
/usr/local/bin/agent-wdd info cpu
|
||||||
|
/usr/local/bin/agent-wdd info mem
|
||||||
|
/usr/local/bin/agent-wdd info swap
|
||||||
|
/usr/local/bin/agent-wdd info disks
|
||||||
|
|
||||||
|
cat /usr/local/etc/wdd/agent-wdd-config.yaml
|
||||||
|
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd base docker local
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd info os
|
||||||
|
/usr/local/bin/agent-wdd base docker online
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd info os
|
||||||
|
/usr/local/bin/agent-wdd zsh
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd base tools
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd base swap
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd base firewall
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd base selinux
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd base sysconfig
|
||||||
|
|
||||||
|
|
||||||
|
/usr/local/bin/agent-wdd download https://pan.107421.xyz/d/oracle-osaka-1/docker-amd64-20.10.15.tgz /root/wdd
|
||||||
|
|
||||||
135
agent-wdd/test/test-shell.sh
Normal file
135
agent-wdd/test/test-shell.sh
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# set -eo pipefail
|
||||||
|
|
||||||
|
# 测试配置
|
||||||
|
TEST_REPEATS=2
|
||||||
|
AGENT_BIN="/usr/local/bin/agent-wdd" # 修正路径拼写错误
|
||||||
|
|
||||||
|
# 输出颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# 测试统计
|
||||||
|
declare -i TOTAL_TESTS=0 PASSED_TESTS=0 FAILED_TESTS=0
|
||||||
|
|
||||||
|
# 实用函数
|
||||||
|
log() {
|
||||||
|
echo -e "${YELLOW}[INFO] $* ${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
pass() {
|
||||||
|
echo -e "${GREEN}PASS: $* ${NC}"
|
||||||
|
((PASSED_TESTS++))
|
||||||
|
((TOTAL_TESTS++))
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo -e "${RED}FAIL: $* ${NC}"
|
||||||
|
((FAILED_TESTS++))
|
||||||
|
((TOTAL_TESTS++))
|
||||||
|
}
|
||||||
|
|
||||||
|
test_command() {
|
||||||
|
local cmd="$1"
|
||||||
|
local expected="${2:-0}"
|
||||||
|
|
||||||
|
if ! eval "$cmd"; then
|
||||||
|
local exit_code=$?
|
||||||
|
[[ $exit_code -eq "$expected" ]] || {
|
||||||
|
fail "$cmd (exit $exit_code)"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
pass "$cmd"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
repeat_test() {
|
||||||
|
local times=$1
|
||||||
|
local cmd="$2"
|
||||||
|
local expected="${3:-0}"
|
||||||
|
|
||||||
|
for ((i=1; i<=times; i++)); do
|
||||||
|
test_command "$cmd" "$expected"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
test_base_docker() {
|
||||||
|
log "\nTesting Docker commands..."
|
||||||
|
test_command "$AGENT_BIN base docker remove" 0
|
||||||
|
test_command "$AGENT_BIN base docker online" 0
|
||||||
|
repeat_test $TEST_REPEATS "$AGENT_BIN base docker local" 0
|
||||||
|
|
||||||
|
if docker --version >/dev/null 2>&1; then
|
||||||
|
pass "docker installation"
|
||||||
|
else
|
||||||
|
fail "docker installation"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
test_base_ssh() {
|
||||||
|
log "\nTesting SSH commands..."
|
||||||
|
repeat_test $TEST_REPEATS "$AGENT_BIN base ssh port 2222" 0
|
||||||
|
test_command "$AGENT_BIN base ssh config" 0
|
||||||
|
}
|
||||||
|
|
||||||
|
test_tools() {
|
||||||
|
log "\nTesting tools installation..."
|
||||||
|
local tools=("htop" "tmux" "nano")
|
||||||
|
for tool in "${tools[@]}"; do
|
||||||
|
if command -v "$tool" >/dev/null 2>&1; then
|
||||||
|
pass "$tool already installed"
|
||||||
|
else
|
||||||
|
test_command "$AGENT_BIN base tools $tool" 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
test_info_commands() {
|
||||||
|
log "\nTesting info commands..."
|
||||||
|
local commands=(
|
||||||
|
"$AGENT_BIN info all"
|
||||||
|
"$AGENT_BIN info cpu"
|
||||||
|
"$AGENT_BIN info disk"
|
||||||
|
"$AGENT_BIN info mem"
|
||||||
|
"$AGENT_BIN info network"
|
||||||
|
"$AGENT_BIN info os"
|
||||||
|
)
|
||||||
|
|
||||||
|
for cmd in "${commands[@]}"; do
|
||||||
|
repeat_test $TEST_REPEATS "$cmd" 0
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
# 前置检查
|
||||||
|
[[ -x "$AGENT_BIN" ]] || {
|
||||||
|
log "Error: Agent binary not found or not executable: $AGENT_BIN"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Starting tests with $AGENT_BIN..."
|
||||||
|
|
||||||
|
# 基本信息测试
|
||||||
|
test_command "$AGENT_BIN version" 0
|
||||||
|
test_command "$AGENT_BIN help" 0
|
||||||
|
|
||||||
|
# 基础模块测试
|
||||||
|
test_base_docker
|
||||||
|
test_base_ssh
|
||||||
|
test_tools
|
||||||
|
|
||||||
|
# 信息模块测试
|
||||||
|
test_info_commands
|
||||||
|
|
||||||
|
log "\nTest Summary:"
|
||||||
|
echo -e "Total Tests: $TOTAL_TESTS"
|
||||||
|
echo -e "${GREEN}Passed: $PASSED_TESTS ${NC}"
|
||||||
|
echo -e "${RED}Failed: $FAILED_TESTS ${NC}"
|
||||||
|
|
||||||
|
exit "$FAILED_TESTS"
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"agent-wdd/log"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -18,7 +21,19 @@ func DownloadFile(url string, path string) (bool, string) {
|
|||||||
return DownloadFileWithClient(client, url, path)
|
return DownloadFileWithClient(client, url, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownloadFileWithClient 使用http客户端下载文件
|
||||||
func DownloadFileWithClient(client *http.Client, url string, path string) (bool, string) {
|
func DownloadFileWithClient(client *http.Client, url string, path string) (bool, string) {
|
||||||
|
|
||||||
|
// path如果是一个目录,则需要获取文件名
|
||||||
|
// 获取url使用 / 分割最后的一部分
|
||||||
|
// 如果path是目录,则需要获取文件名
|
||||||
|
|
||||||
|
if IsDirOrFile(path) {
|
||||||
|
fileName := strings.Split(url, "/")[len(strings.Split(url, "/"))-1]
|
||||||
|
path = filepath.Join(path, fileName)
|
||||||
|
log.Info("path是目录,自动获取文件名为 => : %s", path)
|
||||||
|
}
|
||||||
|
|
||||||
return downloadWithProgress(client, url, path)
|
return downloadWithProgress(client, url, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,14 +42,14 @@ func downloadWithProgress(client *http.Client, url, dest string) (bool, string)
|
|||||||
// 创建目标文件
|
// 创建目标文件
|
||||||
file, err := os.Create(dest)
|
file, err := os.Create(dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Sprintf("创建文件失败: %w", err)
|
return false, fmt.Sprintf("创建文件失败: %s", err.Error())
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
// 发起请求
|
// 发起请求
|
||||||
resp, err := client.Get(url)
|
resp, err := client.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Sprintf("HTTP请求失败: %w", err)
|
return false, fmt.Sprintf("HTTP请求失败: %s", err.Error())
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@@ -46,6 +61,13 @@ func downloadWithProgress(client *http.Client, url, dest string) (bool, string)
|
|||||||
size := resp.ContentLength
|
size := resp.ContentLength
|
||||||
var downloaded int64
|
var downloaded int64
|
||||||
|
|
||||||
|
// 不支持下载超过10GB的文件
|
||||||
|
|
||||||
|
if size > 10*1024*1024*1024 || size < 0 {
|
||||||
|
log.Error("文件大小超过10GB,或者文件大小未知,不支持高级下载方式! 尝试使用wget下载")
|
||||||
|
return downloadFileByWget(url, dest)
|
||||||
|
}
|
||||||
|
|
||||||
// 打印下载信息
|
// 打印下载信息
|
||||||
fmt.Printf("开始下载: %s 大小: %s\n", url, HumanSizeInt(size))
|
fmt.Printf("开始下载: %s 大小: %s\n", url, HumanSizeInt(size))
|
||||||
|
|
||||||
@@ -60,13 +82,32 @@ func downloadWithProgress(client *http.Client, url, dest string) (bool, string)
|
|||||||
|
|
||||||
// 执行拷贝
|
// 执行拷贝
|
||||||
if _, err := io.Copy(file, progressReader); err != nil {
|
if _, err := io.Copy(file, progressReader); err != nil {
|
||||||
return false, fmt.Sprintf("文件拷贝失败: %w", err)
|
return false, fmt.Sprintf("文件拷贝失败: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print("\n") // 保持最后进度显示的完整性
|
fmt.Print("\n") // 保持最后进度显示的完整性
|
||||||
return true, fmt.Sprintf("文件下载成功: %s", dest)
|
return true, fmt.Sprintf("文件下载成功: %s", dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 使用wget下载文件
|
||||||
|
func downloadFileByWget(url, dest string) (bool, string) {
|
||||||
|
|
||||||
|
log.Info("使用wget下载文件: %s", fmt.Sprintf("wget %s -qO %s", url, dest))
|
||||||
|
cmd := exec.Command("wget", url, "-qO", dest)
|
||||||
|
_, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Sprintf("wget下载失败: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件是否存在且不为空
|
||||||
|
fileInfo, err := os.Stat(dest)
|
||||||
|
if err != nil || fileInfo.Size() == 0 {
|
||||||
|
return false, fmt.Sprintf("wget下载失败 文件不存在或为空: %s", dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, fmt.Sprintf("wget下载成功: %s", dest)
|
||||||
|
}
|
||||||
|
|
||||||
// 进度跟踪Reader
|
// 进度跟踪Reader
|
||||||
type progressReader struct {
|
type progressReader struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func BeautifulPrintWithTitle(contend any, title string) {
|
|||||||
func BeautifulPrintListWithTitle(contend []string, title string) {
|
func BeautifulPrintListWithTitle(contend []string, title string) {
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(fmt.Sprintf("content tile is => %s", title))
|
fmt.Println(">>>>>>>> " + title + " <<<<<<<<")
|
||||||
for _, line := range contend {
|
for _, line := range contend {
|
||||||
fmt.Println(line)
|
fmt.Println(line)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user