2

Using the lsof command, I can determine whether a file is in use by some process, but I need to atomically check a file for use and move it only if unused. These files are in use by various other programs over which I have no control, so I can't use advisory locks. The purpose is to stop other processes from modifying that file, so just moving the file while a process has it open is not OK. Any solution?

UPDATE: a solution just occurred to me that I think suits my purposes. The end goal is to process these files in their final state when other programs finish modifying them. If I move the file to another directory, I can then use lsof to check whether it is still in use via its old path; if so, I just check again later until it's no longer in use and then process the file. By moving the file to another directory, it hides the file from users and the program. I don't want users and programs seeing the file in the old directory because that gives them opportunity to open the file in between the time I use lsof and process the file, which means I'd be processing the file in a modified state.

Jegschemesch
  • 11,414
  • 4
  • 32
  • 37
  • Not sure if this would work, but try just marking it not readable or writable any more: chmod a-rw My guess is that it won't affect the running process as it already has it open. – PlexQ Jan 05 '12 at 17:24
  • If another process already has the file open, moving the file has no effect...so just move it. How does waiting until no other process has the file open help at all? – William Pursell Jan 05 '12 at 17:39

2 Answers2

5

How about using fuser? Run it on a file and it will display the PIDs of processes using the file. If there are no PIDs, there is nothing using the file. It will also return a non-zero exit code if there is no process using the file.

However, note that you could still have a race condition, because a process could open the file after the fuser command returns and before you mv it.

Some sample code to move a file if not in use:

if ! fuser /my/file
then
     mv /my/file /somewhere/else
fi 
dogbane
  • 266,786
  • 75
  • 396
  • 414
3

You can move a file which something is accessing it, assuming you move it on the same file system using the rename(2) syscall (which mv would use if source and target are on the same file system). You could even remove it using unlink(2) system call. And moving such a file would indeed forbid other future processes to access it by that same path.

You could also use the inotify(7) API to be notified when something access it.

At you might also consider mandatory locking at least with some file systems.

but rumors are that mandatory locking does not work well and could be buggy sometimes

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547