2011-05-10 264 views
15

考虑以下情形:防止FIFO关闭FIFO

一个FIFO命名创建test。在一个终端窗口(A)中运行cat <test,并在另一个终端窗口(B)中运行cat >test。现在可以在窗口B中写入并在窗口A中获取输出。也可以终止进程A并重新启动它,并仍然可以按照怀疑使用此设置。但是,如果您在窗口B中终止进程,那么B(就我所知)将通过FIFO发送EOF来处理A并终止该进程。实际上,如果您运行的流程不会在EOF上终止,您仍然无法使用您重定向到流程的FIFO。我认为这是因为这个FIFO被认为是关闭的。

有没有办法解决这个问题?

为什么我遇到这个问题的原因是因为我想发送命令到在屏幕会话中运行的我的Minecraft服务器。例如:echo "command" >FIFO_to_server。这可能是通过自己使用屏幕来完成的,但我对屏幕不太舒服,我认为只使用管道的解决方案会更简单和更清晰。

回答

26

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

  1. 更改阅读器的代码,使其在文件结束后继续阅读。这就是说输入文件是无限的,并且到达文件的末尾只是一个幻想。对你来说不实用,因为你不得不改变我的服务器代码。
  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服务器。

+0

不幸的是,'tail'等待EOF,因此它不会逐行传递管道中的内容。 – pabouk 2013-08-22 16:42:34

+2

@pabouk感谢您指出这个错误:'tail -n 1 -f'会跳过在它启动之前可用的输入或使其可用的速度超过其可读的速度。我打算写'tail -n +1 -f',它马上开始输出。 – Gilles 2013-08-22 17:03:55

+2

谢谢。我曾尝试过,但'-n + 1'没有按预期工作。现在,您已确认这是正确的方式,我进一步检查了问题,并意识到问题出现在“tail”标准输出的块缓冲(而不是默认行缓冲)中。逐行管道的解决方案:'stdbuf -oL tail -n +1 -f client_pipe |命令' – pabouk 2013-08-22 17:55:41

6

启动一个进程,使FIFO保持开放状态并保持无限期运行。这将防止读者看到文件结束的情况。