A library for writing system daemons in golang.

Overview

go-daemon Build Status GoDoc

Library for writing system daemons in Go.

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/sevlyar/go-daemon

You can use gopkg.in:

go get gopkg.in/sevlyar/go-daemon.v0

If you want to use the library in production project, please use vendoring, because i can not ensure backward compatibility before release v1.0.

Examples

Documentation

godoc.org/github.com/sevlyar/go-daemon

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 setted - the library executes parent's operations and runs its own copy with mark, and if the mark is setted - the library executes child's operations:

func main() {
	Pre()

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

	if child != nil {
		PostParent()
	} else {
		defer context.Release()
		PostChild()
	}
}

Issues
  • install error

    install error

    Hello ,i am exec go get url ,then prompt follow message: github.com/sevlyar/go-daemon ../../../go/src/github.com/sevlyar/go-daemon/lock_file.go:53:9: undefined: lockFile ../../../go/src/github.com/sevlyar/go-daemon/lock_file.go:58:9: undefined: unlockFile ../../../go/src/github.com/sevlyar/go-daemon/lock_file.go:123:9: undefined: getFdName

    please ,help me ,thanks , runtime environment macos osx go 1.9

    opened by jokerbo1 5
  • go-daemon does not remove the pidfile on exit

    go-daemon does not remove the pidfile on exit

    go-daemon does not remove its pidfile even on a clean stop. This can be seen with the sample application. This is a bit odd as daemon-posix.go has:

    // Release provides correct pid-file release in daemon.
    func (d *Context) Release() (err error) {
        if !initialized {
            return
        }
        if d.pidFile != nil {
            err = d.pidFile.Remove()
        }
        return
    }
    

    and Release() is definitely being called, with d.PidFile non-null.

    I'm running OS-X, with today's master. Here's a demo. Note the file pid is not deleted.

    nimrod:sample amb$ go build
    nimrod:sample amb$ ./sample
    nimrod:sample amb$ ps -ef | fgrep sample
      501 22111     1   0  6:34pm ??         0:00.00 [go-daemon sample]
      501 22116 22094   0  6:34pm ttys021    0:00.00 fgrep sample
    nimrod:sample amb$ cat pid
    22111                                                         # linebreak inserted for ease of reading
    nimrod:sample amb$ ./sample -s stop
    nimrod:sample amb$ ps -ef | fgrep sample
      501 22123 22094   0  6:35pm ttys021    0:00.00 fgrep sample
    nimrod:sample amb$ cat pid
    22111                                                         # linebreak inserted for ease of reading
    nimrod:sample amb$
    
    bug darwin 
    opened by abligh 4
  • What this?

    What this?

    Try to get from github:

    D:\Go\src\inframe>go get github.com/sevlyar/go-daemon
    # github.com/sevlyar/go-daemon
    ..\github.com\sevlyar\go-daemon\daemon_posix.go:51: undefined: syscall.Credential
    
    opened by kolkov 4
  • Is there a new version release plan?

    Is there a new version release plan?

    Hey, we want a stable and suitable version that can be used in the production environment. But I found that it has been a long time since the last version was released(v0.1.5). Will the project be continuously updated with new versions? Is there a new version release plan?

    opened by LilyAndLily 3
  • Added power support for the travis.yml file with ppc64le. and update go versions for package: go-daemon

    Added power support for the travis.yml file with ppc64le. and update go versions for package: go-daemon

    Added power support for the travis.yml file with ppc64le. This is part of the Ubuntu distribution for ppc64le. This helps us simplify testing later when distributions are re-building and re-releasing.

    updated the go version go:1.12, 1.13 and 1.14

    opened by sreekanth370 3
  • Added Support for Illumos via Fcntl

    Added Support for Illumos via Fcntl

    A simple patch to add support for illumos/solaris11 based Distributions. Long story short there is not flock on those systems. We use Fcntl.

    For a detailed explanation from a seasoned engineer look at https://www.perkin.org.uk/posts/solaris-portability-flock.html

    opened by Toasterson 3
  • go-daemon requires cgo on darwin/macOS

    go-daemon requires cgo on darwin/macOS

    I use go-daemon in rclone and it works very well - thanks!

    However I normally cross compile all the binaries. This means I can't support go-daemon on darwin/macOS because it requires cgo.

    This is the only place I found which uses cgo

    https://github.com/sevlyar/go-daemon/blob/32749a731f76154d29bc6a547e6585f320eb235e/lock_file_darwin.go#L10

    And it looks like it might be reasonably easy to remove as all it is used for is to manipulate C strings.

    If you agree, I'd be happy to send a PR to remove the dependency on cgo.

    This would mean I could bring the --daemon flag to macOS which will make my users happy!

    opened by ncw 3
  • daily log rotation (by midnight)

    daily log rotation (by midnight)

    Hi sevlyar

    I've tried the library and its work perfectly.

    I just wondering. Did you have try to do go-daemon on daily log rotation (rotated at midnight)?

     func setupLog() {
            lf, err := NewLogFile(logFileName, os.Stderr)
    	if err != nil {
    		log.Fatal("Unable to create log file: ", err)
    	}
    	log.SetOutput(lf)
    	// rotate log every 30 seconds.
    	rotateLogSignal := time.Tick(30 * time.Second)
    	go func() {
    		for {
    			<-rotateLogSignal
    			if err := lf.Rotate(); err != nil {
    				log.Fatal("Unable to rotate log: ", err)
    			}
    		}
    	}()
    }
    

    Kindly advice.

    opened by mSufi 3
  • generates a blank pid file on Mac (Darwin)

    generates a blank pid file on Mac (Darwin)

    package main
    
    import (
    	"fmt"
    	"github.com/sevlyar/go-daemon"
    	"html"
    	"log"
    	"net/http"
    	"os"
    )
    
    // To terminate the daemon use:
    //  kill `cat pid`
    func main()  {
    
    	fmt.Println(os.Args[1])
    	if os.Args[1] == "test" {
    		test("hello,world")
    	}
    	if os.Args[1] == "hello" {
    		serveHttp()
    	}
    
    }
    
    func test(t string) {
    	cntxt := &daemon.Context{
    		PidFileName: "pid",
    		PidFilePerm: 0644,
    		LogFileName: "log",
    		LogFilePerm: 0640,
    		WorkDir:     "./test2/",
    		Umask:       027,
    		Args:        []string{"[go-daemon sample]", "hello"},
    	}
    
    	d, err := cntxt.Reborn()
    	if err != nil {
    		log.Fatal("Unable to run: ", err)
    	}
    	if d != nil {
    		return
    	}
    	defer cntxt.Release()
    
    	log.Print("- - - - - - - - - - - - - - -")
    	log.Print("daemon started")
    
    	log.Print(t)
    }
    
    func serveHttp() {
    
    	log.Print("testing!")
    	http.HandleFunc("/", httpHandler)
    	http.ListenAndServe("127.0.0.1:3080", nil)
    }
    
    func httpHandler(w http.ResponseWriter, r *http.Request) {
    	log.Printf("request from %s: %s %q", r.RemoteAddr, r.Method, r.URL)
    	fmt.Fprintf(w, "go-daemon: %q", html.EscapeString(r.URL.Path))
    }
    

    it just saves a blank PID file...Nope..Nothing on it...No PIDs

    opened by Shashwatsh 3
  • Reload flag

    Reload flag

    I run go-daemon on FreeBSD and I don't know if the reload flag is not implemented or I'm ignorant of how to use it (I'm rookie). I add a function that writes in file: func Writer()

    func Worker() {
          for {
                go Writer()
                if _, ok := <-stop; ok {
                      break
                }
          }
    }
    

    If I type go-daemon -s reload It does nothing, so i'm sure that I don't know how it works... How can I reload the functions into func Worker()?

    Thank you!

    opened by icarbajovallejo 3
  • Fix search. Now it will only return a daemon pointer if it is live

    Fix search. Now it will only return a daemon pointer if it is live

    Fix Search of Unix systems. According to the docs for os.FindProcess(pid) this will never be nil even when I process doesn't exist.

    On Unix systems, FindProcess always succeeds and returns a Process for the given pid, regardless of whether the process exists.

    opened by stew3254 2
  • error message EOF

    error message EOF

    ctx := &daemon.Context{}
    d, err := ctx.Reborn()
    if err != nil {
    	// When I use exec.Command to execute the sh script and the sh script starts this program, the error prompts EOF
    	return
    }
    if d != nil {
    	return
    }
    defer ctx.Release()
    
    opened by zmhuanf 2
  • Not working with Linux systemd

    Not working with Linux systemd

    [Unit] Description=Golang HTTP Server After=network-online.target remote-fs.target nss-lookup.target Wants=network-online.target

    [Service] Type=forking PIDFile=/home/sample.pid ExecStart=/home/daemon/go-test ExecReload=/home/daemon/go-test -s reload ExecStop=/home/daemon/go-test -s stop

    KillMode=none PrivateTmp=false Restart=on-failure RestartSec=5

    CPUAccounting=false TasksAccounting=false MemoryAccounting=false

    [Install] WantedBy=multi-user.target Alias=gotest.service

    opened by zesle 1
  • enable setting pgid

    enable setting pgid

    After reborn, the new process get pgid the same as it's process id by default. I need to be able to customize the pgid so that I could kill it nicely since the reborn process becomes an orphan process.

    By the way, directly calling to syscall.Setpgid would fail: operation not permitted

    pgid, _ := syscall.Getpgid(os.Getpid())
    cntxt := &daemon.Context{
    	Umask: 027,
    	Env:   append(os.Environ(), "PGID="+strconv.Itoa(pgid)),
    }
    
    d, _ := cntxt.Reborn()
    defer cntxt.Release()
    
    for _, k := range os.Environ() {
            if strings.HasPrefix(k, "PGID=") {
    	        pgid, _ := strconv.Atoi(strings.Split(k, "=")[1])
    	        if err := syscall.Setpgid(os.Getpid(), pgid); err != nil {
    		        panic("fail to set pgid")
    	        }
            }
    }
    

    I'm wondering if there is any way to achieve what I need?

    opened by chensk 0
  • Doesn't work on macOS

    Doesn't work on macOS

    the sample doesn't work on my machine (macOS 11) – the process exits immediately – the pidfile exists for a few milliseconds and then is deleted.

    some info that might help:

    $ go version
    go version go1.16.5 darwin/amd64
    $ uname -a
    Darwin Barteks-MacBook-Pro.local 20.5.0 Darwin Kernel Version 20.5.0: Sat May  8 05:10:33 PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64
    
    opened by bartekpacia 3
  • daemon.Search() doesn't actually confirm if a PID is alive on UNIX* systems

    daemon.Search() doesn't actually confirm if a PID is alive on UNIX* systems

    I noticed that the search function doesn't actually test whether a process is alive or not. According to the docs for os.FindProcess(pid) this will never be nil on Unix systems even when a process doesn't exist.

    On Unix systems, FindProcess always succeeds and returns a Process for the given pid, regardless of whether the process exists.

    This was giving me issues on my Linux machine without this patch, so I have submitted a pull request to fix this. It complains I've not hit some checks or something. I've never submitted a PR to an open source project on any repository ever, so my apologies that I don't know what I am doing for that.

    New search code for daemon_unix.go

    func (d *Context) search() (daemon *os.Process, err error) {
    	if len(d.PidFileName) > 0 {
    		var pid int
    		if pid, err = ReadPidFile(d.PidFileName); err != nil {
    			return
    		}
    		daemon, err = os.FindProcess(pid)
    		if err == nil && daemon != nil {
    			// Truly check on Unix systems that the daemon is running
    			// Daemon is not actually running if an error is received
    			if daemon.Signal(syscall.Signal(0)) != nil {
    				daemon = nil
    			}
    		}
    	}
    	return
    }
    
    opened by stew3254 1
Releases(v0.1.6)
  • v0.1.6(Jul 8, 2022)

    What's Changed

    • Add support for riscv64 on Linux by @Civil in https://github.com/sevlyar/go-daemon/pull/75
    • Remove "darwin/386" pair as it has been obsoleted in Go 1.15 by @eclipseo in https://github.com/sevlyar/go-daemon/pull/69
    • Return error on pid-file release failure by @sergeyklay in https://github.com/sevlyar/go-daemon/pull/62
    • Fix search. Now it will only return a daemon pointer if it is live by @stew3254 in https://github.com/sevlyar/go-daemon/pull/72
    • /dev/stdout & /dev/stderr as LogFileName by @ochinchina in https://github.com/sevlyar/go-daemon/pull/61
    • compatible with new build tags by @tylitianrui in https://github.com/sevlyar/go-daemon/pull/77
    • Fix buildtag for go1.7 introduced in #77 by @skozlov404 in https://github.com/sevlyar/go-daemon/pull/78

    New Contributors

    • @Civil made their first contribution in https://github.com/sevlyar/go-daemon/pull/75
    • @stew3254 made their first contribution in https://github.com/sevlyar/go-daemon/pull/72
    • @ochinchina made their first contribution in https://github.com/sevlyar/go-daemon/pull/61
    • @tylitianrui made their first contribution in https://github.com/sevlyar/go-daemon/pull/77
    • @skozlov404 made their first contribution in https://github.com/sevlyar/go-daemon/pull/78

    Full Changelog: https://github.com/sevlyar/go-daemon/compare/v0.1.5...v0.1.6

    Source code(tar.gz)
    Source code(zip)
  • v0.1.5(May 4, 2019)

  • v0.1.4(Aug 19, 2018)

  • v0.1.3(Mar 5, 2018)

  • v0.1.2(Dec 12, 2017)

  • v0.1.1(May 18, 2017)

    • Fix compilation on Windows #13;
    • Fix removing of PID-file on Darwin #17;
    • Fix removing of PID-file with a long name on Linux #16;
    • Fix race on PID-file creation #18.
    Source code(tar.gz)
    Source code(zip)
Owner
Sergey Yarmonov
Sergey Yarmonov
Go simple progress bar writing to output

?? progress-go Go simple progress bar writing to output ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free to send pull requests! Have

Rafał Lorenz 53 Jun 11, 2022
remindme is a simple application to set reminders from the CLI that integrates with your system's notification system.

remindme remindme is a simple application to set reminders from the CLI that integrates with your system's notification system. Examples Once the serv

Brian Downs 29 Jan 1, 2022
Jsos - A operating system that runs system-level javascript, based on the Linux kernel

JsOS ?? An linux-based operating system that runs Javascript code at the system-

Theo Paris 1 Mar 8, 2022
Command Line Alias Manager and Plugin System - Written in Golang

aly - Command Line Alias Manager and Packager Aly offers the simplest way to manage, share, and obtain command line aliases! Warning: This project is

Max Bridgland 21 Jun 16, 2022
🔹 Golang module to move the terminal cursor in any direction on every operating system.

AtomicGo | cursor Get The Module | Documentation | Contributing | Code of Conduct Description Package cursor contains cross-platform methods to move t

AtomicGo 45 Jul 25, 2022
A personal knowledge management and sharing system for VSCode

Foam ?? This is an early stage project under rapid development. For updates join the Foam community Discord! ?? Foam is a personal knowledge managemen

Foam 12.4k Aug 4, 2022
Procmon is a Linux reimagining of the classic Procmon tool from the Sysinternals suite of tools for Windows. Procmon provides a convenient and efficient way for Linux developers to trace the syscall activity on the system.

Process Monitor for Linux (Preview) Process Monitor (Procmon) is a Linux reimagining of the classic Procmon tool from the Sysinternals suite of tools

Windows Sysinternals 3.3k Jul 27, 2022
A client for managing authzed or any API-compatible system from your command line.

zed A client for managing authzed or any API-compatible system from your command line. Installation zed is currently packaged by as a head-only Homebr

authzed 43 Jul 29, 2022
An Alfred Workflow for the Johnny.Decimal filing system

alfred-jd An Alfred Workflow for the Johnny.Decimal filing system This workflow provides tools for working with the brilliant Johnny.Decimal filing sy

bsag 23 Aug 3, 2022
Libraries and CLIs for my personal all-in-one productivity system including components like bookmarks, notes, todos, projects, etc.

bntp.go Libraries and CLIs for my personal all-in-one productivity system including components like bookmarks, notes, todos, projects, etc. Neovim int

Jonas Mühlmann 11 Apr 29, 2022
go-shellcommand is the package providing the function System like the one of the programming language C.

go-shellcommand go-shellcommand is the package providing the function System like the one of the programming language C. process, err := shellcommand.

zetamatta 1 Oct 17, 2021
🐘 Cross-platform, neofetch alternative for fetching system info.

elefetch ?? Cross-platform, neofetch alternative for fetching system info. Installation go get: go get -u github.com/burntcarrot/elefetch Binaries Bin

Aadhav Vignesh 1 Jan 23, 2022
Virtualization system for remote code execution.

Delta CLI Command line application for executing source code inside of a container. Build: go build -o ./delta-cli ./main.go Usage: ./delta-cli <path

null 1 Nov 20, 2021
🖼️ A command-line system information tool written in bash 3.2+

A command-line system information tool written in bash 3.2+ Neofetch is a command-line system information tool written in bash 3.2+. Neofetch displays

dylan 15.8k Aug 7, 2022
Gofetch is a pretty command-line "Go and System information" tool written in Go

GoFetch Show off your Go information with this cool command-line tool! Report Bug || Request Feature Table of Contents About the Project Built With Ge

null 75 May 31, 2022
CLI Tool for System Administration

CLI CLI Tool for System Administration Description CLI was developed by Heiko for internal purposes for reoccuring actions The aim is to provide syste

Heiko 1 Dec 13, 2021
Green: a distribute key value system for optimize block chain data

Introduce Green is a distribute key value system for optimize block chain data A

null 0 Jan 6, 2022
StudentMgmtSystem - Project for Student Management System and use of CURD Operation

StudentMgmtSystem Project for Student Management System and use of CURD Operatio

null 0 Jan 4, 2022
A CLI tool to find the absolute path of any folder in your local file system.

Table of Contents What is this? How to use this Examples of usage How to compile it What am I looking at It's a CLI tool that I made for finding the a

Benyakir Horowitz 0 Jan 15, 2022