标签 引导 下的文章

systemd 启动过程提供的重要线索可以在问题出现时助你一臂之力。

 title=

在本系列的第一篇文章《学着爱上 systemd》,我考察了 systemd 的功能和架构,以及围绕 systemd 作为古老的 SystemV 初始化程序和启动脚本的替代品的争论。在这第二篇文章中,我将开始探索管理 Linux 启动序列的文件和工具。我会解释 systemd 启动序列、如何更改默认的启动目标(即 SystemV 术语中的运行级别)、以及在不重启的情况下如何手动切换到不同的目标。

我还将考察两个重要的 systemd 工具。第一个 systemctl 命令是和 systemd 交互、向其发送命令的基本方式。第二个是 journalctl,用于访问 systemd 日志,后者包含了大量系统历史数据,比如内核和服务的消息(包括指示性信息和错误信息)。

务必使用一个非生产系统进行本文和后续文章中的测试和实验。你的测试系统需要安装一个 GUI 桌面(比如 Xfce、LXDE、Gnome、KDE 或其他)。

上一篇文章中我写道计划在这篇文章创建一个 systemd 单元并添加到启动序列。由于这篇文章比我预期中要长,这些内容将留到本系列的下一篇文章。

使用 systemd 探索 Linux 的启动

在观察启动序列之前,你需要做几件事情得使引导和启动序列开放可见。正常情况下,大多数发行版使用一个开机动画或者启动画面隐藏 Linux 启动和关机过程中的显示细节,在基于 Red Hat 的发行版中称作 Plymouth 引导画面。这些隐藏的消息能够向寻找信息以排除程序故障、或者只是学习启动序列的系统管理员提供大量有关系统启动和关闭的信息。你可以通过 GRUB( 大统一引导加载器 Grand Unified Boot Loader )配置改变这个设置。

主要的 GRUB 配置文件是 /boot/grub2/grub.cfg ,但是这个文件在更新内核版本时会被覆盖,你不会想修改它的。相反,应该修改用于改变 grub.cfg 默认设置的 /etc/default/grub 文件。

首先看一下当前未修改的 /etc/default/grub 文件的版本:

[root@testvm1 ~]# cd /etc/default ; cat grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_testvm1-swap rd.lvm.
lv=fedora_testvm1/root rd.lvm.lv=fedora_testvm1/swap rd.lvm.lv=fedora_
testvm1/usr rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
[root@testvm1 default]#

GRUB 文档 的第 6 章列出了 /etc/default/grub 文件的所有可用项,我只关注下面的部分:

  • 我将 GRUB 菜单倒计时的秒数 GRUB_TIMEOUT,从 5 改成 10,以便在倒计时达到 0 之前有更多的时间响应 GRUB 菜单。
  • GRUB_CMDLINE_LINUX 列出了引导阶段传递给内核的命令行参数,我删除了其中的最后两个参数。其中的一个参数 rhgb 代表 “ 红帽图形化引导 Red Hat Graphical Boot ”,在内核初始化阶段显示一个小小的 Fedora 图标动画,而不是显示引导阶段的信息。另一个参数 quiet,屏蔽显示记录了启动进度和发生错误的消息。系统管理员需要这些信息,因此我删除了 rhgbquiet。如果引导阶段发生了错误,屏幕上显示的信息可以指向故障的原因。

更改之后,你的 GRUB 文件将会像下面一样:

[root@testvm1 default]# cat grub
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_testvm1-swap rd.lvm.
lv=fedora_testvm1/root rd.lvm.lv=fedora_testvm1/swap rd.lvm.lv=fedora_
testvm1/usr"
GRUB_DISABLE_RECOVERY="false"
[root@testvm1 default]#

grub2-mkconfig 程序使用 /etc/default/grub 文件的内容生成 grub.cfg 配置文件,从而改变一些默认的 GRUB 设置。grub2-mkconfig 输出到 STDOUT,你可以使用程序的 -o 参数指明数据流输出的文件,不过使用重定向也同样简单。执行下面的命令更新 /boot/grub2/grub.cfg 配置文件:

[root@testvm1 grub2]# grub2-mkconfig > /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.18.9-200.fc28.x86_64
Found initrd image: /boot/initramfs-4.18.9-200.fc28.x86_64.img
Found linux image: /boot/vmlinuz-4.17.14-202.fc28.x86_64
Found initrd image: /boot/initramfs-4.17.14-202.fc28.x86_64.img
Found linux image: /boot/vmlinuz-4.16.3-301.fc28.x86_64
Found initrd image: /boot/initramfs-4.16.3-301.fc28.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-7f12524278bd40e9b10a085bc82dc504
Found initrd image: /boot/initramfs-0-rescue-7f12524278bd40e9b10a085bc82dc504.img
done
[root@testvm1 grub2]#

重新启动你的测试系统查看本来会隐藏在 Plymouth 开机动画之下的启动信息。但是如果你没有关闭开机动画,又需要查看启动信息的话又该如何操作?或者你关闭了开机动画,而消息流过的速度太快,无法阅读怎么办?(实际情况如此。)

有两个解决方案,都涉及到日志文件和 systemd 日志 —— 两个都是你的好伙伴。你可以使用 less 命令查看 /var/log/messages 文件的内容。这个文件包含引导和启动信息,以及操作系统执行正常操作时生成的信息。你也可以使用不加任何参数的 journalctl 命令查看 systemd 日志,包含基本相同的信息:

[root@testvm1 grub2]# journalctl
-- Logs begin at Sat 2020-01-11 21:48:08 EST, end at Fri 2020-04-03 08:54:30 EDT. --
Jan 11 21:48:08 f31vm.both.org kernel: Linux version 5.3.7-301.fc31.x86_64 ([email protected]) (gcc version 9.2.1 20190827 (Red Hat 9.2.1-1) (GCC)) #1 SMP Mon Oct >
Jan 11 21:48:08 f31vm.both.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.3.7-301.fc31.x86_64 root=/dev/mapper/VG01-root ro resume=/dev/mapper/VG01-swap rd.lvm.lv=VG01/root rd>
Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: xstate_offset[2]:  576, xstate_sizes[2]:  256
Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format.
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-provided physical RAM map:
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000000100000-0x00000000dffeffff] usable
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000dfff0000-0x00000000dfffffff] ACPI data
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000100000000-0x000000041fffffff] usable
Jan 11 21:48:08 f31vm.both.org kernel: NX (Execute Disable) protection: active
Jan 11 21:48:08 f31vm.both.org kernel: SMBIOS 2.5 present.
Jan 11 21:48:08 f31vm.both.org kernel: DMI: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
Jan 11 21:48:08 f31vm.both.org kernel: Hypervisor detected: KVM
Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: Using msrs 4b564d01 and 4b564d00
Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: cpu 0, msr 30ae01001, primary cpu clock
Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: using sched offset of 8250734066 cycles
Jan 11 21:48:08 f31vm.both.org kernel: clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
Jan 11 21:48:08 f31vm.both.org kernel: tsc: Detected 2807.992 MHz processor
Jan 11 21:48:08 f31vm.both.org kernel: e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
Jan 11 21:48:08 f31vm.both.org kernel: e820: remove [mem 0x000a0000-0x000fffff] usable
<snip>

由于数据流可能长达几十万甚至几百万行,我在这里截断了它。(我的主要工作站上列出的日志长度是 1,188,482 行。)请确保是在你的测试系统尝试的这个命令。如果系统已经运行了一段时间 —— 即使重启过很多次 —— 还是会显示大量的数据。查看这些日志数据,因为它包含了很多信息,在进行问题判断时可能非常有用。了解这个数据文件在正常的引导和启动过程中的模样,可以帮助你在问题出现时定位问题。

我将在本系列之后的文章讨论 systemd 日志、journalctl 命令、以及如何整理输出的日志数据来寻找更详细的信息。

内核被 GRUB 加载到内存后,必须先将自己从压缩后的文件中解压出来,才能执行任何有意义的操作。解压自己后,内核开始运行,加载 systemd 并转交控制权。

引导 boot 阶段到此结束,此时 Linux 内核和 systemd 正在运行,但是无法为用户执行任何生产性任务,因为其他的程序都没有执行,没有命令行解释器提供命令行,没有后台进程管理网络和其他的通信链接,也没有任何东西能够控制计算机执行生产功能。

现在 systemd 可以加载所需的功能性单元以便将系统启动到选择的目标运行状态。

目标

一个 systemd 目标 target 代表一个 Linux 系统当前的或期望的运行状态。与 SystemV 启动脚本十分类似,目标定义了系统运行必须存在的服务,以及处于目标状态下必须激活的服务。图表 1 展示了使用 systemd 的 Linux 系统可能的运行状态目标。就像在本系列的第一篇文章以及 systemd 启动的手册页(man bootup)所看到的一样,有一些开启不同必要服务的其他中间目标,包括 swap.targettimers.targetlocal-fs.target 等。一些目标(像 basic.target)作为检查点使用,在移动到下一个更高级的目标之前保证所有需要的服务已经启动并运行。

除非开机时在 GRUB 菜单进行更改,systemd 总是启动 default.targetdefault.target 文件是指向真实的目标文件的符号链接。对于桌面工作站,default.target 通常是 graphical.target,等同于 SystemV 的运行等级 5。对于服务器,默认目标多半是 multi-user.target,就像 SystemV 的运行等级 3。emergency.target 文件类似单用户模式。目标和 服务 service 都是一种 systemd 单元。

下面的图表,包含在本系列的上一篇文章中,比较了 systemd 目标和古老的 SystemV 启动运行等级。为了向后兼容,systemd 提供了 systemd 目标别名,允许脚本和系统管理员使用像 init 3 一样的 SystemV 命令改变运行等级。当然,SystemV 命令被转发给 systemd 进行解释和执行。

systemd 目标SystemV 运行级别目标别名描述
default.target 这个目标通常是一个符号链接,作为 multi-user.targetgraphical.target 的别名。systemd 总是用 default.target 启动系统。default.target** 不能作为halt.targetpoweroff.targetreboot.target` 的别名。
graphical.target5runlevel5.target带有 GUI 的 multi-user.target
4runlevel4.target未使用。运行等级 4 和 SystemV 的运行等级 3 一致,可以创建这个目标并进行定制,用于启动本地服务,而不必更改默认的 multi-user.target
multi-user.target3runlevel3.target运行所有的服务,但是只有命令行界面(CLI) 。
2runlevel2.target多用户,没有 NFS,但是运行其他所有的非 GUI 服务
rescue.target1runlevel1.target一个基本的系统,包括挂载文件系统,但是只运行最基础的服务,以及一个主控制台上的用于救援的命令行解释器。
emergency.targetS 单用户模式 —— 没有服务运行;文件系统没有挂载。这是最基础级的操作模式,只有一个运行在主控制台的用于紧急情况的命令行解释器,供用户和系统交互。
halt.target 不断电的情况下停止系统
reboot.target6runlevel6.target重启
poweroff.target0runlevel0.target停止系统并关闭电源

每个目标在配置文件中都描述了一组依赖关系。systemd 启动需要的依赖,即 Linux 主机运行在特定功能级别所需的服务。加载目标配置文件中列出的所有依赖并运行后,系统就运行在那个目标等级。如果愿意,你可以在本系列的第一篇文章《学着爱上 systemd》中回顾 systemd 的启动序列和运行时目标。

探索当前的目标

许多 Linux 发行版默认安装一个 GUI 桌面界面,以便安装的系统可以像工作站一样使用。我总是从 Fedora Live USB 引导驱动器安装 Xfce 或 LXDE 桌面。即使是安装一个服务器或者其他基础类型的主机(比如用于路由器和防火墙的主机),我也使用 GUI 桌面的安装方式。

我可以安装一个没有桌面的服务器(数据中心的典型做法),但是这样不满足我的需求。原因不是我需要 GUI 桌面本身,而是 LXDE 安装包含了许多其他默认的服务器安装没有提供的工具,这意味着初始安装之后我需要做的工作更少。

但是,仅仅因为有 GUI 桌面并不意味着我要使用它。我有一个 16 端口的 KVM,可以用于访问我的大部分 Linux 系统的 KVM 接口,但我和它们交互的大部分交互是通过从我的主要工作站建立的远程 SSH 连接。这种方式更安全,而且和 graphical.target 相比,运行 multi-user.target 使用更少的系统资源。

首先,检查默认目标,确认是 graphical.target

[root@testvm1 ~]# systemctl get-default
graphical.target
[root@testvm1 ~]#

然后确认当前正在运行的目标,应该和默认目标相同。你仍可以使用老方法,输出古老的 SystemV 运行等级。注意,前一个运行等级在左边,这里是 N(意思是 None),表示主机启动后没有修改过运行等级。数字 5 是当前的目标,正如古老的 SystemV 术语中的定义:

[root@testvm1 ~]# runlevel
N 5
[root@testvm1 ~]#

注意,runlevel 的手册页指出运行等级已经被淘汰,并提供了一个转换表。

你也可以使用 systemd 方式,命令的输出有很多行,但确实用 systemd 术语提供了答案:

[root@testvm1 ~]# systemctl list-units --type target
UNIT                   LOAD   ACTIVE SUB    DESCRIPTION                
basic.target           loaded active active Basic System              
cryptsetup.target      loaded active active Local Encrypted Volumes    
getty.target           loaded active active Login Prompts              
graphical.target       loaded active active Graphical Interface        
local-fs-pre.target    loaded active active Local File Systems (Pre)  
local-fs.target        loaded active active Local File Systems        
multi-user.target      loaded active active Multi-User System          
network-online.target  loaded active active Network is Online          
network.target         loaded active active Network                    
nfs-client.target      loaded active active NFS client services        
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target           loaded active active Paths                      
remote-fs-pre.target   loaded active active Remote File Systems (Pre)  
remote-fs.target       loaded active active Remote File Systems        
rpc_pipefs.target      loaded active active rpc_pipefs.target          
slices.target          loaded active active Slices                    
sockets.target         loaded active active Sockets                    
sshd-keygen.target     loaded active active sshd-keygen.target        
swap.target            loaded active active Swap                      
sysinit.target         loaded active active System Initialization      
timers.target          loaded active active Timers                    

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

21 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

上面列出了当前加载的和激活的目标,你也可以看到 graphical.targetmulti-user.targetmulti-user.target 需要在 graphical.target 之前加载。这个例子中,graphical.target 是激活的。

切换到不同的目标

切换到 multi-user.target 很简单:

[root@testvm1 ~]# systemctl isolate multi-user.target

显示器现在应该从 GUI 桌面或登录界面切换到了一个虚拟控制台。登录并列出当前激活的 systemd 单元,确认 graphical.target 不再运行:

[root@testvm1 ~]# systemctl list-units --type target

务必使用 runlevel 确认命令输出了之前的和当前的“运行等级”:

[root@testvm1 ~]# runlevel
5 3

更改默认目标

现在,将默认目标改为 multi-user.target,以便系统总是启动进入 multi-user.target,从而使用控制台命令行接口而不是 GUI 桌面接口。使用你的测试主机的根用户,切换到保存 systemd 配置的目录,执行一次快速列出操作:

[root@testvm1 ~]# cd /etc/systemd/system/ ; ll
drwxr-xr-x. 2 root root 4096 Apr 25  2018  basic.target.wants
&lt;snip&gt;
lrwxrwxrwx. 1 root root   36 Aug 13 16:23  default.target -> /lib/systemd/system/graphical.target
lrwxrwxrwx. 1 root root   39 Apr 25  2018  display-manager.service -> /usr/lib/systemd/system/lightdm.service
drwxr-xr-x. 2 root root 4096 Apr 25  2018  getty.target.wants
drwxr-xr-x. 2 root root 4096 Aug 18 10:16  graphical.target.wants
drwxr-xr-x. 2 root root 4096 Apr 25  2018  local-fs.target.wants
drwxr-xr-x. 2 root root 4096 Oct 30 16:54  multi-user.target.wants
&lt;snip&gt;
[root@testvm1 system]#

为了强调一些有助于解释 systemd 如何管理启动过程的重要事项,我缩短了这个列表。你应该可以在虚拟机看到完整的目录和链接列表。

default.target 项是指向目录 /lib/systemd/system/graphical.target 的符号链接(软链接),列出那个目录查看目录中的其他内容:

[root@testvm1 system]# ll /lib/systemd/system/ | less

你应该在这个列表中看到文件、目录、以及更多链接,但是专门寻找一下 multi-user.targetgraphical.target。现在列出 default.target(指向 /lib/systemd/system/graphical.target 的链接)的内容:

[root@testvm1 system]# cat default.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service
AllowIsolate=yes
[root@testvm1 system]#

graphical.target 文件的这个链接描述了图形用户接口需要的所有必备条件。我会在本系列的下一篇文章至少探讨其中的一些选项。

为了使主机启动到多用户模式,你需要删除已有的链接,创建一个新链接指向正确目标。如果你的 PWD 不是 /etc/systemd/system,切换过去:

[root@testvm1 system]# rm -f default.target
[root@testvm1 system]# ln -s /lib/systemd/system/multi-user.target default.target

列出 default.target 链接,确认其指向了正确的文件:

[root@testvm1 system]# ll default.target
lrwxrwxrwx 1 root root 37 Nov 28 16:08 default.target -&gt; /lib/systemd/system/multi-user.target
[root@testvm1 system]#

如果你的链接看起来不一样,删除并重试。列出 default.target 链接的内容:

[root@testvm1 system]# cat default.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes
[root@testvm1 system]#

default.target(这里其实是指向 multi-user.target 的链接)其中的 [Unit] 部分现在有不同的必需条件。这个目标不需要有图形显示管理器。

重启,你的虚拟机应该启动到虚拟控制台 1 的控制台登录,虚拟控制台 1 在显示器标识为 tty1。现在你已经知道如何修改默认的目标,使用所需的命令将默认目标改回 graphical.target

首先检查当前的默认目标:

[root@testvm1 ~]# systemctl get-default
multi-user.target
[root@testvm1 ~]# systemctl set-default graphical.target
Removed /etc/systemd/system/default.target.
Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/graphical.target.
[root@testvm1 ~]#

输入下面的命令直接切换到 graphical.target 和显示管理器的登录界面,不需要重启:

[root@testvm1 system]# systemctl isolate default.target

我不清楚为何 systemd 的开发者选择了术语 isolate 作为这个子命令。我的研究表明指的可能是运行指明的目标,但是“隔离”并终结其他所有启动该目标不需要的目标。然而,命令执行的效果是从一个运行的目标切换到另一个——在这个例子中,从多用户目标切换到图形目标。上面的命令等同于 SystemV 启动脚本和 init 程序中古老的 init 5 命令。

登录 GUI 桌面,确认能正常工作。

总结

本文探索了 Linux systemd 启动序列,开始探讨两个重要的 systemd 工具 systemctljournalctl,还说明了如何从一个目标切换到另一个目标,以及如何修改默认目标。

本系列的下一篇文章中将会创建一个新的 systemd 单元,并配置为启动阶段运行。下一篇文章还会查看一些配置选项,可以帮助确定某个特定的单元在序列中启动的位置,比如在网络启动运行后。

资源

关于 systemd 网络上有大量的信息,但大部分都简短生硬、愚钝、甚至令人误解。除了本文提到的资源,下面的网页提供了关于 systemd 启动更详细可靠的信息。

  • Fedora 项目有一个优质实用的 systemd 指南,几乎有你使用 systemd 配置、管理、维护一个 Fedora 计算机需要知道的一切。
  • Fedora 项目还有一个好用的 速查表,交叉引用了古老的 SystemV 命令和对应的 systemd 命令。
  • 要获取 systemd 的详细技术信息和创立的原因,查看 Freedesktop.orgsystemd 描述
  • Linux.com 上“systemd 的更多乐趣”提供了更高级的 systemd 信息和提示

还有一系列针对系统管理员的深层技术文章,由 systemd 的设计者和主要开发者 Lennart Poettering 所作。这些文章写于 2010 年 4 月到 2011 年 9 月之间,但在当下仍然像当时一样有价值。关于 systemd 及其生态的许多其他优秀的作品都是基于这些文章的。


via: https://opensource.com/article/20/5/systemd-startup

作者:David Both 选题:lujun9972 译者:YungeG 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

概述你的计算机如何引导和启动一个像 FreeDOS 这样的简单操作系统。

 title=

在使用 DOS 计算机的过程中,我很欣赏的一点是,引导过程相对容易理解。在 DOS 中没有太多的变动组件。而今天,我想和大家分享一下电脑是如何引导和启动像 FreeDOS 这样的简单操作系统的概况。

初始引导

当你打开计算机的电源时,系统会进行一些自我检查,如验证内存和其他组件。这被称为 开机自检 Power On Self Test (POST)。POST 之后,计算机使用一个硬编码指令,告诉它在哪里找到加载操作系统的指令。这就是“ 引导加载程序 boot loader ”,通常它将试图找到硬盘上的 主引导记录 Master Boot Record (MBR)。然后,MBR 加载主操作系统,在这里就是 FreeDOS。

这个定位一个信息以便计算机能够加载操作系统的下一个部分的过程被称为“ 引导 bootstrapping ”,来自于“ 通过你自己的努力振作起来 picking yourself up by your bootstraps ”的古老说法。正是从这个用法中,我们采用了“ 引导 boot ”一词来表示启动你的计算机。

内核

当计算机加载 FreeDOS 内核时,内核所做的第一件事就是识别用户所表示要使用的任何参数。它被保存在一个叫做 FDCONFIG.SYS 的文件中,与内核保存在同一个根目录下。如果 FDCONFIG.SYS 不存在,那么 FreeDOS 的内核就会寻找一个叫做 CONFIG.SYS 的替代文件。

如果你在 20 世纪 80 年代或 90 年代使用过 DOS,你可能对 CONFIG.SYS 文件很熟悉。从 1999 年起,FreeDOS 首先寻找 FDCONFIG.SYS,以防你的 DOS 系统与其他 DOS(如 MS-DOS)做了 双启动。请注意,MS-DOS 只使用 CONFIG.SYS 文件。因此,如果你用同一个硬盘同时启动 FreeDOS 和 MS-DOS,MS-DOS 使用 CONFIG.SYS 来配置自己,而 FreeDOS 则使用 FDCONFIG.SYS。这样一来,双方都可以使用自己的配置。

FDCONFIG.SYS 可以包含一些配置设置,其中之一是 SHELL=SHELLHIGH=。任何一个都会指示内核加载这个程序作为用户的交互式 shell。

如果 FDCONFIG.SYSCONFIG.SYS 都不存在,那么内核就会假定几个默认值,包括在哪里找到 shell。如果你在启动 FreeDOS 系统时看到 “Bad or missing Command Interpreter” 的信息,这意味着 SHELL=SHELLHIGH= 指向了一个在你系统中不存在的 shell 程序。

 title=

你可以通过查看 SHELL=SHELLHIGH= 行来调试这个问题。如果做不到这一点,请确保你在 FreeDOS 系统的根目录下有一个名为 COMMAND.COM 的程序。它就是 shell,我接下来会讲到它。

shell

在 DOS 系统中,“shell” 一词通常是指一个命令行解释器:一个交互式程序,它从用户那里读取指令,然后执行它们。在这里,FreeDOS 的 shell 与 Linux 的 Bash shell 相似。

除非你用 SHELL=SHELLHIGH= 要求内核加载一个不同的 shell,否则 DOS 上的标准命令行 shell 被称为 COMMAND.COM。当 COMMAND.COM 启动时,它也寻找一个文件来配置自己。默认情况下,COMMAND.COM 会在根目录下寻找一个名为 AUTOEXEC.BAT 的文件。AUTOEXEC.BAT 是一个“批处理文件”,它包含一组启动时运行的指令,大致类似于 Linux 上 Bash 启动时读取的 ~/.bashrc “资源文件”。

你可以在 FDCONFIG.SYS 文件中用 SHELL=SHELLHIGH= 改变 shell 以及 shell 的启动文件。FreeDOS 1.3 RC4 安装程序将系统设置为读取 FDAUTO.BAT 而不是 AUTOEXEC.BAT。这与内核读取另一个配置文件的原因相同;你可以在硬盘上用另一个 DOS 双启动 FreeDOS。FreeDOS 将使用 FDAUTO.BAT 而 MS-DOS 将使用 AUTOEXEC.BAT

如果没有像 AUTOEXEC.BAT 这样的启动文件,shell 将简单地提示用户输入日期和时间。

 title=

就是这些了。当 FreeDOS 加载了内核,而内核也加载了 shell,FreeDOS 就准备好让用户输入命令了。

 title=


via: https://opensource.com/article/21/6/freedos-boots

作者:Jim Hall 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

systemd 是所有进程之母,负责将 Linux 主机启动到可以做生产性任务的状态。

systemd(是的,全小写,即使在句子开头也是小写),是初始化程序(init)和 SystemV 初始化脚本的现代替代者。此外,它还有更多功能。

当我想到 init 和 SystemV 初始化时,像大多数系统管理员一样,我想到的是 Linux 的启动和关闭,而不是真正意义上的管理服务,例如在服务启动和运行后对其进行管理。像 init 一样,systemd 是所有进程之母,它负责使 Linux 主机启动到可以做生产性任务的状态。systemd 设定的一些功能比老的初始化程序要广泛得多,它要管理正在运行的 Linux 主机的许多方面,包括挂载文件系统、管理硬件、处理定时器以及启动和管理生产性主机所需的系统服务。

本系列文章是基于我的三期 Linux 培训课程《使用和管理 Linux:从零开始进行学习系统管理》部分内容的摘录,探讨了 systemd 在启动和启动完成后的功能。

Linux 引导

Linux 主机从关机状态到运行状态的完整启动过程很复杂,但它是开放的并且是可知的。在详细介绍之前,我将简要介绍一下从主机硬件被上电到系统准备好用户登录的过程。大多数时候,“引导过程”被作为一个整体来讨论,但这是不准确的。实际上,完整的引导和启动过程包含三个主要部分:

  • 硬件引导:初始化系统硬件
  • Linux 引导 boot :加载 Linux 内核和 systemd
  • Linux 启动 startup :systemd 为主机的生产性工作做准备

Linux 启动阶段始于内核加载了 init 或 systemd(取决于具体发行版使用的是旧的方式还是还是新的方式)之后。init 和 systemd 程序启动并管理所有其它进程,它们在各自的系统上都被称为“所有进程之母”。

将硬件引导与 Linux 引导及 Linux 启动区分开,并明确定义它们之间的分界点是很重要的。理解它们的差异以及它们每一个在使 Linux 系统进入生产状态所起的作用,才能够管理这些进程,并更好地确定大部分人所谓的“启动”问题出在哪里。

启动过程按照三步引导流程,使 Linux 计算机进入可进行生产工作的状态。当内核将主机的控制权转移到 systemd 时,启动环节开始。

systemd 之争

systemd 引起了系统管理员和其它负责维护 Linux 系统正常运行人员的广泛争议。在许多 Linux 系统中,systemd 接管了大量任务,这在某些开发者和sysadmins群体中引起了反对和不和谐。

SystemV 和 systemd 是执行 Linux 启动环节的两种不同的方法。SystemV 启动脚本和 init 程序是老的方法,而使用 目标 target 的 systemd 是新方法。尽管大多数现代 Linux 发行版都使用较新的 systemd 进行启动、关机和进程管理,但仍有一些发行版未采用。原因之一是某些发行版维护者和系统管理员喜欢老的 SystemV 方法,而不是新的 systemd。

我认为两者都有其优势。

为何我更喜欢 SystemV

我更喜欢 SystemV,因为它更开放。使用 Bash 脚本来完成启动。内核启动 init 程序(这是一个编译后的二进制)后,init 启动 rc.sysinit 脚本,该脚本执行许多系统初始化任务。rc.sysinit 执行完后,init 启动 /etc/rc.d/rc 脚本,该脚本依次启动 /etc/rc.d/rcX.d 中由 SystemV 启动脚本定义的各种服务。其中 X 是待启动的运行级别号。

除了 init 程序本身之外,所有这些程序都是开放且易于理解的脚本。可以通读这些脚本并确切了解整个启动过程中发生的事情,但是我不认为有太多系统管理员真正做到这一点。每个启动脚本都被编了号,以便按特定顺序启动预期的服务。服务是串行启动的,一次只能启动一个服务。

systemd 是由 Red Hat 的 Lennart Poettering 和 Kay Sievers 开发的,它是一个由大型的、编译的二进制可执行文件构成的复杂系统,不访问其源码就无法理解。它是开源的,因此“访问其源代码”并不难,只是不太方便。systemd 似乎表现出对 Linux 哲学多个原则的重大驳斥。作为二进制文件,systemd 无法被直接打开供系统管理员查看或进行简单更改。systemd 试图做所有事情,例如管理正在运行的服务,同时提供明显比 SystemV 更多的状态信息。它还管理硬件、进程、进程组、文件系统挂载等。systemd 几乎涉足于现代 Linux 主机的每个方面,使它成为系统管理的一站式工具。所有这些都明显违反了“程序应该小,且每个程序都应该只做一件事并做好”的原则。

为何我更喜欢 systemd

我更喜欢用 systemd 作为启动机制,因为它会根据启动阶段并行地启动尽可能多的服务。这样可以加快整个的启动速度,使得主机系统比 SystemV 更快地到达登录屏幕。

systemd 几乎可以管理正在运行的 Linux 系统的各个方面。它可以管理正在运行的服务,同时提供比SystemV 多得多的状态信息。它还管理硬件、进程和进程组、文件系统挂载等。systemd 几乎涉足于现代 Linux 操作系统的每方面,使其成为系统管理的一站式工具。(听起来熟悉吧?)

systemd 工具是编译后的二进制文件,但该工具包是开放的,因为所有配置文件都是 ASCII 文本文件。可以通过各种 GUI 和命令行工具来修改启动配置,也可以添加或修改各种配置文件来满足特定的本地计算环境的需求。

真正的问题

你认为我不能喜欢两种启动系统吗?我能,我会用它们中的任何一个。

我认为,SystemV 和 systemd 之间大多数争议的真正问题和根本原因在于,在系统管理层面没有选择权。使用 SystemV 还是 systemd 已经由各种发行版的开发人员、维护人员和打包人员选择了(但有充分的理由)。由于 init 极端的侵入性,挖出并替换 init 系统会带来很多影响,会带来很多在发行版设计过程之外难以解决的后果。

尽管该选择实际上是为我而选的,但我的Linux主机能不能开机、能不能工作,这是我平时最关心的。作为最终用户,甚至是系统管理员,我主要关心的是我是否可以完成我的工作,例如写我的书和这篇文章,安装更新以及编写脚本来自动化所有事情。只要我能做我的工作,我就不会真正在意发行版中使用的启动系统。

在启动或服务管理出现问题时,我会在意。无论主机上使用哪种启动系统,我都足够了解如何沿着事件顺序来查找故障并进行修复。

替换SystemV

以前曾有过用更现代的东西替代 SystemV 的尝试。大约在两个版本中,Fedora 使用了一个叫作 Upstart 的东西来替换老化的 SystemV,但是它没有取代 init,也没有提供我所注意到的任何变化。由于 Upstart 并未对 SystemV 的问题进行任何显著的改变,所以在这个方向上的努力很快就被放弃了,转而使用 systemd。

尽管大部分 Linux 开发人员都认可替换旧的 SystemV 启动系统是个好主意,但许多开发人员和系统管理员并不喜欢 systemd。与其重新讨论人们在 systemd 中遇到的或曾经遇到过的所有所谓的问题,不如带你去看两篇好文章,尽管有些陈旧,但它们涵盖了大多数内容。Linux 内核的创建者 Linus Torvalds 对 systemd 似乎不感兴趣。在 2014 年 ZDNet 的一篇文章《Linus Torvalds 和其他人对 Linux 上的 systemd 的看法》中,Linus 清楚地表达了他的感受。

“实际上我对 systemd 本身没有任何特别强烈的意见。我对一些核心开发人员有一些问题,我认为他们在对待错误和兼容性方面过于轻率,而且我认为某些设计细节是疯狂的(例如,我不喜欢二进制日志),但这只是细节,不是大问题。”

如果你对 Linus 不太了解的话,我可以告诉你,如果他不喜欢某事,他是非常直言不讳的,很明确,而且相当明确的表示不喜欢。他解决自己对事物不满的方式已经被社会更好地接受了。

2013 年,Poettering 写了一篇很长的博客,他在文章驳斥了关于 systemd 的迷思,同时对创建 systemd 的一些原因进行了深入的剖析。这是一分很好的读物,我强烈建议你阅读。

systemd 任务

根据编译过程中使用的选项(不在本系列中介绍),systemd 可以有多达 69 个二进制可执行文件执行以下任务,其中包括:

  • systemd 程序以 1 号进程(PID 1)运行,并提供使尽可能多服务并行启动的系统启动能力,它额外加快了总体启动时间。它还管理关机顺序。
  • systemctl 程序提供了服务管理的用户接口。
  • 支持 SystemV 和 LSB 启动脚本,以便向后兼容。
  • 服务管理和报告提供了比 SystemV 更多的服务状态数据。
  • 提供基本的系统配置工具,例如主机名、日期、语言环境、已登录用户的列表,正在运行的容器和虚拟机、系统帐户、运行时目录及设置,用于简易网络配置、网络时间同步、日志转发和名称解析的守护进程。
  • 提供套接字管理。
  • systemd 定时器提供类似 cron 的高级功能,包括在相对于系统启动、systemd 启动时间、定时器上次启动时间的某个时间点运行脚本。
  • 它提供了一个工具来分析定时器规范中使用的日期和时间。
  • 能感知分层的文件系统挂载和卸载功能可以更安全地级联挂载的文件系统。
  • 允许主动的创建和管理临时文件,包括删除。
  • D-Bus 的接口提供了在插入或移除设备时运行脚本的能力。这允许将所有设备(无论是否可插拔)都被视为即插即用,从而大大简化了设备的处理。
  • 分析启动环节的工具可用于查找耗时最多的服务。
  • 它包括用于存储系统消息的日志以及管理日志的工具。

架构

这些以及更多的任务通过许多守护程序、控制程序和配置文件来支持。图 1 显示了许多属于 systemd 的组件。这是一个简化的图,旨在提供概要描述,因此它并不包括所有独立的程序或文件。它也不提供数据流的视角,数据流是如此复杂,因此在本系列文章的背景下没用。

 title=

图 1:systemd 的架构,作者 Shmuel Csaba Otto Traian (CC BY-SA 3.0)

如果要完整地讲解 systemd 就需要一本书。你不需要了解图 1 中的 systemd 组件是如何组合在一起的细节。只需了解支持各种 Linux 服务管理以及日志文件和日志处理的程序和组件就够了。但是很明显, systemd 并不是某些批评者所宣称的那样,它是一个单一的怪物。

作为 1 号进程的 systemd

systemd 是 1 号进程(PID 1)。它的一些功能,比老的 SystemV3 init 要广泛得多,用于管理正在运行的 Linux 主机的许多方面,包括挂载文件系统以及启动和管理 Linux 生产主机所需的系统服务。与启动环节无关的任何 systemd 任务都不在本文讨论范围之内(但本系列后面的一些文章将探讨其中的一些任务)。

首先,systemd 挂载 /etc/fstab 所定义的文件系统,包括所有交换文件或分区。此时,它可以访问位于 /etc 中的配置文件,包括它自己的配置文件。它使用其配置链接 /etc/systemd/system/default.target 来确定将主机引导至哪个状态或目标。default.target 文件是指向真实目标文件的符号链接。对于桌面工作站,通常是 graphical.target,它相当于 SystemV 中的运行级别 5。对于服务器,默认值更可能是 multi-user.target,相当于 SystemV 中的运行级别 3。emergency.target 类似于单用户模式。 目标 target 服务 service 是 systemd 的 单元 unit

下表(图 2)将 systemd 目标与老的 SystemV 启动运行级别进行了比较。systemd 提供 systemd 目标别名以便向后兼容。目标别名允许脚本(以及许多系统管理员)使用 SystemV 命令(如 init 3)更改运行级别。当然,SystemV 命令被转发给 systemd 进行解释和执行。

systemd 目标SystemV 运行级别目标别名描述
default.target 此目标总是通过符号连接的方式成为 multi-user.targetgraphical.target 的别名。systemd 始终使用 default.target 来启动系统。default.target 绝不应该设为 halt.targetpoweroff.targetreboot.target 的别名。
graphic.target5runlevel5.target带有 GUI 的 multi-user.target
4runlevel4.target未用。在 SystemV 中运行级别 4 与运行级别 3 相同。可以创建并自定义此目标以启动本地服务,而无需更改默认的 multi-user.target
multi-user.target3runlevel3.target所有服务在运行,但仅有命令行界面(CLI)。
2runlevel2.target多用户,没有 NFS,其它所有非 GUI 服务在运行。
rescue.target1runlevel1.target基本系统,包括挂载文件系统,运行最基本的服务和主控制台的恢复 shell。
emergency.targetS 单用户模式:没有服务运行;不挂载文件系统。这是最基本的工作级别,只有主控制台上运行的一个紧急 Shell 供用户与系统交互。
halt.target 停止系统而不关闭电源。
reboot.target6runlevel6.target重启。
poweroff.target0runlevel0.target停止系统并关闭电源。

图 2:SystemV 运行级别与 systemd 目标和一些目标别名的比较

每个目标在其配置文件中都描述了一个依赖集。systemd 启动必须的依赖项,这些依赖项是运行 Linux 主机到特定功能级别所需的服务。当目标配置文件中列出的所有依赖项被加载并运行后,系统就在该目标级别运行了。在图 2 中,功能最多的目标位于表的顶部,从顶向下,功能逐步递减。

systemd 还会检查老的 SystemV init 目录,以确认是否存在任何启动文件。如果有,systemd 会将它们作为配置文件以启动它们描述的服务。网络服务是一个很好的例子,在 Fedora 中它仍然使用 SystemV 启动文件。

图 3(如下)是直接从启动手册页复制来的。它显示了 systemd 启动期间一般的事件环节以及确保成功启动的基本顺序要求。

                                        cryptsetup-pre.target
                                                   |
 (various low-level                                v
     API VFS mounts:                 (various cryptsetup devices...)
  mqueue, configfs,                                |    |
  debugfs, ...)                                    v    |
  |                                  cryptsetup.target  |
  |  (various swap                                 |    |    remote-fs-pre.target
  |   devices...)                                  |    |     |        |
  |    |                                           |    |     |        v
  |    v                       local-fs-pre.target |    |     |  (network file systems)
  |  swap.target                       |           |    v     v                 |
  |    |                               v           |  remote-cryptsetup.target  |
  |    |  (various low-level  (various mounts and  |             |              |
  |    |   services: udevd,    fsck services...)   |             |    remote-fs.target
  |    |   tmpfiles, random            |           |             |             /
  |    |   seed, sysctl, ...)          v           |             |            /
  |    |      |                 local-fs.target    |             |           /
  |    |      |                        |           |             |          /
  \____|______|_______________   ______|___________/             |         /
                              \ /                                |        /
                               v                                 |       /
                        sysinit.target                           |      /
                               |                                 |     /
        ______________________/|\_____________________           |    /
       /              |        |      |               \          |   /
       |              |        |      |               |          |  /
       v              v        |      v               |          | /
  (various       (various      |  (various            |          |/
   timers...)      paths...)   |   sockets...)        |          |
       |              |        |      |               |          |
       v              v        |      v               |          |
 timers.target  paths.target   |  sockets.target      |          |
       |              |        |      |               v          |
       v              \_______ | _____/         rescue.service   |
                              \|/                     |          |
                               v                      v          |
                           basic.target         rescue.target    |
                               |                                 |
                       ________v____________________             |
                      /              |              \            |
                      |              |              |            |
                      v              v              v            |
                  display-    (various system   (various system  |
              manager.service     services        services)      |
                      |         required for        |            |
                      |        graphical UIs)       v            v
                      |              |            multi-user.target
 emergency.service    |              |              |
         |            \_____________ | _____________/
         v                          \|/
 emergency.target                    v
                              graphical.target

图 3: systemd 启动图

sysinit.targetbasic.target 目标可以看作启动过程中的检查点。尽管 systemd 的设计目标之一是并行启动系统服务,但是某些服务和功能目标必须先启动,然后才能启动其它服务和目标。直到该检查点所需的所有服务和目标被满足后才能通过这些检查点。

sysinit.target 所依赖的所有单元都完成时,就会到达 sysinit.target。所有这些单元,包括挂载文件系统、设置交换文件、启动 Udev、设置随机数生成器种子、启动低层服务以及配置安全服务(如果一个或多个文件系统是加密的)都必须被完成,但在 sysinit.target 中,这些任务可以并行执行。

sysinit.target 启动了系统接近正常运行所需的所有低层服务和单元,它们也是进入 basic.target 所需的。

在完成 sysinit.target 之后,systemd 会启动实现下一个目标所需的所有单元。basic.target 通过启动所有下一目标所需的单元来提供一些额外功能。包括设置为各种可执行程序目录的路径、设置通信套接字和计时器之类。

最后,用户级目标 multi-user.targetgraphical.target 被初始化。要满足 graphical.target 的依赖必须先达到 multi-user.target。图 3 中带下划线的目标是通常的启动目标。当达到这些目标之一时,启动就完成了。如果 multi-user.target 是默认设置,那么你应该在控制台上看到文本模式的登录界面。如果 graphical.target 是默认设置,那么你应该看到图形的登录界面。你看到的具体的 GUI 登录界面取决于你的默认显示管理器。

引导手册页还描述并提供了引导到初始化 RAM 磁盘和 systemd 关机过程的图。

systemd 还提供了一个工具,该工具列出了完整的启动过程或指定单元的依赖项。单元是一个可控的 systemd 资源实体,其范围可以从特定服务(例如 httpd 或 sshd)到计时器、挂载、套接字等。尝试以下命令并滚动查看结果。

systemctl list-dependencies graphical.target

注意,这会完全展开使系统进入 graphical.target 运行模式所需的顶层目标单元列表。也可以使用 --all 选项来展开所有其它单元。

systemctl list-dependencies --all graphical.target

你可以使用 less 命令来搜索诸如 targetslicesocket 之类的字符串。

现在尝试下面的方法。

systemctl list-dependencies multi-user.target

systemctl list-dependencies rescue.target

systemctl list-dependencies local-fs.target

systemctl list-dependencies dbus.service

这个工具帮助我可视化我正用的主机的启动依赖细节。继续花一些时间探索一个或多个 Linux 主机的启动树。但是要小心,因为 systemctl 手册页包含以下注释:

“请注意,此命令仅列出当前被服务管理器加载到内存的单元。尤其是,此命令根本不适合用于获取特定单元的全部反向依赖关系列表,因为它不会列出被单元声明了但是未加载的依赖项。”

结尾语

即使在没有深入研究 systemd 之前,很明显能看出它既强大又复杂。显然,systemd 不是单一、庞大、独体且不可知的二进制文件。相反,它是由许多较小的组件和旨在执行特定任务的子命令组成。

本系列的下一篇文章将更详细地探讨 systemd 的启动,以及 systemd 的配置文件,更改默认的目标以及如何创建简单服务单元。

资源

互联网上有大量关于 systemd 的信息,但是很多都很简短、晦涩甚至是带有误导。除了本文提到的资源外,以下网页还提供了有关 systemd 启动的更详细和可靠的信息。

  • Fedora 项目有一个很好的实用的 systemd 指南。它有你需要知道的通过 systemd 来配置、管理和维护 Fedora 主机所需的几乎所有知识。
  • Fedora 项目还有一个不错的速记表,将老的 SystemV 命令与对比的 systemd 命令相互关联。
  • 有关 systemd 的详细技术信息及创建它的原因,请查看 Freedesktop.orgsystemd 描述
  • Linux.com 的“systemd 的更多乐趣”提供了更高级的 systemd 信息和技巧

还有针对 Linux 系统管理员的一系列技术性很强的文章,作者是 systemd 的设计师和主要开发者 Lennart Poettering。这些文章是在 2010 年 4 月至 2011 年 9 月之间撰写的,但它们现在和那时一样有用。关于 systemd 及其生态的其它许多好文都基于这些论文。


via: https://opensource.com/article/20/4/systemd

作者:David Both 选题:lujun9972 译者:messon007 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

单用户模式,也被称为维护模式,超级用户可以在此模式下恢复/修复系统问题。

通常情况下,这类问题在多用户环境中修复不了。系统可以启动但功能不能正常运行或者你登录不了系统。

在基于 Red Hat(RHEL)7/8 的系统中,使用 runlevel1.targetrescue.target 来实现。

在此模式下,系统会挂载所有的本地文件系统,但不开启网络接口。

系统仅启动特定的几个服务和修复系统必要的尽可能少的功能。

当你想运行文件系统一致性检查来修复损坏的文件系统,或忘记 root 密码后重置密码,或要修复系统上的一个挂载点问题时,这个方法会很有用。

你可以用下面三种方法以单用户模式启动 CentOS/RHEL 7/8 系统。

  • 方法 1:通过向内核添加 rd.break 参数来以单用户模式启动 CentOS/RHEL 7/8 系统
  • 方法 2:通过用 init=/bin/bashinit=/bin/sh 替换内核中的 rhgb quiet 语句来以单用户模式启动 CentOS/RHEL 7/8 系统
  • 方法 3:通过用 rw init=/sysroot/bin/sh 参数替换内核中的 ro 语句以单用户模式启动 CentOS/RHEL 7/8 系统

方法 1

通过向内核添加 rd.break 参数来以单用户模式启动 CentOS/RHEL 7/8 系统。

重启你的系统,在 GRUB2 启动界面,按下 e 键来编辑选中的内核。你需要选中第一行,第一个是最新的内核,然而如果你想用旧的内核启动系统你也可以选择其他的行。

根据你的 RHEL/CentOS 版本,找到 linux16linux 语句,按下键盘上的 End 键,跳到行末,像下面截图中展示的那样添加关键词 rd.break,按下 Ctrl+xF10 来进入单用户模式。

如果你的系统是 RHEL/CentOS 7,你需要找 linux16,如果你的系统是 RHEL/CentOS 8,那么你需要找 linux

这个修改会让你的 root 文件系统以 “只读(ro)” 模式挂载。你可以用下面的命令来验证下。下面的输出也明确地告诉你当前是在 “ 紧急模式 Emergency Mode ”。

# mount | grep root

为了修改 sysroot 文件系统,你需要用读写模式(rw)重新挂载它。

# mount -o remount,rw /sysroot

运行下面的命令修改环境,这就是大家熟知的 “监禁目录” 或 “chroot 监狱”。

# chroot /sysroot

现在,单用户模式已经完全准备好了。当你修复了你的问题要退出单用户模式时,执行下面的步骤。

CentOS/RHEL 7/8 默认使用 SELinux,因此创建下面的隐藏文件,这个文件会在下一次启动时重新标记所有文件。

# touch /.autorelabel

最后,用下面的命令重启系统。你也可以输入两次 exit 命令来重启你的系统。

# reboot -f

方法 2

通过用 init=/bin/bashinit=/bin/sh 替换内核中的 rhgb quiet 语句来以单用户模式启动 CentOS/RHEL 7/8 系统。

重启你的系统,在 GRUB2 启动界面,按下 e 键来编辑选中的内核。

找到语句 rhgb quiet,用 init=/bin/bashinit=/bin/sh 替换它,然后按下 Ctrl+xF10 来进入单用户模式。

init=/bin/bash 的截图。

init=/bin/sh 的截图。

默认情况下,上面的操作会以只读(ro)模式挂载你的 / 分区,因此你需要以读写(rw)模式重新挂载 / 文件系统,这样才能修改它。

# mount -o remount,rw /

现在你可以执行你的任务了。当结束时,执行下面的命令来开启重启时的 SELinux 重新标记。

# touch /.autorelabel

最后,重启系统。

# exec /sbin/init 6

方法 3

通过用 rw init=/sysroot/bin/sh 参数替换内核中的 ro 单词,以单用户模式启动 CentOS/RHEL 7/8 系统。

为了中断自动启动的过程,重启你的系统并在 GRUB2 启动界面按下任意键。

现在会展示你系统上所有可用的内核,选择最新的内核,按下 e 键来编辑选中的内核参数。

找到以 linuxlinux16 开头的语句,用 rw init=/sysroot/bin/sh 替换 ro。替换完后按下 Ctrl+xF10 来进入单用户模式。

运行下面的命令把环境切换为 “chroot 监狱”。

# chroot /sysroot

如果需要,做出必要的修改。修改完后,执行下面的命令来开启重启时的 SELinux 重新标记。

# touch /.autorelabel

最后,重启系统。

# reboot -f

via: https://www.2daygeek.com/boot-centos-7-8-rhel-7-8-single-user-mode/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

快速启动嵌入式设备或电信设备,对于时间要求紧迫的应用程序是至关重要的,并且在改善用户体验方面也起着非常重要的作用。这个文章给予一些关于如何增强任意设备的启动时间的重要技巧。

快速启动或快速重启在各种情况下起着至关重要的作用。为了保持所有服务的高可用性和更好的性能,嵌入式设备的快速启动至关重要。设想有一台运行着没有启用快速启动的 Linux 操作系统的电信设备,所有依赖于这个特殊嵌入式设备的系统、服务和用户可能会受到影响。这些设备维持其服务的高可用性是非常重要的,为此,快速启动和重启起着至关重要的作用。

一台电信设备的一次小故障或关机,即使只是几秒钟,都可能会对无数互联网上的用户造成破坏。因此,对于很多对时间要求严格的设备和电信设备来说,在它们的设备中加入快速启动的功能以帮助它们快速恢复工作是非常重要的。让我们从图 1 中理解 Linux 启动过程。

图 1:启动过程

监视工具和启动过程

在对机器做出更改之前,用户应注意许多因素。其中包括计算机的当前启动速度,以及占用资源并增加启动时间的服务、进程或应用程序。

启动图

为监视启动速度和在启动期间启动的各种服务,用户可以使用下面的命令来安装:

sudo apt-get install pybootchartgui

你每次启动时,启动图会在日志中保存一个 png 文件,使用户能够查看该 png 文件来理解系统的启动过程和服务。为此,使用下面的命令:

cd /var/log/bootchart

用户可能需要一个应用程序来查看 png 文件。Feh 是一个面向控制台用户的 X11 图像查看器。不像大多数其它的图像查看器,它没有一个精致的图形用户界面,但它只用来显示图片。Feh 可以用于查看 png 文件。你可以使用下面的命令来安装它:

sudo apt-get install feh

你可以使用 feh xxxx.png 来查看 png 文件。

图 2:启动图

图 2 显示了一个正在查看的引导图 png 文件。

systemd-analyze

但是,对于 Ubuntu 15.10 以后的版本不再需要引导图。为获取关于启动速度的简短信息,使用下面的命令:

systemd-analyze

图 3:systemd-analyze 的输出

图表 3 显示命令 systemd-analyze 的输出。

命令 systemd-analyze blame 用于根据初始化所用的时间打印所有正在运行的单元的列表。这个信息是非常有用的,可用于优化启动时间。systemd-analyze blame 不会显示服务类型为简单(Type=simple)的服务,因为 systemd 认为这些服务应是立即启动的;因此,无法测量初始化的延迟。

图 4:systemd-analyze blame 的输出

图 4 显示 systemd-analyze blame 的输出。

下面的命令打印时间关键的服务单元的树形链条:

command systemd-analyze critical-chain

图 5 显示命令 systemd-analyze critical-chain 的输出。

图 5:systemd-analyze critical-chain 的输出

减少启动时间的步骤

下面显示的是一些可以减少启动时间的各种步骤。

BUM(启动管理器)

BUM 是一个运行级配置编辑器,允许在系统启动或重启时配置初始化服务。它显示了可以在启动时启动的每个服务的列表。用户可以打开和关闭各个服务。BUM 有一个非常清晰的图形用户界面,并且非常容易使用。

在 Ubuntu 14.04 中,BUM 可以使用下面的命令安装:

sudo apt-get install bum

为在 15.10 以后的版本中安装它,从链接 http://apt.ubuntu.com/p/bum 下载软件包。

以基本的服务开始,禁用扫描仪和打印机相关的服务。如果你没有使用蓝牙和其它不想要的设备和服务,你也可以禁用它们中一些。我强烈建议你在禁用相关的服务前学习服务的基础知识,因为这可能会影响计算机或操作系统。图 6 显示 BUM 的图形用户界面。

图 6:BUM

编辑 rc 文件

要编辑 rc 文件,你需要转到 rc 目录。这可以使用下面的命令来做到:

cd /etc/init.d

然而,访问 init.d 需要 root 用户权限,该目录基本上包含的是开始/停止脚本,这些脚本用于在系统运行时或启动期间控制(开始、停止、重新加载、启动启动)守护进程。

init.d 目录中的 rc 文件被称为 运行控制 run control 脚本。在启动期间,init 执行 rc 脚本并发挥它的作用。为改善启动速度,我们可以更改 rc 文件。使用任意的文件编辑器打开 rc 文件(当你在 init.d 目录中时)。

例如,通过输入 vim rc ,你可以更改 CONCURRENCY=noneCONCURRENCY=shell。后者允许某些启动脚本同时执行,而不是依序执行。

在最新版本的内核中,该值应该被更改为 CONCURRENCY=makefile

图 7 和图 8 显示编辑 rc 文件前后的启动时间比较。可以注意到启动速度有所提高。在编辑 rc 文件前的启动时间是 50.98 秒,然而在对 rc 文件进行更改后的启动时间是 23.85 秒。

但是,上面提及的更改方法在 Ubuntu 15.10 以后的操作系统上不工作,因为使用最新内核的操作系统使用 systemd 文件,而不再是 init.d 文件。

图 7:对 rc 文件进行更改之前的启动速度

图 8:对 rc 文件进行更改之后的启动速度

E4rat

E4rat 代表 e4 减少访问时间 reduced access time (仅在 ext4 文件系统的情况下)。它是由 Andreas Rid 和 Gundolf Kiefer 开发的一个项目。E4rat 是一个通过碎片整理来帮助快速启动的应用程序。它还会加速应用程序的启动。E4rat 使用物理文件的重新分配来消除寻道时间和旋转延迟,因而达到较高的磁盘传输速度。

E4rat 可以 .deb 软件包形式获得,你可以从它的官方网站 http://e4rat.sourceforge.net/ 下载。

Ubuntu 默认安装的 ureadahead 软件包与 e4rat 冲突。因此必须使用下面的命令安装这几个软件包:

sudo dpkg purge ureadahead ubuntu-minimal

现在使用下面的命令来安装 e4rat 的依赖关系:

sudo apt-get install libblkid1 e2fslibs

打开下载的 .deb 文件,并安装它。现在需要恰当地收集启动数据来使 e4rat 工作。

遵循下面所给的步骤来使 e4rat 正确地运行并提高启动速度。

  • 在启动期间访问 Grub 菜单。这可以在系统启动时通过按住 shift 按键来完成。
  • 选择通常用于启动的选项(内核版本),并按 e
  • 查找以 linux /boot/vmlinuz 开头的行,并在该行的末尾添加下面的代码(在句子的最后一个字母后按空格键):init=/sbin/e4rat-collect or try - quiet splash vt.handsoff =7 init=/sbin/e4rat-collect
  • 现在,按 Ctrl+x 来继续启动。这可以让 e4rat 在启动后收集数据。在这台机器上工作,并在接下来的两分钟时间内打开并关闭应用程序。
  • 通过转到 e4rat 文件夹,并使用下面的命令来访问日志文件:cd /var/log/e4rat
  • 如果你没有找到任何日志文件,重复上面的过程。一旦日志文件就绪,再次访问 Grub 菜单,并对你的选项按 e
  • 在你之前已经编辑过的同一行的末尾输入 single。这可以让你访问命令行。如果出现其它菜单,选择恢复正常启动(Resume normal boot)。如果你不知为何不能进入命令提示符,按 Ctrl+Alt+F1 组合键。
  • 在你看到登录提示后,输入你的登录信息。
  • 现在输入下面的命令:sudo e4rat-realloc /var/lib/e4rat/startup.log。此过程需要一段时间,具体取决于机器的磁盘速度。
  • 现在使用下面的命令来重启你的机器:sudo shutdown -r now
  • 现在,我们需要配置 Grub 来在每次启动时运行 e4rat。
  • 使用任意的编辑器访问 grub 文件。例如,gksu gedit /etc/default/grub
  • 查找以 GRUB CMDLINE LINUX DEFAULT= 开头的一行,并在引号之间和任何选项之前添加下面的行:init=/sbin/e4rat-preload 18
  • 它应该看起来像这样:GRUB CMDLINE LINUX DEFAULT = init=/sbin/e4rat- preload quiet splash
  • 保存并关闭 Grub 菜单,并使用 sudo update-grub 更新 Grub 。
  • 重启系统,你将发现启动速度有明显变化。

图 9 和图 10 显示在安装 e4rat 前后的启动时间之间的差异。可注意到启动速度的提高。在使用 e4rat 前启动所用时间是 22.32 秒,然而在使用 e4rat 后启动所用时间是 9.065 秒。

图 9:使用 e4rat 之前的启动速度

图 10:使用 e4rat 之后的启动速度

一些易做的调整

使用很小的调整也可以达到良好的启动速度,下面列出其中两个。

SSD

使用固态设备而不是普通的硬盘或者其它的存储设备将肯定会改善启动速度。SSD 也有助于加快文件传输和运行应用程序方面的速度。

禁用图形用户界面

图形用户界面、桌面图形和窗口动画占用大量的资源。禁用图形用户界面是获得良好的启动速度的另一个好方法。


via: https://opensourceforu.com/2019/10/how-to-go-about-linux-boot-time-optimisation/

作者:B Thangaraju 选题:lujun9972 译者:robsean 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

进行 Linux 内核与固件开发的时候,往往需要多次的重启,会浪费大把的时间。

在所有我拥有或使用过的电脑中,启动最快的那台是 20 世纪 80 年代的电脑。在你把手从电源键移到键盘上的时候,BASIC 解释器已经在等待你输入命令了。对于现代的电脑,启动时间从笔记本电脑的 15 秒到小型家庭服务器的数分钟不等。为什么它们的启动时间有差别?

那台直接启动到 BASIC 命令行提示符的 20 世纪 80 年代微电脑,有着一颗非常简单的 CPU,它在通电的时候就立即开始从一个内存地址中获取和执行指令。因为这些系统的 BASIC 在 ROM 里面,基本不需要载入的时间——你很快就进到 BASIC 命令提示符中了。同时代更加复杂的系统,比如 IBM PC 或 Macintosh,需要一段可观的时间来启动(大约 30 秒),尽管这主要是因为需要从软盘上读取操作系统的缘故。在可以加载操作系统之前,只有很小一部分时间是花费在固件上的。

现代服务器往往在从磁盘上读取操作系统之前,在固件上花费了数分钟而不是数秒。这主要是因为现代系统日益增加的复杂性。CPU 不再能够只是运行起来就开始全速执行指令,我们已经习惯于 CPU 频率变化、节省能源的待机状态以及 CPU 多核。实际上,在现代 CPU 内部有数量惊人的更简单的处理器,它们协助主 CPU 核心启动并提供运行时服务,比如在过热的时候压制频率。在绝大多数 CPU 架构中,在你的 CPU 内的这些核心上运行的代码都以不透明的二进制 blob 形式提供。

在 OpenPOWER 系统上,所有运行在 CPU 内部每个核心的指令都是开源的。在有 OpenBMC(比如 IBM 的 AC922 系统和 Raptor 的 TALOS II 以及 Blackbird 系统)的机器上,这还延伸到了运行在 基板管理控制器 Baseboard Management Controller 上的代码。这就意味着我们可以一探究竟,到底为什么从接入电源线到显示出熟悉的登录界面花了这么长时间。

如果你是内核相关团队的一员,你可能启动过许多内核。如果你是固件相关团队的一员,你可能要启动许多不同的固件映像,接着是一个操作系统,来确保你的固件仍能工作。如果我们可以减少硬件的启动时间,这些团队可以更有生产力,并且终端用户在搭建系统或重启安装固件或系统更新的时候会对此表示感激。

过去的几年,Linux 发行版的启动时间已经做了很多改善。现代的初始化系统在处理并行和按需任务上做得很好。在一个现代系统上,一旦内核开始执行,它可以在短短数秒内进入登录提示符界面。这里短短的数秒不是优化启动时间的下手之处,我们要到更早的地方:在我们到达操作系统之前。

在 OpenPOWER 系统上,固件通过启动一个存储在固件闪存芯片上的 Linux 内核来加载操作系统,它运行一个叫做 Petitboot 的用户态程序去寻找用户想要启动的系统所在磁盘,并通过 kexec 启动它。有了这些优化,启动 Petitboot 环境只占了启动时间的百分之几,所以我们还得从其他地方寻找优化项。

在 Petitboot 环境启动前,有一个先导固件,叫做 Skiboot,在它之前有个 Hostboot。在 Hostboot 之前是 Self-Boot Engine,一个晶圆切片(die)上的单独核心,它启动单个 CPU 核心并执行来自 Level 3 缓存的指令。这些组件是我们可以在减少启动时间上取得进展的主要部分,因为它们花费了启动的绝大部分时间。或许这些组件中的一部分没有进行足够的优化或尽可能做到并行?

另一个研究路径是重启时间而不是启动时间。在重启的时候,我们真的需要对所有硬件重新初始化吗?

正如任何现代系统那样,改善启动(或重启)时间的方案已经变成了更多的并行执行、解决遗留问题、(可以认为)作弊的结合体。


via: https://opensource.com/article/19/1/booting-linux-faster

作者:Stewart Smith 选题:lujun9972 译者:alim0x 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出