Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/krystal/go-runner

Go package exposing a simple interface for executing commands, enabling easy mocking and wrapping of executed commands.
https://github.com/krystal/go-runner

exec execution go golang testing

Last synced: about 1 month ago
JSON representation

Go package exposing a simple interface for executing commands, enabling easy mocking and wrapping of executed commands.

Awesome Lists containing this project

README

        


go-runner



Go package exposing a simple interface for executing commands, enabling easy
mocking and wrapping of executed commands.



Go Reference


GitHub tag (latest SemVer)


Actions Status


Coverage


GitHub last commit


GitHub issues


GitHub pull requests


License Status

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

```go
import "github.com/krystal/go-runner"
```

## Interface

```go
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)
}
```

## Usage

Basic:

```go
var stdout bytes.Buffer

r := runner.New()
_ = r.Run(nil, &stdout, nil, "echo", "Hello world!")

fmt.Print(stdout.String())
```

```
Hello world!
```

Environment:

```go
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:

```go
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:

```go
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:

```go
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):

```go
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
```

## Documentation

Please see the
[Go Reference](https://pkg.go.dev/github.com/krystal/go-runner#section-documentation)
for documentation and examples.

## License

[MIT](https://github.com/krystal/go-runner/blob/main/LICENSE)