github.com/reconquest/executil-go@v0.0.0-20181110204642-1f5c2d67813f/run.go (about) 1 package executil 2 3 import ( 4 "bytes" 5 "io" 6 "os/exec" 7 ) 8 9 type option int 10 11 const ( 12 // IgnoreStdout is option for executil.Run() which should be passed if 13 // stdout data should be ignored. 14 IgnoreStdout option = iota 15 16 // IgnoreStderr is option for executil.Run() which should be passed if 17 // stderr data should be ignored. 18 IgnoreStderr 19 ) 20 21 // Run sets writers for stdout and stderr, starts the specified command and 22 // waits for it to complete. 23 // 24 // The returned error is nil if the command runs, has no problems 25 // copying stdin, stdout, and stderr, and exits with a zero exit 26 // status. 27 // Otherwise, the error is of type Error. 28 func Run( 29 cmd *exec.Cmd, options ...option, 30 ) (stdout []byte, stderr []byte, err error) { 31 var ( 32 stdoutBuffer = &bytes.Buffer{} 33 stderrBuffer = &bytes.Buffer{} 34 combinedBuffer = &threadsafeBuffer{} 35 36 ignoreStdout bool 37 ignoreStderr bool 38 ) 39 40 for _, option := range options { 41 switch option { 42 case IgnoreStdout: 43 ignoreStdout = true 44 45 case IgnoreStderr: 46 ignoreStderr = true 47 } 48 } 49 50 if !ignoreStdout { 51 cmd.Stdout = io.MultiWriter(stdoutBuffer, combinedBuffer) 52 } 53 if !ignoreStderr { 54 cmd.Stderr = io.MultiWriter(stderrBuffer, combinedBuffer) 55 } 56 57 runErr := cmd.Run() 58 if runErr != nil { 59 err = &Error{ 60 RunErr: runErr, 61 Cmd: cmd, 62 Output: combinedBuffer.Bytes(), 63 } 64 } 65 66 return stdoutBuffer.Bytes(), stderrBuffer.Bytes(), err 67 }