<?php

Currently browsing 监控

linux下根据/proc/stat计算CPU使用情况算法详解

本文是介绍在Linux/unix下如何根据/proc/stat文件的信息计算得到CPU使用率。大多情况下自己做系统监控时都会用到这个文件

首先找来一段扫盲文字“在linux下,CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间 / CPU总的执行时间。在内核中,有一个全局变量:Jiffies。 Jiffies代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位就是1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。 CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。”

下面我们看一下/proc/stat 的内容结构

/bin/cat /proc/stat
cpu  3783155 5336 947214 78774537 115679 6 89497 0
cpu0 871159 806 194940 19851524 8176 0 2221 0
cpu1 918820 1900 203290 19794976 7834 1 1980 0
cpu2 922359 882 213789 19715943 61418 2 14503 0
cpu3 1070815 1747 335193 19412092 38250 1 70791 0
intr 284814153 209329067 3 0 0 4 0 0 0 1 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 252 0 0 0 0 0 0 0 2664133 0 0 0 0 0 0 0 72820689 0 0 0 0 0
ctxt 1591477835
btime 1268412588
processes 1346557
procs_running 1
procs_blocked 1

咋一看去相当的晕,完全不知从何下手。有关文件格式的介绍可以参考:http://www.linuxhowtos.org/System/procstat.htm
下面对输出信息做解释:

CPU时间=user+system+nice+idle+iowait+irq+softirq
“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。

“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。
那么CPU利用率可以使用以下两个方法。先取两个采样点,然后计算其差值:

[code lang="code"]
cpu usage=(idle2-idle1)/(cpu2-cpu1)*100 cpu usage=[(user_2 +sys_2+nice_2) - (user_1 + sys_1+nice_1)]/(total_2 - total_1)*100
[/code]

以下用分别用bash和perl做的一个cpu利用率的计算:
原作者注:以下代码则采用公式为:
[code lang="code"]
total_0USER[0]+NICE[0]+SYSTEM[0]+IDLE[0]+IOWAIT[0]+IRQ[0]+SOFTIRQ[0] total_1=USER[1]+NICE[1]+SYSTEM[1]+IDLE[1]+IOWAIT[1]+IRQ[1]+SOFTIRQ[1] cpu usage=(IDLE[0]-IDLE[1]) / (total_0-total_1) * 100
[/code]

bash 代码:

#!/bin/sh
##echo user nice system idle iowait irq softirq
CPULOG_1=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_1=$(echo $CPULOG_1 | awk '{print $4}')
Total_1=$(echo $CPULOG_1 | awk '{print $1+$2+$3+$4+$5+$6+$7}')

sleep 5

CPULOG_2=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_2=$(echo $CPULOG_2 | awk '{print $4}')
Total_2=$(echo $CPULOG_2 | awk '{print $1+$2+$3+$4+$5+$6+$7}') 

SYS_IDLE=`expr $SYS_IDLE_2 - $SYS_IDLE_1`

Total=`expr $Total_2 - $Total_1`
SYS_USAGE=`expr $SYS_IDLE/$Total*100 |bc -l`

SYS_Rate=`expr 100-$SYS_USAGE |bc -l`

Disp_SYS_Rate=`expr "scale=3; $SYS_Rate/1" |bc`
echo $Disp_SYS_Rate%

perl 代码:

#!/usr/bin/perl
use warnings;

$SLEEPTIME=5;

if (-e "/tmp/stat") {
	unlink "/tmp/stat";
}
open (JIFF_TMP, ">>/tmp/stat") || die "Can't open /proc/stat file!\n";
open (JIFF, "/proc/stat") || die "Can't open /proc/stat file!\n";
@jiff_0=<JIFF>;
print JIFF_TMP $jiff_0[0] ;
close (JIFF);

sleep $SLEEPTIME;

open (JIFF, "/proc/stat") || die "Can't open /proc/stat file!\n";  @jiff_1=<JIFF>;
print JIFF_TMP $jiff_1[0];
close (JIFF);
close (JIFF_TMP);

@USER=`awk '{print \$2}' "/tmp/stat"`;
@NICE=`awk '{print \$3}' "/tmp/stat"`;
@SYSTEM=`awk '{print \$4}' "/tmp/stat"`;
@IDLE=`awk '{print \$5}' "/tmp/stat"`;
@IOWAIT=`awk '{print \$6}' "/tmp/stat"`;
@IRQ=`awk '{print \$7}' "/tmp/stat"`;
@SOFTIRQ=`awk '{print \$8}' "/tmp/stat"`;

$JIFF_0=$USER[0]+$NICE[0]+$SYSTEM[0]+$IDLE[0]+$IOWAIT[0]+$IRQ[0]+$SOFTIRQ[0];
$JIFF_1=$USER[1]+$NICE[1]+$SYSTEM[1]+$IDLE[1]+$IOWAIT[1]+$IRQ[1]+$SOFTIRQ[1];
$SYS_IDLE=($IDLE[0]-$IDLE[1]) / ($JIFF_0-$JIFF_1) * 100;  $SYS_USAGE=100 - $SYS_IDLE;

printf ("The CPU usage is %1.2f%%\n",$SYS_USAGE);

参考原文:http://server.51cto.com/sCollege-188250.htm

一个简单的由perl实现的端口监控脚本,邮件通知+手机短信通知

先说一下原理,1,根据端口的响应时间来判断是否宕掉;2,如果宕掉了就发一封邮件到指定邮箱(注意:需要用到sendmail, 要安装配置好)
另一个,如果需要手机短信通知。其实不需要搞什么飞信接口了,直接去注册一个139邮箱,免费的邮件到达短信通知,包括邮件内容的! 如果不想用139邮箱,也可以选择qq邮箱的短信通知服务。或其他服务商,任你选择了。

#!/usr/bin/perl -X

use IO::Socket;

##############################
# Constant define (configure)
##############################
# mail config
use constant MAIL_ADDR          => ('to'=>'zhys9@139.com', 'from'=>'nginx.org@gmail.com');
# common config
use constant MD5SUM_FILE        => '/tmp/__monitor_md5sum_hash';
# apache
use constant WEBSERVER_PORT        => 80;
use constant WEBSERVER_HOSTS     => ('localhost');
# mysql
use constant MYSQL_PORT         => 3306;
use constant MYSQL_HOSTS      => ('localhost');
# memcache
use constant PHPFCGI_PORT      => 9000;
use constant PHPFCGI_HOSTS   => ('localhost');

##############################
# Server port is alive check
##############################
sub check_server_alive {
    my($server, $port) = @_;

    $sock = IO::Socket::INET->new(PeerAddr=>$server, PeerPort=>$port, Proto=>'tcp', Timeout=>1);
    if (!$sock){
        return 0;
    }
    $sock->close();
    return 1;
}

##############################
# Send notice mail
##############################
sub send_mail {
    my ($subject, $content) = @_;;
    my %mailaddr = MAIL_ADDR;

    open(MAIL, "|/usr/sbin/sendmail -t");

    ## Mail Header
    print MAIL "To: $mailaddr{'to'}\n";
    print MAIL "From: $mailaddr{'from'}\n";
    print MAIL "Subject: $subject\n\n";

    ## Mail Body
    print MAIL "$content\n";

    close(MAIL);

}

##############################
# Check server alive main
##############################
sub monitor_main {
    # check apache
    foreach $item (WEBSERVER_HOSTS) {
        if (!check_server_alive($item, WEBSERVER_PORT)) {
            send_mail("$item web server is down", "$item web server is down. please timely restoration");
        }
    }
    # check mysql
    foreach $item (MYSQL_HOSTS) {
        if (!check_server_alive($item, MYSQL_PORT)) {
        print("mysql is down.");
            send_mail("$item mysql server is down", "$item mysql server is down. please timely restoration");
        }
    }
    # check fast-cgi
    foreach $item (PHPFCGI_HOSTS) {
        if (!check_server_alive($item, PHPFCGI_PORT)) {
            send_mail("$item fast-cgi is down", "$item fast-cgi is down. please timely restoration");
        }
    }
}

##############################
# Main running
##############################

monitor_main();

本脚本参考文档:
http://blog.csdn.net/re_think/archive/2009/06/25/4296833.aspx
perl发送邮件:http://www.cyberciti.biz/faq/sending-mail-with-perl-mail-script/