cmdWorker

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2021 License: MIT Imports: 6 Imported by: 0

README

cmdWorker

cmdWorker is the Golang library wrapping github.com/go-cmd/cmd adding timeouts,periodic output parsing using callback function and ability to abort command execution from output parsing callback function.

cmdWorker should not be used for console commands with huge output because go-cmd is used in buffering mode storing all stdout and stderr output in a memory

Three configurable timeouts is supoorted:

var (
	DefTimeout      = time.Second * 120 //timeout the cmd must finished
	DefReadTimeout  = time.Second * 30  //timeout waiting new data from stdout/stderr
	DefReadInterval = time.Second * 1   //the interval outputHandler is called to process the output
)
Usage:
cw := cmdWorker.NewCmdWorker(cmdPath, []string{}, readStdout)
status, err := cw.Run(nil)

if err != nil {
    if err == cmdWorker.ErrOperation {
      fmt.Printf("%v finished with error %v", status.Cmd, status.Exit)
    } else if _, ok := err.(*cmdWorker.InterruptedError); ok {
      fmt.printf("%v interrupted")
    }
}
Another yet example:

Do a file downloading using curl with progress processing

readStdout := func(status cmdWorker.OutputStatus) bool {
        //regexp to parse the curl progress line (we need the second number)
		progressRegexp := regexp.MustCompile(`^\d+\s+(\d+)`)
		
		if len(status.newStderrLines) == 0 {
			return true
		}
		//get the last line from the output removing leading \r
		l := strings.TrimPrefix(status.newStderrLines[len(status.newStderrLines)-1], "\r")
		matches := progressRegexp.FindStringSubmatchIndex(l)
		if len(matches) > 0 {
			s := string(progressRegexp.ExpandString(nil, "$1", l, matches))
			fmt.Printf("Downloaded %v bytes\n", s)
		}
		return true
	}

//download the www.google.com index page using curl with a speed limit of 2kb/s to demonstrate long time stdout parsing
cw := cmdWorker.NewCmdWorker("curl", []string{"www.google.com", "--limit-rate", "2000", "-o", "/dev/null"}, readStdout)
status, err := cw.Run(nil)

if err != nil {
    if err == cmdWorker.ErrOperation {
        fmt.Printf("%v finished with error %v", status.Cmd, status.Exit)
    } else if _, ok := err.(*InterruptedError); ok {
        fmt.Printf("%v interrupted", status.Cmd)
    }
}

fmt.Printf("%v finished", status.Cmd)

Documentation

Index

Constants

View Source
const (
	InterruptedByTimer         = 1
	InterruptedByOutputHandler = 2
)

Variables

View Source
var (
	DefTimeout      = time.Second * 120 //timeout the cmd must finished
	DefReadTimeout  = time.Second * 30  //timeout waiting new data from stdout/stderr
	DefReadInterval = time.Second * 1   //the interval outputHandler is called to process the output
)
View Source
var (
	ErrOperation = errors.New("command finished with error")
)

Functions

This section is empty.

Types

type CmdWorker

type CmdWorker struct {
	Status gocmd.Status
	// contains filtered or unexported fields
}

func NewCmdWorker

func NewCmdWorker(cmd string, args []string, outputHandler func(OutputStatus) bool) CmdWorker

NewCmdWorker creates new worker with cmd as console command, args as command args and outputHandler callback function outputHandler calls every readInterval and used to process a command output, can be nil

func (*CmdWorker) Run

func (w *CmdWorker) Run(stdin io.Reader) (status gocmd.Status, err error)

Run starts the command and blocked until command finished or timeout happened stdin is a io.Reader where the cmd input is reading from, can be nil status is gocmd.Status struct describing running command err is nil on success, ErrOperation when command is finished with exit status != 0 or InterruptedError type when command was interrupted with timeout or by OutputHandler

func (*CmdWorker) SetOutputHandler

func (w *CmdWorker) SetOutputHandler(outputHandler func(OutputStatus) bool)

SetOutputHandler sets command's output callback which is called on every ReadInterval tick outputHandler callback should return true to continue command execution, or false to abort command execution

func (*CmdWorker) SetReadInterval

func (w *CmdWorker) SetReadInterval(t time.Duration)

SetReadInterval sets command's ReadInterval, outputHandler callback is called on every ReadInterval tick

func (*CmdWorker) SetReadTimeout

func (w *CmdWorker) SetReadTimeout(t time.Duration)

SetReadTimeout sets command read timeout

func (*CmdWorker) SetTimeout

func (w *CmdWorker) SetTimeout(t time.Duration)

SetTimeout sets command's execution timeout

func (*CmdWorker) Stop

func (w *CmdWorker) Stop()

Stops aborts the command execution

type InterruptedError

type InterruptedError struct {
	Reason int
}

func (*InterruptedError) Error

func (e *InterruptedError) Error() (str string)

type OutputStatus

type OutputStatus struct {
	NewStdoutlines []string
	NewStderrLines []string
	gocmd.Status
}

Jump to

Keyboard shortcuts

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