Welcome to Aaron Thompson's Page Monday, April 21 2014 @ 00:47 CDT  
Personal
Contact Info
Family
Resume
 
Development
CGI
probability project
 
Perl Modules
Win32::AD::User (cpan)
 
Shell
backup_file (source)
chkconfig (source)
gen-autohome (source)
group-utils (source)
mail-deny (source)
mail-logs (source | archive)
mailman-qmail (source)
qmail vacation (source)
 
Links
Beast of Burden LLC
Central Iowa LUG
CedarLUG
CedarvalleyPM
ITS-IS Home
ITS Home
UNI Home
 
 
#!/usr/bin/perl -w
  #mail-logs.pl v0.5
  # 
  # This script requires the use of Net:SMTP, and Time::Local that can 
  # be gotten from CPAN if needed. To check if you have these, in a shell,
  # run:
  #
  #  perl -e '{use Net::SMTP;use Time::Local;}'
  #
  # If you don't get an error you have both modules installed.
  #
  #
  # Copyright (C) 2001, 2002, 2003, 2004 Aaron Thompson 
  #  thompson@cns.uni.edu
  #
  # This program is free software; you can redistribute it and/or
  # modify it under the terms of the GNU General Public License
  # as published by the Free Software Foundation; either version 2
  # of the License, or (at your option) any later version.
  #
  # This program is distributed in the hope that it will be useful,
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  # GNU General Public License for more details. 
  #
  # You should have received a copy of the GNU General Public License
  # along with this program; if not, write to the Free Software
  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  # or visit http://www.gnu.org/copyleft/gpl.html
  #
  # Written to send a days log files in an email via SMTP. This was written to
  # be used with a daily cron that runs ~12:00.
  # 
  #
  # Changes Between Versions... (CHANGELOG)
  # =======================================
  # v0.1
  # ____________
  # first working version.
  # -> mailed Syslog logfiles.
  #
  # v0.2
  # ____________
  # -> added file names deviders to email
  # -> added support for previous days SMB logs
  # -> added support for previous days Bru logs
  #
  # v0.3
  # ____________
  # -> added support for previous and current days aide files.
  # -> added/fixed zcat support for compressed logs.
  #
  # v0.4
  # ____________
  # -> fixed call to date commands to properly get 'yesterday' (instead of using hack).
  # -> cleaned up &mailAide
  #
  # v0.5
  # -----------
  # -> wrote get_date function the will return a date in the proper format...
  #     get_date(format,n) format is defined in the coments for the sub, and n
  #     is the number of days before 'today'.
  #
  # -> defined file format for web logs.
  #
  # -> fixed so no email is sent for empty log data
  #
  # -> fixed mail_samba_logs
  #
  # -> added support for wtmp.
  #
  ######################################################################
  use strict;
  use Net::SMTP;
  use Time::Local;

  #verbose = 1 will print more info verbose = 0 will not.
  my $verbose = 1; 

  # Hostname stuph - this is the hostname the script is running on...
  # Usually you can get this with 'hostname -f'.
   my $hostname = "host.domain"; 
  
  # The current year (use by mail_samba_logs, get_date)
  # Currently this gets set again via localtime when get_date is called.
   my $global_year = "2003"; 

  # The last command, including path and option to take a file for input. 
  #   (used by mail_wtmp_logs).
   my $last_command = "/usr/bin/last -af";

  #initialize 'list' of logfiles.
  # Each entry in the hash should have the base file name as the key and a 
  # format as understood by get_date. If you add a format that is not defined 
  # in get_date you will need to define an entry in the 'OPTION' block.
   my %log_files = ("/var/log/messages"               =>  "std",
                    "/var/log/syslog"                 =>  "std",
                    "/var/log/boot"                   =>  "std",
                    "/var/log/daemon.log"             =>  "std",
                    "/var/log/debug"                  =>  "std",
                    "/var/log/kern.log"               =>  "std",
                    "/var/log/mail"                   =>  "std",
                    "/var/log/vsfpd.log"              =>  "std",
                    "/var/log/user.log"               =>  "std",
                    "/var/log/setuid"                 =>  "std",
                    "/var/log/uucp"                   =>  "std",
                    "/var/log/apache/access.log"      =>  "apache",
                    "/var/log/apache/error.log"       =>  "apache-error",
                    "/var/log/apache-ssl/access.log"  =>  "apache",
                    "/var/log/apache-ssl/error.log"   =>  "apache-error",
                    "/var/log/bruexeclog"             =>  "bru",
                    "/var/log/samba/log."             =>  "smb",
                    "/var/log/wtmp"                   =>  "wtmp");

  #mail defaults
   my $server     = "smtpserver.domain";      #default smtp server
   my $mail_to    = "someone\@somewhere";     #default email reciever
   my $mail_from  = "mail-logs\@$hostname";   #default email sender

   &mail_logs;

   exit(0);

######################################################################
sub mail_logs{
  my ($file_base, $file, $yesterday, $result, $count);
  
  for $file_base (keys(%log_files)){
    $yesterday = get_date($log_files{$file_base},1); 
    $result = "";
    print "processing $file_base ...\n" if($verbose);
    if ($log_files{$file_base} eq "smb"){
      $result = mail_samba_logs($file_base);
    }
    elsif($log_files{$file_base} eq "wtmp"){
      $result = mail_wtmp_logs($file_base);
    }
    else{
      for $file (<$file_base*>){
        print "  processing $file ..." if($verbose);
        if($file =~ /gz/){
        open (IN,"/bin/gunzip -c $file|") or die "Could not open $file for reading!\n";
            @_=<IN>;
          close(IN);
          $count = grep /$yesterday/, @_;
          if ($count > 0){ 
            $result .= "$file\n##################################################\n";
            $result .= $_ for (grep /$yesterday/, @_);
          }#fi
        }
        else{
          open (IN,"$file") or die "Could not open $file for reading!\n";
            @_=<IN>;
          close(IN);
          $count = grep /$yesterday/, @_;
          if ($count > 0){ 
            $result .= "$file\n##################################################\n";
          $result .= $_ for (grep /$yesterday/, @_);
          }#fi
        }#fi
        print " done.\n" if($verbose);
      }#rof
    }#fi

    if ($result){
      print "  sending email for $file_base ... " if($verbose);
      my $subject = "$file_base ($hostname).";
      send_mail($mail_to,$mail_from,$subject,$result);
      print "done.\n" if($verbose);
    }#fi
    print "done with $file_base.\n" if($verbose);
  }#rof
}

######################################################################
sub send_mail{
  #$smtp info found:
  #http://faqchest.dynhost.com/prgm/perlu-l/perl-00/perl-0010/perl-001005/perl00103111_16616.html
  # creditted to the Perl Cookbook by O'Reilly
  my ($mail_to,$mail_from,$subject,$message) = @_;
	
   my $smtp = Net::SMTP->new($server);
   $smtp->mail($ENV{USER});
   $smtp->to($mail_to);
   $smtp->data();
   $smtp->datasend("To: $mail_to\n");
   $smtp->datasend("From: $mail_from\n");
   $smtp->datasend("Subject: $subject\n");
   $smtp->datasend("\n");
   $smtp->datasend($message);
   $smtp->dataend();
   $smtp->quit;
}

######################################################################
sub get_date{
 # format: std,apache,apache-error,bru
 # day: null==today, number is the days that should be subtracted from today
 #
 # n days ago inspiration.. 
 #   http://www.experts-exchange.com/Programming/Programming_Platforms/Unix_Programming/Q_20812482.html
 # 
  my ($format,$day) = @_;
  if(! defined($day)){$day=0;}


  my @month_short = ("Jan","Feb","Mar","Apr","May","Jun",
                     "Jul","Aug","Sep","Oct","Nov","Dec");
  my ($sec,$min,$hours,$mday,$mon,$year);
  if ($day<0){
    ($sec,$min,$hours,$mday,$mon,$year) = localtime((timelocal(localtime)+(abs($day)*86400)));
  }
  else{
    ($sec,$min,$hours,$mday,$mon,$year) = localtime((timelocal(localtime)-($day*86400)));
  }#fi

  ## Set the global year.
  $global_year = ($year+1900);

  my $value;
  OPTION: {
    if($format eq "std"){ $value = "$month_short[$mon]" . " ";
                          $value .= " " if ($mday < 10);
                          $value .= "$mday";
                          last OPTION;
                        }#fi
    
    if($format eq "apache") { ($mday < 10) ? $value = "0" : $value = "";
                              $value .= "$mday/$month_short[$mon]/". $global_year;
                              last OPTION;
                            }#fi
    if($format eq "apache-error") { $value = get_date("std",$day);
                                    last OPTION;
                                  }#fi
    if($format eq "bru")  { $value = $global_year . ($mon+1);
                            ($mday < 10) ? $value .= "0$mday" : $value .= "$mday";
                            last OPTION;
                          }#fi
    if($format eq "smb")  { $value = $global_year."/".($mon+1)."/$mday";
                            last OPTION;
                          }#fi
    if($format eq "wtmp") { $value = "$month_short[$mon]" . " ";
                            $value .= " " if ($mday < 10);
                            $value .= "$mday";
                            last OPTION;
                          }#fi

  }#:NOITPO
$value;
}

######################################################################
sub mail_samba_logs{
  my ($file_base) = @_;
  my $yesterday = get_date("smb",2);
  my ($result, $keep_flag,$count);

  for my $file (<$file_base*>){

    print "  processing $file ..." if($verbose);
    if($file =~ /gz/){
    open (IN,"/bin/gunzip -c $file|") or die "Could not open $file for reading!\n";
        @_=<IN>;
      close(IN);
      $count = grep /$yesterday/, @_;
      if ($count > 0){
        $result .= "\n$file\n##################################################\n";
        $keep_flag = 0 ;
        for my $line (@_){
          if ($line =~ /$yesterday/){$result.= $line; $keep_flag=1;}
          else{
            if(($keep_flag > 0) and ($line =~ /^\[$global_year/)){$keep_flag=0;}
            else{$result .= $line;}
          }#fi
        }#rof
      }#fi
    }
    else{
      open (IN,"$file") or die "Could not open $file for reading!\n";
        @_=<IN>;
      close(IN);
      $count = grep /$yesterday/, @_;
      if ($count > 0){
        $result .= "\n$file\n##################################################\n";
        $keep_flag = 0 ;
        for my $line (@_){
          if ($line =~ /$yesterday/){$result.= $line; $keep_flag=1;}
          else{
            if(($keep_flag > 0) and ($line =~ /^\[$global_year/)){$keep_flag=0;}
            else{$result .= $line;}
          }#fi
        }#rof
      }#fi
    }#fi
    print " done.\n" if($verbose);

  }#rof
$result;
}

######################################################################
sub mail_wtmp_logs{
  my ($file_base) = @_;
  my $yesterday = get_date("wtmp",1);
  my ($count,$result);
  for my $file (<$file_base*>){

    print "  processing $file ..." if($verbose);
    open(IN, "$last_command $file|") or die "Could not open $file with $last_command !\n";
      @_=<IN>;
    close(IN);
    $count = grep /$yesterday/, @_;
    if($count > 0){
      $result .= "\n$file\n##################################################\n";
      $result .= $_ for (grep /$yesterday/, @_);
    }#fi

    print " done.\n" if($verbose);

  }#rof
$result;
}


syntax highlighted by Code2HTML, v. 0.9.1
Return to mail-logs page