如何使用Babashka过滤tail命令输出并适配tail -f场景?
解决Babashka脚本适配
tail -f实时输出的问题 你的问题根源在于line-seq的工作方式:它会一次性读取输入流直到结束,但tail -f的输出是持续开放的流(不会主动终止),所以line-seq会一直卡在等待流结束的状态,无法实时处理新出现的行。
下面是两种可行的解决办法:
方法1:使用clojure.core.async异步处理流
Babashka原生支持clojure.core.async,我们可以用它来异步读取每行输入,实时处理:
#!/usr/bin/env bb (ns script (:require [clojure.java.io :as io] [clojure.string :as str] [clojure.core.async :as async :refer [go <! >! chan]])) (defn process-line [line] (when (re-find #"^\[.*CONSOLE" line) (println (str "carpenter " line)))) (let [in-chan (async/chan) reader (io/reader *in*)] ;; 异步读取输入流的每一行 (go (loop [] (when-let [line (.readLine reader)] (>! in-chan line) (recur))) (async/close! in-chan)) ;; 异步处理每一行 (go (loop [] (when-let [line (<! in-chan)] (process-line line) (recur)))))
运行方式和之前一致:tail -f your-log-file.log | ./your-script.clj
方法2:同步循环读取(更轻量)
如果不需要复杂的异步逻辑,直接用同步循环逐行读取,也能完美适配tail -f的实时输出:
#!/usr/bin/env bb (ns script (:require [clojure.java.io :as io] [clojure.string :as str])) (let [reader (io/reader *in*)] (loop [] (when-let [line (.readLine reader)] (when (re-find #"^\[.*CONSOLE" line) (println (str "carpenter " line))) (recur))))
这个方案没有额外依赖,代码更简洁,适合简单的流处理场景。
原脚本的小问题修正
另外注意你的原脚本存在括号不匹配的问题,->>的第一个参数(line-seq (io/reader *in*)少了闭合括号,这会导致脚本无法正常运行,上面的修正版本已经解决了这个问题。
内容的提问来源于stack exchange,提问作者serezlan
相关产品推荐
相关产品推荐

