104

I would like to create a "/dev/null" directory (or a "blackhole" directory) such that any files written to it are not really written, but just disappear.

I have an application that writes out large temporary files to a directory. I have no control over the name of the files and I don't really care about the content of these files. I could write a script that periodically clobbers these files, but the files are written out very quickly and fill my disk. I'm looking for something cleverer. I want the application to "think" that it is writing out these files, when in fact, the writes are just being discarded at the other end.

Also see this old related thread.

dogbane
  • 29,677

6 Answers6

54

This isn't supported out-of-the-box on any unix I know, but you can do pretty much anything with FUSE. There's at least one implementation of nullfs¹, a filesystem where every file exists and behaves like /dev/null (this isn't the only implementation I've ever seen).

¹ Not to be confused with the *BSD nullfs, which is analogous to bindfs.

11

Another approach would be an LD_PRELOAD wrapper; basically a small shared library which is loaded before libc.so, and intercepts calls to open() with something that checks the prospective file path and substitutes /dev/null if it would be in the target directory.

This has the advantage of being (a) entirely in user-space - no kernel hacking required; and (b) only affecting the single errant application.

A simple example is at http://www.noah.org/wiki/LD_PRELOAD_notes, but in your case you will want to intercept the access(), open() & creat() system calls. For a more complete implementation you might also need to intercept chdir(), accessat(), openat(), and possibly others.

  • 4
    ...assuming the application does system calls via libc, not directly via int 0x80/syscall/sysenter/whatever else. – Ruslan Feb 07 '16 at 18:44
7

i have created a kernel module based on the ramfs example in the linux kernel, it is basically a blackhole filesystem called nullfsvfs. The FUSE system implementation needs to copy data from user to kernelspace and is quite slow, compared to a straight implementation as kernel module. See:

https://github.com/abbbi/nullfsvfs

michael
  • 71
1

You say that removing the files periodically with a script isn't fast enough. Could you live with a trigger that deletes a temporary file any time your application finishes writing and closes it? If so, you might make use of the "inotify" API.

(See http://en.wikipedia.org/wiki/Inotify and https://github.com/rvoicilas/inotify-tools/wiki/)

  • 1
    On many systems, deleting a file that a process has open removes its directory entry, but the file itself stays on disk until it is closed by the last process using it. Processes might write files and then seek to the beginning and read them back, and so the OS can't just throw the data away. – interfect Apr 18 '17 at 21:58
  • 1
    In line with the previous comment, you're better off periodically truncating the logfile rather than deleting it. It might become sparse as a result, appearing to have lots of NUL bytes at the start, but those don't actually take any space in the filesystem, save for some indirection blocks. – Martin Kealey Sep 21 '20 at 06:59
0

If the program is so stupid to not let you switch those logs off, may be it also doesn't check for errors after opening a log file? I'd try mounting some dummy read-only file system (e.g. using mount -o loop.)

alex
  • 7,223
  • 1
    this approach doesn't work unfortunately. The application dies if it can't write to this file. – dogbane Mar 16 '11 at 12:22
-12

Just symlink that directory to /dev/null

rm -rf ~/.logs
ln -s /dev/null ~/.logs

/dev/null, doesn't have to be a directory. If the program tries writing to ~/.logs/log1.dump, it still goes right into /dev/null.
I do this for Google Chrome's cache because after a while it gets so big that Chrome will take minutes to start.

jonescb
  • 1,918
  • 3
    This wouldn't work because symlinks are files, not directories. Trying echo hello > ~/.logs/log1.dump gives ~/.logs/log1.dump: Not a directory. However, echo hello > ~/.logs works because .logs is a file. – dogbane Mar 16 '11 at 13:25
  • 2
    You must be kidding us. $ ln -s /dev/null dev-null; touch dev-null/zzz gives me touch: cannot touch 'dev-null/zzz': Not a directory – alex Mar 16 '11 at 13:28
  • 2
    Like I said, it works for Chrome. It prevents it from writing into the cache. If it causes the asker's program to crash, then obviously it doesn't check if file pointers are NULL. – jonescb Mar 16 '11 at 13:54
  • 9
    It probably means that Chrome skips writing if there is an error opening the file. You could achieve the same effect by removing write permission from the dump file or the directory its writing in. – KeithB Mar 16 '11 at 14:04
  • True, changing the permissions of the directory would probably make more sense. – jonescb Mar 16 '11 at 14:53