package localcmd import ( "bytes" "io" "io/ioutil" "os/exec" "github.com/golang/glog" ) // LocalCmd is a helper to execute commands locally type LocalCmd struct { cmd string args []string env []string } // New creates a LocalCmd helper func New(command string) *LocalCmd { return &LocalCmd{ cmd: command, } } // Args adds arguments to the command func (c *LocalCmd) Args(args ...string) *LocalCmd { c.args = args return c } // Env adds environment to the command func (c *LocalCmd) Env(env ...string) *LocalCmd { c.env = env return c } // Run executes the command and returns an error if one occurs func (c *LocalCmd) Run() error { return runCmd(c.cmd, c.args, c.env, ioutil.Discard, ioutil.Discard) } // CombinedOutput executes the command and returns combined stdout and stderr from the command func (c *LocalCmd) CombinedOutput() (string, error) { outBuf := &bytes.Buffer{} err := runCmd(c.cmd, c.args, c.env, outBuf, outBuf) return outBuf.String(), err } // Output executes the command and returns separate stdout and stderr from the command func (c *LocalCmd) Output() (string, string, error) { outBuf, errBuf := &bytes.Buffer{}, &bytes.Buffer{} err := runCmd(c.cmd, c.args, c.env, outBuf, errBuf) return outBuf.String(), errBuf.String(), err } func runCmd(cmd string, args []string, env []string, stdOut, errOut io.Writer) error { glog.V(5).Infof("Executing local command:") glog.V(5).Infof(" %s", cmd) for _, a := range args { glog.V(5).Infof(" %s", a) } if len(env) > 0 { glog.V(5).Infof("Environment:") for _, e := range env { glog.V(5).Infof(" %s", e) } } c := exec.Command(cmd, args...) outLog := &bytes.Buffer{} errLog := &bytes.Buffer{} c.Stdout = io.MultiWriter(stdOut, outLog) c.Stderr = io.MultiWriter(errOut, errLog) c.Env = env err := c.Run() if glog.V(5) { if err != nil { glog.Infof("Error from execution: %v", err) } if outLog.Len() > 0 { glog.Infof("Stdout:\n%s", outLog.String()) } if errLog.Len() > 0 { glog.Infof("Errout:\n%s", errLog.String()) } } if err != nil { return newExecError(append([]string{cmd}, args...), err, outLog.Bytes(), errLog.Bytes()) } return nil }