/
scripts.go
88 lines (72 loc) · 2.26 KB
/
scripts.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package command
import (
"bytes"
"io"
"os/exec"
"strings"
"sync"
"github.com/pkg/errors"
)
func runScriptAsync(script string, args []string, outputWriter, errorWriter io.Writer) (output string, err error) {
cmdArgs := []string{"-s", "--"}
if args != nil {
cmdArgs = append(cmdArgs, args...)
}
scriptCommand := exec.Command("/bin/sh", cmdArgs...)
scriptCommand.Stdin = strings.NewReader(script)
stdoutIn, _ := scriptCommand.StdoutPipe()
stderrIn, _ := scriptCommand.StderrPipe()
// By default we will copy standard output and standard error to a collection buffer.
var stdoutBuf, stderrBuf bytes.Buffer
var stdout io.Writer = &stdoutBuf
var stderr io.Writer = &stderrBuf
// If additional writers were passed, we will output to them as well.
if outputWriter != nil {
stdout = io.MultiWriter(outputWriter, &stdoutBuf)
}
if errorWriter != nil {
stderr = io.MultiWriter(errorWriter, &stderrBuf)
}
err = scriptCommand.Start()
if err != nil {
return "", errors.Wrap(err, "script command start error")
}
var wg sync.WaitGroup
wg.Add(1)
var errStdout error
go func() {
_, errStdout = io.Copy(stdout, stdoutIn)
wg.Done()
}()
_, errStderr := io.Copy(stderr, stderrIn)
wg.Wait()
if err != nil {
return "", errors.Wrap(err, "script command start error")
}
err = scriptCommand.Wait()
if err != nil {
return "", errors.Wrap(err, "script command run error")
}
if errStdout != nil || errStderr != nil {
return "", errors.Errorf("failed to capture stdout or stderr")
}
output = string(stdoutBuf.Bytes())
errorString := string(stderrBuf.Bytes())
if errorString != "" {
err = errors.Errorf("command produced error output: %s", errorString)
}
return
}
func runScript(script string, args []string) (output string, err error) {
return runScriptAsync(script, args, nil, nil)
}
func runEmbeddedScriptAsync(scriptName string, args []string, outputWriter, errorWriter io.Writer) (output string, err error) {
script, err := scriptBox.FindString(scriptName)
if err != nil {
return "", errors.Wrap(err, "error while trying to find script")
}
return runScriptAsync(script, args, outputWriter, errorWriter)
}
func runEmbeddedScript(scriptName string, args []string) (output string, err error) {
return runEmbeddedScriptAsync(scriptName, args, nil, nil)
}