package main import ( "fmt" "os" "os/exec" "path/filepath" "runtime" "strconv" "syscall" "github.com/gofrs/flock" ) // ========== PID 文件管理 ========== var fileLock *flock.Flock func getPidFile() string { return filepath.Join(dataDir, "agent.pid") } func getLockFile() string { return filepath.Join(dataDir, "agent.lock") } // tryLock 尝试获取文件锁,确保只有一个实例运行 func tryLock() bool { os.MkdirAll(dataDir, 0755) fileLock = flock.New(getLockFile()) locked, err := fileLock.TryLock() if err != nil || !locked { fileLock = nil return false } return true } // unlock 释放文件锁 func unlock() { if fileLock != nil { fileLock.Unlock() fileLock = nil os.Remove(getLockFile()) } } func writePidFile() { os.MkdirAll(dataDir, 0755) pidFile := getPidFile() os.WriteFile(pidFile, []byte(strconv.Itoa(os.Getpid())), 0644) } func readPidFile() int { pidFile := getPidFile() data, err := os.ReadFile(pidFile) if err != nil { return 0 } pid, _ := strconv.Atoi(string(data)) return pid } func removePidFile() { os.Remove(getPidFile()) } // ========== 命令实现 ========== func cmdStop() { pid := readPidFile() if pid == 0 { fmt.Println("Agent 未运行") return } process, err := os.FindProcess(pid) if err != nil { fmt.Printf("找不到进程 %d\n", pid) removePidFile() return } if runtime.GOOS == "windows" { err = process.Kill() } else { err = process.Signal(syscall.SIGTERM) } if err != nil { fmt.Printf("停止失败: %v\n", err) return } fmt.Println("Agent 已停止") removePidFile() } func cmdStatus() { pid := readPidFile() if pid == 0 { fmt.Println("状态: 未运行") return } if !isProcessRunning(pid) { fmt.Println("状态: 未运行") removePidFile() return } fmt.Printf("状态: 运行中 (PID: %d)\n", pid) } func isProcessRunning(pid int) bool { process, err := os.FindProcess(pid) if err != nil { return false } // Unix 系统发送信号 0 检查进程 if runtime.GOOS != "windows" { err = process.Signal(syscall.Signal(0)) return err == nil } // Windows 下 FindProcess 成功即表示进程存在 return true } func cmdInstall() { exePath, _ := os.Executable() exeDir := filepath.Dir(exePath) if runtime.GOOS == "windows" { installWindows(exePath, exeDir) } else { installLinux(exePath, exeDir) } } func cmdUninstall() { if runtime.GOOS == "windows" { uninstallWindows() } else { uninstallLinux() } } // ========== Linux systemd ========== func installLinux(exePath, exeDir string) { serviceContent := fmt.Sprintf(`[Unit] Description=%s After=network.target [Service] Type=simple WorkingDirectory=%s ExecStart=%s run Restart=always RestartSec=5 [Install] WantedBy=multi-user.target `, ServiceDesc, exeDir, exePath) servicePath := fmt.Sprintf("/etc/systemd/system/%s.service", ServiceName) if err := os.WriteFile(servicePath, []byte(serviceContent), 0644); err != nil { fmt.Printf("创建服务文件失败: %v\n", err) fmt.Println("请使用 sudo 运行") return } // 重载 systemd exec.Command("systemctl", "daemon-reload").Run() exec.Command("systemctl", "enable", ServiceName).Run() fmt.Printf("服务已安装: %s\n", servicePath) fmt.Println("使用以下命令管理服务:") fmt.Printf(" 启动: sudo systemctl start %s\n", ServiceName) fmt.Printf(" 停止: sudo systemctl stop %s\n", ServiceName) fmt.Printf(" 状态: sudo systemctl status %s\n", ServiceName) } func uninstallLinux() { // 停止服务 exec.Command("systemctl", "stop", ServiceName).Run() exec.Command("systemctl", "disable", ServiceName).Run() servicePath := fmt.Sprintf("/etc/systemd/system/%s.service", ServiceName) if err := os.Remove(servicePath); err != nil { fmt.Printf("删除服务文件失败: %v\n", err) fmt.Println("请使用 sudo 运行") return } exec.Command("systemctl", "daemon-reload").Run() fmt.Println("服务已卸载") } // ========== Windows 服务 ========== func installWindows(exePath, exeDir string) { // 使用 sc.exe 创建服务 cmd := exec.Command("sc", "create", ServiceName, "binPath=", fmt.Sprintf(`"%s" run`, exePath), "start=", "auto", "DisplayName=", ServiceDesc) if err := cmd.Run(); err != nil { fmt.Printf("创建服务失败: %v\n", err) fmt.Println("请以管理员身份运行") return } // 设置服务描述 exec.Command("sc", "description", ServiceName, ServiceDesc).Run() fmt.Println("服务已安装") fmt.Println("使用以下命令管理服务:") fmt.Printf(" 启动: sc start %s\n", ServiceName) fmt.Printf(" 停止: sc stop %s\n", ServiceName) fmt.Printf(" 状态: sc query %s\n", ServiceName) } func uninstallWindows() { // 停止服务 exec.Command("sc", "stop", ServiceName).Run() // 删除服务 cmd := exec.Command("sc", "delete", ServiceName) if err := cmd.Run(); err != nil { fmt.Printf("删除服务失败: %v\n", err) fmt.Println("请以管理员身份运行") return } fmt.Println("服务已卸载") }