mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-28 18:05:31 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@5335 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			510 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			510 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl
 | |
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| #------------------------------------------------------------------------------
 | |
| =head1  monaixsyslog
 | |
| =head2  
 | |
| =cut
 | |
| #------------------------------------------------------------------------------
 | |
| use locale;
 | |
| use Getopt::Long;
 | |
| 
 | |
| my $dirname = "xcat_aix_syslog";
 | |
| my $vardir = "/var/opt/$dirname";   
 | |
| 
 | |
| my $default_runfile = "$vardir/.monaixsyslog_run";
 | |
| my $default_file = "$vardir/syslog.out";
 | |
| my $default_pri = "*.warn";
 | |
| 
 | |
| $::MAX_SENSOR_STRING = 65535;
 | |
| my ($facility_priority, $logfile, $runfile) = &getArgs();
 | |
| 
 | |
| my ($syslogconf, $embedinfo);
 | |
| 
 | |
| $syslogconf = "/etc/syslog.conf";
 | |
| $embedinfo = "$facility_priority   $logfile    rotate size 4m files 1";
 | |
| 
 | |
| if (!-d $vardir) { mkdir($vardir); }
 | |
| 
 | |
| #check to see if this is the first time this script has been run
 | |
| if (!-e $runfile)
 | |
| {      #first time
 | |
| 	if ($^O =~ /^aix/i)
 | |
| 	{
 | |
| 		runcmd("grep \"$embedinfo\" $syslogconf", -1);
 | |
| 		if ($::RUNCMD_RC == 1)
 | |
| 		{    #grep did not find embedinfo
 | |
| 			    #update syslog.conf
 | |
| 			if (!-d $vardir) { mkdir($vardir); }
 | |
| 			if (!-e $logfile)
 | |
| 			{
 | |
| 			    touchFile($logfile);
 | |
| 			}
 | |
| 			runcmd("echo \"$embedinfo\" >> $syslogconf");
 | |
| 			my $cmd = "refresh -s syslogd";
 | |
| 			runcmd($cmd);
 | |
| 		}
 | |
| 		touchFile($runfile);
 | |
| 	}	
 | |
| 	else
 | |
| 	{
 | |
| 		print "non-AIX platform, this scripts should not be ran.\n";
 | |
| 		exit 1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #Check for errors
 | |
| 
 | |
| if ($^O =~ /^aix/i)
 | |
| {
 | |
|     unless (open(RUNFILE, "<$runfile"))
 | |
|     {
 | |
|         print "Cannot open file $runfile\n"; 
 | |
|         exit 1;
 | |
|     }
 | |
|     
 | |
|     my $marker = <RUNFILE>;
 | |
|     close(RUNFILE);
 | |
| 
 | |
|     my ($new_number, $new_content, $to_rfile);
 | |
|     # If the $runfile is empty, then we should read the $logfile from the beginning.
 | |
|     if (!$marker)
 | |
|     {
 | |
|         ($new_number, $new_content, $to_rfile) = &refreshSensorFromLogfile($logfile, 0, undef);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         my @info = split ':::', $marker;
 | |
|         my ($last_modified_time, $line_number, $mark_content) = @info;
 | |
|         
 | |
|         my @stats = stat($logfile);
 | |
|         my $time = $stats[9];
 | |
|         if ($time == $last_modified_time)
 | |
|         {
 | |
|             # The log file has not been updated since last modified.
 | |
|             exit 0;
 | |
|         }
 | |
| 
 | |
|         ($new_number, $new_content, $to_rfile) = &refreshSensorFromLogfile($logfile, $line_number, $mark_content);
 | |
| 
 | |
|         # If the $to_rfile is set, then we should refresh the info from rotated file to Sensor first.
 | |
|         if ($to_rfile)
 | |
|         {
 | |
|             # Read the rotated file first.
 | |
|             my $rotated_file = "$logfile" . ".0";
 | |
|             ($new_number, $new_content, $to_rfile) = &refreshSensorFromLogfile($rotated_file, $line_number, $mark_content);
 | |
| 
 | |
|             # Then read the log file just from the beginning to refresh the Sensor.
 | |
|             ($new_number, $new_content, $to_rfile) = &refreshSensorFromLogfile($logfile, 0, undef);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     # Get the last modified time for this log file
 | |
|     my @stats = stat($logfile);
 | |
|     my $new_time = $stats[9];
 | |
| 
 | |
|     &updateRunfile($new_time, $new_number, $new_content, $runfile);
 | |
| }
 | |
| else
 | |
| {
 | |
|     print "non-AIX platform, this scripts should not be ran.\n";
 | |
| 	exit 1;
 | |
| }
 | |
| 
 | |
| exit 0;
 | |
| 
 | |
| #-------------------------------------------------------------------------------
 | |
| 
 | |
| =head3    getArgs
 | |
| 
 | |
| 	parse the command line and check the values
 | |
| 
 | |
| 	paras: 
 | |
| 	-p  :    <facility>.<priority>, the default value is "*.warn"
 | |
| 	-f  :    <fifo_name>, the default value is "/var/opt/xcat_aix_syslog/syslog_fifo"
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------------------------
 | |
| sub getArgs()
 | |
| {
 | |
|     my $routine = "getArgs";
 | |
|     print "ENTERING: $routine\n" if $::DEBUG;
 | |
| 
 | |
|     my @command_line = ();
 | |
|     @command_line   = @ARGV;
 | |
| 
 | |
|     # Checks case in GetOptions
 | |
|     $Getopt::Long::ignorecase = 0;
 | |
| 
 | |
|     my ($facility_priority, $file, $runfile);
 | |
| 
 | |
|     if (
 | |
|         !GetOptions(
 | |
|                     'p=s'      => \$facility_priority,
 | |
|                     'f=s'      => \$file,
 | |
|         )
 | |
|       )
 | |
|     {
 | |
|         print "LEAVING: $routine\n" if $::DEBUG;
 | |
|         exit 1;
 | |
|     }
 | |
| 
 | |
|     # Set runfile mark file
 | |
|     if ($facility_priority || $file)
 | |
|     {
 | |
|         my @para = split '/', $file;
 | |
|         my $newpara = join '-', @para;
 | |
|         $runfile = "$vardir/.monaixsyslog_run" . "-$facility_priority". "-$newpara";
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         $runfile = $default_runfile;
 | |
|     }
 | |
| 
 | |
|     if (!$file)
 | |
|     {
 | |
|         $file = $default_file; 
 | |
|     }
 | |
| 
 | |
|     if (!$facility_priority)
 | |
|     {
 | |
|         $facility_priority = $default_pri;
 | |
|     }
 | |
|     
 | |
|     return ($facility_priority, $file, $runfile);
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------------------------------
 | |
| 
 | |
| =head3    refreshSensorFromLogfile
 | |
| 
 | |
| 	read the log file line by line to refresh the Sensor
 | |
| 
 | |
|     Args:
 | |
|     $file       - the log file
 | |
|     $bgnline    - the beginning line number that we should read from
 | |
|     $bgncontent - the line content related to $line
 | |
| 
 | |
|     Return:
 | |
|     $i            - the line number that has been read and refreshed to Sensor.
 | |
|     $mark_content - the line content related to $i
 | |
|     $to_rfile     - the flag that indicates whether we need to read from the 
 | |
|                     rotated file.
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------------------------
 | |
| sub refreshSensorFromLogfile()
 | |
| {
 | |
|     my ($file, $bgnline, $bgncontent) = @_;
 | |
|     unless (open(FILE, "<$file"))
 | |
|     {
 | |
|         # The file may be opened by syslogd.
 | |
|         exit 0;
 | |
|     }
 | |
|     
 | |
|     my $i = 0;
 | |
|     my $matchflag = 0;
 | |
|     my $to_rfile = 0;
 | |
|     my $mark_content;
 | |
|     my $allinfo = "";
 | |
|     while (my $line = <FILE>)
 | |
|     {
 | |
|         if ($matchflag || $bgnline == 0)
 | |
|         {
 | |
|             # Start reading the file from this line and push it to the sensor
 | |
|             # and update the mark file
 | |
|             $allinfo .= $line;
 | |
|     		$i = $i + 1;
 | |
|     		$mark_content = $line;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if ($i != $bgnline - 1)
 | |
|             {
 | |
|                 $i = $i + 1;
 | |
|                 next;
 | |
|             }
 | |
| 
 | |
|             if ($line eq $bgncontent)
 | |
|             {
 | |
|                 $matchflag = 1;
 | |
|                 $i = $i + 1;
 | |
|                 next;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 # The line number is the same, but the content is different
 | |
|                 # that indicates the log file has been rotated.
 | |
|                 $to_rfile = 1;
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     if ($allinfo)
 | |
|     {
 | |
|         my $strlen = length($allinfo);
 | |
|         # The condition/response can not handle
 | |
|         # the long sensor String very well,
 | |
|         # use file to pass messages.
 | |
|         # file name: /var/opt/xcat_aix_syslog/tmplogmsg_$$
 | |
|         if ($strlen > $::MAX_SENSOR_STRING)
 | |
|         {
 | |
|             srand(time | $$);
 | |
|             my $filename = "$vardir/tmplogmsg_$$";
 | |
|             while (-e $filename)
 | |
|             {
 | |
|                 $filename = createRandomName($filename);
 | |
|             }
 | |
|             if (open(TMPLOG, ">$filename"))
 | |
|             {
 | |
|                 print TMPLOG $allinfo;
 | |
|                 close TMPLOG;
 | |
|                 print "XCAT_MONAIXSYSLOG_FILE:$filename";
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 #open failed, why?
 | |
|                 print "OPEN_FILE_FAILED: $filename";
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|              print $allinfo;
 | |
|         }
 | |
|     }
 | |
|     close(FILE);
 | |
| 
 | |
|     return ($i, $mark_content, $to_rfile);
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------------------------------
 | |
| 
 | |
| =head3    updateRunfile
 | |
| 
 | |
| 	use the new marker line to update the runfile
 | |
| 
 | |
|     Args:
 | |
|     $time - last mofidied time
 | |
|     $line - line number
 | |
|     $content - line content
 | |
|     $file - the run file
 | |
| 
 | |
|     Return:
 | |
|     $i            - the line number that has been read and refreshed to Sensor.
 | |
|     $mark_content - the line content related to $i
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------------------------
 | |
| sub updateRunfile()
 | |
| {
 | |
|     my ($time, $line, $content, $file) = @_;
 | |
|     
 | |
|     # the marker line is something like "last_modified_time:::line_number:::mark_content"
 | |
|     my $new_marker = join(":::", $time, $line, $content);
 | |
|     runcmd("echo \"$new_marker\" > $file");
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| =head3    runcmd
 | |
|     Run the given cmd and return the output in an array (already chopped).  Alternatively,
 | |
|     if this function is used in a scalar context, the output is joined into a single string
 | |
|     with the newlines separating the lines.  
 | |
|     Arguments:
 | |
|         command, exitcode and reference to output
 | |
|     Returns:
 | |
|         see below
 | |
|     Error:
 | |
|         Normally, if there is an error running the cmd, it will display the error msg
 | |
|         and exit with the cmds exit code, unless exitcode is given one of the
 | |
|         following values:
 | |
|              0:     display error msg, DO NOT exit on error, but set
 | |
|                 $::RUNCMD_RC to the exit code.
 | |
|             -1:     DO NOT display error msg and DO NOT exit on error, but set
 | |
|                 $::RUNCMD_RC to the exit code.
 | |
|             -2:    DO the default behavior (display error msg and exit with cmds
 | |
|                 exit code.
 | |
|         number > 0:    Display error msg and exit with the given code
 | |
|     Example:
 | |
|         my $outref =  runcmd($cmd, -2, 1);     
 | |
|     Comments:
 | |
|         If refoutput is true, then the output will be returned as a reference to
 | |
|         an array for efficiency.
 | |
| =cut
 | |
| #--------------------------------------------------------------------------------
 | |
| sub runcmd
 | |
| {
 | |
|   my ($cmd, $exitcode, $refoutput) = @_;
 | |
|   $::RUNCMD_RC = 0;
 | |
|   if (!($cmd =~ /2>&1$/)) { $cmd .= ' 2>&1'; }
 | |
|   
 | |
|   my $outref = [];
 | |
|   @$outref = `$cmd`;
 | |
|   if ($?)
 | |
|   {
 | |
|     $::RUNCMD_RC = $? >> 8;
 | |
|     my $displayerror = 1;
 | |
|     my $rc;
 | |
|     if (defined($exitcode) && length($exitcode) && $exitcode != -2)
 | |
|     {
 | |
|       if ($exitcode > 0)
 | |
|       {
 | |
| 	$rc = $exitcode;
 | |
|       }    # if not zero, exit with specified code
 | |
|       elsif ($exitcode <= 0)
 | |
|       {
 | |
| 	$rc = '';    # if zero or negative, do not exit
 | |
| 	if ($exitcode < 0) { $displayerror = 0; }
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       $rc = $::RUNCMD_RC;
 | |
|     }    # if exitcode not specified, use cmd exit code
 | |
|     if ($displayerror)
 | |
|     {
 | |
|       my $errmsg = '';
 | |
|       if (($^O =~ /^linux/i) && $::RUNCMD_RC == 139)
 | |
|       {
 | |
|         $errmsg = "Segmentation fault  $errmsg";
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         # The error msgs from the -api cmds are pretty messy.  Clean them up a little.
 | |
|         filterRmcApiOutput($cmd, $outref);
 | |
|         $errmsg = join('', @$outref);
 | |
|         chomp $errmsg;
 | |
|       }
 | |
|       print "Exit code $::RUNCMD_RC from command: $cmd\nError message from cmd: $errmsg\n"
 | |
|     }
 | |
|   }
 | |
|   if ($refoutput)
 | |
|   {
 | |
|     chomp(@$outref);
 | |
|     return $outref;
 | |
|   }
 | |
|   elsif (wantarray)
 | |
|   {
 | |
|     chomp(@$outref);
 | |
|     return @$outref;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     my $line = join('', @$outref);
 | |
|     chomp $line;
 | |
|     return $line;
 | |
|   }
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| =head3    filterRmcApiOutput
 | |
|     filter RMC Api Output
 | |
|     Arguments:
 | |
|         RMC command
 | |
|         Output reference
 | |
|     Returns:
 | |
|         none
 | |
|     Globals:
 | |
|         none
 | |
|     Error:
 | |
|         none
 | |
|     Example:
 | |
|           filterRmcApiOutput($cmd, $outref);
 | |
|     Comments:
 | |
|         The error msgs from the RPM -api cmds are pretty messy.
 | |
|         This routine cleans them up a little bit.
 | |
| =cut
 | |
| #--------------------------------------------------------------------------------
 | |
| sub filterRmcApiOutput
 | |
| {
 | |
|   my ($cmd, $outref) = @_;
 | |
|   if (!($cmd =~ m|^/usr/bin/\S+-api |))  {
 | |
|     return;
 | |
|   }    # give as much info as possible, if verbose
 | |
| 
 | |
|   # Figure out the output delimiter
 | |
|   my ($d) = $cmd =~ / -D\s+(\S+)/;
 | |
|   if (length($d))  {
 | |
|     $d =~ s/^(\'|\")(.*)(\"|\')$/$2/;    # remove any surrounding quotes
 | |
|     # escape any chars perl pattern matching would intepret as special chars
 | |
|     $d =~ s/([\|\^\*\+\?\.])/\\$1/g;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     $d = '::';
 | |
|   }    # this is the default output delimiter for the -api cmds
 | |
|   $$outref[0] =~ s/^ERROR${d}.*${d}.*${d}.*${d}.*${d}//;
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| 
 | |
| =head3  touchFile
 | |
|     Arguments: $filename, $donotExit
 | |
|     Returns: non zero return code indicates error
 | |
|     Example:  touchFile("/var/opt/xcat/touch");
 | |
| =cut
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| sub touchFile
 | |
| {
 | |
|   my ($filename, $donotExit) = @_;
 | |
|   my $fh;
 | |
|   my $rc = 0;
 | |
|   if (!-e $filename)  {   
 | |
|     #if the file doesn't exist we need to open and close it
 | |
|     open($fh, ">>$filename") or $rc++;
 | |
|     if ($rc > 0 && !$donotExit)    {
 | |
|       print "Touch of file $filename failed with: $!\n";
 | |
|       return $rc;
 | |
|     }
 | |
|     close($fh) or $rc++;
 | |
|   }
 | |
|   else  { 
 | |
|     #if the file does exist we can just utime it (see the perlfunc man page entry on utime)
 | |
|     my $now = time;
 | |
|     utime($now, $now, $filename);
 | |
|   }
 | |
|   if ($rc > 0 && !$donotExit)  {
 | |
|       print "Touch of file $filename failed with: $!\n";
 | |
|     return $rc;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| 
 | |
| =head3    createRandomName
 | |
| 
 | |
|         Create a randome file name.
 | |
| 
 | |
|         Arguments:
 | |
|                 Prefix of name
 | |
|         Returns:
 | |
|                 Prefix with 8 random letters appended
 | |
|         Error:
 | |
|                 none
 | |
|         Example:
 | |
|                 $file = createRandomName($namePrefix);
 | |
|         Comments:
 | |
|                 None
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #--------------------------------------------------------------------------------
 | |
| 
 | |
| sub createRandomName
 | |
| {
 | |
|     my $name=shift;
 | |
| 
 | |
|     my $nI;
 | |
|     for ($nI = 0 ; $nI < 8 ; $nI++)
 | |
|     {
 | |
|         my $char = ('a' .. 'z', 'A' .. 'Z')[int(rand(52)) + 1];
 | |
|         $name .= $char;
 | |
|     }
 | |
|     $name;
 | |
| }
 | |
| 
 |