关闭SSH会话 - 这可能吗?

时间:2016-02-03 10:19:29

标签: session ssh clojure closures

我要做的是重复发出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上的闭包。

有没有办法让会话具备第二种方法提供的灵活性?

1 个答案:

答案 0 :(得分:2)

您是否尝试在with-connection内移动fn来电?

此外,这可能不是以任何方式特定于SSH。尝试编写一些构建并在with-open块内返回函数的代码,该文件将在退出with-open时关闭。

我想要引起注意的是let绑定和with-*阻止之间的区别。后者是关于资源的,并且在他们的身体执行后关闭资源。因此,在您的特定示例中,您创建了一个资源对象,您通过关闭此对象的函数成功创建。然后关闭这里的资源,连接良好。该函数仍然引用它。它已经不再开放了。

相关问题