とあるエンジニアの備忘log
2012年12月15日土曜日
標準エラー出力をファイルに落としたい (teeの標準エラー出力版)
`tee` というコマンドがあります。 「標準入力から読んだ内容を標準出力とファイルに書きだす」というものです。 例えば、 $ foo | tee logfile とすると、 `foo` コマンドの標準出力は、 `logfile` に書き出されます。 なおかつ、標準出力は標準出力として、標準エラー出力は標準エラー出力として出力されます。 ログを記録するときには便利なコマンドですね。 そこで思ったのは、 `tee` コマンドの標準エラー版に相当するものを実現できないかと思いました。 コンパイルのときの warning とかは通常、標準エラー出力へ出てきます。 標準エラー出力をファイルに記録しておいて、 warning を潰していくのに使いたいのです。 で、考えたシェルスクリプトが以下です。 #!/bin/sh exec 3>&1 foo 2>&1 >&3 3>&- | tee logfile >&2 `foo` コマンドの標準エラー出力を `logfile` に書き出します。 なおかつ、標準出力は標準出力として、標準エラー出力は標準エラー出力として出力されます。 `m>&n` は 「`n` 番の出力先と同じものを `m` 番へコピーする (`dup2` する)」という意味です。 `m>&-` は 「`m` 番を閉じる」という意味です。 また、 `exec` は引数にコマンドが与えられていない場合、リダイレクト処理はカレントシェルで効果を表します。 つまり、上記のスクリプトは、 `foo` コマンドの標準出力と標準エラー出力を入れ替えて、 パイプに流し、さらに `tee` コマンドの標準出力(= `foo` コマンドの標準エラー出力) を標準エラー出力に戻す、ということをしています。 (後日、bash なら `foo |& tee logfile >&2` のように簡単に書けることを知った。。) さらに、 `foo` が異常終了した場合に、即座にシェルスクリプトを止めたいときは、以下のようにします。 パイプに渡してしまうと、そのままでは終了ステータスを取れませんので、ちょっと複雑になっております。。 #!/bin/sh exec 3>&1 status=$({ { foo 2>&1 >&3 3>&- 4>&-; echo $? 1>&4 3>&- 4>&-;} | tee log >&2 3>&- 4>&- ;} 4>&1) if [ "$status" != "0" ]; then set -e /bin/false fi bash の `$PIPESTATUS` の実現方法は[こちらのページ](http://x68000.q-e-d.net/~68user/unix/pickup?%A5%EA%A5%C0%A5%A4%A5%EC%A5%AF%A5%C8)で勉強させていただきました。
0 件のコメント:
コメントを投稿
次の投稿
前の投稿
ホーム
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿