閱讀658 返回首頁    go 阿裏雲 go 技術社區[雲棲]


簡易數據恢複方案實戰:流程和工具

數據恢複有沒有簡易方案?

IT工程師一般都知道如何操作和使用文件和目錄。但是,對於係統如何構建出、抽象出文件和目錄,一般就不熟悉了。至於更下層的概念,可能大家知道最多的就是驅動了。所以,為了規避這點,可行的簡易方案之一,就是以黑箱方式使用testdisk等工具,在我們在對底層了解不多甚至一無所知的情況下,進行數據恢複(商業工具,恢複效果估計更好,當然商業工具的價格也更好)。但是,對於工程師而言,多數時候,僅僅以黑箱方式依賴某些工具進行數據恢複是不夠的。

數據恢複,經常是突發事故響應中關鍵而又耗時的一步。多數情況下,工程師往往並非專司數據恢複,操作環境往往是生產環境,趁手工具難以部署,執行操作要遵循種種約束,加之業務中斷的壓力。這種情形下,工程師很可能還需要推定數據恢複的結果/耗時等信息,提供數據供決策者使用。很明顯,如果你準備考驗一下自己的細致、耐心、知識和技能,數據恢複將是個不錯的課題。當然,有一點是明確的,隻是以黑箱方式使用testdisk等工具進行數據恢複,解決以上問題是不可能的。那麼,有沒有其他簡易方案呢?

這裏,我們以一個實際的case為例,討論一下,在隻使用UNIX常見工具(dd/grep/strace等)的情況下,如何簡單、快捷的恢複數據。

預先準備

工具

我們要用到以下工具

工具 功能 示例
bc 計算器 ```echo 'ibase=2^3;i=0107000;ibase=2^3+2;i/512' \
dd 檢查或者拷貝磁盤/分區的內容,可以是幾個扇區,也可以是幾個字節 ```dd if=/dev/sdb bs=1 count=64 skip=64 2>/dev/null \
grep 搜索製定字符串
od 把二進製內容以ASCII或者16進製顯示出來,搭配dd使用可以代替二進製編輯器 ```dd if=/dev/sdb bs=1 count=64 skip=64 2>/dev/null \
strace 追蹤應用的執行路徑和對數據處理的流程 strace ps

排查和診斷就是數據處理

如果對數據處理了解不多,請參考OSEMN

  1. obtaining data/獲取數據
  2. crubbing data/清洗數據
  3. exploring data/探索數據
  4. modeling data/建模數據
  5. interpreting data/解釋數據

測試環境

使用Virtualbox,基於CentOS/Fedora/debian/Ubuntu搭建Linux實驗環境。隻需要學會strace工具和如下係統調用,就足以追蹤係統如何處理諸如LVM物理卷元數據這樣過的問題。

name 功能
open 打開一個文件,返回一個文件描述符供後續讀寫操作使用
dup/dup2 複製文件描述符
lseek 將讀寫指針移動到指定位置,後續操作從此指定位置讀寫
close 關閉文件描述符
read 讀操作

數據恢複的原理和流程

什麼是元數據?

我們以大家都熟悉的磁盤作為存儲設備的例子。

現代操作係統都會在磁盤上建立多個分層結構來管理和控製磁盤。比如,磁盤分區,分區上建立物理卷,物理卷上建立卷組,卷組上建立邏輯卷,邏輯卷上建立文件係統,就是這樣的一個例子。如果你不熟悉LVM,請參考Logical Volume Manager

這些分層的結構都是很類似的。以磁盤分區為例。所謂分區,以大家最為熟悉的MBR: Master Boot Record結構為例。其實是第一個扇區記錄了各個分區的起始扇區,大小和類型。係統需要時,比如啟動過程中,係統隻要從磁盤的第一個扇區讀取這些數據即能拿到各個分區的數據。

具體看看分區的數據結構。以*fdisk*為例,分區的數據結構定義為

struct dos_partition {
        unsigned char boot_ind;         /* 0x80 - active */
        unsigned char bh, bs, bc;       /* begin CHS */
        unsigned char sys_ind;
        unsigned char eh, es, ec;       /* end CHS */
        unsigned char start_sect[4];    /* 分區開始扇區 */
        unsigned char nr_sects[4];       /* 分區包含的扇區數量 */
} __attribute__((packed));

我們看看具體分區的例子,驗證一下數據結構

83F959699634718530504D12DF3A1175

分區使得磁盤上的扇區有了差別。第一個扇區(其實其編號是0),因分區數據記錄其上而扮演特殊角色。明顯,對係統而言,管理和操作分區實際上就是讀寫第一扇區上的對應記錄而已。

類似分區信息這種係統用以管理某層資源的數據就是元數據。

係統在磁盤上建立的各個分層結構,都有類似分區結構的數據結構。以LVM結構為例,我們可以把磁盤記錄和LVM工具報告的數據做一對比。LVM數據的從第2個扇區開始,卷組數據在第8個扇區中,可以用dd命令提取相關扇區來驗證LVM的數據結構。

[root@pusf ~]# pvdisplay;vgdisplay;lvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               cl
  PV Size               39.00 GiB / not usable 3.00 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              9983
  Free PE               1
  Allocated PE          9982
  PV UUID               TIcs1T-Jksu-HKrn-fKqK-QF4K-ao1S-3PVBGI

  --- Volume group ---
  VG Name               cl
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               39.00 GiB
  PE Size               4.00 MiB
  Total PE              9983
  Alloc PE / Size       9982 / 38.99 GiB
  Free  PE / Size       1 / 4.00 MiB
  VG UUID               KTVFwl-2QRE-ehf3-3dJb-bIfG-bpn0-8FnH7l

  --- Logical volume ---
  LV Path                /dev/cl/swap
  LV Name                swap
  VG Name                cl
  LV UUID                Kc14dR-vFda-qdWJ-zUYo-lsDl-4oKq-RjjrBb
  LV Write Access        read/write
  LV Creation host, time localhost, 2017-04-18 13:23:08 +0800
  LV Status              available
  # open                 2
  LV Size                2.00 GiB
  Current LE             512
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:1

  --- Logical volume ---
  LV Path                /dev/cl/root
  LV Name                root
  VG Name                cl
  LV UUID                PWaI2g-t2Kq-h3aa-HgMC-cBp1-FjBp-dmaGeR
  LV Write Access        read/write
  LV Creation host, time localhost, 2017-04-18 13:23:09 +0800
  LV Status              available
  # open                 1
  LV Size                36.99 GiB
  Current LE             9470
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:0

[root@pusf ~]# dd if=/dev/sda2 bs=512 count=16 skip=1 2>/dev/null | od -tc
0000000   L   A   B   E   L   O   N   E 001  \0  \0  \0  \0  \0  \0  \0
0000020 270 177 251   K      \0  \0  \0   L   V   M   2       0   0   1
0000040   T   I   c   s   1   T   J   k   s   u   H   K   r   n   f   K
0000060   q   K   Q   F   4   K   a   o   1   S   3   P   V   B   G   I
0000100  \0  \0 360 277  \t  \0  \0  \0  \0  \0 020  \0  \0  \0  \0  \0
0000120  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000140  \0  \0  \0  \0  \0  \0  \0  \0  \0 020  \0  \0  \0  \0  \0  \0
0000160  \0 360 017  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000200  \0  \0  \0  \0  \0  \0  \0  \0 002  \0  \0  \0 001  \0  \0  \0
0000220  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0007000 252 314 344   w       L   V   M   2       x   [   5   A   %   r
0007020   0   N   *   > 001  \0  \0  \0  \0 020  \0  \0  \0  \0  \0  \0
0007040  \0 360 017  \0  \0  \0  \0  \0  \0 026  \0  \0  \0  \0  \0  \0
0007060 027 005  \0  \0  \0  \0  \0  \0 026   G 205 374  \0  \0  \0  \0
0007100  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0010000   c   l       {  \n   i   d       =       "   K   T   V   F   w
0010020   l   -   2   Q   R   E   -   e   h   f   3   -   3   d   J   b
0010040   -   b   I   f   G   -   b   p   n   0   -   8   F   n   H   7
0010060   l   "  \n   s   e   q   n   o       =       1  \n   f   o   r
0010100   m   a   t       =       "   l   v   m   2   "  \n   s   t   a
0010120   t   u   s       =       [   "   R   E   S   I   Z   E   A   B
0010140   L   E   "   ,       "   R   E   A   D   "   ,       "   W   R
0010160   I   T   E   "   ]  \n   f   l   a   g   s       =       [   ]
0010200  \n   e   x   t   e   n   t   _   s   i   z   e       =       8
0010220   1   9   2  \n   m   a   x   _   l   v       =       0  \n   m
0010240   a   x   _   p   v       =       0  \n   m   e   t   a   d   a
0010260   t   a   _   c   o   p   i   e   s       =       0  \n  \n   p
0010300   h   y   s   i   c   a   l   _   v   o   l   u   m   e   s
0010320   {  \n  \n   p   v   0       {  \n   i   d       =       "   T
0010340   I   c   s   1   T   -   J   k   s   u   -   H   K   r   n   -
0010360   f   K   q   K   -   Q   F   4   K   -   a   o   1   S   -   3
0010400   P   V   B   G   I   "  \n   d   e   v   i   c   e       =
0010420   "   /   d   e   v   /   s   d   a   2   "  \n  \n   s   t   a
0010440   t   u   s       =       [   "   A   L   L   O   C   A   T   A
0010460   B   L   E   "   ]  \n   f   l   a   g   s       =       [   ]
0010500  \n   d   e   v   _   s   i   z   e       =       8   1   7   8
0010520   6   8   8   0  \n   p   e   _   s   t   a   r   t       =
0010540   2   0   4   8  \n   p   e   _   c   o   u   n   t       =
0010560   9   9   8   3  \n   }  \n   }  \n  \n  \n   }  \n   #       G
0010600   e   n   e   r   a   t   e   d       b   y       L   V   M   2
0010620       v   e   r   s   i   o   n       2   .   0   2   .   1   6
0010640   6   (   2   )   -   R   H   E   L   7       (   2   0   1   6
0010660   -   0   9   -   2   8   )   :       T   u   e       A   p   r
0010700       1   8       0   5   :   2   3   :   0   8       2   0   1
0010720   7  \n  \n   c   o   n   t   e   n   t   s       =       "   T
0010740   e   x   t       F   o   r   m   a   t       V   o   l   u   m
0010760   e       G   r   o   u   p   "  \n   v   e   r   s   i   o   n
0011000       =       1  \n  \n   d   e   s   c   r   i   p   t   i   o
0011020   n       =       "   "  \n  \n   c   r   e   a   t   i   o   n
0011040   _   h   o   s   t       =       "   l   o   c   a   l   h   o
0011060   s   t   "  \t   #       L   i   n   u   x       l   o   c   a
0011100   l   h   o   s   t       3   .   1   0   .   0   -   5   1   4
0011120   .   e   l   7   .   x   8   6   _   6   4       #   1       S
0011140   M   P       T   u   e       N   o   v       2   2       1   6
0011160   :   4   2   :   4   1       U   T   C       2   0   1   6
0011200   x   8   6   _   6   4  \n   c   r   e   a   t   i   o   n   _
0011220   t   i   m   e       =       1   4   9   2   4   9   2   9   8
0011240   8  \t   #       T   u   e       A   p   r       1   8       0
0011260   5   :   2   3   :   0   8       2   0   1   7  \n  \n  \0  \0
0011300  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0012000   c   l       {  \n   i   d       =       "   K   T   V   F   w
0012020   l   -   2   Q   R   E   -   e   h   f   3   -   3   d   J   b
0012040   -   b   I   f   G   -   b   p   n   0   -   8   F   n   H   7
0012060   l   "  \n   s   e   q   n   o       =       2  \n   f   o   r
0012100   m   a   t       =       "   l   v   m   2   "  \n   s   t   a
0012120   t   u   s       =       [   "   R   E   S   I   Z   E   A   B
0012140   L   E   "   ,       "   R   E   A   D   "   ,       "   W   R
0012160   I   T   E   "   ]  \n   f   l   a   g   s       =       [   ]
0012200  \n   e   x   t   e   n   t   _   s   i   z   e       =       8
0012220   1   9   2  \n   m   a   x   _   l   v       =       0  \n   m
0012240   a   x   _   p   v       =       0  \n   m   e   t   a   d   a
0012260   t   a   _   c   o   p   i   e   s       =       0  \n  \n   p
0012300   h   y   s   i   c   a   l   _   v   o   l   u   m   e   s
0012320   {  \n  \n   p   v   0       {  \n   i   d       =       "   T
0012340   I   c   s   1   T   -   J   k   s   u   -   H   K   r   n   -
0012360   f   K   q   K   -   Q   F   4   K   -   a   o   1   S   -   3
0012400   P   V   B   G   I   "  \n   d   e   v   i   c   e       =
0012420   "   /   d   e   v   /   s   d   a   2   "  \n  \n   s   t   a
0012440   t   u   s       =       [   "   A   L   L   O   C   A   T   A
0012460   B   L   E   "   ]  \n   f   l   a   g   s       =       [   ]
0012500  \n   d   e   v   _   s   i   z   e       =       8   1   7   8
0012520   6   8   8   0  \n   p   e   _   s   t   a   r   t       =
0012540   2   0   4   8  \n   p   e   _   c   o   u   n   t       =
0012560   9   9   8   3  \n   }  \n   }  \n  \n   l   o   g   i   c   a
0012600   l   _   v   o   l   u   m   e   s       {  \n  \n   s   w   a
0012620   p       {  \n   i   d       =       "   K   c   1   4   d   R
0012640   -   v   F   d   a   -   q   d   W   J   -   z   U   Y   o   -
0012660   l   s   D   l   -   4   o   K   q   -   R   j   j   r   B   b
0012700   "  \n   s   t   a   t   u   s       =       [   "   R   E   A
0012720   D   "   ,       "   W   R   I   T   E   "   ,       "   V   I
0012740   S   I   B   L   E   "   ]  \n   f   l   a   g   s       =
0012760   [   ]  \n   c   r   e   a   t   i   o   n   _   t   i   m   e
0013000       =       1   4   9   2   4   9   2   9   8   8  \n   c   r
0013020   e   a   t   i   o   n   _   h   o   s   t       =       "   l
0013040   o   c   a   l   h   o   s   t   "  \n   s   e   g   m   e   n
0013060   t   _   c   o   u   n   t       =       1  \n  \n   s   e   g
0013100   m   e   n   t   1       {  \n   s   t   a   r   t   _   e   x
0013120   t   e   n   t       =       0  \n   e   x   t   e   n   t   _
0013140   c   o   u   n   t       =       5   1   2  \n  \n   t   y   p
0013160   e       =       "   s   t   r   i   p   e   d   "  \n   s   t
0013200   r   i   p   e   _   c   o   u   n   t       =       1  \n  \n
0013220   s   t   r   i   p   e   s       =       [  \n   "   p   v   0
0013240   "   ,       0  \n   ]  \n   }  \n   }  \n   }  \n  \n   }  \n
0013260   #       G   e   n   e   r   a   t   e   d       b   y       L
0013300   V   M   2       v   e   r   s   i   o   n       2   .   0   2
0013320   .   1   6   6   (   2   )   -   R   H   E   L   7       (   2
0013340   0   1   6   -   0   9   -   2   8   )   :       T   u   e
0013360   A   p   r       1   8       0   5   :   2   3   :   0   8
0013400   2   0   1   7  \n  \n   c   o   n   t   e   n   t   s       =
0013420       "   T   e   x   t       F   o   r   m   a   t       V   o
0013440   l   u   m   e       G   r   o   u   p   "  \n   v   e   r   s
0013460   i   o   n       =       1  \n  \n   d   e   s   c   r   i   p
0013500   t   i   o   n       =       "   "  \n  \n   c   r   e   a   t
0013520   i   o   n   _   h   o   s   t       =       "   l   o   c   a
0013540   l   h   o   s   t   "  \t   #       L   i   n   u   x       l
0013560   o   c   a   l   h   o   s   t       3   .   1   0   .   0   -
0013600   5   1   4   .   e   l   7   .   x   8   6   _   6   4       #
0013620   1       S   M   P       T   u   e       N   o   v       2   2
0013640       1   6   :   4   2   :   4   1       U   T   C       2   0
0013660   1   6       x   8   6   _   6   4  \n   c   r   e   a   t   i
0013700   o   n   _   t   i   m   e       =       1   4   9   2   4   9
0013720   2   9   8   8  \t   #       T   u   e       A   p   r       1
0013740   8       0   5   :   2   3   :   0   8       2   0   1   7  \n
0013760  \n  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0014000   c   l       {  \n   i   d       =       "   K   T   V   F   w
0014020   l   -   2   Q   R   E   -   e   h   f   3   -   3   d   J   b
0014040   -   b   I   f   G   -   b   p   n   0   -   8   F   n   H   7
0014060   l   "  \n   s   e   q   n   o       =       3  \n   f   o   r
0014100   m   a   t       =       "   l   v   m   2   "  \n   s   t   a
0014120   t   u   s       =       [   "   R   E   S   I   Z   E   A   B
0014140   L   E   "   ,       "   R   E   A   D   "   ,       "   W   R
0014160   I   T   E   "   ]  \n   f   l   a   g   s       =       [   ]
0014200  \n   e   x   t   e   n   t   _   s   i   z   e       =       8
0014220   1   9   2  \n   m   a   x   _   l   v       =       0  \n   m
0014240   a   x   _   p   v       =       0  \n   m   e   t   a   d   a
0014260   t   a   _   c   o   p   i   e   s       =       0  \n  \n   p
0014300   h   y   s   i   c   a   l   _   v   o   l   u   m   e   s
0014320   {  \n  \n   p   v   0       {  \n   i   d       =       "   T
0014340   I   c   s   1   T   -   J   k   s   u   -   H   K   r   n   -
0014360   f   K   q   K   -   Q   F   4   K   -   a   o   1   S   -   3
0014400   P   V   B   G   I   "  \n   d   e   v   i   c   e       =
0014420   "   /   d   e   v   /   s   d   a   2   "  \n  \n   s   t   a
0014440   t   u   s       =       [   "   A   L   L   O   C   A   T   A
0014460   B   L   E   "   ]  \n   f   l   a   g   s       =       [   ]
0014500  \n   d   e   v   _   s   i   z   e       =       8   1   7   8
0014520   6   8   8   0  \n   p   e   _   s   t   a   r   t       =
0014540   2   0   4   8  \n   p   e   _   c   o   u   n   t       =
0014560   9   9   8   3  \n   }  \n   }  \n  \n   l   o   g   i   c   a
0014600   l   _   v   o   l   u   m   e   s       {  \n  \n   s   w   a
0014620   p       {  \n   i   d       =       "   K   c   1   4   d   R
0014640   -   v   F   d   a   -   q   d   W   J   -   z   U   Y   o   -
0014660   l   s   D   l   -   4   o   K   q   -   R   j   j   r   B   b
0014700   "  \n   s   t   a   t   u   s       =       [   "   R   E   A
0014720   D   "   ,       "   W   R   I   T   E   "   ,       "   V   I
0014740   S   I   B   L   E   "   ]  \n   f   l   a   g   s       =
0014760   [   ]  \n   c   r   e   a   t   i   o   n   _   t   i   m   e
0015000       =       1   4   9   2   4   9   2   9   8   8  \n   c   r
0015020   e   a   t   i   o   n   _   h   o   s   t       =       "   l
0015040   o   c   a   l   h   o   s   t   "  \n   s   e   g   m   e   n
0015060   t   _   c   o   u   n   t       =       1  \n  \n   s   e   g
0015100   m   e   n   t   1       {  \n   s   t   a   r   t   _   e   x
0015120   t   e   n   t       =       0  \n   e   x   t   e   n   t   _
0015140   c   o   u   n   t       =       5   1   2  \n  \n   t   y   p
0015160   e       =       "   s   t   r   i   p   e   d   "  \n   s   t
0015200   r   i   p   e   _   c   o   u   n   t       =       1  \n  \n
0015220   s   t   r   i   p   e   s       =       [  \n   "   p   v   0
0015240   "   ,       0  \n   ]  \n   }  \n   }  \n  \n   r   o   o   t
0015260       {  \n   i   d       =       "   P   W   a   I   2   g   -
0015300   t   2   K   q   -   h   3   a   a   -   H   g   M   C   -   c
0015320   B   p   1   -   F   j   B   p   -   d   m   a   G   e   R   "
0015340  \n   s   t   a   t   u   s       =       [   "   R   E   A   D
0015360   "   ,       "   W   R   I   T   E   "   ,       "   V   I   S
0015400   I   B   L   E   "   ]  \n   f   l   a   g   s       =       [
0015420   ]  \n   c   r   e   a   t   i   o   n   _   t   i   m   e
0015440   =       1   4   9   2   4   9   2   9   8   9  \n   c   r   e
0015460   a   t   i   o   n   _   h   o   s   t       =       "   l   o
0015500   c   a   l   h   o   s   t   "  \n   s   e   g   m   e   n   t
0015520   _   c   o   u   n   t       =       1  \n  \n   s   e   g   m
0015540   e   n   t   1       {  \n   s   t   a   r   t   _   e   x   t
0015560   e   n   t       =       0  \n   e   x   t   e   n   t   _   c
0015600   o   u   n   t       =       9   4   7   0  \n  \n   t   y   p
0015620   e       =       "   s   t   r   i   p   e   d   "  \n   s   t
0015640   r   i   p   e   _   c   o   u   n   t       =       1  \n  \n
0015660   s   t   r   i   p   e   s       =       [  \n   "   p   v   0
0015700   "   ,       5   1   2  \n   ]  \n   }  \n   }  \n   }  \n  \n
0015720   }  \n   #       G   e   n   e   r   a   t   e   d       b   y
0015740       L   V   M   2       v   e   r   s   i   o   n       2   .
0015760   0   2   .   1   6   6   (   2   )   -   R   H   E   L   7
0016000   (   2   0   1   6   -   0   9   -   2   8   )   :       T   u
0016020   e       A   p   r       1   8       0   5   :   2   3   :   0
0016040   9       2   0   1   7  \n  \n   c   o   n   t   e   n   t   s
0016060       =       "   T   e   x   t       F   o   r   m   a   t
0016100   V   o   l   u   m   e       G   r   o   u   p   "  \n   v   e
0016120   r   s   i   o   n       =       1  \n  \n   d   e   s   c   r
0016140   i   p   t   i   o   n       =       "   "  \n  \n   c   r   e
0016160   a   t   i   o   n   _   h   o   s   t       =       "   l   o
0016200   c   a   l   h   o   s   t   "  \t   #       L   i   n   u   x
0016220       l   o   c   a   l   h   o   s   t       3   .   1   0   .
0016240   0   -   5   1   4   .   e   l   7   .   x   8   6   _   6   4
0016260       #   1       S   M   P       T   u   e       N   o   v
0016300   2   2       1   6   :   4   2   :   4   1       U   T   C
0016320   2   0   1   6       x   8   6   _   6   4  \n   c   r   e   a
0016340   t   i   o   n   _   t   i   m   e       =       1   4   9   2
0016360   4   9   2   9   8   9  \t   #       T   u   e       A   p   r
0016400       1   8       0   5   :   2   3   :   0   9       2   0   1
0016420   7  \n  \n  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0016440  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0017000   c   l       {  \n   i   d       =       "   K   T   V   F   w
0017020   l   -   2   Q   R   E   -   e   h   f   3   -   3   d   J   b
0017040   -   b   I   f   G   -   b   p   n   0   -   8   F   n   H   7
0017060   l   "  \n   s   e   q   n   o       =       4  \n   f   o   r
0017100   m   a   t       =       "   l   v   m   2   "  \n   s   t   a
0017120   t   u   s       =       [   "   R   E   S   I   Z   E   A   B
0017140   L   E   "   ,       "   R   E   A   D   "   ,       "   W   R
0017160   I   T   E   "   ]  \n   f   l   a   g   s       =       [   ]
0017200  \n   e   x   t   e   n   t   _   s   i   z   e       =       8
0017220   1   9   2  \n   m   a   x   _   l   v       =       0  \n   m
0017240   a   x   _   p   v       =       0  \n   m   e   t   a   d   a
0017260   t   a   _   c   o   p   i   e   s       =       0  \n  \n   p
0017300   h   y   s   i   c   a   l   _   v   o   l   u   m   e   s
0017320   {  \n  \n   p   v   0       {  \n   i   d       =       "   T
0017340   I   c   s   1   T   -   J   k   s   u   -   H   K   r   n   -
0017360   f   K   q   K   -   Q   F   4   K   -   a   o   1   S   -   3
0017400   P   V   B   G   I   "  \n   d   e   v   i   c   e       =
0017420   "   /   d   e   v   /   s   d   a   2   "  \n  \n   s   t   a
0017440   t   u   s       =       [   "   A   L   L   O   C   A   T   A
0017460   B   L   E   "   ]  \n   f   l   a   g   s       =       [   ]
0017500  \n   d   e   v   _   s   i   z   e       =       8   1   7   8
0017520   6   8   8   0  \n   p   e   _   s   t   a   r   t       =
0017540   2   0   4   8  \n   p   e   _   c   o   u   n   t       =
0017560   9   9   8   3  \n   }  \n  \n   p   v   1       {  \n   i   d
0017600       =       "   R   c   p   o   7   Z   -   Q   I   e   g   -
0017620   F   G   V   D   -   T   S   Z   I   -   s   o   Q   O   -   I
0017640   g   a   T   -   r   Q   w   D   4   Y   "  \n   d   e   v   i
0017660   c   e       =       "   /   d   e   v   /   s   d   b   6   "
0017700  \n  \n   s   t   a   t   u   s       =       [   "   A   L   L
0017720   O   C   A   T   A   B   L   E   "   ]  \n   f   l   a   g   s
0017740       =       [   ]  \n   d   e   v   _   s   i   z   e       =
0017760       4   0   9   6   0   1  \n   p   e   _   s   t   a   r   t
0020000
[root@pusf ~]#

元數據和數據:數據損壞分類

係統把磁盤的扇區分成兩種來支持分區:第一扇區和所有其他非第一扇區。並且在第一個扇區上記錄分區信息,即元數據。而其他非第一扇區則供分區層使用,從磁盤的視角看,其他非第一扇區則是數據部分。我們逐層考察下磁盤、分區和LVM結構

CE65898A6041E09A700B8FA227942235

係統啟動時,會逐層讀取各層元數據,創建各層數據結構。如果某一層元數據損壞或者丟失,那麼係統就沒有辦法完成創建各層數據結構的任務。這種情況下,從客戶角度看,很可能就是數據損壞了。比如,如果你把第一個扇區用**0**覆蓋一遍,那麼係統就識別不到分區內容了。當然這種情況下分區層以上的內容,比如物理卷信息,係統也無法處理了。因此,對於數據恢複任務而言,如果元數據損壞,則修複元數據總是必須的,而且往往是第一步。

當然,如果數據損壞了,即使元數據完好無缺,那麼數據也是損壞了。比如,你誤刪了一個文件,那麼,分區結構再完好對於文件被刪也於事無補。

基於以上分析,我們可以把數據損壞簡單分三類類:元數據損壞、數據損壞或者前麵兩種損壞類型的混合型損壞。

元數據修複可以簡易處理

以基於磁盤的分區、LVM以及文件係統為例。分層結構的數據格式都有嚴格的格式(比如分區的數據結構就是一個C的struct),出現位置也固定(有關分區的元數據記錄在第一個扇區的446~462字節之間),而且這些數據結構往往都帶有魔數(比如,分區的類型83),而且常用的分層結構,也不外乎分區、LVM以及文件係統等幾種。因此,對於元數據以及係統如何處理元數據,我們都容易追蹤和檢查。因此,可以預期,修複元數據,有簡易方案。

原理

如果有數據損壞,那麼除非有日誌、備份,或者數據本身有邏輯可供使用,否則數據是不能恢複了。比如,通常的文件刪除操作,係統隻是解除了文件名稱和文件內容相關間的聯係而已。文件本身的內容還是記錄再磁盤上。這種情況下,隻要重建文件名稱和文件內容間的聯係即可恢複文件。

相對而言,簡單情形的是元數據損壞。如果隻是元數據損壞,而且我們知道正確的元數據。因為元數據操作,不會觸及數據部分,因此,我們隻要重建元數據部分即可恢複數據。如果涉及到多層,則逐層恢複即可。以分區丟失為例。

比如我們有一塊數據盤,整盤我們隻是用fdisk分了一個區,現在分區丟失了。這種情形下,隻要用fdsik,按照默認情形,重新分區就能恢複分區。

就這種情形,我們給出一個可用的分析流程。

9C02C2FC6EABF73CE7049F972A7153E4

症狀和初步排查

症狀

客戶反饋

降配重啟後,係統無法啟動

排查發現客戶一邏輯卷無法掛載導致重啟失敗。在/etc/fstab中注釋掉邏輯卷的掛載配置,係統啟動成功。

但是客戶的邏輯卷上有重要數據。此邏輯卷在數據盤上,數據盤大小是2TB。此磁盤全部2TB全部分配給一個分區,此分區上創建有LVM結構。

分區數據如下

[root@localhost ~]# fdisk -l -u /dev/vdb

Disk /dev/vdb: 2199.0 GB, 2199023255552 bytes
5 heads, 3 sectors/track, 286331153 cylinders, total 4294967296 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xde220917

   Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048  4294967294  2147482623+  83  Linux
[root@localhost ~]#

初步排查

首先確定分區上是否有數據,通過查看一些扇區,我們就會有很大的概率確認這一點。當然也可以逐扇區確認。

逐扇區確認,可以用如下命令辦理。假設磁盤是/dev/vdb。

max_sector_to_check=nrsector
for i in $(seq 0 ${max_sector_to_check});do dd if=/dev/vdb bs=512 count=1 skip=${i} 2>/dev/null | sha256sum;done | sort -n | uniq;

當然,也可以通過抽樣檢查來確認。這種方法通常是檢查磁盤分區的前麵一部分扇區。比如,下麵的例子,通過檢查前麵幾十個扇區,我們可以確認磁盤上確有數據。

[root@localhost ~]# dd if=/dev/vdb1 bs=512 count=60 2>/dev/null | od -tx1
0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0007000 f9 80 00 00 f9 80 01 00 f9 80 02 00 f9 80 03 00
0007020 f9 80 04 00 f9 80 0c 00 f9 80 0d 00 f9 80 18 00
0007040 f9 80 28 00 f9 80 3e 00 f9 80 79 00 f9 80 ab 00
0007060 f9 80 38 01 f9 80 6c 01 f9 80 45 04 f9 80 b0 04
0007100 f9 80 1a 06 f9 80 d0 0c f9 80 84 1e 00 00 00 00
0007120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0017000 fa 80 00 00 fa 80 01 00 fa 80 02 00 fa 80 03 00
0017020 fa 80 04 00 fa 80 0c 00 fa 80 0d 00 fa 80 18 00
0017040 fa 80 28 00 fa 80 3e 00 fa 80 79 00 fa 80 ab 00
0017060 fa 80 38 01 fa 80 6c 01 fa 80 45 04 fa 80 b0 04
0017100 fa 80 1a 06 fa 80 d0 0c fa 80 84 1e 00 00 00 00
0017120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0027000 fb 80 00 00 fb 80 01 00 fb 80 02 00 fb 80 03 00
0027020 fb 80 04 00 fb 80 0c 00 fb 80 0d 00 fb 80 18 00
0027040 fb 80 28 00 fb 80 3e 00 fb 80 79 00 fb 80 ab 00
0027060 fb 80 38 01 fb 80 6c 01 fb 80 45 04 fb 80 b0 04
0027100 fb 80 1a 06 fb 80 d0 0c fb 80 84 1e 00 00 00 00
0027120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0037000 fc 80 00 00 fc 80 01 00 fc 80 02 00 fc 80 03 00
0037020 fc 80 04 00 fc 80 0c 00 fc 80 0d 00 fc 80 18 00
0037040 fc 80 28 00 fc 80 3e 00 fc 80 79 00 fc 80 ab 00
0037060 fc 80 38 01 fc 80 6c 01 fc 80 45 04 fc 80 b0 04
0037100 fc 80 1a 06 fc 80 d0 0c fc 80 84 1e 00 00 00 00
0037120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0047000 fd 80 00 00 fd 80 01 00 fd 80 02 00 fd 80 03 00
0047020 fd 80 04 00 fd 80 0c 00 fd 80 0d 00 fd 80 18 00
0047040 fd 80 28 00 fd 80 3e 00 fd 80 79 00 fd 80 ab 00
0047060 fd 80 38 01 fd 80 6c 01 fd 80 45 04 fd 80 b0 04
0047100 fd 80 1a 06 fd 80 d0 0c fd 80 84 1e 00 00 00 00
0047120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0057000 fe 80 00 00 fe 80 01 00 fe 80 02 00 fe 80 03 00
0057020 fe 80 04 00 fe 80 0c 00 fe 80 0d 00 fe 80 18 00
0057040 fe 80 28 00 fe 80 3e 00 fe 80 79 00 fe 80 ab 00
0057060 fe 80 38 01 fe 80 6c 01 fe 80 45 04 fe 80 b0 04
0057100 fe 80 1a 06 fe 80 d0 0c fe 80 84 1e 00 00 00 00
0057120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0067000 ff 80 00 00 ff 80 01 00 ff 80 02 00 ff 80 03 00
0067020 ff 80 04 00 ff 80 0c 00 ff 80 0d 00 ff 80 18 00
0067040 ff 80 28 00 ff 80 3e 00 ff 80 79 00 ff 80 ab 00
0067060 ff 80 38 01 ff 80 6c 01 ff 80 45 04 ff 80 b0 04
0067100 ff 80 1a 06 ff 80 d0 0c ff 80 84 1e 00 00 00 00
0067120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0074000
[root@localhost ~]# 

接下來使用testdisk工具恢複數據。嚐試數次,testdisk工具總是在掃描到2%時停滯,處理過程不能繼續。

初次恢複嚐試

分區還在,但是LVM結構丟失,經檢查,由LVM工具鏈維護的備份數據**/etc/lvm/backup/vg_xxxxxx**文件還在。因此,這種情形下,按照我們的恢複流程,隻要在分區之上,嚐試重建LVM和文件係統,應該就可以解決問題。

[root@localhost ~]# pvdisplay /dev/vdb
  Failed to find device for physical volume "/dev/vdb".
[root@localhost ~]# ls /etc/lvm/backup/vg_xxxxxx 
/etc/lvm/backup/vg_xxxxxx
[root@localhost ~]#

根據備份數據恢複LVM結構,可以參考Recovering Physical Volume Metadata。可惜的是,我們第一步就折戟沉沙了。

[root@localhost ~]# pvcreate --uuid "X1cHlO-kdFk-RZIM-1L12-qHit-0QA5-C1fZxm" --restorefile /etc/lvm/backup/vg_xxxxxx /dev/vdb1
  WARNING: Device /dev/vdb1 has size of 4294965247 sectors which is smaller than corresponding PV size of 4294966977 sectors. Was device resized?
  One or more devices used as PVs in VG vg_xxxxxx have changed sizes.
  Can't initialize physical volume "/dev/vdb1" of volume group "vg_xxxxxx" without -ff
[root@localhost ~]# 

看樣子,分區的數據有些地方出錯了。根據上麵命令報錯的信息,對比LVM的備份數據和分區數據,很快我們就發現了問題。現有分區記錄的其擁有的扇區數目,少於其上LVM卷組記錄的扇區數量。

578896DD48DC5D2C4066BFF980F65DF3

問題出在哪裏?

因為種種原因,我們不能確認分區信息和LVM備份數據為何不一致。但是,我們可以進一步從磁盤上提取、分析數據。因為有關分區的元數據在(分區在),所以我們進一步檢查磁盤上還有沒有有關LVM的元數據?這隻要使用下麵的命令行

dd if=/dev/vdb1 bs=512 count=128 2>/dev/null | od -tc

結果及其結果分析如下

02F56A8A85A2B2B8AD17DD45FFB50C01

所以,磁盤上還有有關LVM的元數據,但是為什麼係統沒有憑借這些數據構建出LVM結構呢?我們創建一個測試環境,用strace追蹤下係統處理LVM物理卷元數據的執行路徑。如下命令即可

strace -s 512 pvdisplay

當然,更好的辦法是把strace記錄放置到文件中,以備仔細檢查

starce -o path_to_strace_log -s 512 -f -ff pvdisplay

我們組合使用strace和grep命令來確認係統默認的LVM物理卷位置。如果你沒有耐心分析下麵的數據,請跳過直接看後麵的截圖

strace -o /tmp/pvdisplay-strace.log -s 512 pvdisplay
grep grep -E '^open|^lseek|^read' /tmp/pvdisplay-strace.log

數據清洗結果如下。如果沒有耐心分析,請跳過直接看下麵的分析截圖

[root@localhost ~]# grep -E '^open|^lseek|^read|^close' /tmp/pvdisplay-strace.log
…
close(4)                                = 0
open("/dev/vdb1", O_RDONLY|O_DIRECT|O_NOATIME) = 4
close(4)                                = 0
open("/dev/vdb1", O_RDONLY|O_DIRECT|O_NOATIME) = 4
lseek(4, 21037056, SEEK_SET)            = 21037056
read(4, "…", 512) = 512
lseek(4, 21118976, SEEK_SET)            = 21118976
read(4, "…", 512) = 512
lseek(4, 0, SEEK_SET)                   = 0
read(4, "…", 512) = 512
lseek(4, 4096, SEEK_SET)                = 4096
read(4, "\26\326\216\333 LVM2 x[5A%r0N*>\1\0\0…", 512) = 512
close(4)                                = 0
…
[root@localhost ~]# 

6CDFD7748A9A3A5C8E24EBB1041903E7

很明顯,係統預期LVM元數據是在分區的第8個扇區,但是在需要做數據恢複的磁盤上,LVM的元數據卻是在第71個扇區,而分區的起始扇區是2048,因此,LVM數據根本不在分區內。這就是為什麼磁盤上還有LVM元數據,係統卻沒有識別出來LVM的原因。

既然係統是因為有關LVM的元數據所在扇區不對而導致係統無法識別LVM結構,設想通過重新分區,我們把有關LVM元數據調整到分區的第8個扇區。稍加計算,就會發現,隻要把分區的起始扇區從第2048個扇區調整到第63個扇區即可。不僅如此,通過調整分區大小,我們同樣也解決了磁盤分區扇區數不足的問題

B79CA9B05F3FC37FE7DF5956B124EBCE

數據恢複

較新的fdisk工具,不允許起始扇區小於2048,因此,我們用parted工具來調整分區的起始扇區。

調整過程是先刪掉扇區,而後再創建之。而結果正如我們所預期的,分區調整完成,客戶的數據立刻恢複了。物理卷、卷組、邏輯卷、文件係統以及數據,都完好無損。

結語

從處理這個實際case可以看出,如果知道如何識別各層元數據,比如分區),LVM文件係統;能夠追蹤係統處理各層元數據的邏輯,那麼,組合使用UNIX常用的ddod等工具,足以簡單有效的處理元數據損壞的情形,快速恢複數據。如果掌握了常見的係統調用,並且掌握了strace工具,那麼對於如何識別元數據以及係統如何處理元數據,完全可以通過簡單分析strace輸出拿到相應答案。

除了易學、簡單、快捷、高效,元數據修複方案還有一個優點,就是可以確保不會破壞數據。這可能是這個方案的最大亮點。

參考

  1. 數據恢複軟件列表
  2. shred (Unix))
  3. 使用Linux文件恢複工具
  4. 如何恢複 Linux 上刪除的文件,第 1 部分
  5. 硬盤分區
  6. RHEL 6 Logical Volume Manager Administration
  7. 文件係統
  8. Linux man pages online

最後更新:2017-07-10 12:02:25

  上一篇:go  夢想開店賣包子
  下一篇:go  編譯redis報錯/deps/hiredis/libhiredis.a解決