Chroot (简体中文)
Chroot 是一种修改当前进程及其子进程的可见根目录的操作。修改后,进程将不能访问该环境目录树以外的任何文件和命令,这种修改后的环境叫作 chroot jail(直译为 chroot 监狱)。
原因
改变根目录通常是为了在无法启动或登录的系统上进行系统维护,例如:
- 重新安装 bootloader。
- 重建 initramfs 镜像。
- 升级或降级软件包。
- 重置忘记的密码。
- 在干净的 clean chroot 中构建软件包。
另见 Wikipedia:Chroot#Limitations。
必要条件
- root 权限
- 另一个 linux 环境,例如 liveCD、USB 闪存介质或者一个已经安装的另一个 linux 发行版。
- 匹配的架构,chroot 前后的环境架构要一致(例如,都是 i686 或 x86_64)。可以用以下命令查看当前环境的架构
uname -m
- 提前加载 chroot 环境需要的内核模块
- 如果需要 swap, chroot 前先启用 swap (
swapon /dev/sdxY
) - 如果需要网络,chroot 之前先建立好网络连接。
用法
- 有些systemd 工具无法在 chroot 中运行,例如 hostnamectl、localectl 和 timedatectl,因为这些程序需要可用的 dbus 连接。 [1]
- 新的 root (
/
) 所在的文件系统必须是可用访问的状态(提前解密、systems (简体中文)#挂载文件系统|挂载)。
有两种使用 chroot 的方式:
使用 arch-chroot
arch-chroot
bash 脚本是软件包 arch-install-scripts 的一部分,在运行 /usr/bin/chroot
前,这个脚本会挂载类似 /proc
的 API 文件系统,建立可用的 /etc/resolv.conf
。
进入 chroot
# arch-chroot /location/of/new/root
例如在 安装指南 中,chroot 到 /mnt
:
# arch-chroot /mnt
退出 chroot:
# exit
运行一个命令并退出
用下面命令在 chroot 中运行一个命令并退出:
# arch-chroot /location/of/new/root mycommand
例如要在 /mnt/arch
中运行 mkinitcpio -p linux
并退出:
# arch-chroot /mnt/arch mkinitcpio -p linux
使用 chroot
--rbind
选项时,将无法卸载某些 dev/
和 sys/
的子目录,用 umount -l
卸载将会破坏会话并需要重启,所以请尽可能使用 -o bind
。在下面的例子中,/location/of/new/root
代指新的根目录所在的文件夹。
首先,临时挂载 API 文件系统:
# cd /location/of/new/root
# mount -t proc /proc proc/
# mount -t sysfs /sys sys/
# mount --rbind /dev dev/
可选挂载:
# 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 -L /etc/resolv.conf etc/resolv.conf
chroot 到新环境中并启用指定 shell
# chroot /mnt/arch /usr/bin/bash
- 如果遇到错误
chroot: cannot run command '/bin/bash': Exec format error
,很可能是因为两个环境架构不匹配。 - 如果遇到错误
chroot: '/usr/bin/bash': permission denied
,用执行权限重新挂载:mount -o remount,exec /location/of/new/root
。
(可选)加载 Bash 配置文件(~/.bashrc
和 /etc/bash.bashrc
),运行:
# source ~/.bashrc # source /etc/profile
或创建一个独特的提示符来区别你的chroot环境:
# export PS1="(chroot) $PS1"
退出 chroot 环境:
# exit
然后卸载临时文件系统:
# cd /
# umount --recursive /location/of/new/root
如果出现 /mnt
(或其它任何分区) is busy, 这可能意味着:
- chroot环境中残留了一个运行的程序或者还有分区没有被卸载,退出程序并用
findmnt -R /location/of/new/root
查找然后卸载未卸载的分区。 - 如果你仍然不能卸载分区,使用
--force
选项:# umount -f /mnt
, 或使用umount --lazy
直接释放挂载。这是,请立即重启系统以避免不一致的状态导致冲突。
在 chroot 中运行图形程序
如果系统上运行了X,可以在 chroot 环境启动图形应用。
为了chroot环境能连接到你的X服务器,在X服务器中打开一个终端(例如,在用户当前登录的桌面中),然后运行如下命令给任何人连接到用户X服务器的权限(另见 Xhost):
$ xhost +local:
然后,从chroot环境中将应用指向你的X服务器,将chroot中的DISPLAY环境变量设定成和拥有X服务器的用户DISPLAY变量相匹配。例如运行:
$ echo $DISPLAY
作为拥有X服务器的用户查看DISPLAY的值。如果是“:0”(例如是),然后在chroot环境中运行
# export DISPLAY=:0
现在就可以从chroot命令行启动图形界面应用
不使用 root 权限
Chroot 需要 root 权限,有时用户并没有这个权限,下面工具可用实现类似的功能:
PRoot
PRoot 可用在没有 root 权限的情况下,用 mount --bind
设置可见根目录,这样可用为不同的 CPU 架构编译程序。这个程序的缺点是文件属于主机系统。可用用 --root-id
选项解决一部分问题。
Fakechroot
fakechroot 是一个拦截 chroot 调用并伪造结果的程序。用 fakeroot 可用为普通用户伪造一个 chroot 环境:
$ fakechroot fakeroot chroot ~/my-chroot bash
Unshare 是 util-linux 的一部分,可以用来创建新的内核命名空间。它使用常规的 chroot 命令运行,例如:
$ unshare --map-root-user chroot ~/namespace /bin/sh
疑难解答
arch-chroot: /location/of/new/root is not a mountpoint. This may have undesirable side effects.
执行 arch-chroot /location/of/new/root
命令后,出现以下警告:
==> WARNING: /location/of/new/root is not a mountpoint. This may have undesirable side effects.
见 arch-chroot(8) 中的解释和使用绑定挂载让 chroot 目录变成挂载点的例子。