func prepareCommand(session *ssh.Session, cmd *command) 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.Stdout == nil { session.Stdout = &cmd.stdout } else { session.Stdout = cmd.Stdout } if cmd.Stdin != nil { session.Stdin = cmd.Stdin } if cmd.Stderr == nil { session.Stderr = &cmd.stderr } else { session.Stderr = cmd.Stderr } return nil }
func (s *sshConn) runSudoCommand(sess *ssh.Session, stdin io.Writer, cmd string) error { // Wrap the output if s.DebugEnabled() { debugOutWriter := util.NewDebugLogWriter("SSH OUT:", s.Context) if sess.Stdout != nil { sess.Stdout = io.MultiWriter(sess.Stdout, debugOutWriter) } else { sess.Stdout = debugOutWriter } debugErrWriter := util.NewDebugLogWriter("SSH ERR:", s.Context) if sess.Stderr != nil { sess.Stderr = io.MultiWriter(sess.Stderr, debugErrWriter) } else { sess.Stderr = debugErrWriter } } // We need a checker to enter the password passwordTyper := util.NewExpectListener(stdin, shell.SudoPasswordPromptMatch, s.server.SSH.Pass+"\n") if sess.Stdout == nil { sess.Stdout = passwordTyper } else { sess.Stdout = io.MultiWriter(sess.Stdout, passwordTyper) } if sess.Stderr == nil { sess.Stderr = passwordTyper } else { sess.Stderr = io.MultiWriter(sess.Stderr, passwordTyper) } if err := sess.Run("sudo -S " + cmd); err != nil { return fmt.Errorf("Error running command %v: %v", cmd, err) } return nil }
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 }
//NewSSHClientSession creates a new ssh session instance func NewSSHClientSession(s *ssh.Session, in io.Reader) *SSHClientSession { out := new(bytes.Buffer) err := new(bytes.Buffer) s.Stdin = in s.Stdout = out s.Stderr = err return &SSHClientSession{s, in, out, err} }
func sshExecNative(c conf.ServerInfo, cmd string, sudo bool) (result execResult) { result.Servername = c.ServerName result.Host = c.Host result.Port = c.Port var client *ssh.Client var err error if client, err = sshConnect(c); err != nil { result.Error = err result.ExitStatus = 999 return } defer client.Close() var session *ssh.Session if session, err = client.NewSession(); err != nil { result.Error = fmt.Errorf( "Failed to create a new session. servername: %s, err: %s", c.ServerName, err) result.ExitStatus = 999 return } defer session.Close() // http://blog.ralch.com/tutorial/golang-ssh-connection/ 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", 400, 256, modes); err != nil { result.Error = fmt.Errorf( "Failed to request for pseudo terminal. servername: %s, err: %s", c.ServerName, err) result.ExitStatus = 999 return } var stdoutBuf, stderrBuf bytes.Buffer session.Stdout = &stdoutBuf session.Stderr = &stderrBuf cmd = decolateCmd(c, cmd, sudo) if err := session.Run(cmd); err != nil { if exitErr, ok := err.(*ssh.ExitError); ok { result.ExitStatus = exitErr.ExitStatus() } else { result.ExitStatus = 999 } } else { result.ExitStatus = 0 } result.Stdout = stdoutBuf.String() result.Stderr = stderrBuf.String() result.Cmd = strings.Replace(cmd, "\n", "", -1) return }
func sshExecNative(c conf.ServerInfo, cmd string, sudo bool, log ...*logrus.Entry) (result sshResult) { logger := getSSHLogger(log...) cmd = decolateCmd(c, cmd, sudo) logger.Debugf("Command: %s", strings.Replace(maskPassword(cmd, c.Password), "\n", "", -1)) var client *ssh.Client var err error client, err = sshConnect(c) defer client.Close() var session *ssh.Session if session, err = client.NewSession(); err != nil { logger.Errorf("Failed to new session. err: %s, c: %s", err, pp.Sprintf("%v", c)) result.ExitStatus = 999 return } defer session.Close() // http://blog.ralch.com/tutorial/golang-ssh-connection/ 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", 400, 256, modes); err != nil { logger.Errorf("Failed to request for pseudo terminal. err: %s, c: %s", err, pp.Sprintf("%v", c)) result.ExitStatus = 999 return } var stdoutBuf, stderrBuf bytes.Buffer session.Stdout = &stdoutBuf session.Stderr = &stderrBuf if err := session.Run(cmd); err != nil { if exitErr, ok := err.(*ssh.ExitError); ok { result.ExitStatus = exitErr.ExitStatus() } else { result.ExitStatus = 999 } } else { result.ExitStatus = 0 } result.Stdout = stdoutBuf.String() result.Stderr = stderrBuf.String() result.Host = c.Host result.Port = c.Port logger.Debugf( "SSH executed. cmd: %s, err: %#v, status: %d\nstdout: \n%s\nstderr: \n%s", maskPassword(cmd, c.Password), err, result.ExitStatus, result.Stdout, result.Stderr) return }