将图像写入当前根分区

将图像写入当前根分区

我目前正在为类似树莓派的计算机构建磁盘映像(基于 Debian)。

我当前的工作流程如下所示:

  1. 创建磁盘映像(未压缩约 16GB;或压缩后 3GB)
  2. 关闭目标系统电源
  3. 弹出目标系统上的 SD 卡
  4. 将 SD 卡插入构建计算机
  5. dd将图像保存到 SD 卡上
  6. 从构建计算机中弹出 SD 卡
  7. 将SD卡插入目标系统
  8. 将目标系统启动到新的操作系统版本

这很乏味。

我想缩短周期:

  1. 创建磁盘映像(未压缩约 16GB;或压缩后 3GB)
  2. scp目标系统的磁盘映像
  3. 用新映像覆盖目标系统的 SD 卡dd
  4. 将目标系统重新启动到新的操作系统版本

现在这显然有一个问题,我正在尝试覆盖包含以下内容的已安装分区根文件系统(磁盘映像仅包含根分区和引导分区)。最终,dd(我用它来将图像复制到 SD 卡)将出现段错误,之后文件系统将无法修复,并且不再起作用。

所以我的问题是:有没有办法在当前 rootfs 上进行低级数据“恢复”?类似于:将相关二进制文件(ddreboot)的一些“静态链接”版本复制到某个安全空间(RAM 磁盘),然后从那里运行。

理想情况下,我希望在不物理访问目标系统的情况下执行此操作(前提是我的磁盘映像未损坏)。

答案1

布莱恩的回答是我的建议:随时从网络接收图像。没有其他办法,因为你显然无法将图像放在你要覆盖的存储设备上。

但 Brian 的方法也会出现这个问题:假设您从当前启动的完整 debian 接收了映像,那么您将开始覆盖文件系统上当前的软件。呃,如果在下载并解压到原始磁盘时出现某些硬件中断、某些计时器/cron 作业或某些文件系统维护工具,会发生什么情况?您的整个系统可能会崩溃,也可能不会崩溃。

如果它崩溃了,您将留下一个无法在您可能无法访问的位置启动的嵌入式设备。这使得努力变得更加糟糕。

因此,您需要做的是接收和拆包软件不会覆盖您当前正在运行的软件。两种方法:

  1. 有两个根卷,例如 A 和 B。您当前的 debian 从 A 运行,您可以安全地覆盖 B 的所有内容。完成后,您可以告诉引导过程从 B 引导,并正确重新启动系统。 (通常,您有一个单独的“引导”分区,引导加载程序从中运行,并且其中包含 RPi 引导硬件的引导配置文件,这很......奇特。)
    您需要两倍于系统大小的存储空间。
    我起草了一个版本,您将如何做到这一点,完全在 RPi 上,在这个最近的答案
  2. 有一个要覆盖的根卷 (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-???),并将其重命名为oldsystemsudo 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。

相关内容