linux.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package device
  2. import (
  3. "fmt"
  4. "network-topology-discovery/pkg/models"
  5. "regexp"
  6. "strings"
  7. )
  8. // LinuxParser Linux服务器解析器
  9. type LinuxParser struct {
  10. BaseParser
  11. }
  12. // GetCommands 获取Linux命令列表
  13. func (p *LinuxParser) GetCommands() []string {
  14. return []string{
  15. "hostname",
  16. "uname -a",
  17. "ip addr show",
  18. "ip link show",
  19. "uptime",
  20. }
  21. }
  22. // Parse 解析Linux输出
  23. func (p *LinuxParser) Parse(device *models.Device, outputs []string) error {
  24. if len(outputs) < 5 {
  25. return fmt.Errorf("insufficient command outputs")
  26. }
  27. device.Hostname = strings.TrimSpace(outputs[0])
  28. device.OSVersion = p.parseOSVersion(outputs[1])
  29. device.Uptime = strings.TrimSpace(outputs[4])
  30. device.Interfaces = p.parseInterfaces(outputs[2], outputs[3])
  31. return nil
  32. }
  33. func (p *LinuxParser) parseOSVersion(output string) string {
  34. // 从uname提取内核版本
  35. parts := strings.Fields(output)
  36. if len(parts) >= 3 {
  37. return fmt.Sprintf("Linux %s", parts[2])
  38. }
  39. return output
  40. }
  41. func (p *LinuxParser) parseInterfaces(addrOutput, linkOutput string) []models.Interface {
  42. var interfaces []models.Interface
  43. // 解析ip addr show输出
  44. interfaceMap := make(map[string]*models.Interface)
  45. var currentInterface *models.Interface
  46. lines := strings.Split(addrOutput, "\n")
  47. for _, line := range lines {
  48. // 匹配接口: 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
  49. if nameRegex := regexp.MustCompile(`^\d+:\s+(\S+):\s+<([^>]*)>`); nameRegex.MatchString(line) {
  50. matches := nameRegex.FindStringSubmatch(line)
  51. name := strings.TrimSuffix(matches[1], ":")
  52. flags := matches[2]
  53. currentInterface = &models.Interface{
  54. Name: name,
  55. Status: "down",
  56. }
  57. if strings.Contains(flags, "UP") {
  58. currentInterface.Status = "up"
  59. }
  60. // 提取MTU
  61. if mtuRegex := regexp.MustCompile(`mtu\s+(\d+)`); mtuRegex.MatchString(line) {
  62. matches := mtuRegex.FindStringSubmatch(line)
  63. currentInterface.MTU = 0
  64. fmt.Sscanf(matches[1], "%d", &currentInterface.MTU)
  65. }
  66. interfaceMap[name] = currentInterface
  67. interfaces = append(interfaces, *currentInterface)
  68. }
  69. if currentInterface != nil {
  70. // 提取MAC地址
  71. if macRegex := regexp.MustCompile(`link/ether\s+(\S+)`); macRegex.MatchString(line) {
  72. matches := macRegex.FindStringSubmatch(line)
  73. currentInterface.MAC = matches[1]
  74. }
  75. // 提取IP地址
  76. if ipRegex := regexp.MustCompile(`inet\s+(\d+\.\d+\.\d+\.\d+)/(\d+)`); ipRegex.MatchString(line) {
  77. matches := ipRegex.FindStringSubmatch(line)
  78. currentInterface.IP = matches[1]
  79. currentInterface.Mask = matches[2]
  80. }
  81. }
  82. }
  83. // 更新接口列表
  84. finalInterfaces := make([]models.Interface, 0, len(interfaceMap))
  85. for _, iface := range interfaceMap {
  86. finalInterfaces = append(finalInterfaces, *iface)
  87. }
  88. return finalInterfaces
  89. }