#!/usr/bin/perl -w
#
# syswatcher.pl
#
# Developed by Lubomir Host 'rajo' <rajo AT platon.sk>
# Copyright (c) 2003 Platon SDG, http://platon.sk/
# Licensed under terms of GNU General Public License.
# All rights reserved.
#
# Changelog:
# 15/10/2003 - created
# 16/10/2003 - added automatic database reconnecting (nepto)
#
# $Platon: scripts/perl/syswatcher/syswatcher.pl,v 1.7 2004/01/05 11:34:21 nepto Exp $
use strict;
use DBI;
use Time::HiRes qw(gettimeofday sleep usleep);
use POSIX qw(strftime);
# declaration: {{{
use vars qw (
$database
$dbh
$sql_loadavg
$sql_meminfo
$update_interval
);
# functions
sub PrepareSQL();
sub print_info($;);
sub loadavg();
sub meminfo();
# }}}
$database = "DBI:mysql:database=system;host=localhost;user=syswatcher;password=;compression=0";
# time between 2 inserts or reconnects:
# range of this value: (2, 1E6)
$update_interval = 10; # seconds
#
# MAIN
#
FORK: {
my $pid;
if ($pid = fork) {
# parent
exit 0;
}
elsif (defined $pid) {
# child
}
elsif ($! =~ /No more process/) {
# EAGAIN
warn "Can't fork: $!";
sleep 5;
redo fork;
}
else {
die "Can't fork: $!";
}
}
print_info("PID = $$ $0 started");
while (1) {
while (! ($dbh = DBI->connect($database))) {
print_info("Database connection failed, reconnecting in $update_interval seconds...($DBI::errstr)");
sleep $update_interval;
}
PrepareSQL();
Time::HiRes::sleep ($update_interval - (Time::HiRes::gettimeofday % $update_interval));
while ($dbh) {
my $sleep = 1;
while (!defined($dbh) or ref($dbh) ne 'DBI::db' or !($dbh->ping())) {
print STDERR "CheckDB - db ping error\n";
sleep $sleep;
$sleep += 10 if ($sleep < 120);
}
$dbh->{mysql_auto_reconnect} = 1;
#
# DB ping must be done twice (bug in DBI??), otherwise warning "DBD::mysql::st execute warning:" [rajo]
#
my $rv = $dbh->ping();
$dbh->{mysql_auto_reconnect} = 1;
last if (! loadavg());
last if (! meminfo());
Time::HiRes::sleep ($update_interval - (Time::HiRes::gettimeofday % $update_interval));
my $modify_time = -86400.0 * -M $0;
if (defined $modify_time && $modify_time > 0) { # Autorestart - if file exists and is modified
print_info("Script '$0' MODIFIED $modify_time seconds after startup, restarting ...");
exec $0, @ARGV;
}
}
sleep $update_interval;
}
sub PrepareSQL()
{ # {{{
$sql_loadavg = $dbh->prepare("
INSERT INTO loadavg
(load1, load5, load15, procs_run, procs_total, last_pid)
VALUES (?, ?, ?, ?, ?, ?)
");
# parameters HugePages_Total, HugePages_Free, Hugepagesize depeds on kernel config
# (not always available in /proc/meminfo)
$sql_meminfo= $dbh->prepare("
INSERT INTO meminfo
(MemTotal, MemFree, Buffers, Cached, SwapCached,
Active, Inactive, HighTotal, HighFree, LowTotal,
LowFree, SwapTotal, SwapFree, Dirty, Writeback,
Mapped, Slab, Committed_AS, PageTables, VmallocTotal,
VmallocUsed, VmallocChunk, HugePages_Total, HugePages_Free, Hugepagesize)
VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"); # 25 values
} # }}}
sub cur_date()
{ # {{{
my ($sec, $msec) = Time::HiRes::gettimeofday;
$msec = sprintf("%06g", $msec);
my $time_string = strftime "%Y/%m/%d %X.$msec", gmtime;
return $time_string;
} # }}}
sub print_info($;)
{ # {{{
my ($text) = @_;
printf STDERR "[%s] %s\n", cur_date(), $text;
} # }}}
sub loadavg()
{ # {{{
open FILE, "</proc/loadavg" or die "loadavg(): $!";
my ($load1, $load5, $load15, $procs_run, $procs_total, $last_pid) = split /[ \/]+/, <FILE>;
$sql_loadavg->execute(
$load1, $load5, $load15, $procs_run, $procs_total, $last_pid) or warn $dbh->errstr;
#print_info("Loadavg inserted");
close FILE;
return 1;
} # }}}
sub meminfo()
{ # {{{
my %xx;
open FILE, "</proc/meminfo" or die "loadavg(): $!";
while (my $line = <FILE>) {
if ($line =~ m/^([a-z_]+)[ :]*([0-9]+).*$/i) {
$xx{$1} = $2;
}
}
close FILE;
$sql_meminfo->execute(
$xx{MemTotal}, $xx{MemFree}, $xx{Buffers}, $xx{Cached}, $xx{SwapCached},
$xx{Active}, $xx{Inactive}, $xx{HighTotal}, $xx{HighFree}, $xx{LowTotal},
$xx{LowFree}, $xx{SwapTotal}, $xx{SwapFree}, $xx{Dirty}, $xx{Writeback},
$xx{Mapped}, $xx{Slab}, $xx{Committed_AS}, $xx{PageTables},$xx{VmallocTotal},
$xx{VmallocUsed}, $xx{VmallocChunk}, $xx{HugePages_Total}, $xx{HugePages_Free}, $xx{Hugepagesize}
) or warn $dbh->errstr;
#print_info("Meminfo inserted");
return 1;
} # }}}
# vim: ts=4
# vim600: fdm=marker fdl=0 fdc=3
Platon Group <platon@platon.sk> http://platon.sk/
|