我最好的解释是通过例子。
mkfifo pipe
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个不同的实例(每个文本文件内容一个实例)。
有没有办法让消费者区分进来的对象?还是说数据会被追加,并作为一个流来读取?
一个可能普遍适用的解决方案(期待听到是否有更有效的替代方案。
首先,问题所描述的一个python脚本例子。
some-script.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
)而不退出进程,并将内容管道到 read
之内 while
襻echo
管线到 base64 -d
(-d代表解码)base64 -d
将解码后的线路(现在可能跨越多条线路)输送到 cat
cat
连线,并将其作为一个管道输送到 python some-script.py
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'"