在命名管道 (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.txt
、b.txt
、c.txt
、d.txt
、e.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) 的消费者端,有没有办法区分每个项目并将其重定向到自己的进程?的主要内容,如果未能解决你的问题,请参考以下文章