第 3 章 系统初始化

# 第 3 章 系统初始化

作为系统管理员，粗略地了解 Debian 系统的启动和配置方式是明智的。尽管准确的细节在安装的软件包及对应的文档中，但这些知识对我们大多数人来说都是必须掌握的。

下面是 Debian 系统初始化的要点概述。由于 Debian 系统在不断发展，您应该参考最新的文档。

- Debian Linux 内核手册 是关于 Debian 内核的主要信息来源。

- bootup(7) 介绍了基于 `systemd` 的系统启动流程。（近期的 Debian）

- boot(7) 介绍了基于 UNIX System V Release 4 的系统启动流程。（旧版的 Debian）

## 3.1. 启动过程概述

计算机系统从上电事件到能为用户提供完整的操作系统（OS）功能为止，需要经历几个阶段的启动过程。

为简便起见，笔者将讨论范围限定在具有默认安装的典型 PC 平台上。

典型的启动过程像是一个四级的火箭。每一级火箭将系统控制权交给下一级。

- 第 3.1.1 节 “第一阶段：UEFI”

- 第 3.1.2 节 “第二阶段：引载加载程序”

- 第 3.1.3 节 “第三阶段：迷你 Debian 系统”

- 第 3.1.4 节 “第四阶段：常规 Debian 系统”

当然，这些阶段可以有不同的配置。比如，你编译了自己的内核，则可能会跳过迷你 Debian 系统的步骤。因此，在读者亲自确认之前，请勿假定自己系统的情况也是如此。

### 3.1.1. 第一阶段：UEFI

Unified Extensible Firmware Interface (UEFI) 统一可扩展固件接口 定义了启动管理器作为 UEFI 规范的一部分。当一个计算机打开电源，启动管理器是启动流程的第一阶段，它检查启动配置并基于启动配置的设置，执行特定的操作系统引导加载程序或操作系统内核（通常是引导加载程序）。启动配置通过变量存储在 NVRAM，变量包括指示操作系统引导加载程序或操作系统内核的文件系统路径的变量。

EFI system partition (ESP) EFI 系统分区 是一个数据存储设备分区，在计算机里用来遵照 UEFI 规范。当计算机打开电源时，由 UEFI 固件来访问，它存储了 UEFI 应用程序和这些应用程序运行所需要的文件，包括操作系统的引导加载程序。（在老的 PC 系统，存放在 MBR 里的 BIOS 可以用来代替。）

### 3.1.2. 第二阶段：引载加载程序

引导加载程序是启动过程的第二阶段，由 UEFI 启动。引导加载程序将系统内核映像和 initrd 映像加载到内存并将控制权交给它们。initrd 映像是根文件系统映像，其支持程度依赖于所使用的引导加载程序。

Debian 系统通常使用 Linux 内核作为默认的系统内核。当前的 5.x Linux 内核的 initrd 映像在技术上是 initramfs（初始 RAM 文件系统）映像。

有许多引导加载程序和配置选项存在。

表 3.1. 引导加载程序列表

软件包 | 流行度 | 大小 | initrd | 引导加载程序 | 说明
--- | --- | --- | --- | --- | ---
grub-efi-amd64 | I:451 | 142 | 支持 | GRUB UEFI | 可智能识别磁盘分区和文件系统，例如 vfat、ext4…（UEFI）
grub-pc | V:17, I:525 | 479 | 支持 | GRUB 第 2 版 | 可智能识别磁盘分区和文件系统，例如 vfat、ext4…（BIOS）
grub-rescue-pc | V:0.06, I:0.59 | 7273 | 支持 | GRUB 第 2 版 | 此为 GRUB 第 2 版的可引导修复映像（CD 和软盘）（PC / BIOS 版本）
grml-rescueboot | V:0.1, I:1.1 | 36 | N/A | GRUB 第 2 版 插件 | grml-rescueboot 增加即用的 Linux ISO 镜像到 grub2 启动菜单
syslinux | V:3, I:32 | 325 | 支持 | Isolinux | 可识别 ISO9660 文件系统。引导 CD 使用此项。
syslinux | V:3, I:32 | 325 | 支持 | Syslinux | 可识别 MSDOS 文件系统（FAT）。引导软盘使用此项。
loadlin | V:0.03, I:0.40 | 87 | 支持 | Loadlin | 新系统从 FreeDOS 或 MSDOS 中启动。
mbr | V:0.3, I:2.9 | 47 | 不支持 | Neil Turton 的 MBR | 此为取代 MSDOS MBR 的自由软件。只可识别硬盘分区。

对于 UEFI 系统，GRUB2 首先读取 ESP 分区，使用 "`/boot/efi/EFI/debian/grub.cfg`"里面 `search.fs_uuid` 指定的 UUID 来确定 GRUB2 菜单配置文件 "`/boot/grub/grub.cfg`" 所在的分区。

GRUB2 菜单配置文件的关键部分看起来像：

    menuentry 'Debian GNU/Linux' ... {
            load_video
            insmod gzio
            insmod part_gpt
            insmod ext2
            search --no-floppy --fs-uuid --set=root fe3e1db5-6454-46d6-a14c-071208ebe4b1
            echo    'Loading Linux 5.10.0-6-amd64 ...'
            linux   /boot/vmlinuz-5.10.0-6-amd64 root=UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 ro quiet
            echo    'Loading initial ramdisk ...'
            initrd  /boot/initrd.img-5.10.0-6-amd64
    }

对于这部分的 `/boot/grub/grub.cfg`，这个菜单条目的意义如下。

表 3.2. `/boot/grub/grub.cfg` 文件上面部分菜单条目意义

设置 | 值
--- | ---
GRUB2 模块加载 | `gzio`, `part_gpt`, `ext2`
使用的根文件系统分区 | 由 `UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1` 指定的分区标识
内核镜像文件在根文件系统中的路径 | `/boot/vmlinuz-5.10.0-6-amd64`
使用的内核启动参数 | "`root=UUID=fe3e1db5-6454-46d6-a14c-071208ebe4b1 ro quiet`"
initrd 镜像文件在根文件系统中的路径 | `/boot/initrd.img-5.10.0-6-amd64`

在 Debian 系统 ，"`/boot/grub/grub.cfg`" 是由安装的 GRUB 软件包(如： `grub-efi-amd64`)管理，不赞成用户直接修改这个文件。应当定制 "`/etc/grub.d/`" 和 "`/etc/default/grub`" 来代替修改配置文件。配置 GRUB 配置文件，更新 NVRAM 变量来自动启动到 Debian：

    # dpkg-reconfigure grub-efi-amd64

| 提示
通过删除 "`/etc/default/grub`" 里面 `GRUB_CMDLINE_LINUX_DEFAULT` 的 `quiet` 值 ，你能够显示内核启动日志信息。

| 提示
把图形文件放到 "`/boot/grub/`" 来增加 GRUB 背景图。

参见 “`info grub`” 、 grub-install(8)、grub-mkconfig(8)。

### 3.1.3. 第三阶段：迷你 Debian 系统

迷你 Debian 系统是启动流程的第三阶段，由引导加载程序启动。它会在内存中运行系统内核和根文件系统。这是启动流程的一个可选准备阶段。

| 注意
“迷你 Debian 系统”是笔者自创的术语，用于在本文档中描述启动流程的第三个阶段。这个系统通常被称为 initrd 或 initramfs 系统。内存中类似的系统在 Debian 安装程序中使用。

`/init` 程序是内存中的根文件系统上执行的第一个程序。这个程序在用户空间把内核初始化，并把控制权交给下一阶段。迷你 Debian 系统能够在主引导流程之前添加内核模块或以加密形式挂载根文件系统，使引导流程更加灵活。

- 如果 initramfs 是由 `initramfs-tools` 创建，则"`/init`" 程序是一个 shell 脚本程序。

  - 通过给内核添加 “`break=init`" 等启动参数，你可以中断这部分启动流程以获取 root shell。更多中断条件请参见 ”`/init`“ 脚本。这个 shell 环境已足够成熟，你可通过它很好地检查机器的硬件。

  - 迷你 Debian 系统中可用的命令是精简过的，且主要由一个称为 busybox(1) 的 GNU 工具提供。

- 如果 initramfs 是由 `dracut` 创建，则 "`/init`" 程序是一个二进制 `systemd` 程序。

  - 迷你 Debian 系统中可用的命令是一个精简过的 systemd(1) 环境。

| 小心
当在一个只读的根文件系统上时，使用 `mount` 命令需要添加 `-n` 选项。

### 3.1.4. 第四阶段：常规 Debian 系统

常规 Debian 系统是启动流程的第四阶段，由迷你 Debian 系统启动。迷你 Debian 系统的内核在此环境下继续运行。根文件系统将由内存切换到物理存储设备上。

init 程序是系统执行的第一个程序（PID=1），它启动其它各种程序以完成主引导流程。init 程序的默认路径是 ”`/usr/sbin/init`“，但可通过内核启动参数修改，例如 ”`init=/path/to/init_program`"。

在 Debian 8 jessie（2015 年发布）版本后，"`/usr/sbin/init`" 是一个到 "`/lib/systemd/systemd`" 的符号链接。

| 提示
你的系统中实际使用的 init 命令可以使用 “`ps --pid 1 -f`” 命令确认。

表 3.3. Debian 系统启动工具列表

软件包 | 流行度 | 大小 | 说明
--- | --- | --- | ---
`systemd` | V:919, I:979 | 11764 | 基于事件且支持并发的 init(8) 守护进程（可替代 `sysvinit`）
`cloud-init` | V:4.3, I:6.8 | 3240 | 云实例架构的初始化系统
`systemd-sysv` | V:909, I:980 | 68 | `systemd` 需用的用以代替 `sysvinit` 的手册页和符号链接
`init-system-helpers` | V:594, I:987 | 133 | 在 `sysvinit` 和 `systemd` 之间进行转换的帮助工具
`initscripts` | V:17, I:62 | 197 | 用于初始化和关闭系统的脚本
`sysvinit-core` | V:3.4, I:3.9 | 365 | 类 System V 的 init(8) 工具
`sysv-rc` | V:33, I:66 | 85 | 类 System V 的运行级别修改机制
`sysvinit-utils` | V:726, I:1000 | 100 | 类 System V 的实用工具（startpar(8)，bootlogd(8)，……）
`lsb-base` | V:227, I:332 | 12 | Linux 标准规范 3.2 版的 init 脚本功能
`insserv` | V:40, I:65 | 132 | 利用 LSB init.d 脚本依赖性来组织启动步骤的工具
`kexec-tools` | V:1.4, I:5.3 | 320 | 用于 kexec(8) 重启（热启动）的 kexec 工具
`systemd-bootchart` | V:0.16, I:0.55 | 131 | 启动流程性能分析器
`mingetty` | V:0.1, I:2.6 | 36 | 仅包含控制台的 getty(8)
`mgetty` | V:0.13, I:0.48 | 318 | 可智能调制解调的 getty(8) 替代品

| 提示
有关启动流程加速的最新信息，请参见 Debian 维基：启动流程加速词条。

## 3.2. 应急救援系统

| 警告
在没有一个应急救援系统的情况下，不要执行一个和启动过程相关的系统管理任务。

应急救援系统能够让我们执行有挑战性的任务，比如：

- 从引导管理器损坏的安装中启动系统

- 修复启动引导器损坏的安装

- 从损坏的无法启动的系统中提取数据

- 编辑文件系统、磁盘分区 和 涉及 root 文件系统的 LVM 卷

典型的，一个应急救援系统用一个 ISO 镜像文件提供，并写到一个可移动存储介质，比如：

- USB 闪存盘 准备作为 第 9.7.2 节 “直接写入硬盘”

- CD / DVD 准备作为 第 9.7.7 节 “直接写入文件到 CD/DVD-R/RW”

为了简化，下面提到的例子用 U 盘作为示例，但是 CD 或 DVD 也能够很好的使用。

| 提示
你可以按需改变一些 UEFI NVRAM 变量来启动在 可移动存储介质上的 任意引导管理器。

### 3.2.1. USB 上的 GRUB UEFI 应急救援系统

"USB 上的 GRUB UEFI 应急救援系统" 插入，打开系统电源，GRUB UEFI 应急救援系统的菜单就能够启动。

这个 " USB 上的 GRUB UEFI 应急救援系统" 是事先将 Super Grub2 Disk ISO 镜像写入到 U 盘 来准备。

在安装其它操作系统等启动管理器配置损坏的场景，可以这样修复：

- 启动 GRUB UEFI 应急救援系统，自动发现已安装的可启动系统。

- 从 GRUB 菜单启动已经安装的 Debian 系统。

- 在 Linux root shell 提示符：

      # dpkg-reconfigure grub-efi-amd64

| 注意
可启动的 GRUB 应急救援 ISO 镜像也能够通过下面的 "`info grub-mkrescue`" 来生成。它提供了一个命令行的 GRUB shell 提示符，但是不提供自动发现已经安装的可启动的系统。

### 3.2.2. USB 上的 Linux 即用救援系统

“Linux 即用应急救援系统 U 盘”插入，打开系统电源，能够启动 Linux 即用应急救援系统。

这个 "USB 上的 Linux 即用应急救援系统" 能够通过予先将一个基于 Debian 的 Linux 即用 ISO 镜像写入到一个 U 盘 来准备好。这里是一些这种 Linux 即用镜像的列子。

- Debian 即用镜像

- Kali Linux 即用镜像

- Grml 即用 Linux

这里是一些 Linux 即用应急管理系统的使用场景：

- 修复由于安装其它操作系统等原因导致损坏的引导管理器配置：

  - 启动 Linux 即用救援系统。

  - 挂载无法启动的 Debian 系统上包含 root 文件系统的分区到 “`/mnt`”。

  - 在 Linux root shell 提示符：

        # chroot /mnt; dpkg-reconfigure grub-efi-amd64

- 修复损坏的 `dpkg` 软件包：

  - 启动 Linux 即用救援系统。

  - 挂载已经安装有损坏 `dpkg` 软件包的 Debian 系统中，包含 root 文件系统的分区到 "`/mnt`"。

  - 在 Linux root shell 提示符：

        # dpkg --root /mnt -i /mnt/var/cache/apt/archives/dpkg_old_version_amd64.deb

- 执行通常被禁止的操作，比如在安装好的系统上进行文件系统操作（参见 第 9.6 节 “数据存储技巧”）。

| 警告
你的 Linux 即用系统的 GUI（图形用户界面）屏幕在不活动时，可以被锁屏。

| 提示

- 设置 你的密码，在你一开始使用 Linux 即用系统时，是一个好的注意。

- 你可以设置你的密码，例如在 Linux 虚拟控制台的用户 shell 提示符下用 "`sudo passwd user`"（参见 第 1.1.6 节 “虚拟控制台”）。

- 一些 Linux 即用系统可以设置默认的 "用户/密码": "Debian Live" = "user/live", "Kali Linux Live" = "kali/kali"

### 3.2.3. 从 GRUB 启动的 Linux 即用应急救援系统

Linux 即用应急救援系统能够从 GRUB 菜单条目启动。使用下面的方式来准备这个 GRUB 配置：

- 安装 `grml-rescueboot` 软件包

- 找到一个在它镜像里面有 "`/boot/grub/loopback.cfg`" 的 Linux 即用 ISO 镜像。

  - 在 第 3.2.2 节 “USB 上的 Linux 即用救援系统” 里面提到的 ISO 镜像，在它们的镜像里面有 "`/boot/grub/loopback.cfg`" 。

- 拷贝这些 Linux 即用 ISO 镜像到 "`/boot/grml/`" 目录。

- 更新 GRUB 菜单：

      # dpkg-reconfigure grub-efi-amd64

紧接着打开系统电源，GRUB 显示候选 Linux 即用应急救援系统的菜单。

## 3.3. Systemd

### 3.3.1. Systemd 初始化

当 Debian 系统启动，`/usr/sbin/init` 符号链接到的 `/usr/lib/systemd` 作为初始系统进程 (`PID=1`) 启动，该进程由 root (`UID=0`)所有。参见 systemd(1)。

`systemd` 初始化进程基于单元配置文件 (参见 systemd.unit(5)) 来并行派生进程，这些单元配置文件使用声明样式来书写，代替之前的类 SysV 的过程样式。这些单元配置文件从下面的一系列路径来加载 (参见 systemd-system.conf(5)) 。

派生的进程被放在一个单独的 Linux control groups，在单元后命名，它们属于一个私有的 systemd 层级结构(参见 cgroups 和 第 4.7.5 节 “Linux 安全特性”)。

系统模式单元从 systemd.unit(5)描述中的"System Unit Search Path" 加载。主要部分是按照下列优先权顺序：

- "`/etc/systemd/system/*`": 管理员创建的系统单元文件

- "`/run/systemd/system/*`": 运行时单元文件

- "`/lib/systemd/system/*`": 发行版软件包管理器安装的系统单元文件

他们的相互依赖关系通过"`Wants=`", "`Requires=`", "`Before=`", "`After=`", … 等指示来配置，(参见 systemd.unit(5) 里的 "MAPPING OF UNIT PROPERTIES TO THEIR INVERSES")。 资源控制也是被定义 (参见 systemd.resource-control(5)).

根据单元配置文件的后缀来区分它们的类型：

- *.service 描述由 `systemd` 控制和监管的进程.参见 systemd.service(5).

- *.device 描述在 sysfs(5) 里面作为 udev(7) 设备树展示的设备。参见 systemd.device(5).

- *.mount 描述由 `systemd` 控制和监管的文件系统挂载点。参见 systemd.mount(5).

- *.automount 描述由 `systemd` 控制和监管的文件系统自动挂载点。参见 systemd.automount(5).

- *.swap 描述由 `systemd` 控制和监管的 swap 文件或设备。参见 systemd.swap(5).

- *.path 描述被 `systemd` 监控的路径，用于基于路径的活动。参见 systemd.path(5).

- *.socket 描述被 `systemd` 控制和监管的套接字，用于基于套接字的活动。参见 systemd.socket(5).

- *.timer 描述被 `systemd` 控制和监管的计时器，用于基于时间的活动。参见 systemd.timer(5).

- *.slice 管理 cgroups(7) 的资源。参见 systemd.slice(5).

- *.scope 使用 `systemd` 的总线接口来程序化的创建，用以管理一系列系统进程。 参见 systemd.scope(5).

- *.target 把其它单元配置文件分组，在启动的时候，来创建同步点。参见systemd.target(5).

系统启动时（即，init），`systemd` 进程会尝试启动"`/lib/systemd/system/default.target`（通常是到"`graphical.target`"的符号链接）。首先，一些特殊的 target 单元（参见 systemd.special(7)），比如 "`local-fs.target`"、"`swap.target`"和"`cryptsetup.target`"会被引入以挂载文件系统。之后，其它 target 单元也会根据单元依赖关系而被引入。详细情况，请阅读 bootup(7)。

`systemd` 提供向后兼容的功能。在 "`/etc/init.d/rc[0123456S].d/[KS]name`" 里面的 SysV 风格的启动脚本仍然会被分析；telinit(8) 会被转换为 systemd 的单元活动请求。

| 小心
模拟的运行级别 2 到 4 全部被符号链接到了相同的“`multi-user.target`”。

### 3.3.2. Systemd 登录

当一个用户通过 gdm3(8)、sshd(8)等登录到 Debian 系统,`/lib/systemd/system --user` 作为用户服务管理器进程启动，并由相应的用户所有。参见 systemd(1)。

`systemd` 初始化进程基于单元配置文件 (参见 systemd.unit(5)) 来并行派生进程，这些单元配置文件使用声明样式来书写，代替之前的类 SysV 的过程样式。这些单元配置文件从下面的一系列路径来加载 (参见 systemd-system.conf(5)) 。

用户模式单元从 systemd.unit(5)描述中的"User Unit Search Path" 加载。主要部分是按照下列优先权顺序：

- "`~/.config/systemd/user/*`": 用户配置单元文件

- "`/etc/systemd/user/*`": 管理员创建的用户单元文件

- "`/run/systemd/user/*`": 用户运行时单元文件

- "`/lib/systemd/user/*`": 发行版软件包管理器安装的用户单元文件

这些是和 第 3.3.1 节 “Systemd 初始化” 用同样的方式管理。

## 3.4. 内核消息

在控制台上显示的内核错误信息，能够通过设置他们的阈值水平来配置。

    # dmesg -n3

表 3.4. 内核错误级别表

错误级别值 | 错误级别名称 | 说明
--- | --- | ---
0 | KERN_EMERG | 系统不可用
1 | KERN_ALERT | 行为必须被立即采取
2 | KERN_CRIT | 危险条件
3 | KERN_ERR | 错误条件
4 | KERN_WARNING | 警告条件
5 | KERN_NOTICE | 普通但重要的条件
6 | KERN_INFO | 信息提示
7 | KERN_DEBUG | debug 级别的信息

## 3.5. 系统消息

在 `systemd` 下, 内核和系统的信息都通过日志服务 `systemd-journald.service` (又名 `journald`)来记录，放在"`/var/log/journal`"下的不变的二进制数据，或放在"`/run/log/journal/`"下的变化的二进制数据.这些二进制日志数据，可以通过 journalctl(1) 命令来访问。例如，你可以显示从最后一次启动以来的日志，按如下所示：

    $ journalctl -b

表 3.5. 典型的 `journalctl` 命令片段列表

操作 | 命令片段
--- | ---
查看从最后一次启动开始的系统服务和内核日志 | "`journalctl -b --system`"
查看从最后一次启动开始的当前用户的服务日志 | "`journalctl -b --user`"
查看从最后一次启动开始的 "`$unit`" 工作日志 | "`journalctl -b -u $unit`"
查看从最后一次启动开始的 "`$unit`"的工作日志 ("`tail -f`" 式样) | "`journalctl -b -u $unit -f`"

在 `systemd` 下，系统日志工具 rsyslogd(8) 可以被卸载。如果安装了它，它会改变它的行为来读取易失性二进制日志数据（代替在 systemd 之前默认的 "`/dev/log`"）并创建传统的永久性 ASCII 系统日志数据。"`/etc/default/rsyslog`" 和 "`/etc/rsyslog.conf`" 能够自定义日志文件和屏幕显示。参见 rsyslogd(8) 和 rsyslog.conf(5)，也可以参见第 9.3.2 节 “日志分析”。

## 3.6. 系统管理

`systemd` 不仅仅提供系统初始化，还用 systemctl(1) 命令提供通用的系统管理操作。

表 3.6. 典型的 `systemctl` 命令片段列表

操作 | 命令片段
--- | ---
列出所有存在的单元类型 | "`systemctl list-units --type=help`"
列出内存中所有 target 单元 | "`systemctl list-units --type=target`"
列出内存中所有 service 单元 | "`systemctl list-units --type=service`"
列出内存中所有 device 单元 | "`systemctl list-units --type=device`"
列出内存中所有 mount 单元 | "`systemctl list-units --type=mount`"
列出内存中所有 socket 单元 | "`systemctl list-sockets`"
列出内存中所有 timer 单元 | "`systemctl list-timers`"
启动 "`$unit`" | "`systemctl start $unit`"
停止 "`$unit`" | "`systemctl stop $unit`"
重新加载服务相关的配置 | "`systemctl reload $unit`"
停止和启动所有 "`$unit`" | "`systemctl restart $unit`"
启动 "`$unit`" 并停止所有其它的 | "`systemctl isolate $unit`"
转换到 "`图形`" (图形界面系统) | "`systemctl isolate graphical`"
转换到 "`多用户`" (命令行系统) | "`systemctl isolate multi-user`"
转换到 "`应急模式`" (单用户命令行系统) | "`systemctl isolate rescue`"
向"`$unit`"发送杀死信号 | "`systemctl kill $unit`"
检查"`$unit`"服务是否是活动的 | "`systemctl is-active $unit`"
检查"`$unit`"服务是否是失败的 | "`systemctl is-failed $unit`"
检查"`$unit|$PID|device`"的状态 | "`systemctl status $unit|$PID|$device`"
显示"`$unit|$job`"的属性 | "`systemctl show $unit|$job`"
重设失败的"`$unit`" | "`systemctl reset-failed $unit"`
列出所有单元服务的依赖性 | "`systemctl list-dependencies --all`"
列出安装在系统上的单元文件 | "`systemctl list-unit-files`"
启用 "`$unit`" (增加符号链接) | "`systemctl enable $unit`"
禁用 "`$unit`" (删除符号链接) | "`systemctl disable $unit`"
取消遮掩 "`$unit`" (删除到 "`/dev/null`" 的符号链接) | "`systemctl unmask $unit`"
遮掩 "`$unit`" (增加到 "`/dev/null`" 的符号链接) | "`systemctl mask $unit`"
获取默认的 target 设置 | "`systemctl get-default`"
设置默认 target 为"`graphical`" (图形系统) | "`systemctl set-default graphical`"
设置默认的 target 为"`multi-user`" (命令行系统) | "`systemctl set-default multi-user`"
显示工作环境变量 | "`systemctl show-environment`"
设置环境变量 "`variable`" 的值为 "`value`" | "`systemctl set-environment variable=value`"
取消环境变量 "`variable`" 的设置 | "`systemctl unset-environment variable`"
重新加载所有单元文件和后台守护进程（daemon） | "`systemctl daemon-reload`"
关闭系统 | "`systemctl poweroff`"
关闭和重启系统 | "`systemctl reboot`"
挂起系统 | "`systemctl suspend`"
休眠系统 | "`systemctl hibernate`"

这里, 上面例子中的"`$unit`"，可以是一个单元名（后缀`.service` 和 `.target` 是可选的)，或者，在很多情况下，也可以是匹配的多个单元 (shell 式样的全局通配符"`*`", "`?`", "`[]`"，通过使用 fnmatch(3) ，来匹配目前在内存中的所有单元的基本名称).

上面列子的系统状态改变命令，通常是通过"`sudo`"来处理，用以获得需要的系统管理权限。

"`systemctl status $unit|$PID|$device`" 的输出使用有颜色的点("●")来概述单元状态，让人看一眼就知道。

- 白色的 "●" 表示一个 "不活动"或"变为不活动中"的状态。

- 红色的 "●"表示“失败”或者“错误”状态。

- 绿色"●"表示“活动”、“重新加载中”或“激活中”状态。

## 3.7. 其它系统监控

这里是 `systemd` 下其它零星的监控命令列表。请阅读包括 cgroups(7) 在内的相关的 man 手册页。

表 3.7. `systemd` 下其它零星监控命令列表

操作 | 命令片段
--- | ---
显示每一个初始化步骤所消耗的时间 | "`systemd-analyze time`"
列出所有单元的初始化时间 | "`systemd-analyze blame`"
加载"`$unit`"文件并检测错误 | "`systemd-analyze verify $unit`"
简洁的显示用户调用会话的运行时状态信息 | "`loginctl user-status`"
简洁的显示调用会话的运行时状态信息 | "`loginctl session-status`"
跟踪 cgroups 的启动过程 | "`systemd-cgls`"
跟踪 cgroups 的启动过程 | "`ps xawf -eo pid,user,cgroup,args`"
跟踪 cgroups 的启动过程 | 读取 "`/sys/fs/cgroup/`" 下的 sysfs

## 3.8. 系统配置

### 3.8.1. 主机名

内核维护系统主机名。在启动的时候，通过 `systemd-hostnamed.service` 启动的系统单位设置系统的主机名，此主机名保存在 "`/etc/hostname`"。这个文件应该只包含系统主机名，而不是全称域名。

不带参数运行 hostname(1) 命令可以打印出当前的主机名。

### 3.8.2. 文件系统

硬盘和网络文件系统的挂载选项可以在 "`/etc/fstab`" 中设置，参见 fstab(5) 和 第 9.6.7 节 “通过挂载选项优化文件系统”。

加密文件系统的配置设置在“`/etc/crypttab`”中。参见 crypttab(5)

软 RAID 的配置 mdadm(8) 设置在 "`/etc/mdadm/mdadm.conf`". 参见 mdadm.conf(5).

| 警告
每次启动的时候，在挂载了所有文件系统以后，"`/tmp`", "`/var/lock`", 和 "`/var/run`" 中的临时文件会被清空。

### 3.8.3. 网络接口初始化

对于使用 `systemd` 的现代 Debian 桌面系统，网络接口通常由两个服务进行初始化：`lo` 接口通常在“`networking.service`”处理，而其它接口则由“`NetworkManager.service`”处理。

参见 第 5 章 网络设置 来获取怎样来配置它们的信息。

### 3.8.4. 云系统初始化

云系统实例可以由 "Debian Official Cloud Images" 或类似的镜像启动。对于这样的系统实例，主机名、文件系统、网络、语言环境、SSH 密钥、用户和组等个性化信息，可以使用 `cloud-init` 和 `netplan.io` 软件包提供的功能来配置，利用多个数据源，放在原始系统镜像里面的文件和在启动过程中提供的外部数据。这些软件包使用 YAML 数据来声明系统配置。

更多信息参见 "Cloud Computing with Debian and its descendants", "Cloud-init documentation" 和 第 5.4 节 “现代云网络配置”。

### 3.8.5. 调整 sshd 服务的个性化例子

使用默认安装，通过 `systemd` 启动的过程中，在 `network.target` 启动后，很多网络服务 (参见 第 6 章 网络应用)作为后台守护进程（daemon）启动。 "`sshd`" 也不列外。让我们修改为按需启动"`sshd`" 作为一个定制化的例子。

首先，禁用系统安装的服务单元。

     $ sudo systemctl stop sshd.service
     $ sudo systemctl mask sshd.service

传统 Unix 服务的按需套接字激活（on-demand socket activation）系统由 `inetd` (或 `xinetd`)超级服务来提供。在 `systemd` 下, 相同功能能够通过增加*.socket 和 *.service 单元配置文件来启用。

`sshd.socket` 用来定义一个监听的套接字

    [Unit]
    Description=SSH Socket for Per-Connection Servers

    [Socket]
    ListenStream=22
    Accept=yes

    [Install]
    WantedBy=sockets.target

`sshd@.service` 作为 `sshd.socket` 匹配的服务文件

    [Unit]
    Description=SSH Per-Connection Server

    [Service]
    ExecStart=-/usr/sbin/sshd -i
    StandardInput=socket

然后重新加载。

     $ sudo systemctl daemon-reload

## 3.9. udev 系统

从 Linux 内核 2.6 版开始，udev 系统 提供了自动硬件发现和初始化机制。(参见 udev(7)).在内核发现每个设备的基础上，udev 系统使用从 sysfs 文件系统 (参见 第 1.2.12 节 “procfs 和 sysfs”)的信息启动一个用户进程，使用 modprobe(8) 程序 (参见 第 3.10 节 “内核模块初始化”)加载支持它所要求的内核模块, 创建相应的设备节点。

| 提示
如果由于某些理由，"`/lib/modules/kernel-version/modules.dep`"没有被 depmod(8) 正常生成，模块可能不会被 udev 系统按期望的方式加载。执行"`depmod -a`" 来修复它。 "`/etc/fstab`"里面的挂载规则,设备节点不必需是静态的。你能够使用 UUID 来挂载设备，来代替"`/dev/sda`"之类的设备名. 参见 第 9.6.3 节 “使用 UUID 访问分区”.

由于 udev 系统是一个正在变化的事物，我在其它文档进行了详细描述，在这里只提供了最少的信息。

| 警告
不要尝试用 udev 规则里面的 `RUN`（在 udev(7) 提到）长期运行程序，比如说备份脚本。请创建一个适当的 systemd.service(5) 文件并激活它来替代。参见 第 10.2.3.2 节 “挂载事件触发的备份”。

## 3.10. 内核模块初始化

通过 modprobe(8) 程序添加和删除内核模块，使我们能够从用户进程来配置正在运行的 Linux 内核。udev 系统(参见 第 3.9 节 “udev 系统”)自动化它的调用来帮助内核模块初始化。

下面的非硬件模块和特殊的硬件驱动模块，需要被预先加载，把它们在"`/etc/modules`"文件里列出 (参见 modules(5)).

- TUN/TAP 模块提供虚拟的 Point-to-Point 网络设备 (TUN) 和虚拟的 Ethernet 以太网网络设备 (TAP),

- netfilter 模块提供 netfilter 防火墙能力(iptables(8), 第 5.7 节 “Netfilter 网络过滤框架”),

- watchdog timer 驱动模块。

modprobe(8) 程序的配置文件是按 modprobe.conf(5)的说明放在"`/etc/modprobes.d/`" 目录下，(如果你想避免自动加载某些内核模块，考虑把它们作为黑名单放在"`/etc/modprobes.d/blacklist`" 文件里.)

"`/lib/modules/version/modules.dep`" 文件由 depmod(8) 程序生成，它描述了 modprobe(8) 程序使用的模块依赖性.

| 注意
如果你在启动时出现模块加载问题，或者 modprobe(8)时出现模块加载问题, "`depmod -a`" 可以通过重构"`modules.dep`"来解决这些问题。

modinfo(8) 程序显示 Linux 内核模块信息。

lsmod(8) 程序以好看的格式展示"`/proc/modules`"的内容,显示当前内核加载了哪些模块。

| 提示
你能够精确识别你系统上的硬件。 参见第 9.5.3 节 “硬件识别”. 你可以在启动时配置硬件来激活期望的硬件特征。参见 第 9.5.4 节 “硬件配置”. 你可以重新编译内核来增加你的特殊设备的支持。参见 第 9.10 节 “内核”.

第 2 章 Debian 软件包管理 |  | 第 4 章 认证和访问控制