From 0c16b5472f027407cb09b078689a2c0e9be534e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Abdelkader=20Mart=C3=ADnez=20P=C3=A9rez?= Date: Wed, 23 Dec 2020 12:40:04 +0100 Subject: [PATCH] feat: run multiple init programs - We log their outputs and status codes - Windows is supported as well, leveraging cmd.exe /c Co-authored-by: pancho horrillo --- internal/cmd/runner.go | 11 ++++++ internal/cmd/runner_windows.go | 9 +++++ internal/cmd/server.go | 63 ++++++++++++++++++++++++---------- test/runwindowsrun.go | 19 ++++++++++ 4 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 internal/cmd/runner.go create mode 100644 internal/cmd/runner_windows.go create mode 100644 test/runwindowsrun.go diff --git a/internal/cmd/runner.go b/internal/cmd/runner.go new file mode 100644 index 0000000..4ba17f5 --- /dev/null +++ b/internal/cmd/runner.go @@ -0,0 +1,11 @@ +// +build !windows + +package cmd + +import ( + "os/exec" +) + +func BuildCmd(path string) *exec.Cmd { + return exec.Command(path) +} diff --git a/internal/cmd/runner_windows.go b/internal/cmd/runner_windows.go new file mode 100644 index 0000000..04f368a --- /dev/null +++ b/internal/cmd/runner_windows.go @@ -0,0 +1,9 @@ +package cmd + +import ( + "os/exec" +) + +func BuildCmd(path string) *exec.Cmd { + return exec.Command("cmd.exe", "/c", path) +} diff --git a/internal/cmd/server.go b/internal/cmd/server.go index 270b6b0..d4f7d3e 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -17,9 +17,11 @@ package cmd import ( + "bufio" "errors" + "io" "os" - "os/exec" + "sync" "github.com/spf13/cobra" @@ -57,23 +59,8 @@ var ServerCmd = &cobra.Command{ server.StartServer(sConf) - if len(args) > 0 { - powfile := args[0] - _, err := os.Stat(powfile) - if os.IsNotExist(err) { - logger.L.Fatalf("%s does not exist", powfile) - } - logger.L.Printf("Running powfile: %q\n", powfile) - kapowCMD := exec.Command("bash", powfile) - kapowCMD.Stdout = os.Stdout - kapowCMD.Stderr = os.Stderr - kapowCMD.Env = os.Environ() - - err = kapowCMD.Run() - if err != nil { - logger.L.Fatal(err) - } - logger.L.Printf("Done running powfile: %q\n", powfile) + for _, path := range args { + go Run(path) } select {} @@ -112,3 +99,43 @@ func validateServerCommandArguments(cmd *cobra.Command, args []string) error { return nil } + +func Run(path string) { + logger.L.Printf("Running init program %+q", path) + cmd := BuildCmd(path) + cmd.Env = os.Environ() + + var wg sync.WaitGroup + if stdout, err := cmd.StdoutPipe(); err == nil { + wg.Add(1) + go logPipe(path, "stdout", stdout, &wg) + } + if stderr, err := cmd.StderrPipe(); err == nil { + wg.Add(1) + go logPipe(path, "stderr", stderr, &wg) + } + err := cmd.Start() + if err != nil { + logger.L.Fatalf("Unable to run init program %+q: %s", path, err) + } + + wg.Wait() + err = cmd.Wait() + if err != nil { + logger.L.Printf("Init program exited with error: %s", err) + } else { + logger.L.Printf("Init program %+q finished OK", path) + } +} + +func logPipe(path, name string, pipe io.ReadCloser, wg *sync.WaitGroup) { + defer wg.Done() + in := bufio.NewScanner(pipe) + + for in.Scan() { + logger.L.Printf("%+q (%s): %s", path, name, in.Text()) + } + if err := in.Err(); err != nil { + logger.L.Printf("Error reading from %+q’s %s: %s", path, name, err) + } +} diff --git a/test/runwindowsrun.go b/test/runwindowsrun.go new file mode 100644 index 0000000..5e4cb97 --- /dev/null +++ b/test/runwindowsrun.go @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "os" + "os/exec" +) + +func main() { + cmd := exec.Command("rundll32.exe", "url.dll,FileProtocolHandler", os.Args[1]) + err := cmd.Start() + if err != nil { + fmt.Println(err) + } + err = cmd.Wait() + if err != nil { + fmt.Println(err) + } +}