Gwt process id which run using runtime.getExec("<tcl file>") function - java

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 "$#"

Related

Exit java program to linux command

I'm making a little tool that handles a sort of exotic device, with lots of options to manage it etc. One of them would be to scan for tty ports, find the right one then throw the user to "minicom" with some parameters for example.
How can I make java completely exit while running a specific command, under certain condition, after such exit ?
Initial thoughts would be to use a bash script, scan the return value, communicate via files etc.A fully functional interactive serial console in Java would be the dream, but the ones I try right now can't seem to even find tty ports now.
Most processes on linux follow a call stack where process A calls process B which calls process C.
Wen process C terminates, the control goes back to process B, and so on.
It sounds like in this case you want java to call minimum, but when java is finished, return to the parent shell.
I am not aware of any way you can terminate a JVM upon a call to another process (returning to the JVM's parent when it terminates). Perhaps with some clever C calls using JNI, but that isn't really java anymore and could create new problems.
You could have the JVM wrap the target process and pass through the user inputs and outputs. Alternatively, use file communication, e.g. the java program writes the command-line to a file, that the parent bash script executes after the JVM terminates, but that is a bit of a kludge.

Java process on Mac OSX seems to "hang" when invoked via webserver, but OK from the commandline

I have a very strange situation where a Java process seems to hang when called via Apache/PHP, but OK when invoked from the command line. I spent hours debugging this, no avail. Any and all thoughts welcome!
Situation: I have a .class file (without the original Java code) that reads an input file, processes the read information, and writes a report on stdout. The Java code doesn't read stdin, and only writes stdout. I wrapped this in a tiny Perl script that basically just execs "java -cp /path/to/classfile MyJavaProgram /path/to/inputfile/to/process". That way I can invoke it from the command line for testing, this works like a charm. Next, I try to invoke this from PHP using popen(), and there Java just hangs. I see the Perl process in the ps list, and Java; but the Java process waits forever. Once I kill it, the webserver page continues loading (but of course without the expected output that the Java process would generate).
What I tried so far:
Wrapping the Java process in a shell script, same behaviour. Java just hangs.
Running it from PHP with popen() without a wrapper, same behaviour.
Starting it from PHP with system() or passthru(), same behaviour.
In the Perl wrapper, reopening STDIN for /dev/null (so that reading stdin immediately returns EOF), same behaviour.
In the Perl wrapper, reopening STDERR for /dev/null, same behaviour.
In the Perl wrapper, reopening STDOUT for /dev/null. Here I would expect no output (as it gets discarded) but still the Java process just hangs.
In the Perl wrapper, reopening all 3 streams for /dev/null. Java still hangs.
Replacing the Java invocation in the Perl wrapper with a simple "ls -l /bin". This works as expected; the web page gets populated with the "ls" listing. So the problem isn't in PHP or Perl.
Starting the Java process with a "/bin/sh -c 'java .....'". Same behaviour, Java hangs.
In the Perl wrapper, I dump the environment variables too, to check them. Environment seems OK.
When the Java process is running, I look up the Perl wrapper invocation in the ps list, and copy/paste it to the command line. Works like a charm.
Similarly, when the Java process is hanging, I look up the invocation in the ps list, and copy/paste it to the command line. Works like a charm.
I also verified that the the input file is readable when invoked from the web server. All above tests with the command line were run using the same user ID as the Apache user.
Unfortunately I can't replace the Java code with something that's under my control. I only have the .class file to work with. What I haven't tried yet is to run this under Linux, so this still might be an OSX specific issue (which would surprise me).
What the hell is going on here? Any and all "wild" ideas appreciated.. thanks!
Check ALL environment from apache AND from cmd line, including the paths, UIDs etc.
Also check what the java process does when hanging (use truss/tusc/strace -f java xxxxxxxxxxx 2>/tmp/trace.$$ ) when wrapping it from both places (apache and cmdline), then compare the results.
Also, when wrapping from perl, set autoflush to 1 for stdin, stdout, stderr before exec-ing java.

Is it possible to execute windows commands in Java in a "batch" manner? ie One after the other but kept persistent?

I'm looking to create a Java Application that is able to run windows commands in a "batch" manner; what I mean by this is that it's persistent in between commands and isn't as if you're only executing one at a time.
An example of this might be:
#echo off
pushd C:\foldertobepushedto\
call batchfiletobecalled.bat
popd
pushd anotherdirectorytobepushedinto
call anotherbatchfiletobecalled.bat
popd
I would like to be able to use the Process process = Runtime.getRuntime().exec(CMD); manner to be able to run each of these lines but kept persistent so that it's not as if each line is run completely separate from the rest of them.
I hope I am making a bit of sense; I intend to essentially remove the use of batch files all together and store each line as an element in a vector/array and execute them "batch" style that way.
Excuse me. I know a way to solve this problem in JScript; I ignore if there is an equivalent method for Java.
You may achieve the desired effect you want if you:
Execute CMD.EXE file alone with NO parameters, but via WshShell.Exec method:
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("cmd");
WshShell.Exec method provide access to the process standard I/O channels.
After that, send to the process' STDIN channel the commands you want to execute:
oExec.Stdin.WriteLine("#echo off");
oExec.Stdin.WriteLine("pushd C:\foldertobepushedto\");
oExec.Stdin.WriteLine("call batchfiletobecalled.bat");
oExec.Stdin.WriteLine("popd");
oExec.Stdin.WriteLine("exit");
This way, all commands will be executed in a way entirely equivalent as if they would be included in a Batch file. The only difference is that certain commands will not be correctly executed, like GOTO.

Graceful kill of Apache Commons Exec process

I am starting an external process in my Java program (on Linux) and I need the ability to send it a SIGTERM signal rather than the SIGKILL that exec.getWatchdog().destroyProcess() is sending. Is there a way that I can more gracefully stop a unix process started with commons-exec? Or can I get the PID so that I can just run the appropriate kill command myself?
ExecuteWatchdog class has method for killing process.
So, you could just create a watchdog with long timeout and use it to kill process when neccessary, i.e.
executor.getWatchdog().destroyProcess();
Well, Commons Exec relies on the Java Process class, which doesn't expose a PID. It's also what is used to kill the process, so it's not something you can change the behavior of. All nice and encapsulated. Gotta love OO, eh?
If you are simply launching processes in to the background, you can wrap them in a simple shell script that captures the PID for you, and then saves that off to a "known place" that your Java routine knows about. Still kind of messy, and, naturally, it doesn't port to other platforms well.
You can write your own exec function using JNI to capture this information for you as well, but that's likely less friendly.
You could write a platform specific exec launcher daemon in something more system oriented (C, Python, etc.). You send IT messages to launch and stop things, and it handles that process for you. One benefit of this is that you don't have to fork the JVM when you run a new process (which can be quite expensive depending on your JVM size).
You can start the daemon up at the beginning and share a socket or a pipe (both pretty portable). That's actually not a horribly INelegant solution, and it compartmentalizes a lot of system specific behavior (so you can have a completely different process on, say, Windows vs Unix and your Java stays the same, you just need to port your little daemon), without having to run JNI.
Well you could grep it, for ex :
for i in $(ps -ef | grep -i "[Y]ourClassName" | awk '{print $2}'); do kill -9 $i; done
This is in case that you have it running more than 1 time(although it works if you have just one project), notice the [] in grep, that is so the grep doesn't give you its own process pid and -i stands for ignore case, awk is for printing second column only that is PID number.

Java: Get a process given a pid

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

Categories

Resources