19

考虑以下场景:

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

事实上,如果您运行的进程未在 EOF 上终止,您仍然无法使用重定向到该进程的 FIFO。我认为这是因为这个 FIFO 被认为是关闭的。

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

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

4

4 回答 4

32

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

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

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

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

于 2011-05-10T23:08:15.080 回答
8

启动一个进程,使 fifo 保持打开以进行写入并无限期地运行。这将防止读者看到文件结束的情况。

于 2011-05-10T22:57:02.910 回答
1

这个答案-

在 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 上尝试了上述方法,它可以工作。

于 2020-08-15T17:35:22.987 回答
0

您可以通过在“mkfifo yourpipe”中用分号在括号中添加您需要的内容来在管道中添加多个输入:

(cat file1; cat file2; ls -l;) > yourpipe
于 2018-10-25T09:59:41.673 回答