package main import ( "fmt" "log" "net" "os" "os/exec" "path" "path/filepath" "strconv" "syscall" ) func main() { //config := src.GetAppConfig() //fmt.Println(config) //src.Apply(config.Domains[0]) //fmt.Println(os.Getwd()) //err := os.MkdirAll("cert\\abc", 0777) //if err != nil { // fmt.Println(err) //} fmt.Println("start()") start() } const pidFile = "acme-mana.pid" const socketFile = "acme-mana.sock" var stdout *os.File var stderr *os.File 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) //} initSocket() } 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 } 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 } func initSocket() { // 删除旧的 socket 文件 if _, err := os.Stat(socketFile); err == nil { os.Remove(socketFile) } listener, err := net.Listen("unix", socketFile) if err != nil { log.Fatalf("Failed to listen on socket: %v", err) } defer listener.Close() for { log.Println("Waiting for connections...") conn, err := listener.Accept() if err != nil { log.Printf("Failed to accept connection: %v", err) continue } go handleConnection(conn) } } func handleConnection(conn net.Conn) { defer conn.Close() buf := make([]byte, 1024) n, err := conn.Read(buf) if err != nil { log.Printf("Failed to read command: %v", err) return } command := string(buf[:n]) log.Printf("Received command: %s", command) // 在这里处理接收到的命令 switch command { case "stop": onStop() default: onCommand(command) } } func onStop() { log.Println("Stopping daemon...") os.Remove(pidFile) log.Println("Remove PID File...") os.Remove(socketFile) log.Println("Remove Socket File...") os.Exit(0) } func onCommand(command string) { }