Reputation: 37
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
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
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
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