Conducting subprocesses output directly to stdout (java / clojure)

I am looking for a way to start a subprocess in clojure (java is fine) and its output will be sent directly to stdout in real time. The closest I managed to find is the Conch library for clojure, which allows you to send output to *out* , but does not actually display the output until the process is complete.

+6
source share
2 answers

Not sure if there is a convenient Clojure shell for this:

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

In practice, it is worth noting that you need to read both stdin and stderr regularly or the process may freeze when one of the buffers is full.

+3
source

I noticed Arthur's answer as correct, as it led me to a solution, and basically this is what someone would like in the base case. I ended up creating a larger method that does more, although I decided that I would put it here if someone else found it useful

 (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] )) 
+1
source

All Articles