ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/host/generic/statgrab.pl
Revision: 1.45
Committed: Tue Oct 16 10:48:08 2001 UTC (22 years, 11 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.44: +3 -3 lines
Log Message:
Added the -l flag to df. This tells df to only look at local filesystems. In
practice not doing so means that NFS file systems are checked, and this was not
sensible for a couple of reasons:
1. Should the remote machine go down, df hangs while the nfs client tries to
   reconnect. This then hangs statgrab and ihost, which then flags an incorrect
   'heartbeat' alert on the cms.
2. It is likely the remote machine will be monitored too, which means data is
   being processed for the remote disk more than once. This is a waste of
   resources, and also means any alerts are replicated.

File Contents

# User Rev Content
1 pjm2 1.1 #!/usr/bin/perl -w
2    
3     #-----------------------------------------------------------------
4     # Machine statistics grabber
5 tdb 1.44 # $Author: tdb1 $
6 tdb 1.45 # $Id: statgrab.pl,v 1.44 2001/05/25 19:42:26 tdb1 Exp $
7 pjm2 1.1 #
8     # A Perl script to return various information about a host machine
9     # by examining the output of some common Unix/Linux commands.
10     # This is a stopgap to act as a generic way of collecting the
11     # data. It is perhaps more reliable than the current Java host
12     # at doing this and it can obviously be used by a C++ program as
13     # well until the C++ host is ready to find the information out
14     # itself.
15     #-----------------------------------------------------------------
16    
17    
18     $| = 1;
19    
20    
21     # You'd be silly not to use this ;)
22     use strict;
23    
24 tdb 1.30 # Have to hope this will work really.
25     my($ostype) = `uname -s`; chop($ostype);
26    
27     # Decide which paths we should use.
28 tdb 1.39 my($topbin); my($dfbin); my($usersbin);
29     my($unamebin); my($uptimebin); my($sysctlbin);
30 tdb 1.30
31     if ($ostype eq "SunOS") {
32     # covers: Solaris 8
33 tdb 1.31 $topbin = "/usr/local/sbin/top -d2 -s1 0";
34 tdb 1.30 $dfbin = "/usr/bin/df";
35     $usersbin = "/usr/ucb/users";
36     $unamebin = "/usr/bin/uname";
37     $uptimebin = "/usr/bin/uptime";
38     }
39     elsif ($ostype eq "Linux") {
40     # covers: Debian r2.2
41 tdb 1.41 $topbin = "/usr/bin/top -d1 -n2 -b -p0";
42 tdb 1.30 $dfbin = "/bin/df";
43     $usersbin = "/usr/bin/users";
44     $unamebin = "/bin/uname";
45     $uptimebin = "/usr/bin/uptime";
46     }
47     elsif ($ostype eq "FreeBSD") {
48     # covers: FreeBSD 4.2-STABLE
49 tdb 1.31 $topbin = "/usr/bin/top -d2 -s1 0";
50 tdb 1.30 $dfbin = "/bin/df";
51     $usersbin = "/usr/bin/users";
52     $unamebin = "/usr/bin/uname";
53     $uptimebin = "/usr/bin/uptime";
54 tdb 1.39 $sysctlbin = "/sbin/sysctl";
55 tdb 1.30 }
56     else {
57     print "statgrab.pl Error: Unable to identify system type - \"$ostype\".\n";
58     print "\"uname -s\" does not report one of the following known types;\n";
59     print " SunOS, Linux, FreeBSD\n";
60     exit(1);
61     }
62 tdb 1.13
63 pjm2 1.6 # Run the following components: -
64 tdb 1.3 &print_ident();
65 tdb 1.2 &include_osver();
66 tdb 1.17 &include_uptime();
67 pjm2 1.1 &include_users();
68     &include_top();
69 pjm2 1.5 &include_disk();
70 pjm2 1.1
71 pjm2 1.6 # End the program normally.
72 pjm2 1.1 exit(0);
73    
74    
75    
76 pjm2 1.6
77 tdb 1.3 # prints out an identifier for this version of statgrab.pl
78     # the host should check this when reading data
79     # means the host must be checked and updated to work with newer versions.
80     sub print_ident() {
81 tdb 1.45 print 'version statgrab.pl $Revision: 1.44 $';
82 tdb 1.3 print "\n";
83     }
84 pjm2 1.1
85     # sub to print pairs of data, separated by a single space character.
86 pjm2 1.5 # If the second argument is undefined, then the pair is still printed,
87 pjm2 1.25 # however, the value shall be displayed as the the 'default' value
88     # if the passed value was undefined.
89 pjm2 1.8 sub print_pair($$$) {
90 pjm2 1.25 my($default, $name, $value) = @_;
91 pjm2 1.1
92     if (!defined $value) {
93 pjm2 1.25 $value = $default;
94 pjm2 1.1 }
95    
96     # Remove the trailing linefeed if we've not already done so.
97     chomp($value);
98    
99     # print the pair of data with a space inbetween.
100     print "$name $value\n";
101     }
102    
103    
104 pjm2 1.5 # sub to find out disk partition information, if it exists.
105     sub include_disk() {
106    
107     # Run the df program.
108 tdb 1.45 my(@df) = `$dfbin -akl`;
109 pjm2 1.5
110     # Go through each line of the program, looking for each thing we want.
111     my($partition_no) = 0;
112     for (my($i) = 0; $i < $#df; $i++) {
113     my($line) = $df[$i];
114 tdb 1.35 $line =~ /^([^\s]*)\s*([0-9]*)\s*([0-9]*)\s*([0-9]*)\s*[^\s]*\s*(\/[^\s]*)\s*/;
115 pjm2 1.5 # $4 will not match unless everything before it does...
116 pjm2 1.7 if (defined $5) {
117     my ($filesystem, $kbytes, $used, $avail, $mount) = ($1, $2, $3, $4, $5);
118 pjm2 1.25 &print_pair("unknown", "packet.disk.p$partition_no.attributes.name", $filesystem);
119     &print_pair(0, "packet.disk.p$partition_no.attributes.kbytes", $kbytes);
120     &print_pair(0, "packet.disk.p$partition_no.attributes.used", $used);
121     &print_pair(0, "packet.disk.p$partition_no.attributes.avail", $avail);
122     &print_pair("unknown", "packet.disk.p$partition_no.attributes.mount", $mount);
123 pjm2 1.5 ++$partition_no;
124     }
125     }
126    
127     }
128    
129     # sub to find out the list of all (non-unique) usernames logged
130     # in to the machine and how many their are. (not
131 pjm2 1.1 sub include_users() {
132    
133     # Find out all users on this machine.
134 tdb 1.13 my($users) = `$usersbin`;
135 pjm2 1.16 $users = "\n" unless defined $users;
136     chop $users;
137 pjm2 1.14 my($users_count) = 0;
138     $users_count++ while $users =~ /\w+/g;
139 pjm2 1.18 my($users_list) = $users." ";
140 pjm2 1.1
141 pjm2 1.25 &print_pair(0, "packet.users.count", $users_count);
142     &print_pair("unknown", "packet.users.list", $users_list);
143 pjm2 1.1 }
144    
145    
146 pjm2 1.5 # sub to run a series of regexps on the output of 'top' to
147     # gather various machine statistics.
148 pjm2 1.1 sub include_top() {
149    
150     # Find out some numbers from top.
151 tdb 1.31 my(@top) = `$topbin`;
152 pjm2 1.1 my($top) = join(" ", @top);
153 tdb 1.41 $top =~ s/\n/ /g;
154 pjm2 1.1
155 tdb 1.32 if($ostype eq "SunOS") {
156 tdb 1.40 &print_pair(0, "packet.processes.total", $top =~ /([0-9]+?) processes:/);
157     &print_pair(0, "packet.processes.sleeping", $top =~ /([0-9]+?) sleeping/);
158     &print_pair(0, "packet.processes.zombie", $top =~ /([0-9]+?) zombie/);
159     &print_pair(0, "packet.processes.stopped", $top =~ /([0-9]+?) stopped/);
160     &print_pair(0, "packet.processes.cpu", $top =~ /([0-9]+?)\s*on cpu/);
161 tdb 1.32 &print_pair(0, "packet.cpu.idle", $top =~ /([^\s]+?)% idle/);
162     &print_pair(0, "packet.cpu.user", $top =~ /([^\s]+?)% user/);
163     &print_pair(0, "packet.cpu.kernel", $top =~ /([^\s]+?)% kernel/);
164     &print_pair(0, "packet.cpu.iowait", $top =~ /([^\s]+?)% iowait/);
165     &print_pair(0, "packet.cpu.swap", $top =~ /([^\s]+?)% swap/);
166    
167     # The following need to be specified in megabytes.
168     # If they are preceeded by a G, then multiply by 1024.
169    
170 tdb 1.40 $top =~ /([0-9]+?)([KMG]) real/;
171 tdb 1.32 my($real) = $1;
172     $real*=1024 if $2 eq "G";
173 pjm2 1.37 $real/=1024 if $2 eq "K";
174 tdb 1.32 &print_pair(0, "packet.memory.total", $real);
175    
176 tdb 1.40 $top =~ /([0-9]+?)([KMG]) free/;
177 tdb 1.32 my($free) = $1;
178     $free*=1024 if $2 eq "G";
179 pjm2 1.37 $free/=1024 if $2 eq "K";
180 tdb 1.32 &print_pair(0, "packet.memory.free", $free);
181    
182 tdb 1.40 $top =~ /([0-9]+?)([KMG]) swap in use/;
183 tdb 1.32 my($swap_in_use) = $1;
184     $swap_in_use*=1024 if $2 eq "G";
185 pjm2 1.37 $swap_in_use/=1024 if $2 eq "K";
186 tdb 1.32 # DO NOT print this one out... save it for in a moment...
187    
188 tdb 1.40 $top =~ /([0-9]+?)([KMG]) swap free/;
189 tdb 1.32 my($swap_free) = $1;
190     $swap_free*=1024 if $2 eq "G";
191 pjm2 1.37 $swap_free/=1024 if $2 eq "K";
192 tdb 1.32 &print_pair(0, "packet.swap.free", $swap_free);
193    
194     &print_pair(0, "packet.swap.total", $swap_free + $swap_in_use);
195     }
196     elsif ($ostype eq "FreeBSD") {
197 tdb 1.40 &print_pair(0, "packet.processes.total", $top =~ /([0-9]+?) processes:/);
198     &print_pair(0, "packet.processes.sleeping", $top =~ /([0-9]+?) sleeping/);
199     &print_pair(0, "packet.processes.zombie", $top =~ /([0-9]+?) zombie/);
200     &print_pair(0, "packet.processes.stopped", $top =~ /([0-9]+?) stopped/);
201     &print_pair(0, "packet.processes.cpu", $top =~ /([0-9]+?)\s*running/);
202 tdb 1.32 &print_pair(0, "packet.cpu.idle", $top =~ /([^\s]+?)% idle/);
203     &print_pair(0, "packet.cpu.kernel", $top =~ /([^\s]+?)% system/);
204     &print_pair(0, "packet.cpu.iowait", $top =~ /([^\s]+?)% interrupt/);
205     &print_pair(0, "packet.cpu.swap", $top =~ /([^\s]+?)% swap/);
206 tdb 1.36
207     # FreeBSD is a bit different, we need to get user and nice.
208     my($user) = 0;
209     if($top =~ /([^\s]+?)% user/) { $user += $1; }
210     if($top =~ /([^\s]+?)% nice/) { $user += $1; }
211     &print_pair(0, "packet.cpu.user", $user);
212 tdb 1.32
213     # The following need to be specified in megabytes.
214     # If they are preceeded by a G, then multiply by 1024.
215    
216 tdb 1.39 # get RAM slightly differently
217     my($real) = `$sysctlbin -n hw.physmem`;
218     my($free) = $real - `$sysctlbin -n hw.usermem`;
219    
220     # turn bytes to megabytes
221     $real = ($real / 1024) / 1024;
222     $free = ($free / 1024) / 1024;
223 tdb 1.32
224 tdb 1.39 &print_pair(0, "packet.memory.total", $real);
225 tdb 1.32 &print_pair(0, "packet.memory.free", $free);
226    
227 tdb 1.40 $top =~ /Swap: ([0-9]+?)([KMG]) Total/;
228 tdb 1.32 my($swap_total) = $1;
229     $swap_total*=1024 if $2 eq "G";
230 pjm2 1.38 $swap_total/=1024 if $2 eq "K";
231 tdb 1.32 &print_pair(0, "packet.swap.total", $swap_total);
232    
233 tdb 1.40 $top =~ /Swap:.*, ([0-9]+?)([KMG]) Free/;
234 tdb 1.32 my($swap_free) = $1;
235     $swap_free*=1024 if $2 eq "G";
236 pjm2 1.38 $swap_free/=1024 if $2 eq "K";
237 tdb 1.32 &print_pair(0, "packet.swap.free", $swap_free);
238 tdb 1.39
239     my($loads) = `$sysctlbin -n vm.loadavg`;
240     $loads =~ /\s+([^\s]+?)\s+([^\s]+?)\s+([^\s]+?)\s+/;
241     &print_pair(0, "packet.load.load1", $1);
242     &print_pair(0, "packet.load.load5", $2);
243     &print_pair(0, "packet.load.load15", $3);
244 tdb 1.32 }
245 tdb 1.33 elsif ($ostype eq "Linux") {
246 tdb 1.41 my ($top) = "";
247     foreach my $line (@top) {
248     $top = $line . $top;
249     }
250     $top =~ s/\n/ /g;
251    
252 tdb 1.40 &print_pair(0, "packet.processes.total", $top =~ /([0-9]+?) processes:/);
253     &print_pair(0, "packet.processes.sleeping", $top =~ /([0-9]+?) sleeping/);
254     &print_pair(0, "packet.processes.zombie", $top =~ /([0-9]+?) zombie/);
255     &print_pair(0, "packet.processes.stopped", $top =~ /([0-9]+?) stopped/);
256     &print_pair(0, "packet.processes.cpu", $top =~ /([0-9]+?)\s*running/);
257 tdb 1.33 &print_pair(0, "packet.cpu.idle", $top =~ /([^\s]+?)% idle/);
258     &print_pair(0, "packet.cpu.kernel", $top =~ /([^\s]+?)% system/);
259     &print_pair(0, "packet.cpu.iowait", $top =~ /([^\s]+?)% interrupt/);
260     &print_pair(0, "packet.cpu.swap", $top =~ /([^\s]+?)% swap/);
261 tdb 1.41
262     # FreeBSD is a bit different, we need to get user and nice.
263     my($user) = 0;
264     if($top =~ /([^\s]+?)% user/) { $user += $1; }
265     if($top =~ /([^\s]+?)% nice/) { $user += $1; }
266     &print_pair(0, "packet.cpu.user", $user);
267 tdb 1.33
268     # The following need to be specified in megabytes.
269     # If they are preceeded by a G, then multiply by 1024.
270    
271 tdb 1.44 $top =~ /Mem:.*?([0-9]+)([KMG])\s+(av|total)/;
272 tdb 1.33 my($real) = $1;
273     $real*=1024 if $2 eq "G";
274     $real/=1024 if $2 eq "K";
275     &print_pair(0, "packet.memory.total", int($real));
276    
277 pjm2 1.42 $top =~ /Mem:.*?([0-9]+)([KMG])\s+free/;
278 tdb 1.33 my($free) = $1;
279     $free*=1024 if $2 eq "G";
280     $free/=1024 if $2 eq "K";
281     &print_pair(0, "packet.memory.free", int($free));
282    
283 tdb 1.44 $top =~ /Swap:.*?([0-9]+)([KMG])\s+(av|total)/;
284 tdb 1.33 my($swap_total) = $1;
285     $swap_total*=1024 if $2 eq "G";
286     $swap_total/=1024 if $2 eq "K";
287     &print_pair(0, "packet.swap.total", int($swap_total));
288    
289 pjm2 1.42 $top =~ /Swap:.*?([0-9]+)([KMG])\s+free/;
290 tdb 1.33 my($swap_free) = $1;
291     $swap_free*=1024 if $2 eq "G";
292     $swap_free/=1024 if $2 eq "K";
293     &print_pair(0, "packet.swap.free", int($swap_free));
294     }
295 tdb 1.32 else {
296     # we could have some catchall here
297 tdb 1.33 # but as it stands this means we'll just skip top stuff
298     # for unknown systems
299 tdb 1.32 }
300 tdb 1.2 }
301    
302 pjm2 1.5 # sub to get details of the machine's operating system.
303 tdb 1.2 sub include_osver() {
304    
305     # Find out details about the operating system
306 pjm2 1.5 # If these values remain undefined, then the print_pair
307     # function shall show the value to be the string "unknown".
308 tdb 1.13 my($os_name) = `$unamebin -s`;
309     my($os_release) = `$unamebin -r`;
310     my($os_platform) = `$unamebin -m`;
311     my($os_sysname) = `$unamebin -n`;
312     my($os_version) = `$unamebin -v`;
313 tdb 1.2
314 pjm2 1.25 &print_pair("unknown", "packet.os.name", $os_name);
315     &print_pair("unknown", "packet.os.release", $os_release);
316     &print_pair("unknown", "packet.os.platform", $os_platform);
317     &print_pair("unknown", "packet.os.sysname", $os_sysname);
318     &print_pair("unknown", "packet.os.version", $os_version);
319 tdb 1.2
320 pjm2 1.1 }
321 tdb 1.17
322 tdb 1.28 # sub to get system uptime in seconds.
323 tdb 1.17 sub include_uptime() {
324    
325 tdb 1.27 # debug stuff, all the different cases
326    
327     # normal
328     #my($uptime) = " 4:48pm up 49 day(s), 6:30, 201 users, load average: 0.33, 0.35, 0.38\n";
329     # 0 days
330     #my($uptime) = " 4:48pm up 6:30, 201 users, load average: 0.33, 0.35, 0.38\n";
331     # 0 hours
332     #my($uptime) = " 4:48pm up 49 day(s), 30 min(s), 201 users, load average: 0.33, 0.35, 0.38\n";
333     # 0 mins
334     #my($uptime) = " 4:48pm up 49 day(s), 6 hr(s), 201 users, load average: 0.33, 0.35, 0.38\n";
335     # 0 days and 0 mins
336     #my($uptime) = " 4:48pm up 6 hr(s), 201 users, load average: 0.33, 0.35, 0.38\n";
337     # 0 days and 0 hours
338     #my($uptime) = " 4:48pm up 30 min(s), 201 users, load average: 0.33, 0.35, 0.38\n";
339     # 0 hours and 0 mins
340     #my($uptime) = " 4:48pm up 49 day(s), 201 users, load average: 0.33, 0.35, 0.38\n";
341    
342 tdb 1.21 # grab the uptime
343 tdb 1.17 my($uptime) = `$uptimebin`;
344 pjm2 1.29
345 tdb 1.39 if($ostype ne "FreeBSD") {
346     &print_pair(0, "packet.load.load1", $uptime =~ /load average.?:\s*([^\s]+?),/);
347     &print_pair(0, "packet.load.load5", $uptime =~ /load average.?:\s*.+?,\s*([^\s]+?),/);
348     &print_pair(0, "packet.load.load15", $uptime =~ /load average.?:\s*.+?,\s*.+?,\s*([^\s]+)/);
349     }
350 tdb 1.21
351     # work out the days, hours, and minutes
352 tdb 1.28
353     if ($uptime =~ /day.*,\s+([0-9]+):([0-9]+)/) {
354     # normal
355 tdb 1.34 $uptime =~ /up\s+([0-9]+)\s+[^\s]+,\s+([0-9]+):([0-9]+)/;
356 tdb 1.28 $uptime = "$1:$2:$3";
357     }
358     else {
359     if ($uptime =~ /day/) {
360     if ($uptime =~ /hr/) {
361     # 0 minutes
362 tdb 1.34 $uptime =~ /up\s+([0-9]+)\s+[^\s]+,\s+([0-9]+)\s+[^\s]+,/;
363 tdb 1.28 $uptime = "$1:$2:0";
364     }
365     elsif ($uptime =~ /min/) {
366     # 0 hours
367 tdb 1.34 $uptime =~ /up\s+([0-9]+)\s+[^\s]+,\s+([0-9]+)\s+[^\s]+,/;
368 tdb 1.28 $uptime = "$1:0:$2";
369     }
370     else {
371     # 0 hours and 0 mins
372     $uptime =~ /up\s+([0-9]+)/;
373     $uptime = "$1:0:0";
374     }
375 tdb 1.27 }
376 tdb 1.28 elsif ($uptime =~ /hr/) {
377 tdb 1.27 # 0 days and 0 minutes
378     $uptime =~ /up\s+([0-9]+)\s+/;
379     $uptime = "0:$1:0";
380     }
381 tdb 1.28 elsif ($uptime =~ /min/) {
382 tdb 1.27 # 0 days and 0 hours
383     $uptime =~ /up\s+([0-9]+)\s+/;
384     $uptime = "0:0:$1";
385     }
386     else {
387 tdb 1.28 # 0 days
388     $uptime =~ /up\s+([0-9]+):([0-9]+)/;
389     $uptime = "0:$1:$2";
390 tdb 1.27 }
391 tdb 1.21 }
392    
393 tdb 1.28 # turn into seconds
394 tdb 1.21 $uptime =~ /([0-9]+):([0-9]+):([0-9]+)/;
395 tdb 1.28 $uptime = ($3+($2+($1*24))*60)*60;
396    
397     # print the value out
398 pjm2 1.25 &print_pair("unknown", "packet.os.uptime", $uptime);
399 tdb 1.17
400 pjm2 1.18 }