开发者

Parsing a syslog entry

This is what an entry looks like:

Jan 26 20:53:31 hostname logger: System rebooted for hard disk upgrade

I'm writing a small application to parse entries like this and email a nicely formatted message to the admin. I'm writing in Perl and found the split() function which is exactly what I'm looking for:

my @tmp = split(/ /, $string, 4);
@tmp = {$date, $hostname, $facility, $message)

That's what I'm hoping to get. Split() can handle the spaces in the $message part because I limit the amount of "words" to split off. However, the spaces in the $date part throw it off. Is there a clean way I can get these variables to represent what they're supposed to?

I know I could use substr() to grab the first 15 characters (the date), then use split() and limit it to 3 words instead of 4, then grab all my strings from there. But is开发者_如何转开发 there a more elegant way to do this?


If one-lined-ness is important to elegance, split on spaces that are not followed by a digit:

my ( $time, $hostname, $facility, $message ) = split /\s+(?=\D)/, $string, 4;

But it makes more sense to use a combination of split and unpack to address the need:

my ( $timeStamp, $log ) = unpack 'A15 A*', $string;

my ( $host, $facility, $msg ) = split /\s+/, $log;


Does Parse::Syslog do what you need without the i-try-this-regexp-oh-it-does-not-work-ok-i-hcanged-and-it-works-oh-not-always-hmm-let-me-try-that-much-better-yay-oh-no-it-broke-let-me-try-this-one-has-nobody-done-this-yet feeling?


Use a regex. Here is a simple example:

$mystring = "Jan 26 20:53:31 hostname logger: System rebooted for hard disk upgrade";
if($mystring =~ m/(\w{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2})\s([^\s]*)\s([^\s:]*):\s(.*$)/) {
    $date=$1;
    $host=$2;
    $facility=$3;
    $mesg=$4;
    print "Date: $date\nHost: $host\nFacility: $facility\nMesg: $mesg";
}


Old question, but I experienced similar problem and rectified by formatting of my syslog messages ( hence modified rsyslog.conf)

I created rsyslog template as follows

template(name="CustomisedTemplate" type="list") {
    property(name="timestamp")
    constant(value=" ")
    property(name="$year")
    constant(value=";")
    property(name="hostname")
    constant(value=";")
    property(name="programname")
    constant(value=";")
    property(name="msg" spifno1stsp="on")
    property(name="msg" droplastlf="on")
    constant(value="\n")
}

then

I set my customised template as default by adding

    $ActionFileDefaultTemplate CustomisedTemplate.

to (r)syslog.conf

I could also create the filter for my program (logger), which will use template and redirect message created by program ( logger) to separate file. To achieve that, I added

    if $programname contains "logger" then /var/logs/logger.err;CustomisedTemplate

to (r)syslog.conf

So at the end my syslog entry looks like

Jan 26 20:53:31 2016;hostname;logger:;System rebooted for hard disk upgrade

which is rather easy to parse.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜