Check if process is running on windows/linux - java

i have a process
Runtime rt = Runtime.getRuntime() ;
Process p = rt.exec(filebase+port+"/hlds.exe +ip "+ip+" +maxplayers "+players+ " -game cstrike -console +port "+port+" -nojoy -noipx -heapsize 250000 +map de_dust2 +servercfgfile server.cfg +lservercfgfile +mapcyclefile mapcycle.txt +motdfile motd.txt +logsdir logs -zone 2048",null, new File(filebase+port)) ;
i want to keep a check on this process whether its running or has crashed in case of crash want to restart it, this Process can have multiple instance available depending upon the port
Can i trace this thing on Linux as well as on windows? Read some articles on it but this 1 is bit different, since it involves multiple occurrences and have to check on some particular process only

boolean isRunning(Process process) {
try {
process.exitValue();
return false;
} catch (Exception e) {
return true;
}
}
See http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html#exitValue()

You can do a p.waitFor() so the thread that executed the statement waits till the process is complete. You can then do the cleanup/restart logic right after, as that code will get executed when the process dies. However I am not sure how this would work if the process hangs instead of dying, but this could be worth a try. By the way I would recommend using Java Service Wrapper and supervisord in your case if this is something you're going to do on production.

As of Java 8 you can do:
process.isAlive()

For pre Java 8 code, I'm using reflection with a fallback to catching IllegalThreadStateException. The reflection will only work on instances of ProcessImpl, but as that's what's returned by ProcessBuilder it's usually the case for me.
public static boolean isProcessIsAlive(#Nullable Process process) {
if (process == null) {
return false;
}
// XXX replace with Process.isAlive() in Java 8
try {
Field field;
field = process.getClass().getDeclaredField("handle");
field.setAccessible(true);
long handle = (long) field.get(process);
field = process.getClass().getDeclaredField("STILL_ACTIVE");
field.setAccessible(true);
int stillActive = (int) field.get(process);
Method method;
method = process.getClass().getDeclaredMethod("getExitCodeProcess", long.class);
method.setAccessible(true);
int exitCode = (int) method.invoke(process, handle);
return exitCode == stillActive;
} catch (Exception e) {
// Reflection failed, use the backup solution
}
try {
process.exitValue();
return false;
} catch (IllegalThreadStateException e) {
return true;
}
}

Java 5 and on have a way to handle this using java.util.concurrent.Future.
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future and return null as a result of the underlying task.

public class ProcessEndNotifier extends Thread
{
Process process;
MyClass classThatNeedsToBeNotified;
public ProcessEndNotifier(MyClass classThatNeedsToBeNotified, Process process)
{
this.process = process;
this.classThatNeedsToBeNotified = classThatNeedsToBeNotified;
}
#Override
public void run()
{
try {
process.waitFor();
}
catch (InterruptedException e) {
classThatNeedsToBeNotified.processEnded();
}
classThatNeedsToBeNotified.processEnded();
}
}
Now you can know if a process in running like this:
public class MyClass
{
boolean isProcessRunning;
public static void main(String[]args)
{
Process process = Runtime.getRuntime().exec("foo -bar");
isProcessRunning = true;
new ProcessEndNotifier(this, process).run();
}
public void processEnded()
{
isProcessRunning = false;
// Or just do stuff here!
}
}

In java 9, you can use the isAlive() method to check if a process is stil running like this:
Runtime rt = Runtime.getRuntime() ;
Process p = rt.exec(filebase+port+"/hlds.exe +ip "+ip+" +maxplayers "+players+ " -game cstrike -console +port "+port+" -nojoy -noipx -heapsize 250000 +map de_dust2 +servercfgfile server.cfg +lservercfgfile +mapcyclefile mapcycle.txt +motdfile motd.txt +logsdir logs -zone 2048",null, new File(filebase+port)) ;
boolean isRunning = p.toHandle.isAlive();

Related

How to get the output from a process and set a timeout?

How can I obtain a process' output while setting a timeout value?
I am currently using Apache Commons IO utils to create a string from the process' standard and error outputs.
The code below, as is (with the comments), works fine for processes that terminate. However, if the process doesn't terminate, the main thread doesn't terminate either!
If I uncomment out the commented code and instead comment out process.waitfor(), the method will properly destroy non terminating processes. However, for terminating processes, the output isn't properly obtained. It appears that once waitFor is completed, I cannot get the process' input and error streams?
Finally, if I attempt to move the commented section to where process.waitFor() currently is, remove process.waitFor() and uncomment the commented section, then for non terminating processes, the main thread also won't stop. This is because the process.waitFor(15, ...) will never be reached.
private static Outputs runProcess(String command) throws Exception {
Process process = Runtime.getRuntime().exec(command);
// if (!process.waitFor(15, TimeUnit.SECONDS)) {
// System.out.println("Destroy");
// process.destroy();
// }
// Run and collect the results from the standard output and error output
String stdStr = IOUtils.toString(process.getInputStream());
String errStr = IOUtils.toString(process.getErrorStream());
process.waitFor();
return new Outputs(stdStr, errStr);
}
As #EJP suggested, You can use different threads to capture the streams or use ProcessBuilder or redirect to a file from your command.
Here are 3 approaches that I feel you can use.
Using different threads for Streams.
Process process = Runtime.getRuntime().exec("cat ");
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
Future<String> output = newFixedThreadPool.submit(() -> {
return IOUtils.toString(process.getInputStream());
});
Future<String> error = newFixedThreadPool.submit(() -> {
return IOUtils.toString(process.getErrorStream());
});
newFixedThreadPool.shutdown();
// process.waitFor();
if (!process.waitFor(3, TimeUnit.SECONDS)) {
System.out.println("Destroy");
process.destroy();
}
System.out.println(output.get());
System.out.println(error.get());
Using ProcessBuilder
ProcessBuilder processBuilder = new ProcessBuilder("cat")
.redirectError(new File("error"))
.redirectOutput(new File("output"));
Process process = processBuilder.start();
// process.waitFor();
if (!process.waitFor(3, TimeUnit.SECONDS)) {
System.out.println("Destroy");
process.destroy();
}
System.out.println(FileUtils.readFileToString(new File("output")));
System.out.println(FileUtils.readFileToString(new File("error")));
Use a redirection operator in your command to redirect Output & Error to a file and then Read from File.
Here is very good blog which explains different ways of handling Runtime.Exec
This is a slightly adjusted version of Kishore Bandi's first solution which uses separate thread to capture output.
It has been simplified, uses no external libraries and have more robust termination code.
Process process = new ProcessBuilder("cat", "file.txt")
.redirectErrorStream(true)
.start();
System.out.println("Output: " + waitForOuput(process, Duration.ofSeconds(10)));
/**
* Waits {#code timeout} time for the output of
* {#code process.getInputStream()}. Returns when the process is terminated.
* Throws on non-zero exit value.
*/
public static String waitForOuput(Process process, Duration timeout) throws InterruptedException, TimeoutException {
ExecutorService pool = Executors.newFixedThreadPool(1);
Future<String> outputFuture = pool.submit(() -> new String(process.getInputStream().readAllBytes()));
pool.shutdown();
try {
String output = outputFuture.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
if (process.exitValue() != 0) {
throw new IllegalStateException("Command " + process.info().command()
+ " returned exit value " + process.exitValue());
}
return output;
} catch (ExecutionException | TimeoutException | InterruptedException ex) {
process.destroyForcibly();
outputFuture.cancel(true);
process.waitFor(1, TimeUnit.SECONDS); // Give process time to die
if (ex instanceof InterruptedException intEx) {
throw intEx;
} else if (ex instanceof TimeoutException timeEx) {
throw timeEx;
} else {
throw new IllegalStateException(ex);
}
}
}

Print Message after successfully compilation

I have a simple JAVA code it will just print hello after compile and Run the Program. But I want to print one message after successful completion. Is this possible? If yes than how?
Although, the following code snippet is way too overkill for your task but, expanding on my comment - you may want to submit a custom task to a class
which implements Callable.
public class Main {
public static void main(String[] args) {
final ExecutorService executorService;
final Future<Integer> future;
final int statusCode;
executorService = Executors.newFixedThreadPool(1);
future = executorService.submit(new TextMessagePrinter());
try {
statusCode = future.get();
if (statusCode == 10) { // Printed successfully
System.out.println("JOB DONE. EXITING...");
Runtime.getRuntime().exit(0); // A zero status code indicates normal termination.
} else {
System.out.println("ERR...SOMETHING WEIRD HAPPENED!");
Runtime.getRuntime().exit(statusCode); // A non-zero status code indicates abnormal termination.
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdownNow();
}
}
}
class TextMessagePrinter implements Callable<Integer> {
public Integer call() {
Integer STATUS_CODE;
try {
System.out.println("Printing hello..."); // Try printing something
System.out.println("Dividing 6 by 0 gives us: " + 6 / 0); // And then you try to do something knowing which will result in an exception
STATUS_CODE = 10; // Indicates success.
} catch (ArithmeticException e) {
STATUS_CODE = 20; // Indicates failure...setting status code to 20.
}
return STATUS_CODE;
}
}
Running the above code on my IDE gives me the following output:
When the exception happens
(Note the status code set in the catch block getting printed when the process finishes):
No exception happens, everything happens fine:
(Comment the following line)
System.out.println("Dividing 6 by 0 gives us: " + 6 / 0);
If you mean completion of the application's Runtime, I think you are looking for the answer in this StackOverflow question: Java Runtime Shutdown Hook.
Or if you want to do what is in the question title and do something after building, then you may consider a build automation tool, like Maven.

java code to wait for parallel code to finish

I m having a server code to process an image.
Now there are n number of requests which tries to execute the code which results in OutOfMemory error or the server to hang and the server goes to not responding state.
To stop the code from executing at once all the requests I m limiting to execute the code one at a time using the below method where i have a variable
if the variable is 10 then wait for the variable to come at 0
if at 0 then set it to 10 then execute the code
run the code and finally set i to 0
The code here -
static newa.Counter cn;
public int getCounta() {
return cn.getCount();
}
public void setCounta(int i) {
cn = new newa.Counter();
cn.setCount(i);
}
at the function i m doing this -
public BufferedImage getScaledImage(byte[] imageBytes)
{
int i=0;
Boolean b = false;
BufferedImage scaledImage = null;
newa.NewClass1 sc = new newa.NewClass1();
try {
sc.getCounta();
} catch (NullPointerException ne) {
sc.setCounta(0);
}
i = sc.getCounta();
if(i==0)
{
sc.setCounta(10);
b = true;
}
else
{
while( b == false)
{
try
{
Thread.sleep(2000);
i = sc.getCounta();
if( i==0)
{
sc.setCounta(10);
b = true;
System.out.println("Out of Loop");
}
} catch (InterruptedException ex) {
System.out.println("getScaledImage Thread exception: " + ex);
}
}
}
..... execute further code
try { } catch { } finally { sc.setCounta(0); }
}
Is there any way I can have this simplified using the Runnable interface or something as I don't know how to do multi-threading.
Forget about the counter and use a synchronized method. Changed your method head to this:
public synchronized BufferedImage getScaledImage(byte[] imageBytes)
This lets all the threads entering the method wait until no other thread is executing the method.
If you want only a small number of threads doing the processing you can use Executor framework to have a thread pool of 10 threads. This will ensure that at one time maximum of 10 threads will be processing the requests.

java - how to kill a Process if it exceeds an alloted time

I am wondering what the best way is to detect/kill a process if it exceeds a predefined time. I know an old way was to use the watchdog/timeoutobserver class from the ant package. But this is deprecated now, so I am wondering how it should be done now?
Here is the code I have which uses watchdog:
import org.apache.tools.ant.util.Watchdog;
import org.apache.tools.ant.util.TimeoutObserver;
public class executer implements TimeoutObserver {
private int timeOut = 0;
Process process = null;
private boolean killedByTimeout =false;
public executer(int to) {
timeOut = t;
}
public String executeCommand() throws Exception {
Watchdog watchDog = null;
String templine = null;
StringBuffer outputTrace = new StringBuffer();
StringBuffer errorTrace = new StringBuffer();
Runtime runtime = Runtime.getRuntime();
try {
//instantiate a new watch dog to kill the process
//if exceeds beyond the time
watchDog = new Watchdog(getTimeout());
watchDog.addTimeoutObserver(this);
watchDog.start();
process = runtime.exec(command);
//... Code to do the execution .....
InputStream inputStream = process.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
while (((templine = bufferedReader.readLine()) != null) && (!processWasKilledByTimeout)) {
outputTrace.append(templine);
outputTrace.append("\n");
}
this.setStandardOut(outputTrace);
int returnCode = process.waitFor();
//Set the return code
this.setReturnCode(returnCode);
if (processWasKilledByTimeout) {
//As process was killed by timeout just throw an exception
throw new InterruptedException("Process was killed before the waitFor was reached.");
}
} finally {
// stop the watchdog as no longer needed.
if (aWatchDog != null) {
aWatchDog.stop();
}
try {
// close buffered readers etc
} catch Exception() {
}
//Destroy process
// Process.destroy() sends a SIGTERM to the process. The default action
// when SIGTERM is received is to terminate, but any process is free to
// ignore the signal or catch it and respond differently.
//
// Also, the process started by Java might have created additional
// processes that don't receive the signal at all.
if(process != null) {
process.destroy();
}
}
public void timeoutOccured(Watchdog arg0) {
killedByTimeout = true;
if (process != null){
process.destroy();
}
arg0.stop();
}
}
}
Any help would be greatly appreciated as I am a bit lost. I am trying to take this up to Java 7, but I am not uptodate with the best way to kill it if it hangs beyond the alloted time.
Thanks,
try
final Process p = ...
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(1000);
p.destroy();
} catch (InterruptedException e) {
}
};
};
p.waitFor();
t.interrupt();
Theoretically Thread has method stop() that totally kills the thread. This method is deprecated since java 1.1 because it may cause resources leak. So, you are really not recommended to use it.
The "right" solution is to implement your thread so that they can gracefully exit when receiving a special "signal". You can use "interruption" mechanism: your watchdog should call "interrupt()" of thread that exceeds the time limit. But thread should call isInterrupted() itself and exit if it is interrupted. The good news is that method like sleep() and wait() already support this, so if your thread is waiting and you interrupt it from outside it InterruptedException will be thrown.
I have written a set of ExecutorServices that will cancel processes after they have been given a certain period of time to execute. This code has been checked into GitHub.
The class to use to create the ExecutorService is CancelingExecutors. There are two main classes:
CancelingListeningExecutorService allows you to specify the timeout for each passed Callable
FixedTimeoutCancelingListeningExecutorService is configured to use a single timeout for all Callables
If you just concern about WatchDog itself is deprecated, it is nothing more difficult for you to make use of TimerTask, and do the process.destroy() after a period of time.

How to redirect child process stdout/stderr to the main process stdout/stderr in Java?

In other languages (like bash and Python), when we spawn a child process, this new process will inherit the stdout and stderr from the parent. This means that any output from the child process will be printed to the terminal as well as the output from the parent.
How can we achieve the same behavior in Java?
My first try was:
proc = Runtime.getRuntime().exec(cmd);
But it won't work. Based on this answer and this answer, I've replaced the code with:
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectOutput(System.out);
pb.redirectError(System.err);
But this doesn't even compile, as the arguments are incompatible with the expected method parameters.
You need to read the output and error streams of the process you've created and write the output to where you want it to go (in your case System.out and System.err).
Edit. The above answer is correct for java < 7. As of 7 from the javadoc it looks to be possible to instead call
processBuilder.redirectOutput(Redirect.INHERIT)
This isn't too bad. I initially said "easy", then I realized I'd had to code the InputStreamConsumer:
public static class InputStreamConsumer extends Thread {
private InputStream is;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
int value = -1;
while ((value = is.read()) != -1) {
System.out.print((char)value);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
private void captureOutput(Process p) {
InputStreamConsumer stdout;
InputStreamConsumer errout;
errout = new InputStreamConsumer(p.getErrorStream());
stdout = new InputStreamConsumer(p.getInputStream());
errout.start();
stdout.start();
}
....running inside of something like ...
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/D", "/C", myCommand, parm, parm...);
try {
System.out.println("Start "+myCommand);
Process myProcess = pb.start();
captureOutput(myProcess);
int returnCode = myProcess.waitFor();
System.out.println("myProcess: return code : "+returnCode);
}
catch (IOException e) {
e.printStackTrace();
}
It's certainly possible. The Ant Java task does this when fork is set true. I don't remember all the details, but on a quick look it appears that most of the magic is in PumpStreamHandler. You might try finding some inspiration from that.

Categories

Resources