將 iso 內容寫入 dd 還是直接寫入 /dev/sda?
一年多前,我貢獻了一篇關於如何在 Linode 上安裝 NixOS 的教程。
似乎大多數處理將 iso 文件放在安裝介質上的教程總是使用
dd
,這就是為什麼“現在 dd 仍然相關?” 不回答我的問題。本教程最初也是使用dd
的,我稍微修改了它以獲取 sha256 校驗和以驗證 iso,同時使用 . 從源管道傳輸它tee
,如下所示:curl -L $iso | tee >(dd of=/dev/sda) | sha256sum
但在我看來,
dd
這裡有些多餘,實際上比以下要慢得多:curl -L $iso | tee /dev/sda | sha256sum
幾個月前,在幫助其他人按照教程進行操作時,我記得他們在使用更簡單的方法時遇到了問題,但是當我上週末嘗試過兩次單獨安裝時,它似乎工作得很好,而且速度也非常快。
這種修改是否足夠可靠,可以送出更新教程的拉取請求?
或者我只是幸運地讓它工作,並且
dd
實際上用於創建安裝媒體更安全、更可靠——因此我們應該保持原樣?
使用
dd
不是更安全、更快或更不可靠。事實上,在這裡,它引入了兩個額外的失敗風險。如果人們手動遵循這些指令,則這兩種風險在實踐中都不會成為問題,但如果指令在自動腳本中,它們將是重大錯誤。錯誤:比賽條件
觀察:
bash-5.0$ echo hello | tee >(sleep 1; echo done); echo next step hello next step bash-5.0$ done
在 bash 中,輸出程序替換是非同步的。當命令包含程序替換
>(…)
時,它不會等待程序替換完成。因此,當
… | tee >(dd of=/dev/sda) | sha256sum
返回時,可能會有數據仍在傳輸中dd
。這不太可能持續足夠長的時間讓人類做出反應並鍵入另一個命令,但它可能會破壞執行類似eject
或mount
之後執行其他命令的腳本。錯誤:缺少錯誤檢測
讓我們開始一個一切正常的名義案例。
bash-5.0$ head -c 1m </dev/zero | tee >(cat >/dev/null) | wc -c; echo $? 1048576 0
現在讓我們看看如果數據寫入命令失敗會發生什麼。
bash-5.0$ head -c 1m </dev/zero | tee >(false) | wc -c; echo $? 8192 0
該命令具有成功狀態,因為管道的退出狀態僅取決於右側。這個想法是,如果您將數據生產者通過管道傳輸到數據處理器中,那麼數據處理器的工作就是檢測故障。不幸的是,這僅適用於數據格式允許數據處理器檢測故障時,這通常不是這種情況,尤其是這裡不是這種情況。
請注意,
tee
一旦無法寫入連接到false
. 由於false
從未讀取任何數據,因此唯一通過的數據wc -c
是兩個PIPE_BUF
(一個tee
寫入兩個管道,一個tee
只寫入管道到管道wc
但未能寫入管道到false
)。根據false
退出與tee
寫入管道和wc
使用數據的相對時間,可能只有 1 或 0PIPE_BUF
成功通過。
tee
可以通過設置pipefail
選項來檢測失敗。(這種可能性存在於 ksh、bash 和 zsh 中,但不存在於普通 sh 中。)bash-5.0$ set -o pipefail; head -c 1m </dev/zero | tee >(false) | wc -c; echo $? 8192 141
tee
無法寫入管道,因此它死於 SIGPIPE,對應的 shell 狀態為 128 + SIGPIPE 的數值(Linux 上為 13)。由於該pipefail
選項,這會導致整個管道以相同的狀態退出。請注意,管道反映了
tee
程序替換中的失敗,而不是直接反映命令的失敗。如果程序替換中的命令成功讀取了所有數據但沒有成功處理,則不會檢測到錯誤。bash-5.0$ head -c 1m </dev/zero | tee >(cat >/dev/null; false) | wc -c; echo $? 1048576 0
wc -c
處理了所有的數據。cat >/dev/null; false
模擬一個沒有正確處理其所有輸入的命令。儘管如此,命令的狀態表明成功。這在您的實際範例中意味著如果數據末尾有錯誤,例如因為目標設備比圖像略小,則不會檢測到此錯誤(除非通過來自 的錯誤消息
dd
) .簡單、正確的解決方案
set -o pipefail curl -L $iso | tee /dev/sda | sha256sum
或者,可以說更簡單:
curl -L $iso | tee >/dev/sda >(sha256sum)
請注意,如果沒有
pipefail
,第二個命令將在curl
失敗時成功。但是,保證此故障會導致錯誤的校驗和。dd 用法的一般說明
似乎大多數處理將 iso 文件放在安裝媒體上的教程總是使用 dd,這就是為什麼“現在 dd 仍然相關?” 沒有回答我的問題
好吧,它或多或少確實做到了。具體來說,它回答了是否
dd
有任何目的的問題:它沒有。它沒有涵蓋使用dd
這種特殊方式的具體問題,這一次實際上並不是由於dd
它本身造成的。大多數教程使用的原因
dd
是大多數教程使用dd
. 這是一個自我延續的傳奇。人們使用dd
它是因為他們已經看到它在其他地方使用過,即使他們並不真正理解為什麼。它的語法不同於其他所有命令,因此顯得有些神秘和強大。但在dd of=/dev/sda
,所有的力量都在/dev/sda
,沒有在dd
。這只是一種自命不凡、脆弱的寫作方式cat >/dev/sda
。