feat: SSH 成功获取系统信息时视为机器在线
在连通性检测逻辑中,当 network ping / ICMP / TCP 三层探测均失败后, 若机器配置了 SSH 凭据,则同步尝试调用 GetSSHInfo 进行 SSH 信息采集: - 若 SSH 采集成功,则将该机器判定为在线,并保存获取到的系统信息; - 若 SSH 采集也失败,则保持离线状态,按原逻辑记录离线日志。 此改进可避免以下场景导致的误判: - 机器禁 ping 或 ICMP 被防火墙拦截; - SSH 端口未被网络层探测正确识别; - 只要 SSH 服务正常且能正确登录并获取系统信息,即认为机器处于可用状态。 其他改动: - 提取 saveSSHResult 辅助函数,统一保存 SSH 采集结果,避免重复代码。 - 同步更新了本地与 Linux 部署二进制文件。
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user