名前付きパイプとの間のファイル リダイレクトは機能しないのに、cat へのパイプは機能するのはなぜですか?

名前付きパイプとの間のファイル リダイレクトは機能しないのに、cat へのパイプは機能するのはなぜですか?

これは、nc を使用した Unix のシンプルなエコー サーバーです。

mkfifo fifo
cat fifo | nc -k -l 4458 -v | cat >fifo

(に基づくこれ

私の見るところ、データフローは次のように機能します。

fifo (my named pipe)
 |
 | (using cat)
 |
 v
nc
 |
 | (using cat)
 |
 v
fifo 

ここで疑問が湧きます。なぜこれが機能しないのでしょうか?

nc -k -l 4458 -v >fifo <fifo

オンにtelnetしようとすると、 「接続が拒否されました」というエラーが表示されます。localhost4458

答え1

これはnetcatコマンドがまだ開始されていないためです。入力用にfifoを開こうとするとシェルがブロックされます。

strace cat >fifo <fifo

何も表示されません。代わりに、例えば、

nc -k -l 4458 -v <>fifo >&0

これは、stdin として読み取りおよび書き込み用に fifo を開き、それを stdout に複製します。


完全な bash コマンドをトレースすると、読み取り用または書き込み用のオープンが返されないことがわかります (反対のオープンが完了するまで)。

$ strace -f -e open bash -c 'nc -k -l 4458 -v  >fifo <fifo'
...
Process 3631 attached
[pid  3631] open("fifo", O_WRONLY|O_CREAT|O_TRUNC, 0666

$ strace -f -e open bash -c 'nc -k -l 4458 -v  <fifo >fifo'
...
Process 3684 attached
[pid  3684] open("fifo", O_RDONLY

man 3 mkfifo: 読み取り用に FIFO を開くと、通常、他のプロセスが同じ FIFO を書き込み用に開くまでブロックされます。その逆も同様です。

関連情報