discovery.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package discovery
  2. import (
  3. "fmt"
  4. "net/http"
  5. "sort"
  6. "time"
  7. "ai-status-light/internal/logger"
  8. )
  9. type Scanner struct {
  10. Host string
  11. ScanRange *[2]int
  12. }
  13. func NewScanner(host string, scanRange *[2]int) *Scanner {
  14. return &Scanner{
  15. Host: host,
  16. ScanRange: scanRange,
  17. }
  18. }
  19. func (s *Scanner) Discover() []int {
  20. logger.Debug("开始发现 OpenCode 实例,主机: %s", s.Host)
  21. ports := findByCmdline()
  22. if len(ports) > 0 {
  23. logger.Debug("通过命令行参数发现端口: %v", ports)
  24. } else {
  25. logger.Debug("命令行未发现端口,尝试通过 PID 查找")
  26. ports = findByPID()
  27. if len(ports) > 0 {
  28. logger.Debug("通过 PID 发现端口: %v", ports)
  29. }
  30. }
  31. if len(ports) == 0 && s.ScanRange != nil {
  32. logger.Info("未通过系统命令发现实例,开始端口扫描 %d-%d", s.ScanRange[0], s.ScanRange[1])
  33. ports = scanPorts(s.Host, s.ScanRange[0], s.ScanRange[1])
  34. if len(ports) > 0 {
  35. logger.Info("端口扫描发现 %d 个实例: %v", len(ports), ports)
  36. }
  37. }
  38. result := unique(ports)
  39. logger.Debug("发现完成,共 %d 个实例: %v", len(result), result)
  40. return result
  41. }
  42. func scanPorts(host string, startPort, endPort int) []int {
  43. var found []int
  44. client := http.Client{Timeout: 1 * time.Second}
  45. for port := startPort; port <= endPort; port++ {
  46. resp, err := client.Get(fmt.Sprintf("http://%s:%d/global/health", host, port))
  47. if err != nil {
  48. continue
  49. }
  50. resp.Body.Close()
  51. if resp.StatusCode == 200 {
  52. logger.Debug("端口扫描发现实例: %d", port)
  53. found = append(found, port)
  54. }
  55. }
  56. return found
  57. }
  58. func contains(slice []int, val int) bool {
  59. for _, v := range slice {
  60. if v == val {
  61. return true
  62. }
  63. }
  64. return false
  65. }
  66. func unique(slice []int) []int {
  67. keys := make(map[int]bool)
  68. var result []int
  69. for _, v := range slice {
  70. if !keys[v] {
  71. keys[v] = true
  72. result = append(result, v)
  73. }
  74. }
  75. sort.Ints(result)
  76. return result
  77. }