Aar*_*all 6 iso dd system-installation tee
一年多前,我撰写了有关如何在 Linode 上安装 NixOS 的教程。
似乎大多数涉及将 iso 文件放在安装介质上的教程总是使用dd,这就是为什么“现在 dd 仍然相关吗?” 没有回答我的问题。本教程最初也使用过dd,我对其进行了稍微修改,以获取 sha256 校验和来验证 iso,同时使用 管道从源中传输它tee,如下所示:
curl -L $iso | tee >(dd of=/dev/sda) | sha256sum
Run Code Online (Sandbox Code Playgroud)
但在我看来,dd这里有点多余,而且实际上比下面的慢很多:
curl -L $iso | tee /dev/sda | sha256sum
Run Code Online (Sandbox Code Playgroud)
几个月前,在帮助别人遵循教程时,我记得他们在使用更简单的方法时遇到了问题,但是当我上周末刚刚尝试过两次单独的安装时,它似乎工作得很好,而且速度也相当快。
此修改是否足够可靠,可以提交更新教程的拉取请求?
或者我只是幸运地让它工作,并且dd实际上用于创建安装介质更安全、更可靠 - 因此我们应该按原样保留教程?
Gil*_*il' 15
使用dd并不更安全、更快或更不可靠。事实上,这里引入了两种额外的失败风险。如果人们手动遵循这些说明,这两种风险在实践中都不太可能成为问题,但如果这些说明位于自动化脚本中,则这两种风险都将是严重的错误。
观察:
\nbash-5.0$ echo hello | tee >(sleep 1; echo done); echo next step\nhello\nnext step\nbash-5.0$ done\nRun Code Online (Sandbox Code Playgroud)\n在 bash 中,输出过程替换是异步的。当命令包含进程替换时>(\xe2\x80\xa6),它不会等待进程替换完成。
因此,当\xe2\x80\xa6 | tee >(dd of=/dev/sda) | sha256sum返回时,可能还有数据仍在通过dd. 这不太可能持续足够长的时间以供人类做出反应并键入另一个命令,但它可能会破坏运行其他命令(例如eject或mount之后)的脚本。
让我们开始一个一切正常的名义情况。
\nbash-5.0$ head -c 1m </dev/zero | tee >(cat >/dev/null) | wc -c; echo $?\n1048576\n0\nRun Code Online (Sandbox Code Playgroud)\n现在让我们看看如果数据写入命令失败会发生什么情况。
\nbash-5.0$ head -c 1m </dev/zero | tee >(false) | wc -c; echo $?\n8192\n0\nRun Code Online (Sandbox Code Playgroud)\n该命令具有成功状态,因为管道的退出状态仅取决于右侧。这个想法是,如果将数据生成器通过管道传输到数据处理器,则数据处理器的工作就是检测故障。不幸的是,这仅适用于数据格式允许数据处理器检测故障的情况,但通常情况并非如此,特别是此处并非如此。
\n请注意,tee一旦无法写入连接到的管道,就彻底放弃false。由于false从未读取任何数据,因此通过 to 的唯一数据wc -c是两个PIPE_BUF(一个tee写入两个管道,另一个tee仅写入管道 towc但未能写入管道 to false)。根据false退出与tee写入管道和wc消耗数据的相对时间,可能只有 1 个或 0 个PIPE_BUF通过。
tee通过设置该选项可以检测故障pipefail。(这种可能性存在于 ksh、bash 和 zsh 中,但不存在于普通 sh 中。)
bash-5.0$ set -o pipefail; head -c 1m </dev/zero | tee >(false) | wc -c; echo $?\n8192\n141\nRun Code Online (Sandbox Code Playgroud)\ntee无法写入管道,因此它死于 SIGPIPE,对应的 shell 状态为 128 + SIGPIPE 的数值(在 Linux 上为 13)。由于该pipefail选项,这会导致整个管道以相同的状态退出。
请注意,管道反映的是 的失败tee,而不是直接反映进程替换中命令的失败。如果进程替换中的命令成功读取了所有数据但未成功处理,则不会检测到错误。
bash-5.0$ head -c 1m </dev/zero | tee >(cat >/dev/null; false) | wc -c; echo $?\n1048576\n0\nRun Code Online (Sandbox Code Playgroud)\nwc -c处理了所有数据。cat >/dev/null; false模拟未正确处理所有输入的命令。尽管如此,命令的状态表明成功。
在您的实际示例中,这意味着如果数据末尾存在错误,例如因为目标设备比图像小一点,则不会检测到此错误(除非通过错误消息来自dd)。
set -o pipefail\ncurl -L $iso | tee /dev/sda | sha256sum\nRun Code Online (Sandbox Code Playgroud)\n或者,可以说更简单:
\ncurl -L $iso | tee >/dev/sda >(sha256sum)\nRun Code Online (Sandbox Code Playgroud)\n请注意,如果没有pipefail,第二个命令即使curl失败也会成功。然而,这种失败肯定会导致错误的校验和。
\n\n似乎大多数涉及将 iso 文件放在安装介质上的教程总是使用 dd,这就是为什么“现在 dd 仍然相关吗?” 没有回答我的问题
\n
嗯,或多或少确实如此。具体来说,它回答了是否有任何目的的问题dd:没有。它没有涵盖使用dd这种特定方式时出现的具体问题,这一次实际上并不是由于dd其本身造成的。
大多数教程使用的原因dd是大多数教程使用dd. 这是一个自我延续的传奇。人们使用它dd是因为他们在其他地方看到过它的使用,尽管他们并不真正理解为什么。它的语法与其他命令不同,因此显得有些神秘和强大。但在dd of=/dev/sda,所有的力量都在/dev/sda,却没有dd。这只是一种自命不凡、脆弱的写作方式cat >/dev/sda。