chroot
一个 chroot 操作会改变当前运行进程及其子进程的根目录。在一个这样的修改过的环境中运行的程序无法访问该环境目录树之外的文件和命令。这个修改过的环境称为一个“chroot 监狱”。
原因
改变根目录通常用于在系统无法启动或无法登录时执行系统维护。常见例子包括:
- 重新安装 引导加载程序。
- 重建 initramfs 镜像。
- 升级或 降级软件包。
- 重置 遗忘的密码。
- 在 干净的 chroot 环境中构建软件包。
参见 Wikipedia:Chroot#Limitations。
需求
要使用 chroot,你需要另一个 Linux 安装环境或安装介质(任何发行版),其中包含:
- Root 权限(参见 #无 root 权限 获取替代方法)。
- 与被 chroot 的系统相同的 指令集架构。当前环境的架构可以通过
uname -m发现(例如 i686 或 x86_64)。也可以使用 QEMU 来执行不匹配原生架构的代码。 - 已加载在 chroot 环境中需要的内核模块。
- 如果需要,已启用 Swap
# swapon /dev/sdxY
- 如果需要,已建立互联网连接。
准备新的根目录位置
chroot 的目标应该是一个包含文件系统层级结构的目录。
在 安装指南中,这个目录通常是 /mnt。对于现有安装,你需要自己将现有分区挂载到 /mnt。
运行 lsblk 并记下你安装的分区布局。通常会是 /dev/sdXY,或者如果你有 NVMe 驱动器,则是 /dev/nvme0nXpY。
挂载文件系统
# mount /dev/sdXY /mnt
如果你有 EFI 系统分区并且需要在其中进行更改(例如更新 vmlinuz 或 initramfs 镜像)
# mount /dev/sdXZ /mnt/esp
如果你有任何 独立分区,也一并挂载它们。
在接下来的示例中,/path/to/new/root 是新根目录所在的位置(例如 /mnt)。
用法
使用 chroot 主要有两种选项,如下所述。
使用 arch-chroot
Bash 脚本 arch-chroot(8) 是 arch-install-scripts 包的一部分。arch-chroot 封装了 chroot(1) 命令,同时确保重要的功能可用,例如挂载 /dev, /proc 和其他 API 文件系统,或将 /etc/resolv.conf 暴露给 chroot。
进入 chroot 环境
运行 arch-chroot,并将新根目录作为第一个参数。
# arch-chroot /path/to/new/root
现在您可以执行您现有安装中的大部分操作。一些需要 D-Bus 的任务将无法工作,如 #用法 中所述。
退出 chroot 环境
要退出 chroot 环境,请使用
# exit
运行单个命令并退出
要从 chroot 环境运行单个命令然后退出,请将命令附加到行末。
# arch-chroot /path/to/new/root mycommand
例如,要在位于 /mnt/arch 的 chroot 环境中运行 mkinitcpio -p linux,请执行:
# arch-chroot /mnt/arch mkinitcpio -p linux
在 Btrfs 上运行
在一个带有子卷的 Btrfs 根文件系统上,在进入 chroot 之前,您必须确保所有子卷都已按 fstab 中的说明正确挂载。
使用 archinstall 的 Btrfs 默认设置的示例:
# mount -o subvol=@ /dev/sdXY /mnt # mount -o subvol=@home /dev/sdXY /mnt/home # mount -o subvol=@pkg /dev/sdXY /mnt/var/cache/pacman/pkg # mount -o subvol=@log /dev/sdXY /mnt/var/log # mount -o subvol=@snapshots /dev/sdXY /mnt/.snapshots # mount /dev/sdXZ /mnt/boot # arch-chroot /mnt
使用 chroot
如果您直接运行 chroot,则在实际 chroot 之前需要执行以下步骤。
首先,挂载临时 API 文件系统
# cd /path/to/new/root # mount -t proc /proc proc/ # mount -t sysfs /sys sys/ # mount --rbind /dev dev/
--rbind 时,dev/ 和 sys/ 的某些子目录将无法卸载。在这种情况下尝试使用 umount -l 卸载将破坏您的会话,需要重启。如果可能,请改用 -o bind。可选地
# mount --rbind /run run/
如果您运行的是 UEFI 系统,您还需要访问 EFI 变量。否则,在安装 GRUB 时,您会收到类似以下的消息:UEFI variables not supported on this machine
# mount --rbind /sys/firmware/efi/efivars sys/firmware/efi/efivars/
接下来,为了在 chroot 环境中使用互联网连接,复制 DNS 详细信息:
# cp /etc/resolv.conf etc/resolv.conf
最后,使用 bash shell 将根目录更改为 /path/to/new/root:
# chroot /path/to/new/root /bin/bash
chroot: cannot run command '/usr/bin/bash': Exec format error,这很可能是主机环境和 chroot 环境的架构不匹配。chroot: '/usr/bin/bash': permission denied,请使用mount -o remount,exec /path/to/new/root重新挂载执行权限。
在 chroot 之后,可能需要加载本地 Bash 配置。
# source /etc/profile # source ~/.bashrc
# export PS1="(chroot) $PS1"
完成 chroot 后,您可以通过以下方式退出:
# exit
然后卸载临时文件系统:
# cd / # umount --recursive /path/to/new/root
umount: /path: device is busy 的错误,通常意味着:要么有一个程序(甚至是一个 shell)仍然在 chroot 环境中运行,要么仍然存在一个子挂载。退出程序并使用 findmnt -R /path/to/new/root 来查找并然后 umount 子挂载。卸载某些东西可能很棘手,可以使用 umount --force。作为最后的手段,使用 umount --lazy,它只是释放它们。无论哪种情况,为了安全起见,如果问题未解决,请尽快 reboot 以避免将来可能发生的冲突。从 chroot 运行图形应用程序
如果您在系统上运行 X server,则可以从 chroot 环境启动图形应用程序。
要允许 chroot 环境连接到 X server,请在 X server 中打开一个虚拟终端(即当前登录用户的桌面中),然后运行 xhost 命令,该命令允许任何人连接到用户的 X server(另请参见 Xhost)。
$ xhost +local:
然后,要将应用程序从 chroot 重定向到 X server,请在 chroot 环境中设置 DISPLAY 环境变量,使其与 X server 所有者的 DISPLAY 变量匹配。例如,运行
$ echo $DISPLAY
作为 X server 所有者来查看 DISPLAY 的值。如果值为 ":0"(例如),则在 chroot 环境中运行以下命令:
# export DISPLAY=:0
无 root 权限
Chroot 需要 root 权限,这在某些情况下用户可能不希望获得或无法获得。但是,有各种方法可以使用替代实现来模拟 chroot 行为。
PRoot
PRoot 可用于更改根目录,并在没有 root 权限的情况下使用 mount --bind。这对于将应用程序限制在单个目录或运行为不同 CPU 架构构建的程序很有用,但由于主机系统上的所有文件都归用户所有,它存在一些限制。PRoot 提供了一个 --root-id 参数,可以作为解决方法来缓解其中一些限制,其方式与 fakeroot 类似(尽管功能更有限)。
Fakechroot
fakechroot 是一个库 shim,它会拦截 chroot 调用并伪造结果。它可以与 fakeroot 一起使用,以模拟普通用户的 chroot 环境。
$ fakechroot fakeroot chroot ~/my-chroot bash
Unshare
unshare(1),是 util-linux 的一部分,可用于创建新的内核命名空间。这可以与常规的 chroot 命令一起使用。例如:
$ unshare --map-root-user chroot ~/namespace /bin/sh
技巧与提示
chroot 检测
systemd-detect-virt --chroot 可检测是否在 chroot 环境中调用。有关检测其他虚拟化环境,请参见 systemd-detect-virt(1)。有关更广泛的讨论和传统工具的使用,请参见 如何判断我正在 chroot 环境中运行。
故障排除
arch-chroot: /path/to/new/root 不是一个挂载点。这可能会产生不良的副作用。
执行 arch-chroot /path/to/new/root 时,会发出警告:
==> WARNING: /path/to/new/root is not a mountpoint. This may have undesirable side effects.
请参见 arch-chroot(8) 以获取解释和使用 bind mount 将 chroot 目录设置为挂载点的示例。