Chinaunix首页 | 论坛 | 博客
  • 博客访问: 128299
  • 博文数量: 28
  • 博客积分: 2431
  • 博客等级: 大尉
  • 技术积分: 321
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-29 18:40
文章分类

全部博文(28)

文章存档

2011年(3)

2010年(6)

2009年(7)

2008年(12)

分类:

2009-04-05 15:59:34

这是我第一次写一些比较实用俄东西,有关服务器的性能监测的脚本,实现了以下功能:
1.监测系统资源的使用情况,包括CPU、磁盘空间、IO操作、TCP连接数等等。 (以后还会进一步的添加更详细的监测情况,包括具体进程的监测)
2.使用内部监测模式                                        
3.要求生成报表(可以word文档的模式,最好可以实现图形模式)(这个迟点再实现)
4.一旦出现性能故障或性能指标达到报警标准,程序会提示,包括声音、邮件、手机短信息等方式自动发送,及时通知相关管理人员在故障发生前及时消除故障隐患。以后还会添加尝试自动解决问题。
5.采用了日志模式。(很简单的模式的说)
-------------------------------
因为是初学者,对性能监测这方面不是很熟悉,在加上perl还不是很难熟,所以,代码比较粗糙,而且有点不是很规范,有点长(其实还可以精简很多的),效率还没有怎样测试过,不过应该不是很好的说```毕竟刚开始```大家有什么意见的话,可以提示一下小弟```好让我修改好``````                                                                                                         

#!/usr/bin/perl -w

#use Fcntl qw(:flock);

use strict;
use Mail::Sender;
use Sys::Statistics::Linux;
use Fetion;
my $cpu_max=90;        #cpu最大占用率

my $mem_free_mix=10;    #最小可用内才能

my $disk_free_mix=50;    #最小可用磁盘空间

my $max_io=1;        #最大的io wait队列

#my $max_send_times=2;        

#my $match_count=0;

my %opt=(sysinfo => 0,
        cpustats => 1,
        procstats => 0,
        memstats => 1,
        pgswstats =>0,
        netstats => 0,
        sockstats => 1,
        diskstats => 0,
        diskusage => 1,
        loadavg => 1,
        filestats => 1,
        processes => 0,    
);
my $lxs = Sys::Statistics::Linux->new(\%opt);
my $cad_check_time=(localtime)[2];        #cad mean cpu and ddram

my $io_check_time=$cad_check_time;
my $disk_usage_check_time=$cad_check_time;
my $warn_flag=0;
my $pre_flag=0;
my $pre_io_check=0;
my $cur_io_flag=0;
my $pre_space_flag=0;
my $cur_space_flag=0;
my $small_space={{},1};
my @space;
my $counter=1;
#print STDOUT Dumper($small_space),"\n";

my $stat;
my @iostat;
while(sleep 2){
my ($cad_flag,$space_flag,$io_flag)=(0,0,0);
$stat = $lxs->get;
@iostat=split /\s/,(`vmstat`)[2];        #这句为后面的IO检查做准备

#如果cpu的占用率大于90%,或者内存占用达到90%,并且平均负载大于5,发送警报邮件和短信通知,这个部分还需要改良,最好进一步分开内存和cpu,因为内存占用很高,负载不一定高的

#--------------------检查cpu和内存的使用情况-------------------

if($stat->cpustats->{cpu}->{total}>$cpu_max||($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100<$mem_free_mix)            #这里都是用百分比来计算的

{
    if($stat->loadavg->{avg_1}>2)
    {
        $pre_flag=$warn_flag;
        $warn_flag=1;        #警报标志

        if($pre_flag==1)    #为1时,证明之前出现过警报的情况

        {
            if((localtime)[2]!=$cad_check_time)            #检查是否在同一时段出现警报,默认时间间隔为1小时,同一时段内,只发送一次短信和邮件

            {
                print 'send when cpu&&ram busy and time !=',"\n";
                #&sendMail('loadavg is too hight',$stat->cpustats->{cpu}->{total},($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100,$stat->loadavg->{avg_1});#sendMail(subject,cpu_usage,ram_free,loadavg)

                &sendMail(1);            #1 mean cpu&&ram

                &sendSms(1,'your phone number','you passwd');
                $cad_check_time=(localtime)[2];            #更新最近一次的警报时间

                
            }
        }
        else
        {
            #初次发送

            print 'send when flag=0, that is the first time',"\n";
            #&sendMail('loadavg is too hight',$stat->cpustats->{cpu}->{total},($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100,$stat->loadavg->{avg_1});#sendMail(subject,cpu_usage,ram_free,loadavg)

            &sendMail(1);
            &sendSms(1,'your phone number','you passwd');
        }
        $cad_flag=1;
    }
    else
    {
        $pre_flag=0;
        $cad_flag=0;
        
    }
}
#---------------------------cpu&&内存检查完毕------------------------

#-------------------------------------------------------

#----------------检查磁盘空间-----------------------------

#这部分还需要改进,如何去进一步的区别容量满的分区

my $driver;
foreach $driver(keys %{$stat->diskusage})
{
    next if $driver!~/^\/dev\//;
    #print $driver,"\n";

    my $drive=$driver;
    #print $drive,"\n";

    $driver=~s/\/dev\///gi;
    
    #print $driver,"\n";    

    #print $drive,"\n";

    if($stat->diskusage->{$drive}->{usage}/$stat->diskusage->{$drive}->{total}*100>$disk_free_mix)
    {
        if(!exists $small_space->{$driver})            #设备是否重复,重复的跳过

        {
                $small_space->{$driver}->{check_time}=(localtime)[2];            #记录出现警报的时间

                $small_space->{$driver}->{space_flag}=1;                #0 mean had checked before,1 not before

                $small_space->{$driver}->{free}=sprintf "%.2f",$stat->diskusage->{$drive}->{free}/$stat->diskusage->{$drive}->{total}*100;    #容量取两位小数

                print "send when the first time that $driver space is hardly full","\n";
                #&sendMail(2);

        }                    
        $space_flag=1;
    }
    else
    {
        if(exists $small_space->{$driver})
        {
            delete     $small_space->{$driver}
        }
        $space_flag=0;
    }
}
if((keys %{$small_space})>1)        #排除本来的没用HASH

{
    if($counter==1)
    {
        &sendMail(2);
        &sendSms(2,'your phone number','you passwd');
        $counter=2;
    }
    else
    {
        foreach $driver(keys %{$small_space})
        {
            next if $driver=~/^HASH/;
            if($small_space->{$driver}->{space_flag}==1)            
            {    
                if($small_space->{$driver}->{check_time}!=(localtime)[2])            #检查是否为同一时段,相同的跳过,避免重复发信,默认为1小时

                {
                    print 'send when someone disk space is fulland time !=',"\n";
                    $small_space->{$driver}->{check_time}=(localtime)[2];            #更新时间点

                    &sendMail(2);
                    &sendSms(2,'your phone number','you passwd');
                }
            }
        }    
    }
    
}
#----------检查磁盘空间结束-----------------

#-----------检查磁盘io操作-----------------

#@iostat=split /\s/,(`vmstat`)[2];        #要求有vmstat这个脚本,在/proc里边

if($iostat[-1]>$max_io)
{
    $pre_io_check=$cur_io_flag;
    $cur_io_flag=1;
    if($pre_io_check==1)
    {
        if((localtime)[2]!=$io_check_time)
        {
            print 'send when io busy and time !=',"\n";
            $io_check_time=(localtime)[2];
            &sendMail(3);
            &sendSms(3,'your phone number','you passwd');
        }
    }
    else
    {
        print 'send when pre_io_check=0, that is the first time',"\n";
        &sendMail(3);
        &sendSms(3,'your phone number','you passwd');
    }
    $io_flag=1;
}
else
{
    $io_flag=0;
}
#---------------------检查磁盘IO结束-----------------

&writeLog($cad_flag,$space_flag,$io_flag);                #无论遇到什么警报,都记录在日志上

}        #主循环结束


#---------------------------函数部分------------------------------

#----------------------writeLog fun----------------------------------------------

sub writeLog{
#use Data::Dumper;

my ($cad_flag,$space_flag,$io_flag)=@_;
if($cad_flag||$space_flag||$io_flag)
{
    my $time=localtime;
    my $log_file='log.txt';
    open LOG,">>",$log_file||die "can't open $log_file for write:$!\n";
#if(flock LOG,LOCK_EX)#||die "can't lock $log_file:$!\n";

#{

#    print STDERR "ok\n";

#}

#select LOG;

#time    cpu_usage%    loadavg        ram_free%    disk_space_free%        io_wait        tcp

#      10          0 73     sda1:10,sda2:5,sda3:11         1          6

#if($cad_flag||$space_flag||$io_flag)

#{

    #print "$time $stat->cpustats->{cpu}->{total} $stat->loadavg->{avg_1} ",$stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100,$stat->diskusage->{$drive}->{free}/$stat->diskusage->{$drive}->{total}*100," $iostat[-1] $stat->sockstats->{tcp}\n";

    #printf("%s %d %d %d %s %d\n",$time,$stat->cpustats->{cpu}->{total},$stat->loadavg->{avg_1},($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100,$iostat[-1],$stat->sockstats->{tcp});

    
    foreach my $dev(keys %{$small_space})        #因为日之中磁盘空间那里比较特别,所以要特殊处理;将整个字段作为一个数组处理,待会儿可以进行join

    {
        next if $dev=~/^HASH/;
        push @space,"$dev:$small_space->{$dev}->{free}";
    }
    printf LOG ("%s %.2f %.2f %.2f %s %s %d\n",$time,$stat->cpustats->{cpu}->{total},$stat->loadavg->{avg_1},($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100),join(",",@space),$iostat[-1],$stat->sockstats->{tcp};
#}

#select STDOUT;

#flock(LOG,LOCK_UN)||die "can't unlock $log_file:$!\n";

    @space=();
    close LOG;
}
}
#------------------------writeLog end ------------------------------

#---------------------sendSms fun-----------------------------------

sub sendSms{
my ($warn_type,$num,$passwd,$to_num)=@_;
#my $sms='cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp};

my $sms;
if($warn_type==1)
{
    $sms='warning:Loadavg is too high.'.'cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp};
}
elsif($warn_type==2)
{
    $sms='warning:Disk space is full.'.'cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp};
}
else
{
    $sms='warning:Disk io are busy.'.'cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp};
}
print "init..", Fetion::fx_init(), "\n";
if(Fetion::fs_login($num , $passwd ))#|| die " cannot login , try again please\n";

{#print "get account", Dumper( Fetion::fx_get_account() ), "\n";

    print "send to self......";
    Fetion::fs_send_sms_to_self($sms);
    print "\n";
    #print "send to $to_num..";

    #Fetion::fs_send_sms_by_mobile_no($to_num, $sms)||die "can't send:$!\n";

    #send to someuser of feixin

    #print "send to 440227509", Fetion::fs_send_sms(440227509, "你这个白痴"), "\n";

    print "loginout", Fetion::fx_loginout(), "\n";
    print "terminate", Fetion::fx_terminate(), "\n";
}
else
{
    if(open ERR,">>",'err.log')
    {    
        print ERR "can't send sms,please check the usename&&password again or make sure you internet is available\n";
        close ERR;
    }
    else
    {
        print "can't open err.log to write:$!\n";
    }
    print "can't send sms,please check the usename&&password again or make sure you internet is available\n";
    return -1;
}
}
#-----------------------sendSms fun end------------------------------

#-----------------------sendMail fun------------------------------------

sub sendMail{
my ($warn_type)=@_;
my $subject;
my $msg='cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp};
if($warn_type==1)
{
    $subject='warning:Loadavg is too high';
    #$msg="cpu usage:$stat->cpustats->{cpu}->{total}% ".'freemem:'.($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100.'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp}.' Disk space:'.join(",",@space);

}
elsif($warn_type==2)
{
    $subject='warning:Disk space is full';
    foreach my $dev(keys %{$small_space})        #因为日之中磁盘空间那里比较特别,所以要特殊处理;将整个字段作为一个数组处理,待会儿可以进行join

    {
        next if $dev=~/^HASH/;
        push @space,"$dev:$small_space->{$dev}->{free}";
    }
    $msg='cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp}.' '.join(",",@space);
}
else
{
    $subject='warning:Disk io are busy';
}
@space=();
#$msg='cpu usage:'.$stat->cpustats->{cpu}->{total}.'% freemem:'.sprintf("%.2f",($stat->memstats->{memfree}+$stat->memstats->{buffers}+$stat->memstats->{cached})/$stat->memstats->{memtotal}*100).'% system loadavg:'.$stat->loadavg->{avg_1}.'% IO wait:'.$iostat[-1].' TCP:'.$stat->sockstats->{tcp};#.' Disk space:'.join(",",@space);

my $sender;
eval{
    $sender=new Mail::Sender();

    #my @protocols = $sender->QueryAuthProtocols(); 查询服务器支持的认证方式

if ($sender->MailMsg({
               #smtp => 'smtp.163.com',by Default,test@163.com

               #from => 'test@163.com', by Default

               to =>'test98@163.com',
               subject => $subject,     #主题

               msg => $msg, #内容

               auth => 'LOGIN',            #smtp的验证方式

               authid => 'user',        #user

               authpwd => 'passwd',    #pwd

     }) < 0) {
              warn "$Mail::Sender::Error\n";
         }
    print "warning Mail sent OK.\n";
};
if($@)
{
    if(open ERR,">>",'err.log')
    {    
        print ERR "$Mail::Sender::Error\n";
        close ERR;
    }
    else
    {
        print "can't open err.log to write:$!\n";
    }
    print "can't send mail,please check the err.log for detail\n";
    return -1;
}
}
#--------------------sendMail fun end--------------------------------------

阅读(2927) | 评论(4) | 转发(0) |
0

上一篇:perl学习之txt转excel

下一篇:文件更新列表

给主人留下些什么吧!~~

wfnh2009-04-27 18:23:39

这个模块不是我自己写的,是在网上下载的。你要的话,我可以给你。 QQ:283257958请注明是LINUX性能监控

chinaunix网友2009-04-27 14:14:02

Can't locate Fetion.pm in @INC

chinaunix网友2009-04-27 13:25:45

fetion这个模块难道是你自己写的

chinaunix网友2009-04-27 13:24:49

这个fetion模块怎么没有