4

Possible Duplicate:
java/shellscript code to find out if a jar file is already running on current machine

I would love to get a cross-platform solution for this, but even if it's unix only- that would be fine.

The simple solution would be to do this from the shell (Pseudocode)(if ps -aux | grep myJar | print {awk 2}.contains myPID, don't run myProgram.

Now unfortunately our linux team doesn't want a script like that running in production since it can (admittedly) have undesired behaviors.

So what I need is to be able to have a file run, and when it runs see if another program is running. If the program is already running and it's below that time limit, it should prevent the program from running.

A bit of an example:

Myprog.jar -- timeout 5 min

Myprog.jar is in a cron that gets called every 4 minutes,

the first time it's called it launches, the second time it's called it's still running, but since it's not over the timeout, it's fine.

If it's still running when the third check comes through (at 8 minutes into execution) it's killed, and its process is replaced by itself afterwards.

If someone can help me understand how to do this (We've been trying to set up a lock file with limited success)

Thanks!

Community
  • 1
  • 1
A_Elric
  • 3,508
  • 13
  • 52
  • 85
  • Hmm, similar to http://stackoverflow.com/questions/13857979/java-shellscript-code-to-find-out-if-a-jar-file-is-already-running-on-current-ma – Qwerky Dec 13 '12 at 14:04

4 Answers4

3

You could make your program open a dummy file for writing with a FileWriter when your program starts, and keep the file open until the program is finished.

When you now start a second instance of your program, it will also try to open this file for writing, which will throw an IOException, because only one process can have a write handle to a file at the same time.

Philipp
  • 67,764
  • 9
  • 118
  • 153
2

You could use a port as a semaphore. See this question for more info on that. I think a port would be a good cross-platform solution

Community
  • 1
  • 1
Chris Gerken
  • 16,221
  • 6
  • 44
  • 59
  • 1
    +1: I like the idea, but at the same time, it doesn't feel clean. Creating a server on a random chosen port, without using it. – Martijn Courteaux Dec 13 '12 at 14:18
  • @MartijnCourteaux - agree, but you'd have to choose some resource I think and you want that resource to have the same id (e.g. port number) on all platforms. – Chris Gerken Dec 13 '12 at 14:28
  • Do you know of another solution that might be more viable for unix only? – A_Elric Dec 13 '12 at 14:35
1

You can create a temporary file on a fixed location.

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);
         }
    });
}
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • 1
    So this causes me to be concerned for a few reasons. 1. What happens if that exception is thrown? The lock file isn't deleted and then the process can't run anymore? 2. This doesn't seem to have the ability to kill rogue processes. – A_Elric Dec 13 '12 at 14:59
  • I know. I'm not a huge fan of the code I provided, but currently I can't think of anything better, than the ServerSocket approach. I added an UncaughtExceptionHandler. – Martijn Courteaux Dec 13 '12 at 15:06
  • I appreciate your trying for sure. I mean we have control over the server so I could take the socket approach if need be, your idea closer mimics what were trying to get working now. – A_Elric Dec 13 '12 at 15:08
1

I had exactly the same problem, and it can be pretty tricky to solve. Both File and Socket based approaches can be made to work, but it gets really tricky on some OS's (think of Windows with multiple users in multiple terminal server sessions etc.).

First, determine the scope where you want only one instance. Then decide on a solution.

The ServerSocket method with a fixed port number will allow you one instance per machine (maybe not exactly what you want).

The locking file approach can be tailored to create the locking file in the users temp directoy, so it gives one instance per session/user.

I personally use a combined approach where the locking file specifies a random port and a second instance connects to that port to pass command line parameter to the running instance.

Durandal
  • 19,919
  • 4
  • 36
  • 70