1. 程式人生 > >linux rm -rf * 檔案恢復記

linux rm -rf * 檔案恢復記

2013-09-12

周海漢/文 2013.9.12

手太快,腸子都毀清了。本來是刪除一個檔案 rm path/myfile.txt 結果不知為何加了個*,變成了 rm path/myfile.txt * 趕緊ls,發現所有程式碼都化為了烏有,還沒提交,還沒備份。刪除時還不確認。一秒鐘,世界就清淨了。

帶著僥倖的心情四處尋找,並無一處壓縮包備份。有一些備份的地方也是很早期的工作。 欲哭無淚。

所以linux的rm刪除時不先備份,真是要不得。難怪很多人rm時左看右看得過個半分鐘才敢下手。有人建議直接將root下的rm改成mv的別名。 沒辦法,必須恢復。 機器在機房裡,也不能斷電拔硬碟或者重啟。

首先,需立即將磁碟掛載為只讀。

否則其他daemons 都來讀寫,神仙都恢復不了了。磁碟規劃時一定要做功能分割槽。否則,誤刪了想恢復也很困難。比如linux安裝時不分割槽整個裝/下面,就很麻煩。 /data掛在/dev/sdb1上

[[email protected] sh]# mount /dev/sdb1 on /data type ext4 (rw)

[[email protected] hadoop]# mount -r -n -o remount /data mount: /data is busy 這需看看有哪些程序在用: [[email protected] hadoop]# fuser -v -m /data 可以看到有很多java和hadoop程序在使用,殺之。 [

[email protected] hadoop]# mount -r -n -o remount /data 成功。 再到/data裡touch檔案,報錯。

[[email protected] data]# touch a touch: cannot touch `a’: Read-only file system

一下就放輕鬆了很多。因為改為只讀掛載後,可以慢慢恢復,再也不用擔心我的檔案被覆蓋。

使用debugfs

用debugfs查詢被刪檔案的inode,再想法恢復。 [[email protected] ~]# debugfs /dev/sdb1 debugfs 1.41.12 (17-May-2010)

debugfs: debugfs: lsdel Inode Owner Mode Size Blocks Time deleted 0 deleted inodes found.

神奇的debugfs 根本沒找到有檔案被刪除的inodes,難道是我不會用?

失敗!

使用grep恢復

grep 在磁碟二進位制中查詢文字,把前後的字元匯出來,也許可以恢復部分。 [[email protected] hadoop]# grep -a -B 100 -A 100 ‘active.sh’ /dev/sdb1 > results.txt 只有一些亂七八糟的二進位制。 失敗!

使用ext3grep

我的是ext4系統,根本不起作用。

只好尋找專業工具

用testdisk 6.14

使用介紹: http://www.cgsecurity.org/wiki/TestDisk%3a_undelete_file_for_ext2 下載: wget http://www.cgsecurity.org/testdisk-6.14.linux26-x86_64.tar.bz2 [[email protected] hadoop]# cd testdisk-6.14 [[email protected] testdisk-6.14]# ls Android.mk ChangeLog documentation.html fidentify_static INFO l photorec.8 README testdisk.8 testdisk_static VERSION AUTHORS COPYING fidentify.8 ico jni NEWS photorec_static readme.txt testdisk.log THANKS

[[email protected] testdisk-6.14]# ./testdisk_static TestDisk 6.14, Data Recovery Utility, July 2013 Christophe GRENIER [email protected] http://www.cgsecurity.org 1 P MS Data 2048 7811889151 7811887104 [primary] Directory /

drwxr-xr-x 500 500 4096 28-Aug-2013 13:41 . drwxr-xr-x 500 500 4096 28-Aug-2013 13:41 .. drwxrwxrwx 500 500 16384 18-Jul-2013 15:42 lost+found drwxrwxrwx 500 500 12288 12-Sep-2013 00:36 logs

drwxrwxrwx 500 500 4096 25-Jul-2013 16:54 test1 drwxrwxr-x 500 500 4096 12-Sep-2013 03:28 statis drwxrwxr-x 500 500 4096 12-Sep-2013 17:40 sh drwxrwxr-x 500 500 12288 3-Sep-2013 15:28 hadoop

Next Use Right to change directory, h to hide deleted files q to quit, : to select the current file, a to select all files C to copy the selected files, c to copy the current file

選到相應目錄,enter,終於看到了刪除的檔名,但是檔案大小怎麼都是0啊? TestDisk 6.14, Data Recovery Utility, July 2013 Christophe GRENIER [email protected] http://www.cgsecurity.org 1 P MS Data 2048 7811889151 7811887104 [primary] Directory /sh

drwxrwxr-x 500 500 4096 12-Sep-2013 17:40 . drwxr-xr-x 500 500 4096 28-Aug-2013 13:41 ..

-rwxrwxr-x 500 500 0 12-Sep-2013 17:40 active.awk -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 active.sh lrwxrwxrwx 500 500 13 2-Aug-2013 17:17 statis -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 dateutil.sh -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 hiveput.sh -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 multidate.sh drwxrwxr-x 500 500 4096 3-Sep-2013 15:24 errlogs -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 hiveactive.sh drwxrwxr-x 500 500 4096 12-Sep-2013 17:40 cps drwxrwxr-x 500 500 4096 30-Aug-2013 15:21 TempStatsStore -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 bkactive.awk -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 test.awk -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 t.awk -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 print -rw-rw-r– 500 500 0 12-Sep-2013 17:40 a -rw-rw-r– 500 500 0 12-Sep-2013 17:40 a.txt -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 user.awk -rw-rw-r– 500 500 0 12-Sep-2013 17:40 luan -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 cps.sh -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 hivenewdev.sh -rw-rw-r– 500 500 0 12-Sep-2013 17:40 hive2mysql.sh -rw-rw-r– 500 500 0 12-Sep-2013 17:40 py lrwxrwxrwx 500 500 12 26-Aug-2013 09:34 userdata lrwxrwxrwx 500 500 10 26-Aug-2013 09:34 bidata -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 bi.awk -rw-r–r– 500 500 0 12-Sep-2013 17:40 luandoutang_09_900037.csv -rw-rw-r– 500 500 0 12-Sep-2013 17:40 luan1 -rwxr-xr-x 500 500 0 12-Sep-2013 17:40 luan.awk -rwxr-xr-x 500 500 0 12-Sep-2013 17:40 luan.sh -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 dvid_price.awk -rwxrwxr-x 500 500 0 12-Sep-2013 17:40 cid_price.awk lrwxrwxrwx 500 500 15 9-Sep-2013 13:33 adsdkdata -rw-rw-r– 500 500 0 12-Sep-2013 17:40 0908.txt -rw-rw-r– 500 500 0 12-Sep-2013 17:40 09081.txt -rw-rw-r– 500 500 0 12-Sep-2013 17:40 09.txt drwxrwxr-x 500 500 4096 9-Sep-2013 16:22 pid

TestDisk 6.14, Data Recovery Utility, July 2013

Please select a destination where /sh/active.awk will be copied. Keys: Arrow keys to select another directory C when the destination is correct Q to quit

用a 選擇所有檔案,C 備份,選一個備份到的目錄,確認。

進去一看,檔名都恢復了,但檔案內容都是空的。號稱能恢復ext4的testdisk恢復失敗。

又下了新版testdisk-7.0-WIP.linux26-x86_64.tar.bz2,一樣的問題。

用extundelete-0.2.4恢復

官方網站:

下載:

wget http://downloads.sourceforge.net/project/extundelete/extundelete/0.2.4/extundelete-0.2.4.tar.bz2

extundelete依賴e2fsprogs [[email protected] extundelete-0.2.4]# ./configure Configuring extundelete 0.2.4 configure: error: Can’t find ext2fs library

[[email protected] extundelete-0.2.4]# yum install e2fsprogs-devel

[[email protected] extundelete-0.2.4]# ./configure Configuring extundelete 0.2.4 Writing generated files to disk

[[email protected] extundelete-0.2.4]# make & make install

[[email protected] extundelete-0.2.4]# cd src [[email protected] src]# ls block.c cli.cc extundelete-block.o extundelete-cli.o extundelete.h extundelete-priv.h jfs_compat.h Makefile Makefile.in block.h extundelete extundelete.cc extundelete-extundelete.o extundelete-insertionops.o insertionops.cc kernel-jbd.h Makefile.am

[[email protected] src]# ./extundelete No action specified; implying –superblock. ./extundelete: Missing device name. Usage: ./extundelete [options] [–] device-file Options: –version, -[vV] Print version and exit successfully. –help, Print this help and exit successfully. –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’. Actions: –inode ino Show info on inode ‘ino’. –block blk Show info on block ‘blk’. –restore-inode ino[,ino,…] Restore the file(s) with known inode number ‘ino’. The restored files are created in ./RECOVERED_FILES with their inode number as extension (ie, file.12345). –restore-file ‘path’ Will restore file ‘path’. ‘path’ is relative to root of the partition and does not start with a ‘/’ The restored file is created in the current directory as ‘RECOVERED_FILES/path’. –restore-files ‘path’ Will restore files which are listed in the file ‘path’. Each filename should be in the same format as an option to –restore-file, and there should be one per line. –restore-directory ‘path’ Will restore directory ‘path’. ‘path’ is relative to the root directory of the file system. The restored directory is created in the output directory as ‘path’. –restore-all Attempts to restore everything. -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. –log 0 Make the program silent. –log filename Logs all messages to filename. –log D1=0,D2=filename Custom control of log messages with comma-separated Examples below: list of options. Dn must be one of info, warn, or –log info,error error. Omission of the ‘=name’ results in messages –log warn=0 with the specified level to be logged to the console. –log error=filename If the parameter is ‘=0’, logging for the specified level will be turned off. If the parameter is ‘=filename’, messages with that level will be written to filename. -o directory Save the recovered files to the named directory. The restored files are created in a directory named ‘RECOVERED_FILES/’ by default. ./extundelete: Error parsing command-line options.

[[email protected] src]# ./extundelete /dev/sdb1 –restore-directory /data/sh NOTICE: Extended attributes are not restored. Loading filesystem metadata … 29800 groups loaded. Loading journal descriptors … 28266 descriptors loaded. Failed to restore file /data/sh Could not find correct inode number past inode 2. Try altering the filename to one of the entries listed below. File name | Inode number | Deleted status . 2 .. 2 lost+found 11 logs 195821569 dfs 14942209 mapred 165806081 bidata 221380609 userdata 3407873 trackdata 112459777 adsdkdata 135135233 test 227409921 a.tar.gz 12 t1 13 Deleted test1 227278849 statis 109051905 sh 24641537 hadoop 59506689 ./extundelete: Operation not permitted while restoring directory. ./extundelete: Operation not permitted when trying to examine filesystem [[email protected] src]# ./extundelete /dev/sdb1 –restore-file /data/sh/active.awk NOTICE: Extended attributes are not restored. Loading filesystem metadata … 29800 groups loaded. Loading journal descriptors … 28266 descriptors loaded. Failed to restore file /data/sh/active.awk Could not find correct inode number past inode 2. Try altering the filename to one of the entries listed below. File name | Inode number | Deleted status . 2 .. 2 lost+found 11 logs 195821569 dfs 14942209 mapred 165806081 bidata 221380609 userdata 3407873 trackdata 112459777 adsdkdata 135135233 test 227409921 a.tar.gz 12 t1 13 Deleted test1 227278849 statis 109051905 sh 24641537 hadoop 59506689 ./extundelete: Operation not permitted while restoring file. ./extundelete: Operation not permitted when trying to examine filesystem

[[email protected] RECOVERED_FILES]# ../extundelete /dev/sdb1 –restore-all NOTICE: Extended attributes are not restored. Loading filesystem metadata … 29800 groups loaded. Loading journal descriptors … 28266 descriptors loaded. [[email protected] RECOVERED_FILES]# cd RECOVERED_FILES/ [[email protected] RECOVERED_FILES]# cd sh [[email protected] sh]# ls 09081.txt a bknewdev.awk charge.sh derby.log hive2mysql.sh luan.awk newdev.awk so.awk 0908.txt active.awk b.txt charge.txt dvid_price.awk hiveactive.sh luandoutang_09900037.csv newdev.sh t.awk 09.txt active.sh charge cid_price.awk emptycid hivenewdev.sh luan.sh pid.awk TempStatsStore 100001 adsdkdata charge_2013-09-09.txt cps err.txt hiveput.sh multidate.sh pid.sh test.awk 1dev.awk a.txt charge_20130909.txt cps_newdev.java getdvid.awk insdata.py newdev print user.awk 201309081.txt bi.awk charge2mysql.sh cps.sh getmysql.sh luan newdev1.awk py 201309091.txt bkactive.awk charge.awk dateutil.sh getnewdev_from_mysql.sh luan1 newdev2mysql.sh sendmail.sh [[email protected] sh]# ls -l total 225360 -rw-r–r– 1 root root 29251633 Sep 12 19:46 09081.txt -rw-r–r– 1 root root 35249787 Sep 12 19:46 0908.txt -rw-r–r– 1 root root 64501420 Sep 12 19:46 09.txt -rw-r–r– 1 root root 2378 Sep 12 19:46 100001 -rw-r–r– 1 root root 840 Sep 12 19:46 1dev.awk -rw-r–r– 1 root root 33931129 Sep 12 19:46 201309081.txt -rw-r–r– 1 root root 27169653 Sep 12 19:46 201309091.txt -rw-r–r– 1 root root 1 Sep 12 19:46 a -rw-r–r– 1 root root 2227 Sep 12 19:46 active.awk -rw-r–r– 1 root root 999 Sep 12 19:46 active.sh -rw-r–r– 1 root root 19242484 Sep 12 19:46 adsdkdata -rw-r–r– 1 root root 5626 Sep 12 19:46 a.txt -rw-r–r– 1 root root 331 Sep 12 19:46 bi.awk -rw-r–r– 1 root root 1543 Sep 12 19:46 bkactive.awk -rw-r–r– 1 root root 931 Sep 12 19:46 bknewdev.awk -rw-r–r– 1 root root 11 Sep 12 19:46 b.txt -rw-r–r– 1 root root 230 Sep 12 19:46 charge -rw-r–r– 1 root root 20964603 Sep 12 19:46 charge_2013-09-09.txt -rw-r–r– 1 root root 229 Sep 12 19:46 charge_20130909_.txt -rw-r–r– 1 root root 1243 Sep 12 19:46 charge2mysql.sh -rw-r–r– 1 root root 428 Sep 12 19:46 charge.awk -rw-r–r– 1 root root 2822 Sep 12 19:46 charge.sh -rw-r–r– 1 root root 227 Sep 12 19:46 charge.txt -rw-r–r– 1 root root 1227 Sep 12 19:46 cid_price.awk drwxr-xr-x 2 root root 4096 Sep 12 19:46 cps -rw-r–r– 1 root root 12070 Sep 12 19:46 cps_newdev.java -rw-r–r– 1 root root 2764 Sep 12 19:46 cps.sh -rw-r–r– 1 root root 885 Sep 12 19:46 dateutil.sh -rw-r–r– 1 root root 992 Sep 12 19:46 derby.log -rw-r–r– 1 root root 658 Sep 12 19:46 dvid_price.awk -rw-r–r– 1 root root 54217 Sep 12 19:46 emptycid -rw-r–r– 1 root root 64279 Sep 12 19:46 err.txt -rw-r–r– 1 root root 379 Sep 12 19:46 getdvid.awk -rw-r–r– 1 root root 1217 Sep 12 19:46 getmysql.sh -rw-r–r– 1 root root 1552 Sep 12 19:46 getnewdev_from_mysql.sh -rw-r–r– 1 root root 532 Sep 12 19:46 hive2mysql.sh -rw-r–r– 1 root root 858 Sep 12 19:46 hiveactive.sh -rw-r–r– 1 root root 926 Sep 12 19:46 hivenewdev.sh -rw-r–r– 1 root root 683 Sep 12 19:46 hiveput.sh -rw-r–r– 1 root root 2227 Sep 12 19:46 insdata.py -rw-r–r– 1 root root 1045 Sep 12 19:46 luan -rw-r–r– 1 root root 813 Sep 12 19:46 luan1 -rw-r–r– 1 root root 336 Sep 12 19:46 luan.awk -rw-r–r– 1 root root 72909 Sep 12 19:46 luandoutang_09_900037.csv -rw-r–r– 1 root root 180 Sep 12 19:46 luan.sh -rw-r–r– 1 root root 420 Sep 12 19:46 multidate.sh drwxr-xr-x 2 root root 4096 Sep 12 19:46 newdev -rw-r–r– 1 root root 777 Sep 12 19:46 newdev1.awk -rw-r–r– 1 root root 1290 Sep 12 19:46 newdev2mysql.sh -rw-r–r– 1 root root 738 Sep 12 19:46 newdev.awk -rw-r–r– 1 root root 762 Sep 12 19:46 newdev.sh -rw-r–r– 1 root root 693 Sep 12 19:46 pid.awk -rw-r–r– 1 root root 518 Sep 12 19:46 pid.sh -rw-r–r– 1 root root 99 Sep 12 19:46 print -rw-r–r– 1 root root 30324 Sep 12 19:46 py -rw-r–r– 1 root root 160 Sep 12 19:46 sendmail.sh -rw-r–r– 1 root root 744 Sep 12 19:46 so.awk -rw-r–r– 1 root root 93 Sep 12 19:46 t.awk drwxr-xr-x 2 root root 4096 Sep 12 19:46 TempStatsStore -rw-r–r– 1 root root 311 Sep 12 19:46 test.awk -rw-r–r– 1 root root 385 Sep 12 19:46 user.awk [[email protected] sh]# vi active.awk 檢視,指令碼都在。

整個恢復成功。 所以唯一成功的是extundelete ,並且不能指定檔案和目錄,而是全部恢復,才能成功。

一塊石頭落了地:) 經驗提供給後來者,一定要備份,磁碟要功能分割槽。rm命令要 alias rm=”rm -i”.

如非註明轉載, 均為原創. 本站遵循知識共享CC協議,轉載請註明來源