github.com/haraldrudell/parl@v0.4.176/pexec/exec-stream.go (about)

     1  /*
     2  © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pexec
     7  
     8  import (
     9  	"context"
    10  	"errors"
    11  	"io"
    12  )
    13  
    14  var ErrArgsListEmpty = errors.New("args list empty")
    15  
    16  // ExecStream executes a system command using the exec.Cmd type and flexible streaming.
    17  //   - ExecStream blocks during command execution
    18  //   - ExecStream returns any error occurring during launch or execution including
    19  //     errors in copy threads
    20  //   - successful exit is: statusCode == 0, isCancel == false, err == nil
    21  //   - statusCode may be set by the process but is otherwise:
    22  //   - — 0 successful exit
    23  //   - — -1 process was killed by signal such as ^C or SIGTERM
    24  //   - context cancel exit is: statusCode == -1, isCancel == true, err == nil
    25  //   - failure exit is: statusCode != 0, isCancel == false, err != nil
    26  //   - —
    27  //   - args is the command followed by arguments.
    28  //   - args[0] must specify an executable in the file system.
    29  //     env.PATH is used to resolve the command executable
    30  //   - if stdin stdout or stderr are nil, the are /dev/null
    31  //     Additional threads are used to copy data when stdin stdout or stderr are non-nil
    32  //   - os.Stdin os.Stdout os.Stderr can be provided
    33  //   - for stdout and stderr pio has usable types:
    34  //   - — pio.NewWriteCloserToString
    35  //   - — pio.NewWriteCloserToChan
    36  //   - — pio.NewWriteCloserToChanLine
    37  //   - — pio.NewReadWriteCloserSlice
    38  //   - any stream provided is not closed. However, upon return from ExecStream all i/o operations
    39  //     have completed and streams may be closed as the case may be
    40  //   - ctx is used to kill the process (by calling os.Process.Kill) if the context becomes
    41  //     done before the command completes on its own
    42  //   - use ExecStream with parl.EchoModerator
    43  //   - if system commands slow down or lock-up, too many (dozens) invoking goroutines
    44  //     may cause increased memory consumption, thrashing or exhaust of file handles, ie.
    45  //     an uncontrollable host state
    46  func ExecStream(stdin io.Reader, stdout io.WriteCloser, stderr io.WriteCloser,
    47  	ctx context.Context, args ...string) (statusCode int, isCancel bool, err error) {
    48  	return ExecStreamFull(stdin, stdout, stderr, nil, ctx, nil, nil, args...)
    49  }