I'm building a c sharp serviceProcess that will start a Batch file (the batch file will start a java application).
If i stop the service it kills the java process. Stopping the java process can take up to 2 minutes. The service has to wait for the java application to stop, so i made a sleep.
System.Threading.Thread.Sleep( );
Is it possible to check if the "java" process is closed and after that stop the ServiceProcess.
You can access the process using the Process-class. It allows you to get several information about a specific process. When you start the java.exe directly (using Process.Start) you already have the Process-instance.
When using a batch-file, you need to find the process, which is not a problem at all. You can find a process using Process.GetProcessesByName, but you'd find all all java-processes running on your machine.
You could try something like the following:
Process[] proc = Process.GetProcessesByName("Java");
if (proc.Count() != 0)
{
//Process Alive
Process prod = proc[0];
prod.Kill();
prod.WaitForExit();
}
else
{
//Process Dead
}
A better option would be to use the process ID(if you know it)
Warning: This will kill the first java process it finds, you need to check which one you need to kill...
Related
In Java, I start one new Process using Runtime.exec(), and this process in turn spawns several child processes.
I want to be able to kill all the processes, and have previously been trying process.destroy() and process.destroyForcibly() - but the docs say that destroyForcibly() just calls destroy() in the default implementation and destroy() may not kill all subprocesses (I've tried and it clearly doesn't kill the child processes).
I'm now trying a different approach, looking up the PID of the parent process using the method suggested here and then calling ps repeatedly to traverse the PIDs of child processes, then killing them all using kill. (It only needs to run on Linux).
I've managed the first bit - looking up the PID, and am trying the following command to call ps to get the child PIDs:
String command = "/bin/ps --ppid " + pid;
Process process = new ProcessBuilder(command).start();
process.waitFor();
Unfortunately the 2nd line above is throwing an IOException, with the following message: java.io.IOException: Cannot run program "/bin/ps --ppid 21886": error=2, No such file or directory
The command runs fine if I paste it straight into the terminal on Ubuntu 16.04.
Any ideas would be very much appreciated.
Thanks
Calling the command you wish to run this way is always destined to fail.
Since Process does not effectively run a shell session, the command is basically handed over to the underlying OS to run. This means that it'll fail, since the path to t he program to be executed (in this case ps), is not the full one hence the error you're getting.
Also, testing whether your command works using a terminal is not correct. Using a terminal contains the notion of performing an action with an active logged in user with a correct path etc etc. All the above are not the case though when running a command through Process as these are not taken into consideration.
Furthermore, you also need to account for cases where the actual java application could be running under a different user, with a different set of permissions, paths etc.
In order for your to fix this, you can simply do either of the following:
1) Invoke your ps command using the full path to it (still not sure if it would work)
2) Change the way your create the Process object into something like: p = new ProcessBuilder("bash", "-c", command).start();
The second, will effectively run a bash session, passing in the ps command as an argument thus obtaining the desired result.
http://commons.apache.org/proper/commons-exec/tutorial.html
```
String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
```
i'm working on a project for my thesis in JAVA which requires automatic RMI generation from Abstract Syntax Tree. I'm using RMI as
`public int createProcess(CompilationUnit cu){
//Some Code Here
return processid;
} `
for generating RMI from AST on each node. And it will automatically generates the Interface file and all the java files from AST and put all the methods in these files. I am able to execute the javac, rmic <remote-class>, rmiRegistry commands using process builder. But
how to destroy and unbind the remote objects after process completion ? Do i have to put this code at the end of each file where control exits ?
public void exit() throws RemoteException
{
try{
// Unregister ourself
Naming.unbind(mServerName);
// Unexport; this will also remove us from the RMI runtime
UnicastRemoteObject.unexportObject(this, true);
}
catch(Exception e){}
}
Do i have to execute rmiRegistry after every remote method/classes creation or it will automatically adds the later remote methods/classes to registry, if it is already in the executing state (means if processbuilder is already executing the command "rmiRegistry") ? For example if nodeA creates a Process1 (RMI class) on nodeB and then execute it using commands via Processbuilder, rmiRegistery will be in running state. Now if NodeA wants to create another Process2 on NodeB, do i have to stop that instance of rmiRegistery and rerun it, or there is no need to do that Registery will detect & add new bindings automatically?
Will all the RMI run on same port ?? means if i create process1 and bind it with localhost/process1 & process2 with localhost/process2 , can we access them via same port ?
i'm working with RMI first time so don't have any previous experience or knowledge.
Apologies, my question seemed unclear , so i tried to put more explanation by editing ?
Following this tutorial Link
1 how to destroy and unbind the remote objects after process completion ?
See 2, but I don't know why you want to do so. Just leave them in existence and bound to the Registry.
2 Do I have to put this code at the end of each file where control exits ?
Yes, if you want it to execute, otherwise no. Don't generate empty catch-blocks though.
3 Do I have to execute rmiRegistry after every remote object creation
No, you have to start it once, at the beginning of the containing process. Simplest way is via LocateRegustry.createRegistry().
I am launching a process with Runtime.getRuntime().exec()
However, once Java reaches the end of the main() loop, java will not close, unless I destroy() the process first.
Problem with that is, I need the process to keep running after Java is closed.
I pretty much want to do this
public static void main(String args[]) {
Runtime.getRuntime().exec("file.bat");
// now I want java to close, and I want file.bat to keep running
}
I tried System.exit(), it will stop my main() loop, however I think a thread or something that was started by exec() keeps running, preventing java from closing. I can't even end it in Eclipse without first exiting file.bat
Why isn't it closing? And how would I fix it?
I couldn't find anything online, and I've been experimenting for a while, so I decided to ask you guys.
Thank you,
-Alex Benoit
Figured it out. I'll share my code in case anyone else has the same question. I brought it down to 1 line.
Desktop.getDesktop().open(new File("C:\\Folder\\File"));
This is a system dependent question. I am not sure if in Windows the parent process can terminate before the child. I believe this is true in linux.
As a guideline, you should call waitFor() on the process. However, on some systems, just doing so might not be enough. As pointed out in the javadoc, the out/err stream need to be properly purged (using the streams returned by getOutputStream() and getErrorStream()) because they could keep your process from completing. To do so, I found it most appropriate to use two separate threads, one purging the err stream, the other the out stream. The calling thread (main in your case), has to do the following:
start the external process;
start a thread to purge the out stream;
start a thread to purge the err stream;
call waitFor() on the calling thread (main).
I found the above approach very robust and easy to implement (if you are familiar with threads). Please use an ExecutorService for the threads.
Launch the file with cmd for Windows Only
Older windows will probably have to use command.com instead
Runtime.getRuntime().exec("cmd /c start file.bat");
Using the start with /wait parameter waits until bat is finished without /wait it should work.
public class Command {
public static void main(String[] args) throws java.io.IOException, InterruptedException {
String path = "C:\\DOCUME~1\\\USER\\DESKTOP";
Process p = Runtime.getRuntime().exec("cmd /c start /wait " + path + "\\test.bat");
System.out.println("Waiting for batch file ...");
p.waitFor();
System.out.println("Batch file done.");
}
}
test.bat
#echo off
cls
:start
echo This is a loop
goto start
Use the command.com file to get short path name, since long path names don't get processed too well in start program.
Here is a sample I made download link below:
https://www.mediafire.com/?mu7vht3e6tto698
Your problem may be that you are not on a Windows Administrator account you could try, But this requires you to type in your Administrator password which is very stupid.
Process p = Runtime.getRuntime().exec("runas /profile /user:Administrator \"cmd.exe /c start test.bat\"");
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();
My main field is .Net but recently I have got something to do with Java. I have to create a shell utility in Java that could run in background reading few database records after specified duration and do further processing. It's a kind of scheduler. Now I have few concerns:
How to make this work as a service. I want to execute it through a shell script and the utility should start running. Off course the control should get back to the calling script.
Secondly, eventually i may want to stop this process from running. How to achieve this?
I understand these are basic question but I really have no idea where to begin and what options are best for me.
Any help / advise please?
I would go for the running the program using a scheduler or a service. However, if you wish to use a bat file and do this programmatically, I have outlined a possible approach below:
In your Java program, you can get the PID programmatically, and then write it to a file:
public static void writePID(String fileLocation) throws IOException
{
// Use the engine management bean in java to find out the pid
// and to write to a file
if (fileLocation.length() == 0)
{
fileLocation = DEFAULT_PID_FILE;
}
String pid = ManagementFactory.getRuntimeMXBean().getName();
if (pid.indexOf("#") != -1)
{
pid = pid.substring(0, pid.indexOf("#"));
}
BufferedWriter writer = new BufferedWriter(new FileWriter(fileLocation));
writer.write(pid);
writer.newLine();
writer.flush();
writer.close();
}
You can then write a stop .bat file that will kill the running program in windows. You could do something like:
setlocal
IF EXIST app.pid FOR /F %%i in ('type app.pid') do TASKKILL /F /PID %%i
IF EXIST app.pid DEL app.pid
endlocal
Of course, app.pid is the file written by the Java method above.
I am not sure how you would be able to write a script that launches a java program, and reverts control on termination. I would be interested to see if anybody has a solution for that.
I assume that you are playing your java program with a Linux/Unix box.
To run your application as a daemon, you can try
nohup java YourJavaClass &
To stop your application, you can either:
kill [psIdofYourApplication]
or
fg [your application job Id]
Ctrl-C
If you want to do some postprocessing after the application receiving 'kill/stop' signal. check out addShutdownHook(Thread hook)
Or sun.misc.SignalHandler
ps ux
see pid
kill pid
Or you'd better provide a stopping script that signals the application, which does System.exit(0)
You didn't specify the platform. If on Windows you should look into integrating with the Service Control to create a Windows service. http://en.wikipedia.org/wiki/Windows_service. Once you've implemented the service hooks, it is possible to start and stop the service through the service control GUI or using net stop MyService syntax from the command line.
As I understand, you want something like this:
if ( System.in.avaliable() > 0 ) {
in = new BufferedReader( new InputStreamReader( System.in );
String InLine = in.readLine();
...
}
Am I right?