scala-ssh
scala-ssh copied to clipboard
Long running command does not come back and does not stream
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.
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
}
Thanks for your input! A better async stream-based API would indeed be great. Maybe something based on reactive streams (www.reactive-streams.org).