"Fossies" - the Fresh Open Source Software Archive 
Member "lmon-1.2/control.pl" (19 May 2005, 12949 Bytes) of package /linux/privat/old/lmon-1.2.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "control.pl" see the
Fossies "Dox" file reference documentation.
1 #! /usr/bin/perl -T
2 # control.pl 1.2 for LMon, anders@bsdconsulting.no, 2005-05-19
3 # External requirements: Config::IniFiles.
4 #
5 # Copyright (c) 2005, Anders Nordby <anders@bsdconsulting.no>
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # * Redistributions of source code must retain the above copyright notice, this
12 # list of conditions and the following disclaimer.
13 #
14 # * Redistributions in binary form must reproduce the above copyright notice,
15 # this list of conditions and the following disclaimer in the documentation
16 # and/or other materials provided with the distribution.
17 #
18 # * Neither the name of BSD Consulting nor the names of its contributors may
19 # be used to endorse or promote products derived from this software without
20 # specific prior written permission.
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
26 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 package LMonControl;
34 use Config::IniFiles;
35 use FindBin qw($Bin);
36 use Getopt::Std;
37 use POSIX;
38 use strict;
39 use IPC::Open3;
40
41 $ENV{PATH} = "/sbin:/bin:/usr/sbin:/usr/bin";
42 $ENV{ENV} = "";
43
44 $LMonControl::gensect = "general";
45 $LMonControl::logvar = "log";
46 $LMonControl::rulevar = "rules";
47 $LMonControl::namevar = "name";
48 $LMonControl::modevar = "mode";
49 $LMonControl::sysnamevar = "sysname";
50 $LMonControl::buffervar = "buffer";
51 $LMonControl::fromvar = "from";
52 $LMonControl::tovar = "to";
53 $LMonControl::mailserversvar = "mailservers";
54 $LMonControl::cmdok = '([-\w\.\/\ \"\@\;\_]+)';
55 $LMonControl::fnok = '([-\w\.\_]+)';
56
57 $LMonControl::commname = "^perl";
58 $LMonControl::argcheck = "lmon\.pl";
59 $LMonControl::cfgfile = "$Bin/control.cfg";
60 $LMonControl::oscheck = '^(SunOS|Linux|FreeBSD)$';
61
62 die("ERROR: Unknown operating system") unless ((POSIX::uname)[0] =~ /$LMonControl::oscheck/);
63
64 use vars qw { $opt_i };
65
66 sub readconfig {
67 if (! -f $LMonControl::cfgfile) {
68 die("ERROR: Config file $LMonControl::cfgfile not found");
69 } elsif (! -T $LMonControl::cfgfile) {
70 die("ERROR: Config file $LMonControl::cfgfile is not a text file");
71 } else {
72 tie %LMonControl::cfg, 'Config::IniFiles', ( -file => $LMonControl::cfgfile );
73 }
74 }
75
76 sub usage {
77 print "Usage: control.pl [options] <keyword>\n\n";
78 print "\tlist\t\t\tlist configured instances\n";
79 print "\tstart\t\t\tstart all configured instances\n";
80 print "\tstart -i <instance>\tstart given instances\n";
81 print "\tstop\t\t\tstop all configured instances\n";
82 print "\tstop -i <instance>\tstop given instances\n";
83 print "\tstatus\t\t\tprint status for all configured instances\n";
84 print "\tstatus -i <instance>\tprint status for given instance\n";
85 exit(1);
86 }
87
88 sub pscmd {
89 # $_[0]: cmd $_[1]: extra (optional)
90 my $cmd = $_[0];
91 my $extracmd = $_[1];
92 if ($cmd =~ /^$LMonControl::cmdok$/) {
93 $cmd = $1;
94 $cmd .= " 2>/dev/null | tail +2";
95 if ($extracmd) { $cmd .= " " . $extracmd; }
96 return `$cmd`;
97 } else {
98 return "";
99 }
100 }
101
102 sub instpid {
103 # $_[0]: inst
104 my $inst = $_[0];
105 my $pidfile = $Bin . "/" . $inst . ".pid";
106 my $username = getpwuid(getuid);
107
108 if (! -T $pidfile) {
109 # PID file missing or not a text file
110 return 0;
111 } else {
112 open(PID, $pidfile);
113 my $regpid = <PID>;
114 close(PID);
115 chomp($regpid);
116 if (!int($regpid)) {
117 return 0;
118 } else {
119 my $psuser;
120 my $pspid;
121 my $pscomm;
122 my $psargs;
123 for ((POSIX::uname)[0]) {
124 /^(FreeBSD|Linux)$/ and do {
125 $psuser = pscmd("ps -p $regpid -oruser");
126 $psuser =~ s@\s+$@@g;
127 $pspid = pscmd("ps -p $regpid -opid");
128 $pspid =~ s@\s+$@@g;
129 $pscomm = pscmd("ps -c -p $regpid -ocommand");
130 $pscomm =~ s@\s+$@@g;
131 $psargs = pscmd("ps -ww -p $regpid -ocommand");
132 $psargs =~ s@\s+$@@g;
133 next;
134 };
135 /^SunOS$/ and do {
136 $psuser = pscmd("ps -p $regpid -oruser", "| awk '{print \$1}'");
137 $pspid = pscmd("ps -p $regpid -opid");
138 $pscomm = pscmd("ps -p $regpid -ocomm", "| xargs -n 1 basename");
139 $psargs = pscmd("ps -p $regpid -oargs");
140 next;
141 };
142 }
143 chomp($psuser);
144 chomp($pspid);
145 chomp($pscomm);
146 chomp($psargs);
147
148 if (int($pspid) && $regpid == $pspid && $psuser eq "$username" && $pscomm =~ /$LMonControl::commname/ && $psargs =~ /$LMonControl::argcheck/) {
149 return($regpid);
150 } else {
151 return(0);
152 }
153 }
154 }
155 }
156
157 sub statusinst {
158 # $_[0]: instance name
159 my $inst = $_[0];
160 my $pid = instpid($inst);
161 if ($pid) {
162 print "$inst up, PID $pid.\n";
163 } else {
164 print "$inst down.\n";
165 }
166 }
167
168 sub startinst {
169 # $_[0]: instance name
170 my $inst = $_[0];
171
172 print "Start lmon.pl instance $_[0]: ";
173 if (!instpid($inst)) {
174 my $cmd = "cd $Bin; ./lmon.pl -r \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"} . "\" -f \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::logvar"} . "\" -p \"" . $inst . ".pid\" -d";
175
176 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::modevar"}) {
177 if ($LMonControl::cfg{"$inst"}{"$LMonControl::modevar"} eq "include") {
178 $cmd .= " -i";
179 }
180 } elsif (exists $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::modevar"} && $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::modevar"} eq "include") {
181 $cmd .= " -i";
182 }
183
184 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::sysnamevar"}) {
185 $cmd .= " -s \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::sysnamevar"} . "\"";
186 } elsif (exists $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::sysnamevar"}) {
187 $cmd .= " -s \"" . $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::sysnamevar"} . "\"";
188 }
189
190 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::fromvar"}) {
191 $cmd .= " -F \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::fromvar"} . "\"";
192 } elsif (exists $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::fromvar"}) {
193 $cmd .= " -F \"" . $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::fromvar"} . "\"";
194 }
195
196 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::tovar"}) {
197 $cmd .= " -t \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::tovar"} . "\"";
198 } elsif (exists $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::tovar"}) {
199 $cmd .= " -t \"" . $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::tovar"} . "\"";
200 }
201
202 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::mailserversvar"}) {
203 $cmd .= " -m \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::mailserversvar"} . "\"";
204 } elsif (exists $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::mailserversvar"}) {
205 $cmd .= " -m \"" . $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::mailserversvar"} . "\"";
206 }
207
208 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::buffervar"}) {
209 $cmd .= " -b \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::buffervar"} . "\"";
210 } elsif (exists $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::buffervar"}) {
211 $cmd .= " -b \"" . $LMonControl::cfg{"$LMonControl::gensect"}{"$LMonControl::buffervar"} . "\"";
212 }
213 if (exists $LMonControl::cfg{"$inst"}{"$LMonControl::namevar"}) {
214 $cmd .= " -n \"" . $LMonControl::cfg{"$inst"}{"$LMonControl::namevar"} . "\"";
215 }
216
217 if (!exists $LMonControl::cfg{"$inst"}{"$LMonControl::logvar"}) {
218 print "FAIL, instance $inst needs configuration parameter " . $LMonControl::logvar . ".\n";
219 } elsif (! -f $LMonControl::cfg{"$inst"}{"$LMonControl::logvar"}) {
220 print "FAIL, log file " . $LMonControl::cfg{"$inst"}{"$LMonControl::logvar"} . " does not exist.\n";
221 } elsif (! -f $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"}) {
222 print "FAIL, rule file " . $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"} . " does not exist.\n";
223 } elsif (! -T $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"}) {
224 print "FAIL, rule file " . $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"} . " is not a text file.\n";
225 } else {
226 # print "TRY: $cmd\n";
227
228 # untaint $cmd if characters are OK, sort-of
229 if ($cmd =~ /^$LMonControl::cmdok$/) {
230 $cmd = $1;
231
232 local(*IN, *OUT, *ERR);
233 my $mypid = open3(*IN, *OUT, *ERR, $cmd);
234 close(IN);
235
236 my $errdata;
237 while (<ERR>) {
238 $errdata .= $_;
239 }
240 close(ERR);
241 close(OUT);
242 waitpid($mypid, 0);
243 my $ret = $?;
244
245 if ($ret == 0) {
246 print "OK.\n";
247 } else {
248 print "FAIL, startup problems:\n\n$errdata\n";
249 }
250 } else {
251 my $badargs = $cmd;
252 $badargs =~ s@$LMonControl::cmdok@@g;
253 print "FAIL, invalid argument characters\nin command for instance $inst (see cmdok setting or disable\n-T option for Perl): $badargs.\n";
254 }
255 }
256 } else {
257 print "FAIL, already running.\n";
258 }
259 }
260
261 sub stopinst {
262 # $_[0]: instance name
263 my $inst = $_[0];
264
265 print "Stop lmon.pl instance $_[0]: ";
266 my $pid = instpid($inst);
267
268 if (int($pid)) {
269 if ($pid =~ /^(\d+)$/) {
270 # untaint PID
271 $pid = $1;
272
273 kill 'TERM', $pid;
274 my $pidfile = $inst . ".pid";
275 if ($pidfile =~ /^$LMonControl::fnok$/) {
276 # Untaint pidfile filename
277 $pidfile = $1;
278 if (-e $pidfile) { unlink($pidfile) };
279 }
280 print "DONE\n";
281 } else {
282 print "no valid PID number found.\n";
283 }
284 } else {
285 print "not running.\n";
286 }
287 }
288
289 sub fixconfig {
290 my $inst;
291 foreach $inst (keys %LMonControl::cfg) {
292 next if ($inst =~ /^$LMonControl::gensect$/);
293
294 # Fix the rule file filename/path
295 if (!exists $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"}) {
296 # No rule file specified, use default: <instance>.rules in $Bin
297 $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"} = $Bin . "/" . $inst . ".rules";
298 } elsif (! -f $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"}) {
299 # Rule file not found, add $Bin before filename
300 $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"} = $Bin . "/" . $LMonControl::cfg{"$inst"}{"$LMonControl::rulevar"};
301 }
302 }
303 }
304
305 sub ckpids {
306 opendir(DIR, $Bin);
307 my @dirfiles = readdir DIR;
308 closedir(DIR);
309 my $dirfile;
310 foreach $dirfile (@dirfiles) {
311 next if ($dirfile !~ /\.pid$/);
312 my $inst = $dirfile;
313 $inst =~ s@\.pid$@@;
314 my $pidfile = $Bin . "/" . $dirfile;
315
316 if (! -T $pidfile) {
317 print "WARNING: PID file $dirfile found in program dir. Not even a valid text file!\n";
318 } elsif (!exists $LMonControl::cfg{"$inst"}) {
319 print "WARNING: PID file $dirfile found in program dir, but $inst is not in config.\n";
320 } else {
321 my $dirpid = $Bin . "/" . $dirfile;
322 open(PID, $dirpid);
323 my $regpid = <PID>;
324 close(PID);
325 if (!int($regpid)) {
326 print "WARNING: PID file $dirfile found in program dir, but has no number.\n";
327 } else {
328 my $ckpid = instpid($inst);
329 if ($ckpid && $ckpid != $regpid) {
330 print "WARNING: PID file $dirfile found in program dir, but has unexpected PID.\n";
331 }
332 }
333 }
334 }
335 }
336
337 if ($ARGV[0]) {
338 if ($ARGV[0] =~ /^(start|stop|status)$/) {
339
340 my $keyword = $ARGV[0];
341 @ARGV = grep(!/^(start|stop|status)/, @ARGV);
342 push(@ARGV, $keyword);
343 }
344 } else {
345 usage;
346 }
347
348 getopts('i:');
349 my $inst;
350
351 for ($ARGV[0]) {
352 /^start$/ and do {
353 readconfig; fixconfig;
354 if ($opt_i) {
355 if ($opt_i eq $LMonControl::gensect) {
356 print "Could not start invalid instance $opt_i.\n";
357 } elsif (exists $LMonControl::cfg{"$opt_i"}) {
358 startinst($opt_i);
359 } else {
360 print "Could not start instance $opt_i, does not exist in configuration.\n";
361 }
362 } else {
363 foreach $inst (keys %LMonControl::cfg) {
364 next if ($inst =~ /^$LMonControl::gensect$/);
365 startinst($inst);
366 }
367 }
368 next;
369 };
370 /^stop$/ and do {
371 readconfig;
372 if ($opt_i) {
373 if (exists $LMonControl::cfg{"$opt_i"}) {
374 stopinst($opt_i);
375 } else {
376 print "Could not stop instance $opt_i, does not exist in configuration.\n";
377 }
378 } else {
379 foreach $inst (keys %LMonControl::cfg) {
380 next if ($inst =~ /^$LMonControl::gensect$/);
381 stopinst($inst);
382 }
383 }
384 next;
385 };
386 /^list$/ and do {
387 readconfig;
388 print "Instances:\n\n";
389 foreach $inst (keys %LMonControl::cfg) {
390 next if ($inst =~ /^$LMonControl::gensect$/);
391 print "$inst\n";
392 }
393 next;
394 };
395 /^status$/ and do {
396 readconfig;
397 if ($opt_i) {
398 if (exists $LMonControl::cfg{"$opt_i"}) {
399 statusinst($opt_i);
400 } else {
401 print "Will not check status for instance $opt_i,\ndoes not exist in configuration.\n";
402 }
403 } else {
404 foreach $inst (keys %LMonControl::cfg) {
405 next if ($inst =~ /^$LMonControl::gensect$/);
406 statusinst($inst);
407 }
408 ckpids;
409 }
410 ckpids;
411 next;
412 };
413 usage;
414 }