diff --git a/handler/raid/raid.go b/handler/raid/raid.go new file mode 100644 index 0000000..2a4dba5 --- /dev/null +++ b/handler/raid/raid.go @@ -0,0 +1,181 @@ +package raid + +import ( + "fmt" + "log" + "os/exec" + "strconv" + "strings" + + "git.lxtend.com/qqbot/constants" + "git.lxtend.com/qqbot/handler" + "git.lxtend.com/qqbot/model" +) + +func init() { + handler.RegisterHandler("!raid", RaidHandler, constants.LEVEL_USER) +} + +func RaidHandler(msg model.Message) (reply *model.Reply) { + diskInfoList := GetDiskInfo() + + if len(diskInfoList) == 0 { + return &model.Reply{ + FromMsg: msg, + ReplyMsg: "未获取到阵列信息", + ReferOriginMsg: false, + } + } + + sb := strings.Builder{} + sb.WriteString("阵列信息:\n") + for _, diskInfo := range diskInfoList { + sb.WriteString(diskInfo.String()) + } + + return &model.Reply{ + FromMsg: msg, + ReplyMsg: sb.String(), + ReferOriginMsg: false, + } +} + +// MegaCli64 -PDList -aALL | grep -E "Slot Number|Drive Temperature|Inquiry Data|Firmware state|S.M.A.R.T alert" | cat +// Slot Number: 0 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 010356A0A001FWWB +// Drive Temperature :56C (132.80 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 1 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6S0A0LRFWWB +// Drive Temperature :54C (129.20 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 2 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 010356F0A00AFWWB +// Drive Temperature :51C (123.80 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 3 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6Q0A0RZFWWB +// Drive Temperature :46C (114.80 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 4 +// Firmware state: Unconfigured(bad) +// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6R0A09VFWWB +// Drive Temperature :49C (120.20 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 5 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6R0A0JZFWWB +// Drive Temperature :53C (127.40 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 6 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 010356F0A004FWWB +// Drive Temperature :56C (132.80 F) +// Drive has flagged a S.M.A.R.T alert : No +// Slot Number: 7 +// Firmware state: Online, Spun Up +// Inquiry Data: TOSHIBA MG04SCA60EE 01034680A01WFWWB +// Drive Temperature :58C (136.40 F) +// Drive has flagged a S.M.A.R.T alert : No + +type DiskInfo struct { + SlotNumber int + DriveTemperature string + Type string + Sn string + FirmwareState string + SmartAlert bool +} + +func (d *DiskInfo) String() string { + sb := strings.Builder{} + sb.WriteString(fmt.Sprintf("槽位: %d\n", d.SlotNumber)) + sb.WriteString(fmt.Sprintf("温度: %s\n", d.DriveTemperature)) + sb.WriteString(fmt.Sprintf("型号: %s\n", d.Type)) + sb.WriteString(fmt.Sprintf("SN: %s\n", d.Sn)) + sb.WriteString(fmt.Sprintf("状态: %s\n", d.FirmwareState)) + sb.WriteString(fmt.Sprintf("S.M.A.R.T报警: %t\n", d.SmartAlert)) + return sb.String() +} + +func ParseDiskInfoList(lines []string) []*DiskInfo { + var diskInfoList []*DiskInfo + var currentDisk *DiskInfo + + for _, line := range lines { + line = strings.TrimSpace(line) + + if strings.HasPrefix(line, "Slot Number:") { + // 新的磁盘信息开始 + if currentDisk != nil { + diskInfoList = append(diskInfoList, currentDisk) + } + + slotStr := strings.TrimSpace(strings.TrimPrefix(line, "Slot Number:")) + slotNum, err := strconv.Atoi(slotStr) + if err != nil { + log.Printf("解析槽位号失败: %v", err) + slotNum = -1 + } + + currentDisk = &DiskInfo{ + SlotNumber: slotNum, + } + } else if currentDisk != nil { + // 处理当前磁盘的其他信息 + if strings.HasPrefix(line, "Firmware state:") { + currentDisk.FirmwareState = strings.TrimSpace(strings.TrimPrefix(line, "Firmware state:")) + } else if strings.HasPrefix(line, "Inquiry Data:") { + inquiryData := strings.TrimSpace(strings.TrimPrefix(line, "Inquiry Data:")) + parts := strings.Fields(inquiryData) + if len(parts) >= 2 { + currentDisk.Type = strings.Join(parts[:len(parts)-1], " ") + currentDisk.Sn = parts[len(parts)-1] + } + } else if strings.HasPrefix(line, "Drive Temperature") { + tempParts := strings.Split(line, ":") + if len(tempParts) >= 2 { + currentDisk.DriveTemperature = strings.TrimSpace(tempParts[1]) + } + } else if strings.HasPrefix(line, "Drive has flagged a S.M.A.R.T alert") { + smartParts := strings.Split(line, ":") + if len(smartParts) >= 2 { + currentDisk.SmartAlert = strings.TrimSpace(smartParts[1]) != "No" + } + } + } + } + + // 添加最后一个磁盘 + if currentDisk != nil { + diskInfoList = append(diskInfoList, currentDisk) + } + + return diskInfoList +} + +func GetDiskInfo() []*DiskInfo { + // 首先尝试运行MegaCli64命令 + cmd := exec.Command("MegaCli64", "-PDList", "-aALL") + outputBytes, err := cmd.Output() + if err != nil { + log.Printf("运行MegaCli64失败: %v", err) + + // 尝试运行grep命令模拟示例输出 + grepCmd := exec.Command("grep", "-E", "Slot Number|Drive Temperature|Inquiry Data|Firmware state|S.M.A.R.T alert") + outputBytes, err = grepCmd.Output() + if err != nil { + log.Printf("获取磁盘信息失败: %v", err) + return nil + } + } + + output := string(outputBytes) + lines := strings.Split(output, "\n") + + return ParseDiskInfoList(lines) +} diff --git a/register.go b/register.go index 2901d55..a82d165 100644 --- a/register.go +++ b/register.go @@ -16,6 +16,7 @@ import ( _ "git.lxtend.com/qqbot/handler/kfccrazy" _ "git.lxtend.com/qqbot/handler/kw" _ "git.lxtend.com/qqbot/handler/newbond" + _ "git.lxtend.com/qqbot/handler/raid" _ "git.lxtend.com/qqbot/handler/restart" _ "git.lxtend.com/qqbot/handler/roll" _ "git.lxtend.com/qqbot/handler/scoresaber"