#!/usr/bin/perl -w # # syswatcher.pl # # Developed by Lubomir Host 'rajo' # 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, "; $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, ") { 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