| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- //go:build darwin
- package discovery
- import (
- "os/exec"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "ai-status-light/internal/logger"
- )
- func findByPID() []int {
- var ports []int
- pidRegex := regexp.MustCompile(`(?:^|/)opencode(?:\s|$)`)
- out, err := exec.Command("ps", "aux").Output()
- if err != nil {
- logger.Debug("执行 ps aux 失败: %v", err)
- return ports
- }
- var pids []int
- for _, line := range strings.Split(string(out), "\n") {
- if pidRegex.MatchString(line) && !strings.Contains(line, "grep") && !strings.Contains(line, "opencode-monitor") {
- fields := strings.Fields(line)
- if len(fields) > 1 {
- if pid, err := strconv.Atoi(fields[1]); err == nil {
- pids = append(pids, pid)
- }
- }
- }
- }
- if len(pids) == 0 {
- logger.Debug("未找到 opencode 进程")
- return ports
- }
- logger.Debug("发现 opencode 进程 PID: %v", pids)
- for _, pid := range pids {
- lsofOut, err := exec.Command("lsof", "-p", strconv.Itoa(pid), "-i", "TCP", "-s", "TCP:LISTEN").Output()
- if err != nil {
- logger.Debug("执行 lsof 失败: %v", err)
- continue
- }
- for _, line := range strings.Split(string(lsofOut), "\n") {
- if strings.Contains(line, "LISTEN") {
- // lsof 输出格式: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- // NAME 部分格式: *:port 或 host:port
- fields := strings.Fields(line)
- if len(fields) >= 9 {
- nameField := fields[len(fields)-1]
- if strings.Contains(nameField, ":") {
- parts := strings.Split(nameField, ":")
- if len(parts) >= 2 {
- if port, err := strconv.Atoi(parts[len(parts)-1]); err == nil {
- if port > 0 && port < 65535 && !contains(ports, port) {
- ports = append(ports, port)
- }
- }
- }
- }
- }
- }
- }
- }
- sort.Ints(ports)
- return ports
- }
- func findByCmdline() []int {
- var ports []int
- out, err := exec.Command("ps", "aux").Output()
- if err != nil {
- logger.Debug("执行 ps aux 失败: %v", err)
- return ports
- }
- for _, line := range strings.Split(string(out), "\n") {
- if strings.Contains(line, "opencode") && !strings.Contains(line, "opencode-monitor") && !strings.Contains(line, "grep") {
- if strings.Contains(line, "--port") {
- fields := strings.Fields(line)
- for i, f := range fields {
- if f == "--port" && i+1 < len(fields) {
- if port, err := strconv.Atoi(fields[i+1]); err == nil {
- if !contains(ports, port) {
- ports = append(ports, port)
- }
- }
- }
- }
- }
- }
- }
- sort.Ints(ports)
- return ports
- }
|