File Coverage

blib/lib/Proc/ProcessTable/piddler.pm
Criterion Covered Total %
statement 26 300 8.6
branch 0 134 0.0
condition 0 123 0.0
subroutine 9 15 60.0
pod 6 6 100.0
total 41 578 7.0


line stmt bran cond sub pod time code
1             package Proc::ProcessTable::piddler;
2              
3 1     1   58529 use 5.006;
  1         5  
4 1     1   6 use strict;
  1         2  
  1         20  
5 1     1   4 use warnings;
  1         1  
  1         45  
6 1     1   435 use Proc::ProcessTable;
  1         4650  
  1         43  
7 1     1   702 use Text::ANSITable;
  1         92348  
  1         49  
8 1     1   724 use Term::ANSIColor;
  1         7301  
  1         106  
9 1     1   639 use Proc::ProcessTable::InfoString;
  1         789  
  1         36  
10 1     1   446 use Sys::MemInfo qw(totalmem freemem totalswap);
  1         695  
  1         65  
11 1     1   433 use Net::Connection::ncnetstat;
  1         96723  
  1         3618  
12              
13             =head1 NAME
14              
15             Proc::ProcessTable::piddler - Display all process table, open files, and network connections for a PID.
16              
17             =head1 VERSION
18              
19             Version 0.2.0
20              
21             =cut
22              
23             our $VERSION = '0.2.0';
24              
25              
26             =head1 SYNOPSIS
27              
28             use Proc::ProcessTable::piddler;
29              
30             # skip over the less useful stuff by default for less spammy output
31             my $args={
32             txt=>0,
33             unix=>0,
34             pipe=>0,
35             vregroot=>0,
36             dont_dedup=>0,
37             dont_resolv=>0,
38             };
39              
40             my $piddler = Proc::ProcessTable::piddler->new( $args );
41            
42             print $piddler->run( [ 0, 1432 ] );
43              
44             =head1 METHODS
45              
46             =head2 new
47              
48             Initiates the object.
49              
50             One argument is taken and that is a option hash reference
51             of options.
52              
53             my $args={
54             txt=>0,
55             unix=>0,
56             pipe=>0,
57             vregroot=>0,
58             dont_dedup=>0,
59             dont_resolv=>0,
60             };
61            
62             my $piddler = Proc::ProcessTable::piddler->new( $args );
63              
64             =head3 args hash
65              
66             =head4 a_inode
67              
68             Print a_inode types.
69              
70             Defaults to 0, false.
71              
72             =head4 dont_dedup
73              
74             Don't dedup the file descriptor list.
75              
76             When deduping a list it checks if a file is open in
77             rw, r, or w, only showing it once for any of thsoe modes.
78             Any file with more than one open FD of that mode will have
79             + appended value in the FD volume.
80              
81             The modes below are all also RW and considered that.
82              
83             u
84             ur
85             uw
86              
87             Defaults to 0, false.
88              
89             =head4 dont_resolv
90              
91             Don't resolve PTR addresses.
92              
93             Defaults to 0, false.
94              
95             =head4 fifo
96              
97             Print FIFOs.
98              
99             Defaults to 0, false.
100              
101             =head4 memreglib
102              
103             Prints memory mappaed libraries that show are of type REG.
104              
105             The following are used to match libraries.
106              
107             /\.[0-9]+$/
108             /\.[0-9]+\.[0-9$/
109             /\.jar/
110              
111             =head4 pipe
112              
113             Print pipes.
114              
115             Defaults to 0, false.
116              
117             =head4 txt
118              
119             Print the linked libraries used by the binary.
120              
121             Defaults to 0, false.
122              
123             =head4 unix
124              
125             Print unix sockets.
126              
127             Defaults to 0, false.
128              
129             =head4 vregroot
130              
131             Show VREG entries for /.
132              
133             Defaults to 0, false.
134              
135             =cut
136              
137             sub new{
138 0     0 1   my %args;
139 0 0         if (defined($_[1])) {
140 0           %args= %{$_[1]};
  0            
141             }
142              
143 0           my $self = {
144             colors=>[
145             'BRIGHT_YELLOW',
146             'BRIGHT_CYAN',
147             'BRIGHT_MAGENTA',
148             'BRIGHT_BLUE'
149             ],
150             nextColor=>0,
151             timeColors=>[
152             'GREEN',
153             'BRIGHT_GREEN',
154             'RED',
155             'BRIGHT_RED'
156             ],
157             vszColors=>[
158             'GREEN',
159             'YELLOW',
160             'RED',
161             'BRIGHT_BLUE'
162             ],
163             rssColors=>[
164             'BRIGHT_GREEN',
165             'BRIGHT_YELLOW',
166             'BRIGHT_RED',
167             'BRIGHT_BLUE'
168             ],
169             file_colors=>[
170             'BRIGHT_YELLOW',
171             'BRIGHT_CYAN',
172             'BRIGHT_MAGENTA',
173             'BRIGHT_BLUE',
174             'MAGENTA',
175             'BRIGHT_RED'
176             ],
177             processColor=>'BRIGHT_RED',
178             varColor=>'GREEN',
179             valColor=>'WHITE',
180             pidColor=>'BRIGHT_CYAN',
181             cpuColor=>'BRIGHT_MAGENTA',
182             memColor=>'BRIGHT_BLUE',
183             zero_time=>1,
184             zero_flt=>1,
185             files=>1,
186             idColors=>[
187             'WHITE',
188             'BRIGHT_BLUE',
189             'MAGENTA',
190             ],
191             is=>Proc::ProcessTable::InfoString->new,
192             colors=>[
193             'BRIGHT_YELLOW',
194             'BRIGHT_CYAN',
195             'BRIGHT_MAGENTA',
196             'BRIGHT_BLUE'
197             ],
198             environ=>'BRIGHT_MAGENTA',
199             txt=>0,
200             pipe=>0,
201             unix=>0,
202             vregroot=>0,
203             dont_dedup=>0,
204             dont_resolv=>0,
205             fifo=>0,
206             a_inode=>0,
207             memreglib=>0,
208             };
209 0           bless $self;
210              
211 0           my @arg_feed=(
212             'txt', 'pipe', 'unix', 'vregroot', 'dont_dedup', 'dont_resolv',
213             'fifo', 'a_inore', 'memreglib'
214             );
215              
216 0           foreach my $feed ( @arg_feed ){
217 0           $self->{$feed}=$args{$feed};
218             }
219              
220 0           return $self;
221             }
222              
223             =head2 run
224              
225             This runs it and returns a string.
226              
227             One option is taken and that is a array ref of PIDs
228             to do.
229              
230             print $piddler->run( [ 0, 1432 ] );
231              
232             =cut
233              
234             sub run{
235 0     0 1   my $self=$_[0];
236 0           my @pids;
237 0 0         if (defined($_[1])) {
238 0           @pids= @{$_[1]};
  0            
239             }
240              
241 0 0         if ( ! defined( $pids[0] ) ){
242 0           return '';
243             }
244              
245 0           my %pids_hash;
246 0           foreach my $pid ( @pids ){
247 0           $pids_hash{$pid}=$pid;
248             }
249              
250 0           my $p = Proc::ProcessTable->new;
251 0           my $pt = $p->table;
252              
253             # figure out what all keys the process table is reporting
254 0           my @proc_keys=keys( %{ $pt->[0] } );
  0            
255 0           my %proc_keys_hash;
256 0           foreach my $proc_key ( @proc_keys ){
257 0           $proc_keys_hash{$proc_key}=1;
258             }
259             # remove the ones we actually use
260 0           delete( $proc_keys_hash{pctcpu} );
261 0           delete( $proc_keys_hash{uid} );
262 0           delete( $proc_keys_hash{pid} );
263 0           delete( $proc_keys_hash{gid} );
264 0           delete( $proc_keys_hash{vmsize} );
265 0           delete( $proc_keys_hash{rss} );
266 0           delete( $proc_keys_hash{state} );
267 0           delete( $proc_keys_hash{wchan} );
268 0           delete( $proc_keys_hash{cmndline} );
269 0           delete( $proc_keys_hash{size} );
270 0           delete( $proc_keys_hash{time} );
271 0 0         if( defined( $proc_keys_hash{pctmem} ) ){
272 0           delete( $proc_keys_hash{pctmem} );
273             }
274 0 0         if( defined( $proc_keys_hash{groups} ) ){
275 0           delete( $proc_keys_hash{groups} );
276             }
277 0 0         if ( defined( $proc_keys_hash{cmdline} ) ){
278 0           delete( $proc_keys_hash{cmdline} );
279             }
280 0           @proc_keys=sort(keys( %proc_keys_hash ));
281              
282 0           my @procs;
283 0           foreach my $proc ( @{ $pt } ){
  0            
284 0 0         if ( defined( $pids_hash{ $proc->pid } ) ){
285 0           push( @procs, $proc );
286             }
287             }
288              
289 0 0         if (!defined( $procs[0] )){
290 0           return ''
291             }
292              
293 0           my $toReturn='';
294 0           my $first=1;
295 0           foreach my $proc ( @procs ){
296 0           my $tb = Text::ANSITable->new;
297 0           $tb->border_style('Default::none_ascii');
298 0           $tb->color_theme('Default::no_color');
299 0           $tb->show_header(0);
300 0           $tb->set_column_style(0, pad => 0);
301 0           $tb->set_column_style(1, pad => 1);
302 0           $tb->columns( ['var','val'] );
303              
304             #
305             # PID
306             #
307 0           my @data;
308             push( @data, [
309             color( $self->{varColor} ).'PID'.color('reset'),
310 0           color( $self->{pidColor} ).$proc->pid.color('reset')
311             ]);
312              
313             #
314             # UID
315             #
316 0           my $user=getpwuid($proc->{uid});
317 0 0         if ( ! defined( $user ) ) {
318 0           $user=color( $self->{idColors}[0] ).$proc->{uid}.color('reset');
319             }else{
320             $user=color( $self->{idColors}[0] ).$user.
321             color( $self->{idColors}[1] ).'('.
322             color( $self->{idColors}[2] ).$proc->{uid}.
323 0           color( $self->{idColors}[1] ).')'
324             .color('reset');
325             }
326              
327             push( @data, [
328 0           color( $self->{varColor} ).'UID'.color('reset'),
329             $user.' '.color('reset')
330             ]);
331              
332             #
333             # GID
334             #
335 0           my $group=getgrgid($proc->{gid});
336 0 0         if ( ! defined( $group ) ) {
337 0           $group=color( $self->{idColors}[0] ).$proc->{gid}.color('reset');
338             }else{
339             $group=color( $self->{idColors}[0] ).$group.
340             color( $self->{idColors}[1] ).'('.
341             color( $self->{idColors}[2] ).$proc->{gid}.
342 0           color( $self->{idColors}[1] ).')'
343             .color('reset');
344             }
345              
346             push( @data, [
347 0           color( $self->{varColor} ).'GID'.color('reset'),
348             $group.' '.color('reset')
349             ]);
350              
351             #
352             # Groups
353             #
354 0 0         if ( defined( $proc->{groups} ) ){
355 0           my @groups;
356 0           foreach my $current_group ( @{ $proc->{groups} } ){
  0            
357 0           $group=getgrgid( $current_group );
358 0 0         if ( ! defined( $group ) ) {
359 0           $group=color( $self->{idColors}[0] ).$current_group.color('reset');
360             }else{
361             $group=color( $self->{idColors}[0] ).$group.
362             color( $self->{idColors}[1] ).'('.
363             color( $self->{idColors}[2] ).$current_group.
364 0           color( $self->{idColors}[1] ).')'
365             .color('reset');
366             }
367 0           push( @groups, $group );
368             }
369              
370             push( @data, [
371 0           color( $self->{varColor} ).'Groups'.color('reset'),
372             join( ' ', @groups )
373             ]);
374             }
375              
376             #
377             # PCT CPU
378             #
379             push( @data, [
380             color( $self->{varColor} ).'CPU%'.color('reset'),
381 0           color( $self->{valColor} ).$proc->pctcpu.color('reset')
382             ]);
383              
384             #
385             # PCT mem
386             #
387 0           my $mem;
388 0 0         if ( !defined( $proc->{pctmem} ) ) {
389 0           $mem=($proc->{rss} / totalmem)*100;
390 0           $mem=sprintf('%.2f', $mem);
391             } else {
392 0           $mem=sprintf('%.2f', $proc->{pctmem});
393             }
394             push( @data, [
395             color( $self->{varColor} ).'MEM%'.color('reset'),
396 0           color( $self->{valColor} ).$mem.color('reset')
397             ]);
398              
399             #
400             # VSZ
401             #
402             push( @data, [
403 0           color( $self->{varColor} ).'VSZ'.color('reset'),
404             $self->memString( $proc->size, 'vsz' )
405             ]);
406              
407             #
408             # RSS
409             #
410             push( @data, [
411 0           color( $self->{varColor} ).'RSS'.color('reset'),
412             $self->memString( $proc->rss, 'rss' )
413             ]);
414              
415             #
416             # time
417             #
418             push( @data, [
419 0           color( $self->{varColor} ).'Time'.color('reset'),
420             $self->timeString( $proc->time )
421             ]);
422              
423             #
424             # info
425             #
426             push( @data, [
427             color( $self->{varColor} ).'Info'.color('reset'),
428 0           color( $self->{valColor} ).$self->{is}->info( $proc ).color('reset')
429             ]);
430              
431             #
432             # misc ones...
433             #
434 0           foreach my $key ( @proc_keys ){
435 0 0         if ( $proc->{$key} !~ /^$/ ){
436 0           my $print_it=1;
437 0           my $value;
438              
439 0 0 0       if (
    0 0        
440             ( $key =~ /time$/ ) &&
441             ( $proc->{$key} =~ /\.0*$/ ) &&
442             ( $self->{zero_time} )
443             ){
444 0           $print_it=0;
445             }elsif( $key =~ /time$/ ){
446 0           $value=$self->timeString( $proc->{$key} );
447             }
448              
449 0 0         if ( $key =~ /^environ$/ ){
450 0           $value=join( color( $self->{environ} ).', '.color('reset') , @{ $proc->{environ} } );
  0            
451 0 0         if ( !defined( $value ) ){
452 0           $value='';
453             }
454             }
455              
456 0 0 0       if (
      0        
457             ( $key =~ /flt$/ ) &&
458             ( $proc->{$key} eq 0 ) &&
459             ( $self->{zero_flt} )
460             ){
461 0           $print_it=0;
462             }
463              
464 0 0         if ( $key =~ /^start$/ ){
465 0           $value=$self->startString( $proc->{start} );
466             }
467              
468 0 0         if ( !defined( $value ) ){
469 0           $value=color( $self->{valColor} ).$proc->{$key}.color('reset');
470             }
471              
472 0 0         if ( $print_it ){
473             push( @data, [
474 0           color( $self->{varColor} ).$key.color('reset'),
475             $value,
476             ]);
477             }
478             }
479             }
480              
481             #
482             # cmndline
483             #
484 0 0         if ( $proc->{cmndline} !~ /^$/ ){
485             push( @data, [
486             color( $self->{varColor} ).'Cmndline'.color('reset'),
487 0           color( $self->{processColor} ).$proc->{cmndline}.color('reset')
488             ]);
489             }
490              
491             #
492             # gets the open files
493             #
494 0           my $open_files='';
495 0           my $pid=$proc->pid;
496 0           my $output_raw=`lsof -n -l -P -p $pid`;
497 0 0 0       if (
      0        
498             ( $? eq 0 ) ||
499             (
500             ( $^O =~ /linux/ ) &&
501             ( $? eq 256 )
502             )
503             ){
504              
505 0           my $ftb = Text::ANSITable->new;
506 0           $ftb->border_style('Default::none_ascii');
507 0           $ftb->color_theme('Default::no_color');
508 0           $ftb->show_header(1);
509 0           $ftb->set_column_style(0, pad => 0);
510 0           $ftb->set_column_style(1, pad => 1);
511 0           $ftb->set_column_style(2, pad => 0);
512 0           $ftb->set_column_style(3, pad => 1);
513 0           $ftb->set_column_style(4, pad => 0);
514             $ftb->columns([
515             color( $self->{varColor} ).'FD'.color('reset'),
516             color( $self->{varColor} ).'TYPE'.color('reset'),
517             color( $self->{varColor} ).'DEVICE'.color('reset'),
518             color( $self->{varColor} ).'SIZE/OFF'.color('reset'),
519             color( $self->{varColor} ).'NODE'.color('reset'),
520 0           color( $self->{varColor} ).'NAME'.color('reset')
521             ]);
522              
523 0           my @fdata;
524              
525             #
526             my %rw_filehandles;
527 0           my %r_filehandles;
528 0           my %w_filehandles;
529 0           my %mem_filehandles;
530 0           my @lines=split(/\n/, $output_raw);
531 0           my $line_int=1;
532 0           while ( defined( $lines[$line_int] ) ){
533 0           my $line=substr $lines[$line_int], 10;
534 0           my @line_split=split(/[\ \t]+/, $line );
535              
536 0 0         if ( !defined( $line_split[7] )){
537 0           $line_split[7]='';
538             }
539              
540             # checks if it is a line we don't want
541 0           my $dont_add=0;
542 0 0 0       if (
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
543             # IP stuff... handled by ncnetstat
544             ( $line_split[3] =~ /^IPv/ ) ||
545             # library... spammy... only print if asked
546             (
547             ( $line_split[2] =~ /^txt$/ ) &&
548             ( ! $self->{txt} )
549             ) ||
550             # pipe... spammy... only print if asked
551             (
552             ( $line_split[3] =~ /^[Pp][Ii][Pp][Ee]$/ ) &&
553             ( ! $self->{pipe} )
554             ) ||
555             # unix... spammy... only print if asked
556             (
557             ( $line_split[3] =~ /^[Uu][Nn][Ii][Xx]$/ ) &&
558             ( ! $self->{unix} )
559             ) ||
560             # fifo... spammy with elasticsearch and the like... only print if asked...
561             (
562             ( $line_split[3] =~ /^[Ff][Ii][Ff][Oo]$/ ) &&
563             ( ! $self->{fifo} )
564             ) ||
565             # memory mapped libraries with REG type....
566             # spammy.... ES tends to have lots of these
567             (
568             ( $line_split[3] =~ /^[Rr][Ee][Gg]$/ ) &&
569             (
570             ( $line_split[7] =~ /\.so$/ ) ||
571             ( $line_split[7] =~ /\.so\.[0-9]$/ ) ||
572             ( $line_split[7] =~ /\.so\.[0-9]+\.[0-9]+$/ ) ||
573             ( $line_split[7] =~ /\.so\.[0-9]+\.[0-9]+\.[0-9]+$/ ) ||
574             ( $line_split[7] =~ /\.jar$/ )
575             ) &&
576             ( ! $self->{memreglib} )
577             ) ||
578             # a_inode... spammy with elasticsearch and the like... only print if asked...
579             (
580             ( $line_split[3] =~ /^a\_inode$/ ) &&
581             ( ! $self->{a_inode} )
582             ) ||
583             # vreg /....can by spammy with somethings like firefox
584             (
585             ( $line_split[3] =~ /^[Vv][Rr][Ee][Gg]$/ ) &&
586             ( $line_split[7] =~ /^\/$/ ) &&
587             ( ! $self->{vregroot} )
588             )
589             ){
590 0           $dont_add=1;
591             }
592              
593             # begin deduping
594 0           my $name= color( $self->{file_colors}[5] ).$line_split[7].color( 'reset' );
595 0 0 0       if (
596             ( ! $self->{dont_dedup} ) &&
597             ( ! $dont_add )
598             ){
599 0 0 0       if (
      0        
      0        
600             ( $line_split[3] =~ /[Vv][Rr][Ee][Gg]/ ) ||
601             ( $line_split[3] =~ /[Rr][Ee][Gg]/ ) ||
602             ( $line_split[3] =~ /[Vv][Dd][Ii][Dd]/ ) ||
603             ( $line_split[3] =~ /[Vv][Cc][Hh][Rr]/ )
604             ) {
605 0 0 0       if (
    0 0        
    0 0        
    0 0        
606             ( $line_split[2] =~ /u/ ) ||
607             ( $line_split[2] =~ /rw/ ) ||
608             ( $line_split[2] =~ /wr/ )
609             ) {
610 0 0         if (! defined( $rw_filehandles{ $name } ) ) {
611 0           $rw_filehandles{ $name } = 1;
612             } else {
613 0           $rw_filehandles{ $name }++;
614             }
615             } elsif (
616             ( $line_split[2] !~ /u/ ) ||
617             ( $line_split[2] =~ /r/ )
618             ) {
619 0 0         if (! defined( $r_filehandles{ $name } ) ) {
620 0           $r_filehandles{ $name } = 1;
621             } else {
622 0           $r_filehandles{ $name }++;
623             }
624             } elsif (
625             ( $line_split[2] !~ /u/ ) ||
626             ( $line_split[2] =~ /w/ )
627             ) {
628 0 0         if (! defined( $w_filehandles{ $name } ) ) {
629 0           $w_filehandles{ $name } = 1;
630             } else {
631 0           $w_filehandles{ $name }++;
632             }
633             }elsif (
634             ( $line_split[2] =~ /mem/ )
635             ){
636 0 0         if (! defined( $mem_filehandles{ $name } ) ) {
637 0           $mem_filehandles{ $name } = 1;
638             } else {
639 0           $mem_filehandles{ $name }++;
640             }
641             }
642             }
643             }
644              
645 0 0         if ( ! $dont_add ) {
646             push( @fdata, [
647             color( $self->{file_colors}[0] ).$line_split[2].color( 'reset' ),
648             color( $self->{file_colors}[1] ).$line_split[3].color( 'reset' ),
649             color( $self->{file_colors}[2] ).$line_split[4].color( 'reset' ),
650             color( $self->{file_colors}[3] ).$line_split[5].color( 'reset' ),
651 0           color( $self->{file_colors}[4] ).$line_split[6].color( 'reset' ),
652             $name,
653             ]);
654             }
655              
656 0           $line_int++;
657             }
658              
659             # finalize deduping
660 0           my @final_fdata;
661 0 0         if ( ! $self->{dont_dedup} ){
662 0           my %rw_dedup;
663             my %r_dedup;
664 0           my %w_dedup;
665 0           my %mem_dedup;
666 0           foreach my $line ( @fdata ){
667 0 0 0       if (
      0        
      0        
668             ( $line->[1] =~ /[Vv][Rr][Ee][Gg]/ ) ||
669             ( $line->[1] =~ /[Rr][Ee][Gg]/ ) ||
670             ( $line->[1] =~ /[Vv][Dd][Ii][Dd]/ ) ||
671             ( $line->[1] =~ /[Vv][Cc][Hh][Rr]/ )
672             ){
673 0           my $add_line=1;
674 0 0 0       if (
    0 0        
    0 0        
    0 0        
675             ( $line->[0] =~ /u/ ) ||
676             ( $line->[0] =~ /rw/ ) ||
677             ( $line->[0] =~ /wr/ )
678             ) {
679 0 0         if( defined( $rw_dedup{ $line->[5] } ) ){
680 0           $add_line=0;
681             }else{
682 0 0         if ($rw_filehandles{ $line->[5] } > 1){
683 0           $line->[0]=$line->[0].'+';
684             }
685 0           $rw_dedup{ $line->[5] } = 1;
686             }
687             } elsif (
688             ( $line->[0] !~ /u/ ) ||
689             ( $line->[0] =~ /r/ )
690             ) {
691 0 0         if( defined( $r_dedup{ $line->[5] } ) ){
692 0           $add_line=0;
693             }else{
694 0 0         if ($r_filehandles{ $line->[5] } > 1){
695 0           $line->[0]=$line->[0].'+';
696             }
697 0           $r_dedup{ $line->[5] } = 1;
698             }
699             } elsif (
700             ( $line->[0] !~ /u/ ) ||
701             ( $line->[0] =~ /w/ )
702             ) {
703 0 0         if( defined( $w_dedup{ $line->[5] } ) ){
704 0           $add_line=0;
705             }else{
706 0 0         if ($w_filehandles{ $line->[5] } > 1){
707 0           $line->[0]=$line->[0].'+';
708             }
709 0           $w_dedup{ $line->[5] } = 1;
710             }
711             }elsif(
712             ( $line->[0] =~ /mem/ )
713             ){
714 0 0         if ($mem_filehandles{ $line->[5] } > 1){
715 0           $line->[0]=$line->[0].'+';
716             }
717 0           $mem_dedup{ $line->[5] } = 1;
718             }
719              
720 0 0         if ( $add_line ){
721 0           push( @final_fdata, [
722             $line->[0],
723             $line->[1],
724             $line->[2],
725             $line->[3],
726             $line->[4],
727             $line->[5],
728             ]);
729             }
730             }else{
731 0           push( @final_fdata, \@{ $line } );
  0            
732             }
733             }
734 0           $ftb->add_rows( \@final_fdata );
735             }else{
736 0           $ftb->add_rows( \@fdata );
737             }
738              
739              
740 0           $open_files=$ftb->draw;
741             }
742              
743             #
744             # handle the netconnection
745             #
746 0           my $netstat='';
747 0           my @filters=(
748             {
749             type=>'PID',
750             invert=>0,
751             args=>{
752             pids=>[$proc->pid],
753             }
754             }
755             );
756 0           my $ptr=1;
757 0 0         if ( $self->{dont_resolv} ){
758 0           $ptr=0;
759             }
760 0           my $ncnetstat=Net::Connection::ncnetstat->new(
761             {
762             ptr=>$ptr,
763             command=>0,
764             command_long=>0,
765             wchan=>0,
766             pct_show=>0,
767             no_pid_user=>1,
768             match=>{
769             checks=>\@filters,
770             }
771             }
772             );
773 0           $netstat=$ncnetstat->run;
774              
775              
776             #
777             # adds the new item
778             #
779 0           $tb->add_rows( \@data );
780 0 0         if ( $first ){
781 0           $first=0;
782 0           $toReturn=$toReturn.$tb->draw.$open_files.$netstat;
783             }else{
784 0           $toReturn=$toReturn.$open_files."\n\n".$tb->draw;
785             }
786             }
787              
788 0           return $toReturn;
789             }
790              
791             =head2 timeString
792              
793             Turns the raw run string into something usable.
794              
795             =cut
796              
797             sub timeString{
798 0     0 1   my $self=$_[0];
799 0           my $time=$_[1];
800              
801 0 0         if ( $^O =~ /^linux$/ ) {
802 0           $time=$time/1000000;
803             }
804              
805 0           my $hours=0;
806 0 0         if ( $time >= 3600 ) {
807 0           $hours = $time / 3600;
808             }
809 0           my $loSeconds = $time % 3600;
810 0           my $minutes=0;
811 0 0         if ( $time >= 60 ) {
812 0           $minutes = $loSeconds / 60;
813             }
814 0           my $seconds = $loSeconds % 60;
815              
816             #nicely format it
817 0           $hours=~s/\..*//;
818 0           $minutes=~s/\..*//;
819             #$seconds=sprintf('%.f',$seconds);
820              
821             #this will be returned
822 0           my $toReturn='';
823              
824             #process the hours bit
825 0 0         if ( $hours == 0 ) {
    0          
826             #don't do anything if time is 0
827             } elsif (
828             $hours >= 10
829             ) {
830 0           $toReturn=color($self->{timeColors}->[3]).$hours.':';
831             } else {
832 0           $toReturn=color($self->{timeColors}->[2]).$hours.':';
833             }
834              
835             #process the minutes bit
836 0 0 0       if (
837             ( $hours > 0 ) ||
838             ( $minutes > 0 )
839             ) {
840 0           $toReturn=$toReturn.color( $self->{timeColors}->[1] ). $minutes.':';
841             }
842              
843 0           $toReturn=$toReturn.color( $self->{timeColors}->[0] ).$seconds.color('reset');
844              
845 0           return $toReturn;
846             }
847              
848             =head2 memString
849              
850             Turns the raw run string into something usable.
851              
852             =cut
853              
854             sub memString{
855 0     0 1   my $self=$_[0];
856 0           my $mem=$_[1];
857 0           my $type=$_[2];
858              
859 0           my $toReturn='';
860              
861 0 0 0       if ( $mem < '10000' ) {
    0 0        
    0          
    0          
862 0           $toReturn=color( $self->{$type.'Colors'}[0] ).$mem;
863             } elsif (
864             ( $mem >= '10000' ) &&
865             ( $mem < '1000000' )
866             ) {
867 0           $mem=$mem/1000;
868              
869             $toReturn=color( $self->{$type.'Colors'}[0] ).$mem.
870 0           color( $self->{$type.'Colors'}[3] ).'k';
871             } elsif (
872             ( $mem >= '1000000' ) &&
873             ( $mem < '1000000000' )
874             ) {
875 0           $mem=($mem/1000)/1000;
876 0           $mem=sprintf('%.3f', $mem);
877 0           my @mem_split=split(/\./, $mem);
878              
879             $toReturn=color( $self->{$type.'Colors'}[1] ).$mem_split[0].'.'.color( $self->{$type.'Colors'}[0] ).$mem_split[1].
880 0           color( $self->{$type.'Colors'}[3] ).'M';
881             } elsif ( $mem >= '1000000000' ) {
882 0           $mem=(($mem/1000)/1000)/1000;
883 0           $mem=sprintf('%.3f', $mem);
884 0           my @mem_split=split(/\./, $mem);
885              
886             $toReturn=color( $self->{$type.'Colors'}[2] ).$mem_split[0].'.'.color( $self->{$type.'Colors'}[1] ).$mem_split[1].
887 0           color( $self->{$type.'Colors'}[3] ).'G';
888             }
889              
890 0           return $toReturn.color('reset');
891             }
892              
893             =head2 startString
894              
895             Generates a short time string based on the supplied unix time.
896              
897             =cut
898              
899             sub startString{
900 0     0 1   my $self=$_[0];
901 0           my $startTime=$_[1];
902              
903 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($startTime);
904 0           my ($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) = localtime(time);
905              
906             #add the required stuff to make this sane
907 0           $year += 1900;
908 0           $cyear += 1900;
909 0           $mon += 1;
910 0           $cmon += 1;
911              
912             #find the most common one and return it
913 0 0         if ( $year ne $cyear ) {
914 0           return $year.sprintf('%02d', $mon).sprintf('%02d', $mday).'-'.sprintf('%02d', $hour).':'.sprintf('%02d', $min);
915             }
916 0 0         if ( $mon ne $cmon ) {
917 0           return sprintf('%02d', $mon).sprintf('%02d', $mday).'-'.sprintf('%02d', $hour).':'.sprintf('%02d', $min);
918             }
919 0 0         if ( $mday ne $cmday ) {
920 0           return sprintf('%02d', $mday).'-'.sprintf('%02d', $hour).':'.sprintf('%02d', $min);
921             }
922              
923             #just return this for anything less
924 0           return sprintf('%02d', $hour).':'.sprintf('%02d', $min);
925             }
926              
927             =head2 nextColor
928              
929             Returns the next color.
930              
931             =cut
932              
933             sub nextColor{
934 0     0 1   my $self=$_[0];
935              
936 0           my $color;
937              
938 0 0         if ( defined( $self->{colors}[ $self->{nextColor} ] ) ) {
939 0           $color=$self->{colors}[ $self->{nextColor} ];
940 0           $self->{nextColor}++;
941             } else {
942 0           $self->{nextColor}=0;
943 0           $color=$self->{colors}[ $self->{nextColor} ];
944 0           $self->{nextColor}++;
945             }
946              
947 0           return $color;
948             }
949              
950             =head1 AUTHOR
951              
952             Zane C. Bowers-Hadley, C<< >>
953              
954             =head1 BUGS
955              
956             Please report any bugs or feature requests to C, or through
957             the web interface at L. I will be notified, and then you'll
958             automatically be notified of progress on your bug as I make changes.
959              
960              
961              
962              
963             =head1 SUPPORT
964              
965             You can find documentation for this module with the perldoc command.
966              
967             perldoc Proc::ProcessTable::piddler
968              
969              
970             You can also look for information at:
971              
972             =over 4
973              
974             =item * RT: CPAN's request tracker (report bugs here)
975              
976             L
977              
978             =item * AnnoCPAN: Annotated CPAN documentation
979              
980             L
981              
982             =item * CPAN Ratings
983              
984             L
985              
986             =item * Search CPAN
987              
988             L
989              
990             =item * Repository
991              
992             L
993              
994             =back
995              
996              
997             =head1 ACKNOWLEDGEMENTS
998              
999              
1000             =head1 LICENSE AND COPYRIGHT
1001              
1002             This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
1003              
1004             This is free software, licensed under:
1005              
1006             The Artistic License 2.0 (GPL Compatible)
1007              
1008              
1009             =cut
1010              
1011             1; # End of Proc::ProcessTable::piddler