【发布时间】:2013-01-18 22:59:29
【问题描述】:
我正在寻找一种在 clojure 中启动子进程的方法(java 可以),并将其输出实时直接发送到标准输出。我能找到的最接近的是 clojure 的 Conch 库,它允许您将输出发送到 *out*,但在进程运行完成之前它实际上不会显示输出。
【问题讨论】:
-
这看起来好像在某处缺少 .flush()。
我正在寻找一种在 clojure 中启动子进程的方法(java 可以),并将其输出实时直接发送到标准输出。我能找到的最接近的是 clojure 的 Conch 库,它允许您将输出发送到 *out*,但在进程运行完成之前它实际上不会显示输出。
【问题讨论】:
不确定是否有一个方便的 Clojure 包装器:
(->> (.. Runtime getRuntime (exec "ls") getInputStream)
java.io.InputStreamReader.
java.io.BufferedReader.
line-seq
(map println))
在实践中值得注意的是,你需要同时阅读 stdin 和 stderr 定期进行,否则当其中一个缓冲区填满时,进程可能会挂起。
【讨论】:
我将 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]
))
【讨论】: