待たずに名前付きパイプをcatする方法

待たずに名前付きパイプをcatする方法

名前付きパイプに何もない場合、次の操作を実行します。

cat my_named_pipe

データが到着するまで待機します。読み取るデータがない場合にすぐに終了するために使用できるフラグはありますか? または、cat 以外のコマンドを使用できるでしょうか?

私も試しました:

read val < "$my_named_pipe";

しかし、これも次のデータ チャンクを待機します。FIFO が空の場合は待機したくありません。

答え1

ライターがない場合にハングアップするのを防ぐにはcat(この場合、ハングするのは FIFO からの読み取りではなく、FIFO のオープンです)、次のようにします。

cat 0<> "$my_named_pipe" <"$my_named_pipe"

最初のリダイレクトは読み取り + 書き込みモードで開きます。ほとんどのシステムでは、書き込み側も読み取り側も存在しない場合でもブロックされず、パイプがインスタンス化されます。その後、2 回目のオープン (今回は読み取り専用) は、少なくとも 1 つの書き込み側 (それ自体) が存在するため、ブロックされません。

0、デフォルトの fd が<>0 から 1 に変更された ksh93 の最近のバージョンでのみ必要です。

また、 では、 がシェルの組み込み関数である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それを読み取るのよりも遅い場合、ライターの出力の一部が失われる可能性があることを意味します ( )。

socat別の方法としては、たとえばのオプションを使用して、しばらく入力がない場合にタイムアウトを設定することもできます-T

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

1 秒間にパイプから何も出力されなかった場合、終了します。

答え2

cat非常に簡単なのは、データがあるかどうかに関係なく、 FIFO を読み取った直後に終了することです。これはtimeout、次のようにして実行できます。

timeout 2 cat my_named_pipe

上記では、timeoutcat を強制終了する前に 2 秒間待機します。 を実行したときに名前付きパイプにバッファリングされているものがある場合はcat、それが stdout に出力されます。

最もクリーンな解決策ではないかもしれませんが、目的は達成できます。

それが役に立てば幸い。

関連情報