github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/util/process.go (about) 1 // Package util - Content managed by Project Forge, see [projectforge.md] for details. 2 package util 3 4 import ( 5 "bytes" 6 "io" 7 "os" 8 "os/exec" 9 "strings" 10 11 "github.com/buildkite/shellwords" 12 "github.com/pkg/errors" 13 ) 14 15 func StartProcess(cmd string, path string, in io.Reader, out io.Writer, er io.Writer, env ...string) (*exec.Cmd, error) { 16 args, err := shellwords.Split(cmd) 17 if err != nil { 18 return nil, err 19 } 20 if len(args) == 0 { 21 return nil, errors.New("no arguments provided") 22 } 23 firstArg := args[0] 24 25 if !strings.Contains(firstArg, "/") && !strings.Contains(firstArg, "\\") { 26 firstArg, err = exec.LookPath(firstArg) 27 if err != nil { 28 return nil, errors.Wrapf(err, "unable to look up cmd [%s]", firstArg) 29 } 30 } 31 32 if in == nil { 33 in = os.Stdin 34 } 35 if out == nil { 36 out = os.Stdout 37 } 38 if er == nil { 39 er = os.Stderr 40 } 41 42 c := &exec.Cmd{Path: firstArg, Args: args, Env: env, Stdin: in, Stdout: out, Stderr: er, Dir: path} 43 err = c.Start() 44 if err != nil { 45 return nil, errors.Wrapf(err, "unable to start [%s] (%T)", cmd, err) 46 } 47 return c, nil 48 } 49 50 func RunProcess(cmd string, path string, in io.Reader, out io.Writer, er io.Writer, env ...string) (int, error) { 51 c, err := StartProcess(cmd, path, in, out, er, env...) 52 if err != nil { 53 return -1, err 54 } 55 err = c.Wait() 56 if err != nil { 57 ec, ok := err.(*exec.ExitError) //nolint:errorlint 58 if ok { 59 return ec.ExitCode(), nil 60 } 61 return -1, errors.Wrapf(err, "unable to run [%s] (%T)", cmd, err) 62 } 63 return 0, nil 64 } 65 66 func RunProcessSimple(cmd string, path string) (int, string, error) { 67 var buf bytes.Buffer 68 ec, err := RunProcess(cmd, path, nil, &buf, &buf) 69 if err != nil { 70 return -1, "", err 71 } 72 return ec, buf.String(), nil 73 }