知らなかった tail の使い方 (続編)

さて。tail -f の stdout にパイプを繋げられてバンバンザイだと思ったのですが、一つ盲点がありました。tail -f は、いつまで経っても終了することがないので、このままではパイプラインを止めることができないのです。つまり、

$ tail -f foo | awk '$1 == "END" {exit 0}'

のようなことをして、仮に foo に END が現れても、このパイプラインは止まりません*1
さて、どうするか。仮に、パイプラインの後段(ここでは awk)で前段(ここでは tail)のプロセス ID が分かれば、シグナルを送って停止させることができますが、プロセス ID を知らせるのが厄介です。
私の解決策は、名前つきパイプ (named pipe) を使うというものです。次のようにします。(もっとエレガントな方法を御存知の方は、教えてください。)

$ mknod bar p
$ tail -f foo > bar &
$ pid=$!
$ awk '$1 == "END" {exit 0}' bar; kill -HUP $pid; rm -f bar

ちなみに、mawk では上記はうまくいきませんでした*2awk にファイルを引数で食わせる代わりに、

$ cat bar | mawk -W interactive '$1 == "END" {exit 0}' bar; kill -HUP $pid; rm bar

のようにしたら、うまくいきました。つーか、素直に gawk とか使ったほうが良いのかも。(← 試してませんが)

後記 (4月3日)

上記 mawk の件、ダメです。パイプで繋いだら、元の木阿弥です。いろいろ試しましたがうまくいかず、結局 gawk に移行しました。

*1:パイプラインでは、前段のプロセスが終了しない限り、終了できないようです。

*2:NetBSDawk では OK だった。