exec_streamer.go
func (e *execStreamer) StartExec() (*exec.Cmd, error) {
	x, err := NewExecutorFromName(e.ExecutorName)
	if err != nil {
		return nil, err
	}

	cmd := x.GetCommand(e.Exe, e.Args...)

	if e.Dir != "" {
		cmd.Dir = e.Dir
	}
	if len(e.Env) > 0 {
		cmd.Env = e.Env
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return nil, err
	}

	err = cmd.Start()
	if err != nil {
		return nil, err
	}

	if e.OnStarted != nil {
		e.OnStarted(&StartedDetails{
			Pid:  cmd.Process.Pid,
			Time: time.Now(),
		})
	}

	e.stdOutAndErrWaitGroup = &sync.WaitGroup{}

	e.stdOutAndErrWaitGroup.Add(1)
	stdoutScanner := bufio.NewScanner(stdout)
	go e.handleStdout(stdoutScanner)

	e.stdOutAndErrWaitGroup.Add(1)
	stderrScanner := bufio.NewScanner(stderr)
	go e.handleStderr(stderrScanner)

	return cmd, nil
}
func (e *execStreamer) StartExec() (*exec.Cmd, error) {
	x, err := NewExecutorFromName(e.ExecutorName)
	if err != nil {
		return nil, err
	}

	cmd := x.GetCommand(e.Exe, e.Args...)

	if e.Dir != "" {
		cmd.Dir = e.Dir
	}
	if len(e.Env) > 0 {
		cmd.Env = e.Env
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return nil, err
	}

	err = cmd.Start()
	if err != nil {
		return nil, err
	}

	if e.OnStarted != nil {
		e.OnStarted(&StartedDetails{
			Pid:  cmd.Process.Pid,
			Time: time.Now(),
		})
	}

	e.stdOutAndErrWaitGroup = &sync.WaitGroup{}

	e.stdOutAndErrWaitGroup.Add(1)
	stdoutScanner := bufio.NewScanner(stdout)
	go e.handleStdout(stdoutScanner)

	e.stdOutAndErrWaitGroup.Add(1)
	stderrScanner := bufio.NewScanner(stderr)
	go e.handleStderr(stderrScanner)

	return cmd, nil
}
//StartExec will execute the command using the given executor and return (without waiting for completion) with the exec.Cmd