How to undelete any open, deleted file on linux.
Introduction
There are many situations where a file has been deleted (typically by an overnight log-cleaning process), yet the inode is still held open by a process reading from, or writing to, it. Recovery of such a file is simple, regardless of whether it is on ext2, ext3, reiserfs or any other filesystem.
When a file is deleted in linux, it is simply 'unlinked'. The inode, which contains the file's data, is not deleted until all processes have finished with it. This is why processes can carry on writing to deleted files.
(Incidentally, this is why linux can be upgraded without requiring a reboot. Programmes, which have shared libraries open, carry on using the old versions of shared libraries until they finish.)
Demonstration
Let's make a test file, and hold it open with a backgrounded 'tail -f':
chris@chris-laptop:/tmp$ echo "hello world" > testfile
chris@chris-laptop:/tmp$ tail -f testfile &
[1] 8530
chris@chris-laptop:/tmp$ hello world
8530 is the process id of the tail command. Let's look at the file descriptors used by the tail:
chris@chris-laptop:/tmp$ ls -lA /proc/8530/fd
total 0
lrwx------ 1 chris chris 64 2009-02-20 10:32 0 -> /dev/pts/23
lrwx------ 1 chris chris 64 2009-02-20 10:32 1 -> /dev/pts/23
lrwx------ 1 chris chris 64 2009-02-20 10:32 2 -> /dev/pts/23
lr-x------ 1 chris chris 64 2009-02-20 10:32 3 -> /home/tmp/testfile
lr-x------ 1 chris chris 64 2009-02-20 10:32 62 -> pipe:[18848062]
lr-x------ 1 chris chris 64 2009-02-20 10:32 63 -> pipe:[18848057]
Now we can delete the test file, check that it's deleted and have another look at this tail's file descriptors.
chris@chris-laptop:/tmp$ rm testfile
chris@chris-laptop:/tmp$ ls testfile
ls: cannot access testfile: No such file or directory
chris@chris-laptop:/tmp$ ls -lA /proc/8530/fd
total 0
lrwx------ 1 chris chris 64 2009-02-20 10:32 0 -> /dev/pts/23
lrwx------ 1 chris chris 64 2009-02-20 10:32 1 -> /dev/pts/23
lrwx------ 1 chris chris 64 2009-02-20 10:32 2 -> /dev/pts/23
lr-x------ 1 chris chris 64 2009-02-20 10:32 3 -> /home/tmp/testfile (deleted)
lr-x------ 1 chris chris 64 2009-02-20 10:32 62 -> pipe:[18848062]
lr-x------ 1 chris chris 64 2009-02-20 10:32 63 -> pipe:[18848057]
The file descriptor shows that the file has been deleted. Now all we have to do is to recover the file. Luckily, we can access the file's contents via the process's file descriptor link.
chris@chris-laptop:/tmp$ cat /proc/8530/fd/3
hello world
chris@chris-laptop:/tmp$ ls testfile
ls: cannot access testfile: No such file or directory
chris@chris-laptop:/tmp$ cp /proc/8530/fd/3 testfile
chris@chris-laptop:/tmp$ ls -lA testfile
-rw-r--r-- 1 chris chris 12 2009-02-20 10:34 testfile
chris@chris-laptop:/tmp$ cat testfile
hello world
Job done. Thanks to my colleagues, at ApplianSys, for requiring this solution.
Posted on 20 February 2009.