防止FIFO关闭/重用关闭的FIFO

时间:2011-05-10 22:50:01

标签: unix named-pipes eof fifo

考虑以下情况:

创建名为test的FIFO。在一个终端窗口(A)中,我运行cat <test,然后运行另一个(B)cat >test。现在可以在窗口B中写入并在窗口A中获得输出。也可以终止进程A并重新启动它,并且仍然可以将此设置用作可疑的。但是,如果你在窗口B中终止进程,B将(据我所知)通过FIFO发送一个EOF来处理A并终止它。

事实上,如果您运行的流程不会终止于EOF,您仍然无法使用重定向到流程的FIFO。我认为这是因为这个FIFO被认为是封闭的。

有没有解决这个问题?

我遇到此问题的原因是因为我想将命令发送到在屏幕会话中运行的我的Minecraft服务器。例如:echo "command" >FIFO_to_server。这可以通过单独使用屏幕来实现,但我对屏幕不太满意我认为仅使用管道的解决方案会更简单,更清洁。

4 个答案:

答案 0 :(得分:29)

A正在从文件中读取。当它到达文件的末尾时,它将停止读取。这是正常行为,即使该文件恰好是fifo。你现在有四种方法。

  1. 更改阅读器的代码,使其在文件结束后继续阅读。这就是说输入文件是无限的,到达文件的末尾只是一种幻觉。对您不实用,因为您必须更改Minecraft服务器代码。
  2. 应用unix哲学。你有一个作家和读者不同意协议,所以你插入一个连接它们的工具。碰巧,unix工具箱中有这样一个工具:tail -ftail -f即使看到文件末尾也会继续读取其输入文件。让所有客户端与管道通信,并将tail -f连接到minecraft服务器:

    tail -n +1 -f client_pipe | minecraft_server &
    
  3. As mentioned by jilles,使用一个技巧:管道支持多个编写器,只有在最后一个编写器消失时才会关闭。因此,请确保客户永远不会消失。

    while true; do sleep 999999999; done >client_pipe &
    
  4. 问题在于服务器基本上是为处理单个客户端而设计的。要处理多个客户端,您应该更改为使用套接字。将套接字视为“元数据管道”:连接到套接字会创建一个管道,一旦客户端断开连接,该特定管道就会关闭,但服务器可以接受更多连接。这是一种干净的方法,因为如果两个客户端碰巧同时连接(使用管道,它们的命令可以散布),它还可以确保您不会混淆数据。但是,它需要更改Minecraft服务器。

答案 1 :(得分:7)

启动一个进程,使fifo保持打开状态并无限期地继续运行。这将阻止读者看到文件结束条件。

答案 2 :(得分:1)

来自this answer-

在Linux等某些系统上,命名管道(FIFO)上的<>会打开命名管道而不会阻塞(无需等待其他进程打开另一端),并确保管道结构保持活动状态。例如:

所以您可以这样做:

cat <>up_stream >down_stream
# the `cat pipeline keeps running
echo 1 > up_stream  
echo 2 > up_stream
echo 3 > up_stream

但是,我找不到有关此行为的文档。因此,这可能是特定于某些系统的实现细节。我在MacOS上尝试了上述方法,并且可以正常工作。

答案 3 :(得分:0)

您可以在管道中添加多个输入,方法是在“ mkfifo yourpipe”中的方括号中添加所需内容:

(cat file1; cat file2; ls -l;) > yourpipe