人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

複数のログファイルを総括してかつ、特定期間分のログを抽出するには?
現在、LinuxのJavaのログファイルから一定文字列を抽出するスクリプトをbashで組んでいるのですが、
・対象はapli.logとする。(例えばの話です)
・週1回実行する(つまり1週間分のログが対象)。
・ログファイルは一定「サイズ」でローテーションされる(apli.log.1と言うような感じ。logrotateではない)。
・ログのフォーマットはyy/mm/dd hh:mm:ss <ログ内容>で出力される。
と言う条件で作成しているのですが、grep <文字列> apli.log*でやってしまうと1週間以上になってしまいますし、apli.logだけだと1週間以内で終わってしまいます。
過去1週間分だけ抽出する何か妙案はないでしょうか。

●質問者: Marin_MTB
●カテゴリ:コンピュータ ウェブ制作
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● a-kuma3
●90ポイント ベストアンサー

シェルスクリプトの中で Perl を使って、ログファイルの時刻を切り出して、一週間前の時刻と比較する。
例えば、こんな感じ。

#! /usr/bin/bash

 cat apli.log* | \
 perl -e '
use Time::Local;

my $now = time;
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($now);
my $today = timelocal(0, 0, 0, $mday, $mon, $year);
my $aweek_before = $today - 7*24*60*60;

while (my $line = <STDIN>) {
 if ($line =~ m/^(\d+)\/(\d+)\/(\d+) (\d+):(\d+):(\d+)/) {
 my $t = timelocal($6, $5, $4, $3, $2 - 1, $1 + 2000);
 if ($t >= $aweek_before) {
 print $line;
 }
 }
}
'

起動時刻の一週間前の午前0時よりも、ログの時刻が後だったら標準出力にログの内容を出力してます。

対象のログファイルは全ファイルとしていますが、ファイル数が多くて速度が気になるようだったら find の mtime で絞り込めば良いと思います。

 find . -name "apli.log*" -mtime -8 -print | xargs cat | \
 perl -e '
 ... 以下、同じ

"-8" は、間違いじゃないです :-)


Marin_MTBさんのコメント
これは予想していましたが、私がPerlが弱い為、メンテナンス出来ない恐れがあって避けていたのですが…やはりそれしかないですかね…。(´・ω・`)

a-kuma3さんのコメント
あ、仲間。 ぼくも Perl は苦手です <tt>:-)</tt> 処理が込み入ってくると grep, sed → awk → perl って感じで考えます。 最後が python や ruby じゃなくて perl なのは、いろんな unix を触って来たからです。 自分でパッケージを組み込んで良い環境なら、ruby を入れちゃいますが、そうもいかない環境での仕事もある(というか、そっちが大半)ので、最初から入ってることが多い perl を使います(仕方なく)。 と言っても、複雑な正規表現の切り出しと、時刻の扱いくらいまでしかやりませんが。 昔の手法だと、TZ 環境変数を無理矢理ずらして、date コマンドでn日前の日付を取得する、という方法もあります。 >|sh| $ TZ=JST+159 date +"%Y/%m/%d" ||< これと、シェルの組み込みコマンドの read を組み合わせる、という方法も無くはないんですが、 -TZ をずらして過去日を取得する方法は、どんな環境でも正しく動くとは限らない -perl を使ってないけど、メンテのしづらさは負けてない という感じで... 将来、条件が複雑になる可能性が高いなら、今から java で作っちゃう、というのもひとつの手だと思います。 もしくは、メンテできる程度までは頑張って、どうにもならなくなってから java で組むことを考えるとか。

a-kuma3さんのコメント
>> これと、シェルの組み込みコマンドの read を組み合わせる、という方法も無くはないんですが、 << こんな感じ。 >|sh| #!/usr/bin/sh aweek_before=`TZ=JST+159 date +"%y/%m/%d"` cat apli.log* | \ while read ymd line do if [ "$ymd" = "$aweek_before" -o "$ymd" \> "$aweek_before" ] then echo $ymd $line fi done ||< solaris だと、これで動いたんですが、Linux だと TZ をごまかしても一日前にしか戻れませんでした <nobr>(´・ω・`)</nobr>

2 ● blue_star22
●10ポイント

いや、だからgrepをふたつかませればいいでしょう。|で。項目1で日時、項目2で目当てのフレーズ。

関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ