我有一个向stdout写入连续字节流的进程。 我有另一个进程从第一个进程的stdout读取然后完成。 但是我发现当第二个进程完成时,它会关闭管道(我认为),因此进程1停止运行。
我尝试了两种不同的方式:
shell 1中的:
# make fifo
mkfifo /tmp/camera
# stream video from my webcam to the pipe
ffmpeg -y -f v4l2 -r 10 -i /dev/video0 -f avi /tmp/camera
shell 2中的:
# attach to pipe and take a snapshot
rrmpeg -y -r 1 -f avi -i /tmp/camera -vframes 1 -s 160x120 -f image2 image1.jpg
我也在shell 2中尝试了相同的结果:
tail -f /tmp/camera
当shell 2中的进程停止时,它会终止进程1.为什么?
我尝试的第二件事是使用python子进程:
from subprocess import Popen, PIPE
import shlex, time
stream = Popen(shlex.split("ffmpeg -y -f v4l2 -r 10 -i /dev/video0 -f avi -"), stdout=PIPE)
while True:
time.sleep(3)
snap = Popen(shlex.split("rrmpeg -y -r 1 -f avi -i - -vframes 1 -s 160x120 -f image2 image1.jpg"), stdin=stream.stdout)
它第一次通过循环,但当snap
进程超出范围时,stream
进程就会死掉。
有没有办法在没有关闭的情况下从进程1中读取一些流?
答案 0 :(得分:1)
是的,有一种方法可以永久地继续管道编写器。为此,你必须确保
第二个选项不是那么简单(不更改/检查编写器的源代码),因为没有阅读器的管道上的write()不会阻塞(一旦读者在那里)。
对于第一个选项,请确保您的第一个阅读器打开fifo / pipe,不读取任何内容,然后永久阻止/睡眠,而不会死亡。
让任何连续的读者做这项工作。他们可以打开一个fifo(命名管道),或者必须从读取结束打开的进程中分叉(它们继承了filedescriptor)。
这样就不会生成SIGPIPE,一旦管道缓冲区已满,write()将阻止编写器。
man 7 pipe
告诉你更多信息。
(注意:如果write()阻止了意外的长时间,某些程序可能会感到困惑。例如,一些经常查看挂钟的应用程序。)
关于“当shell 2中的进程停止时,它会终止进程1.为什么?”:
进程1可能被SIGPIPE杀死(我没有检查源代码),它在没有阅读器的管道上尝试write()
时获得。