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

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

You can do something like this:
$components = #("COMP_Number1","COMP_Number2")
$theProcess | %{
$p = $_
$running = $components | ?{$p.commandline -match $_}
$notrunning = $components | ?{ $running -notcontains $_ }
}
$notrunning

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"}

$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.

Related

Listen DNS requests with Java in continuous and execute cmd command

Ok let's be precise. For many days I've been asking myself a question : Could it be possible to listen DNS request on a computer ( in my case a windows machine ) and ask to the program to execute a shell command if a special DNS is detected ?
I've been playing with this command :
ipconfig /displaydns | find "my.dns.com"
And as expected I'm able to find "my.dns.com" in my DNS cache.
BUT I'm not able to ask to the cmd :
Hey, listen for all the requests in continuous and when you detect
"my.dns.com" please execute "music.exe".
So I imagined a program ( in Java ) doing it for me. Why java ? Because i'ts the only programming language that I'm able to use, I started with it so it's easier for me to understand it. But if what I'm looking for is not possible in Java, let me know it !
BUT ( again ) I don't know how to manage with DNS requests and neither ask for a java program to run in continuous. For the moment here is everything I could add to my program :
if ("my.dns.com" is detected) {
try {
String command = "cmd /c start music.exe";
Process child = Runtime.getRuntime().exec(command);
OutputStream out = child.getOutputStream();
} catch (IOException e) {
}
And maybe for running in continuous :
boolean running = true;
while(running)
{
//main loop...
}
I know, that is very few but I don't even know where to look to answer my question.
Please, if you'r able to understand me ( Yes you behind your screen while eating Doritos ) could you at least help me to find my way ?
Precise if you want me to edit it :)
Perhaps this (untested) clip of PowerShell will get you going. I do not know that it is a good idea to clear the DNS cache, but that is up to you. If you do not, it will still be in there.
while ($true) {
$a = Get-DnsClientCache | ForEach-Object { $_.Name }
if ($a -contains 'the.dns.com') {
Start-Process C:\path\to\music.exe -Wait
Clear-DnsClientCache
}
}

Detect when specific program program has closed with C#

I have two different .jar programs running on the same machine. I want to be able to detect when one of them has been closed, or is no longer running.
This issue that I am having is, when running this code:
var allProc = Process.GetProcesses();
foreach (var p in allProc)
comboBox1.Items.Add(p.ProcessName);
comboBox1.Sorted = true;
It only shows a single instance of Java running, and not only that it doesn't show either of the process names.
The program I want to monitor uses a lot of RAM, so I thought about monitoring RAM usage and doing what I need when it drops below a certain level, but to me that sounds like a hacky way of doing it and other factors could effect it.
Any ideas?
You can use System.Diagnostics.Process to get the Process Id for the parent process you're looking for.
From there you can then use WMI through the (System.Management) namespace to search for the child processes:
Process[] javaProcesses = Process.GetProcessesByName("somejavaapp.exe");
foreach (Process proc in javaProcesses)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"SELECT * " +
"FROM Win32_Process " +
"WHERE ParentProcessId=" + proc.Id);
ManagementObjectCollection collection = searcher.Get();
// Choose what to do with the child processes.
foreach (var childProcess in collection)
{
var childProcessId = (UInt32)childProcess["ProcessId"];
}
}
I had the same Issue a while ago, the best Solution for me was to run the java Programm as child.
Example
server = new Process();
server.StartInfo.FileName = "java";
server.StartInfo.Arguments = "-Xmx4000M -jar forge.jar nogui";
server.Start();
Then Simply
status = server.HasExited;
There is a command line tool that comes with the JDK called jps.
jps -v shows all the arguments you have passed to java. It provides the following output:
lvmid [ [ classname | JARfilename | "Unknown"] [ arg* ] [ jvmarg* ] ]
You can call jps from c# and then read the output.

How to get the path of a running process if its pid of name is known in java on a windows system?

I am writing a program to kill and start processes in another computer connected via lan. I am able to kill the process successfully. I used tasklist to list the process and taskkill for killing it. To start the killed program again the path of the process have to be obtained.
Is there a way that I can do it in java?
I don't think it's possible to kill a process by it's path, but you can always kill it by either it's process name or id.
Here's what I use to kill a process, e.g. firefox.exe.
Create a VB script as follows,
sub killProcess(strProcessName)
set colProcesses = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * from Win32_Process Where Name='" & strProcessName & "'")
if colProcesses.count <> 0 then
for each objProcess in colProcesses
objProcess.Terminate()
next
end if
end sub
killProcess "firefox.exe"
Now in order to run the above script via Java, use the Process API as follows,
Process pr = Runtime.getRuntime().exec(path_to_vbscript_file, null, null);
pr.waitFor();

Can we check the queue depth using a scripting language?

Is it feasible to check queue depth(MQ) using any scripts? [No restrictions on the language]. The plan is to look at non-Java solutions.
I do understand that it is achievable in Java using MQQueueManager but that would need the usage of client API. Hence checking for any alternate options or better practices.
InquireQueue at http://www.capitalware.biz/mq_code_perl_python.html looks similar[but looks a bit outdated]
Didn't Google give you a recent blog posting I wrote called "How to Clear a MQ Queue from a Script or Program" at http://www.capitalware.biz/rl_blog/?p=1616
Just change the MQSC "clear" command to "current depth" (CURDEPTH).
i.e.
DIS QL(TEST.*) CURDEPTH
Does nobody use google anymore ?
PyMQI, an open-source Python extension for WebSphere MQ
http://metacpan.org/pod/MQSeries::Queue
my %qattr = $queue->Inquire( qw(MaxMsgLength MaxQDepth) );
The perl mqseries is very complete. Below is some sample code. (Part of the credit for the sample probably goes to someone else, but it has been floating around my drive for years.) The code connects to the queue manager specified by the command line, if not supplied, it will connect to the default queue manager. It then inquires about the queue name passed in, specifically, the current depth of that queue. This is displayed to the user. This code can easily be modified to display other queue properties. Furthermore, MQINQ can be used to inquire about the attributes of other objects, not just queues.Here is the subset sample code:
use MQSeries;
my $quename = $ARGV[0];
my $quemgrname = $ARGV[1];
my $Hconn = MQCONN($qmgrname, $CompCode, $Reason);
print"MQCONN reason:$Reason\n";
my $ObjDesc = { ObjectType => MQOT_Q, ObjectName => $qname };
my $Options = MQOO_INQUIRE | MQOO_SET | MQOO_FAIL_IF_QUIESCING;
my $Hobj = MQOPEN($Hconn,$ObjDesc,$Options,$CompCode,$Reason);
print"MQOPEN reason:$Reason\n";
my $tst = MQINQ($Hconn,$Hobj,$CompCode,$Reason,MQIA_CURRENT_Q_DEPTH);
print"Depth of $qname is: $tst\n";
MQCLOSE($Hconn,$Hobj,$COptions,$CompCode,$Reason);
print"MQCLOSE reason:$Reason\n";
MQDISC($Hconn,$CompCode,$Reason);
print"MQDISC reason:$Reason\n";
If you are logged in using MQM user on linux and want to have a quick check on queues with messages in them .. here is a quickfix ..
echo "dis ql(*) CURDEPTH" | runmqsc <QMGRNAME> | grep -v '(0' | grep -v 'AMQ'
this will give you a command line output and you can schedule the same command in crontab if needed directly ( without having to save a script for it )
I know its not neat but may be the quickest of solutions.
There's the many JVM based scripting/ish languages that give you access to Java classes. Some need a thin glue layer, some need nothing at all.
Groovy
Jython
Scala
Clojure
etc.

How can I mount a windows drive in Java?

We are working with some legacy code that accesses a shared drive by the letter (f:\ for example). Using the UNC notation is not an option. Our Java wrapper app will run as a service, and as the first step, I would like to map the drive explicitly in the code. Has anyone done this?
Consider executing the DOS command that maps a network drive as in the following code:
String command = "c:\\windows\\system32\\net.exe use f: \\\\machine\\share /user:user password";
Process p = Runtime.getRuntime().exec(command);
...
See details on net use command:
The syntax of this command is:
NET USE
[devicename | *] [\\computername\sharename[\volume] [password | *]]
[/USER:[domainname\]username]
[/USER:[dotted domain name\]username]
[/USER:[username#dotted domain name]
[/SMARTCARD]
[/SAVECRED]
[[/DELETE] | [/PERSISTENT:{YES | NO}]]
NET USE {devicename | *} [password | *] /HOME
NET USE [/PERSISTENT:{YES | NO}]
You can use JCIFS
http://jcifs.samba.org/src/docs/api/jcifs/smb/SmbFile.html
or if you want higher level API and support for other protocols like FTP, Zip and others:
http://commons.apache.org/vfs/filesystems.html
Both options are pure Java and cross platform.
I think the easiest way is to use the Runtime.getRuntime().exec() method and call the "net use" command.
For example:
try {
// Execute a command without arguments
String command = "C:\\Windows\\system32\\net.exe use F: \\\\server\\share /user:user password";
Process child = Runtime.getRuntime().exec(command);
} catch (IOException e) {
}

Categories

Resources