mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 13:22:36 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			519 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			519 lines
		
	
	
		
			14 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;
 | 
						|
}
 | 
						|
 |