数据恢复类型:

  1. 操作系统回收站:直接回收站里还原即可。
  2. 分区表错乱:testdisk(linux下)windows下也有一堆好工具,这个错误导致的文件丢失可以说是经常性的。
  3. 文件系统:easyrecovery(windows下),linux下目前还在找相关好用的工具,可用的工具: ddrecovery extundelete photorec(testdisk),可惜都不够直观。
  4. 坏扇区:safecopy
  5. 被dd写覆盖????不知道dd的写入规则,是否是优先空扇区(这种救活概率大)还是直接逐个扇区写(能抢救多少就多少吧!!!)
  6. 磁盘直接损毁:即使是这个程度,也能恢复,但这个 已经 不是我的能力范围了。。

【前期工作】

当意识到文件丢失的时候,当意识到磁盘有问题的时候

一、原盘备份:dd或者ddrescue

dd的复制是完全基于二进制的物理复制,从硬盘的第一个字节道最后一个字节,完全一样的克隆了一遍,所以是最保险、最准确的。而且由于dd是物理复制,所以只要是硬盘上存在的分区,无论Linux是否认识,甚至是Linux认不出是什么的一段数据,都可以原原本本的复制,例如FreeBSD分区、其他操作系统的分区,甚至加密扇区什么的,就连逻辑坏块也原样复制!因此除非出现物理读取故障,不然dd较难出错的!

因此,只要硬盘出现问题,比如分区破坏,立刻用dd原盘备份,然后再进行其他恢复操作,是最保险的。

提一句:Ghost功能比较多了一些,可以在复制的时候改变分区大小(他认识的分区格式),压缩映像文件(dd本身不具有压缩功能,但是可以用gzip、 bzip2等工具压缩生成的文件),在Windows下还有explore软件可以单独提取文件出来,还有网络功能,而且速度也要比dd快一些(好像 Ghost使用了较大的缓存)。另外一点dd的优势在于,在克隆的当前分区的时候,还可以干些别的事情,不像Ghost那样只能干等(不能对该分区磁盘进行操作)。因此从这方面来看,dd的速度又要比Ghost快,因为它完全占用系统的时间是零!

使用方式,命令行输入类似格式: dd if=/dev/hda of=/dev/hdc

dd就是Linux/Unix下通用的克隆、镜像程序,if=输入的文件 of=输出的文件。由于在Linux下所有的硬件都表示为文件,所以可以进行任何复制、克隆。比如还可以把/dev/hda克隆到MO、磁带以及映像文件中,当然,目标“文件”必须比原“文件”大,不然就会溢出。

如果发生读取错误,使用ddrescue来备份硬盘。

如果dd读出失败, dd_rescue将尝试读出。

二、需要了解的文件系统存储方式

备份后,进入第二步,想想问题出现在什么地方。

主要了解下面核心问题:

  1. 哪里是存储目录的?指系统级别的,一般叫节点或者节点索引(inode)
  2. 哪里是存储数据的?(data block)
  3. 哪里是存储数据间关系的?——也就是大数据的切分,以及切分之后的连接方式,以及如何恢复这种关系?——扩展(extent)
  4. 文件名和扩展名存放在哪里?目录项(directory)

了解这些,有助于手工恢复文件……

关于ext3 和 ext4的文件系统布局,具体的别的帖子有介绍,此处略去

【工具介绍】

一、testdisk+photorec

photorec包含在testdisk这个包里

sudo apt-get install testdisk

rm掉的东西可以使用photorec恢复,恢复后的文件名为”f+随机数字”的组合。

在使用PhotoRec恢复数据前,务必清楚:

二、extundelete

extundelete可用于恢复ext3或者ext4分区上rm删除的文件。

``` extundelete –help 命令格式: extundelete [options] [–] device-file 参数: –version, -[vV] 本软件版本 –help, 本软件帮助 –superblock Print contents of superblock in addition to the rest.显示超级块 If no action is specified then this option is implied. –journal Show content of journal.显示日志 –after dtime Only process entries deleted on or after ‘dtime’.在某天之后被删的 –before dtime Only process entries deleted before ‘dtime’.在某天之前被删的 动作: –inode ino 显示inode节点“ino”的信息 –block blk Show info on block ‘blk’. 显示数据块“blk”的信息 –restore-inode ino[,ino,…] 根据已知的 inode值’ino’(可多个),恢复文件。 恢复的文件保存在./RESTORED_FILES中, 命名方式是:使用inode值当扩展名。(比如: file.12345)。 –restore-file ‘path’ 恢复路径(文件夹?),路径是相对于分区根目录的,路径名不以 ‘/’ 开始(必须是 –dump-names 返回的路径之一)。 恢复的文件被保存在 当前路径下的,如 ‘RECOVERED_FILES/path’。 –restore-files ‘path’ 恢复路径下的文件,恢复的文件命名方式,需要在–restore-file参数中指定,每个一行。 –restore-all 恢复所有东西。 -j journal Reads an external journal from the named file.从已经命名的文件中读取扩展日志 -b blocknumber Uses the backup superblock at blocknumber when opening the file system.打开文件系统时,使用使用备份的超级块——一般用于查看现有超级块不是当前所要的文件 -B blocksize Uses blocksize as the block size when opening the file system. The number should be the number of bytes. 使用数据块大小来打开文件系统——一般用于查看已经知道大小的文件

```

如何使用?

示例:分区/dev/sdb1 挂在在/backup上,建立一个测试目录gnutool-delete 并建立一些文件

mkdir -p /backup/gnutool-delete cd /backup/gnutool-delete man man > file1-test.txt man man > file2-test.txt mkdir folder1; cd folder1; man man > file1-test.txt

现在 删除目录 rm -rf /backup/gnutool-delete # 删除了目录 umount /backup # 卸载 只读挂载要恢复的文件所在的分区(df -h查看挂载点对应的文件系统) mount -o remount,ro /backup 切换到把恢复文件存放的分区: cd /secondarydrive (必须可读可写) 磁盘整体恢复:会在当前目录创建一个“RECOVERED_FILES” 来放修复的文件 使用以下命令找回所有文件 extundelete /dev/partition --restore-all 知道目录时恢复: extundelete /dev/partition --restore-directory /var/lib/mysql 知道文件名时恢复: extundelete /dev/partition --restore-files /etc/passwd 最后用md5sum验证一下,MD5值相同,则恢复成功。 cd RECOVERED_FILES ls

恢复最近一小时删除的文件, hour=$((60 * 60)) current=`date +%s` before=$(($current - $hour)) extundelete --after $before --restore-all /dev/vgdata/data unset hour current before

三、ext3grep

ext3在删除一个文件后,会把文件 inode结点中扇区指针清为0,因为ext3是一个日志型的文件系统,通过分析日志信息,有很大的可能重新解析出块指针,从而恢复出目录和文件。

看起来参数很多,比较复杂。

``` 命令格式: ext3grep [options] [–] device-file 参数: –version, -[vV] 输出版本信息 –help, 输出帮助信息 –superblock Print contents of superblock in addition to the rest.显示超级块的内容 If no action is specified then this option is implied. –print Print content of block or inode, if any. 显示数据块的内容和节点索引 –ls Print directories with only one line per entry. This option is often needed to turn on filtering. –accept filen Accept ‘filen’ as a legal filename. Can be used multi- ple times. If you change any –accept you must remove BOTH stage* files! –accept-all Simply accept everything as filename.允许所有文件名形式 –journal Show content of journal.显示日志内容 –show-path-inodes Show the inode of each directory component in paths. 过滤选项Filters: –group grp Only process group ‘grp’.只执行组“grp” –directory Only process directory inodes.只执行目录节点 –after dtime Only entries deleted on or after ‘dtime’.只要某天后被删的 –before dtime Only entries deleted before ‘dtime’.只要某天前被删的 –deleted Only show/process deleted entries.只显示/执行被删 –allocated Only show/process allocated inodes/blocks. –unallocated Only show/process unallocated inodes/blocks. –reallocated Do not suppress entries with reallocated inodes. Inodes are considered ‘reallocated’ if the entry is deleted but the inode is allocated, but also when the file type in the dir entry and the inode are different. –zeroed-inodes Do not suppress entries with zeroed inodes. Linked entries are always shown, regardless of this option. –depth depth Process directories recursively up till a depth of ‘depth’. 动作Actions: –inode-to-block ino Print the block that contains inode ‘ino’. –inode ino Show info on inode ‘ino’. If –ls is used and the inode is a directory, then the filters apply to the entries of the directory. If you do not use –ls then –print is implied. –block blk Show info on block ‘blk’. If –ls is used and the block is the first block of a directory, then the filters apply to entries of the directory. If you do not use –ls then –print is implied. –histogram=[atime|ctime|mtime|dtime|group] Generate a histogram based on the given specs. Using atime, ctime or mtime will change the meaning of –after and –before to those times. –journal-block jblk Show info on journal block ‘jblk’. –journal-transaction seq Show info on transaction with sequence number ‘seq’. –dump-names Write the path of files to stdout. This implies –ls but suppresses it’s output. –search-start str Find blocks that start with the fixed string ‘str’.搜索使用特定字串“str”开始的数据块 –search str Find blocks that contain the fixed string ‘str’.搜索包含字串“str”的数据块 –search-inode blk Find inodes that refer to block ‘blk’.搜索指向“blk”的节点索引 –search-zeroed-inodes Return allocated inode table entries that are zeroed. –inode-dirblock-table dir Print a table for directory path ‘dir’ of directory block numbers found and the inodes used for each file. –show-journal-inodes ino Show copies of inode ‘ino’ still in the journal.显示日志中存在的节点“ino”的备份索引 –restore-inode ino[@seqnr][,ino[@seqnr],…] Restore the file(s) with known inode number ‘ino’. The restored files are created in ./RESTORED_FILES/ with their inode number as extension (ie, inode.12345). If ‘@seqnr’ is provided then (only) the journal entry with that sequence number is used, otherwise the latest entry is used (if any). You can use that in the case a a file was overwritten or truncated, rather than deleted. –restore-file ‘path’ [–restore-file ‘path’ …] Will restore file ‘path’. ‘path’ is relative to the root of the partition and does not start with a ‘/’ (it must be one of the paths returned by –dump-names). The restored directory, file or symbolic link is created in the current directory as ‘RESTORED_FILES/path’.恢复文件路径(相对路径) –restore-all As –restore-file but attempts to restore everything. The use of –after is highly recommended because the attempt to restore very old files will only result in them being hard linked to a more recently deleted file and as such polute the output.恢复所有文件(此处建议使用时间限定,比如某天后或者某天前,不然会把很多老文件都恢复出来) –show-hardlinks Show all inodes that are shared by two or more files. 显示所有被两个或多个文件共享的节点索引

```

实战例子:

ext3grep /dev/your-device --restore-file path/to/your/file/filename

其中,/dev/your-device是设备名,参数是恢复文件路径, 最后一个是所需恢复的文件路径(使用的是相对地址),默认把恢复的文件放到当前分区下的RECOVER_FILE文件夹中(和extundelete类似,都是软件自动建立的文件夹)

四、foremost

Foremost is a console program to recover files based on their headers, footers, and internal data structures. This process is commonly referred to as data carving. Foremost can work on image files, such as those generated by dd, Safeback, Encase, etc, or directly on a drive. The headers and footers can be specified by a configuration file or you can use command line switches to specify built-in file types. These built-in types look at the data structures of a given file format allowing for a more reliable and faster recovery. Originally developed by the United StatesAir Force Office of Special Investigations and The Center for Information Systems Security Studies and Research , foremost has been opened to the general public.

五、r-studio/rlinux

qt的图形界面。

六、giis

giis-ext4(gET iT i sAY) 是一个 Ext4 文件系统的文件恢复工具,安装后当前文件和新创建的文件都可以恢复,可恢复删除的文件,恢复某个用户的文件和恢复指定类型文件。

七、其他

如果上面的东西仍然无法满足需要,可以搜索scalpel 等

八、dd和grep

用于抢救回 mv覆盖的文件。

使用grep命令在磁盘上通过被误删代码中的比较有代表性的关键字符串查找文件所在偏移位置:比如下面检索了三个关键字符 ``` grep -a -b ‘/home/qishengfu/QQWry.Dat’ /dev/mapper/vg_qidasheng8-home

2851521881:    wry_file=fopen("/home/qishengfu/QQWry.Dat","r");    
2851534169:    wry_file=fopen("/home/qishengfu/QQWry.Dat","r");

grep -a -b 'cJSON_AddStringToObject(fmt,"province"'  /dev/mapper/vg_qidasheng8-home

1862223382:	cJSON_AddStringToObject(fmt,"province", trim_str(tmp[0]));
1876743751:	cJSON_AddStringToObject(fmt,"province", trim_str(tmp[0]));

grep -a -b 'cJSON_AddStringToObject(fmt,"desc"'  /dev/mapper/vg_qidasheng8-home

1889870235:	cJSON_AddStringToObject(fmt,"desc", ip_key[1]); ``` 通过dd命令利用2中获取的的偏移信息直接从磁盘读取内容: ```
dd if=/dev/mapper/vg_qidasheng8-home count=1 skip=$(expr 1876743751 / 512) ``` 得到如下要找回的代码片段: ```
tmp[0] = malloc(len0);
tmp[1] = malloc(len1);
    strncpy(tmp[0], ip_key[0], len0);
    strncpy(tmp[1], pos + len, len1);
    cJSON_AddStringToObject(fmt,"province", trim_str(tmp[0]));
    cJSON_AddStringToObject(fmt,"city", trim_str(tmp[1]));
    } else {
    cJSON_AddStringToObject(fmt,"country", ip_key[0]);
       }
    }
            if (count >=1 && ip_key[1] != NULL) {
    cJSON_AddStringToObject(fmt,"place", ip_key[1]);
}
        if (count >=2 && ip_key[2] != NULL) { ``` 注意事项:

1、 从上面数据可以看出,count=1的情况下读取的只是部分代码片段,可以把count值调大读取前后更大范围的数据;

2、第2步中获取的偏移信息不一定就是被覆盖的文件的偏移,有可能是历次代码编辑中数据的偏移,所以可以把上面获取到的偏移记录位置的数据都读取出来,然后人工核对选择最接近的数据进行汇总,就能恢复得到最近的数据啦。

参数解释

grep中几个参数的解释

-a用来把二进制文件当文本文件处理,-b用来保证显示查找出的结果的偏移位置

   -a, --text
          Process a binary file as if it were text; this is equivalent to the --binary-files=text option.      
   -b, --byte-offset
          Print  the  0-based  byte  offset  within  the  input file before each line of output.  If -o (--only-matching) is specified, print the offset of the
          matching part itself.

dd中使用的几个参数的解释

count指明读取多少个数据块,if指定读取源,skip指定跳过多少个块(后面除以512是因为,skip是跳过ibs-sized blocks,而ibs默认大小为512)

  count=BLOCKS
          copy only BLOCKS input blocks
   ibs=BYTES
          read BYTES bytes at a time (default: 512)
   if=FILE
          read from FILE instead of stdin

   skip=BLOCKS
          skip BLOCKS ibs-sized blocks at start of input

防范于未然

  1. 绝大部分的数据丢失,都是因为误操作引发的。所以,在做数据的移动、覆盖、删除的时候,要留心了。一般是先备份,然后再执行这些操作。或者,使用 版本管理工具。

  2. 删除尽可能不要硬删,而是移入 回收站的。

  3. 刷写系统镜像的时候(比如制作u盘启动盘,个人曾经将自己挂的仓库盘给误当u盘刷了,太惨了!),尤其要小心了!!!!个人目前想到的一个办法是:在虚拟机中操作,虚拟机只挂载有关的硬盘,这样只要挂载的硬盘无错,误操作也最多也只损毁虚拟机的。 另外,最好指定 uuid,注意检查挂载的磁盘大小。

  4. 尽可能使用日志型文件系统,比如 etx4 ntfs等,如果性能可以,更建议使用带版本管理工具的文件系统,比如zfs btrfs等。
  5. 注意日常备份:几周一备份,重大操作(比如装系统)前备份。