Сценарий оболочки для проверки формата даты регистратора в файле журнала - PullRequest
2 голосов
/ 11 февраля 2011

Мне нужно проверить мои файлы журналов:

-Все новые строки журнала должны начинаться с даты.

-Данная дата будет соответствовать стандарту ISO 8601. Пример: 2011-02-03 12: 51: 45,220Z -

Используя сценарий оболочки, я могу проверить его зацикливание на каждой строке и проверку шаблона даты. Код ниже:

#!/bin/bash

processLine(){
    # get all args
    line="$@"    
    result=`echo $line | egrep "[0-9]{4}-[0-9]{2}-[0-9]{2} [012][0-9]:[0-9]{2}:[0-9]{2},[0-9]{3}Z" -a -c`    
    if [ "$result" == "0" ]; then
        echo "The log is not with correct date format: "
        echo $line
        exit 1
    fi

}


# Make sure we get file name as command line argument
if [ "$1" == "" ]; then
   echo "You must enter a logfile"
   exit 0
else
    file="$1"
    # make sure file exist and readable
    if [ ! -f $file ]; then
        echo "$file : does not exists"
        exit 1
    elif [ ! -r $file ]; then
        echo "$file: can not read"
        exit 2
    fi
fi


# Set loop separator to end of line
BAKIFS=$IFS
IFS=$(echo -en "\n\b")
exec 3<&0
exec 0<"$file"
while read -r line
do
    # use $line variable to process line in processLine() function
    processLine $line
done
exec 0<&3

# restore $IFS which was used to determine what the field separators are
IFS=$BAKIFS
echo SUCCESS

Но есть проблема. Некоторые журналы содержат трассировки стека или что-то, что использует более одной строки, другими словами, стек трассировки является примером, это может быть что угодно . Пример стека:

2011-02-03 12:51:45,220Z [ERROR] - File not found
java.io.FileNotFoundException: fred.txt
        at java.io.FileInputStream.<init>(FileInputStream.java)
        at java.io.FileInputStream.<init>(FileInputStream.java)
        at ExTest.readMyFile(ExTest.java:19)
        at ExTest.main(ExTest.java:7)
        ...

не пройдет с моим скриптом, но действует! Затем, если я запускаю свой сценарий, передавая, например, файл журнала со трассировкой стека, мой сценарий завершится сбоем, потому что он циклически переходит в строку.

У меня правильный шаблон, и мне нужно проверить формат даты в регистраторе, но у меня нет неправильного шаблона формата даты для пропуска строк.

Я не знаю, как я могу решить эту проблему. Кто-нибудь может мне помочь?

Спасибо

Ответы [ 4 ]

1 голос
/ 11 февраля 2011

Вам необходимо привязать поиск по дате к началу строки (в противном случае дата может появиться в любом месте строки, а не только в начале).

Следующий фрагмент будет зацикливаться на всех строках, которые не начинаются с правильной даты. Вы все еще должны определить, являются ли строки ошибками или нет.

DATEFMT='^[0-9]{4}-[0-9]{2}-[0-9]{2} [012][0-9]:[0-9]{2}:[0-9]{2},[0-9]{3}Z'
egrep -v ${DATEFMT} /path/to/log | while read LINE; do
   echo ${LINE} # did not begin with date.
done
1 голос
/ 11 февраля 2011

Так что просто (молча) отбросьте одну трассировку стека.В несколько многословном bash:

STATE=idle

while read -r line; do
    case $STATE in
    idle)
        if [[ $line =~ ^java\..*Exception ]]; then
            STATE=readingexception
        else
            processLine "$line"
        fi
        ;;

    readingexception)
        if ! [[ $line =~ ^' '*'at ' ]]; then
            STATE=idle
            processLine "$line"
        fi
        ;;

    *)
        echo "Urk! internal error [$STATE]" >&2
        exit 1
        ;;
    esac
done <logfile

Это полагается на processLine, не продолжая ошибки, иначе вам нужно будет отслеживать чуть больше состояния, чтобы избежать двух последовательных трассировок стека.

0 голосов
/ 12 февраля 2011

Это делает 2 предположения.

  1. строки, начинающиеся с пробела, являются продолжением предыдущих строк. мы сопоставляем начальный пробел или начальную табуляцию.
  2. строки с непробельными символами, начинающимися с ^, являются новыми строками журнала.

Если строка, соответствующая # 2, не соответствует формату даты, у нас есть ошибка, поэтому выведите ошибку и укажите номер строки.

count=0

processLine() {
     count=$(( count + 1 ))
     line="$@"

     result=$( echo $line | egrep '^[0-9]{4}-[0-9]{2}-[0-9]{2} [012][0-9]:[0-9]{2}:[0-9]{2},[0-9]{3}Z' -a -c )

     if (( $result == 0 )); then

        # if result = 0, then my line did not start with the proper date.
        # if the line starts with whitespace, then it may be a continuation
        # of a multi-line log entry (like a java stacktrace)

        continues=$( echo $line | egrep "^ |^   " -a -c )

        if (( $continues == 0 )); then

                # if we got here, then the line did not start with a proper date,
                # AND the line did not start with white space.  This is a bad line.

                echo "The line is not with correct date format: "
                echo "$count: $line"
                exit 1
        fi
    fi
}
0 голосов
/ 11 февраля 2011

Создайте условие, чтобы проверить, начинается ли строка с даты.Если нет, пропустите эту строку, поскольку она является частью многострочного журнала.

processLine(){
    # get all args
    line="$@"    
    result=`echo $line | egrep "[0-9]{4}-[0-9]{2}-[0-9]{2} [012][0-9]:[0-9]{2}:[0-9]{2},[0-9]{3}Z" -a -c`    
    if [ "$result" == "0" ]; then
        echo "Log entry is multi-lined - continuing."
    fi

}
...