我正在寻找一种在clojure中启动子进程的方法(java很好),并将其输出直接发送到stdout实时。我能找到的最接近的是用于clojure的Conch库,它允许您将输出发送到*out*
,但在该过程完成运行之前它实际上并不显示输出。
答案 0 :(得分:5)
不确定是否有方便的Clojure包装:
(->> (.. Runtime getRuntime (exec "ls") getInputStream)
java.io.InputStreamReader.
java.io.BufferedReader.
line-seq
(map println))
在实践中值得注意的是,你需要读取stdin和stderr 定期或当其中一个缓冲区填满时,进程可能会挂起。
答案 1 :(得分:4)
我将Arthur的答案标记为正确,因为它引导我找到解决方案,它基本上是人们在基本情况下想要的。我最终建立了一个更大的方法,虽然做得更多,并且我想把它放在这里以防其他人发现它有用
(defn- print-return-stream
[stream]
(let [stream-seq (->> stream
(java.io.InputStreamReader.)
(java.io.BufferedReader.)
line-seq)]
(doall (reduce
(fn [acc line]
(println line)
(if (empty? acc) line (str acc "\n" line)))
""
stream-seq))))
(defn exec-stream
"Executes a command in the given dir, streaming stdout and stderr to stdout,
and once the exec is finished returns a vector of the return code, a string of
all the stdout output, and a string of all the stderr output"
[dir command & args]
(let [runtime (Runtime/getRuntime)
proc (.exec runtime (into-array (cons command args)) nil (File. dir))
stdout (.getInputStream proc)
stderr (.getErrorStream proc)
outfut (future (print-return-stream stdout))
errfut (future (print-return-stream stderr))
proc-ret (.waitFor proc)]
[proc-ret @outfut @errfut]
))