Clojure可以从现有流程中捕获标准吗?

时间:2016-11-08 07:32:18

标签: java clojure clojure-java-interop

在Clojure计划中,您如何从标准输出 读取 ?我想这样做,或将标准输出传递给我创建的输入流。 Clojure中的标准输出是 java.io.PrintWriter

我有一份Samza工作,由Clojure计划开始。还有一个我可以远程连接的nrepl服务器。在连接之后,我需要能够进入和尾部标准输出(作业写出他们的输出)。

1)根据此SO questionwith-out-str(请参阅here)让我们暂时将*out*绑定到 java .io.StringWriter ),以便您执行的代码写入字符串。但这不允许我利用现有的*out*

2)如果你看一下 clojure.java.shell (参见here),它会获得JVM的Runtime和exec的进程。从该过程中,您可以获得其标准输出流。但同样,这不是我正在寻找的默认标准(*out*)。

3)SO question接近我正在尝试做的事情。但同样,我正在连接到现有流程,并希望减少其标准输出。

这在Clojure中是否可行(见here)?有人解决了这个吗?

1 个答案:

答案 0 :(得分:1)

进程输出不是发布订阅模型,因此当进程将字符放入其输出缓冲区时,实际上只有一个进程将其从该缓冲区中拉出。如果你有一个由shell启动的程序,那么shell会在读取它的输出并将其写入终端(或者读取并忽略它)时进行处理。如果您在启动它的过程之后附加了您的进程并开始尝试获取数据,那么您很可能无法获得任何内容,因为父进程将首先获取它。我刚从两个终端尝试过这个:

1号航站楼:

cat

2号航站楼:

ps -ef | grep cat
tail -f /proc/24547/fd/2 

1号航站楼:

hello

2号航站楼:      <没什么>

字符串"你好"打印到终端1,启动它的过程。

如果没有人阅读输出,那么很有诱惑力,那么它将会让我获得"。虽然听起来不错,但它遇到的问题是这些是固定大小的缓冲区,因此只要输出缓冲区已满,尝试写入它的进程就会阻塞(完全无法运行),直到有人读取输出以解除阻塞它。

一般的解决方案是将稍后想要尾随的进程传递给tee命令,该命令将输出写入文件将其传递给读取它的任何内容。

command-to-watch arg1 arg2 | tee logfile.potentially-huge

虽然如果你走这条路线,你应该在磁盘填充之前旋转日志文件。确保使用此命令

清空日志文件
echo > logfile.potentially-huge

或使用您的程序对文件进行truncate调用。简单地删除文件将从日志目录中删除它的名称而不删除它,它将无声地继续增加占用磁盘空间,新文件将永远不会输出。

这就是我们构建日志库的原因,例如log4j(在90年代)和syslog(在80年代)。

如果你仍然想要对此疯狂,请转向tmux,它可以做任何事情,并改变人们处理文本的方式。一目了然,你应该改变其他过程创建输出的方式,以便更容易获得。