launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/utils/exec/exec.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package exec 5 6 import ( 7 "bytes" 8 "os/exec" 9 "syscall" 10 11 "github.com/loggo/loggo" 12 ) 13 14 var logger = loggo.GetLogger("juju.util.exec") 15 16 // Parameters for RunCommands. Commands contains one or more commands to be 17 // executed using '/bin/bash -s'. If WorkingDir is set, this is passed 18 // through to bash. Similarly if the Environment is specified, this is used 19 // for executing the command. 20 type RunParams struct { 21 Commands string 22 WorkingDir string 23 Environment []string 24 } 25 26 // ExecResponse contains the return code and output generated by executing a 27 // command. 28 type ExecResponse struct { 29 Code int 30 Stdout []byte 31 Stderr []byte 32 } 33 34 // RunCommands executes the Commands specified in the RunParams using 35 // '/bin/bash -s', passing the commands through as stdin, and collecting 36 // stdout and stderr. If a non-zero return code is returned, this is 37 // collected as the code for the response and this does not classify as an 38 // error. 39 func RunCommands(run RunParams) (*ExecResponse, error) { 40 ps := exec.Command("/bin/bash", "-s") 41 if run.Environment != nil { 42 ps.Env = run.Environment 43 } 44 if run.WorkingDir != "" { 45 ps.Dir = run.WorkingDir 46 } 47 ps.Stdin = bytes.NewBufferString(run.Commands) 48 49 stdout := &bytes.Buffer{} 50 stderr := &bytes.Buffer{} 51 52 ps.Stdout = stdout 53 ps.Stderr = stderr 54 55 err := ps.Start() 56 if err == nil { 57 err = ps.Wait() 58 } 59 result := &ExecResponse{ 60 Stdout: stdout.Bytes(), 61 Stderr: stderr.Bytes(), 62 } 63 if ee, ok := err.(*exec.ExitError); ok && err != nil { 64 status := ee.ProcessState.Sys().(syscall.WaitStatus) 65 if status.Exited() { 66 // A non-zero return code isn't considered an error here. 67 result.Code = status.ExitStatus() 68 err = nil 69 } 70 logger.Infof("run result: %v", ee) 71 } 72 return result, err 73 }