Difference between revisions of "Change root (简体中文)"

From ArchWiki
Jump to: navigation, search
m (系统维护: 修正简体中文版链接)
(Update translation.)
Line 7: Line 7:
 
[[ro:Chroot]]
 
[[ro:Chroot]]
 
[[ru:Change root]]
 
[[ru:Change root]]
{{TranslationStatus (简体中文)|Change_Root|2013-06-20|261088}}
+
{{TranslationStatus (简体中文)|Change_Root|2017-12-12|485038}}
[[Wikipedia:Chroot|Chroot]] 是将当前磁盘根路径(和当前进程和它们的子进程)更改到另一个根目录。当你更改根路径到另一个目录下时,你不能在那个目录外存取文件和使用命令。这个目录叫作 ''chroot jail''。切换根目录通常为了系统维护,例如重装引导程序或者重置遗忘的密码。
+
[[Wikipedia:Chroot|Chroot]] 就是变更当前进程及其子进程的可见根路径。变更后,程序无法访问可见根目录外文件和命令。这个目录叫作 ''chroot jail''
 +
 
 +
== 原因 ==
 +
 
 +
切换根目录通常为了系统维护,例如重装引导程序或者重置遗忘的密码。
 +
 
 +
* 重新安装 [[bootloader]].
 +
* 重建 [[mkinitcpio|initramfs 镜像]].
 +
* 更新或 [[downgrading packages|降级软件包]].
 +
* 重置 [[Password recovery|忘记的密码]].
 +
* 在干净的 chroot 中构建软件包:[[DeveloperWiki:Building in a Clean Chroot]].
 +
 
 +
参阅 [[Wikipedia:Chroot#Limitations]].
  
 
== 必要条件 ==
 
== 必要条件 ==
  
* 你需要从另一个运行的linux环境启动(例如从liveCD或USB闪存介质,或者从另一个已经安装的linux发行版中)
+
* root 权限
 +
* 另一个 linux 环境,例如 liveCD、USB 闪存介质或者一个已经安装的另一个 linux 发行版。
 +
* 匹配的架构,chroot 前后的环境架构要一致(例如,都是 i686 或 x86_64)。可以用以下命令查看当前环境的架构 {{bc|uname -m}}
 +
* 提前加载 chroot 环境需要的内核模块
 +
* 如果需要 swap, chroot 前先启用 swap ({{ic|swapon /dev/sdxY}}
 +
* 如果需要网络,chroot 之前先建立好网络连接。
 +
 
 +
== 用法 ==
 +
 
 +
{{Note|
 +
*有些[[systemd]] 工具无法在 chroot 中运行,例如 ''localectl'' 和 ''timedatectl'',因为这些程序需要可用的 [[dbus]] 连接. [https://github.com/systemd/systemd/issues/798#issuecomment-126568596]
 +
*新的 root ({{ic|/}}) 所在的文件系统必须是可用访问的状态(提前解密、挂载).}}
  
* 为了chroot需要root特权。
+
有两种使用 chroot 的方式:
  
* 确定你启动进的linux环境的架构符合你想要更改的根路径的架构(例如,i686,x86_64)。你可以用以下命令得到你的当前环境架构:
+
=== 使用 arch-chroot ===
  
: {{bc|# uname -m}}
+
{{ic|arch-chroot}} bash 脚本是软件包 {{Pkg|arch-install-scripts}} 的一部分,在运行 {{ic|/usr/bin/chroot}} 前,这个脚本会挂载 {{ic|/proc}} api 文件系统,建立可用的 {{ic|/etc/resolv.conf}}。
  
* 如果你需要任何在chroot环境中使用的内核模块,在chroot之前加载它。初始化你的swap ({{ic|swapon /dev/sdxY}})估计也很有用,并且在chroot之前建立网络连接。
+
进入 chroot
  
== 挂载分区 ==
+
# arch-chroot ''/location/of/new/root''
  
你想尝试chroot进去的linux系统根分区需要先被挂载。为了找出内核分配的设备名称,运行:
+
例如在 [[installation guide|安装指南]] 中,chroot 到 {{ic|/mnt}}:
  
  # lsblk /dev/sda
+
  # arch-chroot /mnt
  
你也能运行如下命令获取你的分区布局
+
退出 chroot:
  
  # fdisk -l
+
  # exit
  
现在创建一个你想要挂载root分区的目录并且挂载到它:
+
==== 运行一个命令并退出 ====
  
# mkdir /mnt/arch
+
用下面命令在 chroot 中运行一个命令并退出:
# mount /dev/sda3 /mnt/arch
 
  
接着,如果你的系统的其它分区有单独分区(比如说 {{ic|/boot}}, {{ic|/home}},{{ic|/var}}等等),你也需要挂载他们:
+
# arch-chroot ''/location/of/new/root'' ''mycommand''
  
# mount /dev/sda1 /mnt/arch/boot/
+
例如要在 {{ic|/mnt/arch}} 中运行 {{ic|mkinitcpio -p linux}} 并退出:
# mount /dev/sdb5 /mnt/arch/home/
 
# mount ...
 
  
尽管你chroot之后可以挂载文件系统,之前完事更加方便。原因就是你将不得不在退出chroot之前卸载临时文件系统,而这样做将让你用一个单个命令卸载所有文件系统。这也使得关机更加安全。因为外部linux环境知道所有挂载的分区,它能安全的在关机时卸载他们。
+
# arch-chroot /mnt/arch mkinitcpio -p linux
  
== Change root ==
+
=== 使用 chroot ===
  
作为root挂载临时文件系统:
+
{{警告|使用 {{ic|--rbind}} 选项时,将无法卸载某些 {{ic|dev/}} 和 {{ic|sys/}} 的子目录,用 {{ic|umount -l}} 卸载将会破坏会话并需要重启,所以请尽可能使用 {{ic|-o bind}}。}}
  
{{Note|使用更新的 (2012) Arch
+
作为 root 挂载 api 文件系统:
发行版,以下{{ic|mount}}命令可以被{{ic|arch-chroot
 
/mnt/arch}}取代。你必须安装了{{pkg|arch-install-scripts}}才能运行arch-chroot。如果你在使用其它不同的Linux发行版以下命令应该仍可以使用。}}
 
  
  # cd /mnt/arch
+
  # cd ''/location/of/new/root''
 
  # mount -t proc proc proc/
 
  # mount -t proc proc proc/
  # mount -t sysfs sys sys/
+
  # mount --rbind /sys sys/
  # mount -o bind /dev dev/
+
  # mount --rbind /dev dev/
# mount -t devpts pts dev/pts/
 
  
如果你已经建立了一个网络连接并且想要在chroot环境中使用它,你可能不得不拷贝你的DNS服务器配置让你能够解析主机名:
+
可选挂载:
 +
 
 +
# mount --rbind /run run/
 +
 
 +
如果已经建立了一个网络连接并且想在 chroot 环境中继续使用,将 DNS 服务器配置复制到新环境:
  
 
  # cp -L /etc/resolv.conf etc/resolv.conf
 
  # cp -L /etc/resolv.conf etc/resolv.conf
  
现在chroot到你之前安装的系统中并且指定你的shell
+
chroot 到新环境中并启用指定 shell
  
 
  # chroot /mnt/arch /usr/bin/bash
 
  # chroot /mnt/arch /usr/bin/bash
  
{{Note|如果你遇到错误 {{ic|chroot: cannot run command '/bin/bash': Exec format error}},很可能两个环境架构不匹配。}}
+
{{Note|
 
+
* 如果遇到错误 {{ic|chroot: cannot run command '/bin/bash': Exec format error}},很可能两个环境架构不匹配。
{{Note|如果你遇到错误 {{ic|chroot: '/usr/bin/bash': permission
+
* 如果遇到错误 {{ic|chroot: '/usr/bin/bash': permission denied}},用执行权限重新挂载: {{ic|mount -o remount,exec /mnt/arch}}。
denied}},用执行权限重新挂载: {{ic|mount -o remount,exec /mnt/arch}}。}}
+
}}
  
可选地,source你的Bash配置文件({{ic|~/.bashrc}}和{{ic|/etc/bash.bashrc}}),运行:
+
(可选)加载 Bash 配置文件({{ic|~/.bashrc}} 和 {{ic|/etc/bash.bashrc}}),运行:
  
 
  # source ~/.bashrc
 
  # source ~/.bashrc
 
  # source /etc/profile
 
  # source /etc/profile
  
可选的,创建一个独特的提示符来区别你的chroot环境:
+
或创建一个独特的提示符来区别你的chroot环境:
  
 
  # export PS1="(chroot) $PS1"
 
  # export PS1="(chroot) $PS1"
  
== 运行图形化的chroot应用 ==
+
退出 chroot 环境:
  
如果你在系统上运行了[[X]],你可以在chroot环境启动图形应用。
+
  # exit
 
 
为了chroot环境能连接到你的X服务器,在X服务器中打开一个终端(例如,在用户当前登录的桌面中),然后运行如下命令给任何人连接到用户X服务器的权限:
 
 
 
  $ xhost +
 
  
然后,从chroot环境中将应用指向你的X服务器,将chroot中的DISPLAY环境变量设定成和拥有X服务器的用户DISPLAY变量相匹配。例如,运行:
+
然后卸载临时文件系统:
  
  $ echo $DISPLAY
+
  # cd /
 +
# umount --recursive ''/location/of/new/root''
  
作为拥有X服务器的用户查看DISPLAY的值。如果是“:0”(例如是),然后在chroot环境中运行
+
如果出现 {{ic|/mnt}}(或其它任何分区) is busy, 这可能意味着:
  
  # export DISPLAY=:0
+
* chroot环境中残留了一个运行的程序或者还有分区没有被卸载,退出程序并用 {{ic|mount | grep /mnt/arch}} 查找未卸载的分区。
 +
* 如果你仍然不能卸载分区,使用{{ic|--force}}选项:{{bc|# umount -f /mnt}}}}, 或使用 {{ic|umount --lazy}} 直接释放挂载。这是,请立即重启系统以避免不一致的状态导致冲突。
  
现在你可以从chroot命令行启动图形界面应用;)
+
== 在 chroot 中运行图形程序 ==
  
== 系统维护 ==
+
如果系统上运行了[[X]],可以在 chroot 环境启动图形应用。
  
此时你可以执行任何你需要在chroot环境中执行的系统维护操作。一些常见的例子是:
+
为了chroot环境能连接到你的X服务器,在X服务器中打开一个终端(例如,在用户当前登录的桌面中),然后运行如下命令给任何人连接到用户X服务器的权限:
  
* 重装引导。
+
$ xhost +local
* 重新构建[[mkinitcpio|initramfs]]镜像。
 
* 升级或[[降级软件包]]。
 
* 重置[[Password_Recovery_(简体中文)|遗忘的密码]].
 
  
== 退出chroot环境 ==
+
然后,从chroot环境中将应用指向你的X服务器,将chroot中的DISPLAY环境变量设定成和拥有X服务器的用户DISPLAY变量相匹配。例如,运行:
  
当你完成系统维护后,退出chroot:
+
$ echo $DISPLAY
  
# exit
+
作为拥有X服务器的用户查看DISPLAY的值。如果是“:0”(例如是),然后在chroot环境中运行
  
然后卸载临时文件系统和任何挂载的设备:
+
  # export DISPLAY=:0
 
 
  # umount {proc,sys,dev/pts,boot,[...],}
 
  
最后,尝试卸载你的根分区:
+
现在就可以从chroot命令行启动图形界面应用
  
# cd ..
+
== 不使用 root 权限 ==
# umount arch/
 
  
{{Note|如果你得到错误说{{ic|/mnt}}(或其它任何分区) is busy, 这可能意味着两种情况:
+
Chroot 需要 root 权限,有时用户并没有这个权限,下面工具可用实现类似的功能:
  
* chroot环境中残留了一个运行的程序。
+
=== Proot ===
  
* 或者,更常见的是,仍然存在子挂载(例如 {{ic|/mnt/arch/boot}}挂载在{{ic|/mnt/arch}})。通过{{ic|lsblk}}检查是否还存在任何挂载点(你也可以单输入一个mount查看):
+
[[Proot]] 可用在没有 root 权限的情况下,用 {{ic|mount --bind}} 设置可见根目录,这样可用为不同的 CPU 架构编译程序。这个程序的缺点是文件属于主机系统。可用用 {{ic|--root-id}} 选项解决一部分问题。
  
: {{bc|lsblk /dev/sda}}
+
=== Fakechroot ===
  
: 如果你仍然不能卸载分区,使用{{ic|--force}}选项:
+
{{Pkg|fakechroot}} 是一个拦截 chroot 调用并伪造结果的程序。用 {{Pkg|fakeroot}} 可用为普通用户伪造一个 chroot 环境:
  
: {{bc|# umount -f /mnt}}}}
+
# fakechroot fakeroot chroot ~/my-chroot bash
  
这之后,你可以安全地的重启了。
+
== 参阅 ==
 
 
== 示例 ==  
 
 
 
这也许能在浏览期间保护你的系统免于网络攻击:
 
 
 
{{bc|1=
 
# # as root:
 
# cd /home/user
 
# mkdir myroot
 
# pacman -S arch-install-scripts
 
# # pacstrap must see myroot as mounted:
 
# mount --bind myroot myroot
 
# pacstrap -i myroot base base-devel
 
# mount -t proc proc myroot/proc/
 
# mount -t sysfs sys myroot/sys/
 
# mount -o bind /dev myroot/dev/
 
# mount -t devpts pts myroot/dev/pts/
 
# cp -i /etc/resolv.conf myroot/etc/
 
# chroot myroot
 
# # inside chroot:
 
# passwd # set a password
 
# useradd -m -s /usr/bin/bash user
 
# passwd user # set a password
 
# # in a shell outside the chroot:
 
# pacman -S xorg-server-xnest
 
# # in a shell outside the chroot you can run this as user:
 
$ Xnest -ac -geometry 1024x716+0+0 :1
 
# # continue inside the chroot:
 
# pacman -S xterm
 
# DISPLAY=:1
 
# xterm
 
# # xterm is now running in Xnest
 
# pacman -S xorg-server xorg-xinit xorg-server-utils
 
# pacman -S openbox
 
# # for java we need icedtea-web which requires some fonts:
 
# nano /etc/locale.gen
 
# # uncomment en_US.UTF-8 UTF-8, save and exit
 
# locale-gen
 
# echo LANG=en_US.UTF-8 > /etc/locale.conf
 
# export LANG=en_US.UTF-8
 
# pacman -S ttf-dejavu
 
# pacman -S icedtea-web
 
# pacman -S firefox
 
# firefox
 
# # firefox is now running in Xnest
 
# exit
 
# # outside chroot:
 
# chroot --userspec=user myroot
 
# # inside chroot as user:
 
$ DISPLAY=:1
 
$ openbox &
 
$ HOME="/home/user"
 
$ firefox
 
}}
 
  
参见: [https://help.ubuntu.com/community/BasicChroot Basic Chroot]
+
* [https://help.ubuntu.com/community/BasicChroot Chroot 基础]

Revision as of 05:06, 12 December 2017

翻译状态: 本文是英文页面 Change_Root翻译,最后翻译时间:2017-12-12,点击这里可以查看翻译后英文页面的改动。

Chroot 就是变更当前进程及其子进程的可见根路径。变更后,程序无法访问可见根目录外文件和命令。这个目录叫作 chroot jail

原因

切换根目录通常为了系统维护,例如重装引导程序或者重置遗忘的密码。

参阅 Wikipedia:Chroot#Limitations.

必要条件

  • root 权限
  • 另一个 linux 环境,例如 liveCD、USB 闪存介质或者一个已经安装的另一个 linux 发行版。
  • 匹配的架构,chroot 前后的环境架构要一致(例如,都是 i686 或 x86_64)。可以用以下命令查看当前环境的架构
    uname -m
  • 提前加载 chroot 环境需要的内核模块
  • 如果需要 swap, chroot 前先启用 swap (swapon /dev/sdxY
  • 如果需要网络,chroot 之前先建立好网络连接。

用法

Note:
  • 有些systemd 工具无法在 chroot 中运行,例如 localectltimedatectl,因为这些程序需要可用的 dbus 连接. [1]
  • 新的 root (/) 所在的文件系统必须是可用访问的状态(提前解密、挂载).

有两种使用 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

作为 root 挂载 api 文件系统:

# cd /location/of/new/root
# mount -t proc proc proc/
# mount --rbind /sys sys/
# mount --rbind /dev dev/

可选挂载:

# mount --rbind /run run/

如果已经建立了一个网络连接并且想在 chroot 环境中继续使用,将 DNS 服务器配置复制到新环境:

# cp -L /etc/resolv.conf etc/resolv.conf

chroot 到新环境中并启用指定 shell

# chroot /mnt/arch /usr/bin/bash
Note:
  • 如果遇到错误 chroot: cannot run command '/bin/bash': Exec format error,很可能两个环境架构不匹配。
  • 如果遇到错误 chroot: '/usr/bin/bash': permission denied,用执行权限重新挂载: mount -o remount,exec /mnt/arch

(可选)加载 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环境中残留了一个运行的程序或者还有分区没有被卸载,退出程序并用 mount 查找未卸载的分区。
  • 如果你仍然不能卸载分区,使用--force选项:
    # umount -f /mnt
    }}, 或使用 umount --lazy 直接释放挂载。这是,请立即重启系统以避免不一致的状态导致冲突。

在 chroot 中运行图形程序

如果系统上运行了X,可以在 chroot 环境启动图形应用。

为了chroot环境能连接到你的X服务器,在X服务器中打开一个终端(例如,在用户当前登录的桌面中),然后运行如下命令给任何人连接到用户X服务器的权限:

$ 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

参阅