TimmyT
TimmyT

Reputation: 37

How do I monitor Windows Java processes with "Get-wmiObject"

I have some java components that sometimes die and the only way I know is when a user compains they've gotten an error.

What I've done on our monitoring systems is count the amount of java processes running on the server. If a component dies, I get alerted that the java threshold is below normal and I log in to find out which one of the java components died. It works, but I think it could be refined to which component died and be able to start the java process remotely.

So what I was thinking is writing a Powershell script that is executed from the monitoring system. I think I have most of the 'one liner' but need a little more help getting me to the finish line, as I think this script doesn't need to be elaborate.

What I have so far is:

$theProcess = Get-WmiObject win32_process -Filter "name like '%java%'" | select commandLine

The output of this command gives me all the parameters sent to the JVM, including the name of the component, lets call the component "COMP_Number1", and usually there are 5 java component processes running, so the name of the components are "COMP_Number2", "COMP_Number3", and so on.

My question is: Given the output of $theProcess, how do I check all the java processes to validate that all of the components are running? And if not, which one is not running?

Much Appreciated!

TT

Upvotes: 3

Views: 4566

Answers (3)

JPBlanc
JPBlanc

Reputation: 72660

If you can use WMI on the the server you can use WMI events to detects the processes that are stopped.

Register-WMIEvent -Query "SELECT * FROM Win32_ProcessStopTrace WHERE ProcessName like 'notepad%'" -Action {Write-Host "kind of notepad process is died"; Write-Host $args}

Here you'll detect notepad.exe die and also notepad++.exe.

You can use Get-EventSubscriber to retreive events you suscribe to and Unregister-Event To unsuscribe.

The script block is considered as a job, so be carefull to import all the modules you need inside.

The script block receive two parameters :

1) System.Management.ManagementEventWatcher

2) System.Management.EventArrivedEventArgs

Here are the parameters of $args[1].newevent :

ExitStatus          Property   System.UInt32 ExitStatus {get;set;}
ParentProcessID     Property   System.UInt32 ParentProcessID {get;set;}
ProcessID           Property   System.UInt32 ProcessID {get;set;}
ProcessName         Property   System.String ProcessName {get;set;}
SECURITY_DESCRIPTOR Property   System.Byte[] SECURITY_DESCRIPTOR {get;set;}
SessionID           Property   System.UInt32 SessionID {get;set;}
Sid                 Property   System.Byte[] Sid {get;set;}

Exemple :

Register-WMIEvent -Query "SELECT * FROM Win32_ProcessStopTrace WHERE ProcessName like 'notepad%'" -Action {Write-Host "$($args[1].newevent.ProcessName) process is died"}

Upvotes: 1

Torbjörn Bergstedt
Torbjörn Bergstedt

Reputation: 3429

$components = @("COMP_Number1","COMP_Number2")
$running = @()
do {
   Get-WmiObject win32_process -Filter "name like '%java%'" | select commandLine | Foreach-Object {
      $running += ($_.commandLine -replace ".*(COMP_Number\d).*",'$1')
   }
   if ($running.Count -lt $components.Count) {
     Compare-Object ($running | Sort-Object) ($components | Sort-Object)
   }
   $running = @()
   Start-Sleep 50000
} until (1 -lt 0)

The regexp most certainly needs work on. You might add some other warning method (e-mail?) or even try to automatically restart the missing process in the if statement.

Upvotes: 0

manojlds
manojlds

Reputation: 301327

You can do something like this:

$components = @("COMP_Number1","COMP_Number2")
$theProcess | %{ 
    $p = $_
    $running = $components | ?{$p.commandline -match $_}
    $notrunning = $components | ?{ $running -notcontains $_ }
}

$notrunning

Upvotes: 1

Related Questions