Monday, 9 May 2016

Recovering Deleted Files in Linux


List Open Files For a ParticularProcess

 

Sometimes you may delete a file by mistake.Say for example, If you delete  a Datafile or a redo log or a Control File when the Database is down, you cannot recover it. However, If you delete a n important File when the Database or any Dependant Application is still running, There is a chance of recovering it.

How is it Possible? Well, When you remove a file using the "rm" command, Linux removes the link that points to its inode, but not the inode itself. Other processes (such as Oracle Database ) might still have it open. Only after the Process(In this case, the Database) is stopped, that the Data Blocks for the Inode are made available for writing.

We can exploit this feature to recover the files. If the Process is open, then the file is still available in the File System, even though we cannot see it at the Operating System Level. 

We may have seen a "proc" directory in the "/" File System, This is the Linux process pseudo-filesystem. Every process on the system has a directory here with its name on it, inside of which lies many things -- including an fd ("file descriptor") subdirectory containing links to all files that the process has open. Even if a file has been removed from the filesystem, a copy of the data will be right here:

/proc/process id/fd/file descriptor

To know where to go, you need to get the id of the process that has the file open, and the file descriptor. These you get with lsof, whose name means "list open files." (It actually does a whole lot more than this and is so useful that almost every system has it installed. If yours isn't one of them, you can grab the latest version straight from its author.)

Once you get that information from lsof, you can just copy the data out of /proc, and BAM, your Data is there.

Example

 First, create a text file that you can delete and then bring back:
$ man lsof | col -b > TestFile.txt
Then have a look at the contents of the file that you just created:
$ less TestFile.txt


Now press Ctrl-Z to suspend less. Issue an "ls", and make sure your file is still there:
$ ls -l myfile
 -rw-r--r--  1 Oracle dba 114383 Oct 31 16:14 myfile
$ stat  TestFile.txt
  File: ` TestFile.txt'
  Size: 114383          Blocks: 232        IO Block: 4096   regular file
Device: 341h/833d       Inode: 1276722     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1010/    jimbo)   Gid: ( 1010/    jimbo)
Access: 2006-10-31 16:15:08.423715488 -0400
Modify: 2006-10-31 16:14:52.684417746 -0400
Change: 2006-10-31 16:14:52.684417746 -0400
 
 
Now go ahead and delete it.

$ rm  TestFile.txt
$ ls -l  TestFile.txt
ls:  TestFile.txt: No such file or directory
$ stat  TestFile.txt
stat: cannot stat ` TestFile.txt': No such file or directory
$
 
It's not there anymore. At this point, you must not allow the process still using the file to exit, because once that happens, the file will really be gone and your troubles will intensify. Your background less process in this walkthrough isn't going anywhere (unless you kill the process or exit the shell), but if this were a video or sound file that you were playing, the first thing to do at the point where you realize you deleted the file would be to immediately pause the application playback, or otherwise freeze the process, so that it doesn't eventually stop playing the file and exit.
Now to bring the file  TestFile.txt. First see what lsof has to say about it:
$ lsof | grep myfile
less      4158    oracle   4r      REG       3,65   114383   1276722 /home/oracle/TestFile.txt(deleted)
The first column gives you the name of the command associated with the process, the second column is the process id, and the number in the fourth column is the file descriptor (the "r" means that it's a regular file). Now you know that process 4158 still has the file open, and you know the file descriptor, 4. That's everything you have to know to copy it out of /proc.
You might think that using the -a flag with cp is the right thing to do here, since you're restoring the file -- but it's actually important that you don't do that. Otherwise, instead of copying the literal data contained in the file, you'll be copying a now-broken symbolic link to the file as it once was listed in its original directory:
$ ls -l /proc/4158/fd/4
lr-x------  1 oracle dba 64 Oct 31 16:18 /proc/4158/fd/4 -> /home/oracle/TestFile.txt (deleted)
$ cp -a /proc/4158/fd/4  TestFile.txt.wrong
$ ls -l  TestFile.txt.wrong
lrwxr-xr-x  1 oracle dba 24 Oct 31 16:22  TestFile.txt.wrong -> /home/oracle/ TestFile.txt(deleted)
$ file  TestFile.txt.wrong
myfile.wrong: broken symbolic link to `/home/oracle/TestFile.txt(deleted)'
$ file /proc/4158/fd/4
/proc/4158/fd/4: broken symbolic link to `/home/oracle/TestFile.txt(deleted)'
So instead of all that, just a plain old cp will do the trick:

$ cp /proc/4158/fd/4  TestFile.txt.recovered
And finally, verify that you've done good:
$ ls -l  TestFile.txt.recovered
-rw-r--r--  1 oracle dba 114383 Oct 31 16:25  TestFile.txt.recovered
$ man lsof | col -b >  TestFile.txt.new
$ cmp  TestFile.txt.recovered TestFile.txt.new
 
cmp output confirmed that the file is safely recovered.



No comments:

Post a Comment