1- Go Daemon
2- =========
1+ # Go Daemon
32
43A daemon package for use with Go (golang) services with no dependencies
54
65[ ![ GoDoc] ( https://godoc.org/github.com/takama/daemon?status.svg )] ( https://godoc.org/github.com/takama/daemon )
76
8- ### Examples
7+ ## Examples
8+
9+ ### Simplest example (just install self as daemon)
910
10- Simplest example (just install self as daemon):
1111``` go
1212package main
1313
1414import (
15- " fmt"
16- " log"
15+ " fmt"
16+ " log"
1717
18- " github.com/takama/daemon"
18+ " github.com/takama/daemon"
1919)
2020
2121func main () {
22- service , err := daemon.New (" name" , " description" )
23- if err != nil {
24- log.Fatal (" Error: " , err)
25- }
26- status , err := service.Install ()
27- if err != nil {
28- log.Fatal (status, " \n Error: " , err)
29- }
30- fmt.Println (status)
22+ service , err := daemon.New (" name" , " description" )
23+ if err != nil {
24+ log.Fatal (" Error: " , err)
25+ }
26+ status , err := service.Install ()
27+ if err != nil {
28+ log.Fatal (status, " \n Error: " , err)
29+ }
30+ fmt.Println (status)
3131}
3232```
3333
34- Real example:
34+ ### Real example
35+
3536``` go
3637// Example of a daemon with echo service
3738package main
3839
3940import (
40- " fmt"
41- " log"
42- " net"
43- " os"
44- " os/signal"
45- " syscall"
46-
47- " github.com/takama/daemon"
41+ " fmt"
42+ " log"
43+ " net"
44+ " os"
45+ " os/signal"
46+ " syscall"
47+
48+ " github.com/takama/daemon"
4849)
4950
5051const (
5152
52- // name of the service
53- name = " myservice"
54- description = " My Echo Service"
53+ // name of the service
54+ name = " myservice"
55+ description = " My Echo Service"
5556
56- // port which daemon should be listen
57- port = " :9977"
57+ // port which daemon should be listen
58+ port = " :9977"
5859)
5960
60- // dependencies that are NOT required by the service, but might be used
61+ // dependencies that are NOT required by the service, but might be used
6162var dependencies = []string {" dummy.service" }
6263
6364var stdlog , errlog *log.Logger
6465
6566// Service has embedded daemon
6667type Service struct {
67- daemon.Daemon
68+ daemon.Daemon
6869}
6970
7071// Manage by daemon commands or run the daemon
7172func (service *Service ) Manage () (string , error ) {
7273
73- usage := " Usage: myservice install | remove | start | stop | status"
74-
75- // if received any kind of command, do it
76- if len (os.Args ) > 1 {
77- command := os.Args [1 ]
78- switch command {
79- case " install" :
80- return service.Install ()
81- case " remove" :
82- return service.Remove ()
83- case " start" :
84- return service.Start ()
85- case " stop" :
86- return service.Stop ()
87- case " status" :
88- return service.Status ()
89- default :
90- return usage, nil
91- }
92- }
93-
94- // Do something, call your goroutines, etc
95-
96- // Set up channel on which to send signal notifications.
97- // We must use a buffered channel or risk missing the signal
98- // if we're not ready to receive when the signal is sent.
99- interrupt := make (chan os.Signal , 1 )
100- signal.Notify (interrupt, os.Interrupt , os.Kill , syscall.SIGTERM )
101-
102- // Set up listener for defined host and port
103- listener , err := net.Listen (" tcp" , port)
104- if err != nil {
105- return " Possibly was a problem with the port binding" , err
106- }
107-
108- // set up channel on which to send accepted connections
109- listen := make (chan net.Conn , 100 )
110- go acceptConnection (listener, listen)
111-
112- // loop work cycle with accept connections or interrupt
113- // by system signal
114- for {
115- select {
116- case conn := <- listen:
117- go handleClient (conn)
118- case killSignal := <- interrupt:
119- stdlog.Println (" Got signal:" , killSignal)
120- stdlog.Println (" Stoping listening on " , listener.Addr ())
121- listener.Close ()
122- if killSignal == os.Interrupt {
123- return " Daemon was interruped by system signal" , nil
124- }
125- return " Daemon was killed" , nil
126- }
127- }
128-
129- // never happen, but need to complete code
130- return usage, nil
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
131132}
132133
133134// Accept a client connection and collect it in a channel
134135func acceptConnection (listener net .Listener , listen chan <- net .Conn ) {
135- for {
136- conn , err := listener.Accept ()
137- if err != nil {
138- continue
139- }
140- listen <- conn
141- }
136+ for {
137+ conn , err := listener.Accept ()
138+ if err != nil {
139+ continue
140+ }
141+ listen <- conn
142+ }
142143}
143144
144145func handleClient (client net .Conn ) {
145- for {
146- buf := make ([]byte , 4096 )
147- numbytes , err := client.Read (buf)
148- if numbytes == 0 || err != nil {
149- return
150- }
151- client.Write (buf[:numbytes])
152- }
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+ }
153154}
154155
155156func init () {
156- stdlog = log.New (os.Stdout , " " , log.Ldate |log.Ltime )
157- errlog = log.New (os.Stderr , " " , log.Ldate |log.Ltime )
157+ stdlog = log.New (os.Stdout , " " , log.Ldate |log.Ltime )
158+ errlog = log.New (os.Stderr , " " , log.Ldate |log.Ltime )
158159}
159160
160161func main () {
161- srv , err := daemon.New (name, description, dependencies...)
162- if err != nil {
163- errlog.Println (" Error: " , err)
164- os.Exit (1 )
165- }
166- service := &Service{srv}
167- status , err := service.Manage ()
168- if err != nil {
169- errlog.Println (status, " \n Error: " , err)
170- os.Exit (1 )
171- }
172- fmt.Println (status)
162+ srv , err := daemon.New (name, description, 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, " \n Error: " , err)
171+ os.Exit (1 )
172+ }
173+ fmt.Println (status)
173174}
174175```
175176
176- Cron example:
177- ```
178- See example/cron_example.go
179- ```
177+ ### Cron example
178+
179+ See ` examples/cron/cron_job.go `
180180
181181## Contributors (unsorted)
182182
@@ -196,8 +196,10 @@ See example/cron_example.go
196196- [ 1for] ( https://github.com/1for )
197197- [ okamura] ( https://github.com/sidepelican )
198198- [ 0X8C - Demired] ( https://github.com/Demired )
199+ - [ Maximus] ( https://github.com/maximus12793 )
199200
200201All the contributors are welcome. If you would like to be the contributor please accept some rules.
202+
201203- The pull requests will be accepted only in "develop" branch
202204- All modifications or additions should be tested
203205- Sorry, We will not accept code with any dependency, only standard library
0 commit comments