86 lines
2.3 KiB
Go
86 lines
2.3 KiB
Go
package script
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os/exec"
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
)
|
|
|
|
// Exec executes a command and returns a stream of the stdout of the command.
|
|
func Exec(cmd string, args ...string) Stream {
|
|
return From("empty", nil).Through(exe{cmd: cmd, args: args})
|
|
}
|
|
|
|
// ExecHandleStderr executes a command, returns a stream of the stdout of the command and enable
|
|
// collecting the stderr of the command.
|
|
//
|
|
// If the stderr is nil, it will be ignored.
|
|
//
|
|
// For example, collecting the stderr to memory can be done by providing a `&bytes.Buffer` as
|
|
// `stderr`. Writing it to stderr can be done by providing `os.Stderr` as `stderr`. Logging it
|
|
// to a file can be done by providing an `os.File` as the `stderr`.
|
|
func ExecHandleStderr(stderr io.Writer, cmd string, args ...string) Stream {
|
|
return From("empty", nil).Through(exe{cmd: cmd, args: args, stderr: stderr})
|
|
}
|
|
|
|
// Exec executes a command and returns a stream of the stdout of the command.
|
|
func (s Stream) Exec(cmd string, args ...string) Stream {
|
|
return s.Through(exe{cmd: cmd, args: args})
|
|
}
|
|
|
|
// ExecHandleStderr executes a command, returns a stream of the stdout of the command and enable
|
|
// collecting the stderr of the command.
|
|
//
|
|
// If the stderr is nil, it will be ignored.
|
|
func (s Stream) ExecHandleStderr(stderr io.Writer, cmd string, args ...string) Stream {
|
|
return s.Through(exe{cmd: cmd, args: args, stderr: stderr})
|
|
}
|
|
|
|
type exe struct {
|
|
cmd string
|
|
args []string
|
|
stderr io.Writer
|
|
}
|
|
|
|
func (e exe) Name() string {
|
|
return fmt.Sprintf("exec(%v, %+v)", e.cmd, e.args)
|
|
}
|
|
|
|
func (e exe) Pipe(stdin io.Reader) (io.Reader, error) {
|
|
cmd := exec.Command(e.cmd, e.args...)
|
|
var errors *multierror.Error
|
|
|
|
// Pipe previous stdin if available.
|
|
if stdin != nil {
|
|
cmd.Stdin = stdin
|
|
}
|
|
|
|
// Pipe stdout to the current command output.
|
|
cmdOut, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
errors = multierror.Append(errors, fmt.Errorf("pipe stdout: %v", err))
|
|
}
|
|
|
|
if e.stderr == nil {
|
|
e.stderr = ioutil.Discard
|
|
}
|
|
cmd.Stderr = e.stderr
|
|
|
|
// start the process
|
|
err = cmd.Start()
|
|
if err != nil {
|
|
errors = multierror.Append(errors, fmt.Errorf("start process: %v", err))
|
|
}
|
|
return readcloser{
|
|
Reader: cmdOut,
|
|
Closer: closerFn(func() error { return cmd.Wait() }),
|
|
}, errors.ErrorOrNil()
|
|
}
|
|
|
|
type closerFn func() error
|
|
|
|
func (f closerFn) Close() error { return f() }
|