#!/usr/bin/perl
my $info = <<INFO;
check_duplicate_proc.pl 1.1
Checks for duplicate processes through a linux process listing (ps)
Program assumes previous day's results are 24hours old (1440 minutes) due to my lazyness. :)
Jason Lancaster <jlancaster@affinity.com>
Last modification: 6/20/03

Usage:
$0 -p <process> -t [time] -v [verbose] -d [debug] -h [help]

Options:
<process>\tProcess to search for (required)
[time]\t\tSearch for process running more than [time] minutes. Default is 0.
[verbose]\tPrint out additional information. Useful when running via the command line.
[debug]\t\tPrint debug info for me.
[help]\t\tPrint this help.

INFO

# Set your variables here
my $ps = "/bin/ps -aucxwww";
my $current_time = `/bin/date +%b:%d:%H:%M`;

# Don't touch anything below this line!
use strict;
use Getopt::Std;

my (%arg);
getopts("dvhp:t:", \%arg);

# Set defaults and required fields
$arg{d} = 0 unless $arg{d};
$arg{v} = 0 unless $arg{v};
$arg{h} = 0 unless $arg{h};
$arg{t} = 0 unless $arg{t};
unless ($arg{p}) { warn "Missing required argument (-p)\n\n"; &helpit; }

# Do some basic handling
if ($arg{h} == 1) { &helpit; }

# Print if good
if ($arg{d}) { printf "switch p:%s\nswitch t:%d\n", $arg{p}, $arg{t}; }

sub helpit {
    print $info;
    exit 0;
}

# Read file and print output
sub readit {
    my ($stale_process_count, $process_count) = 0;
    chomp $current_time;
    my (%this, %proc);
    ($this{'month'}, $this{'day'}, $this{'hour'}, $this{'minute'}) = split(/:/, $current_time);

    open(CMD, "$ps |") || die "Cannot execute $ps $!\n";
    while (my $line = <CMD>) {
        chomp $line;
        $line =~ s/\s+/\,/g; # convert to delimited format
        
        # USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
        ($proc{'user'}, $proc{'pid'}, $proc{'cpu'}, $proc{'mem'}, $proc{'vsz'}, $proc{'rss'}, $proc{'tty'}, 
            $proc{'stat'}, $proc{'start'}, $proc{'time'}, $proc{'command'}) = split(/\,/, $line);

        if ($arg{v}) { print "# process found: $proc{'command'}\n"; }

        if ($proc{'command'} =~ /$arg{p}/) {
            # set these vars for each process found
            $this{'minute_conversion'} = int(($this{'hour'} * 60) + $this{'minute'});
            $proc{'day'} = 0;
            $proc{'month'} = 0;

            if ($proc{'start'} =~ /:/) {    # this process started today
                ($proc{'hour'}, $proc{'minute'}) = split(/:/, $proc{'start'});
            } else {                        # old process
                $proc{'start'} =~ /([A-Z][a-z]+)(\d+)$/;
                $proc{'day'} = $2;
                $proc{'month'} = $1;
            
                if ((! $this{'month'} eq $proc{'month'}) && ($stale_process_count > 1)) { 
                    printf "CRITICAL: You have more than one stale '%s' process more than one month old\n", $arg{p}; 
                    exit 2; 
                }
            
            }

            if ($proc{'day'} > 0) {
                $proc{'minute_conversion'} = int(($this{'day'} - $proc{'day'}) * 24 * 60);
                $this{'minute_conversion'} = int($this{'minute_conversion'} + $proc{'minute_conversion'});
            } else { $proc{'minute_conversion'} = int(($proc{'hour'} * 60) + $proc{'minute'}); }

            if ($arg{v}) { print "new process: $proc{'command'} started $proc{'start'} or $proc{'minute_conversion'} minutes\n"; }

            if ($proc{'minute_conversion'} < int($this{'minute_conversion'}-$arg{t}))  {
                if ($arg{v}) {
                    printf "\tchecking previous %s process to see if seeded at less than %d minutes...\n", 
                        $arg{p}, int($this{'minute_conversion'}-$arg{t});
                    printf "\tFOUND pid $proc{'pid'}! Stale by %d minutes\n", 
                        int($this{'minute_conversion'} - $proc{'minute_conversion'}); 
                }
                
                $stale_process_count++;

            } 

            $process_count++;
        }
    } # end while

    close (CMD);

    if ($arg{v}) { print "\ntotal processes: $process_count\nstale_process_count: $stale_process_count\n"; }
    if ($process_count == 0) { die "Cannot find '$arg{p}' in process listing!\n"; }
    if ($stale_process_count > 1) { printf("CRITICAL: More than one stale '%s' process found\n", $arg{p}); exit 2; }
    if ($stale_process_count == 1) { printf("OK: %d parent '%s' process found\n", $stale_process_count, $arg{p}); exit 0; }

    return 1;
}

&readit;

exit 1;

