![将图像写入当前根分区](https://linux22.com/image/224674/%E5%B0%86%E5%9B%BE%E5%83%8F%E5%86%99%E5%85%A5%E5%BD%93%E5%89%8D%E6%A0%B9%E5%88%86%E5%8C%BA.png)
我目前正在为类似树莓派的计算机构建磁盘映像(基于 Debian)。
我当前的工作流程如下所示:
- 创建磁盘映像(未压缩约 16GB;或压缩后 3GB)
- 关闭目标系统电源
- 弹出目标系统上的 SD 卡
- 将 SD 卡插入构建计算机
dd
将图像保存到 SD 卡上- 从构建计算机中弹出 SD 卡
- 将SD卡插入目标系统
- 将目标系统启动到新的操作系统版本
这很乏味。
我想缩短周期:
- 创建磁盘映像(未压缩约 16GB;或压缩后 3GB)
scp
目标系统的磁盘映像- 用新映像覆盖目标系统的 SD 卡
dd
- 将目标系统重新启动到新的操作系统版本
现在这显然有一个问题,我正在尝试覆盖包含以下内容的已安装分区根文件系统(磁盘映像仅包含根分区和引导分区)。最终,dd
(我用它来将图像复制到 SD 卡)将出现段错误,之后文件系统将无法修复,并且不再起作用。
所以我的问题是:有没有办法在当前 rootfs 上进行低级数据“恢复”?类似于:将相关二进制文件(dd
、reboot
)的一些“静态链接”版本复制到某个安全空间(RAM 磁盘),然后从那里运行。
理想情况下,我希望在不物理访问目标系统的情况下执行此操作(前提是我的磁盘映像未损坏)。
答案1
布莱恩的回答是我的建议:随时从网络接收图像。没有其他办法,因为你显然无法将图像放在你要覆盖的存储设备上。
但 Brian 的方法也会出现这个问题:假设您从当前启动的完整 debian 接收了映像,那么您将开始覆盖文件系统上当前的软件。呃,如果在下载并解压到原始磁盘时出现某些硬件中断、某些计时器/cron 作业或某些文件系统维护工具,会发生什么情况?您的整个系统可能会崩溃,也可能不会崩溃。
如果它崩溃了,您将留下一个无法在您可能无法访问的位置启动的嵌入式设备。这使得努力变得更加糟糕。
因此,您需要做的是接收和拆包软件不会覆盖您当前正在运行的软件。两种方法:
- 有两个根卷,例如 A 和 B。您当前的 debian 从 A 运行,您可以安全地覆盖 B 的所有内容。完成后,您可以告诉引导过程从 B 引导,并正确重新启动系统。 (通常,您有一个单独的“引导”分区,引导加载程序从中运行,并且其中包含 RPi 引导硬件的引导配置文件,这很......奇特。)
您需要两倍于系统大小的存储空间。
我起草了一个版本,您将如何做到这一点,完全在 RPi 上,在这个最近的答案 - 有一个要覆盖的根卷 (A),但不要在从该卷运行时执行此操作。相反,向您的引导加载程序添加一个条目,然后添加一个初始 RAM 文件系统文件到您的启动驱动器,该驱动器从几兆字节的映像启动,该映像加载到 RAM 中,并从那里接收和解包到 A。或者,您还有另一个 (C) 小卷,其中包含操作系统的最小版本,除了网络设置、SSH 和解压缩器之外,只需要很少的东西。
考虑到 Raspberry Pi 最重要的硬件故障模式是 SD 卡由于写入疲劳而停止工作,并且考虑到 SD 卡的价格有多低,我可能会选择第一种方法(A/B 启动,没有单独的“维护”操作系统) ),如果新系统工作完美,我会使用blkdiscard
现在未使用的卷,以便 SD 卡的磨损均衡有空间可以使用。
因此,总而言之,假设您使用方法 1:
- 如果您的系统需要略小于 32 GB 的空间,请购买 64 GB 卡
- 在该系统上安装 debian;但稍微修改默认分区方案:
- 当要求对磁盘进行分区时,使用“引导 - 使用整个磁盘并设置 LVM”,并在“分区方案”对话框中使用“一个分区中的所有文件”或“单独的 /home 分区”,具体取决于您是否希望将文件放在您的 pi 上的主目录是否可以在升级后继续存在(您也可以稍后更改它,没什么大不了的)。
- 确保要创建的卷概览中的大小总和略小于 SD 卡大小的一半(为简单起见,30 GB)。如有必要,请相应地减小 /(和 /home,如果存在)的大小。
- 将更改写入磁盘,完成安装,启动 RPi:应该可以工作。
- (当然,您也可以通过减小现有安装的分区大小来实现此目的,但有一些注意事项,以及以后的麻烦;我建议您从干净的 LVM 安装开始,您不会后悔的。我老实说,我不知道为什么 debian 在 2023 年没有默认使用 LVM,而是更喜欢使用特定于特定品牌个人计算机的分区方案,该计算机具有 8 位 CPU @ 5MHz 和 16 kB RAM(字面上从 1983 年开始),四十年前)
因此,在您的新系统运行之后(以及在您进一步设置任何内容之前),我们将描述更新过程:
- 在圆周率上:
- 检查是否有
oldsystem
逻辑卷(Look into/dev/mapper
)- 如果是的话,删除它,
sudo lvremove your-volume-group-name/oldsystem
- 如果是的话,删除它,
- 在 Pi 上:创建一个未压缩图像大小的新卷(假设此处为 30 GB):
sudo lvcreate -L 30G --name image_prep your-volume-group-name
- 检查是否有
- 最后加上您要发送的图像:
- 压缩图像,使用类似
zstd -12 -T0 < /what/you/want/to/compress > /path/to/images/filesystem.image.zst
(-12
已经是相当高的压缩,因此不是很快,但它可以节省您在网络上的时间,所以就是这样;1 到 18 之间的值有效,并且。) - 获取压缩图像的校验和:
sha256sum /path/to/images/filesystem.image.zst >> checksums
- 从主机获取图像到接收计算机;我很懒,我通常只是搭建一个小型的 python web 服务器(因为通过 SSH 复制会让可怜的 RPi 的 CPU 有点热):(
cd /path/to/images; python -m http.server -p HTTP/1.1 8765
如果需要,我会打开端口 8765;记下这台计算机的 IP 地址)
- 压缩图像,使用类似
- 在圆周率上:
- 获取镜像,解压到新卷,同时计算校验和:
mkfifo checksumpipe; sha256sum > checksum < checksumpipe &
curl http://ip.address.as.noted:8765/filesystem.image.zst | tee checksumpipe | zstd -d > /dev/your-volume-group-name/image_prep
- 验证中的校验和是否与传输主机上
checksum
保存的相同checksums
- 找出当前根卷的名称(如果有疑问,
cat /proc/cmdline
请查找root=/dev/mapper/your--volume--group--name-???
),并将其重命名为oldsystem
:sudo lvrename your-volume-group-name ??? oldsystem
- 将新镜像的卷重命名为以前的名称
sudo lvrename your-volume-group-name image_prep ???
- 挂载该卷,bind-mount
/dev/
,,/proc
/sys
进入/boot
其中,chroot
挂载并运行引导加载程序更新 - 重启
- 获取镜像,解压到新卷,同时计算校验和:
一种不太“debian”的方式可能会使用更精简的方式mender
;实际上有一个RPi 官方指南;忽略有关注册“hosted mender”的部分,您正在寻找“独立”模式。
答案2
如果您经常对同一个系统执行此操作。然后,考虑使用网络启动。您将在目标系统上安装一次引导加载程序。然后,目标将在每次重新启动加载时从网络服务器运行当前操作系统。
或者
写入根分区是一个坏主意。但是,您可以构建一个新的最小根,并将根旋转到新根。
答案3
您可以通过网络进行成像。
在来源上,dd if=/dev/hda bs=16065b | netcat < targethost-IP > 1234
估计的正好,netcat -l -p 1234 | dd of=/dev/hdc bs=16065b
首先在目标上按 Enter 键,然后在源上按 Enter。 dd 将从内存中运行,直到作业完成。程序不从存储驱动器运行。替换您选择的合理分区和块大小 (bs)。如果您的映像 /boot 和 /,请先执行 /boot。