blueflashlight has asked for the wisdom of the Perl Monks concerning the following question:
#!/usr/local/bin/perl -w #===================================================================== # cinnamon -- a perl script that translates the sense data from SIM # and MIM messages posted by IBM 3590 tape drives into # human-readable format, and sends the messages via email #--------------------------------------------------------------------- # $Id: cinnamon,v 1.1 2001/08/21 04:48:51 ssklar Exp $ #===================================================================== use strict; $|++; unless ($^O =~ /aix/) { die "Cinnamon is only useful on AIX systems. Sorry.\n" }; #--------------------------------------------------------------------- +- # the email address(es) that the formatted error message is to be sent # to. Don't forget to backslash any "@" signs ... #--------------------------------------------------------------------- +- my $recipient = "root"; unless (defined($recipient)) { $recipient = "root" } #--------------------------------------------------------------------- +- # the sequence number of the error log entry that we were invoked for # will be passed as the single argument ... #--------------------------------------------------------------------- +- my $sequence_number = shift || die "cinnamon: sequence number needed as argument\n"; #--------------------------------------------------------------------- +- # read in the full unformatted error log entry with the specified # sequence number ... #--------------------------------------------------------------------- +- open (ERROR, "/usr/bin/errpt -g -l $sequence_number |"); #------------------------------------------------------------------ # pull out the detail data from the error log entry ... #------------------------------------------------------------------ my %message; while (<ERROR>) { if (/^el_nodeid/) { (undef, $message{host}) = split (/\s+/, $_); next }; if (/^el_resource/) { (undef, $message{drive}) = split (/\s+/, $_); next }; if (/^el_detail_data/) { (undef, $message{detail}) = split (/\s+/, $_); last }; }; close (ERROR); #------------------------------------------------------------------ # get the "Machine Type" and convert it from hex to ascii ... #------------------------------------------------------------------ substr($message{detail}, 128, 10) =~ /(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)/; $message{machine_type} = pack ("CCCCC", hex($1), hex($2), hex($3), hex +($4), hex($5)); #------------------------------------------------------------------ # get the "Model" and convert it from hex to ascii ... #------------------------------------------------------------------ substr($message{detail}, 138, 6) =~ /(\w\w)(\w\w)(\w\w)/; $message{model} = pack ("CCC", hex($1), hex($2), hex($3)); #------------------------------------------------------------------ # get the "Model and Microcode Level" and convert it from hex # to ascii ... #------------------------------------------------------------------ + substr($message{detail}, 32, 8) =~ /(\w\w)(\w\w)(\w\w)(\w\w)/; $message{mml} = pack ("CCCC", hex($1), hex($2), hex($3), hex($4)); #------------------------------------------------------------------ # get the "Message Code" and look up it's meaning ... #------------------------------------------------------------------ my %message_code = ( 3030 => "No Message", 3430 => "Operator Intervention Required", 3431 => "Device Degraded", 3432 => "Device Hardware Failure", 3433 => "Service Circuits Failed, Operations not Affected", 3535 => "Clean Device", 3537 => "Device has been cleaned", 3630 => "Bad Media, Read-Only Permitted", 3631 => "Rewrite Data if Possible", 3632 => "Read Data if Possible", 3634 => "Bad Media, Cannot Read or Write", 3732 => "Replace Cleaner Cartridge" ); $message{code} = $message_code{substr($message{detail}, 40, 4)} || "UN +KNOWN"; #------------------------------------------------------------------ # determine if we're dealing with a SIM or a MIM ... #------------------------------------------------------------------ if (substr($message{detail}, 16, 2) eq "01") { #-------------------------------------------------------------- # it's a SIM ... #-------------------------------------------------------------- $message{type} = "SIM"; #-------------------------------------------------------------- # convert the FID Severity Code into something meaningful ... #-------------------------------------------------------------- my %fid_severity_code = ( 33 => "1 -- Acute", 32 => "2 -- Serious", 31 => "3 -- Moderate", 30 => "4 -- Service" ); $message{severity} = $fid_severity_code{substr($message{detail}, 5 +2, 2)} || "UNKNOWN"; #-------------------------------------------------------------- # get the FID (FRU Identification Number), and convert it from # hex to ascii ... #-------------------------------------------------------------- substr($message{detail}, 64, 4) =~ /(\w\w)(\w\w)(\w\w)/; $message{fid} = pack ("CC", hex($1), hex($2)); #-------------------------------------------------------------- # get the "First FSC" (Fault Symptom Code), and convert it from # hex to ascii ... #-------------------------------------------------------------- substr($message{detail}, 68, 8) =~ /(\w\w)(\w\w)(\w\w)(\w\w)/; $message{first_fsc} = pack ("CCCC", hex($1), hex($2), hex($3), hex +($4)); #-------------------------------------------------------------- # get the "Last FSC" (Fault Symptom Code), and convert it from # hex to ascii ... #-------------------------------------------------------------- substr($message{detail}, 76, 8) =~ /(\w\w)(\w\w)(\w\w)(\w\w)/; $message{last_fsc} = pack ("CCCC", hex($1), hex($2), hex($3), hex( +$4)); } else { #-------------------------------------------------------------- # it's a MIM ... #-------------------------------------------------------------- $message{type} = "MIM"; #-------------------------------------------------------------- # convert the MIM Severity Code into something meaningful ... #-------------------------------------------------------------- my %mim_severity_code = ( 31 => "3 -- Moderate: high temporary read or write e +rrors have occurred", 32 => "2 -- Serious: permanent read or write errors + have occurred", 33 => "1 -- Acute: tape directory errors have occurr +ed" ); $message{severity} = $mim_severity_code{substr($message{detail}, 5 +2, 2)} || "UNKNOWN"; #-------------------------------------------------------------- # get the VOLSER (Volume Serial Number), and convert it from # hex to ascii ... #-------------------------------------------------------------- substr($message{detail}, 68, 12) =~ /(\w\w)(\w\w)(\w\w)(\w\w)(\w\w +)(\w\w)/; $message{volser} = pack ("CCCCCC", hex($1), hex($2), hex($3), hex( +$4), hex($5), hex($6)); }; #------------------------------------------------------------------ # format the data and store it in the array @mail ... #------------------------------------------------------------------ my @mail; push (@mail, sprintf("Subject: %s posted by %s: %s\n", $message{type} +, $message{drive}, $message{code})); push (@mail, sprintf("%-16s: %-20s\n", "Sequence Number", $sequence_nu +mber)); push (@mail, sprintf("%-16s: %-20s\n", "Host", $message{hos +t})); push (@mail, sprintf("%-16s: %-20s\n", "Drive", $message{dri +ve})); push (@mail, sprintf("%-16s: %-20s\n", "Model", $message{mod +el})); push (@mail, sprintf("%-16s: %-20s\n", "Microcode", $message{mml +})); push (@mail, sprintf("%-16s: %-20s\n", "Message Type", $message{typ +e})); push (@mail, sprintf("%-16s: %-20s\n", "Message Code", $message{cod +e})); push (@mail, sprintf("%-16s: %-20s\n", "Severity", $message{sev +erity})); if ($message{type} eq "SIM") { push (@mail, sprintf("%-16s: %-20s\n", "First FSC", $message{fir +st_fsc})); push (@mail, sprintf("%-16s: %-20s\n", "Last FSC", $message{las +t_fsc})); } else { push (@mail, sprintf("%-16s: %-20s\n", "VOLSER", $message{vo +lser})); }; push (@mail, "\n\nRaw Sense Data:\n$message{detail}\n" . "-" x 72 . "\ +n\n"); #------------------------------------------------------------------ # open a pipe to sendmail and sent the message ... #------------------------------------------------------------------ open (SENDMAIL, "|/usr/sbin/sendmail $recipient") or die "cinnamon: couldn't open sendmail: $!"; print SENDMAIL @mail; close (SENDMAIL); exit 0; #--------------------------------------------------------------------- +- # documentation #--------------------------------------------------------------------- +- =pod =head1 NAME cinnamon -- translates the sense data from SIM and MIM messages posted by IBM 3590 tape drives to the AIX error log into human- readable format, and sends the messages via email. =head1 DESCRIPTION B<cinnamon> (so named because I thought it sounded like "sim-mim- mon", which was my original name for the program) parses and mails AIX error log entries posted with the identifier B<D1A1AE6F>, which is + the ERROR ID for B<SIM_MIM_RECORD_3590>. SIM and MIM records are part of the "Statistical Analysis and Reportin +g System" (SARS), and are messages created by IBM 3590 tape drives that report on the condition of the drive (a SIM) or of the medium (a MIM) +. These records are presented by the operating system in different ways. In AIX, they are recorded in the error log, but in a difficult-to-re +ad format. This script breaks down the sense data where the information is stored +, parses it into a human-understandable format, and mails it to root. =head1 SETUP/USAGE If the user wants emails sent by this program to be sent to any other address than B<root>, the variable B<$recipient> should be changed (about line number 26) to that address (or those addresses, comma- separated but all contained within double-quotes, with any "@" signs back-slashed. Additionally, this program is meant to be used as B<errnotify method>, added to the ODM, so that B<cinnamon> will be invoked each time an error log entry that matches the descriptor values of a 3590 SIM or MI +M message. To create the B<errnotify method>, save the following text to the file + B</tmp/cinnamon.add>: errnotify: en_name = "cinnamon" en_persistenceflg = 1 en_label = "SIM_MIM_RECORD_3590" en_class = "H" en_type = "INFO" en_method = "/usr/local/bin/perl /usr/local/sbin/cinnamon $1" (Note: use the proper paths to your perl executible and to this progra +m in the above "en_method" line.) After saving the above text to a file, run the command: odmadd /tmp/cinnamon.add The error notification object will be added to the ODM. To verify tha +t the object was added to the ODM properly, run the command: odmget -q"en_name='cinnamon'" errnotify To remove the object from the ODM (why would you want to do that?), run the command: odmdelete -q"en_name='cinnamon'" -o errnotify =head1 AUTHOR Sandor W. Sklar Unix Systems Administrator Stanford University ITSS mailto:ssklar@stanford.edu http://whippet.stanford.edu/~ssklar/ If this script is useful to you, or even if it is useless to you, or +you have some changes/improvements/questions/large sums of cash and nothing to do with it, please send me an email. =head1 FOR MORE INFORMATION Most of the things that this script does were taken from the IBM publication "Statistical Analysis and Reporting System User Guide", wh +ich can be downloaded from <http://www.storage.ibm.com/hardsoft/tape/pubs +/pubs3590.html>. Information about creating custom error notification objects can be found in Chapter 4 of the IBM manual "General Programming Concepts: Writing and Debugging Programs", available online at < http://www.rs6000.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/genprogc +/error_notice.htm> =head1 COPYRIGHT This program is free software; you may redistribute it and/or modify i +t under the same terms as Perl itself. =cut #--------------------------------------------------------------------- +- # version history #--------------------------------------------------------------------- +- # $Log: cinnamon,v $ # Revision 1.1 2001/08/21 04:48:51 ssklar # Initial revision #
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: how can this be improved?
by mugwumpjism (Hermit) on Aug 21, 2001 at 12:27 UTC | |
by blueflashlight (Pilgrim) on Aug 21, 2001 at 21:55 UTC | |
Re: how can this be improved?
by Hofmator (Curate) on Aug 21, 2001 at 13:39 UTC | |
by busunsl (Vicar) on Aug 21, 2001 at 14:17 UTC | |
by dragonchild (Archbishop) on Aug 21, 2001 at 16:08 UTC | |
by blueflashlight (Pilgrim) on Aug 21, 2001 at 22:03 UTC | |
by blueflashlight (Pilgrim) on Aug 21, 2001 at 22:01 UTC | |
Re: how can this be improved?
by maverick (Curate) on Aug 21, 2001 at 17:43 UTC | |
by blueflashlight (Pilgrim) on Aug 21, 2001 at 22:04 UTC | |
Re: how can this be improved?
by japhy (Canon) on Aug 21, 2001 at 17:50 UTC | |
by blueflashlight (Pilgrim) on Aug 21, 2001 at 22:08 UTC | |
Re: how can this be improved?
by blueflashlight (Pilgrim) on Aug 23, 2001 at 04:52 UTC |