package src import ( "log" "net" "os" "os/exec" "path" "path/filepath" "strconv" "syscall" ) var stdout *os.File var stderr *os.File // Start 启动/* func Start() { initLog() log.Println("Run Acme Mana...") args := os.Args if len(args) <= 1 { daemonStart() return } command := args[1] switch command { case "start": daemonStart() case "stop": daemonStop() case "status": daemonStatus() case "-s": daemonCommand() default: log.Fatalf("Unknown command: %s", command) } } /* 初始化日志文件 */ func initLog() { pwd, err := os.Getwd() if err != nil { log.Fatalf("Failed to get current working directory: %v", err) } dir := path.Join(pwd, "log") _, err = os.Stat(dir) if os.IsNotExist(err) { err := os.Mkdir(dir, 0777) if err != nil { log.Fatalf("Failed to create directory: %v", err) } } outFile, err := os.OpenFile(path.Join(dir, "out.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) defer outFile.Close() stdout = outFile errFile, err := os.OpenFile(path.Join(dir, "err.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) defer stderr.Close() stderr = errFile } /* 守护进程启动 */ func daemonStart() { isDaemon := os.Getenv("GO_DAEMON") log.Println("Run Daemon, DAEMON Is " + isDaemon) if isDaemon != "1" { // 直接启动 if isRunning() { log.Println("Daemon is already running.") return } path, err := os.Executable() if err != nil { log.Fatalf("Failed to get executable path: %v", err) } cmd := exec.Cmd{ Path: path, Args: os.Args, Dir: filepath.Dir(path), Env: append(os.Environ(), "GO_DAEMON=1"), //Stdin: os.Stdin, Stdout: stdout, Stderr: stderr, //Stdin: os.Stdin, //Stdout: os.Stdout, //Stderr: os.Stderr, SysProcAttr: &syscall.SysProcAttr{}, } //cmd := exec.Command(os.Args[0]) //cmd.Env = append(os.Environ(), "GO_DAEMON=1") //cmd.Stdout = os.Stdout //cmd.Stderr = os.Stderr //cmd.SysProcAttr = &syscall.SysProcAttr{} log.Println("Starting daemon...") log.Println(cmd) err = cmd.Start() if err != nil { log.Fatalf("Failed to start daemon: %v", err) } err = os.WriteFile(PidFile, []byte(strconv.Itoa(cmd.Process.Pid)), 0644) if err != nil { log.Fatalf("Failed to write PID file: %v", err) } log.Printf("Daemon started with PID: %d", cmd.Process.Pid) os.Exit(0) } else { // 子进程 doTask() } } /* 守护进程停止 */ func daemonStop() { //pid, err := readPID() //if err != nil { // log.Fatalf("Failed to stop daemon: %v", err) //} // //process, err := os.FindProcess(pid) //if err != nil { // log.Fatalf("Failed to find process: %v", err) //} // //err = process.Signal(syscall.SIGTERM) //if err != nil { // log.Fatalf("Failed to stop process: %v", err) //} // //os.Remove(PidFile) //os.Remove(SocketFile) //log.Println("Daemon stopped.") sendCommand("stop") } /* 守护进程状态 */ func daemonStatus() { if isRunning() { log.Println("Daemon is running.") } else { log.Println("Daemon is not running.") } } /* 守护进程接收名称 */ func daemonCommand() { log.Println("Sending command...") //pid, err := readPID() //if err != nil { // log.Fatalf("Failed to send command: %v", err) //} // //_, err = os.FindProcess(pid) //if err != nil { // log.Fatalf("Failed to find process: %v", err) //} //if len(os.Args) < 3 { // log.Fatalf("No command specified") //} command := os.Args[2] sendCommand(command) } /* 发送命令 */ func sendCommand(command string) { conn, err := net.Dial("unix", SocketFile) if err != nil { log.Fatalf("Failed to connect to daemon: %v", err) } defer func(conn net.Conn) { err := conn.Close() if err != nil { log.Fatalf("Failed to close connection: %v", err) } }(conn) _, err = conn.Write([]byte(command)) if err != nil { log.Fatalf("Failed to send command: %v", err) } log.Printf("Sending command '%s' to daemon with PID: %d", command, 0) } /* * 业务进程执行任务 */ func doTask() { // 示例:每隔10秒打印一条日志 //for { // log.Println("Daemon is running...") // time.Sleep(10 * time.Second) //} // 监听主进程下发的指令 go InitSocket() // 监听HTTP请求 go InitHttpServer("0.0.0.0", 10000) // 自动执行域名证书更新 go AutoRefreshCert() // 阻止退出 select {} } /* * 是否已启动 */ func isRunning() bool { log.Println("Checking if daemon is running...") pid, err := readPID() if err != nil { return false } process, err := os.FindProcess(pid) log.Println("Found process:", process) if err != nil { log.Println("Failed to find process:", err) return false } return true //err = process.Signal(syscall.Signal(0)) //log.Println("Signal result:", err) //return err == nil } /* * 读取PID文件 */ func readPID() (int, error) { log.Println("Reading PID file...") data, err := os.ReadFile(PidFile) if err != nil { log.Println("Failed to read PID file:", err) return 0, err } log.Println("PID file content:", string(data)) pid, err := strconv.Atoi(string(data)) if err != nil { log.Println("Failed to parse PID:", err) return 0, err } log.Println("PID:", pid) return pid, nil }