在命名管道 (FIFO) 的消费者端,有没有办法区分每个项目并将其重定向到自己的进程?

Posted

技术标签:

【中文标题】在命名管道 (FIFO) 的消费者端,有没有办法区分每个项目并将其重定向到自己的进程?【英文标题】:On the consumer-end of a named pipe (FIFO), is there a way to distinguish each item and redirect it to its own processes? 【发布时间】:2020-05-02 12:55:26 【问题描述】:

我能解释的最好的就是举例。

    创建命名管道:mkfifo pipe 创建5个文本文件,a.txtb.txtc.txtd.txte.txt(本例中可以存放任何内容) cat [a-e].txt > pipe

当然,因为在消费者端没有打开管道,所以终端会显得很忙。

    在另一个终端,tail -fn +1 pipe

所有内容都按预期通过管道(通过尾部消耗和打印输出)。

但是,我希望将每个管道文本文件重定向到一次只能处理一个命令(5 个单独的进程),而不是简单地打印出消耗的内容:

类似于python some-script.py < pipe,但它会创建 5 个不同的实例(每个文本文件内容一个实例)。

消费者有什么方法可以区分进来的对象吗?还是数据被追加并作为一个流全部读取?

【问题讨论】:

数据作为一个连续的未区分流出来。 如果您可以信任编写器的行为正确,那么您可以让它向流中插入额外的数据,以便读者可以辨别不同文件之间的边界,然后将它们视为单独的实体。 谢谢。我通过反复试验得出了这个结论,但它确实帮助了我更多知识渊博的人能够证实我的发现。我正在考虑让作者在一行base64 -w 0 中对内容进行base64 编码,以便读者可以逐行解码并将其传递给进程。碰上一些砖墙,但我想慢慢地到达那里。 【参考方案1】:

一个可能普遍适用的潜在解决方案(期待听到是否有更有效的替代方案。

首先,问题描述的示例python脚本:

一些脚本.py:

import sys

lines = sys.stdin.readlines()
print('>>>START-OF-STDIN<<<')
print(''.join(lines))
print('>>>END-OF-STDIN<<<')

目标是使来自管道的文本流可区分。

制作者示例:

cat a.txt | echo $(base64 -w 0) | cat > pipe &
cat b.txt | echo $(base64 -w 0) | cat > pipe &
cat c.txt | echo $(base64 -w 0) | cat > pipe &
cat d.txt | echo $(base64 -w 0) | cat > pipe &
cat e.txt | echo $(base64 -w 0) | cat > pipe &

生产者的描述:

cat 连接整个文件,然后通过管道传输到 echo echo 显示来自子命令 $(base64 -w 0) 的文本并通过管道连接到 cat base64 -w 0 将完整的文件内容编码为一行 在这种情况下使用的cat 在将输出重定向到管道之前连接整行。没有它,消费者将无法正常工作(自己尝试)

消费者的一个例子:

tail -fn +1 pipe | while read line ; do (echo $line | base64 -d | cat | python some-script.py) ; done

消费者的描述:

tail -fn +1 pipe 从一开始就跟随 (-f) 管道 (-n +1) 而不退出进程,并在 while 循环内将内容传递到 read 虽然有要读取的行(假设 base64 编码的单行来自生产者),但每一行都被传递到一个子 shell 在每个子shell中 echo 将线路传送到 base64 -d(-d 代表解码) base64 -d 将解码的行(现在可能跨越多行)传递给cat cat 连接线并将其作为一个管道连接到 python some-script.py 最后,示例python脚本能够以与cat example.txt | python some-script.py完全相同的方式逐行读取

当主机进程没有 Docker 权限但可以管道到作为卷安装到容器中的 FIFO(命名管道)文件时,上述内容对我很有用。消费者的多个潜在实例可能会并行发生。我认为上述成功区分了传入的内容,以便隔离进程可以处理来自命名管道的内容。

涉及管道符号等的 Docker 命令示例:

"bash -c 'tail -fn +1 pipe | while read line ; do (echo $line | base64 -d | cat | python some-script.py) ; done'"

【讨论】:

请注意,这只有在不超过 PIPE_BUF 时才会是原子的。在此处查看有关 PIPE_BUF 的内容 - man7.org/linux/man-pages/man7/pipe.7.html

以上是关于在命名管道 (FIFO) 的消费者端,有没有办法区分每个项目并将其重定向到自己的进程?的主要内容,如果未能解决你的问题,请参考以下文章

PHP中管道的非阻塞打开

Linux系统编程——进程间通信:命名管道(FIFO)

简述Linux进程间通信之命名管道FIFO

检测阅读器何时关闭命名管道(FIFO)

Linux进程间通信之管道(pipe)命名管道(FIFO)与信号(Signal)

Linux - 进程间通信 - 命名管道