如何避免回声closuresFIFO命名pipe道? – Unix的FIFO有趣的行为

我想输出一些数据到一个pipe道,并让另一个进程对数据行逐行进行操作。 这是一个玩具的例子:

mkfifo pipe cat pipe& cat >pipe 

现在我可以input任何我想要的东西,按下后立即看到同一行。 但是,如果用echo替代第二个pipe道:

 mkfifo pipe cat pipe& echo "some data" >pipe 

echocat pipe&完成后,pipe道closures,以便我不能通过pipe道传递更多的数据。 有没有办法避免closurespipe道和接收数据的进程,这样我就可以通过pipe道从bash脚本传递多行数据,并在到达时处理它们?

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

 mkfifo pipe (while cat pipe; do : Nothing; done &) echo "some data" > pipe echo "more data" > pipe 

另一种方法是保持FIFO打开的一些过程。

 mkfifo pipe sleep 10000 > pipe & cat pipe & echo "some data" > pipe echo "more data" > pipe 

把你想要输出到fifo的所有语句放在同一个子shell中:

 # Create pipe and start reader. mkfifo pipe cat pipe & # Write to pipe. ( echo one echo two ) >pipe 

如果你有更多的复杂性,你可以打开pipe道写作:

 # 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>&- 

您可以通过以读写模式打开pipe道的读取端来解决这个问题。 读者只有在最后一名作者closures时才能获得EOF。 因此,以读写方式打开,确保至less有一个作者。

所以把你的第二个例子改成:

 mkfifo pipe cat <>pipe & echo "some data" >pipe 

作为这里的其他解决scheme的替代scheme,您可以在循环中调用cat作为您的命令的input:

 mkfifo pipe (while true ; do cat pipe ; done) | bash 

现在你可以一次给它一个命令,它不会closures:

 echo "'echo hi'" > pipe echo "'echo bye'" > pipe 

当然,当你想要它的时候,你将不得不杀掉这个过程。 我认为这是最方便的解决scheme,因为它可以让您在创build过程时指定非退出行为。

我强化了Jonathan Leffler的答案来支持closurespipe道的第二个版本:

 dir=`mktemp -d /tmp/temp.XXX` keep_pipe_open=$dir/keep_pipe_open pipe=$dir/pipe mkfifo $pipe touch $keep_pipe_open # Read from pipe: cat < $pipe & # Keep the pipe open: while [ -f $keep_pipe_open ]; do sleep 1; done > $pipe & # Write to pipe: for i in {1..10}; do echo $i > $pipe done # close the pipe: rm $keep_pipe_open wait rm -rf $dir