I'm currently building an application in JAVA where there can be only one execution. So I'm currently using a lock file in which I write the PID of the current execution.
So whenever this application will start, it will open the file (if it exists) and try to detect if the PID written in the file is actually running.
This prevent the problem where my app crash before unlocking the file.
I need this to work both on windows (XP,7 or 8) and linux (all the users are on debian based distros).
Here's some code to give you a better picture of what I want to do :
//get the PID from the file
int pidValue = new FileReader(file).read();
//get the OS type
String os = System.getProperty("os.name").toLowerCase();
//Check PID depending of OS type
if( os.contains("nux") || os.contains("nix") ){
/*
* Check PID on Linux/Unix
*/
} else if ( os.contains("win") ) {
/*
* Check PID on Windows
*/
}
I have tried to find documentation on the subject, but I didn't manage to find anything useful yet.
Thank you very much.
The easiest way to find out if process is running is run ps aux command and grep process name. If you got output along with process name/pid, your process is running.
If you want to check the work of java application, run 'ps' command with '-ef' options, that will show you not only the command, time and PID of all the running processes, but also the full listing, which contains necessary information about the file that is being executed and program parameters.
You'll usually find the PID files for daemonized processes in /var/run/ on Redhat/CentOS-style systems. Short of that, you can always look in the process init script. For instance, the SSH daemon is started with the script in /etc/init. d/sshd .
The following code determines if a process with the specified pid is running. It was tested on Windows 7 and Ubuntu 13. On Windows it uses apache commons-exec to run tasklist and determines if they found the specified pid based on their exit code. It overcomes the fact that tasklist always returns 0 by piping the result to findstr. On linux it uses ps to do the same thing. It also suppresses stdout logging of the child process.
public static boolean isProcessRunning(int pid, int timeout, TimeUnit timeunit) throws java.io.IOException {
String line;
if (OS.isFamilyWindows()) {
//tasklist exit code is always 0. Parse output
//findstr exit code 0 if found pid, 1 if it doesn't
line = "cmd /c \"tasklist /FI \"PID eq " + pid + "\" | findstr " + pid + "\"";
}
else {
//ps exit code 0 if process exists, 1 if it doesn't
line = "ps -p " + pid;
//`-p` is POSIX/BSD-compliant, `--pid` isn't<ref>https://github.com/apache/storm/pull/296#discussion_r20535744</ref>
}
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
// disable logging of stdout/strderr
executor.setStreamHandler(new PumpStreamHandler(null, null, null));
// disable exception for valid exit values
executor.setExitValues(new int[]{0, 1});
// set timer for zombie process
ExecuteWatchdog timeoutWatchdog = new ExecuteWatchdog(timeunit.toMillis(timeout));
executor.setWatchdog(timeoutWatchdog);
int exitValue = executor.execute(cmdLine);
// 0 is the default exit code which means the process exists
return exitValue == 0;
}
Please see below ready to copy/paste example.
Boolean method isStillAllive(...) will get as a parameter the process id number(pid). Method call is quite generic and is meant to wrap device dependent logic to solve same problem on windows/linux/unix like operating systems.
public boolean isStillAllive(String pidStr) {
String OS = System.getProperty("os.name").toLowerCase();
String command = null;
if (OS.indexOf("win") >= 0) {
log.debug("Check alive Windows mode. Pid: [{}]", pidStr);
command = "cmd /c tasklist /FI \"PID eq " + pidStr + "\"";
} else if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0) {
log.debug("Check alive Linux/Unix mode. Pid: [{}]", pidStr);
command = "ps -p " + pidStr;
} else {
log.warn("Unsuported OS: Check alive for Pid: [{}] return false", pidStr);
return false;
}
return isProcessIdRunning(pidStr, command); // call generic implementation
}
Actual call to system is delegated to isProcessIdRunning(). This method will invoke preformed system dependent command in generic way and result obtained from system is consumed and parsed line by line. If at least one of response lines contains pid than we interpret this as success.
private boolean isProcessIdRunning(String pid, String command) {
log.debug("Command [{}]",command );
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);
InputStreamReader isReader = new InputStreamReader(pr.getInputStream());
BufferedReader bReader = new BufferedReader(isReader);
String strLine = null;
while ((strLine= bReader.readLine()) != null) {
if (strLine.contains(" " + pid + " ")) {
return true;
}
}
return false;
} catch (Exception ex) {
log.warn("Got exception using system command [{}].", command, ex);
return true;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With