Command-Line

通過布爾 OR 合併兩個二進製圖像文件(ddrescue 輸出文件名錯誤)

  • July 1, 2021

我在恢復 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=?參數來編輯解決方案(見下文)。看來工作!

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

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

$$ … $$ ddrescue在某些情況下,可以生成一個近似的mapfile、來自infile和的(部分)副本outfile,這幾乎和一個精確的mapfile. 它通過簡單地假設包含全零的扇區未獲救來實現這一點。

$$ … $$

ddrescue --generate-mode infile outfile mapfile

來源

複製兩張圖片,以防萬一。如果您的文件系統支持 CoW 複製,則使用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,其中的行應顯示 status+?,具體取決於相應的片段是否被視為“已獲救”或“未嘗試”。

現在你想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這無濟於事)。
  • 我在嘗試搶救易碎設備時複製了您的錯誤後測試了該程序。

引用自:https://unix.stackexchange.com/questions/655288