package model import ( "backend/Type" "backend/common" "backend/feishu" "backend/msg" util "backend/util" "fmt" "log" "sync" "time" "github.com/Ullaakut/nmap" ) const ( DEVOPS_SERVER = "log" ) type Server struct { AppId int `json:"AppId"` ServerId int `json:"ServerId"` ServerName string `json:"ServerName"` Status int `json:"Status"` OpenServerTime int `json:"OpenServerTime"` Type int `json:"Type"` } type ServerInfo struct { AppId int `json:"AppId" db:"AppId"` ServerId int `json:"ServerId" db:"ServerId"` ServerName string `json:"ServerName" db:"ServerName"` Status int `json:"Status" db:"Status"` CreateTime int `json:"CreateTime" db:"CreateTime"` OpenServerTime int `json:"OpenServerTime" db:"OpenServerTime"` StartTime int64 `json:"StartTime"` PlayerNum int `json:"PlayerNum"` } func (s *Server) AppList() ([]*Type.App, error) { Db := util.MPool.GetGameDB() var app []*Type.App err := Db.Select(&app, "SELECT `AppId`, `AppName`, `NodeName`, `MysqlName`, `Topic`, `tz`, `WsHost`, `Database`, `Update`, `Path` FROM app") defer Db.Close() if err != nil { return nil, fmt.Errorf("failed to scan rows: %v", err) } return app, nil } func (s *Server) ServerList() ([]*ServerInfo, error) { Db := util.MPool.GetGameDB() var server []*ServerInfo defer Db.Close() err := Db.Select(&server, "SELECT `AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime` FROM server where AppId = ?", s.AppId) if err != nil { return nil, fmt.Errorf("failed to scan rows: %v", err) } if s.Type == 1 { return server, nil } var w sync.WaitGroup for _, v := range server { ws, err := util.GetWebsocket(v.AppId, v.ServerId) if err != nil { v.Status = 0 continue } ws.SetReadDeadline(time.Now().Add(2 * time.Second)) w.Add(1) go func(v *ServerInfo) { defer w.Done() req := &msg.ReqServerInfo{} r, err := util.SendAdminMsg(ws, req) if err != nil { log.Printf("failed to send admin message: %v", err) v.Status = 0 return } if r["StartTime"] != nil { v.StartTime = int64(r["StartTime"].(float64)) } if r["PlayerNum"] != nil { v.PlayerNum = int(r["PlayerNum"].(float64)) } v.Status = 1 ws.Close() }(v) } w.Wait() return server, nil } func (s *Server) AddServer() error { Db := util.MPool.GetGameDB() defer Db.Close() _, err := Db.Exec("INSERT INTO server (`AppId`, `ServerId`, `ServerName`, `Status`, `CreateTime`, `OpenServerTime`) VALUES (?, ?, ?, ?, ?, ?)", s.AppId, s.ServerId, s.ServerName, s.Status, util.Now(), s.OpenServerTime) if err != nil { return fmt.Errorf("failed to insert: %v", err) } return nil } func (s *Server) UpdateApp() (string, error) { AppConfig, err := util.GetAppConfig(s.AppId) if err != nil { return "", err } ServerConfig, err := common.GetServerConfig(DEVOPS_SERVER) if err != nil { return "", err } SshClient, err := NewSshClient(ServerConfig) if err != nil { return "", err } defer SshClient.client.Close() _, err = SshClient.RunCommand("cd /data/devops && git pull") if err != nil { return "", fmt.Errorf("failed to git pull: %v", err) } cmd := fmt.Sprintf("ansible-playbook /data/devops/playbook/%s.yml -i /data/devops/playbook/hosts", AppConfig.AppName) output, err := SshClient.RunCommand(cmd) if err != nil { return "", err } DB := util.MPool.GetGameDB() defer DB.Close() DB.Exec("UPDATE app SET `Update` = ? WHERE `AppId` = ?", util.Now(), s.AppId) feishu.SendFeishuMsg(fmt.Sprintf("AppName: %s, 执行文件更新完成", AppConfig.AppName)) return output, nil } func (s *Server) UpdateAppFeishu() (string, error) { AppConfig, err := util.GetAppConfig(s.AppId) if err != nil { return "", err } ServerConfig, err := common.GetServerConfig(DEVOPS_SERVER) if err != nil { return "", err } SshClient, err := NewSshClient(ServerConfig) if err != nil { return "", err } defer SshClient.client.Close() _, err = SshClient.RunCommand("cd /data/devops && git pull") if err != nil { return "", fmt.Errorf("failed to git pull: %v", err) } cmd := fmt.Sprintf("ansible-playbook /data/devops/playbook/%s.yml -i /data/devops/playbook/hosts", AppConfig.AppName) output, err := SshClient.RunCommand(cmd) if err != nil { return "", err } DB := util.MPool.GetGameDB() defer DB.Close() DB.Exec("UPDATE app SET `Update` = ? WHERE `AppId` = ?", util.Now(), s.AppId) feishu.SendFeishuMsg(fmt.Sprintf("AppName: %s, 执行文件更新完成", AppConfig.AppName)) return output, nil } func (s *Server) RestartServer() (string, error) { AppConfig, err := util.GetAppConfig(s.AppId) if err != nil { return "", err } ServerConfig, err := common.GetServerConfig(AppConfig.NodeName) if err != nil { return "", err } SshClient, err := NewSshClient(ServerConfig) if err != nil { return "", err } defer SshClient.client.Close() cmd := fmt.Sprintf("%s/tool/tool restart node %d", AppConfig.Path, s.ServerId) output, err := SshClient.RunCommand(cmd) if err != nil { return "", err } feishu.SendFeishuMsg(fmt.Sprintf("AppName: %s, ServerName: %s, 重启完成", AppConfig.AppName, s.ServerName)) return output, nil } func (s *Server) ReloadServer() (string, error) { AppConfig, err := util.GetAppConfig(s.AppId) if err != nil { return "", err } ws, err := util.GetWebsocket(s.AppId, s.ServerId) if err != nil { return "", fmt.Errorf("failed to get websocket: %v", err) } defer ws.Close() req := &msg.ReqReload{} _, err = util.SendAdminMsg(ws, req) if err != nil { log.Printf("failed to send admin message: %v", err) } feishu.SendFeishuMsg(fmt.Sprintf("AppName: %s, ServerName: %s, 配置重载完成", AppConfig.AppName, s.ServerName)) return "success", nil } // 端口扫描 func PortMap(Ip string, Port string) error { // 创建一个新的Nmap扫描器 scanner, err := nmap.NewScanner( nmap.WithTargets(Ip), // 替换为你要扫描的目标IP地址 nmap.WithPorts(Port), // 替换为你要扫描的端口 // nmap.WithTCPFINScan(), // 使用TCP扫描 nmap.WithTimingTemplate(nmap.TimingSneaky), ) if err != nil { return err } // 执行扫描 result, warnings, err := scanner.Run() if err != nil { return err } // 打印扫描结果 for _, warning := range warnings { log.Printf("nmap 警告: %v", warning) } for _, host := range result.Hosts { if len(host.Ports) == 0 || host.Status.State != "up" { continue } for _, port := range host.Ports { if port.State.State == "filtered" { continue } if port.State.State != "open" { return fmt.Errorf("端口 %d 未监听 %v", port.ID, port) } } } return nil }