File Coverage

blib/lib/Linux/Info.pm
Criterion Covered Total %
statement 62 80 77.5
branch 20 36 55.5
condition 2 8 25.0
subroutine 9 12 75.0
pod 6 6 100.0
total 99 142 69.7


line stmt bran cond sub pod time code
1             package Linux::Info;
2 13     13   805773 use strict;
  13         125  
  13         382  
3 13     13   71 use warnings;
  13         24  
  13         373  
4 13     13   62 use Carp qw(confess);
  13         25  
  13         715  
5 13     13   6747 use POSIX qw(strftime);
  13         83207  
  13         67  
6 13     13   25583 use UNIVERSAL;
  13         177  
  13         54  
7 13     13   6313 use Linux::Info::Compilation;
  13         36  
  13         145  
8              
9             our $VERSION = '1.5'; # VERSION
10              
11             =head1 NAME
12              
13             Linux::Info - API in Perl to recover information about the running Linux OS
14              
15             =head1 SYNOPSIS
16              
17             use Linux::Info;
18              
19             # you can't use sysinfo like that!
20             my $lxs = Linux::Info->new(
21             cpustats => 1,
22             procstats => 1,
23             memstats => 1,
24             pgswstats => 1,
25             netstats => 1,
26             sockstats => 1,
27             diskstats => 1,
28             diskusage => 1,
29             loadavg => 1,
30             filestats => 1,
31             processes => 1,
32             );
33              
34             sleep 1;
35             my $stat = $lxs->get;
36              
37             =head1 DESCRIPTION
38              
39             Linux::Info is a fork from L distribution.
40              
41             L is a front-end module and gather different linux
42             system information like processor workload, memory usage, network and disk
43             statistics and a lot more. Refer the documentation of the distribution modules
44             to get more information about all possible statistics.
45              
46             =head1 MOTIVATION
47              
48             L is a great distribution (and I used it a lot), but it
49             was built to recover only Linux statistics when I was also looking for other
50             additional information about the OS.
51              
52             Linux::Info will provide additional information not available in
53             L, as general processor information and hopefully apply
54             patches and suggestions not implemented in the original project.
55              
56             L is also more forgiving regarding compatibility with
57             older perls interpreters, modules version that it depends on and even older OS.
58             If you find that C is not available to your old system, you should
59             try it.
60              
61             =head2 What is different from Sys::Statistics::Linux?
62              
63             Linux::Info has:
64              
65             =over
66              
67             =item *
68              
69             a more modern Perl 5 code;
70              
71             =item *
72              
73             doesn't use C syscall to acquire information;
74              
75             =item *
76              
77             provides additional information about the processors;
78              
79             =item *
80              
81             higher Kwalitee;
82              
83             =back
84              
85             =head1 TECHNICAL NOTE
86              
87             This distribution collects statistics by the virtual F filesystem (procfs) and is
88             developed on the default vanilla kernel. It is tested on x86 hardware with the distributions
89             RHEL, Fedora, Debian, Ubuntu, Asianux, Slackware, Mandriva and openSuSE (SLES on zSeries as
90             well but a long time ago) on kernel versions 2.4 and/or 2.6. It's possible that it doesn't
91             run on all linux distributions if some procfs features are deactivated or too much modified.
92             As example the Linux kernel 2.4 can compiled with the option C what turn
93             on or off block statistics for devices.
94              
95             =head1 VIRTUAL MACHINES
96              
97             Note that if you try to install or run C under virtual machines
98             on guest systems that some statistics are not available, such as C, C
99             and C. The reason is that not all F data are passed to the guests.
100              
101             If the installation fails then try to force the installation with
102              
103             cpan> force install Linux::Info
104              
105             and notice which tests fails, because these statistics maybe not available on the virtual machine - sorry.
106              
107             =head1 DELTAS
108              
109             The statistics for C, C, C, C, C and C
110             are deltas, for this reason it's necessary to initialize the statistics before the data can be
111             prepared by C. These statistics can be initialized with the methods C, C and
112             C. For any option that is set to 1, the statistics will be initialized by the call of
113             C or C. The call of init() re-initialize all statistics that are set to 1 or 2.
114             By the call of C the initial statistics will be updated automatically. Please refer the
115             section L to get more information about the usage of C, C, C
116             and C.
117              
118             Another exigence is to C for a while - at least for one second - before the call of C
119             if you want to get useful statistics. The statistics for C, C, C,
120             C, C and C are no deltas. If you need only one of these information
121             you don't need to sleep before the call of C.
122              
123             The method C prepares all requested statistics and returns the statistics as a
124             L object. The initial statistics will be updated.
125              
126             =head1 MANUAL PROC(5)
127              
128             The Linux Programmer's Manual
129              
130             L
131              
132             If you have questions or don't understand the sense of some statistics then take a look
133             into this awesome documentation.
134              
135             =head1 OPTIONS FOR NEW INSTANCES
136              
137             During the creation of new instances of L, you can pass as parameters to the C method different statistics to
138             collect. The statistics available are those listed on L.
139              
140             You can use the L by using their respective package names in lowercase. To activate the gathering of statistics you have to set the options by the call of C or C.
141             In addition you can deactivate statistics with C.
142              
143             The options must be set with one of the following values:
144              
145             0 - deactivate statistics
146             1 - activate and init statistics
147             2 - activate statistics but don't init
148              
149             In addition it's possible to pass a hash reference with options.
150              
151             my $lxs = Linux::Info->new(
152             processes => {
153             init => 1,
154             pids => [ 1, 2, 3 ]
155             },
156             netstats => {
157             init => 1,
158             initfile => $file,
159             },
160             );
161              
162             Option C is useful if you want to store initial statistics on the filesystem.
163              
164             my $lxs = Linux::Info->new(
165             cpustats => {
166             init => 1,
167             initfile => '/tmp/cpustats.yml',
168             },
169             diskstats => {
170             init => 1,
171             initfile => '/tmp/diskstats.yml',
172             },
173             netstats => {
174             init => 1,
175             initfile => '/tmp/netstats.yml',
176             },
177             pgswstats => {
178             init => 1,
179             initfile => '/tmp/pgswstats.yml',
180             },
181             procstats => {
182             init => 1,
183             initfile => '/tmp/procstats.yml',
184             },
185             );
186              
187             Example:
188              
189             use strict;
190             use warnings;
191             use Linux::Info;
192              
193             my $lxs = Linux::Info->new(
194             pgswstats => {
195             init => 1,
196             initfile => '/tmp/pgswstats.yml'
197             }
198             );
199              
200             $lxs->get(); # without to sleep
201              
202             The initial statistics are stored to the temporary file:
203              
204             #> cat /tmp/pgswstats.yml
205             ---
206             pgfault: 397040955
207             pgmajfault: 4611
208             pgpgin: 21531693
209             pgpgout: 49511043
210             pswpin: 8
211             pswpout: 272
212             time: 1236783534.9328
213              
214             Every time you call the script the initial statistics are loaded/stored from/to the file.
215             This could be helpful if you doesn't run it as daemon and if you want to calculate the
216             average load of your system since the last call.
217              
218             To get more information about the statistics refer the different modules of the distribution.
219              
220             cpustats - Collect cpu statistics with Linux::Info::CpuStats.
221             procstats - Collect process statistics with Linux::Info::ProcStats.
222             memstats - Collect memory statistics with Linux::Info::MemStats.
223             pgswstats - Collect paging and swapping statistics with Linux::Info::PgSwStats.
224             netstats - Collect net statistics with Linux::Info::NetStats.
225             sockstats - Collect socket statistics with Linux::Info::SockStats.
226             diskstats - Collect disk statistics with Linux::Info::DiskStats.
227             diskusage - Collect the disk usage with Linux::Info::DiskUsage.
228             loadavg - Collect the load average with Linux::Info::LoadAVG.
229             filestats - Collect inode statistics with Linux::Info::FileStats.
230             processes - Collect process statistics with Linux::Info::Processes.
231              
232             The options just described don't apply to L since this module doesn't hold statistics from the OS.
233             If you try to use it C will C with an error message. In order to use L, just
234             create an instance of it directly. See L for information on that.
235              
236             =head1 METHODS
237              
238             =head2 new()
239              
240             Call C to create a new Linux::Info object. You can call C with options.
241             This options would be passed to the method C.
242              
243             Without options
244              
245             my $lxs = Linux::Info->new();
246              
247             Or with options
248              
249             my $lxs = Linux::Info->new( cpustats => 1 );
250              
251             Would do nothing
252              
253             my $lxs = Linux::Info->new( cpustats => 0 );
254              
255             It's possible to call C with a hash reference of options.
256              
257             my %options = (
258             cpustats => 1,
259             memstats => 1
260             );
261              
262             my $lxs = Linux::Info->new(\%options);
263             =cut
264              
265             sub new {
266 14     14 1 8304 my $class = shift;
267 14         58 my $self = bless { obj => {} }, $class;
268              
269 14         85 my @options = qw(
270             CpuStats ProcStats
271             MemStats PgSwStats NetStats
272             SockStats DiskStats DiskUsage
273             LoadAVG FileStats Processes
274             );
275              
276 14         43 foreach my $opt (@options) {
277              
278             # backward compatibility
279 154         318 $self->{opts}->{$opt} = 0;
280 154         233 $self->{maps}->{$opt} = $opt;
281              
282             # new style
283 154         230 my $lcopt = lc($opt);
284 154         270 $self->{opts}->{$lcopt} = 0;
285 154         262 $self->{maps}->{$lcopt} = $opt;
286             }
287              
288 14 100       60 $self->set(@_) if @_;
289 12         45 return $self;
290             }
291              
292             =head2 set()
293              
294             Call C to activate or deactivate options.
295              
296             The following example would call C and initialize C
297             and delete the object of C.
298              
299             $lxs->set(
300             processes => 0, # deactivate this statistic
301             pgswstats => 1, # activate the statistic and calls new() and init() if necessary
302             netstats => 2, # activate the statistic and call new() if necessary but not init()
303             );
304              
305             It's possible to call C with a hash reference of options.
306              
307             my %options = (
308             cpustats => 2,
309             memstats => 2
310             );
311              
312             $lxs->set(\%options);
313             =cut
314              
315             sub set {
316 15     15 1 2694 my $self = shift;
317 15         41 my $class = ref $self;
318 15 50       80 my $args = ref( $_[0] ) eq 'HASH' ? shift : {@_};
319 15         40 my $opts = $self->{opts};
320 15         29 my $obj = $self->{obj};
321 15         30 my $maps = $self->{maps};
322              
323             confess 'Linux::Info::SysInfo cannot be instantiated from Linux::Info'
324 15 100       63 if ( exists( $args->{sysinfo} ) );
325              
326 14         28 foreach my $opt ( keys( %{$args} ) ) {
  14         60  
327              
328             confess "invalid delta option '$opt'"
329 17 100       69 unless ( exists( $opts->{$opt} ) );
330              
331 16 50       192 if ( ref( $args->{$opt} ) ) {
    50          
332 0   0     0 $opts->{$opt} = delete $args->{$opt}->{init} || 1;
333             }
334             elsif ( $args->{$opt} !~ qr/^[012]\z/ ) {
335 0         0 confess "invalid value for '$opt'";
336             }
337             else {
338 16         46 $opts->{$opt} = $args->{$opt};
339             }
340              
341 16 50       90 if ( $opts->{$opt} ) {
    0          
342 16         64 my $package = $class . '::' . $maps->{$opt};
343              
344             # require module - require know which modules are loaded
345             # and doesn't load a module twice.
346 16         29 my $require = $package;
347 16         74 $require =~ s/::/\//g;
348 16         40 $require .= '.pm';
349 16         7260 require $require;
350              
351 16 100       91 if ( !$obj->{$opt} ) {
352 15 50       63 if ( ref( $args->{$opt} ) ) {
353 0         0 $obj->{$opt} = $package->new( %{ $args->{$opt} } );
  0         0  
354             }
355             else {
356 15         100 $obj->{$opt} = $package->new();
357             }
358             }
359              
360             # get initial statistics if the function init() exists
361             # and the option is set to 1
362 16 100 66     232 if ( $opts->{$opt} == 1 && UNIVERSAL::can( $package, 'init' ) ) {
363 11         52 $obj->{$opt}->init();
364             }
365              
366             }
367             elsif ( exists $obj->{$opt} ) {
368 0         0 delete $obj->{$opt};
369             }
370             }
371             }
372              
373             =head2 get()
374              
375             Call C to get the collected statistics. C returns a
376             L object.
377              
378             my $lxs = Linux::Info->new(\%options);
379             sleep(1);
380             my $stat = $lxs->get();
381              
382             Or you can pass the time to sleep with the call of C.
383              
384             my $stat = $lxs->get($time_to_sleep);
385              
386             Now the statistcs are available with
387              
388             $stat->cpustats
389              
390             # or
391              
392             $stat->{cpustats}
393              
394             Take a look to the documentation of L for more information.
395              
396             =cut
397              
398             sub get {
399 12     12 1 9002575 my ( $self, $time ) = @_;
400 12 50       124 sleep $time if $time;
401 12         55 my %stat = ();
402              
403 12         33 foreach my $opt ( keys %{ $self->{opts} } ) {
  12         429  
404 264 100       588 if ( $self->{opts}->{$opt} ) {
405 15         144 $stat{$opt} = $self->{obj}->{$opt}->get();
406 15 100       78 if ( $opt eq 'netstats' ) {
407 1         7 $stat{netinfo} = $self->{obj}->{$opt}->get_raw();
408             }
409             }
410             }
411              
412 12         285 return Linux::Info::Compilation->new( \%stat );
413             }
414              
415              
416             =head2 init()
417              
418             The call of C initiate all activated statistics that are necessary for
419             deltas. That could be helpful if your script runs in a endless loop with a high
420             sleep interval. Don't forget that if you call C that the statistics are
421             deltas since the last time they were initiated.
422              
423             The following example would calculate average statistics for 30 minutes:
424              
425             # initiate cpustats
426             my $lxs = Linux::Info->new( cpustats => 1 );
427              
428             while ( 1 ) {
429             sleep(1800);
430             my $stat = $lxs->get;
431             }
432              
433             If you just want a current snapshot of the system each 30 minutes and not the
434             average then the following example would be better for you:
435              
436             # do not initiate cpustats
437             my $lxs = Linux::Info->new( cpustats => 2 );
438              
439             while ( 1 ) {
440             $lxs->init; # init the statistics
441             my $stat = $lxs->get(1); # get the statistics
442             sleep(1800); # sleep until the next run
443             }
444              
445             If you want to write a simple command line utility that prints the current
446             workload to the screen then you can use something like this:
447              
448             my @order = qw(user system iowait idle nice irq softirq total);
449             printf "%-20s%8s%8s%8s%8s%8s%8s%8s%8s\n", 'time', @order;
450              
451             my $lxs = Linux::Info->new( cpustats => 1 );
452              
453             while ( 1 ){
454             my $cpu = $lxs->get(1)->cpustats;
455             my $time = $lxs->gettime;
456             printf "%-20s%8s%8s%8s%8s%8s%8s%8s%8s\n",
457             $time, @{$cpu->{cpu}}{@order};
458             }
459              
460             =cut
461              
462             sub init {
463 0     0 1   my $self = shift;
464 0           my $class = ref $self;
465              
466 0           foreach my $opt ( keys %{ $self->{opts} } ) {
  0            
467 0 0 0       if ( $self->{opts}->{$opt} > 0
468             && UNIVERSAL::can( ref( $self->{obj}->{$opt} ), 'init' ) )
469             {
470 0           $self->{obj}->{$opt}->init();
471             }
472             }
473             }
474              
475             =head2 settime()
476              
477             Call C to define a POSIX formatted time stamp, generated with
478             localtime().
479              
480             $lxs->settime('%Y/%m/%d %H:%M:%S');
481              
482             To get more information about the formats take a look at C of
483             POSIX.pm or the manpage C.
484              
485             =cut
486              
487             sub settime {
488 0     0 1   my $self = shift;
489 0 0         my $format = @_ ? shift : '%Y-%m-%d %H:%M:%S';
490 0           $self->{timeformat} = $format;
491             }
492              
493             =head2 gettime()
494              
495             C returns a POSIX formatted time stamp, @foo in list and $bar in
496             scalar context. If the time format isn't set then the default format
497             "%Y-%m-%d %H:%M:%S" will be set automatically. You can also set a time format
498             with C.
499              
500             my $date_time = $lxs->gettime;
501              
502             Or
503              
504             my ($date, $time) = $lxs->gettime();
505              
506             Or
507              
508             my ($date, $time) = $lxs->gettime('%Y/%m/%d %H:%M:%S');
509             =cut
510              
511             sub gettime {
512 0     0 1   my $self = shift;
513 0 0         $self->settime(@_) unless $self->{timeformat};
514 0           my $tm = strftime( $self->{timeformat}, localtime );
515 0 0         return wantarray ? split /\s+/, $tm : $tm;
516             }
517              
518             =head1 EXAMPLES
519              
520             A very simple perl script could looks like this:
521              
522             use strict;
523             use warnings;
524             use Linux::Info;
525              
526             my $lxs = Linux::Info->new( cpustats => 1 );
527             sleep(1);
528             my $stat = $lxs->get;
529             my $cpu = $stat->cpustats->{cpu};
530              
531             print "Statistics for CpuStats (all)\n";
532             print " user $cpu->{user}\n";
533             print " nice $cpu->{nice}\n";
534             print " system $cpu->{system}\n";
535             print " idle $cpu->{idle}\n";
536             print " ioWait $cpu->{iowait}\n";
537             print " total $cpu->{total}\n";
538              
539             Set and get a time stamp:
540              
541             use strict;
542             use warnings;
543             use Linux::Info;
544              
545             my $lxs = Linux::Info->new();
546             $lxs->settime('%Y/%m/%d %H:%M:%S');
547             print $lxs->gettime, "\n";
548              
549             If you want to know how the data structure looks like you can use C to check it:
550              
551             use strict;
552             use warnings;
553             use Linux::Info;
554             use Data::Dumper;
555              
556             my $lxs = Linux::Info->new( cpustats => 1 );
557             sleep(1);
558             my $stat = $lxs->get;
559              
560             print Dumper($stat);
561              
562             How to get the top 5 processes with the highest cpu workload:
563              
564             use strict;
565             use warnings;
566             use Linux::Info;
567              
568             my $lxs = Linux::Info->new( processes => 1 );
569             sleep(1);
570             my $stat = $lxs->get;
571             my @top5 = $stat->pstop( ttime => 5 );
572              
573             =head1 EXPORTS
574              
575             Nothing.
576              
577             =head1 SEE ALSO
578              
579             =over
580              
581             =item *
582              
583             The L distribution, which is base of Linux::Info
584              
585             =item *
586              
587             The project website at L.
588              
589             =back
590              
591             =head1 AUTHOR
592              
593             Alceu Rodrigues de Freitas Junior, Earfreitas@cpan.orgE
594              
595             =head1 COPYRIGHT AND LICENSE
596              
597             This software is copyright (c) 2015 of Alceu Rodrigues de Freitas Junior, Earfreitas@cpan.orgE
598              
599             This file is part of Linux Info project.
600              
601             Linux Info is free software: you can redistribute it and/or modify
602             it under the terms of the GNU General Public License as published by
603             the Free Software Foundation, either version 3 of the License, or
604             (at your option) any later version.
605              
606             Linux Info is distributed in the hope that it will be useful,
607             but WITHOUT ANY WARRANTY; without even the implied warranty of
608             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
609             GNU General Public License for more details.
610              
611             You should have received a copy of the GNU General Public License
612             along with Linux Info. If not, see .
613              
614             =cut
615              
616             1;