![将 glibc 从 initrd 复制到我的根文件系统](https://linux22.com/image/1435566/%E5%B0%86%20glibc%20%E4%BB%8E%20initrd%20%E5%A4%8D%E5%88%B6%E5%88%B0%E6%88%91%E7%9A%84%E6%A0%B9%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F.png)
我正在尝试使用 FAQ 中引用的指南将 glibc 2.20(最近构建)安装到 Debian这一页(常见问题解答中的问题是如何安装我刚刚构建的所有 GNU C 库项目库?):
安装这些库的唯一正确方法是执行 make install INSTALLDIR=/tmp/glibc,将库安装到 /tmp/glibc,然后将该目录复制到初始根磁盘,启动初始根磁盘,并将结果复制到根文件系统,然后在启动的最后一步转到根文件系统。这就是仅有的今天安装 glibc 的安全方法。
我已设法将这个新的 glibc 目录(包含的产品make install
)复制到 initrd 的解压缩副本(默认加载的副本)中,将其压缩回来,并在通过编辑命令行在 GRUB 中指定这个新的 initrd 后成功启动。
有人能告诉我如何以及在何处将这个 glibc 复制到我的根文件系统(使其成为系统中的主要 C 库而不是当前(默认)库)吗?
答案1
你的问题 (”我应该如何以及在何处将此 glibc 复制到我的根文件系统“) 给出了几种答案,其中常见问题解答中提到的答案具有最低要求(尽管在我看来,它并不是最简单的)。
他们建议,一旦你启动了内核,就可以挂载新的 initrd(因此,会以类似“(initramfs)' 是将您的真实系统挂载到文件系统下方的某个位置。假设您的真实根文件系统位于 /dev/sda1,如下所示:
(initramfs) mkdir /new_root
(initramfs) mount /dev/sda1 /new_root
此后,您将拥有:
- /lib=> 包含新的您自己编译并打包在用于引导和 root 挂载的 INITRD 中的库;
- /新根/lib=> 包含老的在您的(未运行的)实际系统内,这些库仍然存在于您的硬盘上;
(顺便说一句:你也可以有一个lib64除了上述结构之外/lib,具体取决于您的架构。在应用我写的内容之前,请先应用一些常识和健全性检查)
在此阶段,您已经拥有将内容从 /lib 复制到 /new_root/lib 所需的一切,然后只需 umount /new_root 并重新启动即可。
那么为什么他们要建议使用pivot_root之类的“魔法”呢?
恕我直言,他们在常见问题解答中假设的是,您希望将重启次数限制为最低限度。一次重启是不可避免的(从 INITRD 启动)。然后,您可以挂载根分区,复制库并...告诉系统继续正常启动,指向您刚从硬盘挂载的(新)根文件系统。这里的关键点是“根挂载点”(换句话说,即“/”文件夹)需要从与 INITRD 映像相关的挂载点替换为与您的真实系统相关的挂载点(挂载到 INITRD 文件系统下的 /new_root 的 /dev/sda1 分区)。
有几种工具能够“更改根”,其中常见问题解答中引用了pivot_root。这里您可以找到有关使用pivot_root在两个Linux安装之间切换的讨论。 它非常适合您的情况,因为这两个系统是INITRD初始系统和磁盘上的真实系统。
这里您可以找到一些将pivot_root与switch_root进行比较的信息(和链接)。
在发布这个答案之前,我已经进行了一些pivot_root测试:不幸的是,我一直无法到pivot_root,以各种错误结束(顺便说一句:似乎我不孤独这里)。
由于上述问题,我得出结论:“第二次重启”不是问题,并且使整个过程变得简单。
至于其他方法,也可以(...甚至更简单)使用 Live-CD 启动 Linux 系统(例如系统救援光盘) 和:
- 从 INITRD 中手动提取(新)库;
- 用上面的内容替换系统中的(旧)内容。
显然,要访问您的 INITRD 以及您的真实系统,您需要将您的分区“挂载”在 live-cd 的文件系统中的某个位置(以与上面讨论的方式相同)。
至于提取过程,我们假设您的 initrd 是 /mnt/initrd.img-3.2.0-58-generic。让我们检查它是否已压缩:
damiano@tablet:/$ file /mnt/initrd.img-3.2.0-58-generic
/mnt/initrd.img-3.2.0-58-generic: gzip compressed data, from Unix, last modified: Wed Jan 8 11:54:03 2014
我们先解压它,以便更好地检查其内容(我们将在 /tmp/libs 目录中工作):
damiano@tablet:/$ mkdir /tmp/libs
damiano@tablet:/$ cd /tmp/libs
damiano@tablet:/tmp/libs$ gzip -dc /mnt/initrd.img-3.2.0-58-generic > init_uncompressed
damiano@tablet:/tmp/libs$
现在让我们检查一下解压缩后的文件中有什么:
damiano@tablet:/tmp/libs$ file init_uncompressed
init_uncompressed: ASCII cpio archive (SVR4 with no CRC)
好的。现在我们有了cpio 档案提取其内容非常简单:
damiano@tablet:/tmp/libs$ cpio -i < init_uncompressed
109835 blocchi
现在,我们终于提取了所有内容,包括你的库:
damiano@tablet:/tmp/libs$ ls -l
totale 54968
drwxr-xr-x 2 verzulli verzulli 4096 dic 31 14:42 bin
drwxr-xr-x 3 verzulli verzulli 4096 dic 31 14:42 conf
drwxr-xr-x 8 verzulli verzulli 4096 dic 31 14:42 etc
-rwxr-xr-x 1 verzulli verzulli 7230 dic 31 14:42 init
-rw-rw-r-- 1 verzulli verzulli 56235520 dic 31 14:38 init_uncompressed
drwxr-xr-x 9 verzulli verzulli 4096 dic 31 14:42 lib
drwxr-xr-x 2 verzulli verzulli 4096 dic 31 14:42 lib64
drwxr-xr-x 2 verzulli verzulli 4096 dic 31 14:42 run
drwxr-xr-x 2 verzulli verzulli 4096 dic 31 14:42 sbin
drwxr-xr-x 10 verzulli verzulli 4096 dic 31 14:42 scripts
drwxr-xr-x 4 verzulli verzulli 4096 dic 31 14:42 usr
此时,您可以简单地将 lib(和 lib64)文件夹从 /tmp/libs 复制到 /mnt(假设您的根分区 --/dev/sda1-- 安装在 /mnt 下),然后重新启动。
最后(非常个人化)说明:说了以上所有内容,让我补充一点……尽管常见问题解答中明确指出,依靠包管理器来更新系统库很危险我个人认为自己手动处理系统库……肯定更危险:-)
所以,如果您在无法启动的系统中运行,请不要责怪我;-)
更新 1:
至于“启动内核后,挂载新的 initrd“,您可以按照以下步骤进行:
- 在 grub 菜单中,选择您通常运行的条目并按“E”(编辑)。(顺便说一句:如果您没有 grub 菜单,那么这个问题和/或其他在线搜索可以提供帮助)。您将看到类似以下的屏幕:
请注意与内核相关的行。在这样的行上你会发现:
- 参考内核(我的示例中为 vmlinux-3.8.0-19-generic);
- 引用用于挂载根文件系统的设备(在我的示例中为 root=/dev/mapper/kubuntu--vg-root);
其他启动参数( ro quiet splace $vt_handoff )
- 因为您想要 root 挂载您准备好的 initrd 文件(...包含更新的 glibc;而不是通用设备/硬盘驱动器/分区),您需要编辑上面的行,替换对“root=”参数的引用,如下所示:
请注意我使用了根=/initrd.img-3.8.0-19-通用尽管你应该链接到你的特定 initrd 文件
- 正确定义“root=”参数后,只需按 F10 即可。几秒钟后,您应该会看到 (initramfs) 提示符,如下所示:
现在您的“/”有一个 /lib 文件夹,其中包含您编译的库...并打包在 INITRD 中。