How can I get the Ganymed SSH library to tail a file (in Clojure)?
The following code never manages to tail a file. It simply hangs waiting for reader input. Has anyone tried anything similar?
(def output (ref [] ))
(import 'ch.ethz.ssh2.Connection)
(import 'ch.ethz.ssh2.Session)
(import 'ch.ethz.ssh2.StreamGobbler)
(import 'java.lang.开发者_如何学JAVAStringBuilder)
(import 'java.io.InputStream)
(import 'java.io.BufferedReader)
(import 'java.io.InputStreamReader)
(let [connection (new Connection "hostname")]
(. connection connect)
(let [ok (. connection authenticateWithPassword "username" "password" )
session (. connection openSession )]
(. session execCommand "tail -f filename.txt")
(let [sb (StringBuilder.)
stdout (StreamGobbler. (. session getStdout))
br (BufferedReader. (InputStreamReader. stdout))
]
(future (loop [line2 (. br readLine)]
(if (= line2 nil)
nil
(do
(dosync (ref-set output (conj @output line2)))
(recur (. br readLine))))
)
)
)
)
)
I agree with Arthur. Its not clear to me how this would work in practice since the remote command will never return / finish. Try the following as an example:
> (defn never-returns []
(while true
(do (Thread/sleep 2000)
(println "i'm never going to finish")))
"done")
> (def x (future (never-returns)))
> (@x)
i'm never going to finish
i'm never going to finish
...
I think a possibly better approach would to take the threading out your client while providing a means to get access to the tail of the file asynchronously. For example, you might consider using netcat to send the output of tail -f to a socket and then periodically read from that socket in your client to get the file output. Something like this on the remote side:
tail -f filename.txt | nc -l 12000
Then in your clojure code:
(import '(java.net ServerSocket Socket))
(def client (java.net.Socket. "hostname" 12000))
(def r (java.io.BufferedReader. (java.io.InputStreamReader. (.getInputStream client))))
(println (.readLine r)) ; or capture the output
Something like that. Hope this helps.
I'm not sure a future is the best construct for starting your work thread because it blocks on deref until the work is finished
精彩评论