I am using Java Runtime to run commands, including certain CVS commands.
I use:
process = runtime.exec ("cmd /C cvs...");
format for running the Process in Java
I need to have the option of stopping it. For this I use the Java Process destroy method
process.destroy();
However only the cmd is stopped not the cvs process. It continues to run as a separate process without the cmd process as the parent. There are many references to this on the internet, but I haven't found any satisfactory solution. Thanks
This is a problem with the windows cmd shell. Why do you use it? Can't you do exec("cvs ...") instead?
It may be possible using Runtime.exec to get the PID of the process you have run. And with that you might be able to shut down the process tree.
You would however need 2 other programs to find the PID and to terminate the process tree.
Related
I am trying to execute Java application from my c# code. I use Process class from System.Diagnostics.
I am able to run it and kill, but it seems that java starts subprocess when I am executing application. And when I am trying to kill the Process, I kill the parent java process, the second one, which was started behind the scenes, is still running.
Multiple executions of this logic cause dozens of java.exe processes and memory overflow.
Is there a way to do such thing as proper running Java application from c# code and be able to kill started processes?
I wonder if it is possible at all to resolve this issue if I don't have administrative rights
I would be tempted to use taskkill. It runs from this cmd command:
string.Format("cmd /c \"taskkill /f /pid {0}\" /t", this.processId);
the /t does a tree kill, that ends the child processes.
I need to execute a tcl file which gives output util we stop the process from java. So I use
Process proc = Runtime.getRuntime().exec("< tcl file >");
I need to get the process id (PID) to stop the process.I can run that same tcl file multiple times, so I can't get pid using getting name of executing file. Give me some methods to get process id using JAVA when running a external program.
output of ps command :
25014 pts/0 00:00:00 tclfile
29998 pts/0 00:00:09 tclfile
30866 pts/0 00:00:00 tclfile
Each instance is different I need to stop only specified process at a time, can't terminate all by killall -9 tclfile command .
The pid is not exposed to Java, since Java is platform-agnostic and pids are platform-specific. So you aren't going to be able to get the actual pid without using native code, sorry.
But if you just want a handle to the child process which you can later kill, you can do that in pure Java. The Process object has methods destroy() (which kills the process) and waitFor() (which waits for it to exit). In Java 8 it also has isAlive() and destroyForcibly() methods.
OK, after poking around on the net to find source code for ProcessImpl in various JREs, it looks like on Windows ProcessImpl has a field handle which presumably is the Win32 handle returned by CreateProcess, and on Linux UNIXProcess has a field pid which appears to be the process ID. If you wanted to be really hacky (and unsupported, and potentially tied to a specific JDK implementation, etc. -- all the usual caveats apply), you could potentially access those fields by reflection if you need to.
That said, a better solution would be to write the native code yourself, or else delegate to a helper process (e.g. in bash like Donal Fellows' answer).
You can't get the process ID from the Process object; it knows it (strictly, it's known by an object inside of a class that isn't part of the public API) but won't tell you. The simplest method of getting the PID turns out to be to get the subprocess to tell you that value by writing it to its standard out (or standard error, but that's less common) as its first action. You then can just read a line, parse the integer out of it, and there you go.
Getting Tcl scripts to print their PID is trivial. Just put this line in:
puts [pid]
# Or: puts stdout [pid]
If you can't change the Tcl script, you can use a shell script trick to wrap it in something that writes the value:
#!/bin/sh
echo $$
# exec, in bash, *replaces* the process implementation with another program
exec tclsh "$#"
Say I have a current running process known, how can I turn this into a Process object in Java?
The process is already running, so I don't want to spawn off another one, I just want to encapsulate it into a Process object that I can use within the java code.
Something along the lines of:
int pid = getPid();
Process proc = magicGetProcess(pid);
thanks
I don't think this is possible using only the builtin library. AFAIK, it is already non-trivial to get the running process' own PID (see the feature request and alternate mechanisms).
A quick look at the java.lang.Process class shows that you could go about writing your custom implementation of java.lang.Process using JNI and native code. Your custom class could then implement extra methods, such as the one in your question.
In *nix world grabbing exit code of a non-child process is not easy, because the exit code simply disappears together with the process as soon as the parent process has picked up the exit code of the child. You can attach to the running process using some tracing tool and pick up its exit code when the process dies. Most *nix OSes have command line tools which will let you do it (such as strace on Linux, truss on SunOS) in a non-intrusive way. However, you can only use them against your own processes or if you run as root. Another alternative is to configure audit subsystem of your OS to record exit codes of all processes.
You can't. Every operation in Process requires that the process is a child process. Not an arbitrary process.
what about using RMI? It it possible to pass a Process object to the Process which it is? Probably not, because Process is not Serializable
I'm executing a shell pipeline from a java program - it'll be something like
ProcessBuilder builder = new ProcessBuilder(
"sh", "-c", "program1 | program2 | program3");
builder.start();
In some cases this unit might need to be terminated. However
process.destroy();
Will only destroy the "sh" command. The commands in the pipline will be orphaned and adopted by the init process.
Is there any way to easily terminate all these child processes - or execute a pipeline like the above in a way that makes it easier to terminate them . Altering progam 1/2/3 can't be done. Portability beyond linux is not a issue.
There's two ways I can think to do this:
You could run a pkill program1 program2 program3
You could write a intermediate program which launches the whole bash command line, this intermediate program would install a signal handler which kills it's own children when it gets a STOP signal.
Instead of running the pipeline in the shell, build the pipeline in java.
You'll need three process builders then (one for program1, one for program2, and ... one for program3 :D), and some threads to transfer the output from each process' output stream to the input stream of the next process.
This way you get j.l.Process instances for each of the childs, and can call destroy() on those.
Create a wrapper program in C that (a) launches the rest of the pipe, and (b) handles some signals by killing all the participants in the pipe before calling exit(2) itself.
I would like some help understanding and implementing a 'wait until process complete' between the various processes in my application, which need to proceed in a step-wise fashion. My java file runs a batch file which then runs a script. At the conclusion of this there are series of commands that I need to run (through the command line) in a consecutive manner. I'm using:
Runtime.getRuntime().exec("cmd /c start " + command)
to run my batch files and commands (not sure if that information is relevant). Right now what is happening is that the second step that needs to occur in my application is executing before the first step (running the batch file which runs a script) has completed. I need the first step to conclude before running the next series of commands. I really hope I'm making sense!
exec() returns an instance of Process, on which you can do waitFor().
Watch out though: I think "start" will actually spawn off a separate Windows process, so waitFor() may return before the command has finished. Try removing "start" from the command line?
Easy:
just call the method waitFor() of your Process instance.
It will stop the thread until the external process is terminated;
Could you put that series of commands into its own batch file?
Otherwise, you could use ProcessBuilder to get a Process object, and call waitFor() on it:
causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
EDIT: Actually, exec() returns a Process, so you don't need to bother with the ProcessBuilder part at all.