如何避免echo关闭FIFO命名管道? - Unix FIFO的搞笑行为

use*_*871 50 unix bash pipe echo

我想将一些数据输出到管道,并让另一个进程逐行对数据执行某些操作.这是一个玩具示例:

mkfifo pipe
cat pipe&
cat >pipe
Run Code Online (Sandbox Code Playgroud)

现在我可以输入我想要的任何内容,按下回车后我立即看到同一行.但如果替换第二管道echo:

mkfifo pipe
cat pipe&
echo "some data" >pipe
Run Code Online (Sandbox Code Playgroud)

管道在完成之后关闭echo,cat pipe&因此我无法通过管道传递更多数据.有没有办法避免关闭管道和接收数据的进程,以便我可以从bash脚本通过管道传递多行数据,并在它们到达时处理它们?

Mar*_*gar 52

将要输出的所有语句放在同一个子shell中的fifo中:

# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Write to pipe.
(
  echo one
  echo two
) >pipe
Run Code Online (Sandbox Code Playgroud)

如果您有更多复杂性,可以打开管道进行编写:

# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Open pipe for writing.
exec 3>pipe
echo one >&3
echo two >&3
# Close pipe.
exec 3>&-
Run Code Online (Sandbox Code Playgroud)

  • 你能简单解释一下这是如何工作的吗 尤其是最后一行:`exec 3>& - ` (6认同)
  • @NickChammas:在第二个例子中,`exec 3> pipe`打开文件描述符3以写入`pipe`; 两个`echo`命令通过输出重定向写入管道; 最后一个`exec 3>& - `是关闭一个打开的文件描述符 - 在这种情况下描述符3.此时,在后台运行的`cat`获得EOF并终止. (3认同)
  • 很好的答案,实际上成功地保持管道在任意复杂的命令序列中打开. (2认同)

Jon*_*ler 47

当打开FIFO进行读取时,它会阻止调用进程(通常).当进程打开FIFO进行写入时,读取器将被解除阻塞.当写入器关闭FIFO时,读取过程获得EOF(读取0个字节),除了关闭FIFO并重新打开之外,没有什么可以做的.因此,您需要使用循环:

mkfifo pipe
(while cat pipe; do : Nothing; done &)
echo "some data" > pipe
echo "more data" > pipe
Run Code Online (Sandbox Code Playgroud)

另一种方法是在FIFO打开的情况下保留一些进程.

mkfifo pipe
sleep 10000 > pipe &
cat pipe &
echo "some data" > pipe
echo "more data" > pipe
Run Code Online (Sandbox Code Playgroud)

  • 您可以通过使用:`cat pipe 3> pipe`来欺骗并让`cat`将管道打开以进行写入.`cat`命令不会使用文件描述符3,但会将FIFO称为管道打开以进行写入(尽管它将在另一个文件描述符上读取它 - 可能是4号). (9认同)
  • Protip:使用`tail -f`而不是`sleep`版本. (3认同)
  • 第二个版本做得很好!第一个对我不起作用,因为我不想重新启动接收数据的进程。 (2认同)

Pat*_*ick 21

您可以通过以读写模式打开管道的读取端来轻松解决此问题.一旦最后一位作家关闭,读者只能得到一个EOF.因此,在读写中打开它可确保始终至少有一个写入器.

所以将你的第二个例子改为:

mkfifo pipe
cat <>pipe &
echo "some data" >pipe
Run Code Online (Sandbox Code Playgroud)

  • 这显然是唯一正确的答案.谢谢. (2认同)