Unix 防止FIFO关闭/重新使用已关闭的FIFO

Unix 防止FIFO关闭/重新使用已关闭的FIFO,unix,named-pipes,eof,fifo,Unix,Named Pipes,Eof,Fifo,考虑以下场景: 创建名为test的FIFO。在一个终端窗口(A)中,我运行cat测试。现在可以在窗口B中写入并在窗口A中获取输出。还可以终止进程A并重新启动它,并且仍然可以在怀疑时使用此设置。但是,如果您在窗口B中终止进程,B将(据我所知)通过FIFO向进程A发送EOF,并终止该进程 事实上,如果您运行的进程没有在EOF上终止,您仍然无法使用您重定向到该进程的FIFO。我认为这是因为这个FIFO被认为是关闭的 有没有办法解决这个问题 我遇到这个问题的原因是因为我想向在屏幕会话中运行的minecr

考虑以下场景:

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

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

有没有办法解决这个问题


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

启动一个进程,使fifo保持打开状态以便写入,并无限期地运行。这将阻止读卡器看到文件结束状态。

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

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

    tail -n +1 -f client_pipe | minecraft_server &
    
  • ,使用技巧:管道支持多个写入程序,并且只有在最后一个写入程序离开时才会关闭。所以要确保有一个永远不会离开的客户

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


  • 您可以通过在“mkfifo yourpipe”中用分号将所需内容添加到括号中,从而在管道中添加多个输入:

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

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

    所以你可以做:

    cat <>up_stream >down_stream
    

    但是,我找不到有关此行为的文档。因此,这可能是特定于某些系统的实现细节。我在MacOS上尝试了上述方法,效果很好。

    不幸的是,
    tail
    会等待EOF,因此它不会逐行传递管道中的内容。@pabouk感谢您指出这个错误:
    tail-n1-f
    会跳过启动前可用的输入,或者以比读取速度更快的速度提供。我想写
    tail-n+1-f
    ,它马上开始输出。谢谢。我以前尝试过,但是
    -n+1
    没有像我预期的那样工作。现在,当您确认这是正确的方法时,我进一步检查了问题,并意识到问题在于
    tail
    标准输出的块缓冲(而不是默认的行缓冲)。逐行管道的解决方案:
    stdbuf-oL tail-n+1-f client_pipe | command
    有一种更简单的方法来确保管道至少有一个writer:让读取器以读写模式打开它:
    minecraft_server client_pipe&
    # the `cat pipeline keeps running
    echo 1 > up_stream  
    echo 2 > up_stream
    echo 3 > up_stream