現在、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週間分だけ抽出する何か妙案はないでしょうか。
シェルスクリプトの中で 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" は、間違いじゃないです :-)
シェルスクリプトの中で 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" は、間違いじゃないです :-)
あ、仲間。
ぼくも Perl は苦手です :-)
処理が込み入ってくると grep, sed → awk → perl って感じで考えます。
最後が python や ruby じゃなくて perl なのは、いろんな unix を触って来たからです。
自分でパッケージを組み込んで良い環境なら、ruby を入れちゃいますが、そうもいかない環境での仕事もある(というか、そっちが大半)ので、最初から入ってることが多い perl を使います(仕方なく)。
と言っても、複雑な正規表現の切り出しと、時刻の扱いくらいまでしかやりませんが。
昔の手法だと、TZ 環境変数を無理矢理ずらして、date コマンドでn日前の日付を取得する、という方法もあります。
$ TZ=JST+159 date +"%Y/%m/%d"
これと、シェルの組み込みコマンドの read を組み合わせる、という方法も無くはないんですが、
という感じで...
将来、条件が複雑になる可能性が高いなら、今から java で作っちゃう、というのもひとつの手だと思います。
もしくは、メンテできる程度までは頑張って、どうにもならなくなってから java で組むことを考えるとか。
これと、シェルの組み込みコマンドの read を組み合わせる、という方法も無くはないんですが、
こんな感じ。
#!/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 をごまかしても一日前にしか戻れませんでした
あ、仲間。
ぼくも Perl は苦手です :-)
処理が込み入ってくると grep, sed → awk → perl って感じで考えます。
最後が python や ruby じゃなくて perl なのは、いろんな unix を触って来たからです。
自分でパッケージを組み込んで良い環境なら、ruby を入れちゃいますが、そうもいかない環境での仕事もある(というか、そっちが大半)ので、最初から入ってることが多い perl を使います(仕方なく)。
と言っても、複雑な正規表現の切り出しと、時刻の扱いくらいまでしかやりませんが。
昔の手法だと、TZ 環境変数を無理矢理ずらして、date コマンドでn日前の日付を取得する、という方法もあります。
これと、シェルの組み込みコマンドの read を組み合わせる、という方法も無くはないんですが、
という感じで...
2015/04/06 15:31:53将来、条件が複雑になる可能性が高いなら、今から java で作っちゃう、というのもひとつの手だと思います。
もしくは、メンテできる程度までは頑張って、どうにもならなくなってから java で組むことを考えるとか。
こんな感じ。
solaris だと、これで動いたんですが、Linux だと TZ をごまかしても一日前にしか戻れませんでした(´・ω・`)
2015/04/06 16:16:35