sirthias / scala-ssh

Remote shell access via SSH for your Scala applications
Apache License 2.0
233 stars 52 forks source link

Long running command does not come back and does not stream #22

Open rleibman opened 9 years ago

rleibman commented 9 years ago

I tried this

SSH("192.168.1.5") {
  client =>
    val result = client.exec("find .").right.get
    val stream = new SequenceInputStream(result.stdOutStream, result.stdErrStream)
    val buff = new BufferedSource(stream)
    buff.getLines().foreach { println }
}

And I do not get what I expect (the results of the find, and it works if I do something smaller, like "ls ~/"). Instead I get a bunch of the following in the log:

21:55:25.621 [reader] DEBUG n.s.s.c.channel.Window$Remote - Increasing by 2097152 up to 2097152 21:55:25.621 [reader] DEBUG net.schmizz.concurrent.Promise - Setting <<chan#0 / chanreq for exec>> to SOME 21:55:25.622 [ScalaTest-main-running-SSHTest] DEBUG net.schmizz.concurrent.Promise - Awaiting <<chan#0 / close>> 21:55:25.633 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2093056 21:55:25.636 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2088960 21:55:25.637 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2084864 21:55:25.640 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2080768 21:55:25.642 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2076672 21:55:25.644 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2072576 21:55:25.645 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2068480 21:55:25.647 [reader] DEBUG n.s.s.c.channel.Window$Local - Consuming by 4096 down to 2064384

And so on...

It's almost like reading from the streams is not really reading from them.

rleibman commented 9 years ago

Ok... so I think I'm bailing out and using sshj directly, sorry. I managed to figure out how to use sshj in a somewhat more scala way with futures, I think it would be great to change scala-ssh to use futures:

  val ssh = new SSHClient()
  ssh.loadKnownHosts()
  ssh.connect("192.168.1.5")
  ssh.authPublickey(System.getProperty("user.name"))
  val session = ssh.startSession()
  val cmd = session.exec(command)

  val streamFuture = Future {
    val stream = new SequenceInputStream(cmd.getInputStream, cmd.getErrorStream)
    while (cmd.isOpen() || stream.available() > 1) {
      if (stream.available() > 1)
        characterReader(stream.read)
    }
  }

  val commandFuture = Future {
    cmd.join
    cmd.getExitStatus
  }

  (for {
    s1 <- streamFuture
    r <- commandFuture
  } yield (r)) andThen {
    case r =>
      if (session.isOpen())
        session.close
      if (ssh.isConnected())
        ssh.disconnect
      r
  }
sirthias commented 9 years ago

Thanks for your input! A better async stream-based API would indeed be great. Maybe something based on reactive streams (www.reactive-streams.org).