Example #1
27
func configureSessionIO(session *ssh.Session) error {
	fmt.Println("Requesting Pseudo Terminal")
	if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
		fmt.Println("Unable to request Pseudo Terminal")
		fmt.Println("Error : ", err.Error())
		return err
	}

	fmt.Println("Setting up STDIN")
	stdin, err := session.StdinPipe()
	if err != nil {
		fmt.Println("Unable to setup STDIN")
		fmt.Println("Error : ", err.Error())
		return err
	}
	go io.Copy(stdin, os.Stdin)

	fmt.Println("Setting up STDOUT")
	stdout, err := session.StdoutPipe()
	if err != nil {
		fmt.Println("Unable to setup STDOUT")
		fmt.Println("Error : ", err.Error())
		return err
	}
	go io.Copy(os.Stdout, stdout)

	fmt.Println("Setting up STDERR")
	stderr, err := session.StderrPipe()
	if err != nil {
		fmt.Println("Unable to setup STDERR")
		fmt.Println("Error : ", err.Error())
		return err
	}
	go io.Copy(os.Stderr, stderr)

	return nil
}
Example #2
3
// NewClient creates a new SFTP client on top of an already created
// ssh.Session.
func NewClient(s *ssh.Session) (*Client, error) {
	stdin, err := s.StdinPipe()
	if err != nil {
		return nil, err
	}
	stdout, err := s.StdoutPipe()
	if err != nil {
		return nil, err
	}
	stderr, err := s.StderrPipe()
	if err != nil {
		return nil, err
	}

	if err := s.RequestSubsystem("sftp"); err != nil {
		return nil, err
	}
	sftp := &Client{
		stdin:   stdin,
		stdout:  stdout,
		stderr:  stderr,
		chans:   &fxpChanList{},
		session: s,
	}

	if err := sftp.init(); err != nil {
		return nil, err
	}
	return sftp, nil
}
Example #3
3
func logSession(session *ssh.Session) {
	{
		r, err := session.StdoutPipe()
		if err != nil {
			exitf("failed to get stdoutPipe: %s", err)
		}
		go io.Copy(os.Stdout, r)
	}
	{
		r, err := session.StderrPipe()
		if err != nil {
			exitf("failed to get StderrPipe: %s", err)
		}
		go io.Copy(os.Stderr, r)
	}
}
Example #4
2
func tailFile(session *ssh.Session, file string, sudo bool, linec chan<- string) error {

	var command string
	if sudo {
		command = fmt.Sprintf("sudo /usr/bin/env tail -F %s", file)
	} else {
		command = fmt.Sprintf("/usr/bin/env tail -F %s", file)
	}

	var wg sync.WaitGroup
	errc := make(chan error, 3)
	consumeStream := func(r io.Reader) {
		defer wg.Done()
		scan := bufio.NewScanner(r)
		scan.Split(bufio.ScanLines)
		for scan.Scan() {
			linec <- scan.Text()
		}
		if err := scan.Err(); err != nil {
			errc <- err
		}
	}

	stderr, err := session.StderrPipe()
	if err != nil {
		return fmt.Errorf("opening stderr: %v", err)
	}
	stdout, err := session.StdoutPipe()
	if err != nil {
		return fmt.Errorf("opening stdout: %v", err)
	}

	wg.Add(1)
	go consumeStream(stderr)
	go consumeStream(stdout)

	if err := session.Start(command); err != nil {
		return err
	}
	wg.Add(1)
	go func() {
		if err := session.Wait(); err != nil {
			errc <- err
		}
	}()

	go func() {
		wg.Wait()
		close(errc)
	}()

	return <-errc
}
Example #5
2
// Get stdin, stdout, and stderr from the SSH session.
func sessionStreams(session *ssh.Session) (stdin io.WriteCloser, stdout io.Reader, stderr io.Reader, err error) {
	stdin, err = session.StdinPipe()
	if err != nil {
		return
	}
	stdout, err = session.StdoutPipe()
	if err != nil {
		return
	}
	stderr, err = session.StderrPipe()
	if err != nil {
		return
	}
	return
}
Example #6
2
func (client *SSHClient) prepareCommand(session *ssh.Session, cmd *SSHCommand) error {
	for _, env := range cmd.Env {
		variable := strings.Split(env, "=")
		if len(variable) != 2 {
			continue

		}

		if err := session.Setenv(variable[0], variable[1]); err != nil {
			return err

		}

	}

	if cmd.Stdin != nil {
		stdin, err := session.StdinPipe()
		if err != nil {
			return fmt.Errorf("Unable to setup stdin for session: %v", err)

		}
		go io.Copy(stdin, cmd.Stdin)

	}

	if cmd.Stdout != nil {
		stdout, err := session.StdoutPipe()
		if err != nil {
			return fmt.Errorf("Unable to setup stdout for session: %v", err)

		}
		go io.Copy(cmd.Stdout, stdout)

	}

	if cmd.Stderr != nil {
		stderr, err := session.StderrPipe()
		if err != nil {
			return fmt.Errorf("Unable to setup stderr for session: %v", err)

		}
		go io.Copy(cmd.Stderr, stderr)

	}

	return nil

}
Example #7
0
/**
  InitIOPipes binds session IO streams to the output
  @Deprecated
*/
func (client *Client) InitIOPipes(session *ssh.Session) error {
	stdin, err := session.StdinPipe()
	if err != nil {
		return fmt.Errorf("Unable to setup stdin for session: %v", err)
	}
	go io.Copy(stdin, os.Stdin)

	stdout, err := session.StdoutPipe()
	if err != nil {
		return fmt.Errorf("Unable to setup stdout for session: %v", err)
	}
	go io.Copy(os.Stdout, stdout)

	stderr, err := session.StderrPipe()
	if err != nil {
		return fmt.Errorf("Unable to setup stderr for session: %v", err)
	}
	go io.Copy(os.Stderr, stderr)
	return nil
}
Example #8
0
func stream(command string, session *ssh.Session) (output chan string, done chan bool, err error) {
	outReader, err := session.StdoutPipe()
	Ω(err).ShouldNot(HaveOccurred())
	errReader, err := session.StderrPipe()
	Ω(err).ShouldNot(HaveOccurred())
	outputReader := io.MultiReader(outReader, errReader)
	err = session.Start(command)
	Ω(err).ShouldNot(HaveOccurred())
	scanner := bufio.NewScanner(outputReader)
	outputChan := make(chan string)
	done = make(chan bool)
	go func(scanner *bufio.Scanner, out chan string, done chan bool) {
		defer close(outputChan)
		defer close(done)
		for scanner.Scan() {
			outputChan <- scanner.Text()
		}
		done <- true
		session.Close()
	}(scanner, outputChan, done)
	return outputChan, done, err
}
Example #9
0
// handleDownload handles message parsing to and from the session.
func (c *Client) handleUpload(session *ssh.Session, localPath string) {
	var err error

	c.scpStdinPipe, err = session.StdinPipe()
	if err != nil {
		c.addError(err)
		return
	}
	defer c.scpStdinPipe.Close()

	r, err := session.StdoutPipe()
	if err != nil {
		c.addError(err)
		return
	}

	// Wrapper to support cancellation
	c.scpStdoutPipe = &readCanceller{
		Reader: bufio.NewReader(r),
		cancel: make(chan struct{}, 1),
	}

	// This has already been used in the cmd call below
	// so it can be reused for 'end of directory' message handling
	c.DestinationPath = []string{}

	err = filepath.Walk(localPath, c.handleItem)
	if err != nil {
		c.addError(err)
		return
	}

	// End transfer
	paths := strings.Split(c.DestinationPath[0], "/")
	for range paths {
		c.sendEndOfDirectoryMessage(c.scpStdinPipe)
	}
}
		}
		Eventually(connectionFinished).Should(BeClosed())
	})

	Context("when a session is opened", func() {
		var session *ssh.Session

		BeforeEach(func() {
			var sessionErr error
			session, sessionErr = client.NewSession()

			Expect(sessionErr).NotTo(HaveOccurred())
		})

		It("can use the session to execute a command with stdout and stderr", func() {
			stdout, err := session.StdoutPipe()
			Expect(err).NotTo(HaveOccurred())

			stderr, err := session.StderrPipe()
			Expect(err).NotTo(HaveOccurred())

			err = session.Run("/bin/echo -n Hello; /bin/echo -n Goodbye >&2")
			Expect(err).NotTo(HaveOccurred())

			stdoutBytes, err := ioutil.ReadAll(stdout)
			Expect(err).NotTo(HaveOccurred())
			Expect(stdoutBytes).To(Equal([]byte("Hello")))

			stderrBytes, err := ioutil.ReadAll(stderr)
			Expect(err).NotTo(HaveOccurred())
			Expect(stderrBytes).To(Equal([]byte("Goodbye")))
Example #11
0
// handleDownload handles message parsing to and from the session.
func (c *Client) handleDownload(session *ssh.Session) {
	var err error

	c.scpStdinPipe, err = session.StdinPipe()
	if err != nil {
		c.addError(err)
		return
	}
	defer c.scpStdinPipe.Close()

	r, err := session.StdoutPipe()
	if err != nil {
		c.addError(err)
		return
	}

	// Initialize transfer
	c.sendAck(c.scpStdinPipe)

	// Wrapper to support cancellation
	c.scpStdoutPipe = &readCanceller{
		Reader: bufio.NewReader(r),
		cancel: make(chan struct{}, 1),
	}

	for {
		c.outputInfo("Reading message from source")
		msg, err := c.scpStdoutPipe.ReadString('\n')
		if err != nil {
			if err != io.EOF {
				c.addError(err)
			}
			return
		}

		// Strip nulls and new lines
		msg = strings.TrimSpace(strings.Trim(msg, "\x00"))
		c.outputInfo(fmt.Sprintf("Received: %s", msg))

		// Confirm message
		c.sendAck(c.scpStdinPipe)

		switch {
		case c.isFileCopyMsg(msg):
			// Handle incoming file
			err := c.file(msg)
			if err != nil {
				c.addError(err)
				return
			}
		case c.isDirCopyMsg(msg):
			// Handling incoming directory
			err := c.directory(msg)
			if err != nil {
				c.addError(err)
				return
			}
		case msg == endDir:
			// Directory finished, go up a directory
			c.upDirectory()
		case c.isWarningMsg(msg):
			c.addError(fmt.Errorf("Warning message: [%q]\n", msg))
			return
		case c.isErrorMsg(msg):
			c.addError(fmt.Errorf("Error message: [%q]\n", msg))
			return
		default:
			c.addError(fmt.Errorf("Unhandled message: [%q]\n", msg))
			return
		}

		// Confirm message
		c.sendAck(c.scpStdinPipe)
	}
}
Example #12
-1
func pipe(ch ssh.Channel, client *ssh.Client, session *ssh.Session, command string) (int, error) {
	targetStderr, err := session.StderrPipe()
	if err != nil {
		return -1, errors.New("fail to pipe stderr: " + err.Error())
	}
	targetStdout, err := session.StdoutPipe()
	if err != nil {
		return -1, errors.New("fail to pipe stdout: " + err.Error())
	}
	targetStdin, err := session.StdinPipe()
	if err != nil {
		return -1, errors.New("fail to pipe stdin: " + err.Error())
	}

	go io.Copy(targetStdin, ch)
	go io.Copy(ch.Stderr(), targetStderr)
	go io.Copy(ch, targetStdout)

	err = session.Start(command)
	if err != nil {
		ch.Write([]byte("Error when starting '" + command + "': " + err.Error()))
		ch.Close()
	}

	err = session.Wait()
	if err != nil {
		if err, ok := err.(*ssh.ExitError); ok {
			return err.ExitStatus(), nil
		} else {
			return -1, errors.New("failed to wait ssh command: " + err.Error())
		}
	}

	return 0, nil
}