diff --git a/godaemon.go b/godaemon.go index aac199f..bfe2d59 100644 --- a/godaemon.go +++ b/godaemon.go @@ -1,3 +1,5 @@ +// Package godaemon provides a simple daemon library for Go applications. +// It allows applications to run as daemon processes with start/stop/restart capabilities. package godaemon import ( @@ -14,26 +16,32 @@ import ( "git.kingecg.top/kingecg/gologger" ) +// Constants defining environment variable keys and values used for process identification const ( - daemon_env_key = "_go_daemon" - daemon_process = "g_daemon" - daemon_task = "g_dtask" - daemon_taskargs = "g_args" + daemon_env_key = "_go_daemon" // Environment variable key for process role identification + daemon_process = "g_daemon" // Value indicating daemon process role + daemon_task = "g_dtask" // Value indicating task process role + daemon_taskargs = "g_args" // Environment variable key for storing task arguments ) +// GoDaemon represents a daemon process manager type GoDaemon struct { - pidFile string - taskPidFile string - flag *string - sigChan chan os.Signal - state string - *gologger.Logger - Running *exec.Cmd + pidFile string // Path to file storing daemon process PID + taskPidFile string // Path to file storing task process PID + flag *string // Command line flag for signal control + sigChan chan os.Signal // Channel for receiving OS signals + state string // Current state of the daemon ("running", "stopped", etc.) + *gologger.Logger // Embedded logger for logging + Running *exec.Cmd // Currently running task process - StartFn func(*GoDaemon) - StopFn func(*GoDaemon) + StartFn func(*GoDaemon) // Function called when task starts + StopFn func(*GoDaemon) // Function called when task stops } +// GetPid retrieves the daemon process ID from the PID file +// +// Returns: +// - int: process ID if found and valid, 0 otherwise func (g *GoDaemon) GetPid() int { pids, ferr := os.ReadFile(g.pidFile) pid, err := strconv.Atoi(string(pids)) @@ -42,6 +50,11 @@ func (g *GoDaemon) GetPid() int { } return pid } + +// GetTaskPid retrieves the task process ID from the task PID file +// +// Returns: +// - int: process ID if found and valid, 0 otherwise func (g *GoDaemon) GetTaskPid() int { pids, ferr := os.ReadFile(g.taskPidFile) pid, err := strconv.Atoi(string(pids)) @@ -51,6 +64,12 @@ func (g *GoDaemon) GetTaskPid() int { return pid } +// Start begins the daemon process management based on the current process role +// +// Behavior depends on process role: +// - Master: starts the daemon process or sends signals to running daemon +// - Daemon: manages task process lifecycle +// - Task: executes the user-provided StartFn func (g *GoDaemon) Start() { if g.flag == nil { g.flag = flag.String("s", "", "send signal to daemon. support: reload and quit") @@ -111,6 +130,11 @@ func (g *GoDaemon) Start() { } } +// serveSignal handles incoming OS signals for the daemon process +// +// Signals handled: +// - SIGTERM: stops the daemon +// - SIGHUP: restarts the task process func (g *GoDaemon) serveSignal() { sig := <-g.sigChan if sig == syscall.SIGTERM { @@ -122,6 +146,10 @@ func (g *GoDaemon) serveSignal() { g.Running.Process.Signal(syscall.SIGTERM) } +// getDaemonProcess retrieves the daemon process instance if it's running +// +// Returns: +// - *os.Process: running daemon process if found, nil otherwise func (g *GoDaemon) getDaemonProcess() *os.Process { pid := g.GetPid() if pid == 0 { @@ -138,6 +166,9 @@ func (g *GoDaemon) getDaemonProcess() *os.Process { return p } +// startDaemon starts a new daemon process in the background +// +// Checks if daemon is already running before starting a new instance func (g *GoDaemon) startDaemon() { dp := g.getDaemonProcess() @@ -154,6 +185,10 @@ func (g *GoDaemon) startDaemon() { cmd.Start() } +// startTask starts a new task process with the configured arguments +// +// Returns: +// - *exec.Cmd: the started command representing the task process func (g *GoDaemon) startTask() *exec.Cmd { extraArgs, _ := os.LookupEnv(daemon_taskargs) var cmd *exec.Cmd @@ -170,21 +205,42 @@ func (g *GoDaemon) startTask() *exec.Cmd { cmd.Start() return cmd } + +// IsMaster checks if the current process is the master process +// +// Returns: +// - bool: true if this is the master process, false otherwise func IsMaster() bool { goDaemonEnv, _ := os.LookupEnv(daemon_env_key) return goDaemonEnv == "" } +// IsDaemon checks if the current process is the daemon process +// +// Returns: +// - bool: true if this is the daemon process, false otherwise func IsDaemon() bool { goDaemonEnv, _ := os.LookupEnv(daemon_env_key) return goDaemonEnv == daemon_process } +// IsDaemonTask checks if the current process is the task process +// +// Returns: +// - bool: true if this is the task process, false otherwise func IsDaemonTask() bool { goDaemonEnv, _ := os.LookupEnv(daemon_env_key) return goDaemonEnv == daemon_task } +// NewGoDaemon creates a new GoDaemon instance +// +// Parameters: +// - start: function to be called when the task process starts +// - stop: function to be called when the task process stops +// +// Returns: +// - *GoDaemon: initialized GoDaemon instance func NewGoDaemon(start, stop func(*GoDaemon)) *GoDaemon { godaemon := &GoDaemon{ Logger: gologger.GetLogger("daemon"),