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

I'm trying to figure out how to approach this problem:

I have a server process (on Win2k) that occasionally spikes to 100% cpu utilization and eventually hoses the server if no action is taken. Unfortunately, this process shares its name with 9 other processes so it has been difficult for me to narrow it down. Killing all the processes with the same name is not an option, I need to target only the offending process and kill it.

I've looked into many of win32-process modules and they require the PID to kill it. I then looked into win32-process-perf, but I can't figure out how to get it to look for multiple process with the same name.

To summarize, I'm looking to retreive all PID's from exampleprocess.exe, check CPU utilization and kill the problem process. Any ideas?
  • Comment on Win32: Multiple processes with the same name

Replies are listed 'Best First'.
Re: Win32: Multiple processes with the same name
by BrowserUk (Patriarch) on Feb 08, 2006 at 17:55 UTC

    Grab Win32::Process::Info and then try this. It lists name, pid, kernel and user mode cpu utilisations for all the processes in the system.

    #! perl -slw use strict; use Win32::Process::Info; my @info = Win32::Process::Info->new->GetProcInfo({no_user_info=>1}); printf "%20s : %5d : K:%10.3f U:%10.3f\n", @{ $_ }{qw[Name ProcessId KernelModeTime UserModeTime ]} for @info; __END__ c:\test>pi System Idle Process : 0 : K:192689.359 U: 0.000 System : 4 : K: 49.203 U: 0.000 ... TextPad.exe : 1112 : K: 43.328 U: 81.781 CMD.EXE : 1276 : K: 5.953 U: 3.422 CMD.EXE : 644 : K: 0.625 U: 0.219 CMD.EXE : 440 : K: 0.016 U: 0.031 TextPad.exe : 1524 : K: 6.141 U: 7.578 Opera.exe : 816 : K: 6.438 U: 9.516 perl.exe : 1508 : K: 0.000 U: 0.047 perl.exe : 1724 : K: 0.125 U: 0.188

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      That post helped greatly, thanks BrowserUK.

      I am able to determine the PIDS, but now I need to get the CPU info. Here's what I came up with using win32-process-info:

      (note: I've been using perl for less than a week so this script may be a bit ugly)

      use Win32::Process::Info; Win32::Process::Info->Set (variant => 'WMI'); my $pi = Win32::Process::Info->new(); for ( $pi->ListPids ) { my ($info) = $pi->GetProcInfo ($_); if ($info->{Name} =~ /notepad/gi ) { $pid = $info->{ProcessId}; push @pids, $pid; } } print "@pids";

      After I got that working, I started researching the win32::process::perf module. However, that module seems to accept only the name of the process instead of the PID. That won't work for me here.

      Any ideas on how to match the PIDs with CPU utilization?

      the help has been much appreciated!

        Did you try running my example above? It produces all the information you require.

        Learn to use Data::Dumper to inspect anything you do not understand. It is verbose, but clearly displays the structures involved.

        See also Tye's References quick reference for the syntax required to use them.

        Anyhow, here's an annotated version that should be reasonable to follow, though you will have to get up to speed on Perl's datasteuctures quite quickly as W::P::I makes heavy use of them.

        #! perl -slw use strict; use Data::Dumper; use Win32::Process::Info; ## Get an array of hashes for every process in the system my @info = Win32::Process::Info->new ->GetProcInfo({no_user_info=>1}); ## The hashes contain all the information you will ever need! ## This displays the fields available for one of the processes print Dumper $info[ 0 ]; my @notepads; ## A place to hold the hashes that match the name for my $procRef ( @info ) { ## Scan them all ## Extract the Name, ProcessId KernelModeTime & UserModeTime value +s ## Using a hash slice my( $name, $pid, $kcpu, $ucpu ) = @{ $procRef }{ qw[Name ProcessId KernelModeTime UserModeTime ] + }; if( $name =~ m/notepad/i ) { ## If it matches the name you are loo +king for ## Add an anon. array containing the PID and the combined Kern +elMode ## & UserMode time to the array push @notepads, [ $pid, $kcpu + $ucpu ]; } } die 'There are no notepads runnning' unless @notpads; ## Sort the @notepads Array of Arrays (AoA) by cpu utilisation, descen +ding. @notepads = sort{ $b->[ 1 ] <=> $a->[ 1 ] } @notepads; ## The first element (PID) of the first @notepads element ## has the highest cpu utilisation, so kill it. ## On win32, any signal other than 0, 2, & 21 seems to be fatal. ## There may be other non-fatal signals, but it is boring testing for +them. kill 1, $notepads[ 0 ][ 0 ];

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Win32: Multiple processes with the same name
by beachbum (Beadle) on Feb 08, 2006 at 17:56 UTC

    Win32::Process::List looks like it may help you build an array / hash of suspects for you. Win32::Process::Info also has a ListPids() method. If these modules do return your list of pids, you should be able to use Win32::Process::Perf to find the faulty pid, and Win32::Process to kill it.

    Of course, if these process are perl scripts, you could use $$ to capture the pids as they are created.