acme-mana/src/daemon.go
2024-10-14 17:00:25 +08:00

272 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}