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

时间:2013-01-18 22:59:29

标签: java clojure exec

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

2 个答案:

答案 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]      
        ))