我目前正在用JAVA构建一个应用程序,其中只能有一个执行。因此,我目前正在使用一个锁文件,在其中写入当前执行的PID。
因此,每当该应用程序启动时,它都会打开文件(如果存在的话),并尝试检测写入文件中的PID是否实际运行。
这可以防止我的应用程序在解锁文件之前崩溃的问题。
我需要在windows (XP、7或8)和linux (所有用户都是基于debian的发行版)上工作。
这里有一些代码可以让您更好地了解我想要做的事情:
//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
*/
}
我试图找到关于这一主题的文件,但我还没有找到任何有用的东西。
非常感谢。
发布于 2014-01-30 17:05:05
在posix系统中,查询pid是否正在运行的典型方法是向它发送空信号,例如kill(pid, 0)
。如果调用成功,则进程存在;如果它返回ESRCH
,则不存在。这自然会受到不可避免的种族状况的影响,而这些条件在现实中远远低于理论上的情况。不太统一的方式是读取/proc文件系统(如果操作系统有一个),这是更多的工作,相当于相同的东西,并仍然受到相同的竞争条件。
注意,pid锁文件技术可以是两层的.也就是说,正在运行的进程创建文件,锁定它,并写入它的pid。它在运行期间持有锁,因此,这基本上消除了查询进程是否正在运行的需要,因为如果进程崩溃,即使文件仍然存在,文件锁也会自动释放。逻辑是这样的:
if file exists
if can get lock
prev instance died unnaturally
continue with this new process
else
instance already running
else
good to go, continue with new process
这项技术也有比赛条件。
我不记得有足够的Java来说明它是否有用于kill
的包装器或实现此方案所需的文件锁定系统,如flock
、lockf
和fcntl
。
发布于 2014-10-17 11:04:18
下面的代码确定具有指定pid的进程是否正在运行。它在Windows 7和Ubuntu 13上进行了测试。在Windows上,它使用运行任务列表,并根据退出代码确定他们是否找到了指定的pid。它克服了tasklist总是通过将结果传递到findstr返回0的事实。在linux上,它使用ps来做同样的事情。它还会抑制子进程的stdout日志记录。
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;
}
发布于 2017-02-15 19:48:58
请参阅下面准备复制/粘贴示例。
布尔方法isStillAllive(.)将得到进程id号(Pid)作为参数。方法调用是非常通用的,它用于封装与设备相关的逻辑,以解决windows/linux/unix等操作系统上的相同问题。
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
}
对系统的实际调用委托给isProcessIdRunning()。该方法将以泛型的方式调用预编好的系统依赖命令,从系统中获得的结果将被消耗并逐行解析。如果至少有一个响应行包含pid,我们将其解释为成功。
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;
}
}
https://stackoverflow.com/questions/21460775
复制相似问题