Skip to content

Commit

Permalink
Merge branch 'release/0.9.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
takama committed Oct 29, 2017
2 parents b049d01 + 2bb864f commit f30a97d
Showing 1 changed file with 125 additions and 123 deletions.
248 changes: 125 additions & 123 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,182 +1,182 @@
Go Daemon
=========
# Go Daemon

A daemon package for use with Go (golang) services with no dependencies

[![GoDoc](https://godoc.org/github.com/takama/daemon?status.svg)](https://godoc.org/github.com/takama/daemon)

### Examples
## Examples

### Simplest example (just install self as daemon)

Simplest example (just install self as daemon):
```go
package main

import (
"fmt"
"log"
"fmt"
"log"

"github.com/takama/daemon"
"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)
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)
}
```

Real example:
### Real example

```go
// Example of a daemon with echo service
package main

import (
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"

"github.com/takama/daemon"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"

"github.com/takama/daemon"
)

const (

// name of the service
name = "myservice"
description = "My Echo Service"
// name of the service
name = "myservice"
description = "My Echo Service"

// port which daemon should be listen
port = ":9977"
// port which daemon should be listen
port = ":9977"
)

// dependencies that are NOT required by the service, but might be used
// dependencies that are NOT required by the service, but might be used
var dependencies = []string{"dummy.service"}

var stdlog, errlog *log.Logger

// Service has embedded daemon
type Service struct {
daemon.Daemon
daemon.Daemon
}

// Manage by daemon commands or run the daemon
func (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:
stdlog.Println("Got signal:", killSignal)
stdlog.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
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:
stdlog.Println("Got signal:", killSignal)
stdlog.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 channel
func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
for {
conn, err := listener.Accept()
if err != nil {
continue
}
listen <- 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[:numbytes])
}
for {
buf := make([]byte, 4096)
numbytes, err := client.Read(buf)
if numbytes == 0 || err != nil {
return
}
client.Write(buf[:numbytes])
}
}

func init() {
stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
}

func main() {
srv, err := daemon.New(name, description, dependencies...)
if err != nil {
errlog.Println("Error: ", err)
os.Exit(1)
}
service := &Service{srv}
status, err := service.Manage()
if err != nil {
errlog.Println(status, "\nError: ", err)
os.Exit(1)
}
fmt.Println(status)
srv, err := daemon.New(name, description, dependencies...)
if err != nil {
errlog.Println("Error: ", err)
os.Exit(1)
}
service := &Service{srv}
status, err := service.Manage()
if err != nil {
errlog.Println(status, "\nError: ", err)
os.Exit(1)
}
fmt.Println(status)
}
```

Cron example:
```
See example/cron_example.go
```
### Cron example

See `examples/cron/cron_job.go`

## Contributors (unsorted)

Expand All @@ -196,8 +196,10 @@ See example/cron_example.go
- [1for](https://github.com/1for)
- [okamura](https://github.com/sidepelican)
- [0X8C - Demired](https://github.com/Demired)
- [Maximus](https://github.com/maximus12793)

All the contributors are welcome. If you would like to be the contributor please accept some rules.

- The pull requests will be accepted only in "develop" branch
- All modifications or additions should be tested
- Sorry, We will not accept code with any dependency, only standard library
Expand Down

0 comments on commit f30a97d

Please sign in to comment.