如果命名管道中没有任何内容,而我这样做:
cat my_named_pipe
它将等待数据到达。如果没有要读取的数据,是否可以使用一个标志立即退出?或者也许我可以使用除 cat 之外的命令?
我也尝试过:
read val < "$my_named_pipe";
但这也会等待下一个数据块 - 如果 fifo 为空,我不想等待。
答案1
为了防止cat
在没有任何写入器的情况下挂起(在这种情况下,挂起的是 fifo 的打开,而不是从中读取),您可以执行以下操作:
cat 0<> "$my_named_pipe" <"$my_named_pipe"
第一个重定向以读+写模式打开,在大多数系统上,即使没有写入器或读取器,也不会阻塞并实例化管道。然后第二个打开(这次是只读)不会阻塞,因为现在至少有一个写入者(本身)。
仅在 ksh93 的最新版本中才0
需要,其中默认 fd<>
从 0 更改为 1。
另外,在 中,当shell 内置ksh93
时,这将不起作用,例如当在调用之前或之后调用时,(我猜)ksh93 将 stdin 的先前目标保存在单独的文件描述符上,这将保持管道打开。您可以通过编写它来解决这个问题:cat
ksh93
/opt/ast/bin
/bin
$PATH
builtin cat
<"$my_named_pipe"
cat 3<> "$my_named_pipe" <"$my_named_pipe" 3<&-
(您可能还会认为这更清楚地传达了意图)
请注意,<>
管道上的其他读取器也会解锁 fifo。
如果有一些作家,cat
仍然必须读取他们的所有输出并等待他们关闭管道的末端。您可以以非阻塞模式打开管道,就像使用 GNU 一样dd
:
dd bs=64k if="$my_named_pipe" iflag=nonblock status=noxfer
只要管道中有一些数据,它就会从管道中读取数据,然后退出
dd: error reading 'fifo': Resource temporarily unavailable
当没有更多的时候会出错,并且不会解锁其他读取器,但这意味着如果写入管道的速度比您dd
读取它的速度慢,您可能会错过一些写入器的输出。
另一种方法可能是在一段时间内没有输入时超时,例如使用socat
s-T
选项:
socat -u -T1 - - 0<> "$my_named_pipe" <"$my_named_pipe"
如果一秒钟内没有任何东西从管道中流出,它将退出。
答案2
很简单的方法是cat
在读取 fifo 后立即终止,无论是否有数据。您可以使用 执行此操作timeout
,如下所示:
timeout 2 cat my_named_pipe
上面,timeout
在强制 cat 终止之前等待两秒钟。如果运行时命名管道中有缓冲的内容cat
,它将被打印到标准输出。
也许不是最干净的解决方案,但可以完成工作。
希望能帮助到你。