@@ -80,7 +80,7 @@ Licensed under EPL (http://www.eclipse.org/legal/epl-v10.html)"
80
80
81
81
; ; Enable java logging of jsch when in clojure 1.2
82
82
(when-feature deftype
83
- (def ssh-log-levels
83
+ (def ^{ :dynamic true } * ssh-log-levels*
84
84
{com.jcraft.jsch.Logger/DEBUG :debug
85
85
com.jcraft.jsch.Logger/INFO :info
86
86
com.jcraft.jsch.Logger/WARN :warn
@@ -94,7 +94,7 @@ Licensed under EPL (http://www.eclipse.org/legal/epl-v10.html)"
94
94
(>= level log-level))
95
95
(log
96
96
[_ level message]
97
- (logging/log (ssh-log-levels level) message nil " clj-ssh.ssh" )))
97
+ (logging/log (* ssh-log-levels* level) message nil " clj-ssh.ssh" )))
98
98
99
99
(JSch/setLogger (SshLogger. com.jcraft.jsch.Logger/DEBUG)))
100
100
@@ -325,12 +325,18 @@ keys. All other option key pairs will be passed as SSH config options."
325
325
[#^Session session]
326
326
(open-channel session :shell ))
327
327
328
+ (defn- streams-for-out
329
+ [out]
330
+ (if (= :stream out)
331
+ (let [os (java.io.PipedOutputStream. )]
332
+ [os (java.io.PipedInputStream. os)])
333
+ [(java.io.ByteArrayOutputStream. ) nil ]))
328
334
329
335
(defn ssh-shell
330
336
" Run a ssh-shell."
331
337
[#^Session session in out opts]
332
338
(let [#^ChannelShell shell (open-channel session :shell )
333
- out-stream ( java.io.ByteArrayOutputStream. )]
339
+ [ out-stream out-inputstream] ( streams-for-out out )]
334
340
(doto shell
335
341
(.setInputStream
336
342
(if (string? in)
@@ -342,20 +348,24 @@ keys. All other option key pairs will be passed as SSH config options."
342
348
(call-method
343
349
com.jcraft.jsch.ChannelSession 'setPty [Boolean/TYPE]
344
350
shell (boolean (opts :pty ))))
345
- (with-connection shell
346
- (while (connected? shell)
347
- (Thread/sleep 100 ))
348
- [(.getExitStatus shell)
349
- (if (= :bytes out)
350
- (.toByteArray out-stream)
351
- (.toString out-stream out))])))
351
+ (if out-inputstream
352
+ (do
353
+ (connect shell)
354
+ [shell out-inputstream])
355
+ (with-connection shell
356
+ (while (connected? shell)
357
+ (Thread/sleep 100 ))
358
+ [(.getExitStatus shell)
359
+ (if (= :bytes out)
360
+ (.toByteArray out-stream)
361
+ (.toString out-stream out))]))))
352
362
353
363
(defn ssh-exec
354
364
" Run a command via ssh-exec."
355
365
[#^Session session #^String cmd in out opts]
356
366
(let [#^ChannelExec exec (open-channel session :exec )
357
- out-stream ( java.io.ByteArrayOutputStream. )
358
- err-stream ( java.io.ByteArrayOutputStream. )]
367
+ [ out-stream out-inputstream] ( streams-for-out out )
368
+ [ err-stream err-inputstream] ( streams-for-out out )]
359
369
(doto exec
360
370
(.setInputStream
361
371
(if (string? in)
@@ -369,16 +379,20 @@ keys. All other option key pairs will be passed as SSH config options."
369
379
(call-method
370
380
com.jcraft.jsch.ChannelSession 'setPty [Boolean/TYPE]
371
381
exec (boolean (opts :pty ))))
372
- (with-connection exec
373
- (while (connected? exec)
374
- (Thread/sleep 100 ))
375
- [(.getExitStatus exec)
376
- (if (= :bytes out)
377
- (.toByteArray out-stream)
378
- (.toString out-stream out))
379
- (if (= :bytes out)
380
- (.toByteArray err-stream)
381
- (.toString err-stream out))])))
382
+ (if out-inputstream
383
+ (do
384
+ (connect exec)
385
+ [exec out-inputstream err-inputstream])
386
+ (with-connection exec
387
+ (while (connected? exec)
388
+ (Thread/sleep 100 ))
389
+ [(.getExitStatus exec)
390
+ (if (= :bytes out)
391
+ (.toByteArray out-stream)
392
+ (.toString out-stream out))
393
+ (if (= :bytes out)
394
+ (.toByteArray err-stream)
395
+ (.toString err-stream out))]))))
382
396
383
397
(defn default-session [host username port password]
384
398
(doto (session-impl
@@ -409,7 +423,11 @@ cmd specifies a command to exec. If no cmd is given, a shell is started and inp
409
423
Options are
410
424
411
425
:in specifies input to the remote shell. A string or a stream.
412
- :out specify :bytes or a string with an encoding specification.
426
+ :out specify :stream to obtain a an [inputstream shell],
427
+ specify :bytes to obtain a byte array,
428
+ or specify a string with an encoding specification for a
429
+ result string. In the case of :stream, the shell can
430
+ be polled for connected status.
413
431
:return-map when followed by boolean true, sh returns a map of
414
432
:exit => sub-process's exit code
415
433
:out => sub-process's stdout (as byte[] or String)
@@ -437,14 +455,14 @@ Options are
437
455
(let [result (ssh-shell
438
456
session
439
457
(:in opts) (:out opts) (dissoc opts :in :out :cmd ))]
440
- (if (opts :return-map )
458
+ (if (and ( opts :return-map ) ( not= ( :out opts) :stream ) )
441
459
{:exit (first result) :out (second result)}
442
460
result))
443
461
(let [result (ssh-exec
444
462
session
445
463
(apply str (interpose " " (:cmd opts)))
446
464
(:in opts) (:out opts) (dissoc opts :in :out :cmd ))]
447
- (if (opts :return-map )
465
+ (if (and ( opts :return-map ) ( not= ( :out opts) :stream ) )
448
466
{:exit (first result) :out (second result) :err (last result)}
449
467
result)))
450
468
(finally
0 commit comments