github.com/nxadm/ctwrapper@v0.5.3-0.20200107113753-fb73fb7c1f50/consul-template.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "os/exec" 8 "runtime" 9 "strings" 10 "sync" 11 "syscall" 12 ) 13 14 func runCt(tmplExt string, files, ctParams []string) error { 15 ct, err := findConsulTemplate() 16 if err != nil { 17 return err 18 } 19 20 args := createTmplArg(files, tmplExt) 21 args = append(args, ctParams...) 22 fmt.Printf("Executing: %s %s\n", ct, strings.Join(args, " ")) 23 24 /* Execute the command */ 25 switch { 26 // Windows does not really forks the process: we need a wrapper to write the stdOut end stdErr at the same time 27 case runtime.GOOS == "windows": 28 return runWhilePrinting(exec.Command(ct, args...)) 29 default: 30 return syscall.Exec(ct, append([]string{ct}, args...), os.Environ()) 31 } 32 33 return nil 34 } 35 36 func createTmplArg(files []string, tmplExt string) []string { 37 tmplArgs := []string{} 38 for _, tmpl := range files { 39 file := strings.TrimSuffix(tmpl, tmplExt) 40 tmplArgs = append(tmplArgs, "-template") 41 tmplArgs = append(tmplArgs, tmpl+":"+file) 42 } 43 return tmplArgs 44 } 45 46 func runWhilePrinting(cmd *exec.Cmd) error { 47 var err error 48 49 /* Get stdout and stderr realtime */ 50 var wg sync.WaitGroup 51 wg.Add(2) // StdOut + StdErr 52 cmdOutReader, err := cmd.StdoutPipe() 53 if err != nil { 54 return err 55 } else { 56 scanner := bufio.NewScanner(cmdOutReader) 57 go func() { 58 defer wg.Done() 59 for scanner.Scan() { 60 fmt.Fprintf(os.Stdout, "%s\n", scanner.Text()) 61 } 62 }() 63 } 64 cmdErrReader, err := cmd.StderrPipe() 65 if err != nil { 66 return err 67 } else { 68 scanner := bufio.NewScanner(cmdErrReader) 69 go func() { 70 defer wg.Done() 71 for scanner.Scan() { 72 fmt.Fprintf(os.Stderr, "%s\n", scanner.Text()) 73 } 74 }() 75 } 76 77 /* Run the cmd */ 78 err = cmd.Start() 79 if err != nil { 80 return err 81 } 82 83 waitErr := cmd.Wait() 84 if waitErr != nil { 85 return waitErr 86 } 87 88 wg.Wait() // Wait for StdOut + StdErr 89 return err 90 }