"Fossies" - the Fresh Open Source Software Archive

Member "unix/plugins/grep_log" (15 Sep 2021, 11662 Bytes) of package /linux/misc/pandorafms_agent_unix-7.0NG.757.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/usr/bin/perl
    2 ###############################################################################
    3 #
    4 # Copyright (c) 2008  Ramon Novoa  <rnovoa@artica.es>
    5 # Copyright (c) 2008  Artica Soluciones Tecnologicas S.L.
    6 #
    7 # grep_log  Perl script to search log files for a matching pattern. The last
    8 #           searched position is saved in an index file so that consecutive
    9 #           runs do not return the same results. The log file inode number is
   10 #           also saved to detect log rotation.
   11 #
   12 # This program is free software; you can redistribute it and/or modify
   13 # it under the terms of the GNU General Public License as published by
   14 # the Free Software Foundation; version 2 of the License.
   15 #
   16 # This program is distributed in the hope that it will be useful,
   17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19 # GNU General Public License for more details.
   20 #
   21 ###############################################################################
   22 use strict;
   23 use File::Basename;
   24 use Scalar::Util qw(looks_like_number);
   25 
   26 # Output format (module or log_module).
   27 my $Output = 'module';
   28 
   29 # Be verbose
   30 my $Verbose = 0;
   31 
   32 # Index file storage directory, with a trailing '/'
   33 my $Idx_dir=($^O =~ /win/i)?"$ENV{'TMP'}\\":"/tmp/";
   34 
   35 # Log file
   36 my $Log_file = '';
   37 
   38 # Module name
   39 my $Module_name = "default_log";
   40 
   41 # Index file
   42 my $Idx_file = '';
   43 
   44 # Log file position index
   45 my $Idx_pos = 0;
   46 
   47 # Log file inode number
   48 my $Idx_ino = '';
   49 
   50 # Log file size
   51 my $Idx_size = 0;
   52 
   53 # Regular expression to be matched
   54 my $Reg_exp = '';
   55 
   56 # Flag to show or not summary module
   57 my $summary_flag = 0;
   58 
   59 my $nodatalist_flag = 0;
   60 
   61 # Number of coincidences found
   62 my $coincidences = 0;
   63 
   64 if ( (defined ($ENV{GREP_LOG_TMP})) && (-d $ENV{GREP_LOG_TMP}) ) {
   65     $Idx_dir=$ENV{GREP_LOG_TMP};
   66 }
   67 
   68 ########################################################################################
   69 # Erase blank spaces before and after the string
   70 ########################################################################################
   71 sub trim($){
   72     my $string = shift;
   73     if (empty ($string)){
   74         return "";
   75     }
   76 
   77     $string =~ s/\r//g;
   78 
   79     chomp ($string);
   80     $string =~ s/^\s+//g;
   81     $string =~ s/\s+$//g;
   82 
   83     return $string;
   84 }
   85 
   86 ########################################################################################
   87 # Empty
   88 ########################################################################################
   89 sub empty($){
   90     my $str = shift;
   91 
   92     if (! (defined ($str)) ){
   93         return 1;
   94     }
   95 
   96     if(looks_like_number($str)){
   97         return 0;
   98     }
   99 
  100     if ($str =~ /^\ *[\n\r]{0,2}\ *$/) {
  101         return 1;
  102     }
  103     return 0;
  104 }
  105 
  106 ###############################################################################
  107 # SUB error_msg
  108 # Print an error message and exit.
  109 ###############################################################################
  110 sub error_msg ($) {
  111     my $err_msg = $_[0];
  112 
  113     if (! -z $err_msg) {
  114         print(stderr "[error] $err_msg.\n");
  115     }
  116 
  117     exit 1;
  118 }
  119 
  120 ###############################################################################
  121 # SUB print_help
  122 # Print a help message.
  123 ###############################################################################
  124 sub print_help () {
  125     print "Usage: $0 <log_file> <module_name> <pattern> <up_lines_extra> <bot_lines_extra> [--summary] [--nodatalist]\n\n";
  126     print "Options:\n";
  127     print "\t<log_file>\t\tPath to the log file to be monitored\n";
  128     print "\t<module_name>\t\tName of the module that will be created\n";
  129     print "\t<pattern>\t\tRegex string to be matched in log file\n";
  130     print "\t<up_lines_extra>\tShows NUM lines before matching lines to provide context\n";
  131     print "\t<bot_lines_extra>\tShows NUM lines after matching lines to provide context\n";
  132     print "\t--summary\t\tCreates a module with the total number of matches\n";
  133     print "\t--nodatalist\t\tInserts all coincidences in a single data output instead of a data per line\n";
  134 }
  135 
  136 ###############################################################################
  137 # SUB log_msg
  138 # Print a log message.
  139 ###############################################################################
  140 sub log_msg ($) {
  141     my $log_msg = $_[0];
  142 
  143     if (! -z $log_msg && $Verbose == 1) {
  144         print(stdout "[log] $log_msg.\n");
  145     }
  146 }
  147 
  148 ###############################################################################
  149 # SUB load_idx
  150 # Load index file.
  151 ###############################################################################
  152 sub load_idx () {
  153     my $line;
  154     my $current_ino;
  155     my $current_size;
  156 
  157     log_msg("Loading index file $Idx_file");
  158 
  159     open(IDXFILE, $Idx_file) || error_msg("Error opening file $Idx_file: " .
  160                                              $!);
  161 
  162     # Read position and date
  163     $line = <IDXFILE>;
  164     ($Idx_pos, $Idx_ino, $Idx_size) = split(' ', $line);
  165 
  166     close(IDXFILE);
  167 
  168     # Reset the file index if the file has changed
  169     $current_ino = (stat($Log_file))[1];
  170     $current_size = -s "$Log_file";
  171     if ($current_ino != $Idx_ino || $current_size < $Idx_size) {
  172         log_msg("File changed, resetting index");
  173 
  174         $Idx_pos = 0;
  175         $Idx_ino = $current_ino;
  176     }
  177     $Idx_size = $current_size;
  178 
  179     return;
  180 }
  181 
  182 ###############################################################################
  183 # SUB save_idx
  184 # Save index file.
  185 ###############################################################################
  186 sub save_idx () {
  187 
  188     log_msg("Saving index file $Idx_file");
  189 
  190     open(IDXFILE, "> $Idx_file") || error_msg("Error opening file $Idx_file: "
  191                                               . $!);
  192     print (IDXFILE $Idx_pos . " " . $Idx_ino . " " . $Idx_size);
  193     close(IDXFILE);
  194 
  195     return;
  196 }
  197 
  198 ###############################################################################
  199 # SUB create_idx
  200 # Create index file.
  201 ###############################################################################
  202 sub create_idx () {
  203     my $first_line;
  204 
  205     log_msg("Creating index file $Idx_file");
  206 
  207     open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " .
  208                                          $!);
  209 
  210     # Go to EOF and save the position
  211     seek(LOGFILE, 0, 2);
  212     $Idx_pos = tell(LOGFILE);
  213 
  214     close(LOGFILE);
  215 
  216     # Save the file inode number
  217     $Idx_ino = (stat($Log_file))[1];
  218 
  219     # Save the index file
  220     save_idx();
  221 
  222     return;
  223 }
  224 
  225 ###############################################################################
  226 # SUB parse_log
  227 # Parse log file starting from position $Idx_pos.
  228 ###############################################################################
  229 sub parse_log (;$$) {
  230     my ($up_lines,$bot_lines) = @_;
  231     my $line;
  232 
  233     log_msg("Parsing log file $Log_file");
  234 
  235     # Open log file for reading
  236     open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " .
  237                                          $!);
  238 
  239     # Go to starting position.
  240     seek(LOGFILE, $Idx_pos, 0);
  241 
  242     # Parse log file
  243     my %data;
  244 
  245     # Matched line id
  246     my $matched_line = 0;
  247 
  248     if ( (defined($up_lines)) || (defined($bot_lines)) ){
  249         # Detailed workmode
  250         my @lines;
  251         my $nl = 0;
  252         my @nl_found;
  253         while ($line = <LOGFILE>) {
  254             push @lines, $line;
  255             if ($line =~ m/$Reg_exp/i) {
  256                 push @nl_found, $nl;
  257                 $coincidences++;
  258             }
  259             $nl++;
  260         }
  261         # Return all coincidences with the desired margin
  262         foreach my $curr_line (@nl_found){
  263             my $flag = 0; # avoid repetition of current line
  264             if (defined($up_lines)){
  265                 $flag = 1;
  266                 # Push upper lines
  267                 for (my $i = ($curr_line-$up_lines); $i<=$curr_line; $i++){
  268                     if ($i < 0) {next;}
  269                     if (defined ($lines[$i])) {
  270                         push (@{$data{$matched_line}}, $lines[$i]);
  271                     }
  272 
  273                 }
  274             }
  275             if (defined($bot_lines)){
  276                 # Push bottom lines
  277                 for (my $i = ($curr_line+$flag); $i<=($curr_line+$bot_lines); $i++){
  278                     if (defined ($lines[$i])) {
  279                         push (@{$data{$matched_line}}, $lines[$i]);
  280                     }
  281                 }
  282             }
  283             $matched_line++;
  284         }
  285     }
  286     else { # Standar workmode
  287         while ($line = <LOGFILE>) {
  288             if ($line =~ m/$Reg_exp/i) {
  289                 push (@{$data{$matched_line++}}, $line);
  290             }
  291         }
  292     }
  293 
  294     $Idx_pos = tell(LOGFILE);
  295     close(LOGFILE);
  296 
  297     # Save the index file
  298     save_idx();
  299 
  300     return \%data;
  301 }
  302 
  303 ###############################################################################
  304 # SUB print_summary
  305 # Print module summary to stdout.
  306 ###############################################################################
  307 sub print_summary() {
  308     my $output = "<module>\n";
  309     $output .= "<name><![CDATA[" . $Module_name . " coincidences]]></name>\n";
  310     $output .= "<type><![CDATA[async_data]]></type>\n";
  311     $output .= "<datalist>\n";
  312     $output .= "<data><value><![CDATA[$coincidences]]></value></data>\n";
  313     $output .= "</datalist>\n";
  314     $output .= "</module>\n";
  315     print stdout $output;
  316 }
  317 
  318 ###############################################################################
  319 # SUB parse_log
  320 # Print log data to stdout.
  321 ###############################################################################
  322 sub print_log ($) {
  323     my $data = shift;
  324 
  325     # No data
  326     my @kdata = keys (%{$data});
  327     if ($#kdata < 0) {
  328         print_summary() if ($summary_flag == 1);
  329         return;
  330 
  331     }
  332 
  333     # Log module
  334     if ($Output eq 'log_module') {
  335         my $output = "<log_module>\n";
  336         $output .= "<source><![CDATA[" . $Module_name . "]]></source>\n";
  337         $output .= "<data><![CDATA[";
  338         foreach my $line (@kdata) {
  339             my $processed_line = $line;
  340             $processed_line =~ s/\]\]/]]]]><![CDATA[/g;
  341             $output .= $processed_line;
  342         }
  343         $output .= "]]></data>";
  344         $output .= "</log_module>\n";
  345 
  346         print stdout $output;
  347     }
  348     # Regular module
  349     else {
  350         my $output;
  351         print_summary() if ($summary_flag == 1);
  352         $output = "<module>\n";
  353         $output .= "<name><![CDATA[" . $Module_name . "]]></name>\n";
  354         $output .= "<type><![CDATA[async_string]]></type>\n";
  355             if ($nodatalist_flag == 1){
  356                 $output .= "<data><![CDATA[";
  357                         foreach my $line (@kdata) {
  358                                 foreach my $content (@{$data->{$line}}) {
  359                                         my $processed_line = $content;
  360                         $processed_line =~ "\n";
  361                                         $output .= $processed_line;
  362                                 }
  363                         }
  364             $output .= "]]></data>\n";
  365             }
  366             else {  
  367         $output .= "<datalist>\n";
  368         foreach my $line (@kdata) {
  369             $output .= "<data><value><![CDATA[";
  370             foreach my $content (@{$data->{$line}}) {
  371                 my $processed_line = $content;
  372                 $processed_line =~ s/\]\]/]]]]><![CDATA[/g;
  373                 $output .= $processed_line;
  374             }
  375             $output .= "]]></value></data>\n";
  376         }
  377         $output .= "</datalist>\n";
  378             }
  379         $output .= "</module>\n";
  380 
  381         print stdout $output;
  382     }
  383 
  384 }
  385 
  386 ###############################################################################
  387 ###############################################################################
  388 ## Main
  389 ###############################################################################
  390 ###############################################################################
  391 
  392 # Check command line parameters
  393 if ($#ARGV < 2) {
  394     print_help();
  395     exit 1;
  396 }
  397 
  398 $Log_file     = trim($ARGV[0]);
  399 $Module_name  = trim($ARGV[1]);
  400 $Reg_exp      = trim($ARGV[2]);
  401 my $up_lines  = trim($ARGV[3]);
  402 my $bot_lines = trim($ARGV[4]);
  403 my $sum_flag  = trim($ARGV[5]);
  404 my $nodatalist = trim($ARGV[6]);
  405 
  406 if ( grep { /--summary/ } @ARGV )
  407 {
  408         $summary_flag = 1;
  409 }
  410 
  411 if ( grep { /--nodatalist/ } @ARGV )
  412 {
  413         $nodatalist_flag = 1;
  414 }
  415 
  416 # Create index file storage directory
  417 if ( ! -d $Idx_dir) {
  418     mkdir($Idx_dir) || error_msg("Error creating directory $Idx_dir: "
  419                                  . $!);
  420 }
  421 
  422 # Check that log file exists
  423 if (! -e $Log_file) {
  424     error_msg("File $Log_file does not exist");
  425 }
  426 
  427 # Create index file if it does not exist
  428 $Idx_file=$Idx_dir . $Module_name . "_" . basename($Log_file) . ".idx";
  429 if (! -e $Idx_file) {
  430     create_idx();
  431     exit 0;
  432 }
  433 
  434 # Load index file
  435 load_idx();
  436 
  437 # Parse log file
  438 my $data = parse_log($up_lines,$bot_lines);
  439 
  440 # Print output to stdout
  441 print_log ($data);
  442 
  443 exit 0;