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 (23 years, 1 month 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

# Content
1 #!/usr/bin/perl -w
2
3 #-----------------------------------------------------------------
4 # Machine statistics grabber
5 # $Author: tdb1 $
6 # $Id: statgrab.pl,v 1.44 2001/05/25 19:42:26 tdb1 Exp $
7 #
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 # Have to hope this will work really.
25 my($ostype) = `uname -s`; chop($ostype);
26
27 # Decide which paths we should use.
28 my($topbin); my($dfbin); my($usersbin);
29 my($unamebin); my($uptimebin); my($sysctlbin);
30
31 if ($ostype eq "SunOS") {
32 # covers: Solaris 8
33 $topbin = "/usr/local/sbin/top -d2 -s1 0";
34 $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 $topbin = "/usr/bin/top -d1 -n2 -b -p0";
42 $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 $topbin = "/usr/bin/top -d2 -s1 0";
50 $dfbin = "/bin/df";
51 $usersbin = "/usr/bin/users";
52 $unamebin = "/usr/bin/uname";
53 $uptimebin = "/usr/bin/uptime";
54 $sysctlbin = "/sbin/sysctl";
55 }
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
63 # Run the following components: -
64 &print_ident();
65 &include_osver();
66 &include_uptime();
67 &include_users();
68 &include_top();
69 &include_disk();
70
71 # End the program normally.
72 exit(0);
73
74
75
76
77 # 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 print 'version statgrab.pl $Revision: 1.44 $';
82 print "\n";
83 }
84
85 # sub to print pairs of data, separated by a single space character.
86 # If the second argument is undefined, then the pair is still printed,
87 # however, the value shall be displayed as the the 'default' value
88 # if the passed value was undefined.
89 sub print_pair($$$) {
90 my($default, $name, $value) = @_;
91
92 if (!defined $value) {
93 $value = $default;
94 }
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 # sub to find out disk partition information, if it exists.
105 sub include_disk() {
106
107 # Run the df program.
108 my(@df) = `$dfbin -akl`;
109
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 $line =~ /^([^\s]*)\s*([0-9]*)\s*([0-9]*)\s*([0-9]*)\s*[^\s]*\s*(\/[^\s]*)\s*/;
115 # $4 will not match unless everything before it does...
116 if (defined $5) {
117 my ($filesystem, $kbytes, $used, $avail, $mount) = ($1, $2, $3, $4, $5);
118 &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 ++$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 sub include_users() {
132
133 # Find out all users on this machine.
134 my($users) = `$usersbin`;
135 $users = "\n" unless defined $users;
136 chop $users;
137 my($users_count) = 0;
138 $users_count++ while $users =~ /\w+/g;
139 my($users_list) = $users." ";
140
141 &print_pair(0, "packet.users.count", $users_count);
142 &print_pair("unknown", "packet.users.list", $users_list);
143 }
144
145
146 # sub to run a series of regexps on the output of 'top' to
147 # gather various machine statistics.
148 sub include_top() {
149
150 # Find out some numbers from top.
151 my(@top) = `$topbin`;
152 my($top) = join(" ", @top);
153 $top =~ s/\n/ /g;
154
155 if($ostype eq "SunOS") {
156 &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 &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 $top =~ /([0-9]+?)([KMG]) real/;
171 my($real) = $1;
172 $real*=1024 if $2 eq "G";
173 $real/=1024 if $2 eq "K";
174 &print_pair(0, "packet.memory.total", $real);
175
176 $top =~ /([0-9]+?)([KMG]) free/;
177 my($free) = $1;
178 $free*=1024 if $2 eq "G";
179 $free/=1024 if $2 eq "K";
180 &print_pair(0, "packet.memory.free", $free);
181
182 $top =~ /([0-9]+?)([KMG]) swap in use/;
183 my($swap_in_use) = $1;
184 $swap_in_use*=1024 if $2 eq "G";
185 $swap_in_use/=1024 if $2 eq "K";
186 # DO NOT print this one out... save it for in a moment...
187
188 $top =~ /([0-9]+?)([KMG]) swap free/;
189 my($swap_free) = $1;
190 $swap_free*=1024 if $2 eq "G";
191 $swap_free/=1024 if $2 eq "K";
192 &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 &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 &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
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
213 # The following need to be specified in megabytes.
214 # If they are preceeded by a G, then multiply by 1024.
215
216 # 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
224 &print_pair(0, "packet.memory.total", $real);
225 &print_pair(0, "packet.memory.free", $free);
226
227 $top =~ /Swap: ([0-9]+?)([KMG]) Total/;
228 my($swap_total) = $1;
229 $swap_total*=1024 if $2 eq "G";
230 $swap_total/=1024 if $2 eq "K";
231 &print_pair(0, "packet.swap.total", $swap_total);
232
233 $top =~ /Swap:.*, ([0-9]+?)([KMG]) Free/;
234 my($swap_free) = $1;
235 $swap_free*=1024 if $2 eq "G";
236 $swap_free/=1024 if $2 eq "K";
237 &print_pair(0, "packet.swap.free", $swap_free);
238
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 }
245 elsif ($ostype eq "Linux") {
246 my ($top) = "";
247 foreach my $line (@top) {
248 $top = $line . $top;
249 }
250 $top =~ s/\n/ /g;
251
252 &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 &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
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
268 # The following need to be specified in megabytes.
269 # If they are preceeded by a G, then multiply by 1024.
270
271 $top =~ /Mem:.*?([0-9]+)([KMG])\s+(av|total)/;
272 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 $top =~ /Mem:.*?([0-9]+)([KMG])\s+free/;
278 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 $top =~ /Swap:.*?([0-9]+)([KMG])\s+(av|total)/;
284 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 $top =~ /Swap:.*?([0-9]+)([KMG])\s+free/;
290 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 else {
296 # we could have some catchall here
297 # but as it stands this means we'll just skip top stuff
298 # for unknown systems
299 }
300 }
301
302 # sub to get details of the machine's operating system.
303 sub include_osver() {
304
305 # Find out details about the operating system
306 # If these values remain undefined, then the print_pair
307 # function shall show the value to be the string "unknown".
308 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
314 &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
320 }
321
322 # sub to get system uptime in seconds.
323 sub include_uptime() {
324
325 # 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 # grab the uptime
343 my($uptime) = `$uptimebin`;
344
345 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
351 # work out the days, hours, and minutes
352
353 if ($uptime =~ /day.*,\s+([0-9]+):([0-9]+)/) {
354 # normal
355 $uptime =~ /up\s+([0-9]+)\s+[^\s]+,\s+([0-9]+):([0-9]+)/;
356 $uptime = "$1:$2:$3";
357 }
358 else {
359 if ($uptime =~ /day/) {
360 if ($uptime =~ /hr/) {
361 # 0 minutes
362 $uptime =~ /up\s+([0-9]+)\s+[^\s]+,\s+([0-9]+)\s+[^\s]+,/;
363 $uptime = "$1:$2:0";
364 }
365 elsif ($uptime =~ /min/) {
366 # 0 hours
367 $uptime =~ /up\s+([0-9]+)\s+[^\s]+,\s+([0-9]+)\s+[^\s]+,/;
368 $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 }
376 elsif ($uptime =~ /hr/) {
377 # 0 days and 0 minutes
378 $uptime =~ /up\s+([0-9]+)\s+/;
379 $uptime = "0:$1:0";
380 }
381 elsif ($uptime =~ /min/) {
382 # 0 days and 0 hours
383 $uptime =~ /up\s+([0-9]+)\s+/;
384 $uptime = "0:0:$1";
385 }
386 else {
387 # 0 days
388 $uptime =~ /up\s+([0-9]+):([0-9]+)/;
389 $uptime = "0:$1:$2";
390 }
391 }
392
393 # turn into seconds
394 $uptime =~ /([0-9]+):([0-9]+):([0-9]+)/;
395 $uptime = ($3+($2+($1*24))*60)*60;
396
397 # print the value out
398 &print_pair("unknown", "packet.os.uptime", $uptime);
399
400 }