如何在不等待的情况下对命名管道进行cat

如何在不等待的情况下对命名管道进行cat

如果命名管道中没有任何内容,而我这样做:

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 的先前目标保存在单独的文件描述符上,这将保持管道打开。您可以通过编写它来解决这个问题:catksh93/opt/ast/bin/bin$PATHbuiltin 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读取它的速度慢,您可能会错过一些写入器的输出。

另一种方法可能是在一段时间内没有输入时超时,例如使用socats-T选项:

socat -u -T1 - - 0<> "$my_named_pipe" <"$my_named_pipe"

如果一秒钟内没有任何东西从管道中流出,它将退出。

答案2

很简单的方法是cat在读取 fifo 后立即终止,无论是否有数据。您可以使用 执行此操作timeout,如下所示:

timeout 2 cat my_named_pipe

上面,timeout在强制 cat 终止之前等待两秒钟。如果运行时命名管道中有缓冲的内容cat,它将被打印到标准输出。

也许不是最干净的解决方案,但可以完成工作。

希望能帮助到你。

相关内容