脚本功能:
脚本使用Perl来实现,读取/var/log/messages(也可以是其他日志文件)日志文件,从里面找出error或者warn的行,然后发送邮件。
第一次读取的时候,会记录读取的位置,下次读取的时候会从上次读取的位置的开始读取,如果没有发现error或warn行,则不发邮件
脚本使用说明:
1.需要的Perl模块
Net::SMTP //perl自带,不用安装
Socket //perl自带,不用安装
Sys::Hostname //perl自带,不用安装
Authen::SASL (用使来验证邮件用户名和密码) //需要安装
使用root身份用如下命令来安装Authen::SASL模块:
- root@server ~]# cpan Authen::SASL
- If you do not want to enter a dialog now, you can answer 'no' to this
- question and I'll try to autoconfigure. (Note: you can revisit this
- dialog anytime later by typing 'o conf init' at the cpan prompt.)
- Are you ready for manual configuration? [yes] no //如果有该步骤的话,选择no,自动配置
- 中间省略。。。
- Checking if your kit is complete...
- Looks good
- Warning: prerequisite Digest::HMAC_MD5 0 not found.
- Warning: prerequisite ExtUtils::MakeMaker 6.42 not found. We have 6.30.
- Writing Makefile for Authen::SASL
- ---- Unsatisfied dependencies detected during [G/GB/GBARR/Authen-SASL-2.15.tar.gz] -----
- Digest::HMAC_MD5
- ExtUtils::MakeMaker
- Shall I follow them and prepend them to the queue
- of modules we are processing right now? [yes] yes
- Running make install
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL.pod
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl.pod
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/EXTERNAL.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/CRAM_MD5.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/DIGEST_MD5.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/PLAIN.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/ANONYMOUS.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/LOGIN.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/GSSAPI.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/EXTERNAL.pm
- Installing /usr/lib/perl5/site_perl/5.8.8/Authen/SASL/Perl/CRAM_MD5.pm
- Installing /usr/share/man/man3/Authen::SASL::Perl.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::LOGIN.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::CRAM_MD5.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::ANONYMOUS.3pm
- Installing /usr/share/man/man3/Authen::SASL.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::EXTERNAL.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::GSSAPI.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::PLAIN.3pm
- Installing /usr/share/man/man3/Authen::SASL::Perl::DIGEST_MD5.3pm
- Appending installation info to /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
- /usr/bin/make install -- OK 看到这里就表示安装完成。
测试模块是否安装:
[root@server1 ~]# perl -e "use Authen::SASL"
[root@server1 ~]# //什么也不显示表明模块已经正确安装了。
[root@server1 ~]# perl -e "use Net::SMTP"
[root@server1 ~]#
[root@server1 ~]# perl -e "use Socket"
[root@server1 ~]#
[root@server1 ~]# perl -e "use Sys::Hostname"
[root@server1 ~]#
3.可以设置为计划任务,自定义运行时间,如:每30分钟运行一次
4.服务器需联网才能发送邮件
5.如果有防火墙请放开25端口:
- iptables -A INPUT -p tcp --sport 25 -j ACCEPT
- iptables -A OUPUT -p tcp --dport 25 -j ACCEPT
7.有什么不对的地方请留言或者发送邮件(chanyipiaomiao@163.com) 8.发送邮件效果如下:
脚本内容如下:
【第二版】- #!/usr/bin/perl
- use Net::SMTP;
- use Authen::SASL;
- use Socket;
- require 'sys/ioctl.ph';
- #日期:2012-09-15_17:25:48 Author:Leo Email:chanyipiaomiao@163.com
- #测试平台:CentOS 6.0, CentOS 5.6,Red Hat Enterprise Linux AS release 4
- #要读取的日志文件
- my $logfile ="/var/log/messages";
- my $countfile ="/var/log/last_messages.size";
- #发送邮件设置
- my $smtp_host = 'smtp.163.com';
- my $from = 'bookfm_2knowledgeq@163.com';
- my $password = '123456';
- my $to = 'chanyipiaomiao@163.com';
- #定义邮件主题中显示的那个接口的IP地址,默认是eth0
- my $interface = "eth0";
- #定义正则表达式
- my $pattern = "(?:error|warn)";
- #定义邮件主题
- my $subject = "Error Log";
- #读取上一次日志文件的大小
- my $last_size;
- if (-z $countfile){
- $last_size = 0;
- }
- elsif (! -e $countfile ){
- warn "[warning]Can't read \"$countfile\",the file does't exists!\n";
- $last_size = 0;
- }
- else {
- open COUNTFILEREAD , "<", $countfile or die "Can't read \"$countfile\" : $! ";
- chomp($last_size = <COUNTFILEREAD>);
- close COUNTFILEREAD;
- }
- #写入这次日志文件的大小 到 /var/log/last_messages.size
- open COUNTFILEWRITE, ">", $countfile or die "can't write $countfile : $!";
- my $this_size = -s $logfile;
- print COUNTFILEWRITE $this_size ,"\n";
- close COUNTFILEWRITE;
- #读取IP地址
- sub getIP() {
- my $packpack = pack("a*", shift);
- my $socket;
- socket($socket, AF_INET, SOCK_DGRAM, 0);
- ioctl($socket, SIOCGIFADDR(), $pack);
- $ipaddr = inet_ntoa(substr($pack,20,4));
- }
- #得到日期
- sub getDate {
- my ($sec, $min, $hour, $mday, $mon, $year) = (localtime)[0 ..5];
- my $date = sprintf "%4d-%02d-%02d %2d:%02d:%02d" ,$year + 1900,$mon + 1 ,$mday ,$hour ,$min ,$sec;
- }
- #发送邮件函数
- sub SendMail {
- my $date = &getDate;
- my $ipaddr = &getIP($interface);
- my $subjects = "$subject\@${ipaddr} Time:$date\n";
- my $smtp = Net::SMTP->new($smtp_host);
- $smtp->auth($from,$password) || print "Email user or password Auth Error!\n";
- $smtp->mail($from);
- $smtp->to($to);
- $smtp->data();
- $smtp->datasend("Subject:$subjects\n");
- $smtp->datasend("\n");
- $smtp->datasend("@_\n\n");
- $smtp->dataend();
- $smtp->quit;
- }
- #读取日志函数,并找出其中到错误行或者警告行
- open MESSAGESLOG , "<", "$logfile" or die "Can't read $logfile : $!";
- if ($last_size < $this_size){
- seek(MESSAGESLOG,$last_size,0) || die "$!\n"; #主要语句
- my @errorarray;
- while(<MESSAGESLOG>){
- push @errorarray,$_ if (/$pattern/i);
- }
- &SendMail(@errorarray) if (@errorarray.length != 0 );
- }
- close MESSAGESLOG;
【第一版】 请注意修改邮件的信息
- #!/usr/bin/perl
- use Net::SMTP;
- use Authen::SASL;
- use Socket;
- use Sys::Hostname;
- require 'sys/ioctl.ph';
- #DATE:2012-08-25_18:28:47 Author:Leo Email:chanyipiaomiao@163.com
- #Test Platform:CentOS 6.0, CentOS 5.6,Red Hat Enterprise Linux AS release 4
- #Log file setting
- my $logfile ="/var/log/messages";
- my $countfile ="/var/log/last_messages.linenumber";
- #Email Setting
- #注意修改这里面的邮件信息
- my $smtp_host = 'smtp.163.com';
- my $from = 'bookfm_2knowledgeq@163.com';
- my $password = '123456';
- my $to = 'chanyipiaomiao@163.com';
- #custom display email subject network interface address, default eth0
- #发送邮件的时候,邮件的主题里面显示的那个接口的IP地址,默认是eth0
- my $interface = "eth0";
- #custom regular expression
- #如果不想看到warn的行,那么就把该表达式修改为"error"
- my $pattern = "(?:error|warn)";
- #custom email subject
- my $subject = "Error Log";
- #read messages log file
- open MESSAGESLOG , "<", "$logfile" or die "Can't read $logfile : $!";
- my @logarray = <MESSAGESLOG>;
- close MESSAGESLOG;
- #read last messages logfile linenumber
- my $last_linenumber;
- if (-z $countfile){
- $last_linenumber = 0;
- }
- elsif (! -e $countfile ){
- warn "[warning]Can't read \"$countfile\",the file does't exists!\n";
- $last_linenumber = 0;
- }
- else {
- open COUNTFILEREAD , "<", $countfile or die "Can't read \"$countfile\" : $! ";
- chomp($last_linenumber = <COUNTFILEREAD>);
- close COUNTFILEREAD;
- }
- #wirte this_linenumber to /tmp/last_messages.linenumber
- open COUNTFILEWRITE, ">", $countfile or die "can't write $countfile : $!";
- my $this_linenumber = @logarray ;
- print COUNTFILEWRITE $this_linenumber ,"\n";
- close COUNTFILEWRITE;
- #get ip address
- sub getIP() {
- my $packpack = pack("a*", shift);
- my $socket;
- socket($socket, AF_INET, SOCK_DGRAM, 0);
- ioctl($socket, SIOCGIFADDR(), $pack);
- $ipaddr = inet_ntoa(substr($pack,20,4));
- };
- #get date
- sub getDate {
- my ($sec, $min, $hour, $mday, $mon, $year) = (localtime)[0 ..5];
- my $date = sprintf "%4d-%02d-%02d %2d:%02d:%02d" ,$year + 1900,$mon + 1 ,$mday ,$hour ,$min ,$sec;
- }
- #send mail function
- sub SendMail {
- my $date = &getDate;
- my $ipaddr = &getIP($interface);
- my $subjects = "$subject\@${ipaddr} Time:$date\n";
- my $smtp = Net::SMTP->new($smtp_host);
- $smtp->auth($from,$password) || print "Email user or password Auth Error!\n";
- $smtp->mail($from);
- $smtp->to($to);
- $smtp->data();
- $smtp->datasend("Subject:$subjects\n");
- $smtp->datasend("\n");
- $smtp->datasend("@_\n\n");
- $smtp->dataend();
- $smtp->quit;
- }
- #find error or warn line
- my @errorarray;
- if ($last_linenumber < $this_linenumber){
- for (my $i = $last_linenumber; $i < $this_linenumber; $i++){
- if ($logarray[$i] =~ /$pattern/i ){
- push @errorarray ,$logarray[$i];
- }
- }
- &SendMail(@errorarray) unless (0 == @errorarray.length);
- }
转载于:https://blog.51cto.com/linux5588/973962