func RunCommandWithOutput(session *ssh.Session, log logrus.FieldLogger, command string, w io.Writer) (err error) {
	defer func() {
		if err != nil && session != nil {
			errClose := session.Close()
			if errClose != nil {
				log.WithError(err).Error("failed to close SSH session")
			}
		}
	}()
	var stderr io.Reader
	stderr, err = session.StderrPipe()
	if err != nil {
		return trace.Wrap(err)
	}
	var stdout io.Reader
	stdout, err = session.StdoutPipe()
	if err != nil {
		return trace.Wrap(err)
	}
	var wg sync.WaitGroup
	wg.Add(2)
	errCh := make(chan error, 2)
	sink := make(chan string)
	done := make(chan struct{})
	go func() {
		errCh <- stream(stdout, sink)
		wg.Done()
	}()
	go func() {
		errCh <- stream(stderr, sink)
		wg.Done()
	}()
	go func() {
		wg.Wait()
		close(errCh)
	}()
	go func() {
		w := bufio.NewWriter(w)
		for line := range sink {
			_, err := w.Write([]byte(line))
			if err != nil {
				log.Errorf("failed to write to w: %v", err)
			}
		}
		w.Flush()
		close(done)
	}()
	err = session.Start(command)
	if err != nil {
		return trace.Wrap(err, "failed to start %q", command)
	}
	err = session.Wait()
	session.Close()
	session = nil  
	for err := range errCh {
		if err != nil {
			log.Errorf("failed to stream: %v", err)
		}
	}
	close(sink)
	<-done
	return trace.Wrap(err)
}
RunCommandWithOutput executes the specified command in given session and
streams session's Stderr/Stdout into w.
The function takes ownership of session and will destroy it upon completion of
the command
package sshutils
import (
	"bufio"
	"io"
	"io/ioutil"
	"net"
	"os"
	"sync"
	"time"
	"github.com/gravitational/robotest/lib/defaults"
	"github.com/gravitational/trace"
	"github.com/sirupsen/logrus"
	"golang.org/x/crypto/ssh"
)
func Client(addr, user string, signer ssh.Signer) (*ssh.Client, error) {
	return client(addr, user, signer, realTimeoutDialer)
}
func Connect(addr, user string, signer ssh.Signer) (*ssh.Session, error) {
	client, err := Client(addr, user, signer)
	if err != nil {
		return nil, trace.Wrap(err)
	}
	session, err := client.NewSession()
	if err != nil {
		return nil, trace.Wrap(err)
	}
	return session, nil
}