如何使用systemd-nspawn还原Linux系统

本文的翻译是专门为Linux Administrator课程的学生准备的。





我们处理systemd运行容器以恢复已损坏系统的根文件系统的能力。

只要存在GNU / Linux系统,系统管理员就需要从根文件系统的损坏,意外的配置更改或其他阻止系统加载到“正常”状态的情况中恢复。

通常,Linux发行版在启动时会提供一个或多个菜单选项(例如,在GRUB菜单中),可用于修复损坏的系统。 通常,他们会在大多数系统服务关闭的情况下以单用户模式启动系统。 在最坏的情况下,用户可以在引导加载程序中更改内核命令行,以将标准外壳程序用作初始化进程(PID 1)。 这种方法最复杂,而且充满困难,可能导致时间损失和挫败感,同时还需要恢复系统。

最重要的是,所有这些方法都假定损坏的系统具有某种物理控制台,但是在云计算时代,这不再可以依靠。 如果没有物理控制台,只有几种选择(如果它们仍然可用)以这种方式影响引导过程。 即使是物理机也可能是小型的内置设备,它们没有易于使用的控制台,并且找到了正确的电缆和串行端口适配器并设置了终端仿真器,在紧急情况下在串行端口上使用控制台的一切通常都非常复杂。

当另一个系统可用时(具有相同的体系结构和通常类似的配置),简化恢复过程的一般方法是从损坏的系统中删除存储设备,并将它们作为辅助设备连接到工作系统。 在物理系统上,这通常很简单,并且大多数云计算平台也可以支持此功能,因为它们允许您将损坏实例的根卷挂载到另一个实例中。

将根文件系统连接到另一个系统后,可以使用fsck和其他工具解决文件系统损坏问题。 对配置错误,损坏的程序包或其他问题进行故障排除可能会更加困难,因为它们要求您挂载文件系统以及查找和修改正确的配置文件或数据库。

使用systemd


systemd出现之前,实际上修复配置的方法是使用文本编辑器编辑配置文件。 查找必要的文件并了解其内容是一项单独的任务,不在本文的讨论范围之内。

当GNU / Linux系统使用systemd时 ,最好使用它提供的工具来完成许多配置更改-例如,启用或禁用服务需要在各个位置创建或删除符号链接。 systemctl工具用于进行这些更改,但使用它需要systemd实例工作并侦听请求(通过D-Bus)。 当根文件系统作为附加文件系统安装在另一台计算机上时,不能使用systemd的工作实例进行这些更改。

手动启动目标系统的systemd也是不切实际的,因为它被设计为PID 1进程来控制所有其他进程,这可能与用于校正的系统中已经运行的实例发生冲突。

幸运的是, systemd能够运行容器-具有自己的PID 1和环境的完全封装的GNU / Linux系统,该容器使用Linux内核提供的各种名称空间功能。 与Docker和Rocket之类的工具不同, systemd不需要容器映像即可运行该容器。 他可以在现有文件系统中的任何位置以root特权运行它。 这是使用systemd-nspawn工具完成的 ,该工具将创建必要的系统名称空间,并在容器中启动初始过程,然后提供控制台。 与chroot (仅更改文件系统的可见根)不同,此类型的容器将具有单独的文件系统名称空间,在/ dev/ run/ proc中安装的合适的文件系统,以及单独的进程名称空间和IPC。 访问主要的 systemd-nspawn 资源以了解有关其功能的更多信息。

演示其工作原理的示例


在此示例中,包含受损系统根文件系统的存储设备已连接至正在运行的系统,在该系统中,其显示为/ dev / vdc 。 设备的名称将取决于现有存储设备的数量,设备的类型以及用于将其连接到系统的方法。 根文件系统可以使用整个存储设备,也可以驻留在设备内部的分区中。 由于最常见(简单)的配置将根文件系统放置在设备的第一个分区中,因此在本示例中将使用/ dev / vdc1确保使用正确的系统设备名称替换以下命令中的设备名称

损坏的根文件系统也可能比设备上单独的文件系统复杂。 它可以是LVM中的卷,也可以是RAID阵列中组合的一组设备上的卷。 在这些情况下,必须先完成必要的步骤才能创建和激活包含文件系统的逻辑设备,然后再将其安装。 同样,这些步骤超出了本文的范围。

必要的准备


首先,确保已安装systemd-nspawn工具-大多数GNU / Linux发行版默认都不安装它。 大多数发行版中的systemd-container软件包都提供了此软件包,因此请使用发行版的软件包管理器进行安装。 本示例中的指令已使用Debian 9进行了测试,但在任何现代GNU / Linux发行版中均应类似地工作。

使用以下命令几乎肯定会需要root特权,因此您要么需要以root身份登录,要么使用sudo获得具有root特权的shell,要么将sudo前缀添加到每个命令中。

检查并挂载文件系统


首先使用fsck检查目标文件系统的结构和内容:

$ fsck /dev/vdc1 

如果他发现文件系统有任何问题,请相应地回答问题以加以解决。 如果文件系统严重损坏,将无法修复,在这种情况下,您将不得不寻找其他方法来提取其内容。

现在创建一个临时目录并将目标文件系统挂载到其中:

 $ mkdir /tmp/target-rescue $ mount /dev/vdc1 /tmp/target-rescue 

挂载文件系统后,将其作为根文件系统运行容器:

 $ systemd-nspawn --directory /tmp/target-rescue --boot -- --unit rescue.target 

用于启动容器的命令行参数:

  • --directory / tmp / target-rescue提供了容器根文件系统的路径。
  • --boot在容器的根文件系统中寻找合适的初始化程序并启动它,并从命令行将参数传递给它。 在此示例中,目标系统还使用systemd作为进程的PID 1,因此其余参数适用于该进程。 如果要还原的目标系统使用其他工具作为进程的PID 1,则需要相应地配置设置。
  • -将用于容器进程PID 1的参数与systemd-nspawn分开。
  • --unit rescue.target告诉容器中的systemd在引导过程中应尝试实现的目标的名称。 为了简化目标系统上的恢复操作,请以“恢复”模式而不是正常的多用户模式启动它。

如果一切顺利,您应该会看到类似以下内容的输出:

 Spawning container target-rescue on /tmp/target-rescue. Press ^] three times within 1s to kill container. systemd 232 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN) Detected virtualization systemd-nspawn. Detected architecture arm. Welcome to Debian GNU/Linux 9 (Stretch)! Set hostname to <test>. Failed to install release agent, ignoring: No such file or directory [ OK ] Reached target Swap. [ OK ] Listening on Journal Socket (/dev/log). [ OK ] Started Dispatch Password Requests to Console Directory Watch. [ OK ] Reached target Encrypted Volumes. [ OK ] Created slice System Slice. Mounting POSIX Message Queue File System... [ OK ] Listening on Journal Socket. Starting Set the console keyboard layout... Starting Restore / save the current clock... Starting Journal Service... Starting Remount Root and Kernel File Systems... [ OK ] Mounted POSIX Message Queue File System. [ OK ] Started Journal Service. [ OK ] Started Remount Root and Kernel File Systems. Starting Flush Journal to Persistent Storage... [ OK ] Started Restore / save the current clock. [ OK ] Started Flush Journal to Persistent Storage. [ OK ] Started Set the console keyboard layout. [ OK ] Reached target Local File Systems (Pre). [ OK ] Reached target Local File Systems. Starting Create Volatile Files and Directories... [ OK ] Started Create Volatile Files and Directories. [ OK ] Reached target System Time Synchronized. Starting Update UTMP about System Boot/Shutdown... [ OK ] Started Update UTMP about System Boot/Shutdown. [ OK ] Reached target System Initialization. [ OK ] Started Rescue Shell. [ OK ] Reached target Rescue Mode. Starting Update UTMP about System Runlevel Changes... [ OK ] Started Update UTMP about System Runlevel Changes. You are in rescue mode. After logging in, type "journalctl -xb" to view system logs, "systemctl reboot" to reboot, "systemctl default" or ^D to boot into default mode. Give root password for maintenance (or press Control-D to continue): 

在此输出中,您可以看到systemd作为容器中的init进程启动,并确定它在容器中运行,以便可以自定义其行为。 为了使容器工作,启动了各种单元文件,然后要求目标系统的根密码。 如果要请求具有root特权的shell,则可以在此处输入root密码,也可以按Ctrl + D继续启动过程,该过程将显示通常的控制台登录提示。

对目标系统进行必要的更改后,连续按Ctrl +] 3次。 这将关闭容器,并使您返回原始外壳。 从那里,您可以通过卸载目标系统的文件系统并删除临时目录来执行清理:

 $ umount /tmp/target-rescue $ rmdir /tmp/target-rescue 

仅此而已! 现在,您可以删除目标系统的存储设备,然后将其退回。

以这种方式使用systemd-nspawn的想法,尤其是--boot选项 ,来自于StackExchange发布的一个问题 感谢Shibumi和kirbyfan64sos对这个问题的有用答案!

更多Linux资源


Source: https://habr.com/ru/post/zh-CN470497/


All Articles