我要做的是重复发出SSH命令。如果我执行以下操作,这可以正常工作:
(ns bla
(:require [clj-ssh.ssh :as ssh]))
(defn poll [func]
(while true
(func)
(Thread/sleep 1000)))
(defn exec-on-ssh
"Connects to a host and then does there whatever the passed command dictates"
[host command]
(let [agent (ssh/ssh-agent {})
session (ssh/session agent host {:strict-host-key-checking :no})]
(ssh/with-connection session
(poll (fn [] (let [result (ssh/ssh session {:cmd command})]
(println (get result :out))))))))
; usage:
(exec-on-ssh "some-host" "uptime | sed s/^.*average:\\ //")
但后来我有一个明确的想法,即返回一个函数,我只是传递命令和处理函数:
(defn exec-on-ssh
"Connects to a host and then does there whatever the passed command dictates"
[host]
(let [agent (ssh/ssh-agent {})
session (ssh/session agent host {:strict-host-key-checking :no})]
(ssh/with-connection session
(fn [command process-fun]
(while true
(let [result (ssh/ssh session {:cmd command})]
(process-fun (get result :out))))))))
; usage:
((exec-on-ssh "some-host") "uptime | sed s/^.*average:\\ //" println)
但这引发了以下异常:
JSchException Packet corrupt com.jcraft.jsch.Session.start_discard (Session.java:1050)
如果我理解正确,它会发生,因为当它执行任何事情时,会话已经消失了。经过一段时间的实验,看起来这是因为ssh/ssh
上的闭包。
有没有办法让会话和具备第二种方法提供的灵活性?
答案 0 :(得分:2)
您是否尝试在with-connection
内移动fn
来电?
此外,这可能不是以任何方式特定于SSH。尝试编写一些构建并在with-open
块内返回函数的代码,该文件将在退出with-open
时关闭。
我想要引起注意的是let
绑定和with-*
阻止之间的区别。后者是关于资源的,并且在他们的身体执行后关闭资源。因此,在您的特定示例中,您创建了一个资源对象,您通过关闭此对象的函数成功创建。然后关闭这里的资源,连接良好。该函数仍然引用它。它已经不再开放了。