了解Systemd单元和单元文件
介绍
Linux 发行版越来越多地采用 systemd
初始化系统。 这个强大的软件套件可以管理服务器的许多方面,从服务到安装的设备和系统状态。
在 systemd
中,unit
是指系统知道如何操作和管理的任何资源。 这是 systemd
工具知道如何处理的主要对象。 这些资源是使用称为单元文件的配置文件定义的。
在本指南中,我们将向您介绍 systemd
可以处理的不同单位。 我们还将介绍可以在单元文件中使用的许多指令中的一些指令,以塑造在您的系统上处理这些资源的方式。
Systemd Units 为您提供什么?
单元是 systemd
知道如何管理的对象。 这些基本上是系统资源的标准化表示,可以由守护程序套件管理并由提供的实用程序操作。
可以说单元类似于其他init系统中的服务或作业。 然而,一个单元有更广泛的定义,因为它们可以用于抽象服务、网络资源、设备、文件系统挂载和隔离资源池。
在其他 init 系统中可以使用一个统一的服务定义来处理的想法可以根据它们的关注点分解为组件单元。 这按功能组织,允许您轻松启用、禁用或扩展功能,而无需修改单元的核心行为。
单元可以轻松实现的一些功能是:
- 基于套接字的激活:与服务关联的套接字最好从守护程序本身中分离出来,以便单独处理。 这提供了许多优点,例如延迟服务的启动,直到第一次访问相关联的套接字。 这还允许系统在启动过程的早期创建所有套接字,从而可以并行启动相关服务。
- 基于总线的激活:单元也可以在
D-Bus
提供的总线接口上激活。 发布关联的总线时,可以启动一个单元。 - 基于路径的激活:可以根据某些文件系统路径上的活动或可用性来启动单元。 这利用了
inotify
。 - 基于设备的激活:通过利用
udev
事件,也可以在相关硬件首次可用时启动单元。 - 隐式依赖映射:单元的大部分依赖树可以由
systemd
自己构建。 您仍然可以添加依赖项和订购信息,但大部分繁重的工作都由您完成。 - 实例和模板:模板单元文件可用于创建同一个通用单元的多个实例。 这允许轻微的变化或同级单元都提供相同的一般功能。
- 简单的安全加固:单元可以通过添加简单的指令来实现一些相当好的安全功能。 例如,您可以指定对部分文件系统没有或只读访问权限,限制内核功能,并分配私有
/tmp
和网络访问权限。 - 插件和片段:通过提供将覆盖系统单元文件部分的片段,可以轻松地扩展单元。 这使得在原版和自定义单元实现之间切换变得很容易。
systemd
单元与其他初始化系统的工作项相比还有许多其他优点,但这应该让您了解使用本机配置指令可以利用的功能。
Systemd 单元文件在哪里找到?
定义 systemd
如何处理单元的文件可以在许多不同的位置找到,每个位置都有不同的优先级和含义。
系统的单元文件副本一般保存在/lib/systemd/system
目录下。 当软件在系统上安装单元文件时,这是默认放置它们的位置。
存储在此处的单元文件可以在会话期间按需启动和停止。 这将是通用的、普通的单元文件,通常由上游项目的维护人员编写,应该适用于在其标准实现中部署 systemd
的任何系统。 您不应编辑此目录中的文件。 相反,如果需要,您应该使用另一个单元文件位置覆盖该文件,该位置将取代该位置的文件。
如果您希望修改单元的运行方式,最好的位置是在 /etc/systemd/system
目录中。 在此目录位置找到的单元文件优先于文件系统上的任何其他位置。 如果你需要修改系统的一个单元文件的副本,在这个目录中放置一个替换是最安全和最灵活的方法。
如果您希望仅覆盖系统单元文件中的特定指令,您实际上可以在子目录中提供单元文件片段。 这些将附加或修改系统副本的指令,允许您仅指定要更改的选项。
正确的方法是创建一个以单元文件命名的目录,并在末尾附加 .d
。 因此,对于一个名为 example.service
的单元,可以创建一个名为 example.service.d
的子目录。 在这个目录中,一个以 .conf
结尾的文件可以用来覆盖或扩展系统单元文件的属性。
在 /run/systemd/system
处还有一个运行时单元定义的位置。 在此目录中找到的单元文件在 /etc/systemd/system
和 /lib/systemd/system
中的单元文件之间具有优先权。 此位置中的文件的权重低于前一个位置,但权重高于后者。
systemd
进程本身将此位置用于在运行时创建的动态创建的单元文件。 此目录可用于在会话期间更改系统的单元行为。 重新启动服务器后,在此目录中所做的所有更改都将丢失。
单位类型
Systemd
根据它们描述的资源类型对单元进行分类。 确定单元类型的最简单方法是使用其类型后缀,该后缀附加到资源名称的末尾。 以下列表描述了 systemd
可用的单位类型:
- .service:服务单元描述如何管理服务器上的服务或应用程序。 这将包括如何启动或停止服务,在什么情况下应该自动启动,以及相关软件的依赖关系和订购信息。
- .socket:套接字单元文件描述网络或 IPC 套接字,或
systemd
用于基于套接字的激活的 FIFO 缓冲区。 这些总是有一个关联的.service
文件,当在该单元定义的套接字上看到活动时,将启动该文件。 - .device:描述被
udev
或sysfs
文件系统指定为需要systemd
管理的设备的单元。 并非所有设备都有.device
文件。 订购、安装和访问设备时可能需要.device
单元的一些场景。 - .mount:这个单元定义了系统上的一个挂载点,由
systemd
管理。 这些以挂载路径命名,斜杠更改为破折号。/etc/fstab
中的条目可以自动创建单位。 - .automount:一个
.automount
单元配置一个将自动挂载的挂载点。 这些必须以它们引用的挂载点命名,并且必须具有匹配的.mount
单位来定义挂载的细节。 - .swap:此单元描述系统上的交换空间。 这些单元的名称必须反映空间的设备或文件路径。
- .target:目标单元用于在启动或更改状态时为其他单元提供同步点。 它们还可用于将系统带入新状态。 其他单位指定它们与目标的关系以与目标的操作联系在一起。
- .path:这个单元定义了一个可以用于基于路径的激活的路径。 默认情况下,当路径到达指定状态时,会启动一个同名的
.service
单元。 这使用inotify
来监控路径的变化。 - .timer:
.timer
单元定义将由systemd
管理的计时器,类似于延迟或计划激活的cron
作业。 当计时器到达时,将启动一个匹配单元。 - .snapshot:
.snapshot
单元由systemctl snapshot
命令自动创建。 它允许您在进行更改后重建系统的当前状态。 快照不能跨会话存活并用于回滚临时状态。 - .slice:
.slice
单元与 Linux 控制组节点相关联,允许将资源限制或分配给与切片关联的任何进程。 该名称反映了它在cgroup
树中的层次位置。 默认情况下,单元根据其类型放置在某些切片中。 - .scope:范围单元由
systemd
根据从其总线接口接收到的信息自动创建。 这些用于管理外部创建的系统进程集。
如您所见,systemd
知道如何管理许多不同的单元。 许多单元类型一起工作以添加功能。 例如,某些单元用于触发其他单元并提供激活功能。
我们将主要关注 .service
单元,因为它们的实用性和管理员需要管理这些单元的一致性。
单元文件剖析
单元文件的内部结构是按部分组织的。 节由一对方括号“[
”和“]
”表示,节名包含在其中。 每个部分一直延伸到下一个部分的开头或文件的结尾。
单元文件的一般特征
部分名称定义明确且区分大小写。 因此,如果将 [Unit]
部分拼写为 [UNIT]
,则 not 将被正确解释。 如果您需要添加非标准节以供 systemd
以外的应用程序解析,您可以在节名中添加 X-
前缀。
在这些部分中,单元行为和元数据是通过使用键值格式的简单指令定义的,赋值由等号指示,如下所示:
[Section] Directive1=value Directive2=value . . .
在覆盖文件的情况下(例如包含在 unit.type.d
目录中的文件),可以通过将指令分配给空字符串来重置指令。 例如,系统的单元文件副本可能包含设置为如下值的指令:
Directive1=default_value
可以通过引用不带值的 Directive1
在覆盖文件中消除 default_value
,如下所示:
Directive1=
通常,systemd
允许简单灵活的配置。 例如,接受多个布尔表达式(1
、yes
、on
和 true
表示肯定,0
、no
off
和 false
为相反的答案)。 可以智能地解析时间,假定秒为无单位值,并在内部完成多种格式的组合。
[单位] 部分指令
大多数单元文件中的第一部分是 [Unit]
部分。 这通常用于定义单元的元数据和配置单元与其他单元的关系。
虽然在解析文件时节顺序与 systemd
无关,但该节通常放在顶部,因为它提供了单元的概述。 您可以在 [Unit]
部分找到一些常见的指令:
- Description=:该指令可用于描述单元的名称和基本功能。 它由各种
systemd
工具返回,因此最好将其设置为简短、具体和信息丰富的内容。 - Documentation=:该指令为文档的 URI 列表提供位置。 这些可以是内部可用的
man
页面或 Web 可访问的 URL。systemctl status
命令将公开此信息,以便于发现。 - Requires=:该指令列出了该单元本质上依赖的所有单元。 如果当前单位被激活,此处列出的单位也必须成功激活,否则该单位将失败。 默认情况下,这些单元与当前单元并行启动。
- Wants=:该指令类似于
Requires=
,但不那么严格。Systemd
将在此单元被激活时尝试启动此处列出的任何单元。 如果未找到这些单元或无法启动,则当前单元将继续运行。 这是配置大多数依赖关系的推荐方法。 同样,这意味着并行激活,除非被其他指令修改。 - BindsTo=:该指令类似于
Requires=
,但也会导致当前单元在关联单元终止时停止。 - Before=:此指令中列出的单元如果同时激活,则在当前单元标记为已启动之前不会启动。 这并不意味着依赖关系,如果需要,必须与上述指令之一结合使用。
- After=:此指令中列出的单元将在启动当前单元之前启动。 这并不意味着依赖关系,如果需要,必须通过上述指令建立依赖关系。
- Conflicts=:这可用于列出不能与当前单元同时运行的单元。 以这种关系启动一个单元将导致其他单元停止。
- Condition...=:有许多以
Condition
开头的指令允许管理员在启动设备之前测试某些条件。 这可用于提供仅在适当系统上运行的通用单元文件。 如果不满足条件,则优雅地跳过该单元。 - Assert...=:类似于以
Condition
开头的指令,这些指令检查运行环境的不同方面以决定是否应该激活单元。 但是,与Condition
指令不同,否定结果会导致该指令失败。
使用这些指令和其他一些指令,可以建立有关该单元及其与其他单元和操作系统的关系的一般信息。
[安装] 部分指令
在单元文件的另一边,最后一个部分通常是 [Install]
部分。 此部分是可选的,用于定义启用或禁用的行为或单位。 启用一个单元会将其标记为在引导时自动启动。 本质上,这是通过将有问题的单元锁定到另一个单元上来完成的,该单元位于要在启动时启动的单元行中的某个位置。
因此,只有可以启用的单元才会有此部分。 其中的指令规定了启用该单元时应该发生的情况:
- WantedBy=:
WantedBy=
指令是指定如何启用单位的最常用方法。 该指令允许您以与[Unit]
部分中的Wants=
指令类似的方式指定依赖关系。 不同之处在于该指令包含在辅助单元中,允许列出的主要单元保持相对清洁。 启用带有此指令的单元时,将在/etc/systemd/system
内创建一个以指定单元命名的目录,并在末尾附加.wants
。 在此范围内,将创建指向当前单元的符号链接,从而创建依赖关系。 例如,如果当前单元有WantedBy=multi-user.target
,将在/etc/systemd/system
中创建一个名为multi-user.target.wants
的目录(如果尚不可用),并且指向当前单元的符号链接将是放在里面。 禁用此单元将删除链接并删除依赖关系。 - RequiredBy=:此指令与
WantedBy=
指令非常相似,但它指定了一个必需的依赖项,如果不满足该依赖项将导致激活失败。 启用后,具有此指令的单元将创建一个以.requires
结尾的目录。 - Alias=:该指令还允许以另一个名称启用该单元。 在其他用途中,这允许一个函数的多个提供者可用,以便相关单元可以查找任何具有通用别名的提供者。
- Also=:该指令允许将单位作为一组启用或禁用。 可以在此处列出在此单元处于活动状态时应始终可用的支持单元。 它们将作为一组进行管理以执行安装任务。
- DefaultInstance=:对于可以生成具有不可预测名称的单元实例的模板单元(稍后介绍),如果未提供适当的名称,则可以将其用作名称的后备值。
特定于单元的部分指令
夹在前两个部分之间,您可能会找到特定于单元类型的部分。 大多数单元类型提供仅适用于其特定类型的指令。 这些在以其类型命名的部分中可用。 我们将在这里简要介绍这些内容。
device
、target
、snapshot
和 scope
单元类型没有特定于单元的指令,因此没有与其类型相关的部分。
[服务] 部分
[Service]
部分用于提供仅适用于服务的配置。
应该在 [Service]
部分中指定的基本内容之一是服务的 Type=
。 这按服务的进程和守护程序行为对服务进行分类。 这很重要,因为它告诉 systemd
如何正确管理服务并找出其状态。
Type=
指令可以是以下之一:
- simple:在启动行中指定服务的主进程。 如果未设置
Type=
和Busname=
指令,但设置了ExecStart=
,则这是默认设置。 任何通信都应通过适当类型的第二个单元在单元外部处理(例如,如果该单元必须使用套接字进行通信,则通过.socket
单元)。 - forking:当服务分叉子进程时使用此服务类型,几乎立即退出父进程。 这告诉
systemd
即使父进程退出,进程仍在运行。 - oneshot:此类型表示进程将是短暂的,并且
systemd
应等待进程退出,然后再继续处理其他单元。 这是默认未设置Type=
和ExecStart=
。 它用于一次性任务。 - dbus:这表示该单元将在 D-Bus 总线上取一个名字。 发生这种情况时,
systemd
将继续处理下一个单元。 - notify:表示服务启动完成后会发出通知。
systemd
进程将等待这种情况发生,然后再继续处理其他单元。 - idle:这表示在所有作业都被调度之前不会运行服务。
使用某些服务类型时可能需要一些额外的指令。 例如:
- RemainAfterExit=:该指令通常与
oneshot
类型一起使用。 它表明即使在进程退出后,服务也应该被认为是活动的。 - PIDFile=:如果服务类型标记为“forking”,则该指令用于设置文件的路径,该文件应包含应监控的主子进程ID号。
- BusName=:此指令应设置为服务在使用“dbus”服务类型时将尝试获取的 D-Bus 总线名称。
- [x0x] notifyAccess = [x17x]:这指定了对套接字的访问,该套接字应在选择“ Notify”服务类型时使用通知,这可以是“无”,“ main”或“全部。 默认值“none”会忽略所有状态消息。 “main”选项将侦听来自主进程的消息,“all”选项将处理服务控制组的所有成员。
到目前为止,我们已经讨论了一些先决条件信息,但我们还没有真正定义如何管理我们的服务。 执行此操作的指令是:
- ExecStart=:这指定完整路径和要执行以启动进程的命令的参数。 这只能指定一次(“oneshot”服务除外)。 如果命令的路径前面有一个破折号“-”字符,则将接受非零退出状态,而不会将单元激活标记为失败。
- ExecStartPre=:这可用于提供应在主进程启动之前执行的附加命令。 这可以多次使用。 同样,命令必须指定完整路径,并且可以在它们前面加上“-”以表示可以容忍命令失败。
- ExecStartPost=:它与
ExecStartPre=
具有相同的特性,只是它指定了在 主进程启动后将运行的命令。 - ExecReload=:此可选指令指示重新加载服务配置所需的命令(如果可用)。
- ExecStop=:这表示停止服务所需的命令。 如果没有给出,当服务停止时,进程将立即被杀死。
- ExecStopPost=:这可用于指定要在停止命令之后执行的命令。
- RestartSec=:如果启用了自动重新启动服务,这将指定在尝试重新启动服务之前等待的时间量。
- Restart=:这表示
systemd
会尝试自动重启服务的情况。 这可以设置为“始终”、“成功”、“失败”、“异常”、“中止”或“看门狗”等值。 这些将根据服务停止的方式触发重新启动。 - TimeoutSec=:这配置
systemd
在停止或停止服务时将等待的时间量,然后将其标记为失败或强制终止它。 您也可以使用TimeoutStartSec=
和TimeoutStopSec=
设置单独的超时。
[Socket] 部分
套接字单元在 systemd
配置中非常常见,因为许多服务实现基于套接字的激活以提供更好的并行化和灵活性。 每个套接字单元必须有一个匹配的服务单元,该服务单元将在套接字接收到活动时被激活。
通过打破服务本身之外的套接字控制,可以尽早初始化套接字,并且通常可以并行启动相关的服务。 默认情况下,套接字名称会在收到连接时尝试启动同名服务。 当服务初始化时,套接字将被传递给它,允许它开始处理任何缓冲的请求。
要指定实际的套接字,这些指令很常见:
- ListenStream=:这定义了支持顺序可靠通信的流套接字的地址。 使用 TCP 的服务应该使用这种套接字类型。
- ListenDatagram=:这定义了支持快速、不可靠通信包的数据报套接字的地址。 使用 UDP 的服务应设置此套接字类型。
- ListenSequentialPacket=:这定义了一个地址,用于与保留消息边界的最大长度数据报进行顺序、可靠的通信。 这在 Unix 套接字中最常见。
- ListenFIFO:与其他侦听类型一起,您还可以指定 FIFO 缓冲区而不是套接字。
有更多类型的监听指令,但以上是最常见的。
可以通过附加指令控制套接字的其他特性:
- Accept=:这决定了是否会为每个连接启动一个额外的服务实例。 如果设置为 false(默认值),则一个实例将处理所有连接。
- SocketUser=:对于 Unix 套接字,指定套接字的所有者。 如果未设置,这将是 root 用户。
- SocketGroup=:对于 Unix 套接字,指定套接字的组所有者。 如果未设置 this 或 above,这将是根组。 如果只设置了
SocketUser=
,systemd
会尝试寻找匹配的组。 - SocketMode=:对于 Unix 套接字或 FIFO 缓冲区,这将设置创建实体的权限。
- Service=:如果服务名称与
.socket
名称不匹配,则可以使用该指令指定服务。
[安装] 部分
安装单元允许从 systemd
内进行安装点管理。 挂载点以其控制的目录命名,并应用了转换算法。
例如,前导斜杠被删除,所有其他斜杠都被翻译成破折号“-”,所有破折号和不可打印的字符都被替换为 C 样式的转义码。 此转换的结果用作安装单元名称。 挂载单元将隐式依赖于层次结构中高于它的其他挂载。
在引导过程中,挂载单元通常直接从 /etc/fstab
文件转换而来。 对于自动创建的单元定义和您希望在单元文件中定义的单元定义,以下指令很有用:
- What=:需要挂载的资源的绝对路径。
- Where=:资源应该挂载的挂载点的绝对路径。 除了使用传统的文件系统表示法外,这应该与单元文件名相同。
- Type=:挂载的文件系统类型。
- Options=:需要应用的任何挂载选项。 这是一个逗号分隔的列表。
- SloppyOptions=:一个布尔值,用于确定如果存在无法识别的挂载选项,挂载是否会失败。
- DirectoryMode=:如果需要为挂载点创建父目录,这决定了这些目录的权限模式。
- TimeoutSec=:配置系统等待挂载操作被标记为失败的时间量。
[自动挂载] 部分
该单元允许在引导时自动安装关联的 .mount
单元。 与 .mount
单元一样,这些单元必须以转换后的安装点的路径命名。
[Automount]
部分非常简单,只允许以下两个选项:
- Where=:文件系统上自动挂载点的绝对路径。 这将匹配文件名,只是它使用传统的路径表示法而不是翻译。
- DirectoryMode=:如果需要创建自动挂载点或任何父目录,这将决定那些路径组件的权限设置。
[交换] 部分
交换单元用于配置系统上的交换空间。 这些单元必须以交换文件或交换设备命名,使用上面讨论的相同文件系统转换。
与挂载选项一样,交换单元可以从 /etc/fstab
条目自动创建,也可以通过专用单元文件进行配置。
单元文件的 [Swap]
部分可以包含以下配置指令:
- What=:交换空间位置的绝对路径,无论是文件还是设备。
- Priority=:这需要一个整数,表示正在配置的交换的优先级。
- Options=:通常在
/etc/fstab
文件中设置的任何选项都可以使用此指令进行设置。 使用逗号分隔的列表。 - TimeoutSec=:
systemd
在将操作标记为失败之前等待激活交换的时间量。
[路径] 部分
路径单元定义 systmed
可以监视更改的文件系统路径。 必须存在另一个单元,当在路径位置检测到某些活动时将激活该单元。 路径活动通过 inotify
事件确定。
单元文件的 [Path]
部分可以包含以下指令:
- PathExists=:该指令用于检查有问题的路径是否存在。 如果是,则激活相关联的单元。
- PathExistsGlob=:同上,但支持文件glob表达式来判断路径是否存在。
- PathChanged=:这会监视路径位置的变化。 如果在监视文件关闭时检测到更改,则激活关联的单元。
- PathModified=:这会监视类似上述指令的更改,但它会在文件写入以及文件关闭时激活。
- DirectoryNotEmpty=:该指令允许
systemd
在目录不再为空时激活关联单元。 - Unit=:指定满足上述路径条件时激活的单元。 如果省略,
systemd
将查找与本单元共享相同基本单元名称的.service
文件。 - MakeDirectory=:这决定了
systemd
是否会在观看之前创建相关路径的目录结构。 - DirectoryMode=:如果启用以上,这将设置必须创建的任何路径组件的权限模式。
[定时器] 部分
定时器单元用于安排任务在特定时间或特定延迟后运行。 此单元类型替换或补充了 cron
和 at
守护程序的一些功能。 必须提供一个相关的单元,该单元将在达到计时器时被激活。
单元文件的 [Timer]
部分可以包含以下一些指令:
- OnActiveSec=:该指令允许相对于
.timer
单元的激活激活关联单元。 - OnBootSec=:该指令用于指定系统启动后,应激活相关单元的时间量。
- OnStartupSec=:该指令类似于上面的计时器,但与
systemd
进程本身的启动时间有关。 - OnUnitActiveSec=:这将根据关联单元上次激活的时间设置一个计时器。
- OnUnitInactiveSec=:这将设置与关联单元上次标记为非活动时间相关的计时器。
- OnCalendar=:这允许您通过指定绝对而不是相对于事件来激活关联单位。
- AccuracySec=:此单位用于设置计时器应遵守的准确度级别。 默认情况下,相关单元将在计时器到达后一分钟内激活。 该指令的值将确定
systemd
安排激活发生的窗口的上限。 - Unit=:此指令用于指定在计时器结束时应激活的单位。 如果未设置,
systemd
将查找名称与该单位匹配的.service
单位。 - Persistent=:如果设置了此项,如果在定时器未激活期间触发,
systemd
将在定时器激活时触发相关单元。 - WakeSystem=:设置此指令允许您在处于该状态时达到计时器时将系统从挂起中唤醒。
[切片] 部分
单元文件的 [Slice]
部分实际上没有任何 .slice
单元特定配置。 相反,它可以包含一些实际上可用于上面列出的许多单元的资源管理指令。
[Slice]
部分中的一些常用指令,也可以在其他单元中使用,可以在 systemd.resource-control
手册页中找到。 这些在以下特定于单元的部分中有效:
[Slice]
[Scope]
[Service]
[Socket]
[Mount]
[Swap]
从模板单元文件创建实例单元
我们在本指南前面提到了使用模板单元文件创建多个单元实例的想法。 在本节中,我们可以更详细地讨论这个概念。
在大多数情况下,模板单元文件与常规单元文件没有什么不同。 但是,这些通过允许文件的某些部分使用将在运行时可用的动态信息,为配置单元提供了灵活性。
模板和实例单元名称
可以识别模板单元文件,因为它们在基本单元名称之后和单元类型后缀之前包含一个 @
符号。 模板单元文件名可能如下所示:
example@.service
从模板创建实例时,实例标识符放置在 @
符号和表示单元类型开始的句点之间。 例如,上面的模板单元文件可用于创建如下所示的实例单元:
example@instance1.service
实例文件通常创建为模板文件的符号链接,链接名称包括实例标识符。 这样,具有唯一标识符的多个链接可以指向单个模板文件。 管理实例单元时,systemd
将查找具有您在命令行中指定的确切实例名称的文件以使用。 如果找不到,它将寻找相关的模板文件。
模板说明符
模板单元文件的强大之处主要体现在它能够根据操作环境动态替换单元定义中的适当信息。 这是通过在模板文件中正常设置指令来完成的,但是用变量说明符替换某些值或值的一部分。
以下是在使用相关信息解释实例单元时将替换的一些更常见的说明符:
- %n:在模板文件中出现的任何地方,都会插入完整的单元名称。
- %N:这和上面的一样,但是任何转义,比如文件路径模式中的转义,都会被反转。
- %p:这引用了单位名称前缀。 这是位于
@
符号之前的单元名称部分。 - %P:这和上面的一样,但是任何转义都是相反的。
- %i:引用实例名称,即实例单位中
@
后面的标识符。 这是最常用的说明符之一,因为它保证是动态的。 此标识符的使用鼓励使用配置重要标识符。 例如,将运行服务的端口可以用作实例标识符,模板可以使用此说明符来设置端口规范。 - %I:此说明符与上述说明符相同,但任何转义都相反。
- %f:这将被替换为未转义的实例名称或前缀名称,前缀为
/
。 - %c:这将指示单元的控制组,删除了
/sys/fs/cgroup/ssytemd/
的标准父层次结构。 - %u:配置为运行单元的用户名。
- %U:同上,但用数字
UID
代替名称。 - %H:运行单元的系统的主机名。
- %%:用于插入文字百分号。
通过在模板文件中使用上述标识符,systemd
将在解释模板以创建实例单元时填写正确的值。
结论
使用 systemd
时,了解单位和单位文件可以使管理更容易。 与许多其他 init 系统不同,您不必知道脚本语言来解释用于引导服务或系统的 init 文件。 单元文件使用相当简单的声明性语法,使您可以一目了然地看到单元在激活时的用途和效果。
将激活逻辑等功能分解为单独的单元不仅可以让内部 systemd
进程优化并行初始化,还可以保持配置相当简单,并允许您修改和重新启动某些单元而无需拆除和重建它们的关联连接. 利用这些能力可以在管理过程中为您提供更大的灵活性和权力。