ツール書きました。
例えば以下のような3つのコマンドを同時に実行して、結果をリアルタイムでマージして出力したいとします。
1 (sleep 1;echo SlowSlow) 2 (sleep 0;for i in $(seq 1 25);do printf aaa;echo;done) 3 (sleep 0;for i in $(seq 1 25);do printf bbb;echo;done)
SlowSlow
の行は1秒待ってから出力なので、実際に受け取るタイミングを考えれば以下のような結果を得たいことになります。
aaa bbb bbb aaa ... ... bbb aaa SlowSlow
simple bash
bashでもできそうなのでやってみると、
((sleep 1;echo SlowSlow) & \ (sleep 0;for i in $(seq 1 25);do printf aaa;echo;done) & \ (sleep 0;for i in $(seq 1 25);do printf bbb;echo;done))
a
や b
、\n
改行が混ざってしまいます。
aaa baaa aaabaaa \n aaabaaa \n baaaaaa \n baaa ... ... aaaSlowSlow
cat
cat
を使えば行はキレイに出力されますが、引数に渡されたストリームを前から順番に処理するので、それぞれ前のストリーム待ちでブロックしてしまいます。
cat <(sleep 1;echo SlowSlow) \ <(sleep 0;for i in $(seq 1 25);do printf aaa;echo;done) \ <(sleep 0;for i in $(seq 1 25);do printf bbb;echo;done)
SlowSlow # 1秒待ってから出力 aaa # ブロックされる。1つ目の出力SlowSlowを待って出力 aaa ... ... bbb # ブロックされる。2つ目のaaaが全て出力されるのを待って出力 bbb ...
paste
pasteというツールもあります。
paste -d \\n <(sleep 1;echo SlowSlow) \ <(sleep 0;for i in $(seq 1 25);do printf aaa;echo;done) \ <(sleep 0;for i in $(seq 1 25);do printf bbb;echo;done)
3つの入力から1行受け取るのを待って一斉に出力します。つまりは、
SlowSlow\naaa\nbbb\n
-> 出力
aaa\nbbb\n
-> 出力
aaa\nbbb\n
-> 出力
実際に打つと以下のようになります。
SlowSlow # 1秒待ってから出力 aaa bbb aaa bbb ... ... aaa bbb
linecmb
今回作ったlinecmbでは期待した結果が得られるはずです。
linecmb <(sleep 1;echo SlowSlow) \ <(sleep 0;for i in $(seq 1 25);do printf aaa;echo;done) \ <(sleep 0;for i in $(seq 1 25);do printf bbb;echo;done)
実はこのツール参考にしたQiitaの記事にも書かれているfdlinecombineでも同じことができます。
しかもfdlinecombineの方が早い。頑張ってスピード上げたのですが追いつきませんでした。
ReadStringやScannerを使って書き始めたのですが、パフォーマンスが思うように出ずにだんだん低いレイヤのAPIを使っていって、systemcallまで多用して書いてみたのですが、今度はLinuxとMacの互換が取れなくなり、少しレイヤあげてReadとWriteで落ち着いています。それでも、特にMacのファイルディスクリプタ周りはの動きは初めて触ったし、情報も少なくて厳しかったです。途中でそもそもそれならCで書けばいいじゃんとなったり。。。他にもまだまだ改良の余地はあるでしょうが、それは追々。
便利な利用方法
早速使って便利だと思ったのはスケールアウトで複数ならんでるWEBサーバの情報を取得したりするコマンド。
linecmb <(ssh server1 -C "tail -f /path/to/file") <(ssh server2 -C "tail -f /path/to/file") <(ssh server3 -C "tail -f /path/to/file")
ちなみにログ見るときには更にこれ組み合わせています。
Bashのパイプから受け取ったテキストで複数の単語をハイライト表示させる - YOMON8.NET