我想在 Clojure 中维护一个长时间运行的交互式 shell 进程——在 Emacs 中称为“劣质”进程。我认为基本思想很熟悉,因为 Clojure 本身可以通过 CIDER 在 Emacs 中运行。我很高兴知道是否有使用 Clojure 作为顶级流程的此设置的任何工作示例。
编辑:我发现了这个“shell”要点,这是一个非常漂亮的 Conch 包装器这让我深思。
用我自己的first attempt with Conch :我无法将字符串输入 python
并以与我相同的方式获取输出,例如 cat
。但是通过一些实验,我弄清楚了基础知识并绕过了第一个障碍。
(require '[me.raynes.conch.low-level :as sh])
(def sh-python (sh/proc "python" "-i")) ; "-i" needed to get interactive mode
#'flowrweb.core/sh-python
(future (sh/stream-to-out sh-python :out))
#future[{:status :pending, :val nil} 0x516f3fff]
(sh/feed-from-string sh-python "1+1\n") ; just returns nil on the CIDER repl
2 ; <- but we see "2" with the lein repl
nil
所以我知道我感兴趣的数据是可用的,尽管它不在 CIDER 中打印有点奇怪(子问题...为什么不是 2打印?)。无论如何,对于我的用例,我不需要打印;相反,我只想将它作为字符串取回。
第一次尝试:
(def pyout (future (sh/stream-to-string sh-python :out)))
;=> #'flowrweb.core/py-out
(sh/feed-from-string sh-python "1+2\n")
;=> 3
;=> nil
@pyout
^C ; <- the process hangs
看来 sh/stream-to-string
并没有完全满足我的需要。
用 with-out-str
怎么样?
(def something (with-out-str (sh/feed-from-string sh-python "1+3\n")))
;=> 4
;=> #'user/something
something
;=> "" ;<- where is the "4"?
不,那也不起作用。
tl;dr:如何重定向 Conch 子进程的输出以供将来处理?
最佳答案
据我所知,没有用于管理流程的 Clojure 特定机制。此外,严格来说,操作系统进程不在 Clojure 的关注范围之内,因为它是一种托管语言,进程管理绝对是宿主应该管理的东西(例如 JVM 或 CLR)。
那么,假设您在 JVM 上运行 Clojure。 JVM 公开用于创建子进程的一种工具是 ProcessBuilder ,您可以从 Clojure 代码中调用它,就像下面这样 (credits go to @codification):
(ns proc
(:import [java.lang ProcessBuilder])
(:use [clojure.java.io :only [reader writer]]))
(defn spawn [& args]
(let [process (-> (ProcessBuilder. args)
(.start))]
{:out (-> process
(.getInputStream)
(reader))
:err (-> process
(.getErrorStream)
(reader))
:in (-> process
(.getOutputStream)
(writer))
:process process}))
关于shell - clojure 中的 "inferior"进程 - 重定向异步输出以进行进一步处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39104127/