nagios+nginx从环境搭建到配置

    nagios是一个开源免费的系统监控工具,官网地址 http://www.nagios.org/    截止2011-07-27    nagios的最新版本是3.x,基于c语言编写,并提供了一个基于php和cgi的web管理界面
    

环境搭建

    nagios需要一个web容器+php的运行环境,由于现在的公司统一使用nginx作为web容器,在这里我选择了nginx+php
    nginx官网地址为    http://nginx.org/    php官网地址为    http://www.php.net/    
    如果对于nagios的web界面,需要根据用户配置相应的访问权限的话,那还得安装一个apache,没别的用途,就是用htpassword生成账户信息。
    apache官网地址    http://httpd.apache.org/    
    我所准备的jar包如下,其中spawn-fcgi是用于nginx重定向到php用的
        lighttpd-1.4.28.tar.gz
        nginx-1.0.5.tar.gz
        php-5.3.6.tar.gz
        spawn-fcgi-1.6.2.tar.gz
        
    安装nginx   

tar nginx-1.0.5.tar.gz
cd nginx-1.0.5/
./configure    --prefix=/usr/local/nginx
make && make install

   
    注意--prefix是在指定软件的安装路径,可以根据个人情况自行修改
    安装php之前最好参考张宴的这篇博客 http://blog.s135.com/post/297/ 安装对应的图形和xml等lib,当然稍后安装也行    

   

tar zxvf php-5.3.6.tar.gz
cd php-5.3.6/
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc l --with-zlib  --disable-debug --disable-rpath --enable-discard-path --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-fastcgi --enable-force-cgi-redirect
make && make install
cp php.ini-dist /usr/local/php/etc/php.ini
cd ../




    注意,一定要带上--enable-fastcgi --enable-force-cgi-redirect,如果执行 ./configure时 提示缺少某个包,比如zlib,gd等等,安装上即可


    


    解压缩并安装 spawn-fcgi,与张宴博客不同的是,在我写这篇博客时spawn-fcgi已经作为单独的包提供使用了

 

tar spawn-fcgi-1.6.2.tar.gz
cd spawn-fcgi-1.6.2/
./configure    --prefix=/usr/local/spawn-fcgi
make && make install




    然后仅仅是把spawn-fcgi这个文件copy去php的bin目录下,为什么仅仅只要一个文件呢?好吧,我也不知道。


cp spawn-fcgi /usr/local/php/bin
chmod +x /usr/local/php/bin/spawn-fcgi


   
    启动php cgi进程


/usr/local/php/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -C 250 -u www -f /usr/local/php/bin/php-cgi


  这样一来环境就搭建的差不多了,这中间容易出问题的就是php安装的时候可能会报缺某些工具包
    

安装nagios及其插件nagios-plugin

   

tar nagios-3.2.3.tar.gz
cd nagios-3.2.3/
./configure    --prefix=/usr/local/nagios --with-gd --with-libpng --with-libjpeg
make && make install




    注意,在安装gd,libpng,libjpeg时还需要安装对应的devel包才行,即gd-devel,libpng-devel,libjpeg-devel

tar nagios-plugins-1.4.15.tar.gz
cd nagios-plugins-1.4.15/
./configure    --prefix=/usr/local/nagios --with-gd --with-libpng --with-libjpeg
make && make install




    安装fast-cgi

tar FCGI-ProcManager-0.19.tar.gz
cd FCGI-ProcManager-0.19/
./configure    --prefix=/usr/local/fcgi
make && make install

    
    在很多nginx+nagios的搭建教程中都提到一个 nginx-fcgi的脚本文件,下载地址是 http://www.nginx.eu/nginx-fcgi/nginx-fcgi.txt 但当我写这篇博客时该地址已经失效了,脚本文件作为附件奉上
    
    然后启动fcgi


./nginx-fcgi -l /usr/local/logs/nginx-fcgi.log -pid /tmp/nginx-fcgi.pid -S /tmp/nginx-fcgi.sock


    注意, -pid用于指定nginx-fcgi的进程pid, 需要执行以下命令更改运行权限


chmod    777 /tmp/nginx-fcgi.sock


   

配置nginx



cd /usr/local/nginx/conf
vi nginx.conf





server {
    listen          80;
    server_name     nagios.test.com;
    root            /usr/local/nagios/share;
    index index.html index.htm index.php default.html default.htm default.php;

    location ~ .*\.php?$ {
            fastcgi_pass    127.0.0.1:9000;
            fastcgi_index   index.php;
            include fastcgi.conf;
            fastcgi_param SCRIPT_FILENAME /usr/local/nagios/share$fastcgi_script_name;
            auth_basic      "nagios admin";
            auth_basic_user_file    /usr/local/nagios/etc/nagiosAdmin.net;
     }
    location ~ .*\.cgi$ {
            root    /usr/local/nagios/sbin;
            rewrite ^/nagios/cgi-bin/(.*)\.cgi /$1.cgi break;
            fastcgi_pass unix:/tmp/nginx-fcgi.sock;
            fastcgi_index index.cgi;
            fastcgi_param SCRIPT_FILENAME /usr/local/nagios/sbin$fastcgi_script_name;
            include fastcgi.conf;
            auth_basic      "nagios admin";
            auth_basic_user_file    /usr/local/nagios/etc/nagiosAdmin.net;

    }
    location /nagios {
            alias /usr/local/nagios/share;
            auth_basic      "nagios admin";
            auth_basic_user_file    /usr/local/nagios/etc/nagiosAdmin.net;

    }
    location ~ .*\.pl$ {
            fastcgi_pass  unix:/tmp/nginx-fcgi.sock;
            fastcgi_index index.pl;
            fastcgi_param SCRIPT_FILENAME  /usr/local/nagios/sbin$fastcgi_script_name;
            include fastcgi.conf;
    }
}





  其中 auth_basic和auth_basic_user_file用于指定该种URI的访问权限,对应的 /usr/local/nagios/etc/nagiosAdmin.net 需要事先用htpasswd命令生成
    后缀为.php的URI用
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        来指定给spawn-cgi处理
    后缀为.cgi的URI用
        root    /usr/local/nagios/sbin;
        rewrite ^/nagios/cgi-bin/(.*)\.cgi /$1.cgi break;
        fastcgi_pass unix:/tmp/nginx-fcgi.sock;
        fastcgi_index index.cgi;
        fastcgi_param SCRIPT_FILENAME /usr/local/nagios/sbin$fastcgi_script_name;
        include fastcgi.conf;
    指定给刚才启动的nginx-fcgi进程处理,注意nagios的php程序都在/usr/local/nagios/share 下,而cgi程序都在/usr/local/nagios/sbin下,别搞错路径
    
之后就是启动nagios,nginx,在你当前机器设置host后访问 http://nagios.test.com 查看web内容

nagios的配置

nagios的配置文件都在/usr/local/nagios/etc下,其中    
    nagios.cfg    是主配置文件
    cgi.cfg    用于配置权限之类
    详细配置文件在/usr/local/nagios/etc/object之内,如何配置详见 http://nagios-cn.sourceforge.net/nagios-cn/cgiconfig.html    配置文件修改完毕后,执行命令 /usr/local/nagios/bin/nagios -pv /usr/local/nagios/etc/nagios.cfg 更新缓存,详见http://nagios-cn.sourceforge.net/nagios-cn

  下面是nginx-fcgi的源码

#!/usr/bin/perl
#
#	author		Daniel Dominik Rudnicki
#	thanks to:	Piotr Romanczuk
#	email		daniel@sardzent.org
#	version		0.4.3
#	webpage		http://www.nginx.eu/
#
#	BASED @ http://wiki.codemongers.com/NginxSimpleCGI
#
#
# use strict;
use FCGI;
use Getopt::Long;
use IO::All;
use Socket;

sub init {
	GetOptions(	"h"	=> \$help,
			"verbose!"=>\$verbose,
			"pid=s"	=> \$filepid,
			"l=s" => \$logfile,
			"S:s"   => \$unixsocket,
			"P:i"   => \$unixport) or usage();
		usage() if $help;

	print "	Starting Nginx-fcgi\n" if $verbose;
	print "	Running with {1}gt; UID" if $verbose;
	print "	Perl $]" if $verbose;

#	if ( {1}gt; == "0" ) {
#		print "\n\tERROR\tRunning as a root!\n";
#		print "\tSuggested not to do so !!!\n\n";
#		exit 1;
#	}

        if ( ! $logfile ) {
		print "\n\tERROR\t log file must declared\n"
			. "\tuse $0 with option -l filename\n\n";
		exit 1;
	}
	print "	Using log file $logfile\n" if $verbose;
	"\n\n" >> io($logfile);
	addlog($logfile, "Starting Nginx-cfgi");
	addlog($logfile, "Running with {1}gt; UID");
	addlog($logfile, "Perl $]");
	addlog($logfile, "Testing socket options");

	if ( ($unixsocket && $unixport) || (!($unixsocket) && !($unixport)) ) {
		print "\n\tERROR\tOnly one option can be used!\n";
		print "\tSuggested (beacuse of speed) is usage UNIX socket -S \n\n";
		exit 1;
	}

	if ($unixsocket) {
		print "	Daemon listening at UNIX socket $unixsocket\n" if $versbose;
		addlog($logfile, "Deamon listening at UNIX socket $unixsocket");
	} else {
		print "	Daemon listening at TCP/IP socket *:$unixport\n" if $verbose;
		#
		addlog($logfile, "Daemon listening at TCP/IP socket *:$unixport");
	}

	if ( -e $filepid ) {
		print "\n\tERROR\t PID file $filepid already exists\n\n";
		addlog($logfile, "Can not use PID file $filepid, already exists.");
		exit 1;
	}

	if ( $unixsocket ) {
		print "	Creating UNIX socket\n" if $verbose;
		$socket = FCGI::OpenSocket( $unixsocket, 10 );
		if ( !$socket) {
			print "	Couldn't create socket\n";
			addlog($logfile, "Couldn't create socket");
			exit 1;
		}
		print "	Using UNIX socket $unixsocket\n" if $verbose;
	} else {
		print "	Creating TCP/IP socket\n" if $verbose;
		$portnumber = ":".$unixport;
		$socket = FCGI::OpenSocket( $unixport, 10 );
		if ( !$socket ) {
			print "	Couldn't create socket\n";
			addlog($logfile, "Couldn't create socket");
			exit 1;
		}
		print " Using port $unixport\n" if $verbose;
	}
	addlog($logfile, "Socket created");

	if ( ! $filepid ) {
		print "\n\tERROR\t PID file must declared\n"
			. "\tuse $0 with option -pid filename\n\n";
		exit 1;
	}
	print "	Using PID file $filepid\n" if $verbose;
	addlog($logfile, "Using PID file $filepid");

	my $pidnumber = $;
	$pidnumber > io($filepid);
	print " PID number $\n" if $verbose;
	addlog($logfile, "PID number $pidnumber");
	
}

sub addzero {
	my ($date) = shift;
	if ($date < 10) {
		return "0$date";
	}
       return $date;
}

sub logformat {
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$iddst) = localtime(time);
	my $datestring;
	$year += 1900;
	$mon++;
	$mon  = addzero($mon);
	$mday = addzero($mday);
	$min  = addzero($min);
	$datestring = "$year-$mon-$mday $hour:$min";
	return($datestring);
}

sub addlog {
	my ($log_file, $log_message) = @_;
	my $curr_time = logformat();
	my $write_message = "[$curr_time]   $log_message";
	$write_message >> io($log_file);
	"\n" >> io($log_file);
}

sub printerror {
	my $message = @_;
	print "\n	Nginx FastCGI\tERROR\n"
		. "\t $message\n\n";
	exit 1;
}

sub usage {
	print "\n	Nginx FastCGI \n"
		. "\n\tusage: $0 [-h] -S string -P int\n"
		. "\n\t-h\t\t: this (help) message"
		. "\n\t-S path\t\t: path for UNIX socket"
		. "\n\t-P port\t\t: port number"
		. "\n\t-p file\t\t: path for pid file"
		. "\n\t-l file\t\t: path for logfile"
		. "\n\n\texample: $0 -S /var/run/nginx-perl_cgi.sock -l /var/log/nginx/nginx-cfgi.log -pid /var/run/nginx-fcgi.pid\n\n";
	exit 1;
}


init;
#
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; }; eval q{exit}; 
if ($@) { 
	exit unless $@ =~ /^fakeexit/; 
} ;

# fork part
my $pid = fork();

if( $pid == 0 ) {
	&main;
	exit 0;
}

print " Forking worker process with PID $pid\n" if $verbose;
addlog($logfile, "Forking worker process with PID $pid");
print " Update PID file $filepid\n" if $verbose;
addlog($logfile, "Update PID file $filepid");
$pid > io($filepid);
print "	Worker process running.\n" if $verbose;
addlog ($logfile, "Parent process $ is exiting");
exit 0;

sub main {
	$request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket );
	if ($request) { request_loop()};
		FCGI::CloseSocket( $socket );
}

sub request_loop {
	while( $request->Accept() >= 0 ) {
		# processing any STDIN input from WebServer (for CGI-POST actions)
		$stdin_passthrough = '';
		$req_len = 0 + $req_params{'CONTENT_LENGTH'};
		if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){
			while ($req_len) {
				$stdin_passthrough .= getc(STDIN);
				$req_len--;	
			}
		}

		# running the cgi app
		if ( (-x $req_params{SCRIPT_FILENAME}) && 
			(-r $req_params{SCRIPT_FILENAME})
		){
			foreach $key ( keys %req_params){
				$ENV{$key} = $req_params{$key};
			}
			if ( $verbose ) {
				addlog($logfile, "running $req_params{SCRIPT_FILENAME}");
			} else {
				addlog($logfile, "running $req_params{SCRIPT_FILENAME} fail");
			}
			# http://perldoc.perl.org/perlipc.html#Safe-Pipe-Opens
			#
			open $cgi_app, '-|', $req_params{SCRIPT_FILENAME}, $stdin_passthrough or print("Content-type: text/plain\r\n\r\n"); print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n"; # addlog($logfile, "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !");
			
			if ($cgi_app) { 
				addlog($logfile, "$cgi_app is ok.\n");
				print <$cgi_app>; 
				close $cgi_app; 
			} else {
				addlog($logfile, "$cgi_app is not ok!\n");
			}
		} else {
			print("Content-type: text/plain\r\n\r\n");
			print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process. File Again!!\n";
			addlog($logfile, "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.");
		}
	}
}