File Coverage

blib/lib/Linux/Info/SysInfo.pm
Criterion Covered Total %
statement 128 134 95.5
branch 41 58 70.6
condition 7 18 38.8
subroutine 15 15 100.0
pod 2 2 100.0
total 193 227 85.0


line stmt bran cond sub pod time code
1             package Linux::Info::SysInfo;
2 1     1   66082 use strict;
  1         9  
  1         29  
3 1     1   5 use warnings;
  1         2  
  1         27  
4 1     1   5 use Carp qw(croak);
  1         1  
  1         55  
5 1     1   503 use POSIX 1.15;
  1         6187  
  1         6  
6 1     1   3265 use Hash::Util qw(lock_keys);
  1         2701  
  1         6  
7 1     1   89 use base 'Class::Accessor';
  1         2  
  1         532  
8             our $VERSION = '1.5'; # VERSION
9              
10             my @_attribs =
11             qw(raw_time hostname domain kernel release version mem swap pcpucount tcpucount interfaces arch proc_arch cpu_flags uptime idletime model);
12              
13             __PACKAGE__->follow_best_practice;
14             __PACKAGE__->mk_ro_accessors(@_attribs);
15              
16             =head1 NAME
17              
18             Linux::Info::SysInfo - Collect linux system information.
19              
20             =head1 SYNOPSIS
21              
22             use Linux::Info::SysInfo;
23              
24             my $lxs = Linux::Info::SysInfo->new;
25             print $lxs->get_release(), "\n";
26              
27             =head1 DESCRIPTION
28              
29             Linux::Info::SysInfo gathers system information from the virtual F filesystem (procfs).
30              
31             For more information read the documentation of the front-end module L.
32              
33             This class interface is B with L.
34              
35             =head1 ATTRIBUTES
36              
37             Generated by F
38             and F, F, F, F.
39              
40             These are the following attribute available for a instance of this class:
41              
42             =over
43              
44             =item *
45              
46             hostname - The host name.
47              
48             =item *
49              
50             domain - The host domain name.
51              
52             =item *
53              
54             kernel - The kernel name.
55              
56             =item *
57              
58             release - The kernel release.
59              
60             =item *
61              
62             version - The kernel version.
63              
64             =item *
65              
66             mem - The total size of memory.
67              
68             =item *
69              
70             swap - The total size of swap space.
71              
72             =item *
73              
74             uptime - The uptime of the system.
75              
76             =item *
77              
78             idletime - The idle time of the system.
79              
80             =item *
81              
82             pcpucount - The total number of physical CPUs.
83              
84             =item *
85              
86             tcpucount - The total number of CPUs (cores, hyper threading).
87              
88             =item *
89              
90             interfaces - The interfaces of the system.
91              
92             =item *
93              
94             arch - The processor architecture (like C).
95              
96             =item *
97              
98             multithread - A boolean indicating if the process has hyper threading enabled or not.
99              
100             =item *
101              
102             model - the processor name
103              
104             =back
105              
106             C and C are really easy to understand. Both values
107             are collected from C. C is the number of physical
108             CPUs, counted by C. C is just the total number
109             counted by C.
110              
111             All attributes are read-only. Their corresponding value can will be returned upon invocation of their respective "get_" method.
112              
113             =head1 METHODS
114              
115             =head2 new()
116              
117             Call C to create a new object.
118              
119             my $lxs = Linux::Info::SysInfo->new();
120              
121             Without any parameters.
122              
123             If you want to get C and C as raw value, then pass the following hash reference as parameter:
124              
125             my $lxs = Linux::Info::SysInfo->new({ raw_time => 1});
126              
127             By default the C attribute is false.
128              
129             =head2 get_proc_arch
130              
131             This method will return an integer as the architecture of the CPUs: 32 or 64 bits, depending on the flags
132             retrieve for one CPU.
133              
134             It is assumed that all CPUs will have the same flags, so this method will consider only the flags returned
135             by the CPU with "core id" equal to 0 (in other words, the first CPU found).
136              
137             =head2 get_cpu_flags
138              
139             Returns an array reference with all flags retrieve from C using the same logic described in
140             C documentation.
141              
142             =head2 is_multithread
143              
144             A getter for the C attribute.
145              
146             =head2 get_model
147              
148             A getter for the C attribute.
149              
150             =head1 EXPORTS
151              
152             Nothing.
153              
154             =head1 KNOWN ISSUES
155              
156             Linux running on ARM processors have a different interface on /proc/cpuinfo. That means that the methods C and C
157             will not return their respective information. Tests for this module may fail as well.
158              
159             =head1 SEE ALSO
160              
161             =over
162              
163             =item *
164              
165             B
166              
167             =item *
168              
169             L
170              
171             =item *
172              
173             L
174              
175             =item *
176              
177             L
178              
179             =back
180              
181             =head1 AUTHOR
182              
183             Alceu Rodrigues de Freitas Junior, Earfreitas@cpan.orgE
184              
185             =head1 COPYRIGHT AND LICENSE
186              
187             This software is copyright (c) 2015 of Alceu Rodrigues de Freitas Junior, Earfreitas@cpan.orgE
188              
189             This file is part of Linux Info project.
190              
191             Linux-Info is free software: you can redistribute it and/or modify
192             it under the terms of the GNU General Public License as published by
193             the Free Software Foundation, either version 3 of the License, or
194             (at your option) any later version.
195              
196             Linux-Info is distributed in the hope that it will be useful,
197             but WITHOUT ANY WARRANTY; without even the implied warranty of
198             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
199             GNU General Public License for more details.
200              
201             You should have received a copy of the GNU General Public License
202             along with Linux Info. If not, see .
203              
204             =cut
205              
206             sub new {
207              
208 2     2 1 8683 my $class = shift;
209 2         4 my $opts_ref = shift;
210              
211 2         3 my $raw_time;
212              
213             ( ( ref($opts_ref) eq 'HASH' )
214             and ( exists( $opts_ref->{raw_time} ) )
215             and ( $opts_ref->{raw_time} =~ /^[01]$/ ) )
216             ? ( $raw_time = $opts_ref->{raw_time} )
217 2 100 33     19 : ( $raw_time = 0 );
218              
219 2         40 my %self = (
220             files => {
221             path => "/proc",
222             meminfo => "meminfo",
223             sysinfo => "sysinfo",
224             cpuinfo => "cpuinfo",
225             uptime => "uptime",
226             hostname => "sys/kernel/hostname",
227             domain => "sys/kernel/domainname",
228             kernel => "sys/kernel/ostype",
229             release => "sys/kernel/osrelease",
230             version => "sys/kernel/version",
231             netdev => "net/dev",
232             },
233             arch => ( uname() )[4],
234             raw_time => $raw_time,
235             );
236              
237 2         8 my $self = bless \%self, $class;
238              
239 2         7 $self->_set();
240 2         3 lock_keys( %{$self} );
  2         11  
241              
242 2         37 return $self;
243              
244             }
245              
246             sub _set {
247              
248 2     2   3 my $self = shift;
249 2         4 my $class = ref $self;
250 2         10 my $file = $self->{files};
251              
252 2         5 foreach my $attrib (@_attribs) {
253              
254 34 100       79 $self->{$attrib} = undef unless ( exists( $self->{$attrib} ) );
255              
256             }
257              
258 2         8 $self->_set_common;
259 2         12 $self->_set_meminfo;
260 2         12 $self->_set_time;
261 2         25 $self->_set_interfaces;
262 2         7 $self->_set_cpuinfo;
263              
264 2         6 foreach my $attrib (@_attribs) {
265              
266 34 50       59 if ( defined( $self->{attrib} ) ) {
267              
268 0         0 $self->{$attrib} =~ s/\t+/ /g;
269 0         0 $self->{$attrib} =~ s/\s+/ /g;
270              
271             }
272              
273             }
274              
275             }
276              
277             sub is_multithread {
278              
279 1     1 1 1935 my $self = shift;
280 1         6 return $self->{multithread};
281              
282             }
283              
284             sub _set_common {
285              
286 2     2   2 my $self = shift;
287 2         16 my $class = ref($self);
288 2         3 my $file = $self->{files};
289              
290 2         5 for my $attrib (qw(hostname domain kernel release version)) {
291             my $filename =
292 10 50       45 $file->{path} ? "$file->{path}/$file->{$attrib}" : $file->{$attrib};
293 10 50       309 open my $fh, '<', $filename
294             or croak "$class: unable to open $filename: $!";
295 10         121 $self->{$attrib} = <$fh>;
296 10         32 chomp( $self->{$attrib} );
297 10         92 close($fh);
298             }
299              
300             }
301              
302             sub _set_meminfo {
303 2     2   4 my $self = shift;
304 2         4 my $class = ref($self);
305 2         5 my $file = $self->{files};
306              
307             my $filename =
308 2 50       9 $file->{path} ? "$file->{path}/$file->{meminfo}" : $file->{meminfo};
309 2 50       69 open my $fh, '<', $filename
310             or croak "$class: unable to open $filename ($!)";
311              
312 2         60 while ( my $line = <$fh> ) {
313 90 100       249 if ( $line =~ /^MemTotal:\s+(\d+ \w+)/ ) {
    100          
314 2         12 $self->{mem} = $1;
315             }
316             elsif ( $line =~ /^SwapTotal:\s+(\d+ \w+)/ ) {
317 2         7 $self->{swap} = $1;
318             }
319             }
320              
321 2         32 close($fh);
322             }
323              
324             sub _set_cpuinfo {
325 2     2   5 my $self = shift;
326 2         3 my $class = ref($self);
327 2         5 my $file = $self->{files};
328 2         5 my ( %cpu, $phyid );
329              
330 2         4 $self->{tcpucount} = 0;
331              
332             my $filename =
333 2 50       9 $file->{path} ? "$file->{path}/$file->{cpuinfo}" : $file->{cpuinfo};
334 2 50       63 open my $fh, '<', $filename
335             or croak "$class: unable to open $filename ($!)";
336              
337             # default value for hyper threading
338 2         7 $self->{multithread} = 0;
339              
340             # model name : Intel(R) Core(TM) i5-4300M CPU @ 2.60GHz
341 2         11 my $model_regex = qr/^model\sname\s+\:\s(.*)/;
342              
343             # Processor : ARMv7 Processor rev 4 (v7l)
344 2         6 my $arm_regex = qr/^Processor\s+\:\s(.*)/;
345              
346 2         213 while ( my $line = <$fh> ) {
347              
348 864         1495 chomp($line);
349              
350             CASE: {
351              
352 864 100 66     985 if ( ( $line =~ $model_regex ) or ( $line =~ $arm_regex ) ) {
  864         3418  
353              
354 32         90 $self->{model} = $1;
355              
356             }
357              
358 864 100       1559 if ( $line =~ /^physical\s+id\s*:\s*(\d+)/ ) {
359 32         62 $phyid = $1;
360 32         83 $cpu{$phyid}{count}++;
361 32         88 last CASE;
362             }
363              
364 832 100       1336 if ( $line =~ /^core\s+id\s*:\s*(\d+)/ ) {
365 32         80 $cpu{$phyid}{cores}{$1}++;
366 32         88 last CASE;
367             }
368              
369 800 100       1289 if ( $line =~ /^processor\s*:\s*\d+/ ) { # x86
370 32         51 $self->{tcpucount}++;
371 32         91 last CASE;
372             }
373              
374 768 50       1248 if ( $line =~ /^# processors\s*:\s*(\d+)/ ) { # s390
375 0         0 $self->{tcpucount} = $1;
376 0         0 last CASE;
377             }
378              
379 768 100       2375 if ( $line =~ /^flags\s+\:/ ) {
380              
381 32 100       83 last CASE if ( $self->get_cpu_flags ); # no use to repeat this
382              
383 2         38 my ( $attribute, $value ) = split( /\s+:\s/, $line );
384 2         41 my @flags = split( /\s/, $value );
385              
386 2         7 $self->{cpu_flags} = \@flags;
387              
388             #long mode
389 2 50       10 if ( $value =~ /\slm\s/ ) {
390              
391 2         6 $self->{proc_arch} = 64;
392              
393             }
394             else {
395              
396 0         0 $self->{proc_arch} = 32;
397              
398             }
399              
400             #hyper threading
401 2 50       5 if ( $value =~ /\sht\s/ ) {
402              
403 0         0 $self->{multithread} = 1;
404              
405             }
406              
407 2         16 last CASE;
408              
409             }
410              
411             }
412              
413             }
414              
415 2         26 close($fh);
416              
417 2   33     31 $self->{pcpucount} = scalar( keys(%cpu) ) || $self->{tcpucount};
418             }
419              
420             sub _set_interfaces {
421 2     2   6 my $self = shift;
422 2         4 my $class = ref($self);
423 2         4 my $file = $self->{files};
424 2         5 my @iface = ();
425              
426             my $filename =
427 2 50       7 $file->{path} ? "$file->{path}/$file->{netdev}" : $file->{netdev};
428 2 50       101 open my $fh, '<', $filename
429             or croak "$class: unable to open $filename ($!)";
430 2         6 { my $head = <$fh>; }
  2         52  
431              
432 2         10 while ( my $line = <$fh> ) {
433 6 100       28 if ( $line =~ /^\s*(\w+):/ ) {
434 4         29 push @iface, $1;
435             }
436             }
437              
438 2         28 close $fh;
439              
440 2         13 $self->{interfaces} = \@iface;
441              
442             }
443              
444             sub _set_time {
445 2     2   4 my $self = shift;
446 2         5 my $class = ref($self);
447 2         5 my $file = $self->{files};
448              
449             my $filename =
450 2 50       9 $file->{path} ? "$file->{path}/$file->{uptime}" : $file->{uptime};
451 2 50       96 open my $fh, '<', $filename
452             or croak "$class: unable to open $filename ($!)";
453 2         43 ( $self->{uptime}, $self->{idletime} ) = split /\s+/, <$fh>;
454 2         23 close $fh;
455              
456 2 100       10 unless ( $self->get_raw_time() ) {
457 1         25 foreach my $time (qw/uptime idletime/) {
458             my ( $d, $h, $m, $s ) =
459 2         13 $self->_calsec( sprintf( '%li', $self->{$time} ) );
460 2         12 $self->{$time} = "${d}d ${h}h ${m}m ${s}s";
461             }
462             }
463             }
464              
465             sub _calsec {
466 2     2   5 my $self = shift;
467 2         5 my ( $s, $m, $h, $d ) = ( shift, 0, 0, 0 );
468 2 50 33     16 $s >= 86400 and $d = sprintf( '%i', $s / 86400 ) and $s = $s % 86400;
469 2 50 33     12 $s >= 3600 and $h = sprintf( '%i', $s / 3600 ) and $s = $s % 3600;
470 2 50 33     12 $s >= 60 and $m = sprintf( '%i', $s / 60 ) and $s = $s % 60;
471 2         8 return ( $d, $h, $m, $s );
472             }
473              
474             1;