如何从多个日志文件,按日期排序输出从几个不同的日志文件

问题描述:

我有输出:如何从多个日志文件,按日期排序输出从几个不同的日志文件

logfile3 
2010/07/21 15:28:52 INFO xxx 
2010/07/21 15:31:25 INFO xxx 
2010/07/21 15:31:25 DEBUG xxx 

logfile1 
2010/07/21 19:28:52 INFO xxx 
2010/07/21 19:31:25 INFO xxx 
2010/07/21 19:31:25 DEBUG xxx 

logfile2 
2010/07/21 13:28:52 INFO xxx 
2010/07/21 13:31:25 INFO xxx 
2010/07/21 13:31:25 DEBUG xxx 

我想按日期此排序输出,但保留日志上面的日志文件的名称线,所以它应该看起来像:

logfile2 
2010/07/21 13:28:52 INFO xxx 
2010/07/21 13:31:25 INFO xxx 
2010/07/21 13:31:25 DEBUG xxx 

logfile3 
2010/07/21 15:28:52 INFO xxx 
2010/07/21 15:31:25 INFO xxx 
2010/07/21 15:31:25 DEBUG xxx 

logfile1 
2010/07/21 19:28:52 INFO xxx 
2010/07/21 19:31:25 INFO xxx 
2010/07/21 19:31:25 DEBUG xxx 

你有任何想法如何排序这样的输出与bash命令,sed或awk? 非常感谢!

UPDATE: 这是输出

for i in $(find log/ -iname *debug*.log -size +0);do 
if [ `grep -c 'ERROR' $i` -gt 0 ];then 
echo -e "\n$i" 
grep 'ERROR' --color=auto -A 5 -B 5 $i 
fi 
done 

源马丁

+0

“我已经从几个不同的日志文件得到输出......”在一个文件中? – leonbloy 2010-07-21 19:18:30

+0

时间重叠吗?如果是这样,你想如何报告文件? – deinst 2010-07-21 19:30:20

谢谢大家。

我改进了丹尼斯威廉姆森的脚本,按日期排序错误。每个内部存在错误的日志文件都保存在由上次发生错误的时间戳命名的文件中。这些文件稍后进行排序并放在一起。可能会有更清晰的解决方案,而不是使用临时文件。

find log/ -iname "*debug*.log" -size +0 | while read -r file 
do 
    if grep -qsm 1 'ERROR' "$file" 
    then 
     echo -e "$i \t$file" 
     errors=$(grep 'ERROR' --color=auto -C 5 "$file") 
     #get the timestamp of last error occured 
     time=$(echo $errors | head -n 1 | awk '{print $1" "$2}') 
     timestamp=$(date -d "$time" +%s) 
     #save it to temp file 
     echo -e "\n$file\n$errors" > tmp/logs/$timestamp.$i 
    fi 
    let i++ 
done 

#put files together 
rm -f output.txt 
for i in `ls tmp/logs/*|sort`;do cat $i >> output.txt ; rm $i; done 

意见和改进建议表示赞赏!

Nicholas-Knights-MacBook-Pro:~/logtest$ ls 
logfile1 logfile2 logfile3 
Nicholas-Knights-MacBook-Pro:~/logtest$ cat logfile* 
2010/07/21 19:28:52 INFO xxx 
2010/07/21 19:31:25 INFO xxx 
2010/07/21 19:31:25 DEBUG xxx 

2010/07/21 13:28:52 INFO xxx 
2010/07/21 13:31:25 INFO xxx 
2010/07/21 13:31:25 DEBUG xxx 

2010/07/21 15:28:52 INFO xxx 
2010/07/21 15:31:25 INFO xxx 
2010/07/21 15:31:25 DEBUG xxx 

Nicholas-Knights-MacBook-Pro:~/logtest$ for i in `ls logfile*` ; do printf "$i"; sort -n $i; printf '\n'; done 
logfile1 
2010/07/21 19:28:52 INFO xxx 
2010/07/21 19:31:25 DEBUG xxx 
2010/07/21 19:31:25 INFO xxx 

logfile2 
2010/07/21 13:28:52 INFO xxx 
2010/07/21 13:31:25 DEBUG xxx 
2010/07/21 13:31:25 INFO xxx 

logfile3 
2010/07/21 15:28:52 INFO xxx 
2010/07/21 15:31:25 DEBUG xxx 
2010/07/21 15:31:25 INFO xxx 

Nicholas-Knights-MacBook-Pro:~/logtest$ 
+0

谢谢尼古拉斯,对不起,如果我不清楚。我想根据日志行的日期对输出进行排序,而不是按文件名进行排序 - 请参阅我的问题以获取所需输出。 – Martin 2010-07-21 19:24:18

如果你已经在一个文件中(或脚本输出)输出我会去的Perl:

$/=undef; 
$t=<>; 
@t=split(/\s*\n*(logfile.*)$/m,$t); 
foreach $f (@t) { 
    next unless $f; 
    if($f =~ /^logfile/) { 
     print $f; 
    } else { 
     print join("\n",sort (split(/\n/,$f))) . "\n\n"; 
    } 
} 

或者,更清洁一点:

@lines =(); 
while($t=<>) { 
    if($t!~ /^2\d\d\d/) { 
     print sort @lines if(scalar(@lines)); 
     @lines =(); 
     print $t; 
    } 
    else { 
     push @lines,$t; 
    } 
} 
print sort @lines if(scalar(@lines)); 
+0

不,它来自多个文件,我已将源脚本更新为该问题。我怎样才能使用这个脚本?谢谢! – Martin 2010-07-21 19:43:14

+0

它来自多个文件,但你已经有输出合并?如果是这样,是的,我的脚本可能会有帮助。但是在脚本中进行排序会更容易。 – leonbloy 2010-07-21 19:52:50

您也许能够从中得到令人满意的结果(只要不关你的文件名包含冒号):

grep -C 5 --recursive 'ERROR' log/* | sort --field-separator=: --key=2 

每一行都将通过文件名预先考虑。输出将是这个样子:

logfile2:2010/07/21 13:28:52 INFO xxx 
logfile2:2010/07/21 13:31:25 INFO xxx 
logfile2:2010/07/21 13:31:25 DEBUG xxx 

logfile3:2010/07/21 15:28:52 INFO xxx 
logfile3:2010/07/21 15:31:25 INFO xxx 
logfile3:2010/07/21 15:31:25 DEBUG xxx 
etc. 

您可以使用AWK重新格式化成你在你的例子显示格式:

grep -C 5 --recursive 'ERROR' log/* | sort --field-separator=: --key=2 | 
    awk '{colon = match($0,":"); file = substr($0,1,colon - 1); 
    if (file != prevfile) {print "\n" file; prevfile = file}; 
    print substr($0,colon+1)}' 

这里有一些改进你的脚本,如果你仍然使用它:

find log/ -iname "*debug*.log" -size +0 | while read -r file 
do 
    if grep -qsm 1 'ERROR' "$file" 
    then 
     echo -e "\n$file" 
     grep 'ERROR' --color=auto -C 5 "$file" 
    fi 
done 

$ awk 'FNR==1{$NF=$NF" "FILENAME;}1' logfile*|sort -t" " -k1 -k2|awk 'NF==5{ h=$NF;$NF="";$0=h"\n"$0 }1' 
logfile2 
2010/07/21 13:28:52 INFO xxx 
2010/07/21 13:31:25 DEBUG xxx 
2010/07/21 13:31:25 INFO xxx 
logfile3 
2010/07/21 15:28:52 INFO xxx 
2010/07/21 15:31:25 DEBUG xxx 
2010/07/21 15:31:25 INFO xxx 
logfile1 
2010/07/21 19:28:52 INFO xxx 
2010/07/21 19:31:25 DEBUG xxx 
2010/07/21 19:31:25 INFO xxx