我需要验证我的日志文件:
- 所有新的日志行都应以日期开头。
- 此日期将遵守ISO 8601标准。例: 2011-02-03 12:51:45,220Z -
使用shell脚本,我可以验证它在每一行上的循环并验证日期模式。 代码如下:
#!/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
但是,有一个问题。有些日志包含堆栈跟踪或使用多行的东西,换句话说,stacktrace就是一个例子,它可以是任何东西。 Stacktrace示例:
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)
...
不会传递我的脚本,但有效! 然后,如果我运行我的脚本传递带有stacktraces的日志文件,我的脚本将失败,因为它逐行循环。
我有正确的模式,我需要验证记录器日期格式,但我没有错误的日期格式模式来跳过行。
我不知道如何解决这个问题。有人可以帮助我吗?
由于
答案 0 :(得分:1)
您需要将搜索日期锚定到行首(否则日期可能出现在行的任何位置 - 而不仅仅是在开头)。
以下代码段将遍历不以有效日期开头的所有行。您仍然需要确定这些行是否构成错误。
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 :(得分:1)
所以只是(静默地)丢弃单个堆栈跟踪。在一些冗长的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
没有继续出错,否则你需要追踪更多状态以避免两个连续的堆栈跟踪。
答案 2 :(得分:0)
这有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
}
答案 3 :(得分:-1)
创建条件以检查该行是否以日期开头。如果没有,请跳过该行,因为它是多行日志的一部分。
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
}