gitee.com/quant1x/gox@v1.21.2/daemon/README.md (about)

     1  # Go Daemon
     2  
     3  A daemon package for use with Go (golang) services
     4  
     5  [![GoDoc](https://godoc.org/github.com/takama/daemon?status.svg)](https://godoc.org/github.com/takama/daemon)
     6  
     7  ## Examples
     8  
     9  ### Simplest example (just install self as daemon)
    10  
    11  ```go
    12  package main
    13  
    14  import (
    15      "fmt"
    16      "log"
    17  
    18      "github.com/takama/daemon"
    19  )
    20  
    21  func main() {
    22      service, err := daemon.New("name", "description", daemon.SystemDaemon)
    23      if err != nil {
    24          log.Fatal("Error: ", err)
    25      }
    26      status, err := service.Install()
    27      if err != nil {
    28          log.Fatal(status, "\nError: ", err)
    29      }
    30      fmt.Println(status)
    31  }
    32  ```
    33  
    34  ### Real example
    35  
    36  ```go
    37  // Example of a daemon with echo service
    38  package main
    39  
    40  import (
    41      "fmt"
    42      "log"
    43      "net"
    44      "os"
    45      "os/signal"
    46      "syscall"
    47  
    48      "github.com/takama/daemon"
    49  )
    50  
    51  const (
    52  
    53      // name of the service
    54      name        = "myservice"
    55      description = "My Echo Service"
    56  
    57      // port which daemon should be listen
    58      port = ":9977"
    59  )
    60  
    61  //    dependencies that are NOT required by the service, but might be used
    62  var dependencies = []string{"dummy.service"}
    63  
    64  var stdlog, errlog *log.Logger
    65  
    66  // Service has embedded daemon
    67  type Service struct {
    68      daemon.Daemon
    69  }
    70  
    71  // Manage by daemon commands or run the daemon
    72  func (service *Service) Manage() (string, error) {
    73  
    74      usage := "Usage: myservice install | remove | start | stop | status"
    75  
    76      // if received any kind of command, do it
    77      if len(os.Args) > 1 {
    78          command := os.Args[1]
    79          switch command {
    80          case "install":
    81              return service.Install()
    82          case "remove":
    83              return service.Remove()
    84          case "start":
    85              return service.Start()
    86          case "stop":
    87              return service.Stop()
    88          case "status":
    89              return service.Status()
    90          default:
    91              return usage, nil
    92          }
    93      }
    94  
    95      // Do something, call your goroutines, etc
    96  
    97      // Set up channel on which to send signal notifications.
    98      // We must use a buffered channel or risk missing the signal
    99      // if we're not ready to receive when the signal is sent.
   100      interrupt := make(chan os.Signal, 1)
   101      signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)
   102  
   103      // Set up listener for defined host and port
   104      listener, err := net.Listen("tcp", port)
   105      if err != nil {
   106          return "Possibly was a problem with the port binding", err
   107      }
   108  
   109      // set up channel on which to send accepted connections
   110      listen := make(chan net.Conn, 100)
   111      go acceptConnection(listener, listen)
   112  
   113      // loop work cycle with accept connections or interrupt
   114      // by system signal
   115      for {
   116          select {
   117          case conn := <-listen:
   118              go handleClient(conn)
   119          case killSignal := <-interrupt:
   120              stdlog.Println("Got signal:", killSignal)
   121              stdlog.Println("Stoping listening on ", listener.Addr())
   122              listener.Close()
   123              if killSignal == os.Interrupt {
   124                  return "Daemon was interruped by system signal", nil
   125              }
   126              return "Daemon was killed", nil
   127          }
   128      }
   129  
   130      // never happen, but need to complete code
   131      return usage, nil
   132  }
   133  
   134  // Accept a client connection and collect it in a channel
   135  func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
   136      for {
   137          conn, err := listener.Accept()
   138          if err != nil {
   139              continue
   140          }
   141          listen <- conn
   142      }
   143  }
   144  
   145  func handleClient(client net.Conn) {
   146      for {
   147          buf := make([]byte, 4096)
   148          numbytes, err := client.Read(buf)
   149          if numbytes == 0 || err != nil {
   150              return
   151          }
   152          client.Write(buf[:numbytes])
   153      }
   154  }
   155  
   156  func init() {
   157      stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
   158      errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
   159  }
   160  
   161  func main() {
   162      srv, err := daemon.New(name, description, daemon.SystemDaemon, dependencies...)
   163      if err != nil {
   164          errlog.Println("Error: ", err)
   165          os.Exit(1)
   166      }
   167      service := &Service{srv}
   168      status, err := service.Manage()
   169      if err != nil {
   170          errlog.Println(status, "\nError: ", err)
   171          os.Exit(1)
   172      }
   173      fmt.Println(status)
   174  }
   175  ```
   176  
   177  ### Service config file
   178  
   179  Optionally, service config file can be retrieved or updated by calling
   180  `GetTemplate() string` and `SetTemplate(string)` methods(except MS
   181  Windows). Template will be a default Go Template(`"text/template"`).
   182  
   183  If `SetTemplate` is not called, default template content will be used
   184  while creating service.
   185  
   186  | Variable     | Description                      |
   187  |--------------|----------------------------------|
   188  | Description  | Description for service          |
   189  | Dependencies | Service dependencies             |
   190  | Name         | Service name                     |
   191  | Path         | Path of service executable       |
   192  | Args         | Arguments for service executable |
   193  
   194  #### Example template(for linux systemv)
   195  
   196  ```ini
   197  [Unit]
   198  Description={{.Description}}
   199  Requires={{.Dependencies}}
   200  After={{.Dependencies}}
   201  
   202  [Service]
   203  PIDFile=/var/run/{{.Name}}.pid
   204  ExecStartPre=/bin/rm -f /var/run/{{.Name}}.pid
   205  ExecStart={{.Path}} {{.Args}}
   206  Restart=on-failure
   207  
   208  [Install]
   209  WantedBy=multi-user.target
   210  ```
   211  
   212  ### Cron example
   213  
   214  See `examples/cron/cron_job.go`
   215  
   216  ## Contributors (unsorted)
   217  
   218  - [Sheile](https://github.com/Sheile)
   219  - [Nguyen Trung Loi](https://github.com/loint)
   220  - [Donny Prasetyobudi](https://github.com/donnpebe)
   221  - [Mark Berner](https://github.com/mark2b)
   222  - [Fatih Kaya](https://github.com/fatihky)
   223  - [Jannick Fahlbusch](https://github.com/jannickfahlbusch)
   224  - [TobyZXJ](https://github.com/tobyzxj)
   225  - [Pichu Chen](https://github.com/PichuChen)
   226  - [Eric Halpern](https://github.com/ehalpern)
   227  - [Yota](https://github.com/nus)
   228  - [Erkan Durmus](https://github.com/derkan)
   229  - [maxxant](https://github.com/maxxant)
   230  - [1for](https://github.com/1for)
   231  - [okamura](https://github.com/sidepelican)
   232  - [0X8C - Demired](https://github.com/Demired)
   233  - [Maximus](https://github.com/maximus12793)
   234  - [AlgorathDev](https://github.com/AlgorathDev)
   235  - [Alexis Camilleri](https://github.com/krysennn)
   236  - [neverland4u](https://github.com/neverland4u)
   237  - [Rustam](https://github.com/rusq)
   238  - [King'ori Maina](https://github.com/itskingori)
   239  
   240  All the contributors are welcome. If you would like to be the contributor please accept some rules.
   241  
   242  - The pull requests will be accepted only in `develop` branch
   243  - All modifications or additions should be tested
   244  - Sorry, We will not accept code with any dependency, only standard library
   245  
   246  Thank you for your understanding!
   247  
   248  ## License
   249  
   250  [MIT Public License](https://github.com/takama/daemon/blob/master/LICENSE)