恢復資料的方法
python的實現:
zfs是乙個非常穩定可靠的檔案系統,但是還是有一定機率會出現系統壞掉,使用者資料不能讀取出來的情況。如果乙個zfs儲存同時連線到2個控制器,兩個控制器同時zpool import池,由於元資料覆蓋,就會出現整個檔案系統壞掉。
首先應該參考官網:
其中修復 zfs 儲存池範圍內的損壞的方法依次如下:
1.可以嘗試使用 zpool clear -f 命令或 zpool import - f 命令恢復池。這些命令嘗試回滾最後幾次池事務,使其回到執行狀態。可以使用 zpool status 命令檢視損壞的池和建議的恢復步驟.
zpool clear -f tpool
zpool import tpool
zpool import -f tpool
2.您可以在唯讀模式下匯入受損的池。此方法使您可以匯入該池,從而可以訪問資料。
zpool import -o readonly=on tpool
3.您可以使用 zpool import -m 命令匯入缺少日誌裝置的池。
4.如果無法使用上述池恢復方法恢復池,則必須從備份副本中恢復池及其所有資料。所用的機制通常隨池配置和備份策略的不同而有很大差別。首先,儲存 zpool status 命令所顯示的配置,以便在銷毀池後可以重新建立它。然後,使用 zpool destroy -f 命令銷毀池。此外,將描述資料集的布局和在本地設定的各種屬性的檔案儲存在某個安全的位置(因為在使池無法訪問後此資訊將變得無法訪問)。使用池配置和資料集布局,可以在銷毀池後重新構造完整的配置。然後可以使用任何備份或恢復策略填充資料。
1.zpool import -fx
2.zpool import -o readonly=on
3.the combination of zdb -lu and zpool import -t.
如果這些都不能把zfs import進來,而使用者又沒有備份,這意味著資料的丟失。在這種情況下,是沒有現成的工具可以恢復資料,只能依賴人工根據具體問題去編碼,把磁碟上面的資料恢復出來。
我們的思路是這樣的:
1.使用zdb -e -vvvvvv zpoolname >> filename.txt
2.根據zdb執行過程中的錯誤,修改zdb原始碼,略過錯誤的元資料,盡量把元資料完整讀取出來。原始碼中如果發現錯誤,就讀取元資料資訊時直接退出,我們應該注釋掉該行。
3.根據元資料裡面的檔案資訊和位址資訊,寫乙個自動處理指令碼,把檔案讀取出來,儲存到新的儲存空間。
使用的命令如下:
zdb_read -r -e -r 檔案長度 pool2 元資料中的位址1:元資料中的位址2:元資料中的檔案長度:f >> 新的檔案路徑
為了使zdb能夠直接讀取出檔案,我們必須修改這個工具,直接擷取檔案長度大小。
def parse_metadata_blk(self):
self.file_path = ""
self.file_uid = ""
self.file_gid = ""
self.file_mode = 0
self.file_size = 0
self.blk_size = 0
self.blk_type = "unknown"
self.address_list =
for line in self.lines:
if not line:
continue
var_list = line.split()
if len(var_list) <= 1:
#print "error. can't parse: " + line
continue
if line.find("zfs plain file (k=inherit) (z=inherit)") != -1:
self.blk_type = "file"
continue
if line.find("zfs directory (k=inherit) (z=inherit)") != -1:
self.blk_type = "dir"
continue
if self.blk_type == "unknown":
continue
if var_list[0] == "path":
self.file_path = self.output_dir + var_list[1].strip()
continue
if var_list[0] == "uid":
self.file_uid = int(var_list[1].strip())
continue
if var_list[0] == "gid":
self.file_gid = int(var_list[1].strip())
continue
if var_list[0] == "mode":
self.file_mode = int(var_list[1].strip())
continue
if self.blk_type != "file":
continue
if var_list[0] == "size":
self.file_size = int(var_list[1].strip())
continue
if line.startswith("indirect blocks:"):
start_address = true
continue
if len(var_list) >= 6 and var_list[1] == "l0":
self.blk_size_16 = var_list[3].split("l/")[0]
self.blk_size = int(var_list[3].split("l/")[0], 16)
continue
return 0
def recover_file(self):
if not self.address_list:
return 0
if not self.file_path:
return 0
if os.path.exists(self.file_path):
os.remove(self.file_path)
print "the meta data is " + self.current_meta
print "recovering file: %s size: %d" % (self.file_path, self.file_size)
ret = 1
for addr in self.address_list:
addr_list = addr.split(":")
cmd = "%s/zdb_read -r -e -r %d pool2 %s:%s:%s:f >> %s" % (self.pwdstr, self.file_size, addr_list[0], addr_list[1], self.blk_size_16, self.file_path)
try:
ret, out, err = self.run_system_cmd(cmd)
#ret = self.run_cmd(cmd)
except exception, e:
print str(e)
return 1
self.file_size = self.file_size - self.blk_size
if ret != 0:
print "failed to recover: " + self.file_path
return 1
else:
self.recover_file_num = self.recover_file_num + 1
# update the file attribute.
try:
os.chmod(self.file_path, self.file_mode)
os.chown(self.file_path, self.file_uid, self.file_gid)
except exception, e:
print str(e)
return 1
return 0
ZFS檔案系統
zfs zettabyte file system 源自於sun microsystems為solaris作業系統開發的檔案系統。zfs是乙個具有高儲存容量 檔案系統與卷管理概念整合 嶄新的磁碟邏輯結構的輕量級檔案系統,同時也是乙個便捷的儲存池管理系統。zfs是乙個使用common developm...
ZFS檔案系統
本文 zfs zettabyte file system 源自於sun microsystems為solaris作業系統開發的檔案系統。zfs是乙個具有高儲存容量 檔案系統與卷管理概念整合 嶄新的磁碟邏輯結構的輕量級檔案系統,同時也是乙個便捷的儲存池管理系統。zfs是乙個使用common devel...
伺服器zfs檔案系統故障資料恢復過程
伺服器在正常執行的時候突然崩潰,沒有斷電 進水 異常操作 機房不穩定等外部因素。伺服器管理員對裝置進行重啟後發現無法進入系統,需要對伺服器內的資料進行恢復。伺服器管理員對所有硬碟進行扇區級映象後將映象檔案送到資料恢復中心進行資料恢復。伺服器資料恢復工程師對客戶的故障伺服器進行底層資料分析得到如下資訊...