mirror of
https://github.com/oneclickvirt/basics.git
synced 2025-10-15 13:11:06 +08:00
feat: 支持raid检测(虽然几乎没有服务器有查得到的)
This commit is contained in:
@@ -19,7 +19,6 @@ Include: https://github.com/oneclickvirt/gostun
|
||||
## TODO
|
||||
|
||||
- [ ] 在可检索的物理核心的时候,额外添加对虚拟核心的识别,尽量全部核心数量还有线程数都展示出来
|
||||
- [ ] 支持raid识别
|
||||
- [ ] 适配MACOS系统的相关信息识别
|
||||
|
||||
## Usage
|
||||
|
@@ -27,36 +27,6 @@ func getInterface() (string, error) {
|
||||
return "", fmt.Errorf("未找到合适的网络接口")
|
||||
}
|
||||
|
||||
// 获取当前的公网 IPv6 地址
|
||||
// func getCurrentIPv6() (string, error) {
|
||||
// // 创建一个新的req客户端,设置超时
|
||||
// client := req.C().SetTimeout(5 * time.Second)
|
||||
// client.SetTimeout(6 * time.Second)
|
||||
// // 尝试多个 IPv6 检测服务
|
||||
// urls := []string{
|
||||
// "https://ipv6.ip.sb",
|
||||
// "https://api6.ipify.org",
|
||||
// "https://v6.ident.me",
|
||||
// }
|
||||
// var lastErr error
|
||||
// for _, url := range urls {
|
||||
// resp, err := client.R().Get(url)
|
||||
// if err != nil {
|
||||
// lastErr = err
|
||||
// continue
|
||||
// }
|
||||
// body := resp.String()
|
||||
// ipv6 := strings.TrimSpace(body)
|
||||
// if net.ParseIP(ipv6) != nil && strings.Contains(ipv6, ":") {
|
||||
// return ipv6, nil
|
||||
// }
|
||||
// }
|
||||
// if lastErr != nil {
|
||||
// return "", lastErr
|
||||
// }
|
||||
// return "", fmt.Errorf("无法获取公网IPv6地址")
|
||||
// }
|
||||
|
||||
// 判断是否为非全局单播地址前缀
|
||||
func isNonGlobalPrefix(prefix [16]byte) bool {
|
||||
// 链路本地地址 fe80::/10
|
||||
|
241
system/raid.go
Normal file
241
system/raid.go
Normal file
@@ -0,0 +1,241 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RAID信息结构体
|
||||
type RAIDInfo struct {
|
||||
Exists bool
|
||||
Type string
|
||||
DiskCount int
|
||||
Controller string
|
||||
Details string
|
||||
}
|
||||
|
||||
func detectRAID() (RAIDInfo, error) {
|
||||
var info RAIDInfo
|
||||
var err error
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
info, err = detectWindowsRAID()
|
||||
case "linux":
|
||||
info, err = detectLinuxRAID()
|
||||
case "darwin":
|
||||
info, err = detectMacOSRAID()
|
||||
default:
|
||||
err = fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
|
||||
}
|
||||
return info, err
|
||||
}
|
||||
|
||||
func detectWindowsRAID() (RAIDInfo, error) {
|
||||
info := RAIDInfo{}
|
||||
// 使用diskpart和wmic获取存储信息
|
||||
cmd := exec.Command("powershell", "-Command", "Get-WmiObject -Class Win32_DiskDrive | Select-Object Model, InterfaceType, MediaType | Format-Table -AutoSize")
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
// 检查是否有控制器信息
|
||||
controllerCmd := exec.Command("powershell", "-Command", "Get-WmiObject -Class Win32_SCSIController | Select-Object Name, DriverName, PNPDeviceID | Format-Table -AutoSize")
|
||||
controllerOutput, err := controllerCmd.CombinedOutput()
|
||||
if err == nil {
|
||||
controllerStr := string(controllerOutput)
|
||||
if strings.Contains(strings.ToLower(controllerStr), "raid") {
|
||||
info.Exists = true
|
||||
info.Controller = extractControllerName(controllerStr)
|
||||
}
|
||||
}
|
||||
// 检查虚拟磁盘
|
||||
vDiskCmd := exec.Command("powershell", "-Command", "Get-WmiObject -Class Win32_DiskDrive | Where-Object {$_.MediaType -eq 'Fixed hard disk media'} | ForEach-Object {$disk = $_; Get-WmiObject -Class Win32_DiskPartition | Where-Object {$_.DiskIndex -eq $disk.Index}} | Format-Table -AutoSize")
|
||||
vDiskOutput, _ := vDiskCmd.CombinedOutput()
|
||||
// 分析输出确定RAID类型
|
||||
outputStr := string(output) + string(vDiskOutput)
|
||||
if info.Exists || strings.Contains(strings.ToLower(outputStr), "raid") {
|
||||
info.Exists = true
|
||||
info.Type = determineWindowsRAIDType(outputStr)
|
||||
info.DiskCount = estimateDiskCount(outputStr)
|
||||
info.Details = cleanOutput(outputStr)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func detectLinuxRAID() (RAIDInfo, error) {
|
||||
info := RAIDInfo{}
|
||||
// 检查软RAID (mdadm)
|
||||
mdstatCmd := exec.Command("cat", "/proc/mdstat")
|
||||
mdstatOutput, err := mdstatCmd.CombinedOutput()
|
||||
if err == nil && len(mdstatOutput) > 0 && !strings.Contains(string(mdstatOutput), "unused devices") {
|
||||
mdstatStr := string(mdstatOutput)
|
||||
if strings.Contains(mdstatStr, "md") {
|
||||
info.Exists = true
|
||||
info.Type = determineLinuxRAIDType(mdstatStr)
|
||||
info.DiskCount = countDevicesInMdstat(mdstatStr)
|
||||
info.Controller = "软件RAID (mdadm)"
|
||||
info.Details = cleanOutput(mdstatStr)
|
||||
return info, nil
|
||||
}
|
||||
}
|
||||
// 检查硬件RAID控制器
|
||||
lspciCmd := exec.Command("lspci")
|
||||
lspciOutput, err := lspciCmd.CombinedOutput()
|
||||
if err == nil {
|
||||
lspciStr := string(lspciOutput)
|
||||
if strings.Contains(strings.ToLower(lspciStr), "raid") {
|
||||
info.Exists = true
|
||||
info.Controller = extractLinuxControllerName(lspciStr)
|
||||
info.Type = "硬件RAID"
|
||||
info.Details = cleanOutput(lspciStr)
|
||||
// 尝试获取更多详细信息
|
||||
if strings.Contains(strings.ToLower(info.Controller), "lsi") || strings.Contains(strings.ToLower(info.Controller), "avago") || strings.Contains(strings.ToLower(info.Controller), "broadcom") {
|
||||
mptUtilCmd := exec.Command("sh", "-c", "which mpt-status && mpt-status || echo 'mpt-status not installed'")
|
||||
mptOutput, _ := mptUtilCmd.CombinedOutput()
|
||||
info.Details += "\n" + cleanOutput(string(mptOutput))
|
||||
} else if strings.Contains(strings.ToLower(info.Controller), "adaptec") {
|
||||
arcConfCmd := exec.Command("sh", "-c", "which arcconf && arcconf getconfig 1 || echo 'arcconf not installed'")
|
||||
arcOutput, _ := arcConfCmd.CombinedOutput()
|
||||
info.Details += "\n" + cleanOutput(string(arcOutput))
|
||||
}
|
||||
}
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func detectMacOSRAID() (RAIDInfo, error) {
|
||||
info := RAIDInfo{}
|
||||
|
||||
// 使用diskutil获取RAID信息
|
||||
cmd := exec.Command("diskutil", "appleRAID", "list")
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
if err == nil {
|
||||
outputStr := string(output)
|
||||
if !strings.Contains(outputStr, "No RAID sets") {
|
||||
info.Exists = true
|
||||
info.Type = determineMacRAIDType(outputStr)
|
||||
info.DiskCount = countMacRAIDDisks(outputStr)
|
||||
info.Controller = "Apple Software RAID"
|
||||
info.Details = cleanOutput(outputStr)
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func determineWindowsRAIDType(output string) string {
|
||||
lowerOutput := strings.ToLower(output)
|
||||
|
||||
if strings.Contains(lowerOutput, "raid 0") || strings.Contains(lowerOutput, "stripe") {
|
||||
return "RAID 0 (条带化)"
|
||||
} else if strings.Contains(lowerOutput, "raid 1") || strings.Contains(lowerOutput, "mirror") {
|
||||
return "RAID 1 (镜像)"
|
||||
} else if strings.Contains(lowerOutput, "raid 5") || strings.Contains(lowerOutput, "parity") {
|
||||
return "RAID 5 (分布式奇偶校验)"
|
||||
} else if strings.Contains(lowerOutput, "raid 6") {
|
||||
return "RAID 6 (双奇偶校验)"
|
||||
} else if strings.Contains(lowerOutput, "raid 10") {
|
||||
return "RAID 10 (镜像+条带)"
|
||||
} else {
|
||||
return "未知RAID类型"
|
||||
}
|
||||
}
|
||||
|
||||
func determineLinuxRAIDType(mdstat string) string {
|
||||
if strings.Contains(mdstat, "raid0") {
|
||||
return "RAID 0 (条带化)"
|
||||
} else if strings.Contains(mdstat, "raid1") {
|
||||
return "RAID 1 (镜像)"
|
||||
} else if strings.Contains(mdstat, "raid4") {
|
||||
return "RAID 4 (专用奇偶校验)"
|
||||
} else if strings.Contains(mdstat, "raid5") {
|
||||
return "RAID 5 (分布式奇偶校验)"
|
||||
} else if strings.Contains(mdstat, "raid6") {
|
||||
return "RAID 6 (双奇偶校验)"
|
||||
} else if strings.Contains(mdstat, "raid10") {
|
||||
return "RAID 10 (镜像+条带)"
|
||||
} else {
|
||||
return "未知RAID类型"
|
||||
}
|
||||
}
|
||||
|
||||
func determineMacRAIDType(output string) string {
|
||||
lowerOutput := strings.ToLower(output)
|
||||
|
||||
if strings.Contains(lowerOutput, "stripe") {
|
||||
return "RAID 0 (条带化)"
|
||||
} else if strings.Contains(lowerOutput, "mirror") {
|
||||
return "RAID 1 (镜像)"
|
||||
} else if strings.Contains(lowerOutput, "concat") {
|
||||
return "JBOD (磁盘连接)"
|
||||
} else {
|
||||
return "未知RAID类型"
|
||||
}
|
||||
}
|
||||
|
||||
func extractControllerName(output string) string {
|
||||
scanner := bufio.NewScanner(strings.NewReader(output))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Contains(strings.ToLower(line), "raid") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) > 0 {
|
||||
return strings.Join(fields, " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
return "未知RAID控制器"
|
||||
}
|
||||
|
||||
func extractLinuxControllerName(lspci string) string {
|
||||
scanner := bufio.NewScanner(strings.NewReader(lspci))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Contains(strings.ToLower(line), "raid") {
|
||||
return line
|
||||
}
|
||||
}
|
||||
return "未知RAID控制器"
|
||||
}
|
||||
|
||||
func estimateDiskCount(output string) int {
|
||||
// 简单估计,实际情况可能需要更复杂的解析
|
||||
re := regexp.MustCompile(`Disk #\d+`)
|
||||
matches := re.FindAllString(output, -1)
|
||||
return len(matches)
|
||||
}
|
||||
|
||||
func countDevicesInMdstat(mdstat string) int {
|
||||
scanner := bufio.NewScanner(strings.NewReader(mdstat))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Contains(line, "active") {
|
||||
re := regexp.MustCompile(`sd[a-z][0-9]*`)
|
||||
matches := re.FindAllString(line, -1)
|
||||
return len(matches)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func countMacRAIDDisks(output string) int {
|
||||
re := regexp.MustCompile(`Disk: [0-9]`)
|
||||
matches := re.FindAllString(output, -1)
|
||||
return len(matches)
|
||||
}
|
||||
|
||||
func cleanOutput(output string) string {
|
||||
// 删除ANSI颜色代码和控制字符
|
||||
re := regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`)
|
||||
cleanStr := re.ReplaceAllString(output, "")
|
||||
// 限制输出长度
|
||||
if len(cleanStr) > 500 {
|
||||
return cleanStr[:500] + "..."
|
||||
}
|
||||
return cleanStr
|
||||
}
|
@@ -5,5 +5,21 @@ import (
|
||||
)
|
||||
|
||||
func TestGetSystemInfo(t *testing.T) {
|
||||
// 检测整体
|
||||
GetSystemInfo()
|
||||
// 检测raid - 在服务器上几乎没有查得到的,不加入检测
|
||||
// raidInfo, err := detectRAID()
|
||||
// if err != nil {
|
||||
// fmt.Printf("检测RAID时发生错误: %v\n", err)
|
||||
// return
|
||||
// }
|
||||
// if raidInfo.Exists {
|
||||
// fmt.Println("检测到RAID配置:")
|
||||
// fmt.Printf("RAID类型: %s\n", raidInfo.Type)
|
||||
// fmt.Printf("磁盘数量: %d\n", raidInfo.DiskCount)
|
||||
// fmt.Printf("控制器: %s\n", raidInfo.Controller)
|
||||
// // fmt.Printf("详细信息: %s\n", raidInfo.Details)
|
||||
// } else {
|
||||
// fmt.Println("未检测到RAID配置")
|
||||
// }
|
||||
}
|
||||
|
Reference in New Issue
Block a user