Small library for supervising child processes in Go
, it exposes Stdout
,Stderr
and Stdin
in the "Go way" using channles...
example.bash
print stuff to stdout and stderr and quit after 5 seconds...
#!/bin/bash
echo "STDOUT MESSAGE"
echo "STDERR MESSAGE" 1>&2
sleep 5
supervisor-exapmle.go
spawn and supervise the bash program...
package main
import (
"github.com/kontera-technologies/go-supervisor/supervisor"
"log"
)
func main() {
p, err := supervisor.Supervise("example.bash", supervisor.Options{
Args: []string{}, // argumets to pass ( default is none )
SpawnAttempts: 4, // attempts before giving up ( default 10 )
AttemptsBeforeTerminate: 10, // on Stop() terminate process after X interrupt attempts (default is 10)
Debug: true, // print events to stdout ( default false )
Dir: "/tmp", // run dir ( default is current dir )
Id: "example", // will be added to every log print ( default is "NOID")
MaxSpawns: 10, // Max spawn limit ( default is 1 )
StdoutIdleTime: 10, // stop worker if we didn't recived stdout message in X seconds ( default is 0 - disbaled )
StderrIdleTime: 10, // stop worker if we didn't recived stderr message in X seconds ( default is 0 - disbaled )
// function that calculate sleep time based in the current sleep time
// useful for exponential backoff ( default is this function )
DelayBetweenSpawns: func(currentSleep int) (sleepTime int) {
return currentSleep * 2
},
})
if err != nil {
log.Printf("failed to start process: %s", err)
return
}
exit := make(chan bool)
done := p.NotifyDone(make(chan bool)) // process is done...
events := p.NotifyEvents(make(chan *supervisor.Event,1000))
// read stuff
go func() {
for {
select {
case msg := <-p.Stdout:
log.Printf("Recived STDOUT message %s", msg)
case msg := <-p.Stderr:
log.Printf("Recived STDERR message %s", msg)
case event := <- events:
switch event.Code {
case 22:
log.Printf("instance respawned, new pid is: %v...", p.Pid())
default:
log.Printf("[%d] %s", event.Code, event.Message)
}
case <-done: // process quit
log.Printf("Closing loop we are done....")
exit <- true
return
}
}
}()
<-exit
}
running the program should produce this output
2015/02/12 13:02:14 Recived STDERR message &STDERR MESSAGE
2015/02/12 13:02:14 Recived STDOUT message &STDOUT MESSAGE
2015/02/12 13:02:20 [1] [example] can't read from stderr: EOF
2015/02/12 13:02:20 [1] [example] can't read from stdout: EOF
2015/02/12 13:02:20 [7] [example] instance crashed...
2015/02/12 13:02:20 [10] [example] going to sleep for 2 seconds...
2015/02/12 13:02:20 [20] [example] going to kill process..
2015/02/12 13:02:20 [5] [example] stderr goroutine is done...
2015/02/12 13:02:20 [5] [example] stdout goroutine is done...
2015/02/12 13:02:20 [19] [example] closing stdin handler...
2015/02/12 13:02:20 [5] [example] stdin goroutine is done...
2015/02/12 13:02:20 [29] [example] entering sleep stage...
2015/02/12 13:02:22 [8] [example] starting instance...
2015/02/12 13:02:22 [0] [example] opening stdin handler...
2015/02/12 13:02:22 [0] [example] opening stdout handler...
2015/02/12 13:02:22 [0] [example] opening stderr handler...
2015/02/12 13:02:22 instance respawned, new pid is: 58312...
2015/02/12 13:02:22 Recived STDOUT message &STDOUT MESSAGE
2015/02/12 13:02:22 Recived STDERR message &STDERR MESSAGE
2015/02/12 13:02:27 [1] [example] can't read from stdout: EOF
2015/02/12 13:02:27 [1] [example] can't read from stderr: EOF
2015/02/12 13:02:27 [7] [example] instance crashed...
2015/02/12 13:02:27 [10] [example] going to sleep for 4 seconds...
2015/02/12 13:02:27 [20] [example] going to kill process..
2015/02/12 13:02:27 [5] [example] stderr goroutine is done...
2015/02/12 13:02:27 [5] [example] stdout goroutine is done...
2015/02/12 13:02:27 [19] [example] closing stdin handler...
2015/02/12 13:02:27 [5] [example] stdin goroutine is done...
2015/02/12 13:02:27 [29] [example] entering sleep stage...
2015/02/12 13:02:31 [8] [example] starting instance...
2015/02/12 13:02:31 [0] [example] opening stdin handler...
2015/02/12 13:02:31 [0] [example] opening stdout handler...
2015/02/12 13:02:31 [0] [example] opening stderr handler...
2015/02/12 13:02:31 instance respawned, new pid is: 58323...
2015/02/12 13:02:31 Recived STDERR message &STDERR MESSAGE
2015/02/12 13:02:31 Recived STDOUT message &STDOUT MESSAGE
2015/02/12 13:02:36 [1] [example] can't read from stderr: EOF
2015/02/12 13:02:36 [1] [example] can't read from stdout: EOF
2015/02/12 13:02:36 [7] [example] instance crashed...
2015/02/12 13:02:36 [10] [example] going to sleep for 8 seconds...
2015/02/12 13:02:36 [20] [example] going to kill process..
2015/02/12 13:02:36 [5] [example] stderr goroutine is done...
2015/02/12 13:02:36 [5] [example] stdout goroutine is done...
2015/02/12 13:02:36 [19] [example] closing stdin handler...
2015/02/12 13:02:36 [5] [example] stdin goroutine is done...
2015/02/12 13:02:36 [29] [example] entering sleep stage...
2015/02/12 13:02:45 [8] [example] starting instance...
2015/02/12 13:02:45 [0] [example] opening stdin handler...
2015/02/12 13:02:45 [0] [example] opening stdout handler...
2015/02/12 13:02:45 [0] [example] opening stderr handler...
2015/02/12 13:02:45 instance respawned, new pid is: 58338...
2015/02/12 13:02:45 Recived STDOUT message &STDOUT MESSAGE
2015/02/12 13:02:45 Recived STDERR message &STDERR MESSAGE
2015/02/12 13:02:50 [1] [example] can't read from stderr: EOF
2015/02/12 13:02:50 [1] [example] can't read from stdout: EOF
2015/02/12 13:02:50 [7] [example] instance crashed...
2015/02/12 13:02:50 [9] [example] giving up, instance failed to start...
2015/02/12 13:02:50 Closing loop we are done....