名前付きパイプへの、または名前付きパイプからのリダイレクトが機能しないのに、猫へのパイプが機能する理由


8

これは、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

あなたがしようとすることに気づくだろうtelnetlocalhost4458あなたが得るエラーを「接続が拒否しました」。


私には答えはありませんが、うまくいけば、これが私より知識のある人に役立つかもしれません。cat myfifo | nc -k -l 4458 > myfifoも動作します。テキストファイル、file.txtなどを使用する場合、nc -k -l 4458 < file.txt > file.txt最初の接続は接続して閉じます(入力が切り捨てられ、EOFがソケットを閉じるので意味があります)、2番目の接続は忘れっぽいエコーサーバーになります。エコーされていない行をテキストファイルに保存します。
user1794469

回答:


9

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

strace cat >fifo <fifo

何も見えなくなります。代わりに、例えば、

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

これは、読み取りと書き込みのためにstfoとして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を開くまでブロックされ、その逆も同様です。


1
ブロッキングは文書化されています:tldp.org/LDP/lpg/node19.html
2016年

"> fifo <fifo"を使用するとシェルがブロックするのはなぜですか?それはそれを書き込みのために開き、次に読み取りのために開くように見えます。それで、書き込み用のハンドルが既に開いているので、正常に続行すべきではないでしょうか?
Razvan、

@Razvan私はfifoを開く2つの代替順序の実際のトレースで回答を更新しました。書き込みまたは読み取りの両方のブロックで開いていることがわかります。
meuh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.