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

Shu*_*ump 17 unix named-pipes fifo eof

请考虑以下情形:

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

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

反正有办法解决这个问题吗?

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

Gil*_*il' 29

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

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

    tail -n +1 -f client_pipe | minecraft_server &
    
    Run Code Online (Sandbox Code Playgroud)
  3. 正如jilles所提到的,使用一个技巧:管道支持多个编写器,并且只有在最后一个编写器消失时才会关闭.因此,请确保客户永远不会消失.

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

  • @pabouk感谢您指出这个错误:`tail -n 1 -f`会跳过在启动之前可用的输入或者提供比它可读的更快的输入.我打算写`tail -n +1 -f`,它会立即开始输出. (2认同)
  • 谢谢.我之前尝试过但是`-n + 1`没有像我预期的那样工作.现在,当你确认这是正确的方法时,我进一步检查了问题,并意识到问题在于`tail`的stdout的块缓冲(而不是默认的行缓冲).逐行管道的解决方案:`stdbuf -oL tail -n +1 -f client_pipe | command` (2认同)
  • 有一种更简单的方法来确保管道至少有一个写入器:让读取器以读写模式打开它:`minecraft_server &lt;&gt;client_pipe &amp;`。 (2认同)

jil*_*les 7

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