脚本功能:

脚本使用Perl来实现,读取/var/log/messages(也可以是其他日志文件)日志文件,从里面找出error或者warn的行,然后发送邮件。

第一次读取的时候,会记录读取的位置,下次读取的时候会从上次读取的位置的开始读取,如果没有发现error或warn行,则不发邮件

脚本使用说明:

1.需要的Perl模块
Net::SMTP               //perl自带,不用安装
Socket                    //perl自带,不用安装
Sys::Hostname     //perl自带,不用安装
Authen::SASL (用使来验证邮件用户名和密码) //需要安装
使用root身份用如下命令来安装Authen::SASL模块:
 
       
  1. root@server ~]# cpan Authen::SASL 
  2.  If you do not want to enter a dialog now, you can answer 'no' to this 
  3.  question and I'll try to autoconfigure. (Note: you can revisit this 
  4.  dialog anytime later by typing 'o conf init' at the cpan prompt.) 
  5.   
  6.  Are you ready for manual configuration? [yes] no   //如果有该步骤的话,选择no,自动配置 
  7.   
  8.  中间省略。。。 
  9.  Checking if your kit is complete... 
  10.  Looks good 
  11.  Warning: prerequisite Digest::HMAC_MD5 0 not found. 
  12.  Warning: prerequisite ExtUtils::MakeMaker 6.42 not found. We have 6.30. 
  13.  Writing Makefile for Authen::SASL 
  14.  ---- Unsatisfied dependencies detected during [G/GB/GBARR/Authen-SASL-2.15.tar.gz] ----- 
  15.      Digest::HMAC_MD5 
  16.      ExtUtils::MakeMaker 
  17.  Shall I follow them and prepend them to the queue 
  18.  of modules we are processing right now? [yes] yes  
  19.   
  20.  Running make install 
  21.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL.pm 
  22.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL.pod 
  23.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl.pm 
  24.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl.pod 
  25.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/EXTERNAL.pm 
  26.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/CRAM_MD5.pm 
  27.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/DIGEST_MD5.pm 
  28.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/PLAIN.pm 
  29.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/ANONYMOUS.pm 
  30.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/LOGIN.pm 
  31.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/GSSAPI.pm 
  32.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/EXTERNAL.pm 
  33.  Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/CRAM_MD5.pm 
  34.  Installing /usr/share/man/man3/Authen::SASL::Perl.3pm 
  35.  Installing /usr/share/man/man3/Authen::SASL::Perl::LOGIN.3pm 
  36.  Installing /usr/share/man/man3/Authen::SASL::Perl::CRAM_MD5.3pm 
  37.  Installing /usr/share/man/man3/Authen::SASL::Perl::ANONYMOUS.3pm 
  38.  Installing /usr/share/man/man3/Authen::SASL.3pm 
  39.  Installing /usr/share/man/man3/Authen::SASL::Perl::EXTERNAL.3pm 
  40.  Installing /usr/share/man/man3/Authen::SASL::Perl::GSSAPI.3pm 
  41.  Installing /usr/share/man/man3/Authen::SASL::Perl::PLAIN.3pm 
  42.  Installing /usr/share/man/man3/Authen::SASL::Perl::DIGEST_MD5.3pm 
  43.  Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod 
  44.    /usr/bin/make install  -- OK    看到这里就表示安装完成。 
  45.   
  46.  
 
测试模块是否安装:
 
       
  1. [root@server1 ~]# perl -e "use Authen::SASL"      

  2.  [root@server1 ~]#           //什么也不显示表明模块已经正确安装了。 

  3.  [root@server1 ~]# perl -e "use Net::SMTP"     

  4.  [root@server1 ~]# 

  5.   [root@server1 ~]# perl -e "use Socket"     

  6.  [root@server1 ~]# 

  7.   [root@server1 ~]# perl -e "use Sys::Hostname"       

  8.  [root@server1 ~]#  

2.需要ROOT身份运行该脚本,如果读取的是 /var/log/messages这个日志文件
3.可以设置为计划任务,自定义运行时间,如:每30分钟运行一次
4.服务器需联网才能发送邮件
5.如果有防火墙请放开25端口:
 
       
  1. iptables -A INPUT -p tcp --sport 25 -j ACCEPT   
  2. iptables -A OUPUT  -p tcp --dport 25 -j ACCEPT   
6.一些测试数据 测试数据请下载附件 测试的时候第一次测试会创建/var/log/last_messages.linenumber文件, 第二次测试的时候 需要把该文件清空,或者在/var/log/messages增加一些错误的行,这样才可以测试出效果
7.有什么不对的地方请留言或者发送邮件(chanyipiaomiao@163.com) 8.发送邮件效果如下:


脚本内容如下:

【第二版】
 
       
  1. #!/usr/bin/perl  
  2.  use Net::SMTP; 
  3.  use Authen::SASL; 
  4.  use Socket; 
  5.  require 'sys/ioctl.ph'; 
  6.   
  7.  #日期:2012-09-15_17:25:48 Author:Leo Email:chanyipiaomiao@163.com 
  8.  #测试平台:CentOS 6.0, CentOS 5.6,Red Hat Enterprise Linux AS release 4 
  9.   
  10.  #要读取的日志文件 
  11.  my $logfile ="/var/log/messages"
  12.  my $countfile ="/var/log/last_messages.size"
  13.   
  14.  #发送邮件设置 
  15.  my $smtp_host = 'smtp.163.com'
  16.  my $from = 'bookfm_2knowledgeq@163.com'
  17.  my $password = '123456'
  18.  my $to = 'chanyipiaomiao@163.com'
  19.   
  20.  #定义邮件主题中显示的那个接口的IP地址,默认是eth0 
  21.  my $interface = "eth0"
  22.   
  23.  #定义正则表达式  
  24.  my $pattern = "(?:error|warn)"
  25.   
  26.  #定义邮件主题 
  27.  my $subject = "Error Log"
  28.   
  29.  #读取上一次日志文件的大小 
  30.  my $last_size; 
  31.  if (-z $countfile){ 
  32.     $last_size = 0
  33.  } 
  34.  elsif (! -e $countfile ){ 
  35.     warn "[warning]Can't read \"$countfile\",the file does't exists!\n"; 
  36.     $last_size = 0
  37.  } 
  38.  else { 
  39.     open COUNTFILEREAD , "<", $countfile or die "Can't read \"$countfile\" : $! "; 
  40.     chomp($last_size = <COUNTFILEREAD>); 
  41.     close COUNTFILEREAD; 
  42.  } 
  43.      
  44.  #写入这次日志文件的大小 到  /var/log/last_messages.size 
  45.  open COUNTFILEWRITE, ">", $countfile or die "can't write $countfile : $!"; 
  46.  my $this_size = -s $logfile; 
  47.  print COUNTFILEWRITE $this_size ,"\n"; 
  48.  close COUNTFILEWRITE; 
  49.   
  50.  #读取IP地址 
  51.  sub getIP() { 
  52.      my $packpack = pack("a*", shift); 
  53.      my $socket; 
  54.      socket($socket, AF_INET, SOCK_DGRAM, 0); 
  55.      ioctl($socket, SIOCGIFADDR(), $pack); 
  56.      $ipaddr = inet_ntoa(substr($pack,20,4)); 
  57.  } 
  58.   
  59.  #得到日期 
  60.  sub getDate { 
  61.        my ($sec, $min, $hour, $mday, $mon, $year) = (localtime)[0 ..5]; 
  62.        my $date = sprintf "%4d-%02d-%02d %2d:%02d:%02d" ,$year + 1900,$mon + 1 ,$mday ,$hour ,$min ,$sec; 
  63.  } 
  64.   
  65.  #发送邮件函数 
  66.  sub SendMail { 
  67.     my $date = &getDate; 
  68.     my $ipaddr = &getIP($interface); 
  69.     my $subjects = "$subject\@${ipaddr} Time:$date\n"
  70.     my $smtp = Net::SMTP->new($smtp_host); 
  71.     $smtp->auth($from,$password) || print "Email user or password Auth Error!\n"; 
  72.     $smtp->mail($from); 
  73.     $smtp->to($to); 
  74.     $smtp->data(); 
  75.     $smtp->datasend("Subject:$subjects\n"); 
  76.     $smtp->datasend("\n"); 
  77.     $smtp->datasend("@_\n\n"); 
  78.     $smtp->dataend(); 
  79.     $smtp->quit; 
  80.  } 
  81.   
  82.  #读取日志函数,并找出其中到错误行或者警告行 
  83.  open MESSAGESLOG , "<", "$logfile" or die "Can't read $logfile : $!"; 
  84.  if ($last_size < $this_size){ 
  85.     seek(MESSAGESLOG,$last_size,0) || die "$!\n"; #主要语句 
  86.     my @errorarray; 
  87.     while(<MESSAGESLOG>){ 
  88.         push @errorarray,$_ if (/$pattern/i); 
  89.     } 
  90.     &SendMail(@errorarray) if (@errorarray.length != 0 ); 
  91.  } 
  92.  close MESSAGESLOG; 
  93.   
【第一版】
请注意修改邮件的信息
 
       
  1. #!/usr/bin/perl  
  2.  use Net::SMTP; 
  3.  use Authen::SASL; 
  4.  use Socket; 
  5.  use Sys::Hostname; 
  6.  require 'sys/ioctl.ph'; 
  7.   
  8.  #DATE:2012-08-25_18:28:47 Author:Leo Email:chanyipiaomiao@163.com 
  9.  #Test Platform:CentOS 6.0, CentOS 5.6,Red Hat Enterprise Linux AS release 4 
  10.   
  11.  #Log file setting 
  12.  my $logfile ="/var/log/messages"
  13.  my $countfile ="/var/log/last_messages.linenumber"
  14.   
  15.  #Email Setting 
  16. #注意修改这里面的邮件信息
  17.  my $smtp_host = 'smtp.163.com'
  18.  my $from = 'bookfm_2knowledgeq@163.com'
  19.  my $password = '123456'
  20.  my $to = 'chanyipiaomiao@163.com'
  21.   
  22.  #custom display email subject network interface address, default eth0 
  23. #发送邮件的时候,邮件的主题里面显示的那个接口的IP地址,默认是eth0 
  24.  my $interface = "eth0"
  25.   
  26.  #custom regular expression  
  27.  #如果不想看到warn的行,那么就把该表达式修改为"error"
  28.  my $pattern = "(?:error|warn)"
  29.   
  30.  #custom email subject 
  31.  my $subject = "Error Log"
  32.   
  33.  #read messages log file 
  34.  open MESSAGESLOG , "<", "$logfile" or die "Can't read $logfile : $!"; 
  35.  my @logarray = <MESSAGESLOG>
  36.  close MESSAGESLOG; 
  37.   
  38.  #read last messages logfile linenumber 
  39.  my $last_linenumber; 
  40.  if (-z $countfile){ 
  41.     $last_linenumber = 0
  42.  } 
  43.  elsif (! -e $countfile ){ 
  44.     warn "[warning]Can't read \"$countfile\",the file does't exists!\n"; 
  45.     $last_linenumber = 0
  46.  } 
  47.  else { 
  48.     open COUNTFILEREAD , "<", $countfile or die "Can't read \"$countfile\" : $! "; 
  49.     chomp($last_linenumber = <COUNTFILEREAD>); 
  50.     close COUNTFILEREAD; 
  51.  } 
  52.      
  53.  #wirte this_linenumber to  /tmp/last_messages.linenumber 
  54.  open COUNTFILEWRITE, ">", $countfile or die "can't write $countfile : $!"; 
  55.  my $this_linenumber = @logarray ; 
  56.  print COUNTFILEWRITE $this_linenumber ,"\n"; 
  57.  close COUNTFILEWRITE; 
  58.   
  59.  #get ip address 
  60.  sub getIP() { 
  61.      my $packpack = pack("a*", shift); 
  62.      my $socket; 
  63.      socket($socket, AF_INET, SOCK_DGRAM, 0); 
  64.      ioctl($socket, SIOCGIFADDR(), $pack); 
  65.      $ipaddr = inet_ntoa(substr($pack,20,4)); 
  66.  }; 
  67.   
  68.  #get date 
  69.  sub getDate { 
  70.        my ($sec, $min, $hour, $mday, $mon, $year) = (localtime)[0 ..5]; 
  71.        my $date = sprintf "%4d-%02d-%02d %2d:%02d:%02d" ,$year + 1900,$mon + 1 ,$mday ,$hour ,$min ,$sec; 
  72.  } 
  73.   
  74.  #send mail function 
  75.  sub SendMail { 
  76.     my $date = &getDate; 
  77.     my $ipaddr = &getIP($interface); 
  78.     my $subjects = "$subject\@${ipaddr} Time:$date\n"
  79.     my $smtp = Net::SMTP->new($smtp_host); 
  80.     $smtp->auth($from,$password) || print "Email user or password Auth Error!\n"; 
  81.     $smtp->mail($from); 
  82.     $smtp->to($to); 
  83.     $smtp->data(); 
  84.     $smtp->datasend("Subject:$subjects\n"); 
  85.     $smtp->datasend("\n"); 
  86.     $smtp->datasend("@_\n\n"); 
  87.     $smtp->dataend(); 
  88.     $smtp->quit; 
  89.  } 
  90.   
  91.  #find error or warn line 
  92.  my @errorarray; 
  93.  if ($last_linenumber < $this_linenumber){ 
  94.        for (my $i = $last_linenumber; $i < $this_linenumber; $i++){ 
  95.             if ($logarray[$i] =~ /$pattern/i ){ 
  96.                 push @errorarray ,$logarray[$i]; 
  97.            } 
  98.       } 
  99.       &SendMail(@errorarray) unless (0 == @errorarray.length); 
  100.  } 
  101.