将子进程输出直接输出到stdout(java/clojure)

Med*_*her 8 java clojure exec

我正在寻找一种方法来启动clojure中的子进程(java很好),并将其输出实时直接发送到stdout.我能找到的最接近的是用于clojure的Conch库,它允许您将输出发送到*out*,但它实际上并不显示输出,直到该过程完成运行.

Art*_*ldt 5

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

(->> (.. Runtime getRuntime (exec "ls") getInputStream)                                                                                                                   
    java.io.InputStreamReader.                                                                                                                                            
    java.io.BufferedReader.                                                                                                                                               
    line-seq                                                                                                                                                              
    (map println))  
Run Code Online (Sandbox Code Playgroud)

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


Med*_*her 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]      
        ))
Run Code Online (Sandbox Code Playgroud)