add non-forking one machine monitor program
[freeside.git] / bin / monitor
1 #!/usr/bin/perl -w
2
3 use strict;
4 use vars qw( $DEBUG );
5 use Getopt::Std;
6 use FS::Daemon qw(daemonize1 daemonize2 logfile sigint sigterm);
7 use FS::Yori qw(report);
8 use Email::Send;
9
10 $DEBUG = 0;
11
12 &untaint_argv;  #what it sounds like  (eww)
13
14 use vars qw(%opt);
15 getopts('m:p:', \%opt );
16
17 my ($machine, @emails) = @ARGV;
18 die &usage unless @emails;
19
20 warn "starting daemonization (forking)\n" if $DEBUG;
21 daemonize1('freeside-monitor');
22 #logfile( "%%%FREESIDE_LOG%%%/monitorlog.$machine" );
23 logfile( "/usr/local/etc/freeside/monitorlog.$machine" );
24
25 warn "completing daemonization (detaching))\n" if $DEBUG;
26 daemonize2();
27
28 my $wantfree = $opt{m} || 1048576;
29 my $wantload = $opt{p} || 5;
30
31 die 'bogus memory requirement: $wantfree'
32    unless $wantfree && $wantfree =~ /^\d+$/;
33
34 die 'bogus load requirement: $wantload'
35    unless $wantload && $wantload =~ /^[\d.]+$/;
36
37 my $alerts = 0;
38 my $last = time();
39 while (1) {
40
41   my(undef, $load, undef) = report('load');
42   my($free) = report('freememory');
43   
44   unless( defined($load) && $load < $wantload
45        && defined($free) && $free > $wantfree
46        || ( time() < $last + 1800 && $alerts > 2 ) )
47   {
48     warn localtime(). ": $machine has load of $load and $free kB free memory\n";
49     warn "last is $last and alerts is $alerts\n";
50     $alerts++;
51     $alerts = 0 if time() > $last + 1800;
52     $last = time();
53     foreach my $email ( @emails ) {
54
55       my $message = <<"__MESSAGE__";
56 From: support\@freeside.biz
57 To: $email
58 Subject: ALERT - $machine
59
60 ALERT: $machine has a load of $load and only $free kB free..
61
62 __MESSAGE__
63
64     my $sender = Email::Send->new({mailer => 'SMTP'});
65     $sender->mailer_args([Host => 'mail.freeside.biz']);
66     $sender->send($message);
67
68     }
69
70   }
71
72
73
74   if ( sigterm() ) {
75     warn "received TERM signal; exiting\n";
76     exit;
77   }
78   if ( sigint() ) {
79     warn "received INT signal; exiting\n";
80     exit;
81   }
82
83   sleep 30; #too long?  too short?
84
85 }
86
87 sub untaint_argv {
88   foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
89     $ARGV[$_] =~ /^([\w\-\/\@\.]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
90     $ARGV[$_]=$1;
91   }
92 }
93
94 sub usage {
95   die "Usage:\n\n  freeside-monitor [ -pm ] machine email\n";
96 }
97
98 =head1 NAME
99
100 freeside-monitor - Perform some basic load monitoring
101
102 =head1 SYNOPSIS
103
104   freeside-monitor [ -p MAXLOAD ] [ -m REQUIRED_FRERMEM ] machine email [ ... ]
105
106 =head1 DESCRIPTION
107
108 Load monitoring daemon.  Should be running at all times.
109
110 -p: maximum permitted 5 minute load
111
112 -m: minimum free vmem in kB
113
114 machine: a unique name to be used in alert messages
115 email: address(es) to which alerts should be sent
116
117 =head1 VERSION
118
119 =head1 BUGS
120
121 =head1 SEE ALSO
122
123 =cut
124