Apache エラーログのエラー種類毎に件数をまとめたいので

estis2014/03/12 (水) 23:34 に投稿

Apache エラーログの種類毎に件数をまとめたいのだが、エラーの種類を全て網羅したかどうかがわからない。
それを何とかしたかったので、bash(と一部awk)で強引にスクリプトを作った。

#!/bin/sh

MYIFS=$IFS
IFS="
"

ERROR_LIST=error.list
TARGET_FILE=$1
WHILE_CHK=1

errors_extract(){
	true
	# Apacheエラーログからエラー内容のみを抽出
}

new_pattern(){
	echo -n "*** Not use / *** Input New Pattern: "
        read PATTERN
        echo $PATTERN >> $ERROR_LIST
}

error_chk(){
	for i in $(cat $TARGET_FILE)
	do
		echo 0 > match_chk 
		echo 0 > Not_match_chk 
		for j in $(cat $ERROR_LIST)
		do
			echo $i | awk -v notMatch=$(cat Not_match_chk) '/'$j'/{print 1 >"match_chk"} !/'$j'/{notMatch++; print notMatch >"Not_match_chk"}'
			MATCH_CHK=$(cat match_chk)
			[ $MATCH_CHK = 1 ] && WHILE_CHK=0 && break
			ERR_LIST_NUM=$(wc -l $ERROR_LIST | awk '{print $1}')
			NOT_MATCH_CHK=$(cat Not_match_chk)
			[ $NOT_MATCH_CHK = $ERR_LIST_NUM ] && WHILE_CHK=1 && echo $i && break 2
		done
	done
}

error_count(){
	rm match_chk Not_match_chk
	#エラー種類毎にカウントし、降順にソート
}




if [ $# -lt 1 ]; then
   echo "Need 1 argument. Usage: ./ApacheError.sh ApacheErrorLog"
   exit 1
fi

errors_extract

if [ ! -e $ERROR_LIST ]; then
		touch $ERROR_LIST
		echo "There was not \"$ERROR_LIST\". I made it."
fi

if [ ! -s $ERROR_LIST ]; then
		head -1 $TARGET_FILE
		new_pattern
fi

while [ $WHILE_CHK = 1 ] 
do
	error_chk
	[ $WHILE_CHK = 1 ] && new_pattern
done

error_count

error.list ファイルに、エラーの種類を記録していく(入力内容は、対話的に指示していく)
errors_extract と error_count には、それぞれの処理を行うawkスクリプト等を記載する。

Comments

Comment
#!/bin/sh

IFS="
"
TMPDAY=$(date "+%Y%m%H%M%S")
TMP_FILE=tmp.$TMPDAY
RESULT=result.$TMPDAY
ERRORS=errors.$TMPDAY
ERROR_LIST=error.list
TARGET_FILE=$1
WHILE_CHK=1

errors_extract(){
    echo "ERRORS EXTRACT start"
    awk 'BEGIN{FS="]"}$2~/error$/{print $NF}' $TARGET_FILE > $TMP_FILE
    sort $TMP_FILE | uniq -c | sort -k1 -nr > $ERRORS
    echo "ERRORS EXTRACT end"
}

new_pattern(){
    echo -n "*** Not use /() *** Input New Pattern: "
        read PATTERN
        echo $PATTERN >> $ERROR_LIST
}

error_chk(){
    for i in $(cat $TMP_FILE)
    do
        echo 0 > match_chk
        echo 0 > Not_match_chk
        for j in $(cat $ERROR_LIST)
        do
            echo -n "*"
            echo $i | awk -v notMatch=$(cat Not_match_chk) '/'$j'/{print 1 >"match_chk"} !/'$j'/{notMatch++; print notMatch >"Not_match_chk"}'
            MATCH_CHK=$(cat match_chk)
            [ $MATCH_CHK = 1 ] && WHILE_CHK=0 && break
            ERR_LIST_NUM=$(wc -l $ERROR_LIST | awk '{print $1}')
            NOT_MATCH_CHK=$(cat Not_match_chk)
            [ $NOT_MATCH_CHK = $ERR_LIST_NUM ] && WHILE_CHK=1 && echo $i && break 2
        done
    done
}

error_count(){
    echo
    echo "ERROR COUNT start"
    echo
    for i in $(cat $ERROR_LIST)
    do
        awk '/'$i'/{error["'$i'"]++}END{for(i in error)printf "%5i %6.2f%\t%s\n", error[i], error[i]/NR*100, i}' $TMP_FILE
    done | sort -k1 -nr|tee $RESULT
    rm match_chk Not_match_chk $TMP_FILE
    echo
    echo "ERROR COUNT end"
    echo "ERROR COUNT FILE ----> $RESULT"
    echo "ERROR DETAIL FILE ---> $ERRORS"
}



if [ $# -lt 1 ]; then
   echo "Need 1 argument. Usage: ./ApacheError.sh ApacheErrorLog"
   exit 1
fi

errors_extract

if [ ! -e $ERROR_LIST ]; then
        touch $ERROR_LIST
        echo "There was not \"$ERROR_LIST\". I made it."
fi

if [ ! -s $ERROR_LIST ]; then
        head -1 $TMP_FILE
        new_pattern
fi

while [ $WHILE_CHK = 1 ]
do
    error_chk
    [ $WHILE_CHK = 1 ] && new_pattern
done

error_count