Skip to content

Instantly share code, notes, and snippets.

@gomisc
Created December 21, 2018 11:12
Show Gist options
  • Save gomisc/70e22bac6c88b73505cce0d7cd97629b to your computer and use it in GitHub Desktop.
Save gomisc/70e22bac6c88b73505cce0d7cd97629b to your computer and use it in GitHub Desktop.
Simple example for run subprocess from golang
// ExecuteCommand - execute cmd *exec.Cmd with async output from command stderr, stdout
// and return combine output as some byte-buffer object
// 1st, 2nd writers - always stdout, stderr
func ExecuteCommand(cmd *exec.Cmd, writers ...io.Writer) (buff *Buffer, err error) {
var wg sync.WaitGroup
var outputWriter, errorWriter io.Writer
buff = NewBuffer()
// Stdout redirect
if len(writers) >= 1 {
outputWriter = writers[0]
} else {
outputWriter = os.Stdout
}
// stderr redirect
if len(writers) >= 2 {
errorWriter = writers[1]
} else {
errorWriter = os.Stderr
}
/// get streams pipes
stdout, err := cmd.StdoutPipe()
if CheckIfError(err, "Can't open command stdout pipe") { return buff, err}
stderr, err := cmd.StderrPipe()
if CheckIfError(err, "Can't open command stderr pipe") { return buff, err}
/// start command
err = cmd.Start()
if CheckIfError(err, "Command start error") { return buff, err }
/// get combine output continuously
wg.Add(2)
go func() {
defer wg.Done()
routeCmdOutput(stdout, outputWriter, buff)
}()
go func() {
defer wg.Done()
routeCmdOutput(stderr, errorWriter, buff)
}()
/// waiting output done
wg.Wait()
/// waiting command done
err = cmd.Wait()
if CheckIfError(err, "Command return non zero status") { return buff, err }
return buff, nil
}
func Execute(name, path string, arg ...string) error {
cmd := exec.Command(name, arg...)
cmd.Dir = path
_, err := ExecuteCommand(cmd)
return err
}
func routeCmdOutput(r io.Reader, w io.Writer, buffer *Buffer) {
buf := make([]byte, 128)
buffer = NewBuffer()
for {
n, err := r.Read(buf)
if n > 0 {
_, err := fmt.Fprint(w, string(buf[0:n]))
CheckIfError(err, "")
_, err = buffer.Write(buf[0:n])
CheckIfError(err, "")
}
if err != nil { break }
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment