GO daemon -


MIT
跨平台
Google Go

软件简介

daemon 是没有任何依赖的 Go(golang)服务守护进程包。

示例

简单示例 (just install self as daemon):

package mainimport (
    "fmt"
    "log"

    "github.com/takama/daemon")func main() {
    service, err := daemon.New("name", "description")
    if err != nil {
        log.Fatal("Error: ", err)
    }
    status, err := service.Install()
    if err != nil {
        log.Fatal(status, "\nError: ", err)
    }
    fmt.Println(status)}

实际示例:

// Example of the daemon with echo servicepackage mainimport (
    "fmt"
    "log"
    "net"
    "os"
    "os/signal"
    "syscall"

    "github.com/takama/daemon")const (

    // name of the service, match with executable file name
    name        = "myservice"
    description = "My Echo Service"

    // port which daemon should be listen
    port = ":9977")// Service has embedded daemontype Service struct {
    daemon.Daemon}// Manage by daemon commands or run the daemonfunc (service *Service) Manage() (string, error) {

    usage := "Usage: myservice install | remove | start | stop | status"

    // if received any kind of command, do it
    if len(os.Args) > 1 {
        command := os.Args[1]
        switch command {
        case "install":
            return service.Install()
        case "remove":
            return service.Remove()
        case "start":
            return service.Start()
        case "stop":
            return service.Stop()
        case "status":
            return service.Status()
        default:
            return usage, nil
        }
    }

    // Do something, call your goroutines, etc

    // Set up channel on which to send signal notifications.
    // We must use a buffered channel or risk missing the signal
    // if we're not ready to receive when the signal is sent.
    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

    // Set up listener for defined host and port
    listener, err := net.Listen("tcp", port)
    if err != nil {
        return "Possibly was a problem with the port binding", err
    }

    // set up channel on which to send accepted connections
    listen := make(chan net.Conn, 100)
    go acceptConnection(listener, listen)

    // loop work cycle with accept connections or interrupt
    // by system signal
    for {
        select {
        case conn := <-listen:
            go handleClient(conn)
        case killSignal := <-interrupt:
            log.Println("Got signal:", killSignal)
            log.Println("Stoping listening on ", listener.Addr())
            listener.Close()
            if killSignal == os.Interrupt {
                return "Daemon was interruped by system signal", nil
            }
            return "Daemon was killed", nil
        }
    }

    // never happen, but need to complete code
    return usage, nil}// Accept a client connection and collect it in a channelfunc acceptConnection(listener net.Listener, listen chan<- net.Conn) {
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        listen <- conn
    }}func handleClient(client net.Conn) {
    for {
        buf := make([]byte, 4096)
        numbytes, err := client.Read(buf)
        if numbytes == 0 || err != nil {
            return
        }
        client.Write(buf)
    }}func main() {
    srv, err := daemon.New(name, description)
    if err != nil {
        fmt.Println("Error: ", err)
        os.Exit(1)
    }
    service := &Service{srv}
    status, err := service.Manage()
    if err != nil {
        fmt.Println(status, "\nError: ", err)
        os.Exit(1)
    }
    fmt.Println(status)}