package main
import (
"bufio"
"bytes"
"fmt"
"github.com/ramr/go-reaper"
"os"
"syscall"
"time"
)
func main() {
config := reaper.Config{
Pid: -1,
Options: 0,
Debug: true,
DisablePid1Check: false,
}
// Start background reaping of orphaned child processes.
go reaper.Start(config)
go func() {
err := forkForeground([]string{"/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/supervisord.conf"})
fmt.Println(err)
}()
go func() {
for {
select {
case <-time.After(100 * time.Millisecond):
fmt.Println(forkExecRunOnce([]string{"/usr/bin/supervisorctl", "-c", "/etc/supervisor/supervisord.conf", "status", "nginx"}))
}
}
}()
time.Sleep(1 * time.Hour)
}
func forkExecRunOnce(xargs []string) (string, string) {
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
forkExec(xargs, func(stdoutFile *os.File, stderrFile *os.File, waitChan chan error) {
defer stdoutFile.Close()
defer stderrFile.Close()
defer close(waitChan)
err := <-waitChan
if err != nil {
fmt.Println(err)
}
buf := bufio.NewReader(stdoutFile)
for {
if l, _, err := buf.ReadLine(); err == nil {
fmt.Println(string(l))
} else {
break
}
}
buf = bufio.NewReader(stderrFile)
for {
if l, _, err := buf.ReadLine(); err == nil {
fmt.Println(string(l))
} else {
break
}
}
})
return stdout.String(), stderr.String()
}
func forkForeground(xargs []string) error {
var status syscall.WaitStatus
attrs := &syscall.ProcAttr{
Env: append(os.Environ()),
Sys: &syscall.SysProcAttr{
Setsid: true,
},
Files: []uintptr{
0, 1, 2,
},
}
pid, _ := syscall.ForkExec(xargs[0], xargs, attrs)
_, err := syscall.Wait4(pid, &status, 0, nil)
return err
}
func forkExec(xargs []string, call func(*os.File, *os.File, chan error)) {
readOut, writeOut, _ := os.Pipe()
readErr, writeErr, _ := os.Pipe()
var wstatus syscall.WaitStatus
pattrs := &syscall.ProcAttr{
Env: append(os.Environ()),
Sys: &syscall.SysProcAttr{
Setsid: true,
},
Files: []uintptr{
0, writeOut.Fd(), writeErr.Fd(),
},
}
pid, err := syscall.ForkExec(xargs[0], xargs, pattrs)
if err != nil {
fmt.Println(err)
}
waitChan := make(chan error)
go func() {
_, err := syscall.Wait4(pid, &wstatus, 0, nil)
if err != nil {
fmt.Println(wstatus.Stopped())
}
writeOut.Close()
writeErr.Close()
waitChan <- err
}()
// call user func
go call(readOut, readErr, waitChan)
}
docker run -it --rm --name test -v /home/sre/test/:/tmp okteto/supervisord-nginx /tmp/main
nginx STARTING
- Received signal child exited
false
- Grim reaper cleanup: pid=18, wstatus=0
no child processes
nginx STARTING
false
- Grim reaper cleanup: pid=86, wstatus=0
no child processes
nginx STARTING
false
- Grim reaper cleanup: pid=88, wstatus=0
no child processes
nginx STARTING
false
- Grim reaper cleanup: pid=89, wstatus=0
no child processes
nginx STARTING
false
- Grim reaper cleanup: pid=91, wstatus=0
no child processes
nginx STARTING
nginx STARTING
nginx STARTING
nginx STARTING