title: SSH: is it possible to get STDERR from the session with pseudo-terminal?
body: <p>This question is about <code>golang.org/x/crypto/ssh</code> package and maybe pseudo-terminal behaviour.</p>
  
  <p><strong>The code</strong></p>
  
  <p>Here is the demo code. You can run it on your local machine just change credentials to access SSH.</p>
  
  <pre><code>package main
  
  import (
      "bufio"
      "fmt"
      "golang.org/x/crypto/ssh"
      "io"
  )
  
  func main() {
      var pipe io.Reader
      whichPipe := "error" // error or out
  
      address := "192.168.1.62:22"
      username := "username"
      password := "password"
  
      sshConfig := &amp;ssh.ClientConfig{
          User: username,
          Auth: []ssh.AuthMethod{ssh.Password(password)},
      }
  
      connection, err := ssh.Dial("tcp", address, sshConfig)
      if err != nil {
          panic(err)
      }
  
      session, err := connection.NewSession()
      if err != nil {
          panic(err)
      }
  
      modes := ssh.TerminalModes{
          ssh.ECHO: 0,
          ssh.ECHOCTL: 0,
          ssh.TTY_OP_ISPEED: 14400,
          ssh.TTY_OP_OSPEED: 14400,
      }
  
      if err := session.RequestPty("xterm", 80, 0, modes); err != nil {
          session.Close()
          panic(err)
      }
  
      switch whichPipe {
      case "error":
          pipe, _ = session.StderrPipe()
      case "out":
          pipe, _ = session.StdoutPipe()
      }
  
      err = session.Run("whoami23")
  
      scanner := bufio.NewScanner(pipe)
      for scanner.Scan() {
          fmt.Println(scanner.Text())
      }
  }
  </code></pre>
  
  <p><strong>Actual result</strong></p>
  
  <p>Empty line</p>
  
  <p><strong>Expected result</strong></p>
  
  <p><code>bash: whoami23: command not found</code></p>
  
  <p><strong>Current "solution"</strong></p>
  
  <p>To get expected result you have two options:</p>
  
  <ol>
  <li>Change <code>whichPipe</code> value to <code>out</code>. Yes, all errors going to stdout in case if you use <code>tty</code>.</li>
  <li>Remove <code>session.RequestPty</code>. But in my case, I need to run <code>sudo</code> commands which require <code>tty</code> (servers are out of my control so I can't disable this requirement).</li>
  </ol>
  
  <p>I use third way. I check <code>err</code> from <code>err = session.Run("whoami23")</code> and if it's not <code>nil</code> I mark content of <code>session.StdoutPipe()</code> as STDERR one.</p>
  
  <p>But this method has limits. For example, if I run something like <code>sudo sh -c 'uname -r; whoami23;'</code> the whole result will be marked as error while <code>uname -r</code> returns output to STDOUT.</p>
  
  <p><strong>The question</strong></p>
  
  <p>While the behaviour looks logical to me (all that SSH client sees from pty is output without differentiations) I'm still not sure if I may miss something and there is a trick that allows to split these outputs.</p>