Sometimes you have a file which is held open by a running process (probably being written to) but the filename itself has been deleted. The file contents exist as long as the process is running, but when it terminates, the file will disappear and become pretty much unrecoverable.
How can you get at the contents of the file, when the filename has been deleted?
It turns out to be remarkably simple:
You then have a copy of the data (up to that point in time) which will not disappear when the process holding the file open terminates.
It's all based around inodes, which are pointers to the location on disk of the contents of a file, whereas the filename is just an entry in a special file which is normally called a directory, and points to the inode. Deleting the filename from the directory does not affect the inode, it simply removes the usual way of referencing it.
Example:
# ps ax | grep pcap 25028 ? S 0:00 /usr/sbin/tcpdump -w /var/log/smpp.pcap -i any port 2775 # ls -l /var/log/smpp.pcap ls: cannot access '/var/log/smpp.pcap': No such file or directory # lsof | grep /var/log/smpp.pcap tcpdump 25028 root 4w REG 254,2 36995072 527356 /var/log/smpp.pcap (deleted)
The output of lsof has the following meaning:
tcpdump | is the name of the process which has the file open |
25028 | is the Process ID (PID) of the process which has the file open |
root | is the username the process is running under |
4 | is the File Descriptor (FD) being used to reference that file by the process |
w | means that the file is open for writing |
REG | means this is a regular file (not a pipe, socket or similar) |
254 | is the major device number of the disk the file is stored on |
2 | is the minor device number of the disk the file is stored on |
36995072 | is the current size of the file in bytes |
527356 | is the inode where the file is stored on disk |
/var/log/smpp.pcap | is the name the file had when it was opened |
(deleted) | means the name has been deleted since the process started writing to the file |
To recover the file you simply use the PID and the FD, together with the magic of the proc file system:
# cat /proc/25028/fd/4 >/var/log/smpp.pcap # ls -l /var/log/smpp.pcap -rw-r--r-- 1 root root 36995072 May 22 13:06 /var/log/smpp.pcap
You then have a copy of the file with its content at the time you do the copy. Any data which gets written to the file later will only be in the original (deleted) file; you would need to copy it again later if you want to get that content as well.
Go up
Return to main index.