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.
精彩评论