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

I'm using strawberry-perl (win32) to run a script that eternally loops through importing some data from a log, grepping the data for specific errors and then sends me an email if it finds the message.

Occasionally the server has a high load and the script fails. I put sleep 2 in to help, which seems like it helps, but I still get a failures. I've tried intentionally killing tail.exe after use but it doesn't help. The code below runs in the eternal loop. The subroutine backticks_die just sends me an email.

@servergrep = `c:\\unixtools\\usr\\local\\wbin\\tail.exe -n 10 $line` or die backticks_die(); sleep 2; our $message = grep ( /accept Rejected. Max connection reached/i, @servergrep); if ($message) { print "found max connections /n "; }; #clear out @servergrep @servergrep=();

Replies are listed 'Best First'.
Re: Win32 script dies under high load
by mjscott2702 (Pilgrim) on Jul 23, 2007 at 19:22 UTC
    I'd suggest that you use the code tags to better format your code snippet.
    Couple of suggestions:
    1) Use the Windows task scheduler to create a call to the script on a periodic basis, rather than in an eternal loop. That way, if server load is causing a problem with the tail system call, at least the script will restart next time around.
    2) Avoid the use of the system call completely - use the File::Tail module from CPAN with something like:
    use File::Tail; $file=File::Tail->new(name=>$name, maxinterval=>10); while (defined($line=$file->read)) { if ($line =~ m/accept Rejected. Max connection reached/i) { print "found max connections\n"; } }
    Note: this will create a permanent loop, removing the need for the first suggestion!
      1. Thanks for the help. 2. The task scheduler won't eternally loop for me. I'm on win2k server and there's just no option like that. Task scheduling in windows is terrible in so many ways I could write a book about the surprises I've encountered attempting to use it. 3. File::Tail wouldn't work for me. I don't know/remember why but I started with that and I just moved on after banging my head against the wall. I'm going to try the error code in the post below.
        Occasionally the server has a high load and the script fails.

        You never did identify how it fails? Does it die? Hang? Produce the wrong output? Go on a bender and wake up naked in Glasgow? :)


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Win32 script dies under high load
by Argel (Prior) on Jul 23, 2007 at 19:41 UTC
    What do you mean by "fails"? Does the script die? Or the tail fails to return? Or the script fails to detect max connections?

    If the script is failing to detect the max connections situtation then my first guess would be the logfile you are looking at is being updated much more often than you expect -- i.e. more than 10 lines every couple of seconds. In which case you should look into monitoring the file directly (as mjscott2702's suggests in Re: Win32 script dies under high load) instead of shelling out to run an external command. It's also possible that if another process is hogging the CPU then your "sleep 2" may actually take more than two seconds.

    If you are having problems with the tail returning and want to stick with using it then you may want to look into using alarm. Here's some sample code you could adapt to your situation:

    sub cmd_wrapper { my( $cmd ) = @_; my( $rc , $out ); eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 15; $out = (`$cmd`)[0]; # Get first line of output $rc = $?; alarm 0; }; if( $@ ) { die "Eval failed for $cmd but not because of alarm" if $@ ne " +alarm\n"; # Propogate unexpected errors die "Eval failed for $cmd because alarm timed out"; } die "Return code undefined for $cmd" unless defined $rc; return $rc, $out if wantarray; return $rc; }