Skip to content

Commit

Permalink
Merge branch 'release-0.1.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
takama committed Aug 2, 2014
2 parents 6346ac6 + ef1e728 commit 82c53c9
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 22 deletions.
135 changes: 133 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ A daemon package for use with Go (golang) services

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

### Example
### Examples

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

Expand All @@ -30,11 +31,141 @@ func main() {
}
```

Real example:
```go
// Example of the daemon with echo service
package main

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

"github.com/takama/daemon"
)

const (

// name of the service, match with executable file name
name = "myservice"
description = "Some explanation of the service purpose"

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

type Service struct {
daemon.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:
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 channel
func 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)

}
```

## Author

[Igor Dolzhikov](https://github.com/takama)


## License

[MIT Public License](https://github.com/takama/daemon/blob/master/LICENSE)
82 changes: 77 additions & 5 deletions daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package daemon 0.1.0 for use with Go (golang) services.
// Package daemon 0.1.1 for use with Go (golang) services.
//
// Package daemon provides primitives for daemonization of golang services.
// This package is not provide implementation of user daemon,
Expand All @@ -11,24 +11,38 @@
//
// Example:
//
// //Example of the daemon with echo service
// package main
//
// import (
// "fmt"
// "fmt"
// "log"
// "net"
// "os"
// "os/signal"
// "syscall"
//
// "github.com/takama/daemon"
// )
//
// const (
//
// // name of the service, match with executable file name
// name = "myservice"
// description = "Some explanation of the service purpose"
// description = ""My Echo Service"
//
// // port which daemon should be listen
// port = ":9977"
// )
//
// type Service struct {
// daemon.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]
Expand All @@ -43,12 +57,70 @@
// return service.Stop()
// case "status":
// return service.Status()
// default:
// return usage, nil
// }
// }
//
// // Do something, call your goroutines, etc
//
// return "Usage: myservice install | remove | start | stop | status", nil
// // 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 channel
// func 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() {
Expand Down Expand Up @@ -103,7 +175,7 @@ type Daemon interface {

// New - Create a new daemon
//
// name: name ot the service, must be match with executable file name;
// name: name of the service, match with executable file name;
// description: any explanation, what is the service, its purpose
func New(name, description string) (Daemon, error) {
return newDaemon(name, description)
Expand Down
8 changes: 4 additions & 4 deletions darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (darwin *DarwinRecord) Remove() (string, error) {
}

if darwin.checkInstalled() == false {
return removeAction + failed, errors.New(darwin.description + " not installed")
return removeAction + failed, errors.New(darwin.description + " is not installed")
}

if err := os.Remove(darwin.servicePath()); err != nil {
Expand All @@ -132,7 +132,7 @@ func (darwin *DarwinRecord) Start() (string, error) {
}

if darwin.checkInstalled() == false {
return startAction + failed, errors.New(darwin.description + " not installed")
return startAction + failed, errors.New(darwin.description + " is not installed")
}

if _, status := darwin.checkRunning(); status == true {
Expand All @@ -155,7 +155,7 @@ func (darwin *DarwinRecord) Stop() (string, error) {
}

if darwin.checkInstalled() == false {
return stopAction + failed, errors.New(darwin.description + " not installed")
return stopAction + failed, errors.New(darwin.description + " is not installed")
}

if _, status := darwin.checkRunning(); status == false {
Expand All @@ -177,7 +177,7 @@ func (darwin *DarwinRecord) Status() (string, error) {
}

if darwin.checkInstalled() == false {
return "Status could not defined", errors.New(darwin.description + " not installed")
return "Status could not defined", errors.New(darwin.description + " is not installed")
}

statusAction, _ := darwin.checkRunning()
Expand Down
Loading

0 comments on commit 82c53c9

Please sign in to comment.