Last active
April 25, 2021 02:55
-
-
Save yougg/fb2abf3fdfc085209f7004aca9847593 to your computer and use it in GitHub Desktop.
Simple monitor for running multi process in docker scratch image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//go:generate go build -trimpath -buildmode pie -installsuffix netgo -tags "osusergo netgo static_build" -ldflags "-s -w -extldflags '-static'" -o monitor ${GOFILE} | |
package main | |
import ( | |
"bytes" | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"os" | |
"os/exec" | |
"path/filepath" | |
"regexp" | |
"strings" | |
"sync" | |
"time" | |
) | |
var ( | |
command = flag.String("c", "", "") | |
script = flag.String("s", "", "") | |
debug = flag.Bool("d", false, "") | |
interval = flag.Duration("i", 10*time.Second, "") | |
count = flag.Uint("r", 0, "") | |
) | |
var ( | |
regSpace = regexp.MustCompile(`[\s]+`) | |
wg = &sync.WaitGroup{} | |
) | |
func init() { | |
flag.StringVar(command, "command", "", "command line file") | |
flag.StringVar(script, "script", "", "script file") | |
flag.BoolVar(debug, "debug", false, "debug mode") | |
flag.DurationVar(interval, "interval", time.Minute, "interval time for restart failure program") | |
flag.UintVar(count, "retry", 0, "retry times on error, -1 for ever") | |
flag.Usage = func() { | |
name, _ := os.Executable() | |
name = filepath.Base(name) | |
usage := `Usage of ` + name + `:` + | |
"\n -c, --command\n\tcommand line(s) to be execute (default \"\")" + | |
"\n -s, --script\n\tread script file and run commands (default \"\")" + | |
"\n -i, --interval\n\tinterval time(ns/us/ms/s/m/h) for restart failure program (default \"10s\")" + | |
"\n -r, --retry\n\tretry times on error (default 0)" + | |
"\n -d, --debug\n\tdebug mode, attach to program's stdin/stdout/stderr" + | |
"\nExample:" + | |
"\n monitor -d -c 'go version'" + | |
"\n monitor -c 'date\nping -c 4 127.0.0.1\nsleep 5s'" + | |
"\n monitor -s xxx.script -i 100s" | |
fmt.Println(usage) | |
} | |
flag.Parse() | |
} | |
func main() { | |
var err error | |
data := bytes.TrimSpace([]byte(*command)) | |
if len(data) == 0 { | |
data, err = ioutil.ReadFile(*script) | |
if err != nil { | |
fmt.Println("Read script file failed", err) | |
return | |
} | |
} | |
content := bytes.Split(data, []byte{'\n'}) | |
for _, s := range content { | |
line := string(bytes.TrimSpace(s)) | |
if len(line) == 0 { | |
continue | |
} | |
if strings.HasPrefix(line, `#`) || strings.HasPrefix(line, `//`) { | |
fmt.Println("Skip:", line) | |
continue | |
} | |
cmd := regSpace.Split(line, -1) // TODO parse 1. spaces in parameter, 2. quoted spaces in parameter | |
fmt.Println("Run: ", cmd) | |
if strings.ToLower(cmd[0]) == `sleep` { | |
d := time.Second | |
if len(cmd) > 1 { | |
d, err = time.ParseDuration(cmd[1]) | |
if err != nil || d == 0 { | |
d = time.Second | |
} | |
} | |
time.Sleep(d) | |
continue | |
} | |
wg.Add(1) | |
go run(cmd...) | |
} | |
// select {} | |
wg.Wait() | |
} | |
func run(args ...string) { | |
defer wg.Done() | |
if len(args) == 0 { | |
return | |
} | |
cmd := exec.Command(args[0], args[1:]...) | |
if cmd == nil { | |
fmt.Println("Construct running command failed", args) | |
return | |
} | |
if *debug { | |
cmd.Stdin = os.Stdin | |
cmd.Stdout = os.Stdout | |
cmd.Stderr = os.Stderr | |
} | |
err := cmd.Run() | |
if err != nil { | |
fmt.Println("Error:", err) | |
if err == exec.ErrNotFound { | |
return | |
} | |
} | |
for i := uint(0); (err != nil && i < *count) || *count < 0; i++ { | |
time.Sleep(*interval) | |
err = cmd.Run() | |
if err != nil { | |
fmt.Println("Error:", err) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment