godaemon

package module
v0.0.0-...-2ff8816 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2024 License: MIT Imports: 11 Imported by: 3

README

go-daemon

Library for writing system daemons in Go. fork from go-daemon

Now supported only UNIX-based OS (Windows is not supported). But the library was tested only on Linux and OSX, so that if you have an ability to test the library on other platforms, give me feedback, please (#26).

Please, feel free to send me bug reports and fixes. Many thanks to all contributors.

Features

  • Goroutine-safe daemonization;
  • Out of box work with pid-files;
  • Easy handling of system signals;
  • The control of a daemon.

Installation

go get github.com/bingoohuang/godaemon@latest

Examples

package main

import (
	"github.com/bingoohuang/godaemon"
	flag "github.com/spf13/pflag"
)

func main() {
	daemon := flag.BoolP("daemon", "d", false, "run in daemonize mode")
	flag.Parse()
	godaemon.Daemonize(godaemon.WithDaemon(*daemon))

	// logic ...
}

package main

import (
	"log"
	"github.com/bingoohuang/godaemon"
)

func main() {
	// Pre()

	context := new(godaemon.Context)
	child, _ := context.Reborn()

	if child != nil {
		// PostParent()
	} else {
		defer func() {
			if err := context.Release(); err != nil {
				log.Printf("Unable to release pid-file: %s", err.Error())
			}
		}()

		// PostChild()
	}
}

How it works

We can not use fork syscall in Golang's runtime, because child process doesn't inherit threads and goroutines in that case. The library uses a simple trick: it runs its own copy with a mark - a predefined environment variable. Availability of the variable for the process means an execution in the child's copy. So that if the mark is not set - the library executes parent's operations and runs its own copy with mark, and if the mark is set - the library executes child's operations:

Sync logs

  • Commit: 9d78c85, Commits on Mar 21, 2023,2023年04月24日
  • Commit: f14d855, Commits on Feb 12, 2022,2022年09月07日

Documentation

Overview

Package godaemon help program to be deamonized.

Example
signal := flag.String("s", "", "send signal to daemon")

handler := func(sig os.Signal) error {
	log.Println("signal:", sig)
	if sig == syscall.SIGTERM {
		return ErrStop
	}
	return nil
}

// Define command: command-line arg, system signal and handler
AddCommand(StringFlag(signal, "term"), syscall.SIGTERM, handler)
AddCommand(StringFlag(signal, "reload"), syscall.SIGHUP, handler)
flag.Parse()

// Define daemon context
dmn := &Context{
	PidFileName: "/var/run/daemon.pid",
	PidFilePerm: 0o644,
	LogFileName: "/var/log/daemon.log",
	LogFilePerm: 0o640,
	WorkDir:     "/",
	Umask:       0o27,
}

// Send commands if needed
if len(ActiveFlags()) > 0 {
	d, err := dmn.Search()
	if err != nil {
		log.Fatalln("Unable send signal to the daemon:", err)
	}
	SendCommands(d)
	return
}

// Process daemon operations - send signal if present flag or daemonize
child, err := dmn.Reborn()
if err != nil {
	log.Fatalln(err)
}
if child != nil {
	return
}
defer dmn.Release()

// Run main operation
go func() {
	for {
		time.Sleep(0)
	}
}()

err = ServeSignals()
if err != nil {
	log.Println("Error:", err)
}
Output:

Index

Examples

Constants

View Source
const (
	MarkName  = "_GO_DAEMON"
	MarkValue = "1"
)

MarkName marks of daemon process - system environment variable _GO_DAEMON={pid}

View Source
const FilePerm = os.FileMode(0o640)

FilePerm is the default file permissions for log and pid files.

Variables

View Source
var ErrStop = errors.New("stop serve signals")

ErrStop should be returned signal handler function for termination of handling signals.

View Source
var ErrWouldBlock = errors.New("daemon: Resource temporarily unavailable")

ErrWouldBlock indicates on locking pid-file by another process.

Functions

func AddCommand

func AddCommand(f Flag, sig os.Signal, handler SignalHandlerFunc)

AddCommand is wrapper on AddFlag and SetSigHandler functions.

func AddFlag

func AddFlag(f Flag, sig os.Signal)

AddFlag adds the flag and signal to the internal map.

func ClearReborn

func ClearReborn() error

ClearReborn clear the reborn env.

func Daemonize

func Daemonize(optionFns ...OptionFn)

Daemonize set the current process daemonized

func Flags

func Flags() map[Flag]os.Signal

Flags returns flags that was added by the function AddFlag.

func ReadPidFile

func ReadPidFile(name string) (pid int, err error)

ReadPidFile reads process id from file with give name and returns pid. If unable read from a file, returns error.

func SendCommands

func SendCommands(p *os.Process) (err error)

SendCommands sends active signals to the given process.

func ServeSignals

func ServeSignals() (err error)

ServeSignals calls handlers for system signals.

func SetSigHandler

func SetSigHandler(handler SignalHandlerFunc, signals ...os.Signal)

SetSigHandler sets handler for the given signals. SIGTERM has the default handler, he returns ErrStop.

func WasReborn

func WasReborn() bool

WasReborn returns true in child process (daemon) and false in parent process.

Types

type Context

type Context struct {

	// Credential holds user and group identities to be assumed by a daemon-process.
	Credential *Credential

	// If WorkDir is non-empty, the child changes into the directory before
	// creating the process.
	WorkDir string
	// If PidFileName is non-empty, parent process will try to create and lock
	// pid file with given name. Child process writes process id to file.
	PidFileName string
	// If Chroot is non-empty, the child changes root directory
	Chroot string

	// If LogFileName is non-empty, parent process will create file with given name
	// and will link to fd 2 (stderr) for child process.
	LogFileName string

	// If Env is non-nil, it gives the environment variables for the
	// daemon-process in the form returned by os.Environ.
	// If it is nil, the result of os.Environ will be used.
	Env []string
	// If Args is non-nil, it gives the command-line args for the
	// daemon-process. If it is nil, the result of os.Args will be used.
	Args []string

	// If Umask is non-zero, the daemon-process call Umask() func with given value.
	Umask int

	// Permissions for new pid file.
	PidFilePerm os.FileMode

	// Permissions for new log file.
	LogFilePerm os.FileMode
	// contains filtered or unexported fields
}

A Context describes daemon context.

func (*Context) Clean

func (d *Context) Clean() error

func (*Context) Reborn

func (d *Context) Reborn() (child *os.Process, err error)

Reborn runs second copy of current process in the given context. function executes separate parts of code in child process and parent process and provides demonization of child process. It looks similar as the fork-daemonization, but goroutine-safe. In success returns *os.Process in parent process and nil in child process. Otherwise, returns error.

func (*Context) Release

func (d *Context) Release() error

Release provides correct pid-file release in daemon.

func (*Context) Search

func (d *Context) Search() (daemon *os.Process, err error)

Search searches daemons process by given in context pid file name. If success returns pointer on daemons os.Process structure, else returns error. Returns nil if filename is empty.

func (*Context) SetLogFile

func (d *Context) SetLogFile(fd *os.File)

SetLogFile set the log file.

type Credential

type Credential struct {
	Uid         uint32   // User ID.
	Gid         uint32   // Group ID.
	Groups      []uint32 // Supplementary group IDs.
	NoSetGroups bool     // If true, don't set supplementary groups
}

type Flag

type Flag interface {
	IsSet() bool
}

Flag is the interface implemented by an object that has two state: 'set' and 'unset'.

func ActiveFlags

func ActiveFlags() (ret []Flag)

ActiveFlags returns flags that has the state 'set'.

func BoolFlag

func BoolFlag(f *bool) Flag

BoolFlag returns new object that implements interface Flag and has state 'set' when var with the given address is true.

func StringFlag

func StringFlag(f *string, v string) Flag

StringFlag returns new object that implements interface Flag and has state 'set' when var with the given address equals given value of v.

type LockFile

type LockFile struct {
	*os.File
}

LockFile wraps *os.File and provide functions for locking of files.

func CreatePidFile

func CreatePidFile(name string, perm os.FileMode) (lock *LockFile, err error)

CreatePidFile opens the named file, applies exclusive lock and writes current process id to file.

func NewLockFile

func NewLockFile(file *os.File) *LockFile

NewLockFile returns a new LockFile with the given File.

func OpenLockFile

func OpenLockFile(name string, perm os.FileMode) (lock *LockFile, err error)

OpenLockFile opens the named file with flags os.O_RDWR|os.O_CREATE and specified perm. If successful, function returns LockFile for opened file.

func (*LockFile) Lock

func (file *LockFile) Lock() error

Lock apply exclusive lock on an open file. If file already locked, returns error.

func (*LockFile) ReadPid

func (file *LockFile) ReadPid() (pid int, err error)

ReadPid reads process id from file and returns pid. If unable read from a file, returns error.

func (*LockFile) Remove

func (file *LockFile) Remove() error

Remove removes lock, closes and removes an open file.

func (*LockFile) Unlock

func (file *LockFile) Unlock() error

Unlock remove exclusive lock on an open file.

func (*LockFile) WritePid

func (file *LockFile) WritePid() (err error)

WritePid writes current process id to an open file.

type Option

type Option struct {
	Daemon        bool
	Debug         bool
	LogFileName   string
	ParentProcess func(child *os.Process)
}

Option is options for Daemonize function.

type OptionFn

type OptionFn func(option *Option)

OptionFn is an option function prototype.

func WithDaemon

func WithDaemon(v bool) OptionFn

WithDaemon set the deamon flag.

func WithLogFileName

func WithLogFileName(v string) OptionFn

WithLogFileName set the log file name.

func WithParentProcess

func WithParentProcess(f func(child *os.Process)) OptionFn

WithParentProcess set the custom parent processor, if not set, the default is os.Exit(0)

type SignalHandlerFunc

type SignalHandlerFunc func(sig os.Signal) (err error)

SignalHandlerFunc is the interface for signal handler functions.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL