4

可能重复:
java/shellscript 代码来确定 jar 文件是否已经在当前机器上运行

我很想为此获得一个跨平台的解决方案,但即使它只是 unix,也可以。

简单的解决方案是从 shell(伪代码)执行此操作(如果 ps -aux | grep myJar | print {awk 2}.contains myPID,请不要运行 myProgram。

现在不幸的是,我们的 linux 团队不希望这样的脚本在生产中运行,因为它可能(诚然)具有不良行为。

所以我需要的是能够运行一个文件,并在它运行时查看是否有另一个程序正在运行。如果程序已经在运行并且低于该时间限制,它应该阻止程序运行。

一个例子:

Myprog.jar -- 超时 5 分钟

Myprog.jar 位于每 4 分钟调用一次的 cron 中,

第一次调用它启动,第二次调用它仍在运行,但是由于它没有超过超时,所以很好。

如果在第三次检查通过时(在执行 8 分钟时)它仍在运行,它会被杀死,然后它的进程会被自己替换。

如果有人可以帮助我了解如何执行此操作(我们一直在尝试设置锁定文件,但成功有限)

谢谢!

4

4 回答 4

3

您可以让您的程序在程序启动时打开一个虚拟文件以使用FileWriter进行写入,并保持文件打开直到程序完成。

当您现在启动程序的第二个实例时,它还将尝试打开此文件进行写入,这将引发IOException,因为只有一个进程可以同时拥有一个文件的写入句柄。

于 2012-12-13T14:12:19.097 回答
2

您可以将端口用作信号量。有关更多信息,请参阅此问题。我认为移植将是一个很好的跨平台解决方案

于 2012-12-13T14:16:23.537 回答
1

您可以在固定位置创建临时文件。

private static final File LOCK_FILE = new File("app.lock");

public static boolean checkIfAlreadyRunning()
{
    return LOCK_FILE.exists();
}

public static void createLockFile()
{
    LOCK_FILE.createNewFile();
    Runnable shutDown = new Runnable()
    {
         public void run()
         {
             try
             {
                 LOCK_FILE.delete();
             } catch (Exception e) { /* Sad but true */ }
         }
    };

    Runtime.getRuntime().addShutdownHook(new Thread(shutDown));
    Thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
    {
         public void uncaughtException(Thread t, Exception e)
         {
              shutDown.run();
              System.exit(-1);
         }
    });
}
于 2012-12-13T14:55:47.587 回答
1

我遇到了完全相同的问题,解决起来可能非常棘手。基于文件和套接字的方法都可以工作,但它在某些操作系统上变得非常棘手(想想在多个终端服务器会话中具有多个用户的 Windows 等)。

首先,确定您只需要一个实例的范围。然后决定解决方案。

具有固定端口号的 ServerSocket 方法将允许您每台机器一个实例(可能不完全是您想要的)。

可以定制锁定文件方法以在用户临时目录中创建锁定文件,因此它为每个会话/用户提供一个实例。

我个人使用一种组合方法,其中锁定文件指定一个随机端口,第二个实例连接到该端口以将命令行参数传递给正在运行的实例。

于 2012-12-13T15:23:21.300 回答