43

Three files have suddenly appeared in my home directory, called "client_state.xml", "lockfile", and "time_stats_log". The last two are empty. I'm wondering how they got there. It's not the first time it has happened, but the last time was weeks ago; I deleted the files and nothing broke or complained. I haven't been able to think of what I was doing at the time reported by stat $filename. Is there any way I can find out where they came from?

Alternatively, is there a way to monitor the home directory (but not sub-directories) for the creation of files?

Wolf
  • 3,045

7 Answers7

26

You can watch everything that happens on a filesystem by accessing it over LoggedFS. This is a stacked filesystem that logs every access in a directory tree.

loggedfs -l /var/tmp/$USER-home-fs.log ~

Logging your whole home directory might slow your system down though. You'll at least want to write a configuration file with stringent filters.

If you have root access, on Linux, you can use the audit subsystem to log a large number of things, including filesystem accesses. Make sure the auditd daemon is started, then configure what you want to log with auditctl. Each logged operation is recorded in /var/log/audit/audit.log (on typical distributions). To start watching a particular file:

auditctl -w /path/to/file

or in the long form

auditctl -a exit,always -F path=/path/to/file

If you put a watch on a directory (with -w or -F dir=), the files in it and its subdirectories recursively are also watched.

  • BSD also supports this via Security Event Auditing. http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/audit.html – Shawn J. Goff Oct 12 '11 at 17:32
  • The problem with auditd is that in a typical stock configuration, the log file might be written over before you examine it, because the default limit of an 8MB log file is very small. – Philipp Ludwig Feb 21 '22 at 08:01
  • The opposite action of the -w <path> is -W <path> which removes the specified watch rule. – Yuri Apr 29 '22 at 07:25
24

I don't believe there is a way to determine which program created a file.

For your alternative question: You can watch for the file to be recreated, though, using inotify. inotifywait is a command-line interface for the inotify subsystem; you can tell it to look for create events in your home directory:

$ (sleep 5; touch ~/making-a-test-file) &
[1] 22526

$ inotifywait -e create ~/
Setting up watches.
Watches established.
/home/mmrozek/ CREATE making-a-test-file

You probably want to run it with -m (monitor), which tells it not to exit after it sees the first event

Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
  • How do I get inotify? It's not installed (kernel 2.6.34) and there's no /dev/inotify. – Wolf Jan 18 '11 at 19:52
  • 2
    @Wolf What distro? If you build your own kernel, it's CONFIG_INOTIFY_USER (Filesystems -> Inotify support for userspace). inotifywait is probably in a package named something like inotify-tools – Michael Mrozek Jan 18 '11 at 20:01
  • @Michael, it's openSUSE 11.3. I've never built a kernel; have only been using Linux about 5 months and it's a bit of a daunting concept. But I'll look around for a tutorial or something. – Wolf Jan 18 '11 at 20:03
  • @Wolf Well, dogbane's answer might be easier if the kernel you have doesn't come with it – Michael Mrozek Jan 18 '11 at 20:07
  • @Michael Intestingly, /boot/config-2.6.37.7-0.7-desktop (supposedly a copy of the configuration file used for the distro?) contains the lines CONFIG_INOTIFY=y and CONFIG_INOTIFY_USER=y. So I wonder why there's no inotify available. – Wolf Jan 18 '11 at 20:19
  • @Wolf Are you sure it's not available? I don't have /dev/inotify on any of my machines; did you try running something that uses it? – Michael Mrozek Jan 18 '11 at 20:21
  • 2
    @Michael Actually, after a little more hunting and research, I added a community repository which, it turns out, contains the inotify-tools package, so I now have inotifywait (and inotifywatch). I tested it out and it seems to work. – Wolf Jan 18 '11 at 20:46
  • inotifywait is only an answer for the alternative question. the main question remains unanswered. edited answer accordingly – törzsmókus Nov 07 '19 at 16:40
7

I know this is an old question, but I'll suggest another approach just in case someone finds it useful. I originally posted this as an answer to a question that was duped to this one.

One option is to use sysdig: an open-source system monitoring application. Using it, you can monitor for activity on a file by name. Suppose that you wanted to see what process was creating a file named /tmp/example.txt:

# sysdig fd.name=/tmp/example.txt
567335 16:18:39.654437223 0 touch (5470) < openat fd=3(<f>/tmp/example.txt) dirfd=-100(AT_FDCWD) name=/tmp/example.txt flags=70(O_NONBLOCK|O_CREAT|O_WRONLY) mode=0666
567336 16:18:39.654438248 0 touch (5470) > dup fd=3(<f>/tmp/example.txt)
567337 16:18:39.654438592 0 touch (5470) < dup res=0(<f>/tmp/example.txt)
567338 16:18:39.654439629 0 touch (5470) > close fd=3(<f>/tmp/example.txt)
567339 16:18:39.654439764 0 touch (5470) < close res=0
567342 16:18:39.654441958 0 touch (5470) > close fd=0(<f>/tmp/example.txt)
567343 16:18:39.654442111 0 touch (5470) < close res=0

From that output, you can see that a process named touch with pid 5470 opened the file.

If you want more information, you could run in "capture mode" where a system call trace is collected:

# sysdig -w /tmp/dumpfile.scap

Then wait for the file to be created, then stop sysdig and run:

# csysdig -r /tmp/dumpfile.scap

That'll let you explore everything that happened. You can press <F2> and select Files, the press <F4> to search for the filename, then press <F6> to "dig" (which will show you output similar to the command above). With that, you can then use the same approach to find information about the process that actually created the file.

There's a GUI version of csysdig called sysdig-inspect, if that's more your cup of tea.

Andy Dalton
  • 13,993
  • or maybe a busy loop that constantly runs lsof trying to see if/when a process is writing to that file... https://unix.stackexchange.com/a/13782/8337 – rogerdpack Nov 07 '19 at 19:17
  • @rogerdpack You could miss events if you poll with lsof, that's exactly why inotify and auditd were created in the first place. – Alan Evangelista Jan 22 '21 at 20:49
4

You might want to take a look at auditd, this package allows you to do security auditing, and get a lot of information about who changed what in the filesystem.

GAD3R
  • 66,769
lutzky
  • 881
  • if you have a server that provides shell access for multiple users, and need to provide some level of accountability for individual actions, you can build certain shells (like bash and tcsh) with command history logging. I wrote a blog post about logging in shells at http://www.timkennedy.net/2010/12/07/recording-user-commands-to-syslog-on-secure-systems. Shell logging is not a replacement for a real auditing system, as it won't log commands run by non-interactive shells (like scripts or programs). To get that sort of granularity you really need a good auditing solution. – Tim Kennedy Oct 13 '11 at 14:22
  • 1
    @TimKennedy - your blog post isn't coming up anymore. – slm Aug 29 '13 at 18:36
  • 1
    Sorry. site got hacked, and was down for a while. new page is at http://www.timkennedy.net/2010/12/logging-shell-commands-to-syslog-on.html – Tim Kennedy Nov 14 '13 at 18:24
2

You haven't got inotify so you can write a script that checks for the file in a loop:

#!/bin/sh

while [ true ]; do                     # Run for as long as nessesary
  if [ -f /path/to/file ]; then        # If fileexists
    echo "Found file"                  # Notify and stop monitoring
    exit 0
  fi
  sleep 5                             # Else wait 5 secs
done
dogbane
  • 29,677
1

You can use the Linux Audit System to get information and events occurring on files.

touch hello.txt
sudo auditd
sudo auditctl -w $PWD/hello.txt -p warx -k hello-file
echo 'hello world' > hello.txt
sudo ausearch -k hello-file
0

You can use inotifywait in conjunction with lsof to figure out what process has created a file if you're able to run the following command ahead of time - i.e. waiting for the file to be created. Assuming you don't know the filename, but you do know the directory, you would use this command:

inotifywait -e create /tmp | tee /dev/stderr | grep CREATE | cut -d ' ' -f 3 | xargs -I {} lsof /tmp/{}

Replace the two instances of /tmp with the absolute path to the directory you want to watch.