プログラムを書いている時に出力をDEBUGやERRORと言った レベルに分けておいたりすることがよくあると思いますが、 シェルスクリプトでそんなツールを用意してみました。
ちょっと工夫としては、ファイルへ出力されたりパイプでコマンドに渡す様な時は、
grep
とかでやっているように色の装飾などを消す、という作業をしてる点。
shell-logger
このレポジトリにあるetc/shell-logger.shをsource .../etc/shell-logger.sh
等として読み込むと
err
やwarn
と言ったメーッセージを表示させるための関数が使える様になり、
それぞれその時刻などとともにフォーマットされてメッセージが出力されます。
インストールは/etc/shell-logger.shを適当なところにおいてそれを読み込んでください。 Mac Homebrewなら
$ brew install rcmdnk/rcmdnkpac/shell-logger
で/usr/local/etc/shell-logger.shにインストールされます。
実行してみると
こんな感じ。
上の例で最後のnotice
コマンドはパイプで...|cat
とcat
につなげていますが、
cat
の出力には色がついていません。
コマンドの出力で色を付けるとコマンドラインで見る時には便利ですが、 ファイルに出力するとそのカラーコードに関するエスケープシーケンスが余計について分かりづらくなってしまいます。
grep
コマンドなどでは--color=auto
というオプションを使うと
出力がコマンドラインなのかファイルなのかなどによってこの色つけを行ったり辞めたりしますが、
これと同じことをしてるわけです。
1 2 3 4 5 6 7 8 9 |
|
こんな感じのスクリプトを作れば、test_command
が失敗した時はエラーが出ます。
また、エラー出力は標準エラーに出力されます。
./logger_test.sh > log 2>&1
みたいにすると全てlogに書き出されますが、この際は色の情報はない状態で書き込まれます。
使える関数
出力は以下の5段階あってそれぞれに関数があります。
debug
以外にはエイリアスで2つの関数名が充てられています。
LEVEL | Functions |
---|---|
DEBUG | debug |
INFO | info , information |
NOTICE | notice , notification |
WARNING | warn , warning |
ERROR | err , error |
オプション
Variable Name | Description | Default |
---|---|---|
_LOGGER_DATE_FORMAT | Output date format. | ‘%Y/%m/%d %H:%M:%S’ |
_LOGGER_LEVEL | 0: DEBUG, 1: INFO, 2: NOTICE, 3: WARN, 4: ERROR | 1 |
_LOGGER_STDERR_LEVEL | For levels greater than equal this level, outputs will go stderr. | 4 |
_LOGGER_DEBUG_COLOR | Color for DEBUG | 3 (Italicized. Some terminal shows it as color inversion) |
_LOGGER_INFO_COLOR | Color for INFO | ”” (Use default output color) |
_LOGGER_NOTICE_COLOR | Color for NOTICE | 36 (Front color cyan) |
_LOGGER_WARNING_COLOR | Color for WARNING | 33 (Front color yellow) |
_LOGGER_ERROR_COLOR | Color for ERROR | 31 (Front color red) |
_LOGGER_ALWAYS_COLOR | Color mode. -1: Always no color. 0: Put color only for terminal output. 1: Always put color. | 0 |
_LOGGER_LEVELS | Names printed for each level. Need 5 names. | (“DEBUG” “INFO” “NOTICE” “WARNING” “ERROR”) |
これらの変数を変更することで表示を変更できます。 変数の設定はshell-logger.shを読み込む前に行っても後に行っても適用されます。
デフォルトでは出力レベルは1(INFO)なのでdebug
は出力されません。
また、_LOGGER_STDERR_LEVEL
が4になっていますが、これによって4以上(ERRORのみ)が
標準エラーに出力されます。
_LOGGER_ALWAYS_COLOR
を1にするとファイルとかに書き出しても色のコードを残したままに出来ます。
色付けに関しては
_LOGGER_ERROR_COLOR="37;41"
みたいにして複数渡してバックグラウンドと文字色を同時に変える事も可能です。 (色に関しては下記参照。)
shell-logger内で使ってるShell技
出力がファイルなどへの出力かどうか調べる
出力をチェックするには[ -t $n ]
というテストコマンドが使えます。
$n
は標準出力は1、標準エラーは2でこれらを与えて真ならその出力は
ファイルやパイプへの出力ではなくて端末に出している事になります。
なので
1 2 3 4 5 |
|
みたいな感じでやってあげるだけ。
ちょっと複雑なケースもしっかりと考慮しない場合もあるみたいですが、 大体の場合はこの程度で十分だと思います。
bash - How to detect if my shell script is running through a pipe? - Stack Overflow
変数が数値であるかどうかチェックする
色々と方法はあると思いますが、expr
を使った以下の様なものが
伝統的?な感じです。
1 2 3 4 5 6 7 |
|
expr
のマニュアルによると
EXIT STATUS
The expr utility exits with one of the following values:
0 the expression is neither an empty string nor 0.
1 the expression is an empty string or 0.
2 the expression is invalid.
ということなので、もし$n
が数字じゃなくて計算に失敗すると
ステータスコードは2になります。
ちょっと面倒なのがたまたま結果が0になってしまうケースは何故かステータスコードが1になるということ。
通常シェルスクリプトだと0以外の終了ステータスはエラー終了なわけですが、
expr
では何故かこの様な形を取っています。
標準エラー出力を直接行うコマンド
同じ関数の中で、受け取ったメッセージを 場合によって標準出力と標準エラー出力を分けたい様な時、 出力部分は同じなので、場合分けして2回書く様なことをしないで 同じ出力なのでまとめて書きたい、と言った場合。
1 2 3 4 5 |
|
こんな感じでコマンドを変数にして、それをevel
でやってあげれば
まとめて書けます。
>&2
の部分だけ最後に足した方が普段使ってる感じにはなりますが
コマンドとしてまとめた方がスッキリする感じがするので。
eval
に渡すので、後ろの色つけのところとかのエスケープをちょっと気をつけないといけません。
一回余計に\
が入ります。
Zshの配列の調整
Bashの配列は0番目から始まりますが、 Zshでは通常1番目から始まります。
これが結構面倒で簡単なシェルスクリプトでも配列があるだけで上手く動かなくなってしまいます。
しかし、Zshではこの辺を調整することが出来て、
1
|
|
すると、kshの動作に近い動きになりますが、この中で配列も0から始まる様になります。 Bashの動作中心で書きたい場合にはこのオプションを付けておけば大分同じ書き方が出来る様になります。
また、この変更は関数内で呼んだ場合はその外へは影響は残らないので 他の部分を特に気にせずに使うことが出来ます。
シェルスクリプトで使う色のチェックなど
前に書いた色のチェックが出来るスクリプト。
この中にあるbin/colcheck
で色をチェックできます。また、スクリプトの中に各番号の定義とかも書いてあります。