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

I'm trying to write a script that will take the output from running 'ps aux|grep httpd' and 'ps aux|grep named' and store them in an array. Then parse the lines in the arrays and make sure that apache and named are running. Any ideas? I'm stuck on how to read the lines and make sure the processes are running, and differentiating between a running process and my grep process.
  • Comment on Searching strings within an array for a particular word.

Replies are listed 'Best First'.
Re: Searching strings within an array for a particular word.
by stephen (Priest) on Mar 06, 2002 at 01:56 UTC
    Instead of using ps and grep, why not use Proc::ProcessTable? If you're on one of its supported systems (and quite a few are supported), you can use it to parse the process table instead of the ps command. Then you could do (untested and probably wrong, since I have no access to this module):
    use strict; use Proc::ProcessTable; sub is_running { my ($pattern) = @_; my $t = Proc::ProcessTable->new(); foreach $proc ( @{ $t->table() } ) { $proc->cmndline() =~ /^$pattern/ and return 1; } return 0; }
    You might also want to take a look at Watchdog.

    stephen

Re: Searching strings within an array for a particular word.
by zengargoyle (Deacon) on Mar 06, 2002 at 01:33 UTC

    Check this out.

    # ps -aux | grep tail root 19775 0.1 0.2 968 656 pts/3 S 17:07:27 0:00 grep tail root 3030 0.0 0.2 1008 696 pts/4 S 10:23:21 0:00 tail -f /va +r/adm/dd # ps -aux | grep 't\ail' root 3030 0.0 0.2 1008 696 pts/4 S 10:23:21 0:00 tail -f /va +r/adm/dd

    Update: I like petral's way.

    First time I saw this I thought it was a typo. ;) Pick a character that doesn't have special meaning to grep when '\' is used before it.

    or # ps -aux | grep '(httpd|named)' | grep -v grep or #!/usr/bin/perl @ps = qx(ps aux); @httpd = grep {/httpd/} @ps; @named = grep {/named/} @ps; print "httpd's:\n\t", join("\n\t", @httpd), "\nnamed's:\n\t", join("\n\t", @named), "\n";
Re: Searching strings within an array for a particular word.
by petral (Curate) on Mar 06, 2002 at 01:13 UTC
    Well, the grep part is usually done with eg, grep name[d] so that it doesn't match itself.

      p
Re: Searching strings within an array for a particular word.
by ajwans (Scribe) on Mar 06, 2002 at 01:22 UTC
    What I usually do is
    ps -aux|grep httpd|grep -v grep
    which will remove any lines with "grep" in them.
Re: Searching strings within an array for a particular word.
by Zaxo (Archbishop) on Mar 06, 2002 at 01:36 UTC
    $ ps -C httpd,named
      PID TTY          TIME CMD
      367 ?        00:00:08 httpd
     2134 ?        00:00:00 named
     2136 ?        00:00:01 named
     2137 ?        00:18:02 named
     2138 ?        00:00:02 named
     2139 ?        00:02:07 named
     9767 ?        00:00:00 httpd
     9768 ?        00:00:00 httpd
     9769 ?        00:00:00 httpd
     9770 ?        00:00:00 httpd
     9771 ?        00:00:00 httpd
     9772 ?        00:00:00 httpd
     9773 ?        00:00:00 httpd
     9774 ?        00:00:00 httpd
     9775 ?        00:00:00 httpd
     9776 ?        00:00:00 httpd
    $ 

    There are also ps switches to select output fields and not print a heading.

    After Compline,
    Zaxo

Re: Searching strings within an array for a particular word.
by beppu (Hermit) on Mar 06, 2002 at 01:41 UTC
    How's this?
    #!/usr/bin/perl -w use strict; sub is_running { my $process = shift; # name of process my @p = grep { !/grep/ } `ps aux | grep $process`; # ps aux without the greps print @p; # comment this out return scalar @p; # false if @p is empty; true otherwise } # test program foreach (qw(httpd sshd syslogd telnetd ftpd yourmama)) { printf("$_ %s running.\n", (is_running($_) ? "is" : "is not")); }

    w/ the experimental syntax-highlighted remix

    #!/usr/bin/perl -w
    
    use strict;
    
    sub is_running {
        my $process = shift;    # name of process
        my @p = grep { !/grep/ } `ps aux | grep $process`;
                                # ps aux without the greps
        print @p;               # comment this out
        return scalar @p;       # false if @p is empty; true otherwise
    }
    
    # test program
    foreach (qw(httpd sshd syslogd telnetd ftpd yourmama)) {
        printf("$_ %s running.\n", (is_running($_) ? "is" : "is not"));
    }
    
    
Re: Searching strings within an array for a particular word.
by Juerd (Abbot) on Mar 06, 2002 at 18:30 UTC
    Why would one use the external grep from within Perl? It just makes things harder. If you don't use it, there's no grep to exclude. Perl has a grep function that can use regexes or any expression (or even a block of code) you want!

    my @httpd = grep /httpd/, qx(ps aux); # external grep(1) is not called, so it's not in the array.


    Please note that you cannot trust the ps output, because everyone could name his process httpd, and fake your script (I have been bitten). If you must be really sure and you have a /proc filesystem, use that and check command line and path etcetera.

    ++ vs lbh qrpbqrq guvf hfvat n ge va Crey :)
    Nabgure bar vs lbh qvq fb jvgubhg ernqvat n znahny svefg.
    -- vs lbh hfrq OFQ pnrfne ;)
        - Whreq
    

Re: Searching strings within an array for a particular word.
by Anonymous Monk on Mar 07, 2002 at 22:32 UTC
    If you want to make sure httpd is responding versus has a process running, try the following:
    #!/usr/local/bin/perl -w use strict; use LWP::UserAgent; my $debug = 0; my $url = shift || die "Syntax is '$0 url-to-test': $!"; $debug && print "URL is $url\n"; my $ua = new LWP::UserAgent; my $request = HTTP::Request->new('GET', "$url"); my $response = $ua->request($request); if ($response->is_success) { exit 0; } else { exit 1; }
    I have been bitten in the past by checking for a process running.