我在使用命名管道(即使用 创建)和文件描述符来重定向输出并在 ImageMagick ( )mkfifo
中抓取输入时遇到了麻烦。convert
基本上,使用以下bash
代码(嗯,与我正在尝试的更简单的等效代码)脚本会挂起并且不会显示图像:
#!/bin/bash
mkfifo myPipe # Create a named pipe
exec 3<>myPipe # I/O file descriptor using the pipe
convert rose: -resize 640x480\! png:fd:3 # Write the image to the pipe
convert png:fd:3 win: # To read from the pipe using the file descriptor
exec 3>&- # Close the file descriptor
rm myPipe # Close and remove the pipe
做了一些研究,我看到这里这一段(来自乔纳森·莱弗勒的回答):
当打开 FIFO 进行读取时,它会阻塞调用进程(通常)。当进程打开 FIFO 进行写入时,读取器将被解除阻塞。当写入器关闭 FIFO 时,读取过程会得到 EOF(要读取 0 个字节),除了关闭 FIFO 并重新打开之外,没有其他任何操作。
为了避免这种情况,我尝试使用 Mark Edgar 的解决方案,其中包含以下说明(代码取自答案):
# 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>&-
不幸的是,我需要从管道中读取并使用文件描述符写入它(即fd:X
使用convert
)。我怎样才能在没有悬挂问题的情况下实现这一目标?
答案1
问题是,虽然
exec 3<>myPipe
同时打开 FIFO 的 R 端和 W 端,从而防止出现死锁,
convert rose: -resize 640x480\! png:fd:3
是一个普通/前台命令,需要在下一个命令运行之前完成。因为它正在向 FIFO 写入可能大量的数据,所以它不会完成,而是在 FIFO 缓冲区已满时被阻塞,从而有效地使脚本陷入死锁。
为了防止这种情况发生,您需要将此命令放在后台,以便下一个进程可以同时耗尽 FIFO,防止它被填满。
正如我在评论中提到的,在这种情况下,我建议使用常规管道而不是命名管道:
convert rose: -resize 640x480\! png:fd:1 |
convert png:fd:0 win:
如果您担心代码行变得太长,您可以通过以以下方式结束行\
或在需要右侧的标记后添加换行符(例如||
、&&
或|
像我所做的那样)来创建延续行(我也倾向于缩进我的连续行以获得更好的可读性,但这纯粹是可选的)。