package services import ( "bytes" "database/sql" "fmt" "os" "path/filepath" "sync" "time" "xg_dba/api" "xg_dba/internal/global" "xg_dba/internal/models" "xg_dba/module/remote" _ "xg_dba/pkg/xugu" "github.com/BurntSushi/toml" ) func SetSystemInfo_service(connectInfo []api.ServerInfoRequest, saveFilePath string, progressID string) error { //ping服务器是否能连通 //ssh连接服务器 //执行命令 //返回结果并存储到本地 var wg sync.WaitGroup var mu sync.Mutex defer global.Progress.CloseProgress(progressID) // 处理完成后关闭进度 channel progressChan, ok := global.Progress.GetProgressChan(progressID) if !ok { return fmt.Errorf("Progress 队列错误") } commands := map[string]string{ "OS Info": "cat /etc/os-release", "CPU Info": "lscpu", "Memory Info": "free -h", "Disk Info": "df -h", "Network Info": "ip addr", "Disk Speed": "dd if=/dev/zero of=/tmp/testfile bs=8K count=102400 oflag=direct; rm -f /tmp/testfile", "Network Speed": "ping -c 4 8.8.8.8", } //循环每一组集群去执行命令1 for _, server := range connectInfo { wg.Add(1) //开启协程对每一组集群去执行命令 go func(server api.ServerInfoRequest) { defer wg.Done() systemInfo := models.SystemMetaInfo{} var serverWg sync.WaitGroup for name, cmd := range commands { serverWg.Add(1) go func(name, cmd string, server api.ServerInfoRequest) { defer serverWg.Done() // 每次执行命令都新建一个 SSH 客户端 sshClient, err := remote.NewSSHClient("1", server.Username, server.Password, server.Host, server.Port) if err != nil { global.Logger.Errorf("NewSSHClient failed for %s on server %s: %v", name, server.Host, err) progressChan <- fmt.Sprintf("%s on server %s: failed to connect", name, server.Host) return } defer sshClient.Close() output, err := sshClient.RunCommand(cmd) if err != nil { global.Logger.Errorf("%s command failed on server %s: %v", name, server.Host, err) progressChan <- fmt.Sprintf("%s on server %s: command failed", name, server.Host) return } mu.Lock() // 根据命令名称将输出赋值到结构体字段 switch name { case "OS Info": systemInfo.Os = output case "CPU Info": systemInfo.Cpu = output case "Memory Info": systemInfo.Memory = output case "Disk Info": systemInfo.Disk = output case "Network Info": systemInfo.Network = output case "Disk Speed": systemInfo.DiskSpeed = output case "Network Speed": systemInfo.NetworkSpeed = output } mu.Unlock() progressChan <- fmt.Sprintf("%s on server %s: completed. data = %s", name, server.Host, output) fmt.Printf("--%s on server %s:\n%s\n", name, server.Host, output) }(name, cmd, server) } serverWg.Wait() if systemInfo.Cpu != "" { //progressChan <- fmt.Sprintf("Error: failed to get system meta info for server %s", server.Host) timestamp := time.Now().Format("20060102_150405") os.MkdirAll(filepath.Dir(saveFilePath), os.ModePerm) filePath := fmt.Sprintf("%s%s_os_info_%s.toml", saveFilePath, server.Host, timestamp) err := saveSystemMetaInfoToFile(systemInfo, filePath) if err != nil { progressChan <- fmt.Sprintf("Error: failed to save system meta info for server %s", server.Host) fmt.Printf("Error: %v\n", err) } else { progressChan <- fmt.Sprintf("System meta info saved successfully for server %s", server.Host) fmt.Println("System meta info saved successfully for server", server.Host) } return } else { return } }(server) } wg.Wait() //close(progressChan) return nil } // 保存系统环境信息到文件 func saveSystemMetaInfoToFile(info models.SystemMetaInfo, filePath string) error { var buffer bytes.Buffer encoder := toml.NewEncoder(&buffer) if err := encoder.Encode(info); err != nil { return fmt.Errorf("failed to encode system meta info to TOML: %v", err) } err := os.WriteFile(filePath, buffer.Bytes(), 0644) if err != nil { return fmt.Errorf("failed to write to file: %v", err) } return nil } func GetDb() { // 连接数据库 db, err := sql.Open("xugusql", "root:123456@tcp(127.0.0.1:3306)/test") if err != nil { panic(err.Error()) } db.Close() }