在我的计算机/lib/systemd/system
目录中,我看到一个文件multiuser.target
- 该文件包含:
[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
该行:Requires: basic.target
我认为这意味着“运行”文件basic.target
。
但在同一 /lib/systemd/system
目录中还有一个multi-user.target.wants/
子目录。它包含更多单元文件:
/lib/systemd/system $tree multi-user.target.wants/
multi-user.target.wants/
├── dbus.service -> ../dbus.service
├── getty.target -> ../getty.target
├── systemd-ask-password-wall.path -> ../systemd-ask-password-wall.path
├── systemd-logind.service -> ../systemd-logind.service
├── systemd-update-utmp-runlevel.service -> ../systemd-update-utmp-runlevel.service
└── systemd-user-sessions.service -> ../systemd-user-sessions.service
当默认启动目标时,运行这些单元中的哪一个,即文件:basic.target
或子目录中的所有单元?是以上所有的吗?如果是的话,顺序是什么?multi-user.wants.target
multi-user.target
答案1
Before
/After
和Wants
/ Requires
/之间有一个区别Requisite
:第一组表示定时的单位开始,后一组表示依赖关系。通常,两者之间没有什么区别,但有时很重要。阅读文档对于了解更多详细信息很有用,因为我遗漏了您不常看到的内容。
作为一个例子,我们假设您有一些具有依赖关系的服务:
a.服务
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'sleep 5;/bin/false'
RemainAfterExit=yes
b.服务
[Unit]
After=a.service
[Service]
Type=oneshot
ExecStart=/bin/echo B
RemainAfterExit=yes
c.服务
[Unit]
Requires=a.service
[Service]
Type=oneshot
ExecStart=/bin/echo C
RemainAfterExit=yes
d.服务
[Unit]
After=a.service
Requires=a.service
[Service]
Type=oneshot
ExecStart=/bin/echo D
RemainAfterExit=yes
加载的内容(以及加载的顺序)会根据您启动的内容而发生巨大变化:
a
:a
b
:b
c
(或a
+c
):a
同时c
(c
即使a
失败也保持运行)d
(或a
+d
):a
->c
(如果a
启动成功)a
+b
:a
->b
(无论是否a
启动)
为什么这么复杂?这是为了加快单位加载速度。如果服务没有Before
或After
相互引用,那么它们可以同时启动(假设没有其他单元需要它们!)
文件从哪里来.target
?他们将单元放入功能组中,以便当系统启动(或停止等)时,该阶段所需的单元可以一起启动,并且单元可以指示它们想要等待另一个阶段启动。例如,一个单元可以包括After=network.target
确保网络有机会在启动之前进行初始化,即使它是作为multi-user.target
.
如果您想查看单元相互依赖的顺序,您可以运行systemctl list-dependencies
(但它不会告诉您它们加载的顺序,因为这在Before
/After
设置之外有点随机。)