やりたいこと
SoftwareDesignのシェルスクリプト記事を読んでから、シェルスクリプトがちょっとブーム。
いっぱいパイプにつないで喜んでたら、ふと疑問が浮かんだ。
コマンド出力の分岐は伝家の宝刀teeコマンドがある。
じゃぁ結合は?
方法1 一時ファイルに書く
$ TMP=`tempfile`; echo hoge > $TMP; echo fuga >> $TMP; cat $TMP; rm $TMP
まぁ、できてるけども。。。
方法2 bashのプロセス置換を使う
$ cat <(echo hoge) <(echo fuga)
hoge
fuga
スマート。
でもbash限定。
そして出力が継続するコマンド(何て呼べばいいんだろう)に対してはうまく行かない。
(追記:"a continuous streaming command"と言うそうです。@7of9さん、ありがとうございます。)
方法3 fifoを使う
$ mkfifo /tmp/shout
$ echo hoge > /tmp/shout | echo fuga > /tmp/shout | cat /tmp/shout
hoge
fuga
fifoだと入力があるまでブロックしてくれるので、バックドア的な使い方ができる。
例えば、標準入出力しかI/FがないインタラクティブなCUIアプリ(QEMUのようなシミュレータとか)に対して、CIから自動テストのトリガをかける時などに使える。
1. CUIアプリ起動時に標準入力を/tmp/shuoutを経由するようにしておく
(CUIアプリの例として下記ではbashにしている)
$ mkfifo /tmp/shout
$ cat > /tmp/shout | cat /tmp/shout | bash
uname -r
4.13.0-32-generic
2.別のターミナルから、/tmp/shoutにコマンドを流しこむ
$ echo uname -r > /tmp/shout
3. 1.で起動したCUIアプリにコマンドが入力される
(今回の例ではbash上でコマンドが実行される)
4.13.0-32-generic
手順2.でnc -lk
などと繋げば他のホストから入力することも可能。
もちろんecho $'\cC' > /tmp/shout
などとしたら制御文字を送りつけることもできる。
結論
bashで単発のコマンド出力を結合するときは、プロセス置換。
bashじゃない、または終わらないコマンド("a continuous streaming command")の出力を結合するときは、fifo。
雑感
シェルスクリプトは限られたコマンドを組み合わせて目的を達成するパズル的な楽しさがあるなー。