chroot
chroot 是一种操作,它更改当前运行进程及其子进程的根目录。在此修改后的环境中运行的程序无法访问该环境目录树之外的文件和命令。这种修改后的环境称为 chroot 监狱。
原理
更改根目录通常用于在系统维护,在系统无法启动和/或登录时执行。常见的例子有
- 重新安装引导加载程序。
- 重建 initramfs 镜像。
- 升级或降级软件包。
- 重置遗忘的密码。
- 在干净的 chroot 环境中构建软件包。
另请参阅 Wikipedia:Chroot#局限性。
要求
为了使用 chroot,您需要另一个 Linux 安装或安装介质(任何发行版),具有
- Root 权限(有关替代方案,请参阅#无需 root 权限)。
- 与要 chroot 进入的系统相同的指令集架构。可以使用
uname -m
(例如 i686 或 x86_64)发现当前环境的架构。也可以使用QEMU 来执行不具有匹配原生架构的代码。 - chroot 环境中需要的已加载内核模块。
- 如果需要,启用交换分区
# 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
变量匹配。例如,以拥有 X server 的用户身份运行
$ echo $DISPLAY
以查看 DISPLAY
的值。如果该值为“:0”(例如),则在 chroot 环境中运行以下命令
# export DISPLAY=:0
无需 root 权限
Chroot 需要 root 权限,这在某些情况下用户可能不希望或无法获得。但是,有多种方法可以使用替代实现来模拟类似 chroot 的行为。
PRoot
PRoot 可用于更改表观根目录并使用 mount --bind
而无需 root 权限。这对于将应用程序限制在单个目录中或运行为不同 CPU 架构构建的程序很有用,但它具有局限性,因为所有文件都由主机系统上的用户拥有。PRoot 提供了一个 --root-id
参数,可以用作解决其中一些限制的变通方法,其方式与 fakeroot 类似(尽管更有限)。
Fakechroot
fakechroot 是一个库 shim,它拦截 chroot 调用并伪造结果。它可以与 fakeroot 结合使用,以模拟作为普通用户的 chroot。
$ fakechroot fakeroot chroot ~/my-chroot bash
unshare(1),util-linux 的一部分,可用于创建新的内核命名空间。这适用于常用的 chroot 命令。例如
$ unshare --map-root-user chroot ~/namespace /bin/sh
技巧和窍门
chroot 检测
systemd-detect-virt --chroot
检测是否在 chroot 环境中调用。有关检测其他虚拟化环境的信息,请参阅 systemd-detect-virt(1)。有关更广泛的讨论和传统工具的用法,请参阅 how-do-i-tell-im-running-in-a-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.
有关使用绑定挂载使 chroot 目录成为挂载点的解释和示例,请参阅 arch-chroot(8)。