1. Preface
历史上,Linux 的启动一直采用init进程。
1 | $ sudo /etc/init.d/apache2 start |
这种方法有两个缺点:
- 启动时间长
- 启动脚本复杂
init 进程是串行启动,只有前一个进程启动完,才会启动下一个进程。
init 进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。
2. Systemd (daemon)
Systemd 就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。
根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。
Linux OS Daemon management tool Systemd 。它是 OS 的一部分,直接与 kernel 交互,性能棒,功能强。我们完全可以将程序交给 Systemd ,让系统统一管理,成为真正意义上的系统服务。
1 | 查看 Systemd 的版本。 |
3. System management
Systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。
4. Unit
Systemd 可以管理所有系统资源。不同的资源统称为 Unit(单位)。
4.1 Unit definition
Unit 一共分成12种:
- Service unit:系统服务
- Target unit:多个 Unit 构成的一个组
- Device Unit:硬件设备
- Mount Unit:文件系统的挂载点
- Automount Unit:自动挂载点
- Path Unit:文件或路径
- Scope Unit:不是由 Systemd 启动的外部进程
- Slice Unit:进程组
- Snapshot Unit:Systemd 快照,可以切回某个快照
- Socket Unit:进程间通信的 socket
- Swap Unit:swap 文件
- Timer Unit:定时器
systemctl list-units
命令可以查看当前系统的所有 Unit
1 | # 列出正在运行的 Unit |
4.2 Unit status
1 | # 显示系统状态 |
除了 status 命令, systemctl 还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。
4.3 Unit management
对于用户来说,最常用的是下面这些命令,用于 start 和 stop Unit(主要是 service)
1 | # 立即启动一个服务 |
4.4 Unit dependencies
Unit 之间存在依赖关系:A 依赖于 B,就意味着 Systemd 在启动 A 的时候,同时会去启动 B。
systemctl list-dependencies命令列出一个 Unit 的所有依赖
1 | $ systemctl list-dependencies nginx.service |
上面命令的输出结果之中,有些依赖是 Target 类型(详见下文),默认不会展开显示。如果要展开 Target,就需要使用–all参数
1 | $ systemctl list-dependencies --all nginx.service |
5. Unit config
5.1 config overview
每一个 Unit 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit 。
Systemd 默认从目录 /etc/systemd/system/
读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/
,真正的配置文件存放在那个目录。
systemctl enable 命令用于在上面两个目录之间,建立符号链接关系。
1 | $ sudo systemctl enable clamd@scan.service |
配置文件的后缀名,就是该 Unit 的种类,比如 sshd.socket。如果省略,Systemd 默认后缀名为.service,所以 sshd 会被理解成 sshd.service。
5.2 config status
1 | # 列出所有配置文件 |
这个命令会输出一个列表
1 | $ systemctl list-unit-files |
从配置文件的状态无法看出,该 Unit 是否正在运行。这必须执行前面提到的 systemctl status 命令
1 | $ systemctl status bluetooth.service |
一旦修改配置文件,就要让 SystemD 重新加载配置文件,然后重新启动,否则修改不会生效。
1 | $ sudo systemctl daemon-reload |
5.3 config format
systemctl cat service_name
命令可以查看配置文件的内容
1 | $ systemctl cat atd.service |
注意,键值对的等号两侧不能有空格
5.4 config block
[Unit]
区块是配置文件的第一个区块,用来定义 Unit 的元数据及配置与其他 Unit 的关系。它的主要字段如下。
field | desc |
---|---|
Description | 简短描述 |
Documentation | 文档地址 |
Requires | 当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败 |
… | … |
Assert… | 当前 Unit 运行必须满足的条件,否则会报启动失败 |
[Install]
区块是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下。
field | desc |
---|---|
WantedBy | 它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中. |
… | … |
Alias | 当前 Unit 可用于启动的别名 |
Also | 当前 Unit 激活(enable)时,会被同时激活的其他 Unit |
[Service]
区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下。
field | desc |
---|---|
Type | 定义启动时的进程行为。它有以下几种值。 |
… | … |
Environment | 指定环境变量 |
Unit 配置文件的完整字段清单,请参考官方文档.
6. Target (units)
启动计算机的时候,需要启动大量的 Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。Systemd 的解决方案就是 Target。 简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。
1 | # 查看当前系统的所有 Target |
Target 与 传统 RunLevel 的对应关系如下:
1 | Traditional runlevel New target name Symbolically linked to... |
7. Log management
Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用 journalctl 一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是 /etc/systemd/journald.conf
。
1 | # 查看某个 Unit 的日志 |
它与init
进程的主要差别如下
1 | (1)默认的 RunLevel(在/etc/inittab文件设置)现在被默认的 Target 取代,位置是/etc/systemd/system/default.target,通常符号链接到graphical.target(图形界面)或者multi-user.target(多用户命令行)。 |
Reference
- 阮一峰: 计算机是如何启动的? ✔️
- 阮一峰: Linux 的启动流程 ✔️
- 阮一峰: Linux daemon (守护进程)的启动方法 ✔️
- 阮一峰: Systemd 入门教程:命令篇 ✔️
- 阮一峰: Kiss (Keep it sample stupid) Unix哲学 ✔️
sudo
Checking if Disqus is accessible...