feat: 添加新的 raid 处理程序以获取和显示磁盘阵列信息

This commit is contained in:
lixiangwuxian 2025-04-11 01:25:25 +08:00
parent 98c9073f0d
commit 95ccd1f8f3
2 changed files with 182 additions and 0 deletions

181
handler/raid/raid.go Normal file
View File

@ -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)
}

View File

@ -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"