diff -Nru monitorix-3.10.1/Changes monitorix-3.11.0/Changes --- monitorix-3.10.1/Changes 2018-03-15 07:03:23.000000000 +0000 +++ monitorix-3.11.0/Changes 2019-03-14 13:59:00.000000000 +0000 @@ -1,7 +1,46 @@ -3.10.1 - 15-Mar-2018 +3.11.0 - 14-Mar-2019 ==================== +- Added a complete graph to support external ambient sensors ('ambsens.pm'). + (suggested by Zdenko Dolar, zdenko.dolar AT gmail.com) +- Added an advice in monitorix.conf(5) as a reminder that some default values + are overwritten in the configuration files on certain systems. + (suggested by Sander Bos) +- Changed the way how the Used value in Memory graph is calculated. [#204] +- Changed the alert in 'system.pm' to use the minimum value between the second + and the third load averages to obtain a more symmetric curve and a sooner + cancellation of the alert. + (suggested by Michael Tosch) +- Added two new graphs (operations and bandwidth) for each pool in 'zfs.pm' to + show iostats. [#190] +- Removed the 777 permissions bits in docs/monitorix.spec and Makefile for the + 'imgs/' directory. At the same time, when HTTP built-in is enabled, forced to + setup the owner, group and permission bits to that directory every time + Monitorix is started. + (thanks to Sander Bos for pointing this out) +- Added support to include the 'ss' command in 'netstat.pm'. [#196] +- Added to restart the HTTP built-in every time Monitorix receives the SIGHUP + signal. This should fix a truncation in the recently rotated logfile. +- Added in 'du.pm' the ability to count files in every directory defined. [#112] +- Added the ability to show all graphs of a single server in Multihost mode, + instead of showing only the System Load graph. [#216] +- Added the ability to show all graphs of all remote servers in Multihost mode, + instead of showing only the System Load graphs. [#216] +- Added the new option 'default_option_when_all' in Multihost mode. [#216] +- Added in 'ipmi.pm' the ability to save negative values. [#218] +- Added the ability in the alerts of 'gensens.pm' to specify when the alert will + be triggered 'above' or 'below' the threshold. [#221] +- Added the ability in the alerts of 'ambsens.pm' to specify when the alert will + be triggered 'above' or 'below' the threshold. [#221] +- Drop entropy support for FreeBSD in 'system.pm'. [#226] +- Added Exim support in 'mail.pm'. [#96] +- Added an autocheck to control the responsiveness of the HTTP built-in server, + and in case of no response then restart it. This is controlled by a new option + called 'autocheck_responsiveness' which by default is enabled. This should fix + these annoying hangups in the HTTP built-in server. - Fixed a bad memory scaling in *BSD systems. - Fixed in 'process.pm' to fully honour the option 'netstats_in_bps'. +- Fixed to force Monitorix to be started at the end of boot in systemd-based + systems. This should fix a problem with 'traffacct.pm' and iptables. - Fixed the missing declaration of 'allvalues' in 'gensens.pm' which prevented graphs generation if 'show_gaps' option was enabled. - Fixed to correctly represent the values in text mode in 'ipmi.pm'. @@ -10,14 +49,21 @@ - Fixed a missing gap colouring in some zoomed graphs of 'system.pm'. - Fixed to save missing values as 'unknown' in 'apcupsd.pm'. [#201] - Fixed a XSS vulnerability in CGI variables. [#203] - (thanks to Sebastian Gilon from http://testarmy.com/, who pointed this out) + (thanks to Sebastian Gilon from http://testarmy.com/, who pointed this out) - Fixed to check if setgid() and setuid() functions were successful before starting the HTTP built-in. - (thanks to Sander Bos for pointing this out) + (thanks to Sander Bos for pointing this out) - Fixed to disable 'echo' when typing the password in './htpasswd.pl'. - (thanks to Sander Bos for pointing this out) + (thanks to Sander Bos for pointing this out) - Fixed to set permissions 0600 to log files. - (thanks to Sander Bos for pointing this out) + (thanks to Sander Bos for pointing this out) +- Fixed in 'zfs.pm' the way how is collected pool's data. + (thanks to Derek Dongray, derek AT valedon.co.uk) +- Fixed in HTTP built-in to force authentication (when enabled) always, even on + non-existing pages. + (thanks to Sander Bos for pointing this out) +- Fixed to load correctly the file 'monitorix.conf.path' when 'monitorix.cgi' is + called from the command line outside of its own directory. [#218] 3.10.0 - 25-Sep-2017 diff -Nru monitorix-3.10.1/debian/changelog monitorix-3.11.0/debian/changelog --- monitorix-3.10.1/debian/changelog 2019-01-10 22:59:45.000000000 +0000 +++ monitorix-3.11.0/debian/changelog 2019-03-14 17:39:51.000000000 +0000 @@ -1,3 +1,16 @@ +monitorix (3.11.0-1) unstable; urgency=medium + + * New upstream version 3.11.0 + * Rediff patches + + -- Baptiste BEAUPLAT Thu, 14 Mar 2019 18:39:51 +0100 + +monitorix (3.10.1-2) unstable; urgency=medium + + * debian-compat to 12. Remove debian/compat + + -- Baptiste BEAUPLAT Thu, 07 Mar 2019 18:22:52 +0100 + monitorix (3.10.1-1) unstable; urgency=medium * Initial release (Closes: #733479) diff -Nru monitorix-3.10.1/debian/compat monitorix-3.11.0/debian/compat --- monitorix-3.10.1/debian/compat 2019-01-10 22:59:45.000000000 +0000 +++ monitorix-3.11.0/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -11 diff -Nru monitorix-3.10.1/debian/control monitorix-3.11.0/debian/control --- monitorix-3.10.1/debian/control 2019-01-10 22:59:45.000000000 +0000 +++ monitorix-3.11.0/debian/control 2019-03-14 17:39:51.000000000 +0000 @@ -2,7 +2,7 @@ Section: utils Priority: optional Maintainer: Baptiste BEAUPLAT -Build-Depends: debhelper (>= 11) +Build-Depends: debhelper-compat (= 12) Standards-Version: 4.3.0 Homepage: https://www.monitorix.org Vcs-Browser: https://salsa.debian.org/debian/monitorix diff -Nru monitorix-3.10.1/debian/patches/0001-fix-perl-interpreter.patch monitorix-3.11.0/debian/patches/0001-fix-perl-interpreter.patch --- monitorix-3.10.1/debian/patches/0001-fix-perl-interpreter.patch 2019-01-10 22:59:45.000000000 +0000 +++ monitorix-3.11.0/debian/patches/0001-fix-perl-interpreter.patch 2019-03-14 17:39:51.000000000 +0000 @@ -19,7 +19,7 @@ # Usage: htpasswd.pl [encrypted_password] # diff --git a/monitorix b/monitorix -index 2453911..8f23edf 100755 +index 788dfab..660942b 100755 --- a/monitorix +++ b/monitorix @@ -1,4 +1,4 @@ @@ -29,7 +29,7 @@ # Monitorix - A lightweight system monitoring tool. # diff --git a/monitorix.cgi b/monitorix.cgi -index 4ba7ec7..915e42e 100755 +index 27697b1..ae7f5af 100755 --- a/monitorix.cgi +++ b/monitorix.cgi @@ -1,4 +1,4 @@ diff -Nru monitorix-3.10.1/debian/patches/0002-fix-spelling-mistakes.patch monitorix-3.11.0/debian/patches/0002-fix-spelling-mistakes.patch --- monitorix-3.10.1/debian/patches/0002-fix-spelling-mistakes.patch 2019-01-10 22:59:45.000000000 +0000 +++ monitorix-3.11.0/debian/patches/0002-fix-spelling-mistakes.patch 2019-03-14 17:39:51.000000000 +0000 @@ -8,10 +8,10 @@ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/man/man5/monitorix.conf.5 b/man/man5/monitorix.conf.5 -index 44acc37..476b5c3 100644 +index ab8d369..6770306 100644 --- a/man/man5/monitorix.conf.5 +++ b/man/man5/monitorix.conf.5 -@@ -184,7 +184,7 @@ Default value: \fIn\fP +@@ -186,7 +186,7 @@ Default value: \fIn\fP .P .BI url_prefix_proxy .RS @@ -20,7 +20,7 @@ .P An example would be: \fIhttp://myexternalwebsite.com\fP .P -@@ -258,14 +258,14 @@ Default value: \fI/var/lib/monitorix/\fP +@@ -260,14 +260,14 @@ Default value: \fI/var/lib/monitorix/\fP .P .BI base_url .RS @@ -37,7 +37,7 @@ .P Default value: \fI/monitorix-cgi\fP .RE -@@ -1221,7 +1221,7 @@ Default value: \fI/path/to/script.sh\fP +@@ -1337,7 +1337,7 @@ Default value: \fI/path/to/script.sh\fP .RS During the init stage this graph verifies that every defined device name does exist in the system. If not, then the graph disables itself. .P @@ -46,7 +46,7 @@ .P Default value: \fIn\fP .RE -@@ -1407,7 +1407,7 @@ Default value: \fI2\fP +@@ -1544,7 +1544,7 @@ Default value: \fI2\fP .P .BI extra_args .RS @@ -55,7 +55,7 @@ .P .RS extra_args = "-x" -@@ -2787,7 +2787,7 @@ An example would be: +@@ -2949,7 +2949,7 @@ An example would be: .RE .RE .SS Automatic email reports (emailreports) @@ -65,7 +65,7 @@ .BI enabled .RS diff --git a/man/man8/monitorix.8 b/man/man8/monitorix.8 -index b7aaab4..93e2c08 100644 +index a1ce76f..0959da2 100644 --- a/man/man8/monitorix.8 +++ b/man/man8/monitorix.8 @@ -35,7 +35,7 @@ For a reference of all graph names check the option \fBgraph_name\fP in the \fIm diff -Nru monitorix-3.10.1/docs/monitorix-alert.sh monitorix-3.11.0/docs/monitorix-alert.sh --- monitorix-3.10.1/docs/monitorix-alert.sh 2013-03-15 07:25:19.000000000 +0000 +++ monitorix-3.11.0/docs/monitorix-alert.sh 2019-02-08 08:41:35.000000000 +0000 @@ -5,7 +5,7 @@ MAILTO="root@localhost" -if [ $# != 3 ] ; then +if [ $# != 3 ] && [ $# != 4 ] ; then echo "$0: Wrong number of arguments." exit 1 fi @@ -13,12 +13,13 @@ ALERT_TIMEINTVL=$1 ALERT_THRESHOLD=$2 current_value=$3 +ALERT_WHEN=$4 ( cat << EOF Message from hostname '$HOSTNAME'. -This system is reaching/exceeding the defined threshold value ($ALERT_THRESHOLD) during the last '$ALERT_TIMEINTVL' seconds. +This system is reaching/exceeding ($ALERT_WHEN) the defined threshold value ($ALERT_THRESHOLD) during the last '$ALERT_TIMEINTVL' seconds. The current value is: $current_value diff -Nru monitorix-3.10.1/docs/monitorix.nanorc monitorix-3.11.0/docs/monitorix.nanorc --- monitorix-3.10.1/docs/monitorix.nanorc 1970-01-01 00:00:00.000000000 +0000 +++ monitorix-3.11.0/docs/monitorix.nanorc 2018-02-05 14:14:42.000000000 +0000 @@ -0,0 +1,14 @@ +# The following is the syntax for nano(1) text editor, which should make the +# configuration process easier. + +syntax "monitorix" "monitorix.conf$" +color red "=*[[:space:]]n$" +color brightgreen "=*[[:space:]]y$" +color yellow "[A-Za-z0-9\.]*@[A-Za-z0-9\.]*" +color brightyellow "=" +color brightwhite "[0-9]" +icolor magenta "^[[:space:]]*[.A-Z_0-9]*" +color cyan start="<" end=">" +color green "^#.*" +icolor brightgreen "^#.**[[:space:]]*--" + diff -Nru monitorix-3.10.1/docs/monitorix.service monitorix-3.11.0/docs/monitorix.service --- monitorix-3.10.1/docs/monitorix.service 2014-03-25 06:10:03.000000000 +0000 +++ monitorix-3.11.0/docs/monitorix.service 2017-10-30 07:54:05.000000000 +0000 @@ -2,6 +2,7 @@ Description=Monitorix Documentation=man:monitorix(8) Wants=local-fs.target +After=multi-user.target [Service] Type=forking diff -Nru monitorix-3.10.1/docs/monitorix.spec monitorix-3.11.0/docs/monitorix.spec --- monitorix-3.10.1/docs/monitorix.spec 2018-03-15 07:05:49.000000000 +0000 +++ monitorix-3.11.0/docs/monitorix.spec 2019-03-14 13:55:44.000000000 +0000 @@ -3,7 +3,7 @@ Summary: Monitorix is a system monitoring tool Name: monitorix -Version: 3.10.1 +Version: 3.11.0 Release: 1%{?dist} License: GPL Group: Applications/System @@ -85,7 +85,7 @@ %{_localstatedir}/lib/monitorix/www/logo_bot.png %{_localstatedir}/lib/monitorix/www/monitorixico.png %{_localstatedir}/lib/monitorix/www/cgi/monitorix.cgi -%attr(777,root,root) %{_localstatedir}/lib/monitorix/www/imgs +%attr(755,root,root) %{_localstatedir}/lib/monitorix/www/imgs %attr(755,root,root) %{_localstatedir}/lib/monitorix/usage %{_localstatedir}/lib/monitorix/reports/*.html %doc %{_mandir}/man5/monitorix.conf.5.gz diff -Nru monitorix-3.10.1/lib/ambsens.pm monitorix-3.11.0/lib/ambsens.pm --- monitorix-3.10.1/lib/ambsens.pm 1970-01-01 00:00:00.000000000 +0000 +++ monitorix-3.11.0/lib/ambsens.pm 2019-03-14 13:54:01.000000000 +0000 @@ -0,0 +1,495 @@ +# +# Monitorix - A lightweight system monitoring tool. +# +# Copyright (C) 2005-2019 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. +# + +package ambsens; + +use strict; +use warnings; +use Monitorix; +use RRDs; +use POSIX qw(strftime); +use Exporter 'import'; +our @EXPORT = qw(ambsens_init ambsens_update ambsens_cgi); + +sub ambsens_init { + my $myself = (caller(0))[3]; + my ($package, $config, $debug) = @_; + my $rrd = $config->{base_lib} . $package . ".rrd"; + my $ambsens = $config->{ambsens}; + + my $info; + my @ds; + my @rra; + my @tmp; + my $n; + + my @average; + my @min; + my @max; + my @last; + + if(-e $rrd) { + $info = RRDs::info($rrd); + for my $key (keys %$info) { + if(index($key, 'ds[') == 0) { + if(index($key, '.type') != -1) { + push(@ds, substr($key, 3, index($key, ']') - 3)); + } + } + if(index($key, 'rra[') == 0) { + if(index($key, '.rows') != -1) { + push(@rra, substr($key, 4, index($key, ']') - 4)); + } + } + } + if(scalar(@ds) / 9 != scalar(my @fl = split(',', $ambsens->{list}))) { + logger("$myself: Detected size mismatch between 'list' (" . scalar(my @fl = split(',', $ambsens->{list})) . ") and $rrd (" . scalar(@ds) / 9 . "). Resizing it accordingly. All historical data will be lost. Backup file created."); + rename($rrd, "$rrd.bak"); + } + if(scalar(@rra) < 12 + (4 * $config->{max_historic_years})) { + logger("$myself: Detected size mismatch between 'max_historic_years' (" . $config->{max_historic_years} . ") and $rrd (" . ((scalar(@rra) -12) / 4) . "). Resizing it accordingly. All historical data will be lost. Backup file created."); + rename($rrd, "$rrd.bak"); + } + } + + if(!(-e $rrd)) { + logger("Creating '$rrd' file."); + for($n = 1; $n <= $config->{max_historic_years}; $n++) { + push(@average, "RRA:AVERAGE:0.5:1440:" . (365 * $n)); + push(@min, "RRA:MIN:0.5:1440:" . (365 * $n)); + push(@max, "RRA:MAX:0.5:1440:" . (365 * $n)); + push(@last, "RRA:LAST:0.5:1440:" . (365 * $n)); + } + for($n = 0; $n < scalar(my @sl = split(',', $ambsens->{list})); $n++) { + push(@tmp, "DS:ambsens" . $n . "_s1:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s2:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s3:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s4:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s5:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s6:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s7:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s8:GAUGE:120:0:U"); + push(@tmp, "DS:ambsens" . $n . "_s9:GAUGE:120:0:U"); + } + eval { + RRDs::create($rrd, + "--step=60", + @tmp, + "RRA:AVERAGE:0.5:1:1440", + "RRA:AVERAGE:0.5:30:336", + "RRA:AVERAGE:0.5:60:744", + @average, + "RRA:MIN:0.5:1:1440", + "RRA:MIN:0.5:30:336", + "RRA:MIN:0.5:60:744", + @min, + "RRA:MAX:0.5:1:1440", + "RRA:MAX:0.5:30:336", + "RRA:MAX:0.5:60:744", + @max, + "RRA:LAST:0.5:1:1440", + "RRA:LAST:0.5:30:336", + "RRA:LAST:0.5:60:744", + @last, + ); + }; + my $err = RRDs::error; + if($@ || $err) { + logger("$@") unless !$@; + if($err) { + logger("ERROR: while creating $rrd: $err"); + if($err eq "RRDs::error") { + logger("... is the RRDtool Perl package installed?"); + } + } + return; + } + } + + $config->{ambsens_hist_alerts} = (); + push(@{$config->{func_update}}, $package); + logger("$myself: Ok") if $debug; +} + +sub ambsens_update { + my $myself = (caller(0))[3]; + my ($package, $config, $debug) = @_; + my $rrd = $config->{base_lib} . $package . ".rrd"; + my $ambsens = $config->{ambsens}; + + my @sens; + + my $n; + my $str; + my $rrdata = "N"; + + my $e = 0; + while($e < scalar(my @sl = split(',', $ambsens->{list}))) { + my $e2 = 1; + foreach my $dl (split(',', $ambsens->{desc}->{$e})) { + my $str = trim($dl); + my $script = trim($ambsens->{cmd}->{$str}); + + if($script) { + if(-x $script) { + my $val = `$script`; + chomp($val); + $sens[$e][$e2] = $val; + + # check alerts for each sensor defined + my @al = split(',', $ambsens->{alerts}->{$str} || ""); + if(scalar(@al)) { + my $timeintvl = trim($al[0]); + my $threshold = trim($al[1]); + my $script = trim($al[2]); + my $when = lc(trim($al[3] || "")); + my @range = split('-', $threshold); + $when = "above" if !$when; # 'above' is the default + $threshold = 0 if !$threshold; + if(scalar(@range) == 1) { + if($when eq "above" && $val < $threshold) { + $config->{ambsens_hist_alerts}->{$str} = 0; + } elsif($when eq "below" && $val > $threshold) { + $config->{ambsens_hist_alerts}->{$str} = 0; + } else { + if($when eq "above" || $when eq "below") { + if(!$config->{ambsens_hist_alerts}->{$str}) { + $config->{ambsens_hist_alerts}->{$str} = time; + } + if($config->{ambsens_hist_alerts}->{$str} > 0 && (time - $config->{ambsens_hist_alerts}->{$str}) >= $timeintvl) { + if(-x $script) { + logger("$myself: alert on Ambient Sensor ($str): executing script '$script'."); + system($script . " " . $timeintvl . " " . $threshold . " " . $val); + } else { + logger("$myself: ERROR: script '$script' doesn't exist or don't has execution permissions."); + } + $config->{ambsens_hist_alerts}->{$str} = time; + } + } else { + logger("$myself: ERROR: invalid when value '$when'"); + } + } + } elsif(scalar(@range) == 2) { + logger("$myself: range values are not supported yet."); + } else { + logger("$myself: ERROR: invalid threshold value '$threshold'"); + } + } + } else { + logger("$myself: ERROR: script '$script' doesn't exist or don't has execution permissions."); + } + } + $e2++; + } + $e++; + } + + $e = 0; + while($e < scalar(my @sl = split(',', $ambsens->{list}))) { + for($n = 1; $n <= 9; $n++) { + $sens[$e][$n] = 0 unless defined $sens[$e][$n]; + $rrdata .= ":" . $sens[$e][$n]; + } + $e++; + } + print "$rrdata\n"; + + RRDs::update($rrd, $rrdata); + logger("$myself: $rrdata") if $debug; + my $err = RRDs::error; + logger("ERROR: while updating $rrd: $err") if $err; +} + +sub ambsens_cgi { + my ($package, $config, $cgi) = @_; + my @output; + + my $ambsens = $config->{ambsens}; + my @rigid = split(',', ($ambsens->{rigid} || "")); + my @limit = split(',', ($ambsens->{limit} || "")); + my $tf = $cgi->{tf}; + my $colors = $cgi->{colors}; + my $graph = $cgi->{graph}; + my $silent = $cgi->{silent}; + my $zoom = "--zoom=" . $config->{global_zoom}; + my %rrd = ( + 'new' => \&RRDs::graphv, + 'old' => \&RRDs::graph, + ); + my $version = "new"; + my $pic; + my $picz; + my $picz_width; + my $picz_height; + + my $u = ""; + my $width; + my $height; + my @riglim; + my @IMG; + my @IMGz; + my @tmp; + my @tmpz; + my @CDEF; + my $n; + my $n2; + my $str; + my $err; + my @LC = ( + "#4444EE", + "#EEEE44", + "#44EEEE", + "#EE44EE", + "#888888", + "#E29136", + "#44EE44", + "#448844", + "#EE4444", + ); + + $version = "old" if $RRDs::VERSION < 1.3; + my $rrd = $config->{base_lib} . $package . ".rrd"; + my $title = $config->{graph_title}->{$package}; + my $IMG_DIR = $config->{base_dir} . "/" . $config->{imgs_dir}; + my $imgfmt_uc = uc($config->{image_format}); + my $imgfmt_lc = lc($config->{image_format}); + + $title = !$silent ? $title : ""; + + # text mode + # + if(lc($config->{iface_mode}) eq "text") { + if($title) { + push(@output, main::graph_header($title, 2)); + push(@output, " \n"); + push(@output, " \n"); + } + my (undef, undef, undef, $data) = RRDs::fetch("$rrd", + "--start=-$tf->{nwhen}$tf->{twhen}", + "AVERAGE", + "-r $tf->{res}"); + $err = RRDs::error; + push(@output, "ERROR: while fetching $rrd: $err\n") if $err; + my $line1; + my $line2; + my $line3; + push(@output, "
\n");
+		push(@output, "    ");
+		for($n = 0; $n < scalar(my @sl = split(',', $ambsens->{list})); $n++) {
+			$line1 = "";
+			foreach my $dl (split(',', $ambsens->{desc}->{$n})) {
+				$dl = trim($dl);
+				$str = $ambsens->{map}->{$dl} || $dl;
+				$str = sprintf("%7s", substr($str, 0, 5));
+				$line1 .= "        ";
+				$line2 .= sprintf(" %7s", $str);
+				$line3 .= "--------";
+			}
+			if($line1) {
+				my $i = length($line1);
+				push(@output, sprintf(sprintf("%${i}s", sprintf("%s", trim($sl[$n])))));
+			}
+		}
+		push(@output, "\n");
+		push(@output, "Time$line2\n");
+		push(@output, "----$line3 \n");
+		my $line;
+		my $time;
+		my $n2;
+		my $n3;
+		my $from;
+		my $to;
+		for($n = 0, $time = $tf->{tb}; $n < ($tf->{tb} * $tf->{ts}); $n++) {
+			$line = @$data[$n];
+			$time = $time - (1 / $tf->{ts});
+			push(@output, sprintf(" %2d$tf->{tc} ", $time));
+			for($n2 = 0; $n2 < scalar(my @sl = split(',', $ambsens->{list})); $n2++) {
+				$n3 = $n2 * 9;
+				foreach my $dl (split(',', $ambsens->{desc}->{$n2})) {
+					$from = $n3++;
+					$to = $from + 1;
+					my ($j) = @$line[$from..$to];
+					push(@output, sprintf("%7.1lf ", celsius_to($config, $j) || 0));
+				}
+			}
+			push(@output, "\n");
+		}
+		push(@output, "    
\n"); + if($title) { + push(@output, " \n"); + push(@output, " \n"); + push(@output, main::graph_footer()); + } + push(@output, "
\n"); + return @output; + } + + + # graph mode + # + if($silent eq "yes" || $silent eq "imagetag") { + $colors->{fg_color} = "#000000"; # visible color for text mode + $u = "_"; + } + if($silent eq "imagetagbig") { + $colors->{fg_color} = "#000000"; # visible color for text mode + $u = ""; + } + + for($n = 0; $n < scalar(my @sl = split(',', $ambsens->{list})); $n++) { + $str = $u . $package . $n . "." . $tf->{when} . ".$imgfmt_lc"; + push(@IMG, $str); + unlink("$IMG_DIR" . $str); + if(lc($config->{enable_zoom}) eq "y") { + $str = $u . $package . $n . "z." . $tf->{when} . ".$imgfmt_lc"; + push(@IMGz, $str); + unlink("$IMG_DIR" . $str); + } + } + + @riglim = @{setup_riglim($rigid[0], $limit[0])}; + $n = 0; + while($n < scalar(my @sl = split(',', $ambsens->{list}))) { + if($title) { + if($n == 0) { + push(@output, main::graph_header($title, $ambsens->{graphs_per_row})); + } + push(@output, " \n"); + } + for($n2 = 0; $n2 < $ambsens->{graphs_per_row}; $n2++) { + last unless $n < scalar(my @sl = split(',', $ambsens->{list})); + if($title) { + push(@output, " \n"); + } + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + my $e = 0; + my $unit = $ambsens->{units}->{$n}; + foreach my $i (split(',', $ambsens->{desc}->{$n})) { + $i = trim($i); + $str = $ambsens->{map}->{$i} || $i; + $str = sprintf("%-40s", substr($str, 0, 40)); + push(@tmp, "LINE2:s" . ($e + 1) . $LC[$e] . ":$str"); + push(@tmp, "GPRINT:s" . ($e + 1) . ":LAST: Current\\:%7.1lf\\n"); + push(@tmpz, "LINE2:s" . ($e + 1) . $LC[$e] . ":$str"); + $e++; + } + while($e < 9) { + push(@tmp, "COMMENT: \\n"); + $e++; + } + if(lc($config->{show_gaps}) eq "y") { + push(@tmp, "AREA:wrongdata#$colors->{gap}:"); + push(@tmpz, "AREA:wrongdata#$colors->{gap}:"); + push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF"); + } + ($width, $height) = split('x', $config->{graph_size}->{medium}); + $str = substr(trim($sl[$n]), 0, 25); + $pic = $rrd{$version}->("$IMG_DIR" . "$IMG[$n]", + "--title=$str ($tf->{nwhen}$tf->{twhen})", + "--start=-$tf->{nwhen}$tf->{twhen}", + "--imgformat=$imgfmt_uc", + "--vertical-label=$unit", + "--width=$width", + "--height=$height", + @riglim, + $zoom, + @{$cgi->{version12}}, + @{$cgi->{version12_small}}, + @{$colors->{graph_colors}}, + "DEF:s1=$rrd:ambsens" . $n . "_s1:AVERAGE", + "DEF:s2=$rrd:ambsens" . $n . "_s2:AVERAGE", + "DEF:s3=$rrd:ambsens" . $n . "_s3:AVERAGE", + "DEF:s4=$rrd:ambsens" . $n . "_s4:AVERAGE", + "DEF:s5=$rrd:ambsens" . $n . "_s5:AVERAGE", + "DEF:s6=$rrd:ambsens" . $n . "_s6:AVERAGE", + "DEF:s7=$rrd:ambsens" . $n . "_s7:AVERAGE", + "DEF:s8=$rrd:ambsens" . $n . "_s8:AVERAGE", + "DEF:s9=$rrd:ambsens" . $n . "_s9:AVERAGE", + "CDEF:allvalues=s1,s2,s3,s4,s5,s6,s7,s8,s9,+,+,+,+,+,+,+,+", + @CDEF, + @tmp); + $err = RRDs::error; + push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG[$n]: $err\n") if $err; + if(lc($config->{enable_zoom}) eq "y") { + ($width, $height) = split('x', $config->{graph_size}->{zoom}); + $picz = $rrd{$version}->("$IMG_DIR" . "$IMGz[$n]", + "--title=$str ($tf->{nwhen}$tf->{twhen})", + "--start=-$tf->{nwhen}$tf->{twhen}", + "--imgformat=$imgfmt_uc", + "--vertical-label=$unit", + "--width=$width", + "--height=$height", + @riglim, + $zoom, + @{$cgi->{version12}}, + @{$cgi->{version12_small}}, + @{$colors->{graph_colors}}, + "DEF:s1=$rrd:ambsens" . $n . "_s1:AVERAGE", + "DEF:s2=$rrd:ambsens" . $n . "_s2:AVERAGE", + "DEF:s3=$rrd:ambsens" . $n . "_s3:AVERAGE", + "DEF:s4=$rrd:ambsens" . $n . "_s4:AVERAGE", + "DEF:s5=$rrd:ambsens" . $n . "_s5:AVERAGE", + "DEF:s6=$rrd:ambsens" . $n . "_s6:AVERAGE", + "DEF:s7=$rrd:ambsens" . $n . "_s7:AVERAGE", + "DEF:s8=$rrd:ambsens" . $n . "_s8:AVERAGE", + "DEF:s9=$rrd:ambsens" . $n . "_s9:AVERAGE", + "CDEF:allvalues=s1,s2,s3,s4,s5,s6,s7,s8,s9,+,+,+,+,+,+,+,+", + @CDEF, + @tmpz); + $err = RRDs::error; + push(@output, "ERROR: while graphing $IMG_DIR" . "$IMGz[$n]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /ambsens$n/)) { + if(lc($config->{enable_zoom}) eq "y") { + if(lc($config->{disable_javascript_void}) eq "y") { + push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$n] . "\">\n"); + } else { + if($version eq "new") { + $picz_width = $picz->{image_width} * $config->{global_zoom}; + $picz_height = $picz->{image_height} * $config->{global_zoom}; + } else { + $picz_width = $width + 115; + $picz_height = $height + 100; + } + push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$n] . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\">\n"); + } + } else { + push(@output, " \n"); + } + } + if($title) { + push(@output, " \n"); + } + $n++; + } + if($title) { + push(@output, " \n"); + } + } + if($title) { + push(@output, main::graph_footer()); + } + push(@output, "
\n"); + return @output; +} + +1; diff -Nru monitorix-3.10.1/lib/disk.pm monitorix-3.11.0/lib/disk.pm --- monitorix-3.10.1/lib/disk.pm 2017-07-25 10:07:12.000000000 +0000 +++ monitorix-3.11.0/lib/disk.pm 2018-03-05 16:06:13.000000000 +0000 @@ -160,12 +160,12 @@ } # check dependencies - if(lc($disk->{alerts}->{realloc_enabled}) eq "y") { + if(lc($disk->{alerts}->{realloc_enabled} || "") eq "y") { if(! -x $disk->{alerts}->{realloc_script}) { logger("$myself: ERROR: script '$disk->{alerts}->{realloc_script}' doesn't exist or don't has execution permissions."); } } - if(lc($disk->{alerts}->{pendsect_enabled}) eq "y") { + if(lc($disk->{alerts}->{pendsect_enabled} || "") eq "y") { if(! -x $disk->{alerts}->{pendsect_script}) { logger("$myself: ERROR: script '$disk->{alerts}->{pendsect_script}' doesn't exist or don't has execution permissions."); } @@ -236,6 +236,11 @@ $temp = $tmp[3] unless $temp; chomp($temp); } + if(/^Temperature: /) { + my @tmp = split(' ', $_); + $temp = $tmp[1] unless $temp; + chomp($temp); + } } close(IN); if(!$temp) { diff -Nru monitorix-3.10.1/lib/du.pm monitorix-3.11.0/lib/du.pm --- monitorix-3.10.1/lib/du.pm 2017-07-25 10:16:46.000000000 +0000 +++ monitorix-3.11.0/lib/du.pm 2018-10-26 10:32:27.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2018 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 @@ -142,16 +142,32 @@ my $e = 0; while($e < scalar(my @dl = split(',', $du->{list}))) { + my $type; my $e2 = 0; + + $type = lc($du->{type}->{$e} || ""); + + # default type is 'size' + $type = "size" if $type eq ""; + foreach my $i (split(',', $du->{desc}->{$e})) { my $line; $dirs[$e][$e2] = 0 unless defined $dirs[$e][$e2]; $str = trim($i); if(-d $str) { - $line = `du -ks $args "$str"`; # in KB - if($line =~ /(^\d+)\s+/) { - $dirs[$e][$e2] = $1; + if($type eq "size") { + $line = `du -ks $args "$str"`; # in KB + if($line =~ /(^\d+)\s+/) { + $dirs[$e][$e2] = $1; + } + } elsif($type eq "files") { + $line = `ls "$str"/* | wc -l`; + if($line =~ /(^\d+)$/) { + $dirs[$e][$e2] = $1; + } + } else { + logger("$myself: ERROR: unrecognized type '$type'."); } } else { logger("$myself: ERROR: '$str' is not a directory"); @@ -222,6 +238,7 @@ "#448844", "#EE4444", ); + my $type_label; $version = "old" if $RRDs::VERSION < 1.3; my $rrd = $config->{base_lib} . $package . ".rrd"; @@ -336,6 +353,10 @@ push(@output, " \n"); } for($n2 = 0; $n2 < $du->{graphs_per_row}; $n2++) { + my $type; + my @DEF0; + my @CDEF0; + last unless $n < scalar(my @dl = split(',', $du->{list})); if($title) { push(@output, " \n"); @@ -344,12 +365,54 @@ undef(@tmpz); undef(@CDEF); my $e = 0; + + $type = lc($du->{type}->{$n} || ""); + + if($type eq "files") { + $type_label = "files"; + push(@DEF0, "DEF:d1=$rrd:du" . $n . "_d1:AVERAGE"); + push(@DEF0, "DEF:d2=$rrd:du" . $n . "_d2:AVERAGE"); + push(@DEF0, "DEF:d3=$rrd:du" . $n . "_d3:AVERAGE"); + push(@DEF0, "DEF:d4=$rrd:du" . $n . "_d4:AVERAGE"); + push(@DEF0, "DEF:d5=$rrd:du" . $n . "_d5:AVERAGE"); + push(@DEF0, "DEF:d6=$rrd:du" . $n . "_d6:AVERAGE"); + push(@DEF0, "DEF:d7=$rrd:du" . $n . "_d7:AVERAGE"); + push(@DEF0, "DEF:d8=$rrd:du" . $n . "_d8:AVERAGE"); + push(@DEF0, "DEF:d9=$rrd:du" . $n . "_d9:AVERAGE"); + # default type is 'bytes' + } else { + $type_label = "bytes"; + push(@DEF0, "DEF:dk1=$rrd:du" . $n . "_d1:AVERAGE"); + push(@DEF0, "DEF:dk2=$rrd:du" . $n . "_d2:AVERAGE"); + push(@DEF0, "DEF:dk3=$rrd:du" . $n . "_d3:AVERAGE"); + push(@DEF0, "DEF:dk4=$rrd:du" . $n . "_d4:AVERAGE"); + push(@DEF0, "DEF:dk5=$rrd:du" . $n . "_d5:AVERAGE"); + push(@DEF0, "DEF:dk6=$rrd:du" . $n . "_d6:AVERAGE"); + push(@DEF0, "DEF:dk7=$rrd:du" . $n . "_d7:AVERAGE"); + push(@DEF0, "DEF:dk8=$rrd:du" . $n . "_d8:AVERAGE"); + push(@DEF0, "DEF:dk9=$rrd:du" . $n . "_d9:AVERAGE"); + push(@CDEF0, "CDEF:allvalues=dk1,dk2,dk3,dk4,dk5,dk6,dk7,dk8,dk9,+,+,+,+,+,+,+,+"); + push(@CDEF0, "CDEF:d1=dk1,1024,*"); + push(@CDEF0, "CDEF:d2=dk2,1024,*"); + push(@CDEF0, "CDEF:d3=dk3,1024,*"); + push(@CDEF0, "CDEF:d4=dk4,1024,*"); + push(@CDEF0, "CDEF:d5=dk5,1024,*"); + push(@CDEF0, "CDEF:d6=dk6,1024,*"); + push(@CDEF0, "CDEF:d7=dk7,1024,*"); + push(@CDEF0, "CDEF:d8=dk8,1024,*"); + push(@CDEF0, "CDEF:d9=dk9,1024,*"); + } + foreach my $i (split(',', $du->{desc}->{$n})) { $i = trim($i); $str = $du->{dirmap}->{$i} || $i; $str = sprintf("%-40s", substr($str, 0, 40)); push(@tmp, "LINE2:d" . ($e + 1) . $LC[$e] . ":$str"); - push(@tmp, "GPRINT:d" . ($e + 1) . ":LAST: Current\\:%7.1lf%s\\n"); + if($type eq "files") { + push(@tmp, "GPRINT:d" . ($e + 1) . ":LAST: Current\\:%7.0lf%s\\n"); + } else { + push(@tmp, "GPRINT:d" . ($e + 1) . ":LAST: Current\\:%7.1lf%s\\n"); + } push(@tmpz, "LINE2:d" . ($e + 1) . $LC[$e] . ":$str"); $e++; } @@ -368,7 +431,7 @@ "--title=$str ($tf->{nwhen}$tf->{twhen})", "--start=-$tf->{nwhen}$tf->{twhen}", "--imgformat=$imgfmt_uc", - "--vertical-label=bytes", + "--vertical-label=$type_label", "--width=$width", "--height=$height", @riglim, @@ -376,25 +439,8 @@ @{$cgi->{version12}}, @{$cgi->{version12_small}}, @{$colors->{graph_colors}}, - "DEF:dk1=$rrd:du" . $n . "_d1:AVERAGE", - "DEF:dk2=$rrd:du" . $n . "_d2:AVERAGE", - "DEF:dk3=$rrd:du" . $n . "_d3:AVERAGE", - "DEF:dk4=$rrd:du" . $n . "_d4:AVERAGE", - "DEF:dk5=$rrd:du" . $n . "_d5:AVERAGE", - "DEF:dk6=$rrd:du" . $n . "_d6:AVERAGE", - "DEF:dk7=$rrd:du" . $n . "_d7:AVERAGE", - "DEF:dk8=$rrd:du" . $n . "_d8:AVERAGE", - "DEF:dk9=$rrd:du" . $n . "_d9:AVERAGE", - "CDEF:allvalues=dk1,dk2,dk3,dk4,dk5,dk6,dk7,dk8,dk9,+,+,+,+,+,+,+,+", - "CDEF:d1=dk1,1024,*", - "CDEF:d2=dk2,1024,*", - "CDEF:d3=dk3,1024,*", - "CDEF:d4=dk4,1024,*", - "CDEF:d5=dk5,1024,*", - "CDEF:d6=dk6,1024,*", - "CDEF:d7=dk7,1024,*", - "CDEF:d8=dk8,1024,*", - "CDEF:d9=dk9,1024,*", + @DEF0, + @CDEF0, @CDEF, @tmp); $err = RRDs::error; @@ -405,7 +451,7 @@ "--title=$str ($tf->{nwhen}$tf->{twhen})", "--start=-$tf->{nwhen}$tf->{twhen}", "--imgformat=$imgfmt_uc", - "--vertical-label=bytes", + "--vertical-label=$type_label", "--width=$width", "--height=$height", @riglim, @@ -413,25 +459,8 @@ @{$cgi->{version12}}, @{$cgi->{version12_small}}, @{$colors->{graph_colors}}, - "DEF:dk1=$rrd:du" . $n . "_d1:AVERAGE", - "DEF:dk2=$rrd:du" . $n . "_d2:AVERAGE", - "DEF:dk3=$rrd:du" . $n . "_d3:AVERAGE", - "DEF:dk4=$rrd:du" . $n . "_d4:AVERAGE", - "DEF:dk5=$rrd:du" . $n . "_d5:AVERAGE", - "DEF:dk6=$rrd:du" . $n . "_d6:AVERAGE", - "DEF:dk7=$rrd:du" . $n . "_d7:AVERAGE", - "DEF:dk8=$rrd:du" . $n . "_d8:AVERAGE", - "DEF:dk9=$rrd:du" . $n . "_d9:AVERAGE", - "CDEF:allvalues=dk1,dk2,dk3,dk4,dk5,dk6,dk7,dk8,dk9,+,+,+,+,+,+,+,+", - "CDEF:d1=dk1,1024,*", - "CDEF:d2=dk2,1024,*", - "CDEF:d3=dk3,1024,*", - "CDEF:d4=dk4,1024,*", - "CDEF:d5=dk5,1024,*", - "CDEF:d6=dk6,1024,*", - "CDEF:d7=dk7,1024,*", - "CDEF:d8=dk8,1024,*", - "CDEF:d9=dk9,1024,*", + @DEF0, + @CDEF0, @CDEF, @tmpz); $err = RRDs::error; diff -Nru monitorix-3.10.1/lib/gensens.pm monitorix-3.11.0/lib/gensens.pm --- monitorix-3.10.1/lib/gensens.pm 2018-03-14 08:00:54.000000000 +0000 +++ monitorix-3.11.0/lib/gensens.pm 2019-03-14 13:53:52.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -164,22 +164,37 @@ my $timeintvl = trim($al[0]); my $threshold = trim($al[1]); my $script = trim($al[2]); - - if(!$threshold || $val < $threshold) { - $config->{gensens_hist_alerts}->{$str} = 0; - } else { - if(!$config->{gensens_hist_alerts}->{$str}) { - $config->{gensens_hist_alerts}->{$str} = time; - } - if($config->{gensens_hist_alerts}->{$str} > 0 && (time - $config->{gensens_hist_alerts}->{$str}) >= $timeintvl) { - if(-x $script) { - logger("$myself: alert on Generic Sensor ($str): executing script '$script'."); - system($script . " " . $timeintvl . " " . $threshold . " " . $val); + my $when = lc(trim($al[3] || "")); + my @range = split('-', $threshold); + $when = "above" if !$when; # 'above' is the default + $threshold = 0 if !$threshold; + if(scalar(@range) == 1) { + if($when eq "above" && $val < $threshold) { + $config->{gensens_hist_alerts}->{$str} = 0; + } elsif($when eq "below" && $val > $threshold) { + $config->{gensens_hist_alerts}->{$str} = 0; + } else { + if($when eq "above" || $when eq "below") { + if(!$config->{gensens_hist_alerts}->{$str}) { + $config->{gensens_hist_alerts}->{$str} = time; + } + if($config->{gensens_hist_alerts}->{$str} > 0 && (time - $config->{gensens_hist_alerts}->{$str}) >= $timeintvl) { + if(-x $script) { + logger("$myself: alert on Generic Sensor ($str): executing script '$script'."); + system($script . " " . $timeintvl . " " . $threshold . " " . $val . " " . $when); + } else { + logger("$myself: ERROR: script '$script' doesn't exist or don't has execution permissions."); + } + $config->{gensens_hist_alerts}->{$str} = time; + } } else { - logger("$myself: ERROR: script '$script' doesn't exist or don't has execution permissions."); + logger("$myself: ERROR: invalid when value '$when'"); } - $config->{gensens_hist_alerts}->{$str} = time; } + } elsif(scalar(@range) == 2) { + logger("$myself: range values are not supported yet."); + } else { + logger("$myself: ERROR: invalid threshold value '$threshold'"); } } diff -Nru monitorix-3.10.1/lib/HTTPServer.pm monitorix-3.11.0/lib/HTTPServer.pm --- monitorix-3.10.1/lib/HTTPServer.pm 2017-09-06 06:25:05.000000000 +0000 +++ monitorix-3.11.0/lib/HTTPServer.pm 2019-03-08 10:37:28.000000000 +0000 @@ -241,25 +241,26 @@ } } - if(scalar(@data)) { - if($auth eq "y") { - if(http_header("401", $mimetype)) { - print("\r\n"); - print "\r\n"; - print "401 Authorization Required\r\n"; - print "\r\n"; - print "

Authorization Required

\r\n"; - print "

This server could not verify that you\r\n"; - print "are authorized to access the document\r\n"; - print "requested. Either you supplied the wrong\r\n"; - print "credentials (e.g., bad password), or your\r\n"; - print "browser doesn't understand how to supply\r\n"; - print "the credentials required.

\r\n"; - print "\r\n"; - logger($url, "AUTHERR"); - exit(0); - } + if($auth eq "y") { + if(http_header("401", $mimetype)) { + print("\r\n"); + print "\r\n"; + print "401 Authorization Required\r\n"; + print "\r\n"; + print "

Authorization Required

\r\n"; + print "

This server could not verify that you\r\n"; + print "are authorized to access the document\r\n"; + print "requested. Either you supplied the wrong\r\n"; + print "credentials (e.g., bad password), or your\r\n"; + print "browser doesn't understand how to supply\r\n"; + print "the credentials required.

\r\n"; + print "\r\n"; + logger($url, "AUTHERR"); + exit(0); } + } + + if(scalar(@data)) { http_header("200", $mimetype); foreach(@data) { print $_; diff -Nru monitorix-3.10.1/lib/ipmi.pm monitorix-3.11.0/lib/ipmi.pm --- monitorix-3.10.1/lib/ipmi.pm 2018-03-15 06:52:55.000000000 +0000 +++ monitorix-3.11.0/lib/ipmi.pm 2019-03-14 13:54:18.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -78,15 +78,15 @@ push(@last, "RRA:LAST:0.5:1440:" . (365 * $n)); } for($n = 0; $n < scalar(my @sl = split(',', $ipmi->{list})); $n++) { - push(@tmp, "DS:ipmi" . $n . "_s1:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s2:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s3:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s4:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s5:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s6:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s7:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s8:GAUGE:120:0:U"); - push(@tmp, "DS:ipmi" . $n . "_s9:GAUGE:120:0:U"); + push(@tmp, "DS:ipmi" . $n . "_s1:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s2:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s3:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s4:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s5:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s6:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s7:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s8:GAUGE:120:U:U"); + push(@tmp, "DS:ipmi" . $n . "_s9:GAUGE:120:U:U"); } eval { RRDs::create($rrd, @@ -158,7 +158,7 @@ $str = trim($i); $unit = $ipmi->{units}->{$e}; foreach(@data) { - if(/^($str)\s+\|\s+(\d+\.*\d*)\s+$unit\s+/) { + if(/^($str)\s+\|\s+(-?\d+\.*\d*)\s+$unit\s+/) { my $val = $2; $sens[$e][$e2] = $val; diff -Nru monitorix-3.10.1/lib/mail.pm monitorix-3.11.0/lib/mail.pm --- monitorix-3.10.1/lib/mail.pm 2017-09-01 10:11:08.000000000 +0000 +++ monitorix-3.11.0/lib/mail.pm 2019-03-14 13:54:08.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -322,6 +322,45 @@ } close(IN); } + } elsif(lc($mail->{mta}) eq "exim") { + if(open(IN, "eximstats -h0 -ne -nr -t0 /var/log/exim/mainlog |")) { + while() { + if(/^ Received\s+(\d+)(\S\S)\s+(\d+).*?$/) { + $bytes_recvd = $1; + $bytes_recvd = $1 * 1024 if $2 eq "KB"; + $bytes_recvd = $1 * 1024 * 1024 if $2 eq "MB"; + $recvd = $3; + } + if(/^ Delivered\s+(\d+)(\S\S)\s+(\d+).*?$/) { + $bytes_delvd = $1; + $bytes_delvd = $1 * 1024 if $2 eq "KB"; + $bytes_delvd = $1 * 1024 * 1024 if $2 eq "MB"; + $delvd = $3; + } + if(/^ Rejects\s+(\d+).*?$/) { + $rejtd = $1; + } + if(/^ remote_smtp\s+\d+\S*\s+(\d+)$/) { + $out_conn = $1; + } + } + close(IN); + $in_conn = $recvd - $rejtd; + $delvd -= $out_conn; + } + if(open(IN, "exim -bp |")) { + while() { + # discard blank lines and lines with recipients + if(!/^$/ && !/^\s{10}\S+$/) { + my ($size, undef, $unit) = ($_ =~ m/^\s*\d+.\s+(\d(.\d)?)(\S*)\s.*?$/); + $queues += int($size) if !$unit; + $queues += int($size * 1024) if $unit eq "K"; + $queues += int($size * 1024 * 1024) if $unit eq "M"; + $queued++; + } + } + close(IN); + } } $gl_records = $gl_greylisted = $gl_whitelisted = $gl_delayed = 0; @@ -953,6 +992,67 @@ push(@tmpz, "LINE1:held#00EE00"); push(@tmpz, "LINE1:n_forwrd#00EEEE"); push(@tmpz, "LINE1:n_delvd#0000EE"); + } elsif(lc($mail->{mta}) eq "exim") { + push(@tmp, "AREA:in#44EE44:In Connections"); + push(@tmp, "GPRINT:in:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:in:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:in:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:in:MAX: Max\\: $valform\\n"); + push(@tmp, "AREA:rejtd#EE4444:Rejected"); + push(@tmp, "GPRINT:rejtd:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:rejtd:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:rejtd:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:rejtd:MAX: Max\\: $valform\\n"); + push(@tmp, "AREA:recvd#448844:Received"); + push(@tmp, "GPRINT:recvd:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:recvd:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:recvd:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:recvd:MAX: Max\\: $valform\\n"); + push(@tmp, "AREA:spam#EEEE44:Spam"); + push(@tmp, "GPRINT:spam:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:spam:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:spam:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:spam:MAX: Max\\: $valform\\n"); + push(@tmp, "AREA:virus#EE44EE:Virus"); + push(@tmp, "GPRINT:virus:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:virus:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:virus:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:virus:MAX: Max\\: $valform\\n"); + push(@tmp, "AREA:n_delvd#4444EE:Delivered"); + push(@tmp, "GPRINT:delvd:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:delvd:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:delvd:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:delvd:MAX: Max\\: $valform\\n"); + push(@tmp, "AREA:n_out#44EEEE:Out Connections"); + push(@tmp, "GPRINT:out:LAST: Cur\\: $valform"); + push(@tmp, "GPRINT:out:AVERAGE: Avg\\: $valform"); + push(@tmp, "GPRINT:out:MIN: Min\\: $valform"); + push(@tmp, "GPRINT:out:MAX: Max\\: $valform\\n"); + push(@tmp, "LINE1:in#00EE00"); + push(@tmp, "LINE1:rejtd#EE0000"); + push(@tmp, "LINE1:recvd#1F881F"); + push(@tmp, "LINE1:spam#EEEE00"); + push(@tmp, "LINE1:virus#EE00EE"); + push(@tmp, "LINE1:n_delvd#0000EE"); + push(@tmp, "LINE1:n_out#00EEEE"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + + push(@tmpz, "AREA:in#44EE44:In Connections"); + push(@tmpz, "AREA:rejtd#EE4444:Rejected"); + push(@tmpz, "AREA:recvd#448844:Received"); + push(@tmpz, "AREA:spam#EEEE44:Spam"); + push(@tmpz, "AREA:virus#EE44EE:Virus"); + push(@tmpz, "AREA:n_delvd#4444EE:Delivered"); + push(@tmpz, "AREA:n_out#44EEEE:Out Connections"); + push(@tmpz, "LINE1:in#00EE00"); + push(@tmpz, "LINE1:rejtd#EE0000"); + push(@tmpz, "LINE1:recvd#1F881F"); + push(@tmpz, "LINE1:spam#EEEE00"); + push(@tmpz, "LINE1:virus#EE00EE"); + push(@tmpz, "LINE1:n_delvd#0000EE"); + push(@tmpz, "LINE1:n_out#00EEEE"); } if(lc($config->{show_gaps}) eq "y") { push(@tmp, "AREA:wrongdata_p#$colors->{gap}:"); diff -Nru monitorix-3.10.1/lib/Monitorix.pm monitorix-3.11.0/lib/Monitorix.pm --- monitorix-3.10.1/lib/Monitorix.pm 2018-03-15 06:59:01.000000000 +0000 +++ monitorix-3.11.0/lib/Monitorix.pm 2019-03-14 13:53:19.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2016 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -133,6 +133,7 @@ open(OUT, ">> " . $config->{httpd_builtin}->{log_file}); close(OUT); chown($uid, $gid, $config->{httpd_builtin}->{log_file}); + chmod(0600, $config->{httpd_builtin}->{log_file}); setgid($gid); if(getgid() != $gid) { @@ -155,9 +156,8 @@ logger("$myself: '$config->{httpd_builtin}->{auth}->{htpasswd}' $!"); } } else { - if(!grep {$_ eq $config->{httpd_builtin}->{host}} - ("localhost", "127.0.0.1")) { - logger("WARNING: the built-in HTTP server has authentication disabled."); + if(!grep {$_ eq $config->{httpd_builtin}->{host}} ("localhost", "127.0.0.1")) { + logger("WARNING: the HTTP built-in server has authentication disabled."); } } diff -Nru monitorix-3.10.1/lib/netstat.pm monitorix-3.11.0/lib/netstat.pm --- monitorix-3.10.1/lib/netstat.pm 2017-08-03 08:39:36.000000000 +0000 +++ monitorix-3.11.0/lib/netstat.pm 2019-03-14 13:53:41.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -179,65 +179,118 @@ my $rrdata = "N"; if($config->{os} eq "Linux") { - if(open(IN, "netstat -tn -A inet |")) { - while() { - my $last = (split(' ', $_))[-1]; - $i4_closed++ if trim($last) eq "CLOSED"; - $i4_synsent++ if trim($last) eq "SYN_SENT"; - $i4_synrecv++ if trim($last) eq "SYN_RECV"; - $i4_estblshd++ if trim($last) eq "ESTABLISHED"; - $i4_finwait1++ if trim($last) eq "FIN_WAIT1"; - $i4_finwait2++ if trim($last) eq "FIN_WAIT2"; - $i4_closing++ if trim($last) eq "CLOSING"; - $i4_timewait++ if trim($last) eq "TIME_WAIT"; - $i4_closewait++ if trim($last) eq "CLOSE_WAIT"; - $i4_lastack++ if trim($last) eq "LAST_ACK"; - $i4_unknown++ if trim($last) eq "UNKNOWN"; - } - close(IN); - } - if(open(IN, "netstat -ltn -A inet |")) { - while() { - my $last = (split(' ', $_))[-1]; - $i4_listen++ if trim($last) eq "LISTEN"; - } - close(IN); - } - if(open(IN, "netstat -lun -A inet |")) { - while() { - $i4_udp++ if /^udp\s+/; - } - close(IN); - } - if(open(IN, "netstat -tn -A inet6 |")) { - while() { - my $last = (split(' ', $_))[-1]; - $i6_closed++ if trim($last) eq "CLOSED"; - $i6_synsent++ if trim($last) eq "SYN_SENT"; - $i6_synrecv++ if trim($last) eq "SYN_RECV"; - $i6_estblshd++ if trim($last) eq "ESTABLISHED"; - $i6_finwait1++ if trim($last) eq "FIN_WAIT1"; - $i6_finwait2++ if trim($last) eq "FIN_WAIT2"; - $i6_closing++ if trim($last) eq "CLOSING"; - $i6_timewait++ if trim($last) eq "TIME_WAIT"; - $i6_closewait++ if trim($last) eq "CLOSE_WAIT"; - $i6_lastack++ if trim($last) eq "LAST_ACK"; - $i6_unknown++ if trim($last) eq "UNKNOWN"; - } - close(IN); - } - if(open(IN, "netstat -ltn -A inet6 |")) { - while() { - my $last = (split(' ', $_))[-1]; - $i6_listen++ if trim($last) eq "LISTEN"; - } - close(IN); - } - if(open(IN, "netstat -lun -A inet6 |")) { - while() { - $i6_udp++ if /^udp[ 6]\s+/; + my $cmd = $config->{netstat}->{cmd} || ""; + if(!$cmd || $cmd eq "ss") { + if(open(IN, "ss -na -f inet |")) { + while() { + m/^(\S+)\s+(\S+)/; + my $proto = $1 || ''; + my $state = $2 || ''; + if ($proto eq 'tcp') { + if ($state eq "LISTEN") { $i4_listen++ } + elsif ($state eq "ESTAB") { $i4_estblshd++ } + elsif ($state eq "TIME-WAIT") { $i4_timewait++ } + elsif ($state eq "CLOSE-WAIT") { $i4_closewait++ } + elsif ($state eq "FIN-WAIT-1") { $i4_finwait1++ } + elsif ($state eq "FIN-WAIT-2") { $i4_finwait2++ } + elsif ($state eq "SYN-SENT") { $i4_synsent++ } + elsif ($state eq "SYN-RECV") { $i4_synrecv++ } + elsif ($state eq "CLOSING") { $i4_closing++ } + elsif ($state eq "LAST-ACK") { $i4_lastack++ } + elsif ($state eq "UNCONN") { $i4_closed++ } + elsif ($state eq "UNKNOWN") { $i4_unknown++ } + } elsif ($proto eq 'udp') { + $i4_udp++; + } + } + close(IN); + } + if(open(IN, "ss -na -f inet6 |")) { + while() { + m/^(\S+)\s+(\S+)/; + my $proto = $1 || ''; + my $state = $2 || ''; + if ($proto eq 'tcp') { + if ($state eq "LISTEN") { $i6_listen++ } + elsif ($state eq "ESTAB") { $i6_estblshd++ } + elsif ($state eq "TIME-WAIT") { $i6_timewait++ } + elsif ($state eq "CLOSE-WAIT") { $i6_closewait++ } + elsif ($state eq "FIN-WAIT-1") { $i6_finwait1++ } + elsif ($state eq "FIN-WAIT-2") { $i6_finwait2++ } + elsif ($state eq "SYN-SENT") { $i6_synsent++ } + elsif ($state eq "SYN-RECV") { $i6_synrecv++ } + elsif ($state eq "CLOSING") { $i6_closing++ } + elsif ($state eq "LAST-ACK") { $i6_lastack++ } + elsif ($state eq "UNCONN") { $i6_closed++ } + elsif ($state eq "UNKNOWN") { $i6_unknown++ } + } elsif ($proto eq 'udp') { + $i6_udp++; + } + } + close(IN); + } + } + if($cmd eq "netstat") { + if(open(IN, "netstat -tn -A inet |")) { + while() { + my $last = (split(' ', $_))[-1]; + $i4_closed++ if trim($last) eq "CLOSED"; + $i4_synsent++ if trim($last) eq "SYN_SENT"; + $i4_synrecv++ if trim($last) eq "SYN_RECV"; + $i4_estblshd++ if trim($last) eq "ESTABLISHED"; + $i4_finwait1++ if trim($last) eq "FIN_WAIT1"; + $i4_finwait2++ if trim($last) eq "FIN_WAIT2"; + $i4_closing++ if trim($last) eq "CLOSING"; + $i4_timewait++ if trim($last) eq "TIME_WAIT"; + $i4_closewait++ if trim($last) eq "CLOSE_WAIT"; + $i4_lastack++ if trim($last) eq "LAST_ACK"; + $i4_unknown++ if trim($last) eq "UNKNOWN"; + } + close(IN); + } + if(open(IN, "netstat -ltn -A inet |")) { + while() { + my $last = (split(' ', $_))[-1]; + $i4_listen++ if trim($last) eq "LISTEN"; + } + close(IN); + } + if(open(IN, "netstat -lun -A inet |")) { + while() { + $i4_udp++ if /^udp\s+/; + } + close(IN); + } + if(open(IN, "netstat -tn -A inet6 |")) { + while() { + my $last = (split(' ', $_))[-1]; + $i6_closed++ if trim($last) eq "CLOSED"; + $i6_synsent++ if trim($last) eq "SYN_SENT"; + $i6_synrecv++ if trim($last) eq "SYN_RECV"; + $i6_estblshd++ if trim($last) eq "ESTABLISHED"; + $i6_finwait1++ if trim($last) eq "FIN_WAIT1"; + $i6_finwait2++ if trim($last) eq "FIN_WAIT2"; + $i6_closing++ if trim($last) eq "CLOSING"; + $i6_timewait++ if trim($last) eq "TIME_WAIT"; + $i6_closewait++ if trim($last) eq "CLOSE_WAIT"; + $i6_lastack++ if trim($last) eq "LAST_ACK"; + $i6_unknown++ if trim($last) eq "UNKNOWN"; + } + close(IN); + } + if(open(IN, "netstat -ltn -A inet6 |")) { + while() { + my $last = (split(' ', $_))[-1]; + $i6_listen++ if trim($last) eq "LISTEN"; + } + close(IN); + } + if(open(IN, "netstat -lun -A inet6 |")) { + while() { + $i6_udp++ if /^udp[ 6]\s+/; + } + close(IN); } - close(IN); } } elsif(grep {$_ eq $config->{os}} ("FreeBSD", "OpenBSD")) { if(open(IN, "netstat -na -p tcp -f inet |")) { diff -Nru monitorix-3.10.1/lib/nvidia.pm monitorix-3.11.0/lib/nvidia.pm --- monitorix-3.10.1/lib/nvidia.pm 2017-08-04 08:17:09.000000000 +0000 +++ monitorix-3.11.0/lib/nvidia.pm 2017-09-29 08:30:46.000000000 +0000 @@ -570,15 +570,11 @@ push(@tmp, "GPRINT:gpu5:LAST:\\:%3.0lf%%"); push(@tmp, "LINE2:gpu8#963C74:Card 8\\g"); push(@tmp, "GPRINT:gpu8:LAST:\\:%3.0lf%%\\n"); - push(@tmpz, "LINE2:gpu0#FFA500:Card 0"); - push(@tmpz, "LINE2:gpu3#4444EE:Card 3"); - push(@tmpz, "LINE2:gpu6#EE44EE:Card 6"); - push(@tmpz, "LINE2:gpu1#44EEEE:Card 1"); - push(@tmpz, "LINE2:gpu4#448844:Card 4"); - push(@tmpz, "LINE2:gpu7#EEEE44:Card 7"); - push(@tmpz, "LINE2:gpu2#44EE44:Card 2"); - push(@tmpz, "LINE2:gpu5#EE4444:Card 5"); - push(@tmpz, "LINE2:gpu8#963C74:Card 8"); + for($n = 0; $n < 9; $n++) { + if($n < $nvidia->{max}) { + push(@tmpz, "LINE2:gpu" . $n . $LC[$n] . ":Card $n"); + } + } if(lc($config->{show_gaps}) eq "y") { push(@tmp, "AREA:wrongdata#$colors->{gap}:"); push(@tmpz, "AREA:wrongdata#$colors->{gap}:"); @@ -688,15 +684,11 @@ push(@tmp, "GPRINT:mem5:LAST:\\:%3.0lf%%"); push(@tmp, "LINE2:mem8#963C74:Card 8\\g"); push(@tmp, "GPRINT:mem8:LAST:\\:%3.0lf%%\\n"); - push(@tmpz, "LINE2:mem0#FFA500:Card 0"); - push(@tmpz, "LINE2:mem3#4444EE:Card 3"); - push(@tmpz, "LINE2:mem6#EE44EE:Card 6"); - push(@tmpz, "LINE2:mem1#44EEEE:Card 1"); - push(@tmpz, "LINE2:mem4#448844:Card 4"); - push(@tmpz, "LINE2:mem7#EEEE44:Card 7"); - push(@tmpz, "LINE2:mem2#44EE44:Card 2"); - push(@tmpz, "LINE2:mem5#EE4444:Card 5"); - push(@tmpz, "LINE2:mem8#963C74:Card 8"); + for($n = 0; $n < 9; $n++) { + if($n < $nvidia->{max}) { + push(@tmpz, "LINE2:mem" . $n . $LC[$n] . ":Card $n"); + } + } if(lc($config->{show_gaps}) eq "y") { push(@tmp, "AREA:wrongdata#$colors->{gap}:"); push(@tmpz, "AREA:wrongdata#$colors->{gap}:"); diff -Nru monitorix-3.10.1/lib/system.pm monitorix-3.11.0/lib/system.pm --- monitorix-3.10.1/lib/system.pm 2018-03-15 06:56:37.000000000 +0000 +++ monitorix-3.11.0/lib/system.pm 2019-03-14 13:53:34.000000000 +0000 @@ -1,7 +1,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -122,7 +122,7 @@ } # check dependencies - if(lc($system->{alerts}->{loadavg_enabled}) eq "y") { + if(lc($system->{alerts}->{loadavg_enabled} || "") eq "y") { if(! -x $system->{alerts}->{loadavg_script}) { logger("$myself: ERROR: script '$system->{alerts}->{loadavg_script}' doesn't exist or don't has execution permissions."); } @@ -167,6 +167,8 @@ my $entropy = 0; my $uptime = 0; + my $srecl = 0; + my $snorecl = 0; my $rrdata = "N"; if($config->{os} eq "Linux") { @@ -231,11 +233,24 @@ } if(/^Inactive:\s+(\d+) kB$/) { $minac = $1; + next; + } + if(/^SReclaimable:\s+(\d+) kB$/) { + $srecl = $1; + next; + } + if(/^SUnreclaim:\s+(\d+) kB$/) { + $snorecl = $1; last; } } close(IN); + # SReclaimable and SUnreclaim values are added to 'mfree' + # in order to be also included in the subtraction later. + $mfree += $srecl; + $mfree += $snorecl; + open(IN, "/proc/sys/kernel/random/entropy_avail"); while() { if(/^(\d+)$/) { @@ -290,10 +305,10 @@ $macti = ($page_size * $macti) / 1024; $minac = ($page_size * $minac) / 1024; - open(IN, "/sbin/sysctl -n kern.random.sys.seeded |"); - $entropy = ; - close(IN); - chomp($entropy); +# open(IN, "/sbin/sysctl -n kern.random.sys.seeded |"); +# $entropy = ; +# close(IN); +# chomp($entropy); open(IN, "/sbin/sysctl -n kern.boottime |"); (undef, undef, undef, $uptime) = split(' ', ); @@ -380,7 +395,10 @@ # SYSTEM alert if(lc($system->{alerts}->{loadavg_enabled}) eq "y") { - if(!$system->{alerts}->{loadavg_threshold} || $load15 < $system->{alerts}->{loadavg_threshold}) { + my $load; + + $load = min($load5, $load15); + if(!$system->{alerts}->{loadavg_threshold} || $load < $system->{alerts}->{loadavg_threshold}) { $config->{system_hist_alert1} = 0; } else { if(!$config->{system_hist_alert1}) { @@ -389,7 +407,7 @@ if($config->{system_hist_alert1} > 0 && (time - $config->{system_hist_alert1}) >= $system->{alerts}->{loadavg_timeintvl}) { if(-x $system->{alerts}->{loadavg_script}) { logger("$myself: ALERT: executing script '$system->{alerts}->{loadavg_script}'."); - system($system->{alerts}->{loadavg_script} . " " .$system->{alerts}->{loadavg_timeintvl} . " " . $system->{alerts}->{loadavg_threshold} . " " . $load15); + system($system->{alerts}->{loadavg_script} . " " .$system->{alerts}->{loadavg_timeintvl} . " " . $system->{alerts}->{loadavg_threshold} . " " . $load); } else { logger("$myself: ERROR: script '$system->{alerts}->{loadavg_script}' doesn't exist or don't has execution permissions."); } @@ -489,7 +507,7 @@ $buff /= 1024; $cach /= 1024; $free /= 1024; - @row = ($load1, $load5, $load15, $total_mem - $free, $cach, $buff, $macti, $minac, $nproc, $nprun, $npslp, $npwio, $npzom, $npstp, $npswp, $entropy, $uptime); + @row = ($load1, $load5, $load15, ($total_mem - $free - $buff - $cach), $cach, $buff, $macti, $minac, $nproc, $nprun, $npslp, $npwio, $npzom, $npstp, $npswp, $entropy, $uptime); $time = $time - (1 / $tf->{ts}); push(@output, sprintf(" %2d$tf->{tc} %4.1f %4.1f %4.1f %6d %6d %6d %6d %6d %4d %4d %4d %4d %4d %4d %4d %6d %8d\n", $time, @row)); } @@ -707,7 +725,7 @@ "CDEF:m_mtotl=mtotl,1024,*", "CDEF:m_mbuff=mbuff,1024,*", "CDEF:m_mcach=mcach,1024,*", - "CDEF:m_mused=m_mtotl,mfree,1024,*,-", + "CDEF:m_mused=m_mtotl,mfree,1024,*,-,m_mbuff,-,m_mcach,-", "CDEF:m_macti=macti,1024,*", "CDEF:m_minac=minac,1024,*", "CDEF:allvalues=mtotl,mbuff,mcach,mfree,macti,minac,+,+,+,+,+", @@ -742,7 +760,7 @@ "CDEF:m_mtotl=mtotl,1024,*", "CDEF:m_mbuff=mbuff,1024,*", "CDEF:m_mcach=mcach,1024,*", - "CDEF:m_mused=m_mtotl,mfree,1024,*,-", + "CDEF:m_mused=m_mtotl,mfree,1024,*,-,m_mbuff,-,m_mcach,-", "CDEF:m_macti=macti,1024,*", "CDEF:m_minac=minac,1024,*", "CDEF:allvalues=mtotl,mbuff,mcach,mfree,macti,minac,+,+,+,+,+", diff -Nru monitorix-3.10.1/lib/zfs.pm monitorix-3.11.0/lib/zfs.pm --- monitorix-3.10.1/lib/zfs.pm 2017-08-31 08:05:14.000000000 +0000 +++ monitorix-3.11.0/lib/zfs.pm 2018-03-23 10:07:11.000000000 +0000 @@ -82,10 +82,10 @@ push(@tmp, "DS:zfs" . $n . "_usnap:GAUGE:120:0:U"); push(@tmp, "DS:zfs" . $n . "_cap:GAUGE:120:0:100"); push(@tmp, "DS:zfs" . $n . "_fra:GAUGE:120:0:100"); - push(@tmp, "DS:zfs" . $n . "_val1:GAUGE:120:0:U"); - push(@tmp, "DS:zfs" . $n . "_val2:GAUGE:120:0:U"); - push(@tmp, "DS:zfs" . $n . "_val3:GAUGE:120:0:U"); - push(@tmp, "DS:zfs" . $n . "_val4:GAUGE:120:0:U"); + push(@tmp, "DS:zfs" . $n . "_oper:GAUGE:120:0:U"); + push(@tmp, "DS:zfs" . $n . "_opew:GAUGE:120:0:U"); + push(@tmp, "DS:zfs" . $n . "_banr:GAUGE:120:0:U"); + push(@tmp, "DS:zfs" . $n . "_banw:GAUGE:120:0:U"); push(@tmp, "DS:zfs" . $n . "_val5:GAUGE:120:0:U"); } eval { @@ -145,6 +145,17 @@ } } + # Since 3.11.0 four new values were included (operations r/w and + # bandwidth r/w). + for($n = 0; $n < $zfs->{max_pools}; $n++) { + RRDs::tune($rrd, + "--data-source-rename=zfs" . $n . "_val1:zfs" . $n . "_oper", + "--data-source-rename=zfs" . $n . "_val2:zfs" . $n . "_opew", + "--data-source-rename=zfs" . $n . "_val3:zfs" . $n . "_banr", + "--data-source-rename=zfs" . $n . "_val4:zfs" . $n . "_banw", + ); + } + $config->{zfs_hist} = (); push(@{$config->{func_update}}, $package); logger("$myself: Ok") if $debug; @@ -247,19 +258,19 @@ my $usnap = 0; my $cap = 0; my $fra = 0; - my $val1 = 0; - my $val2 = 0; - my $val3 = 0; - my $val4 = 0; + my $oper = 0; + my $opew = 0; + my $banr = 0; + my $banw = 0; my $val5 = 0; my $pool = (split(',', $zfs->{list}))[$n] || ""; if($pool) { my @zpool; - $free = trim(`zfs get -rHp -o value available $pool`); - $udata = trim(`zfs get -rHp -o value used $pool`); - $usnap = trim(`zfs get -rHp -o value usedbysnapshots $pool`); + $free = trim(`zfs get -Hp -o value available $pool`); + $udata = trim(`zfs get -Hp -o value used $pool`); + $usnap = eval join('+',`zfs get -rHp -o value usedbysnapshots -tfilesystem $pool`); @zpool = split(' ', `zpool list -H $pool` || ""); if(scalar(@zpool) == 10) { # ZFS version 0.6.4+ @@ -271,9 +282,11 @@ } $cap =~ s/%//; $fra =~ s/[%-]//g; $fra = $fra || 0; + @zpool = split(' ', `zpool iostat -Hp $pool` || ""); + (undef, undef, undef, $oper, $opew, $banr, $banw) = @zpool; } - $rrdata .= ":$free:$udata:$usnap:$cap:$fra:0:0:0:0:0"; + $rrdata .= ":$free:$udata:$usnap:$cap:$fra:$oper:$opew:$banr:$banw:0"; } RRDs::update($rrd, $rrdata); @@ -417,19 +430,16 @@ "$IMG_DIR" . "$IMG3z"); } for($n = 0; $n < scalar(my @pl = split(',', $zfs->{list})); $n++) { - $str = $u . $package . ($n + 4) . "1." . $tf->{when} . ".$imgfmt_lc"; - push(@IMG, $str); - unlink("$IMG_DIR" . $str); - $str = $u . $package . ($n + 4) . "2." . $tf->{when} . ".$imgfmt_lc"; - push(@IMG, $str); - unlink("$IMG_DIR" . $str); - if(lc($config->{enable_zoom}) eq "y") { - $str = $u . $package . ($n + 4) . "1z." . $tf->{when} . ".$imgfmt_lc"; - push(@IMGz, $str); - unlink("$IMG_DIR" . $str); - $str = $u . $package . ($n + 4) . "2z." . $tf->{when} . ".$imgfmt_lc"; - push(@IMGz, $str); + my $n2; + for($n2 = 1; $n2 < 5; $n2++) { + $str = $u . $package . ($n + 4) . $n2 . "." . $tf->{when} . ".$imgfmt_lc"; + push(@IMG, $str); unlink("$IMG_DIR" . $str); + if(lc($config->{enable_zoom}) eq "y") { + $str = $u . $package . ($n + 4) . $n2 . "z." . $tf->{when} . ".$imgfmt_lc"; + push(@IMGz, $str); + unlink("$IMG_DIR" . $str); + } } } @@ -840,10 +850,6 @@ } $e++; - if($title) { - push(@output, " \n"); - push(@output, " \n"); - } @riglim = @{setup_riglim($rigid[$e + 3], $limit[$e + 3])}; undef(@tmp); undef(@tmpz); @@ -913,6 +919,188 @@ if(lc($config->{enable_zoom}) eq "y") { if(lc($config->{disable_javascript_void}) eq "y") { push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$e] . "\">\n"); + } else { + if($version eq "new") { + $picz_width = $picz->{image_width} * $config->{global_zoom}; + $picz_height = $picz->{image_height} * $config->{global_zoom}; + } else { + $picz_width = $width + 115; + $picz_height = $height + 100; + } + push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$e] . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\">\n"); + } + } else { + push(@output, " \n"); + } + } + $e++; + + if($title) { + push(@output, " \n"); + push(@output, " \n"); + } + @riglim = @{setup_riglim($rigid[$e + 3], $limit[$e + 3])}; + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:oper#00EEEE:Read"); + push(@tmp, "GPRINT:oper:LAST: Current\\: %5.1lf%S\\n"); + push(@tmp, "AREA:n_opew#4444EE:Write"); + push(@tmp, "GPRINT:opew:LAST: Current\\: %5.1lf%S\\n"); + push(@tmpz, "AREA:oper#00EEEE:Read"); + push(@tmpz, "AREA:n_opew#4444EE:Write"); + if(lc($config->{show_gaps}) eq "y") { + push(@tmp, "AREA:wrongdata#$colors->{gap}:"); + push(@tmpz, "AREA:wrongdata#$colors->{gap}:"); + push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF"); + } + ($width, $height) = split('x', $config->{graph_size}->{medium2}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + $pic = $rrd{$version}->("$IMG_DIR" . "$IMG[$e]", + "--title=$config->{graphs}->{_zfs6}: $str ($tf->{nwhen}$tf->{twhen})", + "--start=-$tf->{nwhen}$tf->{twhen}", + "--imgformat=$imgfmt_uc", + "--vertical-label=Number", + "--width=$width", + "--height=$height", + @riglim, + $zoom, + @{$cgi->{version12}}, + @{$cgi->{version12_small}}, + @{$colors->{graph_colors}}, + "DEF:oper=$rrd:zfs" . $n . "_oper:AVERAGE", + "DEF:opew=$rrd:zfs" . $n . "_opew:AVERAGE", + "CDEF:n_opew=opew,-1,*", + "CDEF:allvalues=oper,opew,+", + @CDEF, + @tmp); + $err = RRDs::error; + push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG[$e]: $err\n") if $err; + if(lc($config->{enable_zoom}) eq "y") { + ($width, $height) = split('x', $config->{graph_size}->{zoom}); + $picz = $rrd{$version}->("$IMG_DIR" . "$IMGz[$e]", + "--title=$config->{graphs}->{_zfs6}: $str ($tf->{nwhen}$tf->{twhen})", + "--start=-$tf->{nwhen}$tf->{twhen}", + "--imgformat=$imgfmt_uc", + "--vertical-label=Number", + "--width=$width", + "--height=$height", + @riglim, + $zoom, + @{$cgi->{version12}}, + @{$cgi->{version12_small}}, + @{$colors->{graph_colors}}, + "DEF:oper=$rrd:zfs" . $n . "_oper:AVERAGE", + "DEF:opew=$rrd:zfs" . $n . "_opew:AVERAGE", + "CDEF:n_opew=opew,-1,*", + "CDEF:allvalues=oper,opew,+", + @CDEF, + @tmpz); + $err = RRDs::error; + push(@output, "ERROR: while graphing $IMG_DIR" . "$IMGz[$e]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /zfs4/)) { + if(lc($config->{enable_zoom}) eq "y") { + if(lc($config->{disable_javascript_void}) eq "y") { + push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$e] . "\">\n"); + } else { + if($version eq "new") { + $picz_width = $picz->{image_width} * $config->{global_zoom}; + $picz_height = $picz->{image_height} * $config->{global_zoom}; + } else { + $picz_width = $width + 115; + $picz_height = $height + 100; + } + push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$e] . "','','width=" . $picz_width . ",height=" . $picz_height . ",scrollbars=0,resizable=0'))\">\n"); + } + } else { + push(@output, " \n"); + } + } + $e++; + + @riglim = @{setup_riglim($rigid[$e + 3], $limit[$e + 3])}; + undef(@tmp); + undef(@tmpz); + undef(@CDEF); + push(@tmp, "AREA:banr_b#00EEEE:Read"); + push(@tmp, "GPRINT:banr_b:LAST: Current\\: %4.1lf%S\\n"); + push(@tmp, "AREA:n_banw_b#4444EE:Write"); + push(@tmp, "GPRINT:banw_b:LAST: Current\\: %4.1lf%S\\n"); + push(@tmpz, "AREA:banr_b#00EEEE:Read"); + push(@tmpz, "AREA:n_banw_b#4444EE:Write"); + if(lc($config->{show_gaps}) eq "y") { + push(@tmp, "AREA:wrongdata#$colors->{gap}:"); + push(@tmpz, "AREA:wrongdata#$colors->{gap}:"); + push(@CDEF, "CDEF:wrongdata=allvalues,UN,INF,UNKN,IF"); + } + ($width, $height) = split('x', $config->{graph_size}->{medium2}); + if($silent =~ /imagetag/) { + ($width, $height) = split('x', $config->{graph_size}->{remote}) if $silent eq "imagetag"; + ($width, $height) = split('x', $config->{graph_size}->{main}) if $silent eq "imagetagbig"; + @tmp = @tmpz; + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + push(@tmp, "COMMENT: \\n"); + } + $pic = $rrd{$version}->("$IMG_DIR" . "$IMG[$e]", + "--title=$config->{graphs}->{_zfs7}: $str ($tf->{nwhen}$tf->{twhen})", + "--start=-$tf->{nwhen}$tf->{twhen}", + "--imgformat=$imgfmt_uc", + "--vertical-label=bytes", + "--width=$width", + "--height=$height", + @riglim, + $zoom, + @{$cgi->{version12}}, + @{$cgi->{version12_small}}, + @{$colors->{graph_colors}}, + "DEF:banr=$rrd:zfs" . $n . "_banr:AVERAGE", + "DEF:banw=$rrd:zfs" . $n . "_banw:AVERAGE", + "CDEF:banr_b=banr,1024,*", + "CDEF:banw_b=banw,1024,*", + "CDEF:n_banw_b=banw_b,-1,*", + "CDEF:allvalues=banr,banw,+", + @CDEF, + @tmp); + $err = RRDs::error; + push(@output, "ERROR: while graphing $IMG_DIR" . "$IMG[$e]: $err\n") if $err; + if(lc($config->{enable_zoom}) eq "y") { + ($width, $height) = split('x', $config->{graph_size}->{zoom}); + $picz = $rrd{$version}->("$IMG_DIR" . "$IMGz[$e]", + "--title=$config->{graphs}->{_zfs7}: $str ($tf->{nwhen}$tf->{twhen})", + "--start=-$tf->{nwhen}$tf->{twhen}", + "--imgformat=$imgfmt_uc", + "--vertical-label=bytes", + "--width=$width", + "--height=$height", + @riglim, + $zoom, + @{$cgi->{version12}}, + @{$cgi->{version12_small}}, + @{$colors->{graph_colors}}, + "DEF:banr=$rrd:zfs" . $n . "_banr:AVERAGE", + "DEF:banw=$rrd:zfs" . $n . "_banw:AVERAGE", + "CDEF:banr_b=banr,1024,*", + "CDEF:banw_b=banw,1024,*", + "CDEF:n_banw_b=banw_b,-1,*", + "CDEF:allvalues=banr,banw,+", + @CDEF, + @tmpz); + $err = RRDs::error; + push(@output, "ERROR: while graphing $IMG_DIR" . "$IMGz[$e]: $err\n") if $err; + } + if($title || ($silent =~ /imagetag/ && $graph =~ /zfs5/)) { + if(lc($config->{enable_zoom}) eq "y") { + if(lc($config->{disable_javascript_void}) eq "y") { + push(@output, " {url} . "/" . $config->{imgs_dir} . $IMGz[$e] . "\">\n"); } else { if($version eq "new") { $picz_width = $picz->{image_width} * $config->{global_zoom}; diff -Nru monitorix-3.10.1/Makefile monitorix-3.11.0/Makefile --- monitorix-3.10.1/Makefile 2017-01-12 15:12:47.000000000 +0000 +++ monitorix-3.11.0/Makefile 2018-10-04 10:43:33.000000000 +0000 @@ -21,7 +21,7 @@ INSTALL_PROGRAM = $(INSTALL) -m755 INSTALL_DATA = $(INSTALL) -m644 INSTALL_DIR = $(INSTALL) -d -INSTALL_WORLDDIR = $(INSTALL) -dm777 +INSTALL_WORLDDIR = $(INSTALL) -dm755 Q = @ @@ -64,6 +64,7 @@ $(INSTALL_DATA) docs/$(PN).sysconfig "$(DESTDIR)$(CONFDIR)/sysconfig/$(PN)" $(INSTALL_DIR) "$(DESTDIR)$(LIBDIR)" + $(INSTALL_DATA) lib/ambsens.pm "$(DESTDIR)$(LIBDIR)/ambsens.pm" $(INSTALL_DATA) lib/apache.pm "$(DESTDIR)$(LIBDIR)/apache.pm" $(INSTALL_DATA) lib/apcupsd.pm "$(DESTDIR)$(LIBDIR)/apcupsd.pm" $(INSTALL_DATA) lib/bind.pm "$(DESTDIR)$(LIBDIR)/bind.pm" diff -Nru monitorix-3.10.1/man/man5/monitorix.conf.5 monitorix-3.11.0/man/man5/monitorix.conf.5 --- monitorix-3.10.1/man/man5/monitorix.conf.5 2018-03-15 07:05:23.000000000 +0000 +++ monitorix-3.11.0/man/man5/monitorix.conf.5 2019-03-13 08:02:09.000000000 +0000 @@ -1,9 +1,9 @@ .\" Monitorix manpage. -.\" Copyright (C) 2005-2018 by Jordi Sanfeliu +.\" Copyright (C) 2005-2019 by Jordi Sanfeliu .\" .\" This is the man page for the monitorix.conf configuration file. .\" -.TH monitorix.conf 5 "Mar 2018" 3.10.1 "Monitorix configuration file" +.TH monitorix.conf 5 "Mar 2019" 3.11.0 "Monitorix configuration file" .SH NAME monitorix.conf \- Configuration file for Monitorix. .SH DESCRIPTION @@ -15,6 +15,8 @@ .P It also creates a file called \fI/cgi/monitorix.conf.path\fP that includes the absolute path of the configuration file. This file will be read by \fBmonitorix.cgi\fP to determine the exact location of the configuration file. .SH CONFIGURATION OPTIONS +IMPORTANT NOTE: these options have default values that might vary depending on your operating system. Please check the configuration files in \fI/etc/monitorix/conf.d/\fP. +.P Blank lines are ignored, and whitespace before and after a token or value is ignored as well as tabulators, although a value can contain whitespace within. Lines which begin with a # are considered comments and ignored. .P If you want to comment out a large block you can use C-style comments. A /* signals the begin of a comment block and the */ signals the end of the comment block. @@ -269,7 +271,7 @@ .P Default value: \fI/monitorix-cgi\fP .RE -.SS Built-in HTTP server +.SS HTTP built-in server .BI enabled .RS This enables or disables the HTTP server that Monitorix has built-in. This is specially useful for system administrators that don't want to install a web server (Apache, Lighttpd, Nginx, etc.) to see the Monitorix graphs. @@ -331,11 +333,20 @@ .P .BI https_url .RS -This will force to use the prefix \fIhttps://\fP in all links. This is special useful if you plan to use a reverse-proxy HTTPS server in front of the Monitorix built-in HTTP. +This will force to use the prefix \fIhttps://\fP in all links. This is special useful if you plan to use a reverse-proxy HTTPS server in front of the Monitorix HTTP built-in server. +.P +Default value: \fIn\fP +.RE +.P +.BI autocheck_responsiveness +.RS +There is a well known problem with the HTTP built-in server that Monitorix implements using the Perl module 'HTTP::Server::Simple'. It looks like it's pretty weak to the common attacks that any web server receives every day. As a consequence of that, it just hangs, and when you want to see the stats of your server, you just see your browser waiting for a response that never comes, which ends up with a timeout. In these cases, you are forced to login to your server and restart Monitorix, in order to refresh the HTTP built-in server. .P -Default value: n +So in order to mitigate (hopefully) all this annoying hangups, this options acts like an autocheck to control the responsiveness of the HTTP server on every minute, and in case of no response then it will be restarted automatically. +.P +Default value: \fIy\fP .RE -.SS Built-in HTTP server with access authentication +.SS HTTP built-in server with access authentication .BI enabled .RS This enables or disables the authentication mechanism to control access to pages and other resources. The only allowed mechanism is Basic and uses the 401 status code and the WWW-Authenticate response header. @@ -489,14 +500,16 @@ .RS This enables or disables the monitoring of each graph. Placing a \fIy\fP on a desired graph and restarting Monitorix will automatically create the RRD file for that graph and start gathering information according to its settings. .RE -.SS System load average and usage (system.rrd) +.SS System load average and usage (system.pm) This graph shows information about system load average (classical UNIX triplet), memory allocation, active processes (on Linux brought directly from the /proc directory), entropy and the system uptime. .P .BI loadavg_enabled .RS This section enables or disables the alert capabilities for this graph. Only the alert for the average CPU load is currently implemented. It works as follows: .P -The CPU load average uses the third value (the one that represents the last 15 minutes of the load average), and if it reaches the \fBloadavg_threshold\fP value for the interval of time defined in \fBloadavg_timeintvl\fP, Monitorix will execute the external alert script defined in \fBloadavg_script\fP. +This alert uses the minimum value between the second and the third load averages (those that represent the last 5 and 15 minutes), and if it reaches the \fBloadavg_threshold\fP value for the interval of time defined in \fBloadavg_timeintvl\fP, Monitorix will execute the external alert script defined in \fBloadavg_script\fP. +.P +The idea to use \fImin(load5, load15)\fP is to obtain a more symmetric curve and a sooner cancellation of the alert. .P The default Monitorix installation includes an example of a shell-script alert called \fBmonitorix-alert.sh\fP which you can use as a base for your own script. .P @@ -533,7 +546,7 @@ .P Default value: \fI/path/to/script.sh\fP .RE -.SS Global kernel usage (kern.rrd) +.SS Global kernel usage (kern.pm) Note that the VFS graph is just informative of how the kernel is balancing its tables. .BI graph_mode .RS @@ -546,7 +559,7 @@ .RS This is the list of values offered in modern Linux kernels. Older Linux kernels or other Operating Systems may not have all of them. Placing a \fIy\fP or an \fIn\fP will enable or disable the value in the graph. .RE -.SS Kernel usage per processor (proc.rrd) +.SS Kernel usage per processor (proc.pm) .BI max .RS This is the number of processors or cores that your system has. There is no limit, however keep in mind that every time this number is changed Monitorix will resize the \fIproc.rrd\fP file accordingly, removing all historical data. @@ -589,7 +602,7 @@ .P Default value: \fIy\fP .RE -.SS HP ProLiant System Health (hptemp.rrd) +.SS HP ProLiant System Health (hptemp.pm) .BI list .RS This list will hold the defined temperature sensors for each graph. You must have installed the command \fIhplog\fP that comes with HP ProLiant System Health Application and Command Line Utilities. @@ -676,12 +689,12 @@ .RS .br - 2 = 3600, 40, /path/to/script + 2 = 3600, 40, /path/to/script.sh .br .P .RE -Such alert means that if the value of the sensor number 2 reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script\fP will be executed. +Such alert means that if the value of the sensor number 2 reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. .P The external script will receive the following arguments: .P @@ -693,7 +706,7 @@ 3rd - the value of the sensor. .P .RE -.SS LM-Sensors and GPU temperatures (lmsens.rrd) +.SS LM-Sensors and GPU temperatures (lmsens.pm) .BI list .RS In this list you may specify the sensors you want to monitor with the same names as they appear in your \fIsensors\fP(1) command. @@ -853,12 +866,12 @@ .RS .br - core0 = 3600, 40, /path/to/script + core0 = 3600, 40, /path/to/script.sh .br .P .RE -Such alert means that if the value of the sensor core0 reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script\fP will be executed. +Such alert means that if the value of the sensor core0 reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. .P The external script will receive the following arguments: .P @@ -870,7 +883,7 @@ 3rd - the value of the sensor. .P .RE -.SS Generic sensors statistics (gensens.rrd) +.SS Generic sensors statistics (gensens.pm) This graph is able to monitor up to 9 temperatures and CPU frequencies which, depending of your machine, should appear in the \fI/sys/devices\fP directory. .P .BI list @@ -960,7 +973,7 @@ .P .BI alerts .RS -This optional list enables the alert capabilities for this graph and complements with the \fBlist\fP option. Each alert has three fields separated by comma: the \fItime interval\fP, the \fIthreshold\fP and the path to the \fIscript\fP to be executed. +This optional list enables the alert capabilities for this graph and complements with the \fBlist\fP option. Each alert has four fields separated by comma: the \fItime interval\fP, the \fIthreshold\fP, the path to the \fIscript\fP to be executed and \fIwhen\fP the alert must be triggered. the last field is optional. .P The \fItime interval\fP is the period of time (in seconds) that the \fIthreshold\fP needs to be exceeded before the external script is executed. .P @@ -968,6 +981,8 @@ .P The \fIscript\fP is the full path name of the script that will be executed by this alert. .P +The \fIwhen\fP value specifies when the alert must be triggered (\fIabove\fP or \fIbelow\fP) the threshold, being \fIabove\fP the default value when it's not specified. +.P Each defined sensor has its own alert. .P The default Monitorix installation includes an example of a shell-script alert called \fImonitorix-alert.sh\fP which you can use as a base for your own script. @@ -977,12 +992,16 @@ .RS .br - temp0 = 3600, 40, /path/to/script + temp0 = 3600, 40, /path/to/script.sh, above +.br + temp1 = 3600, 10, /path/to/script.sh, below .br .P .RE -Such alert means that if the value of the sensor temp0 reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script\fP will be executed. +The first alert means that if the value of the sensor temp0 exceeds above 40 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. +.P +The second alert means that if the value of the sensor temp1 exceeds below 10 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. .P The external script will receive the following arguments: .P @@ -992,9 +1011,11 @@ 2nd - the value defined as \fIthreshold\fP. .br 3rd - the value of the sensor. +.br +4th - the direction or when that alert was triggered by (above or below). .P .RE -.SS IPMI sensor statistics (ipmi.rrd) +.SS IPMI sensor statistics (ipmi.pm) This graph is able to monitor an unlimited number of IPMI sensors (temperatures, fans and voltages). .P .BI list @@ -1054,14 +1075,14 @@ .RS .br - CPU_Temp = 3600, 40, /path/to/script + CPU_Temp = 3600, 40, /path/to/script.sh .br .P Notice that the spaces in the sensor's name must be converted to underscores, since a variable can hold spaces in its name. .P .RE -Such alert means that if the value of the sensor CPU_Temp reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script\fP will be executed. +Such alert means that if the value of the sensor CPU_Temp reaches or exceeds 40 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. .P The external script will receive the following arguments: .P @@ -1094,7 +1115,102 @@ .RS Default value: \fInone\fP .RE -.SS NVIDIA temperatures and usage (nvidia.rrd) +.SS Ambient sensor statistics (ambsens.pm) +This graph is able to monitor an unlimited number of ambient sensors (temperatures, humidity, barometer, etc.). +.P +.BI list +.RS +This is a comma-separated list that describes the type of sensors in \fBdesc\fP. Put one description for each type. For every type specified you need to specify its sensors in the \fBdesc\fP option. Each one most be referenced as a numeric value starting from zero in the \fBdesc\fP option. There you will define all the sensors than come with that type of sensor. +.P +WARNING: Every time the number of entries in this option changes, Monitorix will resize the \fIambsens.rrd\fP file accordingly, removing all historical data. +.P +An example would be: +.P +list = Ambient temperature, Humidity +.RE +.P +.BI desc +.RS +This is a list of sensors per type defined. The name is irrelevant. +.P + +.br + 0 = at1, at2, at3 +.br + 1 = h0 +.br + +.P +The maximum number of sensors allowed for each type is 9. +.RE +.P +.BI units +.RS +This is the class of sensor for each type. It's important to not mix different type of sensors in a same group. This value is informative only, it's mostly used as a title for the y-axis in the graphs. +.RE +.P +.BI cmd +.RS +This list complements the \fBdesc\fP option. It basically allows you to associate a script or program that will be executed to retrieve the value for each sensor. +.RE +.P +.BI map +.RS +This list complements the \fBdesc\fP option. It basically allows you to change the name that will appear in the graph, hiding the real name of the sensor. If no association is defined, then Monitorix will display the name specified in the \fBdesc\fP option. Note, this only works in names that don't include whitespaces. +.RE +.P +.BI alerts +.RS +This optional list enables the alert capabilities for this graph and complements with the \fBlist\fP option. Each alert has four fields separated by comma: the \fItime interval\fP, the \fIthreshold\fP, the path to the \fIscript\fP to be executed and \fIwhen\fP the alert must be triggered. the last field is optional. +.P +The \fItime interval\fP is the period of time (in seconds) that the \fIthreshold\fP needs to be exceeded before the external script is executed. +.P +The \fIthreshold\fP is the value (either temperature or HZ) that needs to be reached or exceeded within the specified time in \fItime interval\fP to execute the external script. +.P +The \fIscript\fP is the full path name of the script that will be executed by this alert. +.P +The \fIwhen\fP value specifies when the alert must be triggered (\fIabove\fP or \fIbelow\fP) the threshold, being \fIabove\fP the default value when it's not specified. +.P +Each defined sensor has its own alert. +.P +The default Monitorix installation includes an example of a shell-script alert called \fImonitorix-alert.sh\fP which you can use as a base for your own script. +.P +The following is an example of an alert defined for the first temperature sensor: +.P +.RS + +.br + temp0 = 3600, 40, /path/to/script.sh, above +.br + temp1 = 3600, 10, /path/to/script.sh, below +.br + +.P +.RE +The first alert means that if the value of the sensor temp0 exceeds above 40 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. +.P +The second alert means that if the value of the sensor temp1 exceeds below 10 during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. +.P +The external script will receive the following arguments: +.P +.RS +1st - the value defined as \fItime interval\fP. +.br +2nd - the value defined as \fIthreshold\fP. +.br +3rd - the value of the sensor. +.br +4th - the direction or when that alert was triggered by (above or below). +.P +.RE +.RE +.BI graphs_per_row +.RS +This is the number of graphs that will be put in a row. +.P +Default value: \fI2\fP +.RE +.SS NVIDIA temperatures and usage (nvidia.pm) This graph requires to have installed the official NVIDIA drivers. .P .BI max @@ -1105,7 +1221,7 @@ .P Default value: \fI1\fP .RE -.SS Disk drive temperatures and health (disk.rrd) +.SS Disk drive temperatures and health (disk.pm) This graph is able to monitor an unlimited number of disk drives. .P .BI list @@ -1225,7 +1341,7 @@ .P Default value: \fIn\fP .RE -.SS Filesystem usage and I/O activity (fs.rrd) +.SS Filesystem usage and I/O activity (fs.pm) This graph is able to monitor an unlimited number of filesystems. .P .BI list @@ -1331,12 +1447,12 @@ .RS .br - / = 3600, 98, /path/to/script + / = 3600, 98, /path/to/script.sh .br .P .RE -Such alert means that if the percentage of disk space used in the root filesystem reaches or exceeds 98 (more than 98) during at least one hour (3600 seconds) the script in \fI/path/to/script\fP will be executed. +Such alert means that if the percentage of disk space used in the root filesystem reaches or exceeds 98 (more than 98) during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. .P The external script will receive the following arguments: .P @@ -1348,7 +1464,7 @@ 3rd - the filesystem disk usage. .P .RE -.SS ZFS statistics (zfs.rrd) +.SS ZFS statistics (zfs.pm) This graph is able to monitor an unlimited number of pools. .P .BI max_pools @@ -1362,7 +1478,7 @@ .RS This is a comma-separated list of pool names. The number of pool names defined here can't be greater than the number defined in \fBmax_pools\fP. .RE -.SS Directory usage statistics (du.rrd) +.SS Directory usage statistics (du.pm) This graph is able to monitor the usage of an unlimited number of directories. .P IMPORTANT NOTE: The \fIdu\fP command makes intensive disk I/O access that might slow down the whole system. Moreover, continued executions of this command will affect the buffer cache mechanism and this will also increase the system response time. @@ -1393,6 +1509,27 @@ The maximum number of directories allowed for each group is 9. .RE .P +.BI type +.RS +This specifies the information that will be presented for each directory specified in each list. It accepts two possible values: +.P +.RS +\fIsize\fP for the directory size (which is the default option). +.br +\fIfiles\fP for the number of files inside the directory. +.RE +.P +An example would be: +.P + +.br + 0 = size +.br + 1 = files +.br + +.RE +.P .BI dirmap .RS This list complements the \fBdesc\fP option. It basically allows you to change the name that will appear in the graph, hiding the real name of the directory. If no association is defined, then Monitorix will display the name specified in the \fBdesc\fP option. @@ -1414,7 +1551,7 @@ .RE .P IMPORTANT NOTICE: Keep in mind that including certain flags like '-h' (which gives results in human readable format) could make Monitorix unable to interpret the results. -.SS Network traffic and usage (net.rrd) +.SS Network traffic and usage (net.pm) .P .BI max .RS @@ -1454,11 +1591,23 @@ .RS This is where the network interface that acts as the gateway for this server is defined. This is mainly used if you plan to monitor network traffic usage of your devices/networks using the \fBtraffacct\fP graph below. .RE -.SS Netstat statistics (netstat.rrd) +.SS Netstat statistics (netstat.pm) This graph shows the state of the all IPv4 and IPv6 network connections. .P -Only the limit and rigid values can be set here. -.SS Traffic Control statistics (tc.rrd) +Only the command to be used can be set here, besides the limit and rigid values. +.P +.BI cmd +.RS +This is the command that will be used to gather statistics. There are two possible values: +.P +.RS +\fIss\fP +.br +\fInetstat\fP +.RE +.P +Default value: \fIss\fP +.SS Traffic Control statistics (tc.pm) This graph is able to monitor an unlimited number of network interfaces managed by the \fItc\fP command. .P .BI list @@ -1518,7 +1667,7 @@ .RE .RE -.SS Libvirt statistics (libvirt.rrd) +.SS Libvirt statistics (libvirt.pm) This graph is able to monitor an unlimited number of virtual machines managed by Libvirt. .P .BI cmd @@ -1610,7 +1759,7 @@ .br .P This option also allows you to change the name that will appear in the graph, hiding the real name of the virtual machine. If no association is defined, then Monitorix will display the name specified in the \fBlist\fP option. -.SS Process statistics (process.rrd) +.SS Process statistics (process.pm) This graph is able to monitor an unlimited number of processes. This graph requires a Linux kernel version 2.6.20 at least to support process I/O accounting. Some systems with older kernels might also have been ported it though. .P .BI list @@ -1625,7 +1774,7 @@ # ps -eo pid,comm,command .P .RE -Therefore names in the process list must *EXACTLY* correspond to those in the \fIcomm\fP (or \fIcommand\fP) field of the above command (no substring, no wildcard). +Therefore names in the process list can be either exactly to the process name as it appears in the \fIcomm\fP columns, or just a substring of the process name that appears in the \fIcommand\fP column. .P An example of this option would be: .P @@ -1657,7 +1806,7 @@ .RE .P You can define as much entries as you want. -.SS System services demand (serv.rrd) +.SS System services demand (serv.pm) This graph requires either \fIMailScanner\fP or \fIamavisd-new\fP mail scanners in order to account spam and virus emails. .P .BI mode @@ -1672,7 +1821,7 @@ .P Default value: \fIi\fP .RE -.SS Mail statistics (mail.rrd) +.SS Mail statistics (mail.pm) This graph requires either \fIMailScanner\fP or \fIamavisd-new\fP mail scanners in order to account spam and virus emails. Spamassassin and Clamav antivirus are also used for spam and virus email accounting. .P .BI mta @@ -1682,6 +1831,8 @@ \fISendmail\fP .br \fIPostfix\fP +.br +\fIExim\fP .RE .P NOTE: the \fIpflogsumm\fP utility is required when using the \fBPostfix\fP MTA. @@ -1806,7 +1957,7 @@ .P Default value: \fI/path/to/script.sh\fP .RE -.SS Network port traffic (port.rrd) +.SS Network port traffic (port.pm) This graph requires the \fIiptables\fP(8) command and optionally the \fIip6tables\fP(8) command on Linux systems and the \fIipfw\fP command on *BSD systems. .P .BI max @@ -1875,9 +2026,9 @@ .P Default value: \fI3\fP .RE -.SS Users using the system (user.rrd) +.SS Users using the system (user.pm) Only the limit and rigid values can be set here. -.SS FTP statistics (ftp.rrd) +.SS FTP statistics (ftp.pm) This graph supports currently ProFTPD, vsftpd and Pure-FTPd log file formats. .P For best results with the ProFTPD server I recommend to add the following line in its configuration file: @@ -1908,7 +2059,7 @@ .P Default value: \fIanonymous, ftp\fP .RE -.SS Apache statistics (apache.rrd) +.SS Apache statistics (apache.pm) This graph requires that \fImod_status\fP be loaded and \fIExtendedStatus\fP option set to \fIOn\fP in order to collect full status information of the Apache web server. .P This graph is able to monitor an unlimited number of local and remote Apache web servers. @@ -1941,12 +2092,12 @@ .RS .br - http://localhost/server-status?auto = 3600, 5, /path/to/script + http://localhost/server-status?auto = 3600, 5, /path/to/script.sh .br .P .RE -Such alert means that if the remaining free slots reaches or exceeds 5 (less than 5) during at least one hour (3600 seconds) the script in \fI/path/to/script\fP will be executed. +Such alert means that if the remaining free slots reaches or exceeds 5 (less than 5) during at least one hour (3600 seconds) the script in \fI/path/to/script.sh\fP will be executed. .P The external script will receive the following arguments: .P @@ -1958,7 +2109,7 @@ 3rd - the remaining free slots. .P .RE -.SS Nginx statistics (nginx.rrd) +.SS Nginx statistics (nginx.pm) This graph may require adding some lines in the configuration file \fInginx.conf\fP. Please see the \fIREADME.nginx\fP file to determine the exact steps needed to configure Nginx to get status information. .P This graph requires the \fIiptables\fP(8) command on Linux systems, and the \fIipfw\fP command on *BSD systems. @@ -1983,7 +2134,7 @@ .P Default value: \fI24100\fP .RE -.SS Lighttpd statistics (lighttpd.rrd) +.SS Lighttpd statistics (lighttpd.pm) This graph requires that \fImod_status\fP is loaded in order to collect status information from the Lighttpd web server. .P This graph is able to monitor an unlimited number of local and remote Lighttpd web servers. @@ -1996,7 +2147,7 @@ .P Default value: \fIhttp://localhost/server-status?auto\fP .RE -.SS MySQL statistics (mysql.rrd) +.SS MySQL statistics (mysql.pm) This graph requires that you create a password protected MySQL user that is NOT granted privileges on any DB. .P Example: @@ -2110,7 +2261,7 @@ Therefore this value helps to know how many tmp tables go to the disk instead than to the memory. Keep in mind that some large queries, involving TEXT and BLOB columns, are directly written to the disk instead than to the memory, because they would be too big. So you probably will want to avoid having a high % of tmp tables written to the disk, but you will never reach 0% on a big site, and this is fine. .br Lower is better ... but 0% is not reachable and you should not try to reach it, usually. -.SS MongoDB statistics (mongodb.rrd) +.SS MongoDB statistics (mongodb.pm) This graph is able to monitor an unlimited number of MongoDB servers. .P .BI list @@ -2170,11 +2321,11 @@ .P Default value: \fImydb\fP .RE -.SS Varnish cache statistics (varnish.rrd) +.SS Varnish cache statistics (varnish.pm) This graph monitors a local installation of the Varnish HTTP accelerator. .P Only the limit and rigid values can be set here. -.SS PageSpeed Module statistics (pagespeed.rrd) +.SS PageSpeed Module statistics (pagespeed.pm) This graph is able to monitor an unlimited number of PageSpeed installations. .P .BI list @@ -2187,7 +2338,7 @@ .RE .P For more information please refer to https://developers.google.com/speed/pagespeed/module and http://stackoverflow.com/questions/9115595/what-do-the-mod-pagespeed-statistics-mean -.SS Squid Proxy Web Cache (squid.rrd) +.SS Squid Proxy Web Cache (squid.pm) .P .BI cmd .RS @@ -2206,7 +2357,7 @@ .P Each graph has a limit number of 9 entries. .RE -.SS NFS server statistics (nfss.rrd) +.SS NFS server statistics (nfss.pm) .P .BI version .RS @@ -2234,7 +2385,7 @@ .P Each graph has a limit number of 10 entries. .RE -.SS NFS client statistics (nfsc.rrd) +.SS NFS client statistics (nfsc.pm) .P .BI version .RS @@ -2276,7 +2427,7 @@ .br \fBgraph_5\fP up to 4 entries. .RE -.SS BIND statistics (bind.rrd) +.SS BIND statistics (bind.pm) This graph requires a BIND server with version 9.5 or higher, and in order to see all statistics provided by BIND you must configure the \fIstatistics-channels\fP option like this: .P statistics-channels { @@ -2362,7 +2513,7 @@ .P The maximum number of RR types allowed for this graph is 20. .RE -.SS NTP statistics (ntp.rrd) +.SS NTP statistics (ntp.pm) This graph is able to monitor an unlimited number of NTP servers. .P .BI list @@ -2403,7 +2554,7 @@ .P Monitorix will add this extra argument to the NTP command which will become as "ntpq -pn -4". .RE -.SS Chrony statistics (chrony.rrd) +.SS Chrony statistics (chrony.pm) This graph is able to monitor an unlimited number of Chrony daemons. .P .BI list @@ -2414,7 +2565,7 @@ .P Default value: \fIlocalhost\fP .RE -.SS Fail2ban statistics (fail2ban.rrd) +.SS Fail2ban statistics (fail2ban.pm) This graph is able to monitor an unlimited number of Fail2ban jails. .P .BI list @@ -2449,7 +2600,7 @@ .P Default value: \fI2\fP .RE -.SS Icecast Streaming Media Server (icecast.rrd) +.SS Icecast Streaming Media Server (icecast.pm) This graph is able to monitor an unlimited number of Icecast servers. .P .BI list @@ -2480,7 +2631,7 @@ .P Default value: \fIr\fP .RE -.SS Raspberry Pi sensor statistics (raspberrypi.rrd) +.SS Raspberry Pi sensor statistics (raspberrypi.pm) .P For more information please refer to http://elinux.org/RPI_vcgencmd_usage. .P @@ -2512,7 +2663,7 @@ .P The maximum number of clocks allowed is 6. .RE -.SS Alternative PHP Cache statistics (phpapc.rrd) +.SS Alternative PHP Cache statistics (phpapc.pm) This graph is able to monitor an unlimited number of PHP-APC installations. .P .BI list @@ -2523,7 +2674,7 @@ .P Default value: \fIhttp://localhost/apc.php?auto\fP .RE -.SS Memcached statistics (memcached.rrd) +.SS Memcached statistics (memcached.pm) This graph is able to monitor an unlimited number of Memcached installations. .P .BI list @@ -2534,7 +2685,7 @@ .P Default value: \fIlocalhost:11211\fP .RE -.SS APC UPS statistics (apcupsd.rrd) +.SS APC UPS statistics (apcupsd.pm) This graph is able to monitor an unlimited number of APC UPS (apcupsd) installations. .P .BI cmd @@ -2552,7 +2703,7 @@ .P Default value: \fIlocalhost:3551\fP .RE -.SS Network UPS Tools statistics (nut.rrd) +.SS Network UPS Tools statistics (nut.pm) This graph is able to monitor an unlimited number of Network UPS Tools (upsc) installations. .P .BI list @@ -2565,7 +2716,7 @@ .P Default value: \fIups@localhost\fP .RE -.SS Wowza Media Server (wowza.rrd) +.SS Wowza Media Server (wowza.pm) This graph is able to monitor an unlimited number of Wowza servers. .P .BI list @@ -2589,11 +2740,11 @@ .P The maximum number of applications allowed for each URL is 8. .RE -.SS Devices interrupt activity (int.rrd) +.SS Devices interrupt activity (int.pm) Only the limit and rigid values can be set here. -.SS Verlihub statistics (verlihub.rrd) +.SS Verlihub statistics (verlihub.pm) This graph monitors the Verlihub software for DC++ network. -.SS Monitoring the Internet traffic of your LAN (traffacct.rrd) +.SS Monitoring the Internet traffic of your LAN (traffacct.pm) If your server acts as the gateway for a group of PCs, devices or even whole networks in your local LAN, you may want to know how much Internet traffic each one is generating. .P This graph requires the \fIiptables\fP(8) command on GNU/Linux systems, and the \fIipfw\fP command on *BSD systems. @@ -2654,7 +2805,7 @@ \fP section (near the end) of the \fImonitorix.conf\fP file. +.P +Default value: "\fISystem load\fP" +.RE +.P .BI remotehost_list .RS This is a comma-separated list with descriptive names of remote servers with Monitorix already installed and working that you plan to monitor from here. @@ -2751,7 +2913,7 @@ .RE .P -As you can see all these three entries use URLs to designate the location of each remote server. This means that each server most also have been enabled the built-in HTTP server, or have been installed a CGI capable web server like Apache. +As you can see all these three entries use URLs to designate the location of each remote server. This means that each server most also have been enabled the HTTP built-in server, or have been installed a CGI capable web server like Apache. .RE .P .BI groups @@ -2908,7 +3070,7 @@ .SH AUTHOR Monitorix is written by Jordi Sanfeliu .SH COPYRIGHT -Copyright \(co 2005-2018 Jordi Sanfeliu +Copyright \(co 2005-2019 Jordi Sanfeliu .br Licensed under the GNU General Public License version 2 (GPLv2). .SH SEE ALSO diff -Nru monitorix-3.10.1/man/man8/monitorix.8 monitorix-3.11.0/man/man8/monitorix.8 --- monitorix-3.10.1/man/man8/monitorix.8 2018-03-15 07:05:06.000000000 +0000 +++ monitorix-3.11.0/man/man8/monitorix.8 2019-03-11 10:04:47.000000000 +0000 @@ -1,9 +1,9 @@ .\" Monitorix manpage. -.\" Copyright (C) 2005-2018 by Jordi Sanfeliu +.\" Copyright (C) 2005-2019 by Jordi Sanfeliu .\" .\" This is the man page for the monitorix collector daemon. .\" -.TH monitorix 8 "Mar 2018" 3.10.1 "Monitorix collector daemon" +.TH monitorix 8 "Mar 2019" 3.11.0 "Monitorix collector daemon" .SH NAME monitorix - a lightweight system monitoring tool .SH SYNOPSIS @@ -54,7 +54,7 @@ .SH AUTHOR Monitorix is written by Jordi Sanfeliu .SH COPYRIGHT -Copyright \(co 2005-2018 Jordi Sanfeliu +Copyright \(co 2005-2019 Jordi Sanfeliu .br Licensed under the GNU General Public License version 2 (GPLv2). .SH "SEE ALSO" diff -Nru monitorix-3.10.1/monitorix monitorix-3.11.0/monitorix --- monitorix-3.10.1/monitorix 2018-03-15 07:04:47.000000000 +0000 +++ monitorix-3.11.0/monitorix 2019-03-14 13:56:31.000000000 +0000 @@ -2,7 +2,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -42,11 +42,10 @@ $SIG{'TRAP'} = 'INT_handler'; $SIG{'STOP'} = 'INT_handler'; $SIG{'TERM'} = 'INT_handler'; -$SIG{'CHLD'} = 'CHLD_handler'; $SIG{'HUP' } = 'HUP_handler'; -use constant VERSION => "3.10.1"; -use constant RELDATE => "15-Mar-2018"; +use constant VERSION => "3.11.0"; +use constant RELDATE => "14-Mar-2019"; my @suppsys = ("Linux", "FreeBSD", "OpenBSD", "NetBSD"); our %config; @@ -64,20 +63,18 @@ exit(0); } -sub CHLD_handler { - my $pid = waitpid(-1, WNOHANG); -} - sub HUP_handler { my ($signal) = @_; my $myself = (caller(0))[3]; + return if $options{n}; # only continue if it's a daemon + my (undef, undef, $uid) = getpwnam($config{httpd_builtin}->{user}); my (undef, undef, $gid) = getgrnam($config{httpd_builtin}->{group}); logger("SIG$signal caught."); - # upon receiving a SIGHUP signal a new logfile opened + # upon receiving SIGHUP a new logfile is opened close(STDOUT); close(STDERR); open(STDOUT, ">> $config{log_file}") || logger("Can't write to LOG: $!"); @@ -85,11 +82,16 @@ chmod(0600, $config{log_file}); logger("$myself: opening a new log file."); - # create the HTTPd logfile - open(OUT, "> " . $config{httpd_builtin}->{log_file}); - close(OUT); - chown($uid, $gid, $config{httpd_builtin}->{log_file}); - chmod(0600, $config{httpd_builtin}->{log_file}); + # restart HTTP built-in + if(lc($config{httpd_builtin}->{enabled}) eq "y") { + if(defined($config{httpd_pid})) { + require HTTPServer; + kill(15, $config{httpd_pid}); + kill(9, $config{httpd_pid}); + httpd_setup(\%config, $options{d}); + logger("Restarted HTTP built-in server (pid $config{httpd_pid}).") if (defined($config{httpd_pid})); + } + } } sub daemonize { @@ -120,6 +122,9 @@ my $title_fore_color; my $piwik_code = ""; my ($piwik_url, $piwik_sid, $piwik_img); + my $text_when_all; + my $value_when_all; + my $when_all_code = ""; # keep backwards compatibility for v3.2.1 and less if(ref($config{theme}) ne "HASH") { @@ -146,8 +151,37 @@ $title_fore_color = $config{theme}->{$theme}->{title_fg}; } + # Default option in 'Graph' list when 'All' is selected in 'Hostname' list. + # + # The following small JavaScript function is intended to avoid to select to view + # accidentally (unless explicitly selected by the user) a huge amount of remote + # images that will hang the browser for a while. + $text_when_all = $config{multihost}->{default_option_when_all}; + my @match = grep { $config{graphs}{$_} eq $text_when_all } keys %{$config{graphs}}; + $value_when_all = $match[0] || ""; + if(!$value_when_all) { + logger("$myself: ERROR: invalid value in 'default_option_when_all' option ('$text_when_all')."); + $value_when_all = "_system1"; + } + $when_all_code = <<"EOF"; + + + +EOF + # Piwik tracking code - if(lc($config{piwik_tracking}->{enabled}) eq "y") { + if(lc($config{piwik_tracking}->{enabled} || "") eq "y") { $piwik_url = $config{piwik_tracking}->{url} || ""; $piwik_sid = $config{piwik_tracking}->{sid} || ""; $piwik_img = $config{piwik_tracking}->{img} || ""; @@ -190,6 +224,7 @@ $piwik_code + $when_all_code


@@ -225,12 +260,12 @@ EOF print(OUT " \n"); - print(OUT " \n"); print(OUT " \n"); print(OUT " \n"); print(OUT " \n"); - if(scalar(my @remotehost_list = split(',', $config{multihost}->{remotehost_list})) && lc($config{multihost}->{enabled}) eq "y") { + if(scalar(my @remotehost_list = split(',', $config{multihost}->{remotehost_list})) && lc($config{multihost}->{enabled} || "") eq "y") { print(OUT " \n"); print(OUT " \n"); for($n = 0; $n < scalar(@remotehost_list); $n++) { @@ -249,7 +284,7 @@ } } - if(scalar(my @tal = split(',', $config{traffacct}->{list})) && lc($config{traffacct}->{enabled}) eq "y") { + if(scalar(my @tal = split(',', $config{traffacct}->{list})) && lc($config{traffacct}->{enabled} || "") eq "y") { print(OUT " \n"); print(OUT " \n"); for($n = 0; $n < scalar(@tal); $n++) { @@ -263,7 +298,7 @@ print(OUT " \n"); - print(OUT " \n"); print(OUT " \n"); foreach (split(',', $config{graph_name})) { my $g = trim($_); @@ -284,6 +319,14 @@ } next; } + if($g eq "ambsens") { + for($n = 0; $n < scalar(my @ambsens_list = split(',', $config{ambsens}->{list})); $n++) { + my $name = trim($ambsens_list[$n]); + $gname = "_" . $g; + print(OUT " \n"); + } + next; + } if($g eq "fs" || $g eq "process") { $n = 0; foreach my $k (sort keys %{$config{graphs}}) { @@ -454,7 +497,7 @@ usage(); exit(1); } -$options{c} = abs_path($options{c}) unless $^V lt 5.6.2; +$options{c} = (abs_path($options{c}) || $options{c}) unless $^V lt 5.6.2; if(!stat($options{c})) { die "can't open file '$options{c}': $!"; } @@ -600,6 +643,26 @@ logger("WARNING: the 'max' option in 'net.pm' doesn't exist. Please consider upgrading your configuration file."); $config{net}->{max} = 10; } +if(!$config{global_zoom}) { + logger("WARNING: the 'global_zoom' option is not valid or doesn't exist. Please consider upgrading your configuration file."); + # it's set in 'monitorix.cgi' +} +if(!$config{image_format}) { + logger("WARNING: the 'image_format' option is not valid or doesn't exist. Please consider upgrading your configuration file."); + # it's set in 'monitorix.cgi' +} +if(!defined($config{logo_top_url})) { + logger("WARNING: the 'logo_top_url' option doesn't exist. Please consider upgrading your configuration file."); + $config{logo_top_url} = "http://www.monitorix.org/"; +} +if(!$config{httpd_builtin}->{autocheck_responsiveness}) { + logger("WARNING: the 'autocheck_responsiveness' option is not valid or doesn't exist. Please consider upgrading your configuration file."); + $config{httpd_builtin}->{autocheck_responsiveness} = "y"; +} +if(!$config{multihost}->{default_option_when_all}) { + logger("WARNING: the 'default_option_when_all' option is not valid or doesn't exist. Please consider upgrading your configuration file."); + $config{multihost}->{default_option_when_all} = "System load"; +} # make sure that there aren't residual Monitorix iptables rules flush_accounting_rules(\%config, $options{d}); @@ -608,7 +671,7 @@ # check for inconsistencies between enabled graphs and defined graphs foreach my $g (sort keys %{$config{graph_enable}}) { - if(lc($config{graph_enable}->{$g}) eq "y") { + if(lc($config{graph_enable}->{$g} || "") eq "y") { if(!grep {trim($_) eq $g} (split(',', $config{graph_name}))) { logger("WARNING: inconsitency between '' and 'graph_name' options; '$g' doesn't exist."); } @@ -621,9 +684,9 @@ my $e = "n"; if($g eq "traffacct") { - $e = lc($config{$g}->{enabled}); + $e = lc($config{$g}->{enabled} || ""); } else { - $e = lc($config{graph_enable}->{$g}); + $e = lc($config{graph_enable}->{$g} || ""); } if($e eq "y") { @@ -654,30 +717,21 @@ } logger("Generating the 'index.html' file."); -if(!defined($config{logo_top_url})) { - logger("WARNING: the 'logo_top_url' option doesn't exist. Please consider upgrading your configuration file."); - $config{logo_top_url} = "http://www.monitorix.org/"; -} create_index(); # start the HTTP built-in (if enabled) if(lc($config{httpd_builtin}->{enabled}) eq "y") { + logger("Setting owner/group and permission bits for the imgs/ directory.") if defined($options{d}); + my (undef, undef, $uid) = getpwnam($config{httpd_builtin}->{user}); + my (undef, undef, $gid) = getgrnam($config{httpd_builtin}->{group}); + chown($uid, $gid, $config{base_dir} . "/" . $config{imgs_dir}); + chmod(0755, $config{base_dir} . "/" . $config{imgs_dir}); + require HTTPServer; httpd_setup(\%config, $options{d}); - logger("Started built-in HTTP server (pid $config{httpd_pid}).") if (defined($config{httpd_pid})); + logger("Started HTTP built-in server (pid $config{httpd_pid}).") if (defined($config{httpd_pid})); } -# make sure that some options are correctly defined -if(!$config{global_zoom}) { - logger("WARNING: the 'global_zoom' option is not valid or doesn't exist. Please consider upgrading your configuration file."); - # it's set in 'monitorix.cgi' -} -if(!$config{image_format}) { - logger("WARNING: the 'image_format' option is not valid or doesn't exist. Please consider upgrading your configuration file."); - # it's set in 'monitorix.cgi' -} - - setpriority(0, 0, $config{priority} || 0); logger("Ok, ready."); @@ -791,5 +845,36 @@ } } } + + # check if the HTTP built-in server is responsive + if(lc($config{httpd_builtin}->{enabled}) eq "y") { + if(lc($config{httpd_builtin}->{autocheck_responsiveness}) eq "y") { + use LWP::UserAgent; + my $pid = fork(); + if(!$pid) { + my $url = "http://localhost:" . $config{httpd_builtin}->{port} . $config{base_url}; + my $ua = LWP::UserAgent->new(timeout => 30); + my $response = $ua->request(HTTP::Request->new('GET', $url)); + if(!$response->is_success) { + logger("WARNING: unable to connect to HTTP built-in server '$url'."); + exit(1); + } + exit(0); + } + waitpid($pid, 0); + # waitpid sets the child's status in $? + if($? != 0) { + # restart HTTP built-in server + if(defined($config{httpd_pid})) { + require HTTPServer; + kill(15, $config{httpd_pid}); + kill(9, $config{httpd_pid}); + httpd_setup(\%config, $options{d}); + logger("Restarted HTTP built-in server (pid $config{httpd_pid}).") if defined($config{httpd_pid}); + } + } + } + } } + waitpid(-1, WNOHANG); } diff -Nru monitorix-3.10.1/monitorix.cgi monitorix-3.11.0/monitorix.cgi --- monitorix-3.10.1/monitorix.cgi 2018-03-15 07:04:32.000000000 +0000 +++ monitorix-3.11.0/monitorix.cgi 2019-01-16 11:28:24.000000000 +0000 @@ -2,7 +2,7 @@ # # Monitorix - A lightweight system monitoring tool. # -# Copyright (C) 2005-2017 by Jordi Sanfeliu +# Copyright (C) 2005-2019 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 @@ -21,6 +21,7 @@ use strict; use warnings; +use File::Basename; use FindBin qw($Bin); use lib $Bin . "/lib", "/usr/lib/monitorix"; @@ -94,76 +95,117 @@ my $graph = ($cgi->{graph} eq "all" || $cgi->{graph} =~ m/group\[0-9]*/) ? "_system1" : $cgi->{graph}; if($cgi->{val} eq "all" || $cgi->{val} =~ m/group[0-9]*/) { - for($n = 0; $n < scalar(@host); $n += $multihost->{graphs_per_row}) { + if($cgi->{graph} eq "all") { print "\n"; - print " \n"; - for($n2 = 0; $n2 < $multihost->{graphs_per_row}; $n2++) { - if($n < scalar(@host)) { - print " \n"; + my $g = 0; + foreach (split(',', $config{graph_name})) { + my $gn = trim($_); + if(lc($config{graph_enable}->{$gn}) eq "y") { + if(!$g) { + print " \n"; + for($n = 0; $n < scalar(@host); $n++) { + print " \n"; + } + print " \n"; + } + for(my $sg = 1; $config{graphs}->{"_$gn$sg"}; $sg++) { + my $sgd = $sg; + if($gn eq "fs" || $gn eq "net") { + $sgd = sprintf("%02d", $sg); + } + print " \n"; + for($n = 0; $n < scalar(@host); $n++) { + print " \n"; + } + print " \n"; + } } - $n++; + $g++; } - print " \n"; - print " \n"; - for($n2 = 0, $n = $n - $multihost->{graphs_per_row}; $n2 < $multihost->{graphs_per_row}; $n2++) { - if($n < scalar(@host)) { - print " \n"; - + print "
\n"; - print " \n"; - print "   " . $host[$n] . "\n"; - print " \n"; - print "
\n"; + print " \n"; + print "   " . $host[$n] . "\n"; + print " \n"; + print "
\n"; + print " \n"; + print "
\n"; - print " \n"; - print "
\n"; + print "
\n"; + } else { + for($n = 0; $n < scalar(@host); $n += $multihost->{graphs_per_row}) { + print "\n"; + print " \n"; + for($n2 = 0; $n2 < $multihost->{graphs_per_row}; $n2++) { + if($n < scalar(@host)) { + print " \n"; + } + $n++; } - $n++; - } - print " \n"; - print " \n"; - for($n2 = 0, $n = $n - $multihost->{graphs_per_row}; $n2 < $multihost->{graphs_per_row}; $n2++) { - if($n < scalar(@host)) { - if(lc($multihost->{footer_url}) eq "y") { - print " \n"; + print " \n"; + print " \n"; + for($n2 = 0, $n = $n - $multihost->{graphs_per_row}; $n2 < $multihost->{graphs_per_row}; $n2++) { + if($n < scalar(@host)) { + print " \n"; + + } + $n++; } + print " \n"; + print " \n"; + for($n2 = 0, $n = $n - $multihost->{graphs_per_row}; $n2 < $multihost->{graphs_per_row}; $n2++) { + if($n < scalar(@host)) { + if(lc($multihost->{footer_url}) eq "y") { + print " \n"; + } + } + $n++; } - $n++; + $n = $n - $multihost->{graphs_per_row}; + print " \n"; + print "
\n"; + print " \n"; + print "   " . $host[$n] . "\n"; + print " \n"; + print "
\n"; - print " \n"; - print " \n"; - print "   $foot_url[$n]\n"; - print " \n"; - print "
\n"; + print " \n"; + print "
\n"; + print " \n"; + print " \n"; + print "   $foot_url[$n]\n"; + print " \n"; + print "
\n"; + print "
\n"; } - $n = $n - $multihost->{graphs_per_row}; - print " \n"; - print "\n"; - print "
\n"; } } else { - print " \n"; - print " \n"; - print " \n"; - print " \n"; - print " \n"; - print " \n"; - print " \n"; - print " \n"; - if(lc($multihost->{footer_url}) eq "y") { - print " \n"; - } - print " \n"; - print "
\n"; - print " \n"; - print "   " . $host[$cgi->{val}] . "\n"; - print " \n"; - print "
\n"; - print " \n"; - print "
\n"; - print " \n"; - print " \n"; - print "   $foot_url[$cgi->{val}]\n"; - print " \n"; - print "
\n"; - print "
\n"; + if($cgi->{graph} eq "all") { + print " \n"; + } else { + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + if(lc($multihost->{footer_url}) eq "y") { + print " \n"; + } + print " \n"; + print "
\n"; + print " \n"; + print "   " . $host[$cgi->{val}] . "\n"; + print " \n"; + print "
\n"; + print " \n"; + print "
\n"; + print " \n"; + print " \n"; + print "   $foot_url[$cgi->{val}]\n"; + print " \n"; + print "
\n"; + print "
\n"; + } } } @@ -195,7 +237,7 @@ # MAIN # ---------------------------------------------------------------------------- -open(IN, "< monitorix.conf.path"); +open(IN, dirname(__FILE__)."/monitorix.conf.path"); my $config_path = ; chomp($config_path); close(IN); @@ -412,6 +454,7 @@ if(!$silent) { my $title; my $str; + my @output; my $piwik_code = ""; my ($piwik_url, $piwik_sid, $piwik_img); @@ -456,65 +499,72 @@ print(" \n"); print(" $piwik_code\n"); print("

\n"); - print(" \n"); - print(" \n"); + push(@output, "
\n"); + push(@output, " \n"); if(lc($config{enable_back_button} || "") eq "y") { - print(" \n"); + push(@output, " \n"); } if(($val ne "all" || $val ne "group") && $mode ne "multihost") { - print(" \n"); + push(@output, " \n"); } if($val =~ m/group(\d+)/) { my $gnum = $1; my $gname = (split(',', $config{multihost}->{remotegroup_list}))[$gnum]; $gname = trim($gname); - print(" \n"); + push(@output, " \n"); } - print(" \n"); - print(" \n"); - print(" \n"); - print("
\n"); - print(" \n"); - print("   Host: \n"); - print(" \n"); - print(" \n"); + push(@output, " \n"); + push(@output, "   Host: \n"); + push(@output, " \n"); + push(@output, " \n"); - print(" \n"); - print("   $gname \n"); - print(" \n"); - print(" \n"); + push(@output, " \n"); + push(@output, "   $gname \n"); + push(@output, " \n"); + push(@output, " \n"); - print(" \n"); + push(@output, " \n"); + push(@output, " \n"); if($mode eq "localhost" || $mode eq "traffacct") { $title = $config{hostname}; } elsif($mode eq "multihost") { - $graph = $graph eq "all" ? "_system1" : $graph; - my ($g1, $g2) = ($graph =~ /(_\D+).*?(\d)$/); - if($g1 eq "_port") { - $title = $config{graphs}->{$g1}; - $g2 = trim((split(',', $config{port}->{list}))[$g2]); - $title .= " " . $g2; - $g2 = (split(',', $config{port}->{desc}->{$g2}))[0]; - $title .= " (" . trim($g2) . ")"; + if($graph ne "all") { + my ($g1, $g2) = ($graph =~ /(_\D+).*?(\d)$/); + if($g1 eq "_port") { + $title = $config{graphs}->{$g1}; + $g2 = trim((split(',', $config{port}->{list}))[$g2]); + $title .= " " . $g2; + $g2 = (split(',', $config{port}->{desc}->{$g2}))[0]; + $title .= " (" . trim($g2) . ")"; + } else { + $g2 = "" if $g1 eq "_proc"; # '_procn' must be converted to '_proc' + $title = $config{graphs}->{$g1 . $g2}; + } } else { - $g2 = "" if $g1 eq "_proc"; # '_procn' must be converted to '_proc' - $title = $config{graphs}->{$g1 . $g2}; + $title = $graph eq "all" ? "all graphs" : $graph; } } $title =~ s/ / /g; my $twhen = $tf{nwhen} > 1 ? "$tf{nwhen} $tf{twhen}" : $tf{twhen}; $twhen .= "s" if $tf{nwhen} > 1; - print("   $title  \n"); - print(" \n"); - print(" \n"); - print(" \n"); - print("   last $twhen  \n"); + + if($mode ne "multihost" || $graph ne "all" || $val eq "all") { + print @output; + print("   $title  \n"); print(" \n"); print("
\n"); - print(" \n"); - print encode('utf-8', "

" . strftime("%a %b %e %H:%M:%S %Z %Y", localtime) . "

\n"); + print(" \n"); + print(" \n"); + print("   last $twhen  \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print(" \n"); + print encode('utf-8', "

" . strftime("%a %b %e %H:%M:%S %Z %Y", localtime) . "

\n"); + } } @@ -623,16 +673,18 @@ } if(!$silent) { - print("\n"); - print("
\n"); - print("
\n"); - print("\n"); - print("

\n"); - print(" \n"); - print("
\n"); - print(" \n"); - print("Copyright © 2005-2018 Jordi Sanfeliu\n"); - print(" \n"); + if($mode ne "multihost" || $graph ne "all" || $val eq "all") { + print("\n"); + print("
\n"); + print("

\n"); + print("\n"); + print("

\n"); + print(" \n"); + print("
\n"); + print(" \n"); + print("Copyright © 2005-2017 Jordi Sanfeliu\n"); + print(" \n"); + } print(" \n"); print("\n"); print("\n"); diff -Nru monitorix-3.10.1/monitorix.conf monitorix-3.11.0/monitorix.conf --- monitorix-3.10.1/monitorix.conf 2017-09-05 07:47:09.000000000 +0000 +++ monitorix-3.11.0/monitorix.conf 2019-03-11 07:00:23.000000000 +0000 @@ -34,6 +34,7 @@ log_file = /var/log/monitorix-httpd hosts_deny = hosts_allow = + autocheck_responsiveness = y enabled = n msg = Monitorix: Restricted access @@ -80,6 +81,7 @@ lmsens = n gensens = n ipmi = n + ambsens = n nvidia = n disk = n fs = y @@ -130,7 +132,7 @@ loadavg_threshold = 5.0 loadavg_script = /path/to/script.sh - rigid = 1, 0, 0, 0 ,0 + rigid = 1, 0, 0, 0, 0 limit = 1, 1000, 1000, 1000, 1000 @@ -255,6 +257,30 @@ +# AMBSENS graph +# ----------------------------------------------------------------------------- + + list = Ambient Temperature + + 0 = at1 + + + 0 = Celsius + + + at1 = /path/to/script.sh + + + at1 = Gold TEMPer PC USB + + + + graphs_per_row = 2 + rigid = 0 + limit = 100 + + + # NVIDIA graph # ----------------------------------------------------------------------------- @@ -307,8 +333,8 @@ max_pools = 5 list = pool1, pool2 - rigid = 0, 0, 0, 0, 2, 0, 2 - limit = 1000, 1000, 1000, 1000, 100, 1000, 100 + rigid = 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0 + limit = 1000, 1000, 1000, 1000, 100, 1000, 1000, 1000, 100, 1000, 1000 @@ -320,6 +346,10 @@ 0 = /var/spool/mail, /var/spool/mqueue, /etc, /var/ftp, /tmp 1 = /home/ace, /home/gene, /home/paul, /home/peter + + 0 = size + 1 = files + /var/spool/mail = Mail boxes /var/spool/mqueue = Mail queue @@ -345,6 +375,7 @@ # NETSTAT graph # ----------------------------------------------------------------------------- + cmd = ss rigid = 0, 0, 0, 0, 0 limit = 100, 100, 100, 100, 100 @@ -765,6 +796,7 @@ enabled = n footer_url = y graphs_per_row = 2 + default_option_when_all = "System load" remotehost_list = server 1, server 2, server 3 0 = http://www.example.com,/monitorix,/monitorix-cgi @@ -865,7 +897,7 @@ remote = 300x100 -graph_name = system, kern, proc, hptemp, lmsens, gensens, ipmi, nvidia, disk, fs, zfs, du, net, netstat, tc, libvirt, process, serv, mail, port, user, ftp, apache, nginx, lighttpd, mysql, mongodb, varnish, pagespeed, squid, nfss, nfsc, bind, ntp, chrony, fail2ban, icecast, raspberrypi, phpapc, memcached, apcupsd, nut, wowza, int, verlihub +graph_name = system, kern, proc, hptemp, lmsens, gensens, ipmi, ambsens, nvidia, disk, fs, zfs, du, net, netstat, tc, libvirt, process, serv, mail, port, user, ftp, apache, nginx, lighttpd, mysql, mongodb, varnish, pagespeed, squid, nfss, nfsc, bind, ntp, chrony, fail2ban, icecast, raspberrypi, phpapc, memcached, apcupsd, nut, wowza, int, verlihub system = System load average and usage @@ -875,6 +907,7 @@ lmsens = LM-Sensors and GPU temperatures gensens = Generic sensor statistics ipmi = IPMI sensor statistics + ambsens = Ambient sensor statistics nvidia = NVIDIA temperatures and usage disk = Disk drive temperatures and health fs = Filesystem usage and I/O activity @@ -936,6 +969,7 @@ _gensens1 = Temperatures _gensens2 = CPU frequency _ipmi = IPMI sensors + _ambsens = Ambient sensors _nvidia1 = NVIDIA temperatures _nvidia2 = CPU usage _nvidia3 = Memory usage @@ -951,6 +985,8 @@ _zfs3 = L2ARC cache _zfs4 = Pool data usage _zfs5 = Pool usage + _zfs6 = Operations + _zfs7 = Bandwidth _du = Directory usage _net1 = Network traffic _net2 = Network packets diff -Nru monitorix-3.10.1/README monitorix-3.11.0/README --- monitorix-3.10.1/README 2018-03-15 07:04:20.000000000 +0000 +++ monitorix-3.11.0/README 2019-03-14 13:57:02.000000000 +0000 @@ -8,7 +8,8 @@ It consists mainly of two programs: a collector, called monitorix, which is a Perl daemon that is started automatically like any other system service, -and a CGI script called monitorix.cgi. Since 3.0 version Monitorix includes its own HTTP server built in, so you don't need to install any web server to use it. +and a CGI script called monitorix.cgi. Since 3.0 version Monitorix includes its +own HTTP server built in, so you don't need to install any web server to use it. Every time 'monitorix' is started it reads the configuration file from the path specified in the command line (using the -c option), and once checked, it @@ -190,6 +191,6 @@ Monitorix is distributed under the terms of the GNU General Public License. See the included file "COPYING". -Copyright (C) 2005-2018 Jordi Sanfeliu. +Copyright (C) 2005-2019 Jordi Sanfeliu. http://www.monitorix.org