ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/host/generic/statgrab.pl
Revision: 1.33
Committed: Tue Feb 13 12:18:07 2001 UTC (23 years, 9 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.32: +43 -2 lines
Log Message:
Added some basic support for Linux. Linux top chucks out values in K's, so we
need to strip down to Megabytes (to be inline with the others).
Also, not convinced about the output of top, it seems to be stating that only
a couple of % of CPU is in use, when I can see clearly this isn't correct.

File Contents

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