ターミナルで使用できるのと同じ方法で、bash スクリプトで exec 3>myfifo を使用できないのはなぜですか?
名前付きパイプを使用して、awk フィルターを単純な「サーバー」に変えています。これは、クライアントからテキスト入力を受け取り、フィルター処理し、NUL でフラッシュできるはずです。
ターミナル 1 では、サーバーは次のように実行されています。
$ mkfifo to_server from_server;
$ while true; do
# Really, this awk script BEGIN's with reading in a huge file,
# thus the client-server model
awk '{sub("wrong", "correct");print;} /\0/ {fflush();}' <to_server >from_server;
echo "restarting...";
done
そして、NUL で終わる入力を入力パイプに入れ、出力パイプから読み取り、EOF をサーバーに送信せずに終了する単純なスクリプトを用意しました (サーバーは不要です)。再起動します):
#!/bin/bash
# According to http://mywiki.wooledge.org/BashFAQ/085 , using
# `exec 3>mypipe; echo foo >&3;` instead of `echo foo >mypipe`
# should ensure that the pipe does not get the EOF which closes it:
exec 3>to_server;
exec 4<from_server;
cat >&3;
echo -e '\0' >&3;
while read -rd '' <&4; do echo -n "$REPLY"; break; done;
ここで、ターミナル 2$ echo This is wrong | bash client.sh
で を実行すると元にThis is correct
戻りますが、ターミナル 1 ではサーバーが再起動することが示されます。ただし、ターミナル 2 内から client.sh からコマンドを実行すると、再起動しません。
私もできるので、それはexecコマンドに関連しているようです
$ exec 3>to_server; exec 4<from_server;
$ echo "This is wrong" | sh client.sh
そして再起動しません。私なら
$ exec 3>&-; exec 4<&-
(もちろん、一度再起動します)そして
$ echo "This is wrong" | sh client.sh
毎回再起動します。そのため、スクリプト内の exec コマンドは効果がないようです。ただし、スクリプト内の exec コマンドの後に置くls /proc/$$/fd/
と、実際には正しいパイプを指していることがわかります。
ここで何が欠けていますか?