diff --git a/ng/monitorix b/ng/monitorix new file mode 100755 index 0000000..796d076 --- /dev/null +++ b/ng/monitorix @@ -0,0 +1,534 @@ +#!/usr/bin/env perl +# +# Monitorix - A lightweight system monitoring tool. +# +# Copyright (C) 2005-2012 by Jordi Sanfeliu +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +require 5.006; + +use warnings; +use strict; +use RRDs; +use POSIX; +use Config::General; +use File::Basename; +use LWP::UserAgent; +use XML::Simple; +use Socket; +use DBI; +use Getopt::Std; +use Cwd 'abs_path'; +use locale; +use Data::Dumper; + +# Force a standard locale +$ENV{LANG} = ""; +setlocale(LC_TIME, "C"); + +$SIG{'INT' } = 'INT_handler'; +$SIG{'ABRT'} = 'INT_handler'; +$SIG{'QUIT'} = 'INT_handler'; +$SIG{'TRAP'} = 'INT_handler'; +$SIG{'STOP'} = 'INT_handler'; +$SIG{'TERM'} = 'INT_handler'; +$SIG{'CHLD'} = 'CHLD_handler'; +$SIG{'HUP' } = 'HUP_handler'; +$SIG{'ALRM'} = 'ALRM_handler'; + +use constant VERSION => "2.9.901"; +use constant RELDATE => "06-Nov-2012"; + +my @suppsys = ("Linux", "FreeBSD", "OpenBSD", "NetBSD"); +my %config; +my @graphs; +my @graphs_debug; +my $os; +my $kernel; +our %options; + +sub INT_handler { + my ($signal) = @_; + + logger("SIG$signal caught."); + flush_accounting_rules(); + logger("Exiting."); + exit(0); +} + +sub CHLD_handler { + my $pid = waitpid(-1, WNOHANG); +} + +sub HUP_handler { + my ($signal) = @_; + my $myself = (caller(0))[3]; + + logger("SIG$signal caught."); + close(STDOUT); + close(STDERR); + unless(open(STDOUT, ">> $config{log_file}")) { + logger("Can't write to LOG: $!"); + } + unless(open(STDERR, ">> $config{log_file}")) { # >>&STDOUT XXX + logger("Can't write to LOG: $!"); + } + logger("$myself: reopening log file."); +} + +sub ALRM_handler { + my $myself = (caller(0))[3]; + my ($sec, $min, $hour, $mday) = localtime(time); + + if($sec == 0) { + foreach my $g (@graphs) { + my ($t) = split('_', $g); + logger("$myself: calling $g()") unless !$options{d}; + if(!grep {trim($_) eq $t} (@graphs_debug)) { + undef($t); + } + eval {&$g($t);}; + if($@) { + logger("$g(): $@"); + } + } + if(lc($config{graph_enable}->{pc}) eq "y" && lc($config{pc_enable_monthly_reports}) eq "y") { + if($min == 0 && $hour == 0) { + get_counters(); + if($mday == 1) { + send_reports(); + } + } + } + } + alarm(1); +} + +sub logger { + my ($msg) = @_; + + $msg = localtime() . " - " . $msg; + print("$msg\n"); +} + +sub daemonize { + if(fork) { + exit(0); # parent exits + } + + setsid(); + foreach(0 .. (sysconf(&POSIX::_SC_OPEN_MAX) || 1024)) { + close($_); + } + unless(chdir("/")) { + die("Can't chdir to /: $!"); + } + unless(umask(022)) { + die("Unable to umask 022: $!"); + } +# unless(open(STDIN, "< /dev/null")) { +# die("Can't read /dev/null: $!"); +# } + unless(open(STDOUT, ">> $config{log_file}")) { + die("Can't write to LOG: $!"); + } + unless(open(STDERR, ">> $config{log_file}")) { # >>&STDOUT XXX + die("Can't write to LOG: $!"); + } +} + +sub usage { + print(STDERR << "EOF"); +Usage: monitorix -c configfile [-p pidfile] [-d none | graph[,graph] | all ] [-v] + +EOF + exit(1); +} + +sub trim { + my $str = shift; + + $str =~ s/^\s+//; + $str =~ s/\s+$//; + return $str; +} + +sub create_index { + my $myself = (caller(0))[3]; + + my $n; + my $gname; + my $theme = $config{theme}; + my $bgcolor; + my $table_back_color; + my $title_back_color; + my $title_fore_color; + + if($theme eq "black") { + $bgcolor = $config{$theme}->{main_bg}; + $table_back_color = $config{$theme}->{graph_bg}; + $title_back_color = $config{$theme}->{title_bg}; + $title_fore_color = $config{$theme}->{title_fg}; + } elsif(!$theme || $theme eq "white") { + $bgcolor = "#ffffff"; + $table_back_color = "#CCCCCC"; + $title_back_color = "#777777"; + $title_fore_color = "#CCCC00"; + } else { + logger("$myself: ERROR: invalid value in 'theme' option") unless !$options{d}; + } + + if(!open(OUT, "> $config{base_dir}/index.html")) { + die "unable to create '${config{base_dir}}index.html'. $!"; + } + print(OUT < + + + $config{title} + + + +
+

+
+ + + + + + + + +
+ +
+

v@{[VERSION]}

+
+

+

+ + + + + + +EOF + + print(OUT " \n"); + + + + print(OUT " \n"); + + + print(OUT < +
+ + Hostname  + + + + Graph  + +
\n"); + print(OUT " \n"); + print(OUT " \n"); + print(OUT " \n"); + print(OUT "
+

+ + + + + + + +
+ + Daily  + + + Weekly  + + + Monthly  + + + Yearly  +
+

+ + +

+
+
+ + +EOF + close(OUT); +} + +sub flush_accounting_rules { + my $num = 0; + + # flushes out any Monitorix iptables/ipfw rules + if($os eq "Linux") { + logger("Flushing out iptables rules.") unless !$options{d}; + if(open(IN, "iptables -nxvL INPUT --line-numbers |")) { + my @rules; + my @names; + while() { + my ($rule, undef, undef, $name) = split(' ', $_); + if($name =~ /monitorix_IN/ || /monitorix_nginx_IN/) { + push(@rules, $rule); + push(@names, $name); + } + } + close(IN); + @rules = reverse(@rules); + foreach(@rules) { + system("iptables -D INPUT $_"); + $num++; + } + foreach(@names) { + system("iptables -X $_"); + } + } + if(open(IN, "iptables -nxvL OUTPUT --line-numbers |")) { + my @rules; + my @names; + while() { + my ($rule, undef, undef, $name) = split(' ', $_); + if($name =~ /monitorix_OUT/ || /monitorix_nginx_OUT/) { + push(@rules, $rule); + push(@names, $name); + } + } + close(IN); + @rules = reverse(@rules); + foreach(@rules) { + system("iptables -D OUTPUT $_"); + $num++; + } + foreach(@names) { + system("iptables -X $_"); + } + } + logger("$num iptables rules have been flushed.") unless !$options{d}; + } + if($os eq "FreeBSD" || $os eq "OpenBSD") { + logger("Flushing out ipfw rules.") unless !$options{d}; + system("ipfw delete $config{port_rule} 2>/dev/null"); + system("ipfw delete $config{nginx_rule} 2>/dev/null"); + } +} + + +# Main +# ---------------------------------------------------------------------------- +getopts("d:vc:p:", \%options) || usage(); + +if($options{v}) { + print("Monitorix version " . VERSION . " (" . RELDATE . ")\n"); + print("by Jordi Sanfeliu \n"); + print("http://www.monitorix.org/\n\n"); + exit(0); +} +if(!$options{c}) { + usage(); + exit(1); +} +$options{c} = abs_path($options{c}) unless $^V lt 5.6.2; +if(!stat($options{c})) { + die("can't open file '$options{c}'.\n"); +} + +# get the current OS and kernel version and check its support +my $release; +($os, undef, $release) = uname(); +my ($major, $minor) = split('\.', $release); +$kernel = $major . "." . $minor; +if(!grep {$_ eq $os} @suppsys) { + die("FATAL: your operating system ($os) is not supported.\n"); +} + +if(grep {$_ eq $os} ("FreeBSD", "OpenBSD", "NetBSD")) { + $SIG{'CHLD'} = 'DEFAULT'; +} + +# load configuration file +my $conf = new Config::General( + -ConfigFile => $options{c}, + ); +%config = $conf->getall; + +$0 = sprintf("%s %s%s%s%s", + $^V lt 5.6.2 ? "monitorix" : abs_path($0), + $options{c} ? "-c $options{c}" : "", + $options{p} ? " -p $options{p}" : "", + $options{d} ? " -d $options{d}" : "", + $options{v} ? " -v" : ""); + +#daemonize(); +logger("Starting Monitorix version " . VERSION . " (pid $$)."); + +if($options{p}) { + $options{p} = abs_path($options{p}); + open(OUT, "> $options{p}") + || die("could not open '$options{p}' for writing"); + print(OUT "$$"); + close(OUT); +} + +# change to a safety directory +unless(chdir("/tmp")) { + logger("can't chdir to /tmp: $!"); + unless(chdir("/lost+found")) { + die("Can't chdir to /lost+found: $!"); + } +} + +if($options{d}) { + if($options{d} ne "none" && $options{d} ne "all") { + @graphs_debug = split(',', $options{d}); + foreach my $t (@graphs_debug) { + if(!grep {trim($_) eq $t} (split(',', $config{graph_name}))) { + die("Invalid debug key '$t'"); + } + } + } + logger("Entering in debug mode."); + logger("Changed process name to '$0'."); +} + +# save the path of the configuration file +if(open(OUT, "> " . $config{base_dir} . "/cgi-bin/monitorix.conf.path")) { + print(OUT "$options{c}\n"); + close(OUT); +} else { + logger("Unable to create the file '$config{base_dir}/cgi-bin/monitorix.conf.path'."); +} + +logger("Initializing graphs.") unless !$options{d}; +flush_accounting_rules(); + +foreach (split(',', $config{graph_name})) { + my $g = trim($_); + if(lc($config{graph_enable}->{$g}) eq "y") { + my $func = $g . "_init"; + eval {&$func();}; + logger("WARNING: unexpected errors in function $func()") if($@); + } +} + +if(!scalar(@graphs)) { + logger("nothing to do, exiting."); + exit(0); +} + +logger("Generating the 'index.html' file.") unless !$options{d}; +create_index(); +logger("Ok, done.") unless !$options{d}; + +alarm(1); +while(1) { + pause(); +}