#!/usr/bin/perl ## ## coredump-report : scans the AIX error log for notifications of ## abnormally terminated programs, and displays or mails a summary. ## ## $Id: coredump-report,v 1.2 2005/04/01 21:19:20 ssklar Exp ssklar $ ## use strict; use File::stat; use Getopt::Long; sub print_usage { print "\nUsage: $0 [--hours NN] [--email you\@wherever,someone\@else.com,...]\n\n"; print " --hours specifies the number of hours to go back for the report.\n"; print " (i.e., '--hours 24' will process one day of errlog entries.)\n"; print " If not specified, the entire errlog will be processed.\n\n"; print " --email specifies the address(es) to which the the output of the\n"; print " script will be emailed to. Separate multiple addresses with\n"; print " commas. If not specified, the report will be written to STDOUT.\n"; print "\n\n"; exit 1 }; ## parse the options ... my ($hours, $email) = ''; GetOptions ( 'hours=i' => \$hours , 'email=s' => \$email , 'usage|?' => sub { &print_usage } ); my $errpt = "/usr/bin/errpt -a -j B6048838,45C7A35B"; ## if a number of hours was provided, we'll specify a start and end ## time to the errpt command. Otherwise, we'll process the whole errlog. if ($hours) { my $now = time; my $then = $now - $hours * 60 * 60; my $start = sprintf '%02d%02d%02d%02d%02d', sub { $_[4]+1, $_[3], $_[2], $_[1], $_[5] % 100 } -> (localtime($then)); my $end = sprintf '%02d%02d%02d%02d%02d', sub { $_[4]+1, $_[3], $_[2], $_[1], $_[5] % 100 } -> (localtime($now)); $errpt = $errpt . " -s $start -e $end"; }; ## read in the errpt output in one big chunk, and put the individual ## errpt records into the array @records ... open (ERRPT, "$errpt |") || die "couldn't run errpt command: $!"; my @records; { local $/ = undef; @records = split(/LABEL:/, ); }; close ERRPT; if (scalar (@records) > 1) { shift @records } else { exit 0 }; my ($when, $seqnum, $cfile, $prog, $user, @output); push (@output, sprintf " %-18s%-7s%-12s%-12s%-s\n", "DATE/TIME", "SEQNO", "USER", "PROGRAM", "CORE FILE"); push (@output, "=" x 80 . "\n"); foreach (@records) { chomp; if ($_ =~ /Date\/Time:\s+...\s(...\s.\d\s\d\d:\d\d:\d\d).*/) { $when = $1 }; if ($_ =~ /Sequence Number:\s+(.*)\n/) { $seqnum = $1 }; if ($_ =~ /CORE FILE NAME.(.*?)\n/s) { $cfile = $1 }; if ($_ =~ /PROGRAM NAME.(.*?)\n/s) { $prog = $1 }; if ($_ =~ /USER ID.\s+(\d+?)\n/s) { $user = getpwuid ($1) || "(UID $1)"}; if (! defined ($user) && defined ($cfile)) { my $st = stat ($cfile) || do { $user = "(?)" }; unless ($user) { $user = getpwuid ($st->uid) || $st->uid }; }; unless (($cfile) && ($seqnum)) { $cfile = "--" }; push (@output, sprintf " %-18s%-7s%-12s%-12s%-s\n", $when, $seqnum, $user, $prog, $cfile); }; ## if email is not defined, print the output to STDOUT ... unless (defined $email) { foreach (@output) { print }; exit 0 }; ## otherwise, send the report by email ... chomp (my $host = `/usr/bin/hostname`); my $subject; if (defined $hours) { $subject = "Core dump report for the past $hours hours ($host)\n" } else { $subject = "Core dump report ($host)\n"; }; open (SENDMAIL, "| /usr/sbin/sendmail $email") || die "couldn't open sendmail: $!"; print SENDMAIL ("Subject: $subject\n"); foreach (@output) { print SENDMAIL ("$_") }; print SENDMAIL ".\n"; close SENDMAIL; exit 0