Go package exposing a simple interface for executing commands, enabling easy mocking and wrapping of executed commands.
The Runner interface is basic and minimal, but it is sufficient for most use cases. This makes it easy to mock Runner for testing purposes.
It's also easy to create wrapper runners which modify commands before executing
them. The Sudo
struct is a simple example of this.
import "github.com/krystal/go-runner"
type Runner interface {
Run(
stdin io.Reader,
stdout, stderr io.Writer,
command string,
args ...string,
) error
RunContext(
ctx context.Context,
stdin io.Reader,
stdout, stderr io.Writer,
command string,
args ...string,
) error
Env(env ...string)
}
Basic:
var stdout bytes.Buffer
r := runner.New()
_ = r.Run(nil, &stdout, nil, "echo", "Hello world!")
fmt.Print(stdout.String())
Hello world!
Environment:
var stdout bytes.Buffer
r := runner.New()
r.Env("USER=johndoe", "HOME=/home/johnny")
_ = r.Run(nil, &stdout, nil, "sh", "-c", `echo "Hi, ${USER} (${HOME})"`)
fmt.Print(stdout.String())
Hi, johndoe (/home/johnny)
Stdin, Stdout, and Stderr:
stdin := bytes.NewBufferString("Hello world!")
var stdout, stderr bytes.Buffer
r := runner.New()
err := r.Run(
stdin, &stdout, &stderr,
"sh", "-c", "cat; echo 'Oh noes! :(' >&2",
)
if err != nil {
fmt.Println(err)
}
fmt.Print(stderr.String())
fmt.Print(stdout.String())
Oh noes! :(
Hello world!
Failure:
var stdout, stderr bytes.Buffer
r := runner.New()
err := r.Run(
nil, &stdout, &stderr,
"sh", "-c", "echo 'Hello world!'; echo 'Oh noes! :(' >&2; exit 3",
)
if err != nil {
fmt.Printf("%s: %s", err.Error(), stderr.String())
}
exit status 3: Oh noes! :(
Context:
var stdout bytes.Buffer
ctx, cancel := context.WithTimeout(
context.Background(), 1*time.Second,
)
defer cancel()
r := runner.New()
err := r.RunContext(
ctx, nil, &stdout, nil,
"sh", "-c", "sleep 0.5 && echo 'Hello world!'",
)
if err != nil {
fmt.Println(err)
}
fmt.Print(stdout.String())
Hello world!
Sudo (requires NOPASS
in sudoers file):
var stdout bytes.Buffer
r := runner.New()
sudo := &runner.Sudo{Runner: r}
_ = sudo.Run(nil, &stdout, nil, "whoami")
sudo.User = "web"
_ = sudo.Run(nil, &stdout, nil, "whoami")
fmt.Print(stdout.String())
root
web
Please see the Go Reference for documentation and examples.