hi, monks ...

In the never-ending quest to become a less lame writer of perl programs (hoping to someday be able to proudly have a JAPH sig), I would appreciate any and all comments on this script, which I am posting below.

This program works fine (but is only useful on AIX, which incidently, is NOT being canned in favor of Linux, contrary to postings on various sites, including those who use only non-alphanumeric characters in their names (but I digress))

However, I'm sure that some of ways that I'm doing things are awkward, inefficient, or just plain dumb. I hope that y'all would like to help me be less awkward, inefficient, and dumb.

thanks, and try to be gentle (well, not *too* gentle, but I don't think I have to worry about that. :-)

-blueflashlight

#!/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 #

In reply to how can this be improved? by blueflashlight

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.