1 |
#!/usr/bin/perl |
---|
2 |
|
---|
3 |
BEGIN { |
---|
4 |
(my $dir = $0) =~ s/\/?[^\/]+$//; |
---|
5 |
eval "use lib '$dir/lib';"; |
---|
6 |
die $@ if($@); |
---|
7 |
}; |
---|
8 |
|
---|
9 |
use strict; |
---|
10 |
use warnings; |
---|
11 |
use Time::HiRes qw( gettimeofday tv_interval sleep ); |
---|
12 |
use POSIX qw( :sys_wait_h setsid ); |
---|
13 |
use Getopt::Long; |
---|
14 |
use Data::Dumper; |
---|
15 |
use vars qw($config_file $debug $status_file $interface $port $config |
---|
16 |
$status $update); |
---|
17 |
|
---|
18 |
use Resmon::Config; |
---|
19 |
use Resmon::ExtComm; |
---|
20 |
use Resmon::Status; |
---|
21 |
|
---|
22 |
GetOptions( |
---|
23 |
"i=s" => \$interface, |
---|
24 |
"p=i" => \$port, |
---|
25 |
"c=s" => \$config_file, |
---|
26 |
"d" => \$debug, |
---|
27 |
"f=s" => \$status_file, |
---|
28 |
"u" => \$update, |
---|
29 |
); |
---|
30 |
|
---|
31 |
if ($update) { |
---|
32 |
use Resmon::Updater; |
---|
33 |
(my $resmondir = $0) =~ s/\/?[^\/]+$//; |
---|
34 |
exit(Resmon::Updater::update($debug, $resmondir)); |
---|
35 |
} |
---|
36 |
|
---|
37 |
$config_file ||= "$0.conf"; |
---|
38 |
die "Cannot open configuration file: $config_file" unless (-r $config_file); |
---|
39 |
|
---|
40 |
sub configure { |
---|
41 |
$config = Resmon::Config->new($config_file); |
---|
42 |
$config->{statusfile} = $status_file if($status_file); |
---|
43 |
$config->{port} = $port if($port); |
---|
44 |
$config->{interface} = $interface if($interface); |
---|
45 |
} |
---|
46 |
|
---|
47 |
configure(); |
---|
48 |
|
---|
49 |
my $sighup = 0; |
---|
50 |
sub sighup_handler { $sighup = 1; } |
---|
51 |
$SIG{'HUP'} = \&sighup_handler; |
---|
52 |
|
---|
53 |
my $sigint = 0; |
---|
54 |
sub sigint_handler { $sigint = 1; } |
---|
55 |
$SIG{'INT'} = \&sigint_handler; |
---|
56 |
|
---|
57 |
my $rmlast = undef; |
---|
58 |
sub wait_interval { |
---|
59 |
$rmlast = [gettimeofday] unless defined($rmlast); |
---|
60 |
my $elapsed = $config->{interval} - tv_interval($rmlast); |
---|
61 |
if($elapsed > 0) { |
---|
62 |
sleep($elapsed); |
---|
63 |
} |
---|
64 |
$rmlast = [gettimeofday]; |
---|
65 |
} |
---|
66 |
|
---|
67 |
sub reap_zombies { |
---|
68 |
my $kid; |
---|
69 |
do { |
---|
70 |
$kid = waitpid(-1, WNOHANG); |
---|
71 |
} while $kid > 0; |
---|
72 |
} |
---|
73 |
|
---|
74 |
unless($debug) { |
---|
75 |
fork && exit; |
---|
76 |
setsid; |
---|
77 |
open(STDIN, "</dev/null"); |
---|
78 |
open(STDOUT, ">/dev/null"); |
---|
79 |
open(STDERR, ">/dev/null"); |
---|
80 |
fork && exit; |
---|
81 |
} |
---|
82 |
|
---|
83 |
my $list = []; |
---|
84 |
$status = Resmon::Status->new($config->{statusfile}); |
---|
85 |
$status->open(); |
---|
86 |
$status->serve_http_on($config->{interface}, $config->{port}, |
---|
87 |
$config->{authuser}, $config->{authpass}) |
---|
88 |
if($config->{port}); |
---|
89 |
|
---|
90 |
while(1) { |
---|
91 |
while(my($module_name, $mod_configs) = each %{$config->{Module}}) { |
---|
92 |
while(my($check_name, $monitor_obj) = each %$mod_configs) { |
---|
93 |
my $check_metrics = {}; |
---|
94 |
my $starttime = [gettimeofday]; |
---|
95 |
# Get old status if it hasn't expired |
---|
96 |
$check_metrics = $monitor_obj->get_cached_metrics(); |
---|
97 |
# Otherwise, run the check |
---|
98 |
if (!$check_metrics) { |
---|
99 |
my $timeout = $monitor_obj->{'check_timeout'} || |
---|
100 |
$config->{'timeout'}; |
---|
101 |
alarm($timeout); |
---|
102 |
my $handler; |
---|
103 |
eval { |
---|
104 |
local $SIG{ALRM} = sub { die "alarm\n" }; |
---|
105 |
if ($check_name eq "*") { |
---|
106 |
$check_metrics = $monitor_obj->wildcard_handler; |
---|
107 |
} else { |
---|
108 |
$check_metrics = { |
---|
109 |
$check_name => $monitor_obj->handler |
---|
110 |
}; |
---|
111 |
} |
---|
112 |
}; |
---|
113 |
alarm 0; |
---|
114 |
# Store the last metrics for use by fresh_status_msg later |
---|
115 |
$monitor_obj->cache_metrics($check_metrics); |
---|
116 |
}; |
---|
117 |
my $checkproblem = $@; |
---|
118 |
if($checkproblem) { |
---|
119 |
chomp $checkproblem; |
---|
120 |
if ($checkproblem eq "alarm") { |
---|
121 |
$checkproblem = "Check timeout"; |
---|
122 |
} |
---|
123 |
$check_metrics = { |
---|
124 |
$check_name => {"error" => ["$checkproblem", "s"]} |
---|
125 |
}; |
---|
126 |
Resmon::ExtComm::clean_up; |
---|
127 |
} |
---|
128 |
foreach my $name (keys %$check_metrics) { |
---|
129 |
my $results = { |
---|
130 |
last_runtime_seconds => sprintf("%.6f", |
---|
131 |
tv_interval($starttime)), |
---|
132 |
metric => $check_metrics->{$name} |
---|
133 |
}; |
---|
134 |
$status->store($module_name,$name, $results); |
---|
135 |
$status->write($module_name,$name, $results->{'metric'}, |
---|
136 |
$debug); |
---|
137 |
} |
---|
138 |
} |
---|
139 |
} |
---|
140 |
$status->close(); |
---|
141 |
die "Exiting.\n" if($sigint); |
---|
142 |
if ($sighup) { |
---|
143 |
# Reload configuration (and modules) on SIGHUP |
---|
144 |
$sighup = 0; |
---|
145 |
print STDERR "Reloading modules\n"; |
---|
146 |
$config = Resmon::Config->new($config_file); |
---|
147 |
# Needed to ensure any removed modules do not continue to show in the |
---|
148 |
# web interface |
---|
149 |
$status->clear(); |
---|
150 |
} else { |
---|
151 |
reap_zombies(); |
---|
152 |
wait_interval(); |
---|
153 |
reap_zombies(); |
---|
154 |
} |
---|
155 |
die "Exiting.\n" if($sigint); |
---|
156 |
print "\n---- ".localtime(time)."----------\n" |
---|
157 |
unless $status->open(); |
---|
158 |
} |
---|