シェルスクリプトの作成をお願いします。


・シスログ(/var/adm/messages)からエラー項目を抽出し、
 監査対象かを判別するリストファイルを読み込んで、
 あてはまるならば別のログファイルに書き出す。


これを1つのスクリプトファイルとして保存して
cronで5分毎に実行させます。

その際に前の実行時に記録されたエラーは含まれないように
するのですが私にはできませんでした。。

シスログのフォーマットは
"Nov 29 21:23:52 serverA snmpd[2408]: /etc/snmp/snmpd.conf: line 67: Error: Blank line following proc token.

であり、これをdateコマンドで取った日付と比較できずに行き詰っております。

(※date +%b でも解決できず・・・)


どうぞよろしくお願いします。

回答の条件
  • 1人10回まで
  • 登録:2006/11/30 18:01:19
  • 終了:2006/12/07 18:05:02

回答(5件)

id:bonlife No.1

回答回数421ベストアンサー獲得回数752006/11/30 19:07:35

ポイント20pt

GNU版のdateが使える環境であれば、日付文字列の比較は可能です。

date_comparison.sh というシェルを参考にしてみてください。

ちなみに「Nov 29 21:23:52」と同様の表示は「date +"%b %d %H:%M:%S"」で可能です。

(日の値が10未満の場合、前ゼロではなく、スペースにしたいのであれば、%d の部分は %e になります。)

後は、今どういうスクリプトになっているのか、などの情報を公開すると、より適切な回答が付くと思います。

(単純に別のログファイルの最終行をsedなどで読み込んで、それと一致する行以降を処理するようにすれば良いような気がしますが、いかがでしょうか。)

少しでも参考になれば幸いです。

id:SuperBel

ご回答ありがとうございます。

sedによる変換も考えましたが、日・月・年またぎの処理を意識してしまい思うように動きません。

現在のスクリプトは以下のとおりです。

=====================================

#!/bin/bash

#mo_evlc.bash

#daemon-list 監視を除外するデーモンのリスト

SYSLOGLIST=SYS_list.txt



NOWTIME=$(date '+%Y%m%d%H%M%S')


var1=$NOWTIME

SUM=$(expr $var1 - $var2)

SUM2=301

SYSLOG_CHECK=TRUE

cat /var/log/errlog > error.list2

#ER_LIST=(`tail -n 1 error.list2 | sed -e 's/ /,/g'` )

#ER_LIST=(`tail -n 1 error.list2` )

sed 's/Jan/01/g' error.list2

sed 's/Feb/02/g' error.list2

sed 's/Mar/03/g' error.list2

sed 's/Apr/04/g' error.list2

sed 's/May/05/g' error.list2

sed 's/Jun/06/g' error.list2

sed 's/Jul/07/g' error.list2

sed 's/Aug/08/g' error.list2

sed 's/Sep/09/g' error.list2

sed 's/Oct/10/g' error.list2

sed 's/Nov/11/g' error.list2

sed 's/Dec/12/g' error.list2



if [ "$SUM" -lt "$SUM2" ] ; then

A=${ER_LIST[2]}

if [ -z "${A// }" ] ; then

date >> result.log

echo "OK" >> result.log

else

if [ "${A//:}" -lt "$TIME" ] ; then

SYSLOG_CHECK=FALSE

elif [ "${A//:}" -ge "$TIME" ] ; then

if [ "${DAY}" -ne "${ER_LIST[1]}" ] ; then

SYSLOG_CHECK=FALSE

else

SYSLOG_CHECK=TRUE

fi

if [ "${SYSLOG_CHECK}" = TRUE ] ; then

FILTER_CHECK=TRUE

if [ "${FILTER_CHECK}" = TRUE ] ; then

date >> result2.log

echo "OK" >> result2.log

else

date >> result2.log

echo "NG" >> result2.log

tail -n 1 error.list2 >> more_detail2.log

fi



elif [ "${SYSLOG_CHECK}" = FALSE ] ; then

date >> result2.log

echo "NG" >> result2.log

fi



elif [ "${A//:}" -eq "$TIME" ] ; then

if [ "${DAY}" -ne "${ER_LIST[1]}" ] ; then

SYSLOG_CHECK=FALSE

else

SYSLOG_CHECK=TRUE

fi

if [ "${SYSLOG_CHECK}" = TRUE ] ; then

${ER_LIST} > sys.tmp

FILTER_CHECK=TRUE


if [ "${FILTER_CHECK}" = TRUE ] ; then

date >> result2.log

echo "OK" >> result2.log

else

date >> result2.log

echo "NG" >> result2.log

tail -n 1 error.list2 >> more_detail2.log

fi



elif [ "${SYSLOG_CHECK}" = FALSE ] ; then

date >> result2.log

echo "OK" >> result2.log

tail -n 1 error.list2 >> more_detail2.log

fi

fi


date '+%Y%m%d%H%M%S' > date.txt

fi

else

date >> result2.log

echo "OK" >> result2.log

fi


exit;

======================================

それではよろしくお願いします。

2006/11/30 19:28:14
id:kurukuru-neko No.2

kurukuru-neko回答回数1844ベストアンサー獲得回数1552006/11/30 21:07:11

ポイント20pt

時刻の比較は

date +"%s"

日付は

date --date="xxxx "

をしてあげればほとんど変換してくれます。

時間は同じ場合もあるので文字も比較をした方が

よいように思います。

以下例:

-------------------------------------------

#!/bin/bash

TMPF1=/tmp/tmpfile1.$$

TMPF2=/tmp/tmpfile2.$$

PREVLOG=/tmp/tmpfile.prev

NLINE=3

export LANG=C

trap "rm -f $TMPF1 $TMPF2" INT QUIT TERM EXIT

cp /var/log/messages $TMPF1

tail -$NLINE $PREVLOG >$TMPF2 2>>/dev/null

if [ $? -ne 0 ] ; then

tail -$NLINE $TMPF1 >$PREVLOG

else

tail -$NLINE $TMPF1 >$PREVLOG

gawk -v OUTPUT=$TMPF2 -v NLINE=$NLINE '

BEGIN {

# Read Last N Lines

ilog=0;

while( (getline line <OUTPUT ) > 0 ) {

ilogs[ilog++] = line;

# print "PREV",line;

};

# Parse Log Date

lasttime=0;

do {

if( ilog == 0 ) {

break;

};

if( split(ilogs[ilog-1],idata," ")< 3 ){

break;

};

scmd=sprintf("date --date=\"%s %s %s\" +\"%%s\"",idata[1],idata[2],idata[3]);

scmd | getline lasttime;

} while( 0 );

# Clear Output File

lmatch=0;

system("rm -f "OUTPUT);

}

NF > 2 {

if( lmatch >= ilog ) {

print >>OUTPUT;next;

};

if( NR == 1 && NF >= 3) {

scmd=sprintf("date --date=\"%s %s %s\" +\"%%s\"",$1,$2,$3);

scmd | getline logdate;

if( logdate > lasttime ) {

lmatch = ilog;print >>OUTPUT;next

};

};

if( ilogs[lmatch] == $0 ) {

lmatch++; next;

};

lmatch=0;

next;

}

' $TMPF1

rm -f $TMPF1

if [ -f $TMPF2 ]; then

mv $TMPF2 $TMPF1

fi

fi

# Check Log

if [ -f $TMPF1 ] ; then

echo "Analyse data $TMPF1"

cat $TMPF1

fi

id:SuperBel

ありがとうございます。

この場合は直近の3つのログを確認しているということでよろしいでしょうか?

前回実行時から今回までの5分間に発生したエラーログをすべて対象としたいのですが。

2006/11/30 21:41:02
id:kurukuru-neko No.3

kurukuru-neko回答回数1844ベストアンサー獲得回数1552006/11/30 21:50:39

ポイント20pt

年末をまたぐ場合の処理はしていません。

※: のログ書式によってはもう少し工夫が必要

年末対策

scmd=sprintf("date --date=\"%s %s %s\" +\"%%s\"",idata[1],idata[2],idata[3]);

scmd | getline lasttime;

# Add New Year Fix

if( lasttime > systime() ) {

iyear=strftime("%Y",systime());

scmd=sprintf("date --date=\"%s %s %s %d\" +\"%%s\"",idata[1],idata[2],idata[3],iyear-1);

scmd | getline lasttime;

}

同様に

scmd | getline logdate;

# Add New Year Fix

if( logdate > systime() ) {

iyear=strftime("%Y",systime());

scmd=sprintf("date --date=\"%s %s %s %d\" +\"%%s\"",$1,$2,$3,iyear-1);

scmd | getline logdate;

}

一部訂正

tail -$NLINE $PREVLOG >$TMPF2 2>>/dev/null

RC=$?

tail -$NLINE $TMPF1 >$PREVLOG

if [ $RC -ne 0 ] ; then

rm -f $TMPF2

else

gawk .....

id:SuperBel

ありがとうございます!

これは監査対象となるデーモンを

1行毎に記入したテキストのリストファイルで

フィルタリングをかけることが可能でしょうか?

2006/12/01 01:49:51
id:kurukuru-neko No.4

kurukuru-neko回答回数1844ベストアンサー獲得回数1552006/11/30 22:15:43

ポイント20pt

>前回実行時から今回までの5分間に発生したエラーログを

>すべて対象としたいのですが。

 対象です。

 

 ログファイルは文字なので1行で比較してもよいが

 連続したログが記録される場合があります。

 念のために最後に処理したログの3行を保存して

 再度処理する場合に3行したデータを移行又は、

 一致データがない場合は全てを対象とします。

 最初は全て対象ですが2回目以降は、対象は差分のみです。

 差分だけほしい場合

 tail -3 /var/log/messages >/tmp/tmpfile.prev

としてログの時刻を少し前変更してみてください。

※:/tmp/tmpfilexxxxのファイル名は変更してください。

  

id:kurukuru-neko No.5

kurukuru-neko回答回数1844ベストアンサー獲得回数1552006/11/30 22:37:02

ポイント20pt

>date '+%Y%m%d%H%M%S' > date.txt

 処理をした時刻を記録していますが。

 エラーログに記録される時刻が常に正しいとは

 限りません。

 時刻は進んだり戻ったりする事もあります。

 又、処理している間にもログはかかれていたり

 バッファにあってたまたまかかれていない場合も

 あるので処理した時刻を記録することはあまり

 意味ないと思います。

 必要なのは未処理データの抽出と思います。

よくする方法はsyslog.confの出力先に

named pipe等を指定してあげて

 常駐プロセスが適時処理するような方法か

 syslog-ngのようなログ解析機能があるものを

 検討するのも手です。

 http://www.infoscience.co.jp/technical/press/app06.html

 http://www.atmarkit.co.jp/fsecurity/rensai/unix_sec09/unix_sec01...

 swatchによるログの常時監視 

 http://www.atmarkit.co.jp/flinux/rensai/root04/root04b.html

 http://itpro.nikkeibp.co.jp/members/NBY/techsquare/20030630/2/

id:SuperBel

ありがとうございます。

しかしながら、今回はsyslogの運用方法で決定しているので変えることはできません。

上に記述した要件を満たすスクリプト、作成していただければ幸いです。

2006/12/01 17:21:25

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません