透過布林 OR 合併兩個二進位影像檔案(ddrescue 輸出檔案名稱錯誤)

透過布林 OR 合併兩個二進位影像檔案(ddrescue 輸出檔案名稱錯誤)

我在恢復 ddrescue 時使用了錯誤的輸出檔名,犯了一個愚蠢的錯誤。這就是發生的事情:

ddrescue -b 2048 -d -v /dev/sr1 IDTa.img IDTa.ddrescue.log 

然後計算機崩潰了,我錯誤地恢復了:

ddrescue -b 2048 -d -v /dev/sr1 IDTa.iso IDTa.ddrescue.log

我收集到兩個圖像檔案都會開始全部歸零,所以我想如果我對兩個檔案進行布林或運算,那麼結果將是如果我沒有犯錯的話 ddrescue 會輸出什麼?

這些文件不是彼此的延續(例如如何合併兩個 ddrescue 影像?)因為我之前已經運行過ddrescue -n,並且成功完成。即 IDTa.img 包含大部分數據,IDTa.iso 包含圖像各處的分散塊(這些塊在 IDTa.img 中為零)。

有沒有簡單的 CLI 方法可以做到這一點?我可能可以用 C 語言做到這一點,但我很生疏!也可能是 Python 的一個很好的第一個練習,我從來沒有時間學習它!儘管如此,如果已經存在一些東西,就不要特別想重新發明輪子。不太注重性能。

更新:(如果這是回复答案的錯誤位置,我深表歉意。“評論”選項似乎允許的字符太少,所以我在這裡回复!)

我還嘗試過使用 '--fill-mode=?' 進行 ddrescue作為上述問題的解決方案,但沒有成功。這就是我所做的:

ddrescue --generate-mode -b 2048 -v /dev/sr1 IDTa.img IDTa.img.log
cp IDTa.img IDTa.img.backup
ddrescue '--fill-mode=?' -b 2048 -v IDTa.iso IDTa.img IDTa.img.log 

為了檢查,我查找了 IDTa.iso 有資料的第一個位置:

hexdump -C IDTa.iso |less

輸出是:

00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
001da800  00 00 01 ba 21 00 79 f3  09 80 10 69 00 00 01 e0  |....!.y....i....|
...
001db000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
...

我在 IDTa.img 中查找了 001da800:

hexdump -C IDTa.img |less
/001da800

輸出:

001da800  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
001db000  00 00 01 ba 21 00 7b 00  bf 80 10 69 00 00 01 e0  |....!.{....i....|
...

那麼,位置 001da800 處的資料還沒有從檔案 IDTa.iso 複製到 IDTa.img 嗎?

檢查IDTa.img.log:

# Mapfile. Created by GNU ddrescue version 1.22
# Command line: ddrescue --fill-mode=? -b 2048 -v IDTa.iso IDTa.img IDTa.img.log
# Start time:   2021-06-28 13:52:39
# Current time: 2021-06-28 13:52:46
# Finished
# current_pos  current_status  current_pass
0x299F2000     +               1
#      pos        size  status
0x00000000  0x00008000  ?
0x00008000  0x001D2800  +
0x001DA800  0x00000800  ?
0x001DB000  0x00049000  +
...

以及現實檢驗:

diff -q IDTa.img IDTa.img.backup

返回沒有區別。

更新2:

@Kamil 透過刪除參數編輯了解決方案(見下文)--fill-mode=?。看來工作了!

答案1

我認為這可以自己完成ddrescue。你需要--generate-mode

ddrescue使用選項呼叫時--generate-mode,它在“生成模式”下運行,這與預設的“救援模式”不同。也就是說,在「生成模式」下ddrescue不會拯救任何東西。它只是嘗試產生mapfile以供以後使用。

[…]

ddrescue在某些情況下可以從 和 產生近似mapfile,infile和 中的(部分)副本outfile,這幾乎與精確的 一樣好mapfile。它透過簡單地假設包含全零的扇區沒有被拯救來實現這一點。

[…]

ddrescue --generate-mode infile outfile mapfile

來源

複製這兩個影像,以防萬一。如果您的檔案系統支援 CoW-copy,則使用cp --reflink=always每個影像幾乎可以立即進行複製。

您需要確保兩個圖像的大小相同。如果其中之一較小,則應將其放大,即應附加零(可能是稀疏零)。此程式碼將自動執行此操作(truncate必需):

( f1=IDTa.img
  f2=IDTa.iso
  s1="$(wc -c <"$f1")"
  s2="$(wc -c <"$f2")"
  if [ "$s2" -gt "$s1" ]; then
    truncate -s "$s2" "$f1"
  else
    truncate -s "$s1" "$f2"
  fi
)

(我使用了子 shell,因此變數會隨之消失,而主 shell 不受影響。)

現在讓工具分析您的第一張影像並找出哪些磁區可能未獲救:

ddrescue --generate-mode -b 2048 -v /dev/sr1 IDTa.img new_mapfile

注意new_mapfile這裡有一個新文件,不是你的IDTa.ddrescue.log。請勿觸摸IDTa.ddrescue.log

new_mapfile產生後,其中的行應顯示狀態+?,取決於對應的片段是否被視為「已救援」或「未嘗試」。

IDTa.img現在您想要用來自 的資料填充據稱「未嘗試過」的區塊IDTa.iso。下一個命令將修改IDTa.img.

IDTa.img透過讀取資料來拯救所謂的「未嘗試過」的區塊IDTa.iso

ddrescue -b 2048 -v IDTa.iso IDTa.img new_mapfile

現在,修改後的內容IDTa.img和未修改的內容IDTa.ddrescue.log應該和您沒有犯錯一樣好。

筆記:

  • 可能發生了一些包含全零的扇區實際上被拯救的情況。--generate-mode將它們分類為?.它們將充滿從IDTa.iso「徒勞」中獲取的數據。這對於最終結果並不重要,因為它們在另一個文件中也全為零。
  • IDTa.iso如果在整個過程中互換和 ,結果應該是相同的IDTa.img(但請記住,如果這樣做,結果將在 中IDTa.iso)。所以有一個選擇。我--generate-mode將使用預計包含全零的扇區較少的文件,因為這應該最大限度地減少最後一個命令的工作量。
  • 此方法適用於常規文件IDTa.isoIDTa.img.相反,如果您有一個區塊設備,那麼您工作之前的「隨機」內容ddrescue會幹擾並破壞結果(因此,首先解決不同大小的潛在問題是沒有意義的,這truncate沒有幫助)。
  • 我在嘗試拯救一個人時複製了你的錯誤後測試了該程序片狀裝置

相關內容