-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcmd.go
73 lines (66 loc) · 2.41 KB
/
cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package urun
import (
"bytes"
"os/exec"
"strings"
"sync"
)
// CmdTry is used for `CmdsTryStart` to probe in parallel the installation status of multiple programs.
type CmdTry struct {
Args []string
Ran *bool
}
// CmdTryStart attempts to run the specified program, records whether this resulted in an `error`, and immediately kills the program before returning.
func CmdTryStart(cmdname string, cmdargs ...string) (err error) {
cmd := exec.Command(cmdname, cmdargs...)
err = cmd.Start()
defer cmd.Wait()
if cmd.Process != nil {
_ = cmd.Process.Kill()
}
return
}
// CmdsTryStart calls `CmdTryStart` for all specified `cmds` in parallel.
func CmdsTryStart(cmds map[string]*CmdTry) {
var w sync.WaitGroup
run := func(cmd string, try *CmdTry) {
defer w.Done()
*try.Ran = (nil == CmdTryStart(cmd, try.Args...))
}
w.Add(len(cmds))
for cmdname, cmdmore := range cmds {
go run(cmdname, cmdmore)
}
w.Wait()
}
// CmdExecStdin runs the specified program,
// returning its full `stdout` response and whitespace-trimmed `stderr` response.
func CmdExec(cmdName string, cmdArgs ...string) (stdout string, stderr string, err error) {
return CmdExecStdin("", "", cmdName, cmdArgs...)
}
// CmdExecStdin runs the specified program in the specified `dir` (if any),
// returning its full `stdout` response and whitespace-trimmed `stderr` response.
func CmdExecIn(dir string, cmdName string, cmdArgs ...string) (stdout string, stderr string, err error) {
return CmdExecStdin("", dir, cmdName, cmdArgs...)
}
// CmdExecStdin runs the specified program with the specified `stdin` (if any),
// returning its full `stdout` response and whitespace-trimmed `stderr` response.
func CmdExecStdin(stdin string, dir string, cmdName string, cmdArgs ...string) (stdout string, stderr string, err error) {
if cmdName != "" && strings.Contains(cmdName, " ") && len(cmdArgs) == 0 {
cmdArgs = strings.Split(cmdName, " ")
cmdName, cmdArgs = cmdArgs[0], cmdArgs[1:]
}
cmd := exec.Command(cmdName, cmdArgs...)
if cmd.Dir = dir; stdin != "" {
cmd.Stdin = strings.NewReader(stdin)
}
var bufout, buferr bytes.Buffer
cmd.Stdout, cmd.Stderr = &bufout, &buferr
if err = cmd.Run(); err != nil {
if _, isexiterr := err.(*exec.ExitError); isexiterr || strings.Contains(err.Error(), "pipe has been ended") || strings.Contains(err.Error(), "pipe has been closed") {
err = nil
}
}
stdout, stderr = bufout.String(), strings.TrimSpace(buferr.String())
return
}