Skip to content

Commit f6cd19a

Browse files
committed
Fix :out :stream in the cli namespace
Caller becomes responsible for closing the session. Closes #29
1 parent 6b001a7 commit f6cd19a

File tree

3 files changed

+80
-9
lines changed

3 files changed

+80
-9
lines changed

src/clj_ssh/cli.clj

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,14 @@ Options are:
135135
:cmd specifies a command to exec. If no cmd is given, a shell is started
136136
and input is taken from :in.
137137
:in specifies input to the remote shell. A string or a stream.
138+
138139
:out specify :stream to obtain a an [inputstream shell]
139140
specify :bytes to obtain a byte array
140141
or specify a string with an encoding specification for a
141-
result string. In the case of :stream, the shell can
142-
be polled for connected status.
142+
result string.
143+
In the case of :stream, the shell can be polled for connected
144+
status, and the session (in the :session key of the return value)
145+
must be disconnected by the caller.
143146
:username username to use for authentication
144147
:password password to use for authentication
145148
:port port to use if no session specified
@@ -152,13 +155,17 @@ sh returns a map of
152155
(let [{:keys [cmd in out username password port ssh-agent args]
153156
:or {ssh-agent *ssh-agent*}
154157
:as options} (parse-args args)
155-
session (default-session ssh-agent hostname options)]
156-
(ssh/with-connection session
157-
(ssh/ssh
158-
session
159-
(if (seq args)
160-
(merge {:cmd (string/join " " args)} options)
161-
options)))))
158+
session (default-session ssh-agent hostname options)
159+
arg (if (seq args)
160+
(merge {:cmd (string/join " " args)} options)
161+
options)]
162+
(if (= :stream (:out options))
163+
(do
164+
(ssh/connect session)
165+
(assoc (ssh/ssh session arg)
166+
:session session))
167+
(ssh/with-connection session
168+
(ssh/ssh session arg)))))
162169

163170
(defn sftp
164171
"Execute SFTP commands.

test/clj_ssh/cli_test.clj

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,34 @@
176176
(finally
177177
(.delete tmpfile1)
178178
(.delete tmpfile2))))))
179+
180+
181+
(deftest out-stream-test
182+
(testing "exec"
183+
(testing ":out :string"
184+
(let [proc (ssh "localhost" "ls")]
185+
(is (zero? (:exit proc)))
186+
(is (pos? (count (:out proc))) "no options")))
187+
(testing ":out :stream"
188+
(let [proc (ssh "localhost" "ls" :out :stream :pty true)]
189+
(is (clj-ssh.ssh/connected-channel? (:channel proc))
190+
":channel not connected")
191+
(is (> (count (slurp (:out-stream proc))) 1) ":out-stream")
192+
(Thread/sleep 100)
193+
(is (zero? (clj-ssh.ssh/exit-status (:channel proc)))
194+
"zero exit status")
195+
(clj-ssh.ssh/disconnect (:session proc)))))
196+
(testing "shell"
197+
(testing ":out :string"
198+
(let [proc (ssh "localhost" :in "ls")]
199+
(is (pos? (count (:out proc))) ":out has content")
200+
(is (zero? (:exit proc)) "zero exit status")))
201+
(testing ":out stream"
202+
(let [proc (ssh "localhost" :in "ls" :out :stream)]
203+
(is (clj-ssh.ssh/connected-channel? (:channel proc))
204+
":channel connected")
205+
(is (> (count (slurp (:out-stream proc))) 1) ":out-stream")
206+
(Thread/sleep 100)
207+
(is (zero? (clj-ssh.ssh/exit-status (:channel proc)))
208+
"zero exit status")
209+
(clj-ssh.ssh/disconnect (:session proc))))))

test/clj_ssh/ssh_test.clj

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,3 +602,36 @@
602602
(with-connection s
603603
(ssh-exec (the-session s) "ls" "" "" {})))
604604
"two hosts"))
605+
606+
607+
(deftest out-stream-test
608+
(let [s (session (ssh-agent {}) "localhost" {})]
609+
(with-connection s
610+
(testing "exec"
611+
(testing ":out :string"
612+
(let [proc (ssh s {:cmd "ls"})]
613+
(is (zero? (:exit proc)))
614+
(is (pos? (count (:out proc))) "no options")))
615+
(testing ":out :stream"
616+
(let [proc (ssh s {:cmd "ls" :out :stream :pty true})]
617+
(is (connected-channel? (:channel proc))
618+
":channel connected")
619+
(is (> (count (slurp (:out-stream proc))) 1) ":out-stream")
620+
(is (not (connected-channel? (:channel proc)))
621+
":channel not connected")
622+
(is (zero? (exit-status (:channel proc)))
623+
"zero exit status"))))
624+
(testing "shell"
625+
(testing ":out :string"
626+
(let [proc (ssh s {:in "ls"})]
627+
(is (pos? (count (:out proc))) ":out has content")
628+
(is (zero? (:exit proc)) "zero exit status")))
629+
(testing ":out stream"
630+
(let [proc (ssh s {:in "ls" :out :stream})]
631+
(is (connected-channel? (:channel proc))
632+
":channel connected")
633+
(is (> (count (slurp (:out-stream proc))) 1) ":out-stream")
634+
(is (not (connected-channel? (:channel proc)))
635+
":channel not connected")
636+
(is (zero? (exit-status (:channel proc)))
637+
"zero exit status")))))))

0 commit comments

Comments
 (0)