System-Installation

將 iso 內容寫入 dd 還是直接寫入 /dev/sda?

  • January 11, 2022

一年多前,我貢獻了一篇關於如何在 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。這不太可能持續足夠長的時間讓人類做出反應並鍵入另一個命令,但它可能會破壞執行類似ejectmount之後執行其他命令的腳本。

錯誤:缺少錯誤檢測

讓我們開始一個一切正常的名義案例。

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

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