我正在编写一个node.js函数来ssh到远程机器,并尝试从各种不同的日志文件中获取异常日志。日志文件的重要位将如下所示:
.... gunk ....
2013-01-29 04:06:39,133 com.blahblah.BaseServlet processRequest Thread-1629 Site-102 Cons-0 Url-http://theurlthat.com/caused/the/problem App-26 yada yada yada
java.lang.NullPointerException
at com.blahblah.MyClass.hi(MyClass.java:173)
at com.blahblah.StandardStackTrace.main(StandardStackTrace.java:125)
at com.blahblah.SoOnAndSo.forth(SoOnAndSo.java:109)
at java.lang.Thread.run(Thread.java:595)
2013-01-29 04:06:39,133 com.blahblah.BaseServlet defaultThrowableHandler Thread-1629 Site-102 Cons-0 Url-http://theurlthat.com/caused/the/problem App-26 yad yada yada
TechnicalDifficultiesException: TD page delivered by handleThrowable
http://theurlthat.com/caused/the/problem
....more gunk....
我需要在日志文件中找到满足以下三个要求的异常和相应日期:
例外必须是此静态文本之前的第一个:
TechnicalDifficultiesException:由handleThrowable
Exception必须直接在具有“BaseServlet。* Site-102”的两行之间
例外必须是满足上述条件的日志文件中的最新(最后)。日志定期滚动,因此它需要是Log中的最后一个,或者如果它不存在于Log.001中的最后一个,或者如果不存在,则Log.002中的最后一个等等。
由于该程序必须ssh到许多潜在服务器中的一个,因此最好只需要维护node.js程序中的逻辑而不是具有日志的计算机上的逻辑。因此,perl / sed / awk / grep / etc中的单行是最理想的。
答案 0 :(得分:2)
所以,如果我理解正确,你的问题就是这样:
/BaseServlet.*?Site-102/
匹配的部分感兴趣。/^TechnicalDifficultiesException: TD page delivered by handleThrowable/
匹配,我们想要选择之前匹配的部分的主体,我们应该验证它看起来像一个java异常。足够公平。
#!/usr/bin/perl
use strict; use warnings;
local $/ = ""; # paragraph mode
my ($prev_sec, $prev_err);
SECTION:
while (my $head = <>) {
my $body = <>;
defined $body or die "Can't read from empty filehandle.";
next SECTION unless $head =~ /BaseServlet.*?Site-102/;
if ($body =~ /^TechnicalDifficultiesException: TD page delivered by handleThrowable/) {
$prev_err = $prev_sec;
}
$prev_sec = $body;
}
die "No error found" unless defined $prev_err;
print $prev_err;
(没有真正测试那么多,但打印出你的代码片段中的错误)
单行代码有点长。如果需要,您可以随时将源代码传递给perl解释器。
perl -ne'BEGIN{$/=""}END{print$prev_err}$b=<>;defined$b or die"empty FH";/BaseServlet.*?Site-102/ or next;$prev_err=$prev_sec if $b=~/^TechnicalDifficultiesException: TD page delivered by handleThrowable/;$prev_sec=$b'
将日志文件指定为命令行参数,或将文件内容直接传递到该程序中。找到正确的日志文件并不难。在Perl的片段中:
my $log_dir = ...;
my ($log) = sort glob "$log_dir/LOG*";
die "no log in $log_dir" unless defined $log;
如果还应捕获日期,则代码将更改为
#!/usr/bin/perl
use strict; use warnings;
local $/ = ""; # paragraph mode
my (@prev, @prev_err);
SECTION:
while (my $head = <>) {
my $body = <>;
defined $body or die "Can't read from empty filehandle.";
next SECTION unless $head =~ /BaseServlet.*?Site-102/;
if ($body =~ /^TechnicalDifficultiesException: TD page delivered by handleThrowable/) {
@prev_err = @prev;
}
@prev = ($head, $body);
}
die "No error found" unless @prev_err;
my ($date) = $prev_err[0] =~ /^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d),/;
print "$date\n\n$prev_err[1]";
并且作为单行:
perl -ne'BEGIN{$/=""}END{@perr||die"No error found";($date)=$perr[0]=~/^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d),/;print"$date\n\n$perr[1]"}$b=<>;defined$b or die"empty FH";/BaseServlet.*?Site-102/ or next;@perr=@p if $b=~/^TechnicalDifficultiesException: TD page delivered by handleThrowable/;@p=($_,$b)'
我不明白它是如何只返回第一场比赛的;此代码应处理整个文件。如果您可以提供更完整的测试用例,我可以验证此代码是否按要求运行。