Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Module to parse output from Unix ps command?

by shriken (Priest)
on Apr 10, 2013 at 16:37 UTC ( #1028010=perlquestion: print w/ replies, xml ) Need Help??
shriken has asked for the wisdom of the Perl Monks concerning the following question:

A quick CPAN search didn't turn up anything.

Parsing would involve mostly fixed-width column data; The difficulty arises when the data in some columns exceeds the width and pushes rightward columns over. Other strategies could be to "consume" no-whitespace-words left-to-right after noting the column ordering output.

I simply don't want to start out writing this if it's already been done.

Excerpt of some sample output below. Note the last line shows the TIME column overly wide.

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMA +ND root 6332 1.0 0.0 4096 660 ? S 06:25 0:00 /bin/ +sh ./monitor.sh /var/log/kern.log.1 root 6349 0.0 0.0 14976 1116 ? R 06:25 0:00 /bin/ +ps auxw ntp 10330 0.0 0.0 25808 1532 ? Ss Jul23 0:16 /usr/ +sbin/ntpd -p /var/run/ntpd.pid -g -u 106:115 root 13438 0.0 0.2 10248 4512 ? Ss Jul03 0:00 /usr/ +sbin/knockd -d -i eth0 bind 24285 4.6 2.2 212112 46136 ? Ssl Jul17 1056:29 /usr +/sbin/named -u bind

Comment on Module to parse output from Unix ps command?
Download Code
Re: Module to parse output from Unix ps command?
by educated_foo (Vicar) on Apr 10, 2013 at 16:43 UTC
    There's Proc::ProcessTable, but it gets mixed reviews. I've just rolled my own in the past, keeping in mind that "ps" varies so much from platform to platform that it is probably a throwaway.

    EDIT: Porc -> Proc, duh.

Re: Module to parse output from Unix ps command?
by talexb (Canon) on Apr 10, 2013 at 17:43 UTC

    Maybe I've missed something, but couldn't you just do a split on the output of ps and go from there? That way, you don't care about whether one of the columns pushes one of the later columns out of alignment. You could even track the maxwidth of each column, then dump out the data you've collected in a more efficient, 100% aligned format.

    If I were doing this, I'd keep the first row and use that as a title for all of the other rows

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Module to parse output from Unix ps command?
by blue_cowdawg (Monsignor) on Apr 10, 2013 at 18:22 UTC

    P9Y::ProcessTable promises "will portably access the process table, no matter what the OS, and normalize its outputs to work similar across all platforms" but I have not idea how well it delivers on those promises. Not sure what motivated the author to pick "P9Y" as the top level name space either...


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

      From the documentation:

      P9Y?

      Portability. You know, like I18N and L10N.

            Portability. You know, like I18N and L10N.

        Oh... that's interesting. Totally OT here, but I had an interesting debate with the pumpkins of CPAN when I released RPG::Dice without realizing there was a Games::Dice module. My module does things slightly different than the other so I kept mine. Considering the rest of the family of modules that are undergoing much rewrite and debugging I did not want to have to refactor them as well to use the other module.

        So I guess we all have different views on name space.


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Module to parse output from Unix ps command?
by hdb (Prior) on Apr 10, 2013 at 19:26 UTC
Re: Module to parse output from Unix ps command?
by hdb (Prior) on Apr 10, 2013 at 20:12 UTC

    It was easier said than done...

    use strict; use warnings; use Data::Dumper; my $command = "ps -f"; my $id = "PID"; my @ps =`$command`; $ps[0] =~ s/^\s*//; my @header = split /\s+/, shift @ps; my ($posid) = grep { $header[$_] eq $id } 0..$#header; die "$id: No such column!\n" unless defined( $posid ); splice @header, $posid, 1; my $n = (scalar @header) - 1; my %psdata; while( @ps ) { my $row = shift @ps; $row =~ s/^\s*//; my @row = split /\s+/, $row; my $this_id = splice @row, $posid, 1; @{$psdata{$this_id}}{@header[0..$n-1]} = splice @row, 0, $n; $psdata{$this_id}{$header[$n]} = join " ", @row; # inaccurate as it +just pastes everything together } print Dumper( %psdata );
      Using split's third possible argument too instead of just /\s+/, you'd preserve the original spacing of the user command as well (assuming it's always the last column).


      Krambambuli
      ---

        Thanks for this comment, I never heard about this third argument. Here is the updated script:

        use strict; use warnings; use Data::Dumper; my $command = "ps -f"; my $id = "PID"; my @ps =`$command`; $ps[0] =~ s/^\s*//; my @header = split /\s+/, shift @ps; my ($posid) = grep { $header[$_] eq $id } 0..$#header; die "$id: No such column!\n" unless defined( $posid ); splice @header, $posid, 1; my %psdata; while( @ps ) { my $row = shift @ps; chomp $row; $row =~ s/^\s*//; my @row = split /\s+/, $row, $#header+2; my $this_id = splice @row, $posid, 1; @{$psdata{$this_id}}{@header} = @row; } print Dumper( %psdata );

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1028010]
Approved by igelkott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (12)
As of 2014-12-25 16:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (160 votes), past polls