Systemd 教程

Systemd 是一系列工具的集合,其作用也远远不仅是启动操作系统,它还接管了后台服务、结束、状态查询,以及日志归档、设备管理、电源管理、定时任务等许多职责,并支持通过特定事件(如插入特定 USB 设备)和特定端口数据触发的 On-demand(按需)任务。

Unit 文件

Systemd 可以管理所有系统资源,不同的资源统称为 Unit(单位)。Systemd 通过不同的文件后缀来区分这些配置文件。

Systemd Unit 文件类型

Unit 是 Systemd 管理系统资源的基本单元,可以认为每个系统资源就是一个 Unit,并使用一个 Unit 文件定义。在 Unit 文件中需要包含相应服务的描述、属性以及需要运行的命令 Target 是 Systemd 中用于指定系统资源启动组的方式,相当于 SysV-init 中的运行级别。 简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于”状态点”,启动某个 Target 就好比启动到某种状态。

命令 说明
.automount 用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务
.device 对于 /dev 目录下的设备,主要用于定义设备之间的依赖关系
.mount 定义系统结构层次中的一个挂载点,可以替代过去的 /etc/fstab 配置文件
.path 用于监控指定目录或文件的变化,并触发其它 Unit 运行
.scope 这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息
.service 封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件
.slice 用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件
.snapshot 用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照
.socket 监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动
.swap 定义一个用户做虚拟内存的交换分区
.target 用于对 Unit 文件进行逻辑分组,引导其它 Unit 的执行。它替代了 SysV-init 运行级别的作用,并提供更灵活的基于特定设备事件的启动方式
.timer 用于配置在特定时间触发的任务,替代了 Crontab 的功能

systemd 目录

命令 说明
/etc/systemd/system 系统或用户自定义的配置文件
/run/systemd/system 软件运行时生成的配置文件
/usr/lib/systemd/system 系统或第三方软件安装时添加的配置文件。
/lib/systemd/system ubuntu 系统或第三方软件安装时添加的配置文件。真正文件存放目录,其他是链接。

Unit 文件配置

[Unit]
Description=Hello World
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox1
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox1 busybox /bin/ sh -c "while true; do echo Hello World; sleep 1; done"
ExecStop="/usr/bin/docker stop busybox1"
ExecStopPost="/usr/bin/docker rm busybox1"
[Install]
WantedBy=multi-user.target
命令 说明
Unit 和 Install 段 所有 Unit 文件通用,用于配置服务(或其它系统资源)的描述、依赖和随系统启动的方式
Service 段 服务(Service)类型的 Unit 文件(后缀为 .service)特有的,用于定义服务的具体管理和操作方法

Unit 文件 unit 段

命令 说明
Description 描述这个 Unit 文件的信息
Documentation 指定服务的文档,可以是一个或多个文档的 URL 路径
Requires 依赖的其它 Unit 列表,列在其中的 Unit 模板会在这个服务启动时的同时被启动。并且,如果其中任意一个服务启动失败,这个服务也会被终止
Wants 与 Requires 相似,但只是在被配置的这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
After 与 Requires 相似,但是在后面列出的所有模块全部启动完成以后,才会启动当前的服务
Before 与 After 相反,在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
Binds To 与 Requires 相似,失败时失败,成功时成功,但是在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
Part Of 一个 Bind To 作用的子集,仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
OnFailure 当这个模板启动失败时,就会自动启动列出的每个模块
Conflicts 与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然

Unit 文件 install 段

这部分配置的目标模块通常是特定运行目标的 .target 文件,用来使得服务在系统启动时自动运行。这个区段可以包含三种启动约束

命令 说明
WantedBy 和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 + .wants 后缀构成的子目录中,如 “/etc/systemd/system/multi-user.target.wants/“
RequiredBy 和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入 /etc/systemd/system 目录下面以 + .required 后缀构成的子目录中
Also 当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit
Alias 当前 Unit 可用于启动的别名

Unit 文件 Service 段

用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段分为服务生命周期和服务上下文配置两个方面。

命令 说明
Type=simple 默认值,执行ExecStart指定的命令,启动主进程。还有forking(fork方式), oneshot(一次性), dbus(通过D-Bus启动), notify(当前启动完毕后), idle(其他任务执行完毕后)。
RemainAfterExit 值为 true 或 false(默认)。当配置为 true 时,Systemd 只会负责启动服务进程,之后即便服务进程退出了,Systemd 也仍然会认为这个服务还在运行中。
ExecStart 启动当前服务的命令
ExecStartPre 启动当前服务之前执行的命令
ExecStartPos 启动当前服务之后执行的命令
ExecReload 重启当前服务时执行的命令
ExecStop 停止当前服务时执行的命令
ExecStopPost 停止当其服务之后执行的命令
RestartSec 自动重启当前服务间隔的秒数
Restart 定义何种情况 Systemd 会自动重启当前服务,可能的值包括 always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutStartSec 启动服务时等待的秒数,这一配置对于使用 Docker 容器而言显得尤为重要,因其第一次运行时可能需要下载镜像,严重延时会容易被 Systemd 误判为启动失败杀死。通常,对于这种服务,将此值指定为 0,从而关闭超时检测
TimeoutStopSec 停止服务时的等待秒数,如果超过这个时间仍然没有停止,Systemd 会使用 SIGKILL 信号强行杀死服务的进程

Unit 文件占位符

在 Unit 文件中,有时会需要使用到一些与运行环境有关的信息,例如节点 ID、运行服务的用户等。这些信息可以使用占位符来表示,然后在实际运行被动态地替换实际的值。

命令 说明
%n 完整的 Unit 文件名字,包括 .service 后缀名
%p Unit 模板文件名中 @ 符号之前的部分,不包括 @ 符号
%i Unit 模板文件名中 @ 符号之后的部分,不包括 @ 符号和 .service 后缀名
%t 存放系统运行文件的目录,通常是 “run”
%u 运行服务的用户,如果 Unit 文件中没有指定,则默认为 root
%U 运行服务的用户 ID
%h 运行服务的用户 Home 目录,即 %{HOME} 环境变量的值
%s 运行服务的用户默认 Shell 类型,即 %{SHELL} 环境变量的值
%m 实际运行节点的 Machine ID,对于运行位置每个的服务比较有用
%b Boot ID,这是一个随机数,每个节点各不相同,并且每次节点重启时都会改变
%H 实际运行节点的主机名
%v 内核版本,即 “uname -r” 命令输出的内容
%% 在 Unit 模板文件中表示一个普通的百分号

Systemclt 命令

命令 说明
systemctl enable 在 /etc/systemd/system/ 建立服务的符号链接,指向 /usr/lib/systemd/system/ 中
systemctl start 依次启动定义在 Unit 文件中的 ExecStartPre、ExecStart 和 ExecStartPost 命令
systemctl start 依次启动定义在 Unit 文件中的 ExecStartPre、ExecStart 和 ExecStartPost 命令
systemctl stop 依次停止定义在 Unit 文件中的 ExecStopPre、ExecStop 和 ExecStopPost 命令
systemctl restart 重启服务
systemctl kill 立即杀死服务
systemctl enable 除了激活服务以外,也可以置服务为开机启动
systemctl disable 取消服务的开机启动
systemctl daemon-reload Systemd 会将 Unit 文件的内容写到缓存中,因此当 Unit 文件被更新时,需要重新读取所有的 Unit 文件
systemctl reset-failed 移除标记为丢失的 Unit 文件。在删除 Unit 文件后,由于缓存的关系,即使通过 daemon-reload 更新了缓存,在 list-units 中依然会显示标记为 not-found 的 Unit。
systemctl list-units 列出正在运行的 Unit
systemctl list-units –all 列出所有Unit,包括没有找到配置文件的或者启动失败的
systemctl list-units –all –state=inactive 列出所有没有运行的 Unit
systemctl list-units –failed 列出所有加载失败的 Unit
systemctl list-units –type=service 列出所有正在运行的、类型为 service 的 Unit
systemctl cat *.service 查看 Unit 配置文件的内容
systemctl status 显示系统状态
systemctl status *.service 显示单个 Unit 的状态
systemctl -H root@rhel7.example.com status httpd.service 显示远程主机的某个 Unit 的状态
systemctl start *.service 立即启动一个服务
systemctl stop apache.service 立即停止一个服务
systemctl restart apache.service 重启一个服务
systemctl kill apache.service 杀死一个服务的所有子进程
systemctl reload apache.service 重新加载一个服务的配置文件
systemctl daemon-reload 重载所有修改过的配置文件
systemctl show httpd.service 显示某个 Unit 的所有底层参数
systemctl show -p CPUShares httpd.service 显示某个 Unit 的指定属性的值
systemctl set-property httpd.service CPUShares=500 设置某个 Unit 的指定属性
systemctl list-dependencies nginx.service 列出一个 Unit 的所有依赖,默认不会列出 target 类型
systemctl list-dependencies –all nginx.service 列出一个 Unit 的所有依赖,包括 target 类型