Ok, so I have a couple of Java programs that I'm running using a chron job on a linux server. These jobs run every ten minutes or so, take literally two minutes to run, and then exit. I need to add a way for the programs to detect, when they start up, if there is already an instance of themselves running, and if so to exit without going any further. I'm really not sure of the best way to handle this though and am hoping someone can offer some advice.
One approach I've considered is to run a command line argument from the java code that does some sort of PS command and looks through those to see if it's running. This seems pretty finicky and complex though for something so small. Plus, I'm not all that knowledgeable with linux and am not even sure the best way to do that. If anyone has some better thoughts, please let me know. Or if that is the best way, if you could provide the linux commands I'd need I'd appreciate it. Thanks.
If you have a writable /tmp directory you can use a lockfile.
When your Java program starts up, check for a file with a name unique to your application (e.g. "my-lock-file.lock") in the /tmp directory. If none exists, create one, and remove it when you're done. If one exists, just exit.
You can check the existence of a file with the .exists() method of the java.io.File class.
If your code needs to be portable, you can use System.getProperty("java.io.tmpdir")); to get an appropriate temporary directory for the platform your code is running on.
You could look at JMX and the Attach API to query for running JVMs.
Or, as Andrew logvinov mentioned, by using a lock file.
If you are using Java WebStart, there's already native support for this.
Many programs solve this by creating a temporary file that points to their PID (often referred to as a "lock" file). The filename should encode all relevant information to distinguish this process from other processes that could legitimately run in parallel.
For example, if the process is bound to a user, it should contain the user name. If the process is bound to a machine, it should (also) contain the hostname (if you put it in machine-bound temp. directory, this is debatable. If you put it in a home directory, think of the case of multiple machines sharing a home via NFS).
The location of these files is typically /tmp. This is a great location, as /tmp is typically wiped during system boot, so no orphan files are left in case of a system crash. Another solution employed by some programs is to put the lock file in the user settings directory, if it is related to the settings. E.g. mozilla thunderbird has a file called /home/<username>/.thunderbird/<profilename>.default/lock.
The file should contain the PID of the process. The idea is simple: If the file contains the PID, it is easy to check whether this process is indeed still running. So if the process crashes, the file gets orphaned. The new process instance will check the PID in the file, see that it is not running any more, and ignore the file (overwrite).
Putting it all together, you could create a file like this:
/tmp/myawesomeservice-username-hostname-lock
With the content:
12345
Related
I have a Java application that needs to run several times. Every time it runs, it checks if there's data to process and if so, it processes the data.
I'm trying to figure out what's the best approach (performance, resource consumption, etc.) to do this:
1.- Launch it once, and if there's nothing to process make it sleep (All Java).
2.- Using a bash script to launch the Java app, and when it finishes, sleep (the script) and then relaunch the java app.
I was wondering if it is best to keep the Java app alive (sleeping) or relaunching every time.
It's hard to answer your question without the specific context. On the face of it, your questions sounds like it could be a premature optimization.
Generally, I suggest you do what's easier for you to do (and to maintain), unless you have good reasons not to. Here are some possible good reasons, pick the ones appropriate to your situation:
For sleeping in Java:
The check of whether there's new data is easier in Java
Starting the Java program takes time or other resources, for example if on startup, your program needs to load a bunch of data
Starting the Java process from bash is complex for some reason - maybe it requires you to fiddle with a bunch of environment variables, files or something else.
For re-launching the Java program from bash:
The check of whether there's new data is easier in bash
Getting the Java process to sleep is complex - maybe your Java process is a complex multi-threaded beast, and stopping, and then re-starting the various threads is complicated.
You need the memory in between Java jobs - killing the Java process entirely would free all of its memory.
I would not keep it alive.
Instead of it you can use some Job which runs at defined intervals you can use jenkins or you can use Windows scheduler and configure it to run every 5 minutes (as you wish).
Run a batch file with Windows task scheduler
And from your batch file you can do following:
javac JavaFileName.java // To Compile
java JavaFileName // to execute file
See here how to execute java file from cmd :
How do I run a Java program from the command line on Windows?
I personally would determine it, by the place where the application is working.
if it would be my personal computer, I would use second option with bash script (as resources on my local machine might change a lot, due to extensive use of some other programs and it can happen that at some point I might be running out of memory for example)
if it goes to cloud (amazon, google, whatever) I know exactly what kind of processes are running there (it should not change so dynamically comparing to my local PC) and long running java with some scheduler would be fine for me
Can I somehow check if another program reads a specified file?
I want my program to monitor a file, and whenever it is accessed by another program, it should run some code. Is this possible?
As some people have mentionned, Java new IO offers you to watch a directory/files for some activities :
ENTRY_CREATE – A directory entry is created.
ENTRY_DELETE – A directory entry is deleted.
ENTRY_MODIFY – A directory entry is modified.
OVERFLOW – Indicates that events might have been lost or discarded. You do not have to register for the OVERFLOW event to receive it.
However, as you can see, it does not allow you to detect if the file has been accessed. If really you want to do that, you will have to write some native code.
On windows, you can list who access a file using Handle. I believe you could call this command from a java program (let say each couple of minutes) then from the output detect if the file is used.
I'm pretty sure there is alternative for other OS.
BasicFileAttributes interface offers last access time. But it wont be able to tell you which program accessed it. As mentioned by others WatchService will also do the same but what you want to do can be achieved via logging from those programs and then check those logs for determining what to do next.
I need to programmatically edit, write or delete protected files. In Windows, if i do it manually, it asks for permission and in Unix systems i need "sudo".
How can I ask in Java for higher privileges during execution?
If your program requires high level access it is best to advise the user that they need to run it as root / a privileged account in order to work.
Otherwise the best option is to start a new 'proxy process' that is initialised using "sudo" and then a program doing what you want, eg "sudo cp File1 File2" that will perform your dirty work for you.
Unfortunately this is not cross platform and requires the users password.
There is simply no way you can just bump the JVM to a higher user during execution as this would pose a huge security risk.
md_5
Because Java works using a virtual machine, you can't just start (for example) another thread in an elevated mode. Instead, you'll need to launch an entirely new VM, which you won't be able to connect to.
I'd look into ways of executing a separate Java process which can run with elevated permissions. You can still use the same code, but have it be a main method.
You won't be able to just raise your privillages.
I might be entirely wrong, and am happy to be shown otherwise.
lsof is a nice tool for Unix, showing all currently open file handles.
Does anyone know a similar tool that would show all open files inside a running JVM (via JVMTI or any similar interface)?
In this particular case, it would be sufficient for me to know which class has a handle open. Method/line or even an entire chain to GC root would be fantastic, but handler owner class is already a good start.
I know I could make a heap dump, open it in a profiler and find this out, but this is a tedious task, especially for the big heaps.
The JVMTI option sounds like it wouldn't be a bad choice. The big issue would be ensuring you wrap everything that may open a file handle: you would basically have to go through the JDK source code and find every native function that did a file open (littered throughout java.io., java.nio., I'd think java.net.* as well if you consider sockets as file handles, and just about everywhere else that a file handle may be opened by a native function) and then wrap them all with the SetNativeMethodPrefix call.
I'm assuming that is what some of the profiling folks do: however if you're not required to do this listing in real time then I'd think it would be WAY easier to use lsof or handle (on Windows platforms) and filter for your JVM's process id.
I'm writing a Maven plugin that deletes and renames various files using the File.delete() and File.renameTo(File) JDK methods.
Roughly every second time I run the plugin, one of these operations fails, and each time it fails it's a different file that cannot be deleted or renamed. An obvious explanation for why a file cannot be deleted is that another process is using it (I'm running on Windows), but I've no idea which process might be responsible. The fact that the problem cannot be reproduced consistently suggests a threading issue, but AFAIK, Maven plugins are run in a single thread. It's difficult to get any information about the cause of the problem, because the methods referred to above don't throw exceptions, they just return false.
Is there a way to programatically detect a locked file and the name of the process holding the lock? Alternatively, if anyone has other suggestion about how to go about debugging a problem such as this one, please send them on.
Thanks,
Don
Handle can let you find out what processes have handles on files.
Sample output (it's a command line utility):
C:\Users\Jon\Downloads\Handle>handle Test.cs
Handle v3.42
Copyright (C) 1997-2008 Mark Russinovich
Sysinternals - www.sysinternals.com
Test.exe pid: 6088 190: C:\Users\Jon\Test\Test.cs