Chroot

From Gentoo Wiki
Jump to:navigation Jump to:search
This page is a translated version of the page Chroot and the translation is 21% complete.
Outdated translations are marked like this.
Resources

Chroot (Change Root) 是一个Unix系统应用,用来改变根目录来创建一个与主系统隔离的新环境。这个新环境就是著名的“Chroot监狱(chroot jail)。”用户在这个“监狱”中进行的操作,不能访问和读写此环境之外的数据文件。

任何Chroot之后的操作都是为了在当前环境中创建一个虚拟Linux系统,来测试系统及软件的兼容性。Chroot一般被视为一个轻量级的虚拟环境,因为它可以不依赖虚拟化环境来运行。

准备

设置环境

当你创建一个新的 chroot 环境时,首先要做的就是创建一个你将 chroot 进入的目录,比如 /mnt/mychroot:

user $mkdir /mnt/mychroot
user $cd /mnt/mychroot

如果你想挂载一个已经装好系统的分区,你可以使用以下命令。一定要更换 <DEVICE>字符串,在下面的驱动器和现有安装的分区中,例如:

user $mkdir /mnt/mychroot
user $mount /dev/DEVICE /mnt/mychroot

如果你有一个已经安装在根目录下某个子目录中的系统,就不需要再做上述操作。

为新建环境解压系统文件和portage树(新安装)

当你已经开始安装,下一步就是下载stage3和portage包,并将它们放到要chroot的位置。获取此操作更多信息,请看Gentoo Handbook中的Downloading the stage tarballUnpacking the stage tarball章节。

root #links http://distfiles.gentoo.org/releases/amd64/autobuilds/
root #tar xvjpf stage3-*.tar.bz2 -C /mnt/mychroot

配置

在进入chroot之前,我们挂载一些目录。

root #mount --rbind /dev /mnt/mychroot/dev
root #mount --make-rslave /mnt/mychroot/dev
root #mount -t proc /proc /mnt/mychroot/proc
root #mount --rbind /sys /mnt/mychroot/sys
root #mount --make-rslave /mnt/mychroot/sys
root #mount --rbind /tmp /mnt/mychroot/tmp

然后你还要从主系统复制一些基本配置文件,如果你使用一个已装好的系统,就不要复制make.conf

user $cp /etc/portage/make.conf /mnt/mychroot/etc/portage # 如果你使用一个已装好的系统,请忽略这条命令。
user $cp /etc/resolv.conf /mnt/mychroot/etc

使用

做完这几步,你就可以通过执行下面的命令chroot进入新环境了。

root #chroot /mnt/mychroot /bin/bash
root #env-update && . /etc/profile
root #export PS1="(chroot) $PS1"

创建好环境后,你就应该同步portage,更新到最新状态。

(chroot) root #emerge-webrsync
(chroot) root #emerge --sync

现在系统就已经准备好了,你可以安装软件、随意设置、测试包和配置环境,都不会影响到你的主系统。离开chroot环境只需要输入exit,或者按Ctrl+d键,将会回到你的控制台。最后不要忘记unmount你已经挂载的目录。

systemd-nspawn

If the system uses systemd, systemd-nspawn can be used, which can automatically handle much of the boilerplate required in administering chroots. For example, to enter a chroot via systemd-nspawn with the same configuration as specified in the Configuration section, simply run:

root #cp /etc/portage/make.conf /mnt/mychroot/etc/portage
root #systemd-nspawn -D /mnt/mychroot --bind=/tmp --resolv-conf=/etc/resolv.conf

初始化脚本

如果你需要经常这样做,可以用一个初始化脚本来实现快速挂载你所需要的chroot目录。这个脚本可以添加到默认运行级别进而在系统引导时自动设置。

文件 /etc/init.d/mychroot
#!/sbin/openrc-run
 
depend() {
   need localmount
   need bootmisc
}
 
start() {
     ebegin "Mounting chroot directories"
     mount -o rbind /dev /mnt/mychroot/dev > /dev/null &
     mount -t proc none /mnt/mychroot/proc > /dev/null &
     mount -o bind /sys /mnt/mychroot/sys > /dev/null &
     mount -o bind /tmp /mnt/mychroot/tmp > /dev/null &
     eend $? "An error occurred while mounting chroot directories"
}
 
stop() {
     ebegin "Unmounting chroot directories"
     umount -f /mnt/mychroot/dev > /dev/null &
     umount -f /mnt/mychroot/proc > /dev/null &
     umount -f /mnt/mychroot/sys > /dev/null &
     umount -f /mnt/mychroot/tmp > /dev/null &
     eend $? "An error occurred while unmounting chroot directories"
}

当你正在使用其他目录或分区,在the start()部分添加必要的挂载命令,另外,如果你使用的不同目录名,修改/mnt/chroot为适当的名字即可。

Sound and graphics

The software running inside the chroot will by default not have access to the system sound- and display-server. Fixing this is done by either sharing a socket, or by running the communication with TCP over localhost.

Wayland

Wayland uses a socket to connect clients with the compositor. This socket needs to be shared with the chroot to make graphical applications work. The general procedure for finding this socket is:[1]

  1. If WAYLAND_SOCKET is set, interpret it as a file descriptor number on which the connection is already established, assuming that the parent process configured the connection for us.
  2. If WAYLAND_DISPLAY is set, concat with XDG_RUNTIME_DIR to form the path to the Unix socket.
  3. Assume the socket name is wayland-0 and concat with XDG_RUNTIME_DIR to form the path to the Unix socket.

Using WAYLAND_DISPLAY and XDG_RUNTIME_DIR is fine in most cases and will be used here. By default XDG_RUNTIME_DIR is set to /run/user/$(uid). This directory will not be available in the chroot because the #Configuration instructions bind mounts /run non-recursively. Assuming the user's uid is 1000, this can be solved by either bind-mounting /run/user/1000 with:

root #mkdir -p /mnt/mychroot/run/user/1000
root #mount --bind /run/user/1000 /mnt/mychroot/run/user/1000

or by simply recursively bind mounting /run with:

root #mount --rbind /run /mnt/mychroot/run

The Wayland library dev-libs/wayland uses the same procedure for finding out the socket as listed above. So to share the socket with the chroot, the only thing that's needed to do is defining XDG_RUNTIME_DIR and WAYLAND_DISPLAY. Here it is assumed that the Wayland socket name WAYLAND_DISPLAY is wayland-0.

(chroot) root #useradd -m user
(chroot) root #su -l user
(chroot) user $export XDG_RUNTIME_DIR=/run/user/1000
(chroot) user $export WAYLAND_DISPLAY=wayland-0
(chroot) user $MOZ_ENABLE_WAYLAND=1 firefox-bin

Permission errors will occur if the user in the chroot does not have permissions to access the Wayland socket. This can be solved by using user namespace remapping or ACLs. The easiest solution is to just make sure that the user ids match. The useradd -u, --uid UID option can be used when creating a user.

PipeWire

Like Wayland, PipeWire uses a socket to connect clients to the PipeWire daemon.

Applications assume that the PipeWire socket will be located in ${XDG_RUNTIME_DIR}/pipewire-0, so the only thing that's needed to get PipeWire clients to connect to the host's daemon is to expose XDG_RUNTIME_DIR to the chroot. This process is identical to the one described in #Wayland. To expose XDG_RUNTIME_DIR, often /run/user/$(uid), the following commands are used:

root #mkdir -p /mnt/mychroot/run/user/1000
root #mount --bind /run/user/1000 /mnt/mychroot/run/user/1000

XDG_RUNTIME_DIR will not be set when logging in inside the chroot, therefore XDG_RUNTIME_DIR needs to exported so the PipeWire client can find the socket:

(chroot) user $export XDG_RUNTIME_DIR=/run/user/1000
(chroot) user $pw-cli

Xorg

Xorg by default listens on a socket located in /tmp/.X11-unix/X${DISPLAY}, as well as on localhost TCP port 6000 + ${DISPLAY}[2]. The instructions in #Configuration bind mounts /tmp, and therefore no additional configuration is needed except setting the DISPLAY variable before running a graphical application:

(chroot) user $DISPLAY=:0 firefox-bin

If the uid of the user inside the chroot does not match the uid outside the chroot, then setting permissions with xhost will be needed. To allow all local connections, run outside the chroot:

user $xhost +local:

另请参阅

External resources

References

  1. https://wayland-book.com/protocol-design/wire-protocol.html
  2. So if DISPLAY=:12, then Xorg will listen on localhost TCP port 6012