2010年12月27日月曜日

[Reading] 12月読書リスト

ゴールデンスランバー(新潮文庫)伊坂幸太郎
サクサク読めた。これまでの伊坂作品以上に構成が練りに練られてる感がある。その感覚が強すぎて納得感が薄いと感じてしまった。エンターテインメントとしてのポップさを意図的に目指しているのだろうけど、もう少し重厚さが欲しいと思いました。

2010年12月26日日曜日

[Maintenance] 改行を含むログの解析手法

デバッグログによくあるようにログが複数行に跨がって出力されている場合、単純にエラーコードでgrepが行えないわけです。

そんなときは、如何に複数行のログを1行として扱うか検討する必要があります。

ログの出力はシステムごとにポリシーが違うため、統一的なコマンドは存在しないと思いますが、コマンド作成の道筋は同様だと考えています。

方針:
1行と見なす開始点の文字列をパターン化すること、そして行末と見なす文字列をパターン化することです。

以下のようなログについて考えてみます。

2010-12-26 23:00:14 [3300] CRIT (GetData.php 30) DB error
SQL= Select test_id from Table_name Where test_id = ?
array {
0=>1000
}
2010-12-26 23:00:14 [3300] ~~~~~~

この場合、日付部(2010~~~)が開始点となり、SQL文の末尾の配列の閉じ括弧が行末です。
したがって、閉じ括弧が登場するまでが1行ですので、途中の改行は不要となります。

そこで、調査時のコマンドは以下のようになります。

Perlが使える環境ならコレ

perl -pe 's/[^}]\n//' awk_test.log | grep 'CRIT'


perl -オプション 'スクリプト' 入力ファイル
  文字列の検索: perl -ne 'print if (m/検索文字列/[i])' 入力ファイル
  文字の置換:  perl -pe 'tr/文字列1/文字列2/' 入力ファイル
  文字列の置換: perl -pe 's/検索文字列/置換文字列/[ig]' 入力ファイル

sedを使うならコレ

sed ':loop; N; $!b loop; ;s/\n/\x20/g' awk_test.log | grep 'CRIT'

ただし、回りくどい上に、1度全体行を読み込んでからの処理となるため、それなりの容量があるテキストファイルを扱うのは難しいと思われる。また、環境によっては使用できない可能性もある。

awkは全体の改行コードを変換することはできるが、部分的にはできないようです。
例えば、以下の置換はうまくいかない。どうしても改行コードが基点になるようです。

awk '{sub(/[^}]\x0A/,"\x20"); print;}' awk_test.log

全体の改行をスペースに変換(というか出力時の区切りを変更するだけ)

awk -F\n -v ORS='' '{print}' filename

# 改行
$kaigyou = '\x0A';

# 半角スペース
$space = '\x20';

# 全角スペース
$Zspace = '(?:\xA1\xA1)'; # EUC-JP
$Zspace_sjis = '(?:\x81\x40)'; # SJIS

Mac のファイルは改行コードが 0x0D (8進で 015) だが、これを UNIX の改行コード 0x0A (8進で 012) に変換する


以上です。