如果罐子已经运行,防止罐子运行?

时间:2012-12-13 14:00:45

标签: java jvm locking

  

可能重复:
  java/shellscript code to find out if a jar file is already running on current machine

我很想获得一个跨平台的解决方案,但即使它只是unix,那也没关系。

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

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

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

一点例子:

Myprog.jar - 超时5分钟

Myprog.jar是一个每4分钟调用一次的cron,

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

如果在第三次检查结束时它仍在运行(执行后8分钟),它就会被杀死,之后它的过程会自动替换。

如果有人可以帮我理解如何做到这一点(我们一直试图设置一个锁定文件但成效有限)

谢谢!

4 个答案:

答案 0 :(得分:3)

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

当你现在启动你的程序的第二个实例时,它也会尝试打开这个文件进行写入,这将抛出IOException,因为只有一个进程可以同时拥有一个文件的写句柄时间。

答案 1 :(得分:2)

您可以将端口用作信号量。有关详细信息,请参阅this question。我认为端口将是一个很好的跨平台解决方案

答案 2 :(得分: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);
         }
    });
}

答案 3 :(得分:1)

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

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

具有固定端口号的ServerSocket方法将允许您为每台计算机一个实例(可能不完全符合您的要求)。

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

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