我正在寻找一些我怀疑不存在的东西:用于从命令行使用的非阻塞缓冲命名管道(fifo)。有这样的事吗?
这是用例:假设我有一个进程将在后台运行很长时间并将大量输出输出到stdout
.我并不真正关心输出,也不想存储它(也许我没有足够的空间),但我想定期“插入”并跟踪它正在做什么,然后再次退出并让它继续工作。所以我想将其输出重定向到这个理论上的缓冲、非阻塞命名管道,然后定期利用它。
所以基本上我想像这样开始(10M
缓冲区的大小):
mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &
...并定期过来看看发生了什么...
tail -f magicfifo
...没有 magicfifo
存储所有输出(因此,不是普通文件),并且没有当它填满并且未被点击时,它会阻止喷射过程(因此,这不是一个正常的命名管道)。
我不认为涉及tail
或prune
会做到这一点的解决方案(好吧,我可以想到涉及的解决方法tail
),因为tail
仍然需要我将所有数据存储在某处(如果我想插入并退出查看它),并且prune
必须重写文件,大概(我承认我没有尝试/证明这一点)破坏了生成所有输出的进程的重定向。
我希望我可以编写一些实用程序来执行此操作,但是 *nix 有很多文件和管道等很酷的方面,我只是情不自禁地认为它存在,但我只是不知道它。
那么:是否有这样的事情?如果有的话,它是什么?
答案1
我认为您正在寻找的是 GNU screen
。它维护一个缓冲区来保存一个或多个程序的最后一个屏幕或两个输出,并让您断开连接并稍后返回。
答案2
您可以使用pv
,它在管道中提供了您想要的尽可能多的缓冲。你可以这样使用它:
sprewingprocess | pv -B 1g > ordinaryfifo &
spewingprocess
这将为您在fifo之间提供高达 1GB 的缓冲。pv
不管你信不信,大多数 Linux 发行版都提供了一个名为pv
.
答案3
我有同样的问题。这是我的第一个解决方案。首先将输出写入一个文件,我们在每行之后截断该文件,这样它就不会无限增长:
spewingprocess | while read line; do echo $line > buffer.txt ; done
然后使用 tail 从文件中读取(其中2> /dev/null
消除了“文件被截断”错误消息):
tail -f ./buffer.txt 2> /dev/null
这样缓冲区就不会增长,我们可以进行多路复用,例如运行我们想要的任意数量的尾部。然而,这种方法的问题是,当截断速度快于 tail 读取速度时,我们可能会丢失数据,如以下测试所示:
for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt
运行一段时间后,第一行和最后一行是:
$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783
但该文件的行数较少,因此有些内容丢失了:
$ wc log.txt
67087 67087 392819 log.txt
如果您不太关心数据丢失或者当您的喷射过程不够快而不会发生数据丢失时,这似乎仍然是一个不错的解决方案。