跳转至内容

chroot

来自 ArchWiki
(从Change root重定向而来)

一个 chroot 操作会改变当前运行进程及其子进程的根目录。在一个这样的修改过的环境中运行的程序无法访问该环境目录树之外的文件和命令。这个修改过的环境称为一个“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 系统分区并且需要在其中进行更改(例如更新 vmlinuzinitramfs 镜像)

# mount /dev/sdXZ /mnt/esp

如果你有任何 独立分区,也一并挂载它们。

在接下来的示例中,/path/to/new/root 是新根目录所在的位置(例如 /mnt)。

用法

  • 一些 systemd 工具,如 hostnamectl, localectltimedatectl,无法在 chroot 环境中使用,因为它们需要一个活动的 dbus 连接。[1]
  • 将作为 chroot 新根目录(/)的文件系统必须是可访问的(即已解密、已 挂载)。

使用 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/archchroot 环境中运行 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 重新挂载执行权限。
    • 如果检查此问题未解决,请 确保新环境的基础组件完好(如果是 Arch 根目录,请尝试使用 paccheck --root=/path/to/new/root --files --file-properties --md5sum glibc filesystem,来自 pacutils)。

chroot 之后,可能需要加载本地 Bash 配置。

# source /etc/profile
# source ~/.bashrc
提示 可选地,创建一个独特的提示符,以便能够区分您的 chroot 环境。
# 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 目录设置为挂载点的示例。

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.