8

我正在寻找一种在 clojure 中启动子进程的方法(java 可以)并将其输出实时直接发送到标准输出。我能找到的最接近的是 clojure 的 Conch 库,它允许您将输出发送到*out*,但在进程完成运行之前它实际上不会显示输出。

4

2 回答 2

5

不确定是否有一个方便的 Clojure 包装器:

(->> (.. Runtime getRuntime (exec "ls") getInputStream)                                                                                                                   
    java.io.InputStreamReader.                                                                                                                                            
    java.io.BufferedReader.                                                                                                                                               
    line-seq                                                                                                                                                              
    (map println))  

在实践中值得注意的是,您需要定期读取 stdin 和 stderr ,否则当其中一个缓冲区填满时,进程可能会挂起。

于 2013-01-19T00:35:20.563 回答
5

我将 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]      
        ))
于 2013-05-18T19:05:23.563 回答