Skip to main content

per-process transient /tmp mount

Posted by kohsuke on February 8, 2009 at 8:28 PM PST

One of the things I recently came across is the Linux kernel's unique ability to have a process-specific file system mount table. In Unix that I know of, a file system mount table is global to the entire system, but apparently, starting Linux 2.6.16, you can have multiple mount tables in the system. In a way, this is a kind of a virtualization technology, because two processes in the same system can see entirely different file system (but then, this has already been true, with things like chroot.)

You can create a new mount table in multiple ways, but one way to do that is to use unshare(2), which clones the current mount table for the calling process. Once you do that, all the successive mount/unmount calls will only affect this table and won't affect the original mount table, and any new process created by this process will see the new mount table.

So I used this system call to write a small tool called "transienttmp". This tool unshares the mount table, mount a new tmpfs to /tmp, then exec into the commands specified in the argument. The net result is that it creates an empty, transient /tmp file system, which will be discarded as soon as the exec-ed process exits.

The following example runs a big test (that clutters /tmp) with the transient /tmp. Whatever temporary files that this ant process creates are totally invisible from the rest of the world, and when ant exits, its local /tmp will be gone forever.

$ transienttmp ant build some-big-test

I plan to use this to improve isolation of bad-behaving tests on my Hudson cluster — it's more productive to do this than chasing down every use of File.createTempFile and add try/finally delete code. The source code of this tool is available on GitHub. Run sudo make install to install the binary. Debian packages are also available for those who are using Debian/Ubuntu.

P.S. I would have loved to write this tool in Java, but unfortunately a setuid program is only thing you can never write in an interpreted language...

Related Topics >>

Comments

ejono --- that breaks down as soon as the JVM forks another JVM, which is too often the case. You have Ant script forking another JVM for tests which clutters /tmp, or you have a wrapper shell script that forks a JVM, which in turn forks GlassFish/Tomcat/JBoss, which in turn clutters /tmp. System properties don't inherit, and that makes "java.io.tmpdir" solution impossible.

Yeah, couldn't you just make Hudson automatically set java.io.tmpdir to some directory in the workspace, then automatically blow away that directory after a build?

OK, this might be a java "bug", but my JDK doesn't honor TMPDIR. I looked at the JDK source code in the past, and AFAIKT it's hard-coding /tmp. I just run a quick experiment to confirm this with the following, and see that it's getting ignored. % TMPDIR=$PWD groovy -e "println File.createTempFile('test',null)" /tmp/test50452.tmp Yes, in JVM I can set java.io.tmpdir system property but that has to be set for all JVMs that are launched.

transienttemp sounds cool, but you can accomplish this functionality without per-process mounts. Simply set the "TMPDIR" environment variables to someplace else, run what you need to run, then delete the contents of TMPDIR when you're done. Instant, per process, tmp directories.