Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I just wrote something with awk which fetches my unix ps -ef output where I eliminate the awk and /bin/ksh part of the script that is fetching my ps -ef output:
jones 11111 33334 09:37:46 awk jones 11113 44454 09:37:46 grep jones 11123 33334 09:37:46 /bin/ksh jones 11118 22234 06:18:58 -ksh
to this
jones 11135 44322 09:39:38 grep jones 11118 22234 06:18:58 -ksh
Here is how I did it with Unix:
ps -ef | grep Jones | awk '$8 !~ /awk/ && $8 !~ /\/bin\/ksh/ \ {print $1" "$2" "$3" "$5" "$8}'
Now my attempt to do it with perl shows this in my output file:
jones 11111 55555 0 09:42:09 pts/1 0:00 /usr/local/bin/perl ps1 jones 22222 66666 0 09:42:09 pts/1 0:00 grep jones jones 33333 77777 0 09:42:09 pts/1 0:00 sh -c ps -ef | grep jones +> out r jones 44444 88888 0 06:18:58 pts/1 0:01 -ksh
I want this output (the same as I got in my unix script):
jones 22222 66666 0 09:42:09 pts/1 0:00 grep jones jones 44444 88888 0 06:18:58 pts/1 0:01 -ksh
Here is my attempt at it in Perl. Please advise how I can improve this so it works???
#!/usr/local/bin/perl system("ps -ef | grep Jones > outr"); $outr = 'outr'; open(OF, "$outr") || die "Can not open $outr: $!\n"; @data=(<OF>); close(OF); open(OF,">$outr") || die "File not opening $outr: $!\n"; foreach $_ (@data) { next if ($_ !~ m/\/usr/local/bin/perl ps1$/) && ($_ !~ /sh \-c ps \-ef + \| grep jones \> out) ; print OF $_; } close(OF);

Replies are listed 'Best First'.
Re: Trying to grab process output.
by rob_au (Abbot) on Jul 16, 2002 at 14:10 UTC
    I would recommend that you have a look at Proc::ProcessTable - It provides a very easy and neat interface to the /proc filesystem for the delivery of this information (as opposed to parsing the output of ps). There is a review of this module on this site with examples of usage from myself here and here.

     

Re: Trying to grab process output.
by Abigail-II (Bishop) on Jul 16, 2002 at 14:10 UTC
    open my $fh, "ps -ef | grep Jones |" or die; while (<$fh>) { my @F = split; next if $F [7] =~ /perl/ || $F [7] =~ /ps -ef/ || $F [7] =~ m{/bin/ksh}; print "@F[0,1,3,4,7]\n"; }

    Abigail

      Thanks to all.
Re: Trying to grab process output.
by cybear (Monk) on Jul 16, 2002 at 14:11 UTC
    Some suggestions:
    Don't use "system" use back-ticks ``. Like this: my $outr = `ps -ef|grep Jones|grep -v awk|grep -v ksh`;
    That will assign the output of your ps to $outr.

    Or:

    my $outr = `ps -ef|grep Jones`; @outr = split(/\n/, $outr); foreach (@outr) { unless (($_ eq /bin/ksh) or ($_ eq awk)) { print "$_\n"; } }

    I think that one of these will do what you want. And if
    you don't want to use ps -ef there are some modules that
    will return this kind of system process info also.
Re: Trying to grab process output.
by thelenm (Vicar) on Jul 16, 2002 at 14:26 UTC
    The code you provided seems to have a few syntax errors (e.g., /usr/local/bin/perl needs the slashes to be escaped, and the regex beginning with sh is never terminated), but I've tried to clean it up as well as I could. This program is not equivalent to your Unix grep/awk pipeline, but I've tried to keep the meaning of your Perl code approximately the same.
    #!/usr/local/bin/perl use strict; use warnings; open(OF,">outr") || die "File not opening outr: $!\n"; foreach (`ps -ef | grep jones` =~ /[^\n]*\n/g) { next if m!/usr/local/bin/perl ps1$! or /sh -c ps -ef \| grep jones > + outr$/; print OF; } close(OF);
    Hopefully this does about what you want. A couple of points about it:
    • Backticks are used to capture the output of ps rather than a system with output piped to a file.
    • "Jones" is changed to "jones" in the grep, since I think that's what you want.
    • The elements of the array in a foreach are automatically aliased to $_, so there's no need to do it manually.
    • Similarly, $_ is used by default by regexes and print, so there's no need to specify it there, either.

    -- Mike

    --
    just,my${.02}