我该如何在Clojure中订阅(逐行)一个阻塞shell命令的输出?

4

基本上,我想捕获 shell 命令输出的第一行(FIFO)并存储在某种对象中,无论是原子(atom)还是chan。我已经查看了 core.cache 和 core.async,但我尚未找到任何可以解决问题的东西,即sh(来自clojure.java.shell)只有当命令停止写入标准输出时才返回值。我如何访问它正在发出的数据呢?例如,我想要一个对象,该对象具有bspc subscribepactl subscribe或类似内容的最新输出行。

为了背景,我编写了一个配置文件用于 Lemonbar,它是一个从标准输入读取并写入标准输出的状态栏。目前,我有一堆Thread,它们休眠100毫秒并更新wmctrl -dmpc current等内容的输出。相反,我希望像在 Bash 中一样订阅这些事件(bspc subscribe | while read line ...)。

谢谢。

1个回答

2

这个解决方案使用了 [com.kohlschutter.junixsocket/junixsocket-core "2.3.2"][me.raynes/fs "1.4.6"]

(ns so.unix-socket
    (:require
        [me.raynes.fs :as fs]
        [clojure.java.io :as io])
    (:import
        (org.newsclub.net.unix AFUNIXServerSocket AFUNIXSocketAddress)))


(def file-name (fs/temp-file "abc"))
(.deleteOnExit file-name)
(def file (io/file file-name))

(def server (doto (AFUNIXServerSocket/newInstance)
                (.. (bind (AFUNIXSocketAddress. file)))
                (.. (setSoTimeout 10000))))

(future
    (let [socket (.. server (accept))
          rdr    (io/reader (.getInputStream socket))]
        (loop [line (.readLine rdr)]
            (when (some? line)
                (println line)
                (recur (.readLine rdr))))))

(clojure.java.shell/sh "bash" "-c"
    (format "pactl subscribe|socat STDIN UNIX-CONNECT:%s"
            (.getAbsolutePath file-name)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接