systemd 是 Linux 的系统和服务管理器。作为系统启动的第一个进程,初始化系统并且管理其他用户服务。
概述
systemd 提供了一套完整的系统启动和管理的解决方案,其中的 d
为守护进程(daemon)的缩写,即系统的守护进程。
查看 systemd 简介
1 | man systemd |
systemd 作为系统的第一个进程,PID = 1,其余所有进程都是 systemd 的子进程。
1 | root@ubuntu:~# pstree -p |
Unit
systemd 可以管理所有系统资源,unit 为 systemd 的基本管理单元,用于描述系统服务、资源、设备和其他对象,根据不同资源分为了 12 种 Unit。
- 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:定时器
可通过 man systemd.service
查看各种 Unit 的简介。
配置
每个 Unit 需设置对应类型的配置文件。Unit 配置分为三个区块:Unit、Service\Timer\Socket、Install
Unit 区块
Unit 的元数据,定义了 unit 的基本信息、依赖关系和启动顺序。
1 | [Unit] |
Description
:简短描述Documentation
:文档地址,可以是手册页或 URL
依赖关系
例如:unit-A Requires/BindsTo/Wants/PartOf=unit-B.service
Requires
:- 强依赖
- unit-A 启动时,自动启动被依赖 unit-B,如果被依赖 unit-B 启动失败,则该 unit-A 也会启动失败
BindsTo
:- 强依赖
- unit-A 启动时,自动启动被依赖 unit-B,如果被依赖 unit-B 启动失败,则该 unit-A 也会启动失败
- unit-B 停止或者失败时,依赖 unit-B 的 unit-A 也会自动停止
Wants
:- 弱依赖
- unit-A 启动时,自动启动被依赖 unit-B,但被依赖 unit-B 启动失败,也不会一些该 unit-A 启动
特性 | Requires |
BindsTo |
Wants |
---|---|---|---|
启动行为 | 必须成功启动被依赖的 unit | 必须成功启动被依赖的 unit | 建议启动被依赖的 unit |
停止行为 | 不会自动停止依赖它的 unit | 自动停止依赖它的 unit | 不会自动停止依赖它的 unit |
依赖关系类型 | 单向强依赖 | 双向强依赖 | 弱依赖 |
适用场景 | 功能密切相关但生命周期不必一致的服务 | 需要同时运行并在同一生命周期内运行的服务 | 可能相互关联但非必需的服务 |
Conflicts
:互斥关系,unit-A 和 unit-B 不能同时运行,当 unit-A 启动时,会自动停止 unit-B,反之亦然PartOf
:unit-A 是目标服务 unit-B 的一部分,当目标服务 unit-B 停止或被重启时,作为其一部分的 unit-A 也会停止或重启
启动顺序
例如:unit-A Before/After=unit-B.service
Before
:当前 unit A 应该在指定的 unit B 之前启动(A -> B)After
:当前 unit A 应该在指定的 unit B 之后启动(B -> A)
顺序配置Before
、After
只是设置一起启动时的顺序,A 服务启动时并不会自动启动 B 服务,如需设置自启动,需搭配依赖关系使用。
其他关系
Condition...
:检查服务启动时的条件,如果条件不满足,服务将不会被启动,但不会导致启动失败ConditionPathExists=
:检查指定的文件或路径是否存在。如果路径存在,服务将启动ConditionPathExistsGlob=
:使用通配符检查路径是否匹配ConditionPathIsDirectory=
:检查指定路径是否是一个目录ConditionPathIsSymbolicLink=
:检查指定路径是否是一个符号链接ConditionKernelCommandLine=
:检查内核命令行参数是否包含指定的字符串ConditionVirtualization=
:检查当前系统是否运行在虚拟化环境中(如 KVM、LXC 等)ConditionHost=
:检查主机名是否与指定值匹配
Assert...
:对服务启动的条件进行强制检查。与Condition
不同,如果指定的条件未满足,服务将不会启动,且系统会报告错误AssertPathExists=
:检查指定路径是否存在AssertPathIsDirectory=
:检查指定路径是否是目录AssertPathIsSymbolicLink=
:检查指定路径是否是符号链接AssertKernelCommandLine=
:检查内核命令行参数AssertVirtualization=
:检查当前系统是否在虚拟化环境中
类型区块
Service
systemd.service
是用于定义和管理系统服务的单位类型。
配置文件以 .service
结尾,主要用于描述如何启动、停止和管理服务。
.service
配置中,通过 [Service] 区块定义服务的启动和运行参数。
1 | [Service] |
启动类型
Type
:配置服务如何通知systemd服务启动完成simple
(默认值):systemd 调用完ExecStart
后即认为服务启动成功,即使ExecStart
运行失败,服务也启动成功notify
:启动时,服务通过sd_notify()
发送一个 “READY=1” 信号,systemd 收到这个信号后才认为服务启动成功,再启动之后的 unitdbus
:需设置BusName=
(如设置,自动为 dbus 类型),当 systemd 确认BusName=
的 dbus 存在后,则认为服务启动成功- 等等
启动命令
EnvironmentFile
:启动时会加载这个配置的环境变量文件ExecStartPre
:启动服务之前执行的命令如果
ExecStartPre
执行失败,则服务启动失败,不会执行ExecStart
如果希望
ExecStartPre
执行失败也能继续执行ExecStart
,需在ExecStartPre
加前缀-
1
ExecStartPre=-/usr/bin/check_dependencies
支持多个
ExecStartPre
,按顺序执行
ExecStart
(必选):启动服务执行的命令ExecStartPost
:启动服务成功之后执行的命令- 如果
Type
规定的启动没成功,则不会执行ExecStartPost
- 如果
终止类型
KillMode
:停止服务时如何处理进程control-group
(默认值):停止服务时,所有属于该服务 cgroup 的所有进程都会被杀死process
:停止服务时,只杀主进程,主进程产生的子进程不会被杀死mixed
:停止服务时,向主进程发送 SIGTERM 信号,接着向子进程发送 SIGKILL 信号none
:没有进程会被杀掉,只是执行服务的ExecStop
命令
杀进程过程:
- 向进程发送
KillSignal=
信号(默认为SIGTERM
)- 等待进程被杀死
- 若等候
TimeoutStopSec=
时间(默认 90s)后,进程仍然未被杀死,向进程发送FinalKillSignal=
信号(默认为SIGKILL
)强制杀死进程
终止命令
ExecStop
字段:停止服务时执行的命令ExecStopPost
字段:停止服务之后执行的命令
重启类型
有时候,服务需要保持运行状态,如有意外奔溃,能自动拉起,可通过下面配置设置自拉起
1 | Restart=always |
Restart
:重启机制,什么情况下会自动触发重启服务(systemctl stop/restart 触发的停止服务,不会被这里设置的重启机制拉起)- no(默认值):退出后不会重启
- always:所有情况触发自动重启
- on-success:只有正常退出时触发自动重启
- on-failure:异常退出时触发自动重启
- on-abnormal:只有被信号终止和超时,才会重启
- on-abort:只有在收到没有捕捉到的信号终止时,才会重启
- on-watchdog:超时退出,才会重启
退出原因 | no | always | on-success | on-failure | on-abnormal | on-abort | on-watchdog |
---|---|---|---|---|---|---|---|
systemctl stop | |||||||
正常退出 | restart | restart | |||||
退出码不为“0” | restart | restart | |||||
进程被强制杀死 | restart | restart | restart | restart | |||
systemd操作超时 | restart | restart | restart | ||||
看门狗超时 | restart | restart | restart | restart |
- 正常退出:退出码为”0”, 或者进程收到
SIGHUP
,SIGINT
,SIGTERM
,SIGPIPE
信号之一,并且退出码符合SuccessExitStatus=
的设置- 异常退出:包括退出码不为“0”、进程被强制杀死、systemd操作超时、看门狗超时
RestartSec
:配合Restart
使用,重新启动服务之前的睡眠时间,设置如异常退出后,等待多少秒再次启动,默认 100ms
1 | |----RestartSec------| |
StartLimitInterval
、StartLimitBurst
:重启限制次数,在StartLimitBurst=
时间内尝试重启超过StartLimitInterval=
次则不再重启,默认为 10s 内 5 次,如需无限制,则设置StartLimitInterval=0
重启命令
ExecReload
字段:重启服务时执行的命令
Install 区块
定义服务单元的安装和启用选项,指定如何将服务单元与目标(如启动目标或其他服务)关联。
1 | [Install] |
WantedBy
:定义服务应该被哪些目标“需要”,这意味着在这些目标启动时,该服务也会被自动启动示例说明服务所在 target 是 multi-user.target,这个设置很通用且重要
在 enable 这个服务后,在
/etc/systemd/system/multi-user.target.wants/
的指定目录中创建了一个指向/usr/lib/systemd/system/XXX.service
的符号链接1
2root@ubuntu:~# systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.相当于为
multi-user.target
添加了Wants=nginx
配置当系统启动时,
multi-user.target
启动,nginx.service
单元也会被启动
RequiredBy
:类似于WantedBy
,但表示更强的依赖关系,如果目标启动失败,相关服务也不会启动Alias
:当前 Unit 的别名Also
:当前 Unit 启用(enable)或禁用(disable)时,会被同时(enable)或禁用(disable)的其他 Unit
配置路径
配置文件存放在下面地址:
- 系统级目录:
/lib/systemd/system/
- Linux 系统提供的默认 unit 配置文件的存放位置
- 用户级目录:
~/.config/systemd/user/
- 用户级的 unit 配置文件,允许普通用户定义和管理自己的服务和任务。
- 本地配置目录:
/etc/systemd/system/
- 本地的 unit 配置文件,用户可以在这里创建或修改 unit 文件。
优先级顺序:
/etc/systemd/system/
(本地配置目录,最高优先级)/run/systemd/system/
(临时配置,通常在运行时创建)/lib/systemd/system/
(默认系统提供的配置)
优先级从高到低,如在高低优先级的目录下有同名 unit,则采用高优先级中的配置。
命令
systemd 由一组系统命令组成,用来控制系统的方方面面。
systemctl
参考链接:manpages、man systemctl
systemctl
是 systemd 的主命令,用于控制 systemd 系统与服务。
- 命令格式:
systemctl [OPTIONS...] COMMAND [UNIT...]
系统命令
1 | # 列出 systemd 所有单位 |
单 Unit 命令
1 | # 查看服务状态 |
journalctl
参考链接:manpages、man journalctl
journalctl
用来查看 systemd 日志,包括系统日志还有各 unit 日志。
- 服务:systemd-journald.service
- 命令格式:
journalctl [OPTIONS...] [MATCHES...]
1 | # 查看所有日志(默认情况下 ,只保存本次启动的日志) |
loginctl
参考链接:manpages、man loginctl
loginctl
命令用来控制 systemd 登录管理器(systemd-logind.service)。
- 服务:systemd-logind.service
- 命令格式:
loginctl [OPTIONS...] {COMMAND} [NAME...]
COMMAND 分为三种类型:用户、会话和席位
用户
用户是操作系统中进行交互和操作的实体。在Linux中,每个用户都有一个唯一的用户名和用户ID(UID)。用户可以是普通用户、超级用户(root)等,拥有不同的权限。
会话
会话是用户与系统之间的交互过程。当用户登录到Linux系统时,会创建一个会话。会话包含用户的环境设置、运行的程序、打开的文件等。一个用户可以同时拥有多个会话,例如在不同的终端或远程登录时。
席位
席位(TTY或终端)是用户与系统之间交互的接口。在Linux中,每个物理或虚拟终端都被称为一个席位。用户可以通过这些席位输入命令并接收输出。现代Linux系统通常支持多个席位,例如通过虚拟终端(tty)或图形界面(X Window System)。
用户命令
列出当前登录用户
list-users
1
2
3
4
5
6root@ubuntu:~# loginctl list-users
UID USER
0 root
1000 guoyi
2 users listed.显示用户状态
user-status [USER...]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26root@ubuntu:~# loginctl user-status root
root (0)
Since: Sat 2024-10-05 01:40:47 PDT; 9h ago
State: active
Sessions: 321 *304
Linger: no
Unit: user-0.slice
├─session-304.scope
│ ├─57001 sshd: root@pts/1
│ ├─57094 -bash
│ ├─58718 loginctl user-status root
│ └─58719 pager
├─session-321.scope
│ ├─58486 sshd: root@pts/2
│ └─58572 -bash
└─user@0.service
└─init.scope
├─57004 /lib/systemd/systemd --user
└─57005 (sd-pam)
Oct 05 01:40:48 ubuntu systemd[57004]: Condition check resulted in Sound System being sk>
Oct 05 01:40:48 ubuntu systemd[57004]: Listening on REST API socket for snapd user sessi>
Oct 05 01:40:48 ubuntu systemd[57004]: Listening on D-Bus User Message Bus Socket.
Oct 05 01:40:48 ubuntu systemd[57004]: Reached target Sockets.
Oct 05 01:40:48 ubuntu systemd[57004]: Reached target Basic System.
Oct 05 01:40:48 ubuntu systemd[57004]: Condition check resulted in Sound Service being s显示用户各属性
show-user [USER...]
,可以用--all
选项查看缺省空置,使用--property=
查看特定属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16root@ubuntu:~# loginctl show-user root
UID=0
GID=0
Name=root
Timestamp=Sat 2024-10-05 01:40:47 PDT
TimestampMonotonic=574471117888
RuntimePath=/run/user/0
Service=user@0.service
Slice=user-0.slice
Display=304
State=active
Sessions=321 304
IdleHint=no
IdleSinceHint=0
IdleSinceHintMonotonic=0
Linger=no等等
会话命令
列出当前所有会话
list-sessions
1
2
3
4
5
6
7root@ubuntu:~# loginctl list-sessions
SESSION UID USER SEAT TTY
2 1000 guoyi seat0 tty2
304 0 root
321 0 root
3 sessions listed.显示简洁的会话状态信息
session-status [ID...]
1
2
3
4
5
6
7
8
9
10
11
12
13
14root@ubuntu:~# loginctl session-status 304
304 - root (0)
Since: Sat 2024-10-05 01:40:47 PDT; 9h ago
Leader: 57001 (sshd)
Remote: 192.168.45.1
Service: sshd; type tty; class user
State: active
Unit: session-304.scope
├─57001 sshd: root@pts/1
├─57094 -bash
├─58744 loginctl session-status 304
└─58745 pager
Oct 05 01:40:48 ubuntu systemd[1]: Started Session 304 of user root.显示会话的各项属性值
show-session [ID...]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21root@ubuntu:~# loginctl show-session 321
Id=321
User=0
Name=root
Timestamp=Sat 2024-10-05 10:31:06 PDT
TimestampMonotonic=606290337700
VTNr=0
Remote=yes
RemoteHost=192.168.45.1
Service=sshd
Scope=session-321.scope
Leader=58486
Audit=321
Type=tty
Class=user
Active=yes
State=active
IdleHint=no
IdleSinceHint=0
IdleSinceHintMonotonic=0
LockedHint=no等等
席位命令
显示所有可用席位
list-seats
1
2
3
4
5root@ubuntu:~# loginctl list-seats
SEAT
seat0
1 seats listed.等等