pexec

package
v0.4.179 Latest Latest
Warning

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

Go to latest
Published: May 26, 2024 License: ISC Imports: 16 Imported by: 0

Documentation

Overview

Package pexec provides streaming, context-cancelable system command execution

Index

Constants

View Source
const (
	// [ExitErrorData.ExitErrorString] should include standard error output
	ExitErrorIncludeStderr = true
	// status code 1, which in POSIX means a general error
	StatusCode1 = 1
)
View Source
const (
	// the status code of a process terminated by signal
	TerminatedBySignal = -1
)

Variables

View Source
var (
	// [ExecStreamFull] env: use the environment of the parent process
	DefaulEnv []string
	// [ExecStreamFull] startCallback: no startCallback
	NoStartCallback StartCallback
	// [ExecStreamFull] stdin: no stdin
	NoStdin io.Reader
	// [ExecStreamFull] stdout: no stdout
	NoStdout io.Writer
	// [ExecStreamFull] stderr: no stderr
	NoStderr io.Writer
	// [ExecStreamFull] extraFiles: no extraFiles
	NoExtraFiles []*os.File
)
View Source
var ErrArgsListEmpty = errors.New("args list empty")
View Source
var NoExecBlockingStdin []byte

Functions

func ExecBlocking added in v0.4.87

func ExecBlocking(stdin []byte, wantStdout Stdouts, wantStderr Stderrs, ctx context.Context, args ...string) (stdout, stderr *bytes.Buffer, err error)

ExecBlocking executes a system command with independent control over stdin stdout stderr

  • if stdin is nil, no stdin is provided to command
  • if wantStdout is true, stdout contains any command output, if false stdout nil
  • if wantStderr is true, stderr contains any command error output, if false stderr nil

func ExecStream

func ExecStream(stdin io.Reader, stdout io.WriteCloser, stderr io.WriteCloser,
	ctx context.Context, args ...string) (statusCode int, isCancel bool, err error)

ExecStream executes a system command using the exec.Cmd type and flexible streaming.

  • ExecStream blocks during command execution
  • ExecStream returns any error occurring during launch or execution including errors in copy threads
  • successful exit is: statusCode == 0, isCancel == false, err == nil
  • statusCode may be set by the process but is otherwise:
  • — 0 successful exit
  • — -1 process was killed by signal such as ^C or SIGTERM
  • context cancel exit is: statusCode == -1, isCancel == true, err == nil
  • failure exit is: statusCode != 0, isCancel == false, err != nil
  • args is the command followed by arguments.
  • args[0] must specify an executable in the file system. env.PATH is used to resolve the command executable
  • if stdin stdout or stderr are nil, the are /dev/null Additional threads are used to copy data when stdin stdout or stderr are non-nil
  • os.Stdin os.Stdout os.Stderr can be provided
  • for stdout and stderr pio has usable types:
  • — pio.NewWriteCloserToString
  • — pio.NewWriteCloserToChan
  • — pio.NewWriteCloserToChanLine
  • — pio.NewReadWriteCloserSlice
  • any stream provided is not closed. However, upon return from ExecStream all i/o operations have completed and streams may be closed as the case may be
  • ctx is used to kill the process (by calling os.Process.Kill) if the context becomes done before the command completes on its own
  • use ExecStream with parl.EchoModerator
  • if system commands slow down or lock-up, too many (dozens) invoking goroutines may cause increased memory consumption, thrashing or exhaust of file handles, ie. an uncontrollable host state

func ExecStreamFull added in v0.4.38

func ExecStreamFull(
	stdin io.Reader, stdout io.Writer, stderr io.Writer,
	env []string, ctx context.Context, startCallback StartCallback, extraFiles []*os.File,
	args ...string,
) (statusCode int, isCancel bool, err error)

ExecStreamFull executes a system command using the exec.Cmd type and flexible streaming

  • ExecStreamFull makes streaming exec.Cmd easy to use
  • args: the command and its arguments. args[0] empty is error. If args[0] does not contain path, the command is resolved using the parent process’ env.PATH
  • stdin: an io.Reader producing the new process’ standard input.
  • — stdin be os.Stdin if the parent process does not use its standard input
  • — stdin can be [pio.EofReader] which is a standard input that is open but does not provide any input
  • — If stdin is nil, stdin is /dev/null meaning the sub-process’ standard input is closed which for some commands cause immediate process termination
  • —ExecStreamFull does not close a non-nil stdin but its use has ceased upon return
  • stdout: an io.Writer receiving the process’ standard output
  • — stdout can be os.Stdout causing the sub-process’ output to appear on the terminal
  • — If stdout is nil, the sub-process’ output is discarded
  • — ExecStreamFull does not close stdout but its use has ceased upon return
  • stderr: an io.Writer receiving the process’ standard error
  • — stderr can be os.Stderr causing the sub-process’ output to appear on the terminal
  • — If stderr is nil, the new process’ error output is discarded. However, on process error exit, stderr output is available in the returned error value
  • — ExecStreamFull does not close stderr but its use has ceased upon return
  • env: an environment for the process. If env is nil, the new process uses the current process’ environment
  • ctx: a context that can be used to terminate the process using SIGKILL. ctx nil is panic
  • startCallback: an optional callback invoked immediately after process start exec.Cmd.Start
  • extraFiles: an optional list of streams for the process’ file descriptors 3…
  • statusCode: the process’ exit code:
  • — 0 on successful process termination
  • TerminatedBySignal -1 on process terminated by signal such as ^C SIGINT or SIGTERM
  • — otherwise, a command-specific exit value
  • isCancel: true if context cancel terminated the process with SIGKILL or a stream-copying error occurred
  • err: any occurring error
  • upon return from ExecStreamFull there are 5 outcomes:
  • — successful exit: statusCode == 0, err == nil
  • — failure exit: statusCode != 0, isCancel == false. statusCode is the command-specific value provided by sub-process exit. err is the value returned by exec.Cmd.Wait upon process exit. If statusCode is pexec.TerminatedBySignal -1, the process was terminated by signal. The signal value can be obtained from err using pexec.ExitError
  • — context cancel: isCancel == true, err == nil. statusCode is pexec.TerminatedBySignal -1
  • — stream copying error: isCancel == true, err != nil statusCode is pexec.TerminatedBySignal -1
  • — other error condition: err != nil, statusCode == 0
  • ExecStreamFull blocks during command execution until:
  • — the started sub-process terminates
  • — ctx context is canceled causing the process to be terminated by signal unix.SIGKILL
  • — the process’ context is canceled due to an error ocurring in stream-copying threads
  • ExecStreamFull may fail prior to exec.Cmd.Wait command-execution:
  • — args does not contain a valid command
  • — an error occured during stream-copying thread creation
  • exec.Cmd.Start returned an error occuring prior to process start
  • Up to 3 stream-copying threads are used to copy data when stdin, stdout or stderr are non-nil and not os.Stdin, os.Stdout or os.Stderr respectively
  • for stdout and stderr, the [pio] package has usable types:
  • — [pio.NewWriteCloserToString]
  • — [pio.NewWriteCloserToChan]
  • — [pio.NewWriteCloserToChanLine]
  • — [pio.NewReadWriteCloserSlice]
  • parl.EchoModerator can be use with ExecStreamFull:
  • — if system commands slow down or lock-up, too many (dozens) invoking goroutines may cause increased memory consumption, thrashing or exhaust of file handles, ie. an uncontrollable host state
  • — EchoModerator notifies of slow or hung commands and limits parallelism

func ExitError added in v0.4.40

func ExitError(err error) (hasStatusCode bool, statusCode int, signal unix.Signal, stderr []byte)

ExitError returns information on why the exec.Cmd.Start process terminated

  • if hasStatusCode is true, the process terminated with a status code
  • if hasStatusCode is false, exec.Cmd.Start failed prior to launch
  • if StatusCode has value -1 or pexec.TerminatedBySignal, the process terminated due to the signal signal. Common signals are:
  • — unix.SIGINT from ^C
  • — unix.SIGKILL from context termination
  • — unix.SIGTERM from operating-system process-termination

func NewCmdContainer added in v0.4.179

func NewCmdContainer() (cmd *CmdContainer, startCallback StartCallback)

NewCmdContainer returns a thread-safe container for the exec.Cmd value

Types

type CmdContainer added in v0.4.179

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

CmdContainer is a thread-safe container for the exec.Cmd value

func (*CmdContainer) Ch added in v0.4.179

func (c *CmdContainer) Ch() (ch parl.AwaitableCh)

Ch awaits process start when the Cmd value is available

func (*CmdContainer) Cmd added in v0.4.179

func (c *CmdContainer) Cmd() (execCmd *exec.Cmd)

Cmd returns the exec.Cmd value, available after process start

func (*CmdContainer) Err added in v0.4.179

func (c *CmdContainer) Err() (err error)

Cmd returns any error from exec.Cmd.Start

type ExitErrorData added in v0.4.106

type ExitErrorData struct {
	// the original error
	Err error
	// Err interpreted as ExitError, possibly nil
	ExitErr *exec.ExitError
	// status code in ExitError, possibly 0
	StatusCode int
	// signal in ExitError, possibly 0
	Signal unix.Signal
	// stderr in ExitError or from argument, possibly nil
	Stderr []byte
}

ExitErrorData provides additional detail on pexec.ExitError values

func NewExitErrorData added in v0.4.106

func NewExitErrorData(err error, stderr ...[]byte) (exitErrorData *ExitErrorData)

NewExitErrorData returns parse-once data on a possible ExitError

  • if ExitErr field is nil or IsExitError method returns false, err does not contain an ExitError
  • the returned value is an error implementation

func (*ExitErrorData) AddStderr added in v0.4.111

func (e *ExitErrorData) AddStderr(err error) (err2 error)

AddStderr adds standard error output at the end of the error message for err. Also ensures stack trace.

  • ExitError has standard error if the Output method was used
  • NewExitErrorData can also have been provided stderr

func (*ExitErrorData) Error added in v0.4.106

func (e *ExitErrorData) Error() (exitErrorMessage string)

the Error method returns the message from any ExitError, otherwise empty string

  • Error also makes ExitErrorData implementing the error interface

func (*ExitErrorData) ExitErrorString added in v0.4.106

func (e *ExitErrorData) ExitErrorString(includeStderr ...bool) (errS string)

ExitErrorString returns the ExitError error message and data from Err and stderr, not an error value

  • for non-signal: “status code: 1 ‘read error’”
  • for signal: “signal: "abort trap" ‘signal: abort trap’”
  • the error message for err: “message: ‘failure’”
  • stderr if non-empty from ExitErr or stderr argument and includeStderr is ExitErrorIncludeStderr:
  • “stderr: ‘I/O error’”
  • returned value is never empty

func (*ExitErrorData) IsExitError added in v0.4.106

func (e *ExitErrorData) IsExitError() (isExitError bool)

IsExitError returns true if an pexec.ExitError is present

  • false if Err was nil or some other type of error

func (*ExitErrorData) IsSignalKill added in v0.4.106

func (e *ExitErrorData) IsSignalKill() (isSignalKill bool)

IsSignalKill returns true if the err error chain contains an ExitError with signal kill

  • signal kill is the response to a command’s context being canceled. This should be checked together with context.Context.Err
  • SIGKILL can also be sent to the process by the operating system trying to reclaim memory or by other processes

func (*ExitErrorData) IsStatusCode1 added in v0.4.106

func (e *ExitErrorData) IsStatusCode1() (is1 bool)

IsStatusCode1 returns if the err error chain contains an ExitError that indicates status code 1

  • Status code 1 indicates an unspecified failure of a process
  • Success has no ExitError and status code 0
  • Terminated by signal is status code -1
  • Input syntax error is status code 2

type StartCallback added in v0.4.104

type StartCallback interface {
	// StartResult is invoked by [ExecStreamFull] unless it fails
	// prior to Start
	//	- StartResult receives the command-description and
	//		process data along with any error occurring during Start
	//	- if err is nil, the command sub-process did start
	//	- StartResult must be thread-safe
	StartResult(execCmd *exec.Cmd, err error)
}

ExecStreamFull startCallback: the signature of startCallback

type Stderrs added in v0.4.87

type Stderrs uint8
const (
	NoExecBlockingStderr Stderrs = iota + 1
	WantStderr
	StderrIsError
)

type Stdouts added in v0.4.87

type Stdouts bool
const (
	NoExecBlockingStdout Stdouts = false
	WantStdout           Stdouts = true
)

Jump to

Keyboard shortcuts

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