このパイプラインスクリプトが機能しないのはなぜですか?

このパイプラインスクリプトが機能しないのはなぜですか?
#!/bin/bash
rm out
mkfifo out
nc -l 8080 < out | while read line
do
    echo hello > out   
    echo $line
done

このスクリプトを実行しているコンピュータ(ポート8080を使用)のIPに移動すると、「hello」という単語が表示されると予想され、スクリプトを実行しているコンピュータから要求の行を出力したいと思います。

しかし、何も起こりませんでした。ブラウザは何の応答も受け取らず、サーバー端末も何の出力も得られません。

うまくいかないのはなぜですか。それを機能させるには何を修正する必要がありますか?私はそれを単純なパイプで維持したいと思います。プロセスの置き換えやそのようなものを使用したくありません。

ベストアンサー1

リダイレクト< outのため、名前付きパイプが読み取り用に開きます。書き込み用に開いているパイプがないプロセスはブロックされます。一方、パイプの右側はコマンドからブロックされ、パイプを介して出力される内容をread待っています(まだ開始されていません)。ncそれ二重ロック

スクリプトを実行し続けるには、名前付きパイプが独立した書き込みおよび読み取り用に開かれていることを確認してください。たとえば、

nc -l 8080 < out | while read line
do
    echo hello >&3
    echo "$line"
done 3>out

または

nc -l 8080 < out | {
  exec 3>out
  while read line
  do
    echo hello >&3
    echo "$line"
  done
}

ncこの操作はゼロバイトを読み取った後に入力が閉じていることを確認し、後続の書き込みは、読み取るために名前付きパイプが再び開くのを待つのをブロックするため、機能しません。

nc -l 8080 < out | {
  : >out
  while read line
  do
    echo hello >out
    echo "$line"
  done
}

おすすめ記事