diff --git a/server/services/ping.go b/server/services/ping.go index d768eb0..c16c88b 100644 --- a/server/services/ping.go +++ b/server/services/ping.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "lan-manager/server/db" + "lan-manager/server/models" "lan-manager/server/utils" "net" "os" @@ -146,9 +147,43 @@ type machinePing struct { wasOnline bool } +func saveSSHResult(mid int64, mip string, mport int, result *models.SSHInfoResult) { + portsStr := "" + if len(result.ListenPorts) > 0 { + b, _ := json.Marshal(result.ListenPorts) + portsStr = string(b) + if len(portsStr) > 2 { + portsStr = portsStr[1 : len(portsStr)-1] + } + } + _, dbErr := db.DB.Exec(`UPDATE machines SET cpu_info=?, memory_info=?, disk_info=?, uptime=?, listen_ports=?, ssh_synced_at=CURRENT_TIMESTAMP, updated_at=CURRENT_TIMESTAMP WHERE id=?`, + result.RawCPUInfo, result.RawMemoryInfo, result.RawDiskInfo, result.Uptime, portsStr, mid) + if dbErr != nil { + fmt.Printf("[SSH] auto-fetch db error for %s:%d: %v\n", mip, mport, dbErr) + } else { + fmt.Printf("[SSH] auto-fetch success for %s:%d\n", mip, mport) + } +} + func handlePingResult(m *machinePing, res PingResult) { online := res.Online reason := res.Reason + var sshResult *models.SSHInfoResult + + // 如果网络层检测失败,尝试通过 SSH 获取系统信息来判定在线 + if !online && m.sshUsername != "" && m.sshPassword != "" { + plainPass, decryptErr := utils.Decrypt(m.sshPassword) + if decryptErr == nil { + result, err := GetSSHInfo(m.ip, m.sshPort, m.sshUsername, plainPass) + if err == nil { + online = true + reason = "" + sshResult = result + fmt.Printf("[Ping] %s -> network unreachable, but SSH info fetched successfully, treating as online\n", m.ip) + } + } + } + var onlineInt int if online { onlineInt = 1 @@ -185,6 +220,9 @@ func handlePingResult(m *machinePing, res PingResult) { _, _ = db.DB.Exec(`UPDATE machines SET total_offline_seconds=total_offline_seconds+? WHERE id=?`, duration, m.id) } m.wasOnline = true + if sshResult != nil { + saveSSHResult(m.id, m.ip, m.sshPort, sshResult) + } return } @@ -197,33 +235,23 @@ func handlePingResult(m *machinePing, res PingResult) { } if online && m.sshUsername != "" && m.sshPassword != "" { - go func(mid int64, mip string, mport int, muser, mpass string) { - plainPass, decryptErr := utils.Decrypt(mpass) - if decryptErr != nil { - fmt.Printf("[SSH] decrypt failed for %s:%d: %v\n", mip, mport, decryptErr) - return - } - result, err := GetSSHInfo(mip, mport, muser, plainPass) - if err != nil { - fmt.Printf("[SSH] auto-fetch failed for %s:%d: %v\n", mip, mport, err) - return - } - portsStr := "" - if len(result.ListenPorts) > 0 { - b, _ := json.Marshal(result.ListenPorts) - portsStr = string(b) - if len(portsStr) > 2 { - portsStr = portsStr[1 : len(portsStr)-1] + if sshResult != nil { + saveSSHResult(m.id, m.ip, m.sshPort, sshResult) + } else { + go func(mid int64, mip string, mport int, muser, mpass string) { + plainPass, decryptErr := utils.Decrypt(mpass) + if decryptErr != nil { + fmt.Printf("[SSH] decrypt failed for %s:%d: %v\n", mip, mport, decryptErr) + return } - } - _, dbErr := db.DB.Exec(`UPDATE machines SET cpu_info=?, memory_info=?, disk_info=?, uptime=?, listen_ports=?, ssh_synced_at=CURRENT_TIMESTAMP, updated_at=CURRENT_TIMESTAMP WHERE id=?`, - result.RawCPUInfo, result.RawMemoryInfo, result.RawDiskInfo, result.Uptime, portsStr, mid) - if dbErr != nil { - fmt.Printf("[SSH] auto-fetch db error for %s:%d: %v\n", mip, mport, dbErr) - } else { - fmt.Printf("[SSH] auto-fetch success for %s:%d\n", mip, mport) - } - }(m.id, m.ip, m.sshPort, m.sshUsername, m.sshPassword) + result, err := GetSSHInfo(mip, mport, muser, plainPass) + if err != nil { + fmt.Printf("[SSH] auto-fetch failed for %s:%d: %v\n", mip, mport, err) + return + } + saveSSHResult(mid, mip, mport, result) + }(m.id, m.ip, m.sshPort, m.sshUsername, m.sshPassword) + } } }