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スクリプト等を記載する。
完成版
#!/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