exec

package
v0.0.0-...-b04d5d2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2024 License: BSD-3-Clause Imports: 15 Imported by: 20

Documentation

Overview

Package exec is a wrapper around the os/exec package that supports timeouts and testing.

Example usage:

Simple command with argument:

   err := exec.Run(ctx, &exec.Command{
	 Name: "touch",
	 Args: []string{file},
   })

More complicated example:

   output := bytes.Buffer{}
   err := exec.Run(ctx, &exec.Command{
     Name: "make",
     Args: []string{"all"},
     // Set environment:
     Env: []string{fmt.Sprintf("GOPATH=%s", projectGoPath)},
     // Set working directory:
     Dir: projectDir,
     // Capture output:
     CombinedOutput: &output,
     // Set a timeout:
     Timeout: 10*time.Minute,
   })

	For testing, see exec_testutil.go and exec.CommandCollector.

Index

Constants

View Source
const (
	TIMEOUT_ERROR_PREFIX = "Command killed since it took longer than"
)

Variables

View Source
var (
	WriteInfoLog    = WriteLog{LogFunc: sklog.Infof}
	WriteWarningLog = WriteLog{LogFunc: sklog.Warningf}
)

Functions

func DebugString

func DebugString(command *Command) string

DebugString returns the Env, Name, and Args of command joined with spaces. Does not perform any quoting.

func DefaultRun

func DefaultRun(ctx context.Context, command *Command) error

DefaultRun can be passed to SetRunForTesting to go back to running commands as normal.

func GetRunFn

func GetRunFn(ctx context.Context) func(context.Context, *Command) error

GetRunFn retrieves the function used to run commands for this context.

func IsTimeout

func IsTimeout(err error) bool

IsTimeout returns true if the specified error was raised due to a command timing out.

func LookPath

func LookPath(file, path string) (string, error)

LookPath searches for an executable named file in the directories named by the path argument. Implementation is taken directly from the os/exec package but modified to search given path argument instead of os.Getenv("PATH").

func NewContext

func NewContext(ctx context.Context, runFn func(context.Context, *Command) error) context.Context

NewContext returns a context.Context instance which uses the given function to run Commands.

func NoInterruptContext

func NoInterruptContext(ctx context.Context) context.Context

NoInterruptContext returns a context.Context instance which launches subprocesses in a difference process group so that they are not killed when this process is killed.

On Windows, this function just returns withoutCancel(ctx).

func Run

func Run(ctx context.Context, command *Command) error

Run runs command and waits for it to finish. If any failure, returns non-nil. If a timeout was specified, returns an error once the command has exceeded that timeout.

func RunCommand

func RunCommand(ctx context.Context, command *Command) (string, error)

RunCommand executes the given command and returns the combined stdout and stderr. May also return an error if the command exited with a non-zero status or there is any other error.

func RunCwd

func RunCwd(ctx context.Context, cwd string, args ...string) (string, error)

RunCwd executes the given command in the given directory. Returns the combined stdout and stderr. May also return an error if the command exited with a non-zero status or there is any other error.

func RunSimple

func RunSimple(ctx context.Context, commandLine string) (string, error)

RunSimple executes the given command line string; the command being run is expected to not care what its current working directory is. Returns the combined stdout and stderr. May also return an error if the command exited with a non-zero status or there is any other error.

func WithRetryContext

func WithRetryContext(ctx context.Context, settings backoff.BackOff) context.Context

WithRetryContext enables retries with exponential backoff according to the given settings.

Types

type Command

type Command struct {
	// Name of the command, as passed to osexec.Command. Can be the path to a binary or the
	// name of a command that osexec.Lookpath can find.
	Name string
	// Arguments of the command, not including Name.
	Args []string
	// The environment of the process. If nil, the current process's environment is used.
	Env []string
	// If Env is non-nil, adds the current process's entire environment to Env, excluding
	// variables that are set in Env.
	InheritEnv bool
	// If Env is non-nil, adds the current process's PATH to Env. Do not include PATH in Env.
	InheritPath bool
	// The working directory of the command. If nil, runs in the current process's current
	// directory.
	Dir string
	// See docs for osexec.Cmd.Stdin.
	Stdin io.Reader
	// If true, duplicates stdout of the command to WriteInfoLog.
	LogStdout bool
	// Sends the stdout of the command to this Writer, e.g. os.File or bytes.Buffer.
	Stdout io.Writer
	// If true, duplicates stderr of the command to WriteWarningLog.
	LogStderr bool
	// Sends the stderr of the command to this Writer, e.g. os.File or bytes.Buffer.
	Stderr io.Writer
	// Sends the combined stdout and stderr of the command to this Writer, in addition to
	// Stdout and Stderr. Only one goroutine will write at a time. Note: the Go runtime seems to
	// combine stdout and stderr into one stream as long as LogStdout and LogStderr are false
	// and Stdout and Stderr are nil. Otherwise, the stdout and stderr of the command could be
	// arbitrarily reordered when written to CombinedOutput.
	CombinedOutput io.Writer
	// Time limit to wait for the command to finish. No limit if not specified.
	Timeout time.Duration
	// Whether to log when the command starts.
	Verbose Verbosity
	// SysProcAttr holds optional, operating system-specific attributes.
	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
	SysProcAttr *syscall.SysProcAttr
}

func ParseCommand

func ParseCommand(commandLine string) Command

ParseCommand divides commandLine at spaces; treats the first token as the program name and the other tokens as arguments. Note: don't expect this function to do anything smart with quotes or escaped spaces.

type CommandCollector

type CommandCollector struct {
	// contains filtered or unexported fields
}

CommandCollector collects arguments to the Run method for later inspection. Safe for use in multiple goroutines as long as the function passed to SetDelegateRun is.

Example usage:

mock := exec.CommandCollector{}
ctx := exec.NewContext(context.Background(), mock.Run)
err := exec.Run(ctx, &exec.Command{
  Name: "touch",
  Args: []string{"/tmp/file"},
})
assert.Equal(t, "touch /tmp/file"", exec.DebugString(mock.Commands()[0]))

func (*CommandCollector) ClearCommands

func (c *CommandCollector) ClearCommands()

ClearCommands resets the commands seen thus far.

func (*CommandCollector) Commands

func (c *CommandCollector) Commands() []*Command

Commands returns a copy of the commands that have been run up to this point.

func (*CommandCollector) Run

func (c *CommandCollector) Run(ctx context.Context, command *Command) error

Run collects command into c and delegates to the function specified by SetDelegateRun. Returns nil if SetDelegateRun has not been called. The command will be visible in Commands() before the SetDelegateRun function is called.

func (*CommandCollector) SetDelegateRun

func (c *CommandCollector) SetDelegateRun(delegateRun func(context.Context, *Command) error)

SetDelegateRun allows some custom function to be executed when Run is called on this object. By default, nothing will happen apart from storing the command.

type Process

type Process interface {
	Kill() error
}

func RunIndefinitely

func RunIndefinitely(command *Command) (Process, <-chan error, error)

RunIndefinitely starts the command and then returns. Clients can listen for the command to end on the returned channel or kill the process manually using the Process handle. The timeout param is ignored if it is set. If starting the command returns an error, that error is returned.

type Verbosity

type Verbosity int
const (
	Info Verbosity = iota
	Debug
	Silent
)

type WriteLog

type WriteLog struct {
	LogFunc func(format string, args ...interface{})
}

WriteLog implements the io.Writer interface and writes to the given log function.

func (WriteLog) Write

func (wl WriteLog) Write(p []byte) (n int, err error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL