2つのプログラム間で双方向パイプを作成する方法は?

2つのプログラム間で双方向パイプを作成する方法は?

2つのプログラム間に一方向パイプを設定する方法(stdout最初のプログラムとstdin2番目のプログラムバインディング)は誰でも知っていますfirst | second

しかし、双方向パイプライン、つまり2つのプログラムのクロスstdinバインディングを作成する方法は何ですかstdout?シェルで簡単にできる方法はありますか?

答え1

まあ、名前付きパイプ()を使うのはかなり「簡単」ですmkfifo。プログラムがこの目的のために設計されていない場合は、デッドロックが発生する可能性が高いため、引用符で囲まれました。

mkfifo fifo0 fifo1
( prog1 > fifo0 < fifo1 ) &
( prog2 > fifo1 < fifo0 ) &
( exec 30<fifo0 31<fifo1 )      # write can't open until there is a reader
                                # and vice versa if we did it the other way

標準出力に書き込む操作には通常バッファリングが含まれます。たとえば、両方のプログラムが次のような場合:

#!/usr/bin/perl
use 5.010;
say 1;
print while (<>);

無限ループが予想されます。しかし、むしろ両側はデッドロックに陥る。$| = 1出力バッファリングをオフにするには追加(またはそれに対応するもの)が必要です。デッドロックの原因は両方プログラムが標準入力で何かを待っていますが、他のプログラムの標準出力バッファにあり、まだパイプに書き込まれていないため、これは表示されません。

修正する:Stéphane CharzelasとJoostの提案を組み合わせます。

mkfifo fifo0 fifo1
prog1 > fifo0 < fifo1 &
prog2 < fifo0 > fifo1

同じことを行い、より短くて携帯性に優れています。

答え2

システムでパイプが双方向の場合(少なくともSolaris 11および一部のBSDでは可能ですが、Linuxでは不可能):

cmd1 <&1 | cmd2 >&0

しかし、デッドロックに注意してください。

また、一部のシステムの一部のksh93バージョンはパイプ(|)を使用します。ソケットペア。ソケットペアは双方向ですが、ksh93は明示的に反対方向を閉じるため、pipe(2)パイプ(システムコールによって生成される)が双方向のシステムでも、上記のコマンドはこれらのksh93では機能しません。

答え3

これがあなたが望むものであるかどうかはわかりません。

nc -l -p 8096 -c second &
nc -c first 127.0.0.1 8096 &

まず、ポート8096でリスニングソケットを開き、接続が確立されると、プログラムが生成され、ストリーム出力とストリーム入力にsecondストリーミングされます。stdinstdout

nc次に、リスンポートに接続し、プログラムをストリーム入力とストリーム出力firstとして生成する2番目のプログラムを起動します。stdoutstdin

これはパイプを使用して正確には実行されませんが、必要な作業を実行するようです。

これはネットワークを使用しているため、2台のリモートコンピュータで実行できます。これは、Webサーバー(second)とWebブラウザ()の動作方法とほぼ同じですfirst

答え4

あなたはそれを使用することができますパイプラインアクチュエータ:

$ pipexec -- '[A' cmd1 ] '[B' cmd2 ] '{A:1>B:0}' '{B:1>A:0}'

関連情報