Given file path, how can I determine which process creates it (and/or reads/writes to it)?
5 Answers
The lsof command (already mentioned in several answers) will tell you what process has a file open at the time you run it. lsof is available for just about every unix variant.
lsof /path/to/file
lsof won't tell you about file that were opened two microseconds ago and closed one microsecond ago. If you need to watch a particular file and react when it is accessed, you need different tools.
If you can plan a little in advance, you can put the file on a LoggedFS filesystem. LoggedFS is a FUSE stacked filesystem that logs all accesses to files in a hierarchy. The logging parameters are highly configurable. FUSE is available on all major unices. You'll want to log accesses to the directory where the file is created. Start with the provided sample configuration file and tweak it according to this guide.
loggedfs -l /path/to/log_file -c /path/to/config.xml /path/to/directory
tail -f /path/to/log_file
Many unices offer other monitoring facilities. Under Linux, you can use the relatively new audit subsystem. There isn't much literature about it (but more than about loggedfs); you can start with this tutorial or a few examples or just with the auditctl man page. Here, it should be enough to make sure the daemon is started, then run auditctl:
auditctl -w /path/to/file
(I think older systems need auditctl -a exit,always -w /path/to/file) and watch the logs in /var/log/audit/audit.log.
-
1From my understanding, LoggedFS and audit are like inotify in that they log the information. With something like vim's write feature, first foo.txt.swp is CREATED, then it is MOVED_TO foo.txt. This is logged (I use inotify), but the problem I now have is that when I am reviewing the logs, more often than not, I can no longer stat the foo.txt.swp file. This is creating a great deal of problems for me as the file may be deleted before the DELETE event is logged, so I try to get the file info and the OS complains the file no longer exists.puk– puk2012-09-01 15:45:52 +00:00Commented Sep 1, 2012 at 15:45
-
1@puk This question was about logging, not about reacting to the operation. That would be a different question. OpenBSD's systrace is the leader here, though I think Linux has other things to offer.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2012-09-02 11:57:24 +00:00Commented Sep 2, 2012 at 11:57
-
I doubt I will find what I am looking for: callbacks for system operationspuk– puk2012-09-04 19:59:47 +00:00Commented Sep 4, 2012 at 19:59
-
loggedFS, is pretty buggy, and it just dumps me sermentation core dumps after some time. And auditfs is enormously slowing my system..sandric– sandric2015-02-26 03:29:43 +00:00Commented Feb 26, 2015 at 3:29
Well you could run lsof repeatedly, and if you're lucky the culprit will hold the file open long enough for it to show. Ie.:
$ lsof -r1 /path/to/file
or for many files
$ lsof -r1 /path/to/folder/*
This will list all access to the given path at a certain point in time, once per second. This includes listing the PID of the process accessing the file.
If that doesn't work, that is, the file is opened and closed very quickly, which is often the case, I believe you need to look for more elaborate tools. Maybe loggedfs could be something?
Hackland
If the once-per-second lsof won't work, you could of course hack a while-loop that runs lsof repeatedly as fast as possible. Like:
$ while true; do lsof /paht/to/file; done;
Not pretty, but who knows, might just do it.
-
2Suggesting running
while trueon a tool that doesn't give the right answer anyway isn't a great way to help a new unix user. There are better ways to trigger an action on a file create (seeinotifywait) and better better ways to audit file system access (see Gilles answer).Caleb– Caleb2011-05-26 12:32:37 +00:00Commented May 26, 2011 at 12:32 -
I tried your while suggestion on a file (bash on mac). Edited the file and saved it.
lsofnever showed anything.jcollum– jcollum2018-04-06 21:40:05 +00:00Commented Apr 6, 2018 at 21:40
You can use lsof for that:
$ lsof /tmp/file
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
less 4737 wena 4r REG 8,6 90700 1643536 /tmp/file
It says the process named less is the keeping the file "/tmp/file" open.
NOTE: Strangely, that doesn't work if I use geany or nano. Am looking forward to better suggestions.
-
If the output (or lack of it) of
lsofis to be believed and my understanding is correct,lessopens a file butemacsdoes not. Strange.Faheem Mitha– Faheem Mitha2011-05-25 19:12:47 +00:00Commented May 25, 2011 at 19:12 -
7I think that editors just open and read the file to the memory and close it. After that they only monitor file for changes (like vim).Lukasz Stelmach– Lukasz Stelmach2011-05-25 19:27:32 +00:00Commented May 25, 2011 at 19:27
-
The column that says
rwould be different if it were writing it.Random832– Random8322011-05-25 20:04:03 +00:00Commented May 25, 2011 at 20:04 -
3Lukasz is correct; if you use
inotify -m /tmp/fileyou can see that bothvimandnanoopen, read/write to the file and close it immediately.André Paramés– André Paramés2011-05-26 00:43:01 +00:00Commented May 26, 2011 at 0:43 -
Vim opens a buffer in memory and writes to a file on save, emacs is similar i believe.chiggsy– chiggsy2011-07-13 08:08:17 +00:00Commented Jul 13, 2011 at 8:08
lsof |grep (filename)
This will show you the process that is currently using the file.
-
There is no need for
grephere. You can givelsofand argument of a specific filename to query and save a lot of time.Caleb– Caleb2011-05-26 12:35:10 +00:00Commented May 26, 2011 at 12:35 -
Ah cool to know. Honestly I only ever use it for finding open sockets so I don't really use it for actual files that much. Thanks for the heads up :)Matthew– Matthew2011-05-26 13:16:10 +00:00Commented May 26, 2011 at 13:16
You can use ls and grep to find out the files used by chrome
$ ls -l /proc/*/fd | grep "chrome"
lrwx------ 1 ba abc 64 Jul 16 22:19 104 -> /home/abc/.config/google-chrome/Default/Cookies
lr-x------ 1 abc abc 64 Jul 16 22:19 113 -> /opt/google/chrome/nacl_irt_x86_64.nexe
lrwx------ 1 abc abc 64 Jul 16 22:19 121 -> /home/abc/.cache/google-chrome/Default/Cache/data_0
lrwx------ 1 abc abc 64 Jul 16 22:19 122 -> /home/abc/.cache/google-chrome/Default/Cache/data_1
lrwx------ 1 abc abc 64 Jul 16 22:19 123 -> /home/abc/.cache/google-chrome/Default/Cache/data_2
lr-x------ 1 abc abc 64 Jul 16 22:19 125 -> /home/abc/.config/google-chrome/Dictionaries/en-US-3-0.bdic
Another way is to use lsof and grep
$ lsof | grep "chrome"
chrome 2204 abc cwd DIR 8,5 4096 1441794 /home/abc
chrome 2204 abc rtd DIR 8,5 4096 2 /
chrome 2204 abc txt REG 8,5 87345336 5111885 /opt/google/chrome/chrome
chrome 2204 abc mem REG 8,5 4202496 1443927 /home/abc/.cache/google-chrome/Default/Media Cache/data_3
chrome 2204 abc mem REG 8,5 1056768 1443926 /home/abc/.cache/google-chrome/Default/Media Cache/data_2
chrome 2204 abc mem REG 8,5 270336 1443925 /home/abc/.cache/google-chrome/Default/Media Cache/data_1
chrome 2204 abc mem REG 8,5 45056 1443924 /home/abc/.cache/google-chrome/Default/Media Cache/data_0
inotifywait $file ; lsof -r1 $file, though. It's much better than runningwhileloops or usingwatch.lsofruns the file may already have been closed.