通過布爾 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=?
參數來編輯解決方案(見下文)。看來工作!
我認為這可以自己完成
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.iso
和IDTa.img
. 相反,如果您有一個塊設備,那麼在您使用之前它的“隨機”內容ddrescue
會干擾並破壞結果(因此首先解決不同尺寸的潛在問題是沒有意義的,truncate
這無濟於事)。- 我在嘗試搶救易碎設備時複製了您的錯誤後測試了該程序。