leostereo has asked for the wisdom of the Perl Monks concerning the following question:

Hello perl masters: Im trying to get some especific values listed on the status.dat file generated by nagios. I have seen some php scripts that can parse this file into a json format , this is ok but when I turn the json into an array there are a lot of data lost due to the nature of the json source. Im thinking about a script that changes dinamically a pattern to match while doing a loop over the file. The content of the file is something like:

hoststatus { host_name=AAA1 modified_attributes=0 check_command=check-host-alive check_period=24x7 notification_period=24x7 check_interval=5.000000 retry_interval=1.000000 } servicestatus { host_name=AAA1 plugin_output=eth0:UP, eth2:UP, eth3:UP, eth1:UP:4 UP: OK }

So I would like then to have: $1=host_name=AAA1 $2=plugin_output=eth0:UP, eth2:UP, eth3:UP, eth1:UP:4 Any ideas about how to achieve this would be pretiated Regards.

Replies are listed 'Best First'.
Re: Parsing nagios status.dat
by atcroft (Abbot) on Apr 01, 2016 at 15:06 UTC

    Here is a quick bit of "one-linery" that appears to work much as requested (at least with both the sample data you provided and a status.dat file from a Nagios system I have access to). It creates a hash, loads the values (with the type of entry in a TYPE field), and displays the entry using Data::Dumper. (Code also includes a "one-liner" that generates the sample data you provided.)

    Code:

    perl -Mstrict -Mwarnings -le ' sub tab { return q{ } x 4; } foreach my $s ( q(hoststatus {), tab . q{host_name=AAA1}, tab . q{modified_attributes=0}, tab . q{check_command=check-host-alive}, tab . q{check_period=24x7}, tab . q{notification_period=24x7}, tab . q{check_interval=5.000000}, tab . q{retry_interval=1.000000}, tab . q(}), q{}, q(servicestatus {), tab . q{host_name=AAA1}, tab . q{plugin_output=eth0:UP, eth2:UP, eth3:UP, eth1:UP:4 UP: OK}, tab . q(}) ) { print $s; } ' \ | \ perl -Mstrict -Mwarnings -MData::Dumper -lne ' use vars qw(%s); BEGIN{ $Data::Dumper::Deepcopy = $Data::Dumper::Sortkeys = 1; }; chomp; if ( m/\}/ ) { print Data::Dumper->Dump( [ \%s, ], [ qw( *s ) ] ); %s = (); } next if ( m/^\s*$/imsx ); $s{TYPE} = $1 if ( m/^\s*(\S+)\s*\{/imsx ); $s{$1} = $2 if ( m/^\s+([^=]+)=(.+)$/imsx ); '

    Output:

    Hope that helps.

    Update: 2016-04-01
    Quote mentions of "one-liner", as the code was written over multiple lines for readability.

    Update: 2016-04-01
    To answer the question in Re^2: Parsing nagios status.dat, instead of the first perl code (before the pipe ('|' character)), you would instead put something like cat /path/to/status.dat | perl .... (If you have questions regarding execution of scripts or "one-liners", you may wish to speak to your local sysadmin or help desk.)

      Wow !! thanks for the response. Two questions: 1; How should I run this script, are there 2 separated file? 2; where are you declaring the path to the status.dat file ? Thanks!

        Leo, what atcroft was pointing out is that you need to put your code like this:

        cat status.dat | \ perl -Mstrict -Mwarnings -MData::Dumper -lne ' use vars qw(%s); BEGIN{ $Data::Dumper::Deepcopy = $Data::Dumper::Sortkeys = 1; }; chomp; if ( m/\}/ ) { print Data::Dumper->Dump( [ \%s, ], [ qw( *s ) ] ); %s = (); } next if ( m/^\s*$/imsx ); $s{TYPE} = $1 if ( m/^\s*(\S+)\s*\{/imsx ); $s{$1} = $2 if ( m/^\s+([^=]+)=(.+)$/imsx ); '

      Ok ... I can not get it to work ... So far I have:

      #!/usr/bin/perl sub tab { return q{ } x 4; } my $host=shift(@ARGV); foreach my $s ( q(servicestatus {), tab . 'host_name='.$host, tab . 'plugin_output='./*./, tab . q(}) ) { print $s; }

      I can not get the string following the "plugin_output=" Sorry, I did not mentioned that , there are several lines beetween the "host_name" and the "plugin.." Any ideas ?