Having a file open is not a lock because, if each process has to check whether the file is open first and not proceed if it is or create/open it if it isn't, then two processes could quite well check simultaneously, both find that it isn't open, then both create or open it.
To use a file as a lock, the check-and-lock operation has to be a single uninterruptable operation. You can achieve this in a Unix filesystem by creating a file with read-only mode and removing it to unlock. If the file exists (and is read only) the file creation will fail, so you get check-and-lock in a single atomic operation.
If your locking process is a shell script that will be running as a daemon, you can get this effect by using umask
, a per-process setting that sets the permissions that new files are created with:
oldumask=$(umask)
umask 222 # create files unwritable to owner too
if echo $$ > /var/lock/foo
then
: locking succeeded
else
: locking failed
fi
umask $oldumask
This also writes the owning process' PID into the file, which solves your other problem:
cat /var/lock/foo
As regards the specific question "Which processes have this file open?", this can be useful when you want to unmount a filesystem but can't because some process has a file open in it. If you don't have those commands available, you can ask
/proc
as root:
ls -l /proc/*/cwd | grep '/var/lock/foo$'
or, as a mortal user:
ls -l /proc/*/cwd 2>/dev/null | grep '/var/lock/foo$'
2fuser has strange behavior with exit codes. it returns 1 exitcode with two states: A/ some internal error, checked file not found etc, B/ no process opened specified file. In situation A/ some error message is printed to its output. Unfortunately when file is available and opened by something, output is generated but with exit code 0. It would be better if fuser will exit with three codes, not two like currently. lsoft is a bit worse resolve because this is working more slowly. – Znik – 2014-12-11T10:01:42.330
This is essentially the same pattern that
ls
follows — it returns exit code 2 if there's an error (e.g., invalid option specified) *or* file not found (and 0 if it successfully reports information). – Scott – 2016-11-16T00:48:32.547this was great, but to use it in a script i had to check the output length. – chovy – 2013-08-21T07:39:39.680
what do you mean the output length? – Nathan Fellman – 2013-08-21T08:40:12.903
if [
fuser "$file"]; then exit
– chovy – 2013-08-21T09:05:30.927