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 }
// 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 }
// 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 }
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 }
func (this *Scp) copy(size int64, mode os.FileMode, fileName string, contents io.Reader, destination string) error { var ( session *ssh.Session err error ) ParallelController[this.Server].Session <- token session, err = this.client.NewSession() if nil != err { return errors.New("Failed to create new session" + err.Error()) } go func() { w, _ := session.StdinPipe() defer w.Close() fmt.Fprintf(w, "C%#o %d %s\n", mode, size, fileName) io.Copy(w, contents) fmt.Fprint(w, "\x00") <-ParallelController[this.Server].Session }() cmd := fmt.Sprintf("scp -t %s", destination) if err := session.Run(cmd); nil != err { return err } session.Close() return nil }
/* Expected to be invoked as a goroutine which runs in parallel to sending the ssh command to the far side. This function reads from the input buffer reader br and writes to the target stripping blank and comment lines as it goes. */ func send_script(sess *ssh.Session, argv0 string, env_file string, br *bufio.Reader) { target, err := sess.StdinPipe() // we create the pipe here so that we can close here if err != nil { fmt.Fprintf(os.Stderr, "unable to create stdin for session: %s\n", err) return } defer target.Close() if argv0 != "" { target.Write([]byte("ARGV0=\"" + argv0 + "\"\n")) // $0 isn't valid using this, so simulate $0 with argv0 } if env_file != "" { // must push out the environment first env_file, err = find_file(env_file) // find it in the path if not a qualified name if err == nil { ef, err := os.Open(env_file) if err != nil { fmt.Fprintf(os.Stderr, "ssh_broker: could not open environment file: %s: %s\n", env_file, err) } else { ebr := bufio.NewReader(ef) // get a buffered reader for the file send_file(ebr, target) ef.Close() } } else { fmt.Fprintf(os.Stderr, "ssh_broker: could not find environment file: %s: %s\n", env_file, err) } } send_file(br, target) }
func (config *Config) executeCommand(s *ssh.Session, cmd string, sudo bool) ([]byte, error) { if s.Stdout != nil { return nil, errors.New("ssh: Stdout already set") } if s.Stderr != nil { return nil, errors.New("ssh: Stderr already set") } b := newSingleWriterReader() s.Stdout = &b s.Stderr = &b done := make(chan bool) if sudo { stdInWriter, err := s.StdinPipe() if err != nil { if config.AbortOnError == true { log.Fatalf("%s", err) } return nil, err } go config.injectSudoPasswordIfNecessary(done, &b, stdInWriter) } err := s.Run(cmd) close(done) return b.Bytes(), err }
func (ssc *SSHConfig) Exec(cmd string, stdout, stderr io.Writer, input chan string) (err tree_lib.TreeError) { var ( session *ssh.Session stdin io.WriteCloser command_ended bool ) err.From = tree_lib.FROM_SSH_EXEC session, err.Err = ssc.conn.NewSession() if !err.IsNull() { return } defer session.Close() session.Stdout = stdout session.Stderr = stderr stdin, err.Err = session.StdinPipe() if !err.IsNull() { return } err.Err = session.Start(cmd) if !err.IsNull() { return } command_ended = false go func() { for !command_ended { io.Copy(stdin, bytes.NewBufferString(<-input)) } }() err.Err = session.Wait() command_ended = true return }
func copy(size int64, mode os.FileMode, fileName string, contents io.Reader, destination string, session *ssh.Session) error { defer session.Close() go func() { w, _ := session.StdinPipe() defer w.Close() fmt.Fprintf(w, "C%#o %d %s\n", mode, size, fileName) io.Copy(w, contents) fmt.Fprint(w, "\x00") }() cmd := fmt.Sprintf("scp -t %s", destination) if err := session.Run(cmd); err != nil { return err } return nil }
func writeFileToHost(session *ssh.Session, host *Host, file string, fileReader *os.File, fileInfo os.FileInfo, destination string, sessionWaitGroup *sync.WaitGroup) { defer sessionWaitGroup.Done() defer session.Close() sessionWaitGroup.Add(1) go func() { defer sessionWaitGroup.Done() mode := uint32(fileInfo.Mode().Perm()) header := fmt.Sprintf("C%04o %d %s\n", mode, fileInfo.Size(), filepath.Base(file)) OutputLocal(fmt.Sprintf("copy %s (%dMB) to %s:%s", file, fileInfo.Size()/1024/2014, host.Host, destination)) stdinPipe, _ := session.StdinPipe() defer stdinPipe.Close() _, err := stdinPipe.Write([]byte(header)) if err != nil { return } _, err = io.Copy(stdinPipe, fileReader) if err != nil { return } _, err = stdinPipe.Write([]byte{0}) if err != nil { return } }() if err := session.Run("/usr/bin/scp -trv " + destination); err != nil { fmt.Println("in here") fmt.Println(err.Error()) os.Exit(1) } }
/** 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 }
// 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) } }
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"))) }) It("returns when the process exits", func() { stdin, err := session.StdinPipe() Expect(err).NotTo(HaveOccurred()) err = session.Run("ls") Expect(err).NotTo(HaveOccurred()) stdin.Close() }) Describe("scp", func() { var ( sourceDir, generatedTextFile, targetDir string err error stdin io.WriteCloser stdout io.Reader fileContents []byte
// 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) } }
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 }
func runPipe(user, pass, host, cmd string) { fmt.Println("runPipe...") sshConfig := &ssh.ClientConfig{ User: user, Auth: []ssh.AuthMethod{ssh.Password(pass)}, } sshConfig.SetDefaults() client, err := ssh.Dial("tcp", host, sshConfig) if err != nil { // errors.Wrap(err, err.Error()) fmt.Println(err.Error()) } var session *ssh.Session session, err = client.NewSession() if err != nil { // errors.Wrap(err, err.Error()) fmt.Println(err.Error()) } defer session.Close() // modes := ssh.TerminalModes{ // ssh.ECHO: 0, // disable echoing // ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud // ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud // } // if err := session.RequestPty("xterm", 80, 40, modes); err != nil { // log.Fatal(err) // } w, err := session.StdinPipe() if err != nil { panic(err) } // r, err := session.StdoutPipe() // if err != nil { // panic(err) // } var stdoutBuf bytes.Buffer session.Stdout = &stdoutBuf // session.Run(cmd) err = session.Shell() w.Write([]byte(fmt.Sprintf("%s\n", "configure"))) w.Write([]byte(fmt.Sprintf("%s %s\n", "set interfaces ethernet eth4 description", cmd))) w.Write([]byte(fmt.Sprintf("%s\n", "commit"))) w.Write([]byte(fmt.Sprintf("%s\n", "save"))) w.Write([]byte(fmt.Sprintf("%s\n", "exit"))) w.Write([]byte(fmt.Sprintf("%s\n", "exit"))) fmt.Println(stdoutBuf.String()) }