Nagios on CentOS

Prerequisites

* Apache HTTP Server
* GCC compiler
* GD development libraries

yum install httpd
yum install gcc
yum install glibc glibc-common
yum install gd gd-devel

Create a new nagios user account and give it a password.

/usr/sbin/useradd nagios
passwd nagios

Create a new nagcmd group

/usr/sbin/groupadd nagcmd
/usr/sbin/usermod -G nagcmd nagios
/usr/sbin/usermod -G nagcmd apache

Download

wget http://osdn.dl.sourceforge.net/s … agios-3.0rc2.tar.gz
wget http://osdn.dl.sourceforge.net/s … ugins-1.4.11.tar.gz
tar xzf nagios-3.0rc2.tar.gz
cd nagios-3.0rc2

Build

./configure –with-command-group=nagcmd
make all
make install
make install-init
make install-config
make install-commandmode

Configuration

vi /usr/local/nagios/etc/objects/contacts.cfg

Configure the Web Interface

make install-webconf
htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin
service httpd restart

Compile and Install the Nagios Plugins

tar xzf nagios-plugins-1.4.11.tar.gz
cd nagios-plugins-1.4.11
./configure –with-nagios-user=nagios –with-nagios-group=nagios
make
make install

Start Nagios

chkconfig –add nagios
chkconfig nagios on
/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
service nagios start

Modify SELinux Settings

getenforce
setenforce 0
chcon -R -t httpd_sys_content_t /usr/local/nagios/sbin/
chcon -R -t httpd_sys_content_t /usr/local/nagios/share/

Login to the Web Interface

http://localhost/nagios/
username (nagiosadmin) and password you specified earlier

参考: http://nagios.sourceforge.net/docs/3_0/quickstart-fedora.html

系统监控:msn在线机器人实时报警

作者:Michael Field
一、实际需求
在应用各种监控软件(比如:cacti、nagios、sitescope等)的时候,我一般都会用到它的email阀值报警功能。如果这时候再加上一个 msn在线监控机器人为你把关,第一时间给你发出msn报警信息,是不是能让你更快的处理问题呢。以下我为大家介绍一个msn command line 的小程序来实现这个功能。
软件下载地址:sendMsg: http://downloads.fanatic.net.nz/dev/php/sendMsg.zip
二、运行环境
一个支持php的系统环境就可以啦,当然要能上网,不然怎么发消息呢。
我的做法是和cacti监控服务器放一起,不需要额外的设备和资源投入。
注册一个msn的帐号用于监控机器人。比如: 密码:123456
需要收到消息的msn帐号必须加监控帐号为好友,不然收不到消息。

三、sendMsg用法
sendMsg.zip包中所有文件如下:
# ls -l sendMsg/
-rw-r–r– 1 root root 1213 Jul 29   2007 index.php //测试页面,web中打开开始测试;很容易做。
-rw-r–r– 1 root root 3894 Jul 29   2007 msnpauth-1.1.3.php
-rw-r–r– 1 root root 3372 Jul 29   2007 msnpauth.php
-rw-r–r– 1 root root 4586 Jul 29   2007 sendMsg.php
-rw-r–r– 1 root root   223 Jul 29   2007 simple.php
-rw-r–r– 1 root root 1424 Jul 29   2007 template.tpl

该程序也是通过登录msn服务器、建立IM会话,发送消息;
基本PHP语法如下:
$sendMsg = new sendMsg();
$sendMsg->login(‘test@test.com’, ‘123456’);
//刚才建立的用于举例的msn监控机器人帐号
$sendMsg->createSession(‘recipient@hotmail.com’);
//接受信息人的msn帐号
$sendMsg->sendMessage(‘message’, ‘Times New Roman’, ‘FF0000’);
//第一个是具体信息内容,后面可以设定字体和颜色;
$sendMsg->sendMessage(iconv("GBK", "UTF-8", 测试), ‘Times New Roman’, ‘008000’);
//也利用iconv转换gbk到utf8来发送中文信息;

效果如下:

四、实际应用
这里是我自己写的一个应用发送msn信息的php脚本:仅供参考,如果大家有更好请和我交流。
#!/usr/bin/php
<?
if ($argc != 3) {
die("Usage: send_cndmonitor.php <msn-address> <messages>n");
}
array_shift($argv);
$msnaddr = $argv[0];
$messages = $argv[1];
include(‘sendMsg.php’);
$sendMsg = new sendMsg();
$sendMsg-&gt;login(‘test@test.com’, ‘123456’);
$sendMsg-&gt;createSession($msnaddr);
$sendMsg-&gt;sendMessage($messages, ‘Times New Roman’, ‘008000’);
?>

主要是为了能被其他脚本调用,用于发送一个报警信息。缺点是不能判定错误,所以时机运用中存在故障,需要网络流畅的环境下使用。

我们的生产环境已经存在大量的监控系统,所以针对错误信息已经整理到数据库中,因此我只需要从数据库导出目前存在error信息的文本文件,然后根据节点位置发送给相关维护负责人即可。

为了能判定和确保发送正确,我利用sendMsg中的index.php的页面和shell脚本相结合来循环发送,实在抱歉本人PHP程度有限;
脚本如下:(这是我实例用使用的一个工作脚本,仅供大家借鉴)
#!/bin/sh
wget –user=monitor –password=123456 http://127.0.0.1/monitor/msn.txt -O /var/www/html/sendMsg/msn.txt.1 >/dev/null 2>&1
#下载msn要发送的信息,因为页面都是认证的所以用了wget的user和password;
now=`date +%Y-%m-%d-%H:%M`
[ -f /var/www/html/sendMsg/msn.txt ] && oldmd5=`md5sum msn.txt |awk ‘{print $1}’ |tee /var/log/cdn_status_old.md5` || exit 0
[ -f /var/www/html/sendMsg/msn.txt.1 ] && newmd5=`md5sum msn.txt.1 |awk ‘{print $1}’ |tee /var/log/cdn_status_new.md5` || exit 0
SA=(admin1 admin2 admin3 admin4)
# 相关负责人列表和下载的msn信息的中的名字对应;
msnaddr=( )
# 相关负责人的msn帐号和SA变量中的的名字顺序一一对应;
sendMsg()
{
num=0
while [ $num -lt 1 ];
do
wget –post-data "sender=test@test.com&password=123456&recipient=${1}&message=${2}" http://127.0.0.1/sendMsg/index.php -O /var/www/html/sendMsg/index.php.1 >/dev/null 2>&1
# 使用wget post-data发送post参数给index.php页面,用以发送msn信息。
if [ -f /var/www/html/sendMsg/index.php.1 ]; then
if cat /var/www/html/sendMsg/index.php.1 |grep -i successfully >/dev/null 2>&1;then
num=1 #判断信息发送成功
elif cat /var/www/html/sendMsg/index.php.1 |grep -i "The user appears to be offline" >/dev/null 2>&1;then
num=1 #判断msn接受人为是否在线状态
echo "The user is offline."
exit 0
elif cat /var/www/html/sendMsg/index.php.1 |grep -i "Something went wrong trying to connect to the server" >/dev/null 2>&1;then
num=1 #判断msn 服务器存在连接问题
echo "MSN server is wrong."
exit 0
else
num=0 #除了以上三种情况退出循环外,其他情况重试。
fi
rm -f /var/www/html/sendMsg/index.php.1
else
num=0
fi
done
}

if [[ $oldmd5 == $newmd5 ]];then #校验msn的信息是否是已经发送过的,主要是为了不重复发送错误信息。
rm -f /var/www/html/sendMsg/msn.txt.1
exit 0
else
mv /var/www/html/sendMsg/msn.txt /var/www/html/sendMsg/bak/msn$now.txt -f
mv /var/www/html/sendMsg/msn.txt.1 /var/www/html/sendMsg/msn.txt -f
#备份已发送的msn错误信息

fi

for i in `seq 0 1 3` #根据维护人员的数量进行判断和循环
do
if cat /var/www/html/sendMsg/msn.txt |grep -i ${SA[$i]}; then
messages=`cat /var/www/html/sendMsg/msn.txt |grep -i ${SA[$i]}`
sendMsg "${msnaddr[$i]}" "$messages"
else
continue
fi
done

加入到crontab每5分钟执行一次;考虑维护人员的上线时间(最好是24H值班msn,那就不存在这个问题)设定执行时间为每周1到5的9点到18点;
*/5 10-19 * * 1-5 /var/www/html/sendMsg/send_report.sh

实际应用大家可以根据自己的情况进行调整,我这里只是告诉大家怎么使用sendmsg,举了一个简单的实例帮助大家理解和应用。

如果懂php语言的可以把这个作为cacti的一个插件使用,那样效果就更棒啦~

使用Perl实现系统服务监控和报警(zt)

作者:heiyeluren
博客:http://blog.csdn.net/heiyeshuwu
时间:2008-5-22

一般的Web站点来说,都包括很多服务和应用,我们没法实时知道系统运行是否正常,特别是晚上的时候,如果服务器宕机或应用挂掉了,都会影响业务和用户访问,这时候一套对系统监控的错设就必须得当。目前有很多软件应的监控通知和报警服务,有收费的也有免费的,大家都可以选择。

我们就尝试自己来实现一个服务监控和报警通知的程序,这样能够使用很小的代价,同样让我们的服务高可用性和高可靠性。

【监控原理】

远程服务
对于远程机器来说,我们可以有一台监控服务器,或者随便找一台比较不容宕机的服务器来作为监控服务器,那么就能够监控其他的服务机上的服务了,远程监控是比较大家需要的方式了。一般远程监控就监控服务器和端口是否开放,比如说,我们的 Web 服务 Apache 一般都会开放 80 端口,那么我们就可以通过访问这台服务器的 80 端口来确定 Apache 是否在正常工作,如果无法连接上,那么说明该服务就停止了。

本地服务
对于本机来说,监控进程和日志文件都 是可行的,一般来说,长期频繁工作的服务,比如 Apache 都会在每次访问后把访问信息记录到 access 访问日志文件里,如果这个文件长时间没有更新,就可以怀疑该服务已经停止了(当然了,不排除,这段时间内都没有人访问的情况)。另外对于进程来说,本机是 很容易可以查看到进程情况的,对于 MySQL 等服务器来说,守护进程都是长期开放的,如果发现当前系统中没有了 MySQL 守护进程,那么也可以确认 MySQL 服务已经停止了。

报警通知
服务停止了,自然需要通知系统维护人员,那么一般就是通过邮件或者短信的方式,短信是最好的了,但是频繁短信同样让维护人员很郁闷,这个叫做短信炸弹(Message Bomb),所以邮件也许是个简单实在的方式,本地再配置上 Outlook/Foxmail 定期接收和通知方式,也比较快捷,但是晚上回家后,一般都无法收到邮件了,所以合理的方式是白天邮件通知,晚上和周末短信通知 的报警方式更合理。

【代码实现】

具体代码实现可以使用各种代码了,C/C++、Ruby、Python、PHP ,只要能够访问文件、Socket ,能够定期执行的语言都可以,我们下面的代码采用 Perl 来构建,因为 Perl 是很好的系统管理脚本语言,任何 Unix/Linux 都缺省安装了 Perl 引擎,能够很方便的在任何机器上面运行,同时 Perl 的灵活性强,而且有强大的 CPAN 包库,所以编写代码很方便,在系统管理中也是值得推荐大家使用的,当然了,很多系统管理工作使用 shell 脚本也许更方便。

下面的代码实现对远程监控、本地日志文件监控、本地进程监控都进行了实现,但是只使用了远程端口监控的方式,因为这样就能够监控多台机器和服务了,如果只 是单台机器或者只是想监控本地进程,可以很简单的修改主函数来实现。同时通知方式主要是采用邮件通知的方式,并且函数实现了SMTP协议进行邮件发送(因 为我发现Perl内置的 Net::SMTP 在进行型验证的时候,并不是很靠谱),当然了,在报警通知方面,完全可以改写成发送短信或者按照时间来分别调用短信和邮件的方式。

代码中主要监控了包括   Apache、MySQL、Memcache、Search(假如你有的话)等服务,可以在这个基础上进行增删不同的服务器监控,只需要增加一个常量配置和修改 main 函数代码。

说明:以下Perl代码在 RHEL 4 + Perl v5.8.6 环境下测试通过复制内容到剪贴板代码:#!/usr/bin/perl
use IO::Socket;
use IO::File;
use MIME::Base64;

##############################
# Constant define (configure)
##############################
# mail config
use constant MAIL_ADDR       => ('to'=>'webmaster@example.com', 'from'=>'webmaster@example.com');
use constant SMTP_INFO       => ('host'=>'smtp.example.com', 'user'=>'webmaster', 'password'=>'pass',
                                 'debug'=>1, 'bufsize'=>1024);
# common config
use constant MD5SUM_FILE        => '/tmp/__monitor_md5sum_hash';
use constant APACHE_LOG_PATH => '/usr/local/apache2/logs/access';
# apache
use constant APACHE_PORT        => 80;
use constant APACHE_SERVERS     => ('web1.example.com', 'web2.example.com');
# mysql
use constant MYSQL_PORT       => 3306;
use constant MYSQL_SERVERS    => ('db1.example.com', 'db2.example.com');
# memcache
use constant MEMCACHE_PORT    => 11211;
use constant MEMCACHE_SERVERS => ('cache1.example.com', 'cache2.example.com');
# search
use constant SEARCH_PORT        => 8000;
use constant SEARCH_SERVERS     => ('search1.example.com');

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

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

##############################
# Check process is exist
##############################
sub check_process_exist {
my $proc_name = shift;
$line = `/bin/ps auxw | /bin/grep $proc_name | /bin/grep -v grep | /usr/bin/wc -l`;
$line =~ s/^s+|s+$//g;
if ($line == 0){
       return 0;
}
return 1;
}

##############################
# Check file md5 fingerprint
##############################
sub check_file_md5sum {
my $io, $line;
$filename = shift;
@arr = split(/s/, `/usr/bin/md5sum $filename`);
$filehash = shift(@arr);
$io = IO::File->new();
$io->open(MD5SUM_FILE, O_RDWR);
if (!($line = $io->getLine())){
       $io->syswrite($filehash);
       $io->close;
       return true;
}
if ($line != $filehash){
       $io->truncate(0);
       $io->syswrite($filehash);
       $io->close;
       return true;
}
return true;
}

##############################
# SMTP execute command
##############################
sub smtp_cmd {
my ($sock, $cmd, $blocking) = @_;
my %smtpinfo = SMTP_INFO;
my $buf, $bufsize = $smtpinfo{'bufsize'}, $debug=$smtpinfo{'debug'};

$sock->syswrite($cmd);
if ($debug == 1){
       print ">>> $cmd ";
}
if ($blocking == 1){
       $sock->sysread($buf, $bufsize);
       if ($debug){
         print "<<< $buf";
       }
}
}

##############################
# Send notice mail
##############################
sub send_mail {
my ($subject, $content) = @_;
my $sock;
my %mailaddr = MAIL_ADDR;
my %smtpinfo = SMTP_INFO;
my $debug = $smtpinfo{'debug'};

# Count date time
($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime(time());
$datetime = sprintf("%s-%s-%s %s:%s:%s", "20".substr($year,1,2), length($mon)==1?"0$mon":$mon, length($day)==1?"0$day":$day, length($hour)==1?"0$hour":$hour, length($min)==1?"0$min":$min, length($sec)==1?"0$sec":$sec);
$subject .= "[$datetime]";

# Connect to SMTP server
$sock = IO::Socket::INET->new(PeerAddr=>$smtpinfo{'host'}, PeerPort=>25, Proto=>'tcp', Timeout=>10);
$sock->blocking(1);

# Send smtp command
if ($debug == 1){
       print "<<< ". $sock->sysread($buf, $smtpinfo{'bufsize'});
}
smtp_cmd($sock, "HELO locahost ", 1);
smtp_cmd($sock, "AUTH LOGIN ", 1);
smtp_cmd($sock, encode_base64($smtpinfo{'user'}), 1);
smtp_cmd($sock, encode_base64($smtpinfo{'password'}), 1);
smtp_cmd($sock, "MAIL FROM: <". $mailaddr{'from'} ."> ", 1);
smtp_cmd($sock, "RCPT TO: <". $mailaddr{'to'} ."> ", 1);
smtp_cmd($sock, "DATA ", 1);
smtp_cmd($sock, "From: ". $smtpinfo{'from'} ." ", 0);
smtp_cmd($sock, "To: ". $smtpinfo{'to'} ." ", 0);
smtp_cmd($sock, "Subject: $subject ", 0);
smtp_cmd($sock, "$content ", 0);
smtp_cmd($sock, " . ", 1);
smtp_cmd($sock, "QUIT ", 0);
$sock->close();

return 1;
}

##############################
# Check server alive main
##############################
sub monitor_main {
# check apache
foreach $item (APACHE_SERVERS) {
       if (!check_server_alive($item, APACHE_PORT)) {
         send_mail("$item apache server is down", "$item apache server is down. please timely restoration");
       }
}
# check mysql
foreach $item (MYSQL_SERVERS) {
       if (!check_server_alive($item, MYSQL_PORT)) {
         send_mail("$item mysql server is down", "$item mysql server is down. please timely restoration");
       }
}
# check memcache
foreach $item (MEMCACHE_SERVERS) {
       if (!check_server_alive($item, MEMCACHE_PORT)) {
         send_mail("$item memcache server is down", "$item memcache server is down. please timely restoration");
       }
}
# check search
foreach $item (SEARCH_SERVERS) {
       if (!check_server_alive($item, SEARCH_PORT)) {
         send_mail("$item search server is down", "$item search server is down. please timely restoration");
       }
}
}

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

monitor_main();

Nagios短信报警功能通过飞信实现

现在在已有邮件报警的基础上,再进行短信报警的实现,而实现短信报警是通过调用飞信来实现的,下面具体说一下安装的步骤.
1、首先保证sms这个脚本能正常运行,并且能够发送飞信。
2、在command.cfg文件中添加下面两段(手机号码为接收方的号码)
#host-notify-by-sms //发送短信报警
define command {
   command_name    host-notify-by-sms
   command_line    /usr/local/sms/duanxin.sh 138********* "Host $HOSTSTATE$ alert for $HOSTNAME$! on ‘$DATETIME$’ " $CONTACTPAGER$
   }

#service notify by sms   //发送短信报警
define command {
   command_name     service-notify-by-sms
   command_line     /usr/local/sms/duanxin.sh 138******** "’$HOSTADDRESS$’ $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" $CONTACTPAGER$
   }

3、建立duanxin.sh这个脚本,这里我们将建立在/usr/local/sms下,写以下内容
(-f后面跟飞信手机号,-p是飞信密码)
/usr/local/sms/sms -f 138******** -p ****** -t $1 -m "$2"

4、要想让Nagios报警会调用sms这个脚本来发送还需要修改contacts.cfg这个文件
将主机报警和服务报警项改成command.cfg里定义的sms(不过邮件报警将不可用)

       service_notification_commands service-notify-by-sms
       host_notification_commands    host-notify-by-sms
5、还有一点要注意,就是Nagios用户必须对/usr/local/sms目录及内的文件有权限,
Chmod –R 777 /usr/local/sms

系统监控:linux命令行-飞信客户端发送免费报警短信

从 架构研究室 作者:Michael Field

一、软件环境(centos 5为例)
这里向大家推荐的是飞信机器人的软件,支持linux、命令行下的飞信、完全免费(目前为止);
官网地址:http://www.it-adv.net/
支持库安装:
需要Glibc2.4以上的版本;centos5默认安装的Glibc2.5,所不需要额外升级;
目前网上的安装文档只有ubuntu的,至于redhat、fedora、centos都没有相关安装文档,我在安装的过程中遇到很多库的问题,所以在这里一并给大家进行介绍;

二、安装过程
下载包地址 LINUX X86/32(REDHAT ES4X32):支持库 最新程序fetion20080522004-linrh4.tar.gz
其中支持库和安装包内容如下:
# tar zxvf libraryrh4x32.tar.gz
libACE-5.6.5.so
libACE_SSL-5.6.5.so
libcrypto.so.0.9.7a
libssl.so.0.9.7a

# tar zxvf fetion20080522004-linrh4.tar.gz
./install/
./install/www/
./install/www/index.html
./install/www/css/
./install/www/css/scheme.css
./install/www/css/main.css
./install/www/css/print.css
./install/www/css/main-msie.css
./install/www/images/
./install/www/js/
./install/www/js/jquery.js
./install/socket_interface/
./install/socket_interface/socket_demo.php
./install/Readme.txt
./install/sound/
./install/sound/smile8.wav
./install/sound/message.wav
./install/sound/smile1.wav
./install/sound/login.wav
./install/sound/openchatwin.wav
./install/sound/closechatwin.wav
./install/fetion
./install/plugins/
./install/plugins/plugin_contact_update
./install/plugins/plugin_buddy_application
./install/plugins/plugin_message
./install/plugins/plugin_invite
./install/plugins/plugin_timer
./install/conf/

把支持库复制到/usr/lib/目录下,并作软链接如下:
cp lib*so* /usr/lib/
ln -s /usr/lib/libcrypto.so.0.9.7a /usr/lib/libcrypto.so.4
ln -s /usr/lib/libssl.so.0.9.7a /usr/lib/libssl.so.4

设定lib库配置文件
#vi /etc/ld.so.conf
#增加一条
/usr/lib/
#保存退出后,执行
#ldconfig

fetion的目录结构:
.Readme.txt: 本说明文件
.fetion:主程序
.sound*.wav:各种音效文件,您可以用自己喜欢的文件替换
.pluginsplugin_*: 插件程序,您可以修改插件以达到自己的各性化需求

我在安装中遇到缺少krb5的库问题,这里写一下解决方法:
错误如下:
./fetion: error while loading shared libraries: libgssapi_krb5.so.2: cannot open shared object file: No such file or directory
安装一下krb5-libs包就可以解决啦:
yum install krb5-libs

完成之后测试,安装是否成功;执行
#cd install
# ./fetion -h
Usage:
fetion -h
       -h: help
fetion -u mobile -p pwd [-b batchfile] [-EN] [-d]
fetion -u mobile -p pwd [-b batchfile] [-EN] [-d]
       -u: Fetion user account(only supports mobile phone No.)
       -p: Account password
       -b: Batch file name
       -d: Debug on and write logs to [mobile]-debug.log
       -EN: English

三、实际测试
登录飞信默认是中文utf8的,如果linux系统不支持utf8会出现乱码:我使用english的方式来登录啦。
测试帐号:13713718888
密码:123456 (如果密码中含有特殊字符,请使用单引号)
./fetion -u 13713718888 -p 123456 -EN

登录后输入?获得帮助
****************************************************************
指令                    指令说明
list                   好友列表: list
sms                    发送短信: sms 飞信号/手机号/编号 短信内容(换行请用n代替)
chat                在线消息: chat 飞信号/手机号/编号 短信内容(换行请用n代替)
status                 在线状态: status online/busy/away/hidden [个性化信息]
add                    添加好友: add 飞信号/手机号 申请信息 本地呢称
del                   删除好友: del 飞信号/手机号/编号
invite                 邀请好友: invite 手机号 您的姓名(邀请好友开通飞信)
autoaccept       自动接受: autoaccept on/off/status 自动接受加为好友申请
myinfo             修改资料: myinfo nickname/impresa 内容(呢称/心情)
help                帮助菜单: help/?
exit                退出系统: quit/exit
****************************************************************

sms 137******** "this is test message" # 这个就是我们需要的发送短信的指令啦!

脚本测试:
可以使用fetion的-b参数来实现p处理;
举例如下:

# vi p.sh
sms 13712312311 “msyqlserver is down”
sms 13712312312 “db1 is not running”
sms 13712312313 “warning db2 disk3 is full”
保存后执行:
./fetion -u 13713718888 -p 123456 -b p.sh
就是一次给3个admin发出报警信息。

还有许多插件的功能,我会在下次实际应用中写出日志和大家一起研究;
在初步接触中,发现可以实现一些交互信息的查询,比如直接向短信机器人发指令得到某台服务器的运行状态等。