Stream returns one channel that combines the stdout and stderr of the command as it is run on the remote machine, and another that sends true when the command is done. The sessions and channels will then be closed.
(command string, timeout ...time.Duration)
| 351 | // as it is run on the remote machine, and another that sends true when the |
| 352 | // command is done. The sessions and channels will then be closed. |
| 353 | func (ssh_conf *MakeConfig) Stream(command string, timeout ...time.Duration) (<-chan string, <-chan string, <-chan bool, <-chan error, error) { |
| 354 | // continuously send the command's output over the channel |
| 355 | stdoutChan := make(chan string) |
| 356 | stderrChan := make(chan string) |
| 357 | doneChan := make(chan bool) |
| 358 | errChan := make(chan error) |
| 359 | |
| 360 | session, client, err := ssh_conf.Connect() |
| 361 | if err != nil { |
| 362 | return stdoutChan, stderrChan, doneChan, errChan, err |
| 363 | } |
| 364 | |
| 365 | closeBoth := func() { |
| 366 | _ = session.Close() |
| 367 | _ = client.Close() |
| 368 | } |
| 369 | |
| 370 | outReader, err := session.StdoutPipe() |
| 371 | if err != nil { |
| 372 | closeBoth() |
| 373 | return stdoutChan, stderrChan, doneChan, errChan, err |
| 374 | } |
| 375 | errReader, err := session.StderrPipe() |
| 376 | if err != nil { |
| 377 | closeBoth() |
| 378 | return stdoutChan, stderrChan, doneChan, errChan, err |
| 379 | } |
| 380 | if err = session.Start(command); err != nil { |
| 381 | closeBoth() |
| 382 | return stdoutChan, stderrChan, doneChan, errChan, err |
| 383 | } |
| 384 | |
| 385 | bufSize := ssh_conf.ReadBuffSize |
| 386 | if bufSize <= 0 { |
| 387 | bufSize = defaultBufferSize |
| 388 | } |
| 389 | stdoutScanner := bufio.NewReaderSize(outReader, bufSize) |
| 390 | stderrScanner := bufio.NewReaderSize(errReader, bufSize) |
| 391 | |
| 392 | executeTimeout := defaultTimeout |
| 393 | if len(timeout) > 0 { |
| 394 | executeTimeout = timeout[0] |
| 395 | } |
| 396 | |
| 397 | go func() { |
| 398 | defer close(doneChan) |
| 399 | defer close(errChan) |
| 400 | defer closeBoth() |
| 401 | |
| 402 | ctxTimeout, cancel := context.WithTimeout(context.Background(), executeTimeout) |
| 403 | defer cancel() |
| 404 | |
| 405 | scan := func(r *bufio.Reader, out chan<- string) { |
| 406 | defer close(out) |
| 407 | for { |
| 408 | text, readErr := r.ReadString('\n') |
| 409 | if text != "" { |
| 410 | select { |