Red Hat Training

A Red Hat training course is available for RHEL 8

第 17 章 使用 systemd 单元文件

本章包含 systemd 单元文件的描述。以下部分介绍了如何进行:

  • 创建自定义单元文件
  • 将 SysV init 脚本转换为单元文件
  • 修改现有单元文件
  • 使用实例化单元

17.1. 单元文件简介

单元文件包含描述这个单元并定义其行为的配置指令。几个 systemctl 命令可用于后台的单元文件。要进行更细的调整,系统管理员必须手动编辑或创建单元文件。表 13.1 “systemd 单元文件位置” 列出将单元文件存储在系统中的三个主要目录, /etc/systemd/system/ 目录为系统管理员创建或自定义的单元文件保留。

单元文件名的格式如下:

unit_name.type_extension

在这里 , unit_name 代表单元名称, type_extension 代表单元类型,请参阅 表 13.2 “可用的 systemd 单元类型” 了解单元类型的完整列表。例如:系统中通常会有 sshd.servicesshd.socket 单元。

可通过一个目录来补充单元文件,以了解额外的配置文件。例如:要在 sshd.service 中添加自定义配置选项,请创建 sshd.service.d/custom.conf 文件并插入附加指令。有关配置目录的更多信息,请参阅 修改现有单元文件

另外,可以创建 sshd.service.wants/sshd.service.requires/ 目录。这些目录包含到 sshd 服务依赖的单元文件的符号链接。符号链接可在安装过程中根据 [Install] 单元文件选项或在运行时根据 [Unit] 选项自动创建。也可以手动创建这些目录和符号链接。有关 [Install] 和 [Unit] 选项的详情请参考下表。

可使用称为单元 指定符 - 通配符字符串来设置很多单元 文件选项,当载入单元文件时,它们会被动态替换为单元参数。这允许创建作为模板的通用单元文件,以生成实例化单元。详情请查看 使用实例化单元 进行操作。

17.2. 单元文件结构

单元文件通常由三个部分组成:

  • [Unit] 部分 - 包含不依赖于单元类型的通用选项。这些选项提供单元描述,指定单元的行为,并将依赖项设置为其他单元。有关最常用 [Unit] 选项的列表请参考 表 17.1 “重要 [Unit] 部分选项”
  • [Unit type] 部分 - 如果某个单元有特定类型指令,则在以单元类型命名的部分中分组。例如,服务单元文件包含 [Service] 部分。
  • [Install] 部分 - 包含 systemctl enabledisable 命令使用的单元安装的信息。有关 [Install] 部分的选项列表,请参阅 表 17.3 “重要 [Install] 部分选项”

17.2.1. 重要 [Unit] 部分选项

下表列出了 [Unit] 部分的重要选项。

表 17.1. 重要 [Unit] 部分选项

选项 [a]描述

Description

对这个单元有有意义的描述。这个文本显示在 systemctl status 命令的输出中。

Documentation

提供单元参考文档的 URI 列表。

After[b]

定义启动单位的顺序。这个单元仅在 After 中指定的单元处于活跃状态后启动。与 Requires 不同,After 不会显式激活指定的单元。Before 选项的功能与 After 相反。

Requires

配置其它单元上的依赖关系。Requires 中列出的单元与单元一同被激活。如果任何需要的单元无法启动,则该单位就不会被激活。

Wants

配置比 Requires 更弱的依赖项。如果列出的单元没有成功启动,它对单元激活不会有影响。这是建立自定义单元依赖项的建议方法。

Conflicts

配置负的依赖关系,与 Requires 相反。

[a] 有关 [Unit] 部分中可配置选项的完整列表,请查看 systemd.unit(5) 手册页。
[b] 在大多数情况下,只使用 AfterBefore 单元文件选项设置排序依赖关系就足够了。如果您还使用 Wants (推荐)或 Requires 设置了需要的依赖关系,仍需要指定依赖关系顺序。这是因为排序和要求依赖关系可以独立地工作。

17.2.2. 重要 [Service] 部分选项

下表列出了 [Service] 部分的重要选项。

表 17.2. 重要 [Service] 部分选项

选项 [a]描述

Type

配置影响 ExecStart 及相关选项功能的单元进程启动类型。其中之一:

* simple - 默认值。使用 ExecStart 启动的进程是该服务的主要进程。

* forking - 进程以 ExecStart 启动,生成一个作为服务主要进程的子进程。父进程在启动完成后会退出。

* oneshot - 这个类型与 simple 类似,但在启动单元前会退出。

* dbus - 这个类型与 simple 类似,但仅在主进程获得 D-Bus 名称后启动。

* notify - 这个类型与 simple 类似,但只有在通过 sd_notify() 函数发送通知消息后才启动该单元。

* idle - 与 simple 类似,服务二进制的实际执行会延迟到所有作业完成为止,这可以避免将状态输出与服务的 shell 输出混合。

ExecStart

指定在启动该单元时要执行的命令或脚本。ExecStartPreExecStartPost 指定在 ExecStart 之前和之后要执行的自定义命令。Type=oneshot 启用指定可按顺序执行的多个自定义命令。

ExecStop

指定在该单元停止时要执行的命令或脚本。

ExecReload

指定重新载入该单元时要执行的命令或脚本。

Restart

启用这个选项后,服务会在进程退出后重启,但 systemctl 命令有一个干净的 stop 除外。

RemainAfterExit

如果设为 True,即使其所有进程已退出,该服务也被视为活跃。默认值为 False。这个选项在配置了 Type=oneshot 时特别有用。

[a] 有关 [Service] 部分中可配置选项的完整列表,请查看 systemd.service(5) 手册页。

17.2.3. 重要 [Install] 部分选项

下表列出了 [Install] 部分的重要选项。

表 17.3. 重要 [Install] 部分选项

选项 [a]描述

Alias

为这个单元提供空格分开的额外名称列表。除 systemctl enable 外,大多数 systemctl 命令可使用别名而不是实际单元名称。

RequiredBy

依赖于这个单元的单元列表。当启用这个单元时, RequiredBy 中列出的单元会得到对这个单元的 Require 依赖项。

WantedBy

依赖于这个单元的单位列表。当启用这个单元时, WantedBy 中列出的单元会得到对这个单元的 Want 依赖项。

Also

指定要随这个单元一起安装或卸载的单元列表。

DefaultInstance

仅限于实例化单元,这个选项指定启用单位的默认实例。请参阅 使用实例化单元进行操作

[a] 有关 [Install] 部分中可配置选项的完整列表,请查看 systemd.unit(5) 手册页。

17.3. 创建自定义单元文件

从头开始创建单元文件有几个用例:您可以运行自定义守护进程,创建第二个现有服务实例(如 创建第二个 sshd 服务实例),或导入 SysV init 脚本(更多在 将 SysV init 脚本转换到单元文件中)。另一方面,如果您只想修改或扩展现有单元的行为,请使用 修改现有单元文件的说明。以下流程描述了创建自定义服务的一般过程。

流程

  1. 使用自定义服务准备可执行文件。这可以是自定义创建的脚本,也可以是软件供应商提供的可执行文件。如果需要,准备 PID 文件来保存自定义服务主要进程的恒定 PID。也可以包含环境文件来存储该服务的 shell 变量。确保源脚本是可执行文件(通过执行 chmod a+x),且不具有互动性。
  2. /etc/systemd/system/ 目录中创建单元文件并确保它有正确的文件权限。以 root 身份执行:

    touch /etc/systemd/system/name.service
    
    chmod 664 /etc/systemd/system/name.service

    使用要创建的服务的名称替换 name。请注意,该文件不需要可执行。

  3. 打开上一步中创建的 name.service 文件并添加服务配置选项。根据您想要创建的服务类型,可以使用各种选项,请参阅 单元文件结构。以下是网络相关服务的单元配置示例:

    [Unit]
    Description=service_description
    After=network.target
    
    [Service]
    ExecStart=path_to_executable
    Type=forking
    PIDFile=path_to_pidfile
    
    [Install]
    WantedBy=default.target

    其中:

    • Service_description 是一个说明性描述,在日志日志文件和 systemctl status 命令的输出中显示。
    • After 设置可确保仅在网络运行时启动该服务。添加以空格分隔的其他相关服务或目标的列表。
    • path_to_executable 代表到实际可执行服务的路径。
    • Type=forking 用于生成 fork 系统调用的守护进程。该服务的主要进程使用 path_to_pidfile 中指定的 PID 创建。更多与启动类型包括在 表 17.2 “重要 [Service] 部分选项”
    • WantedBy 说明服务应该启动的目标。将这些指标看成是旧的运行级别概念的替代。
  4. root 身份执行以下命令来通知 systemd 存在新的 name.service 文件:

    systemctl daemon-reload
    
    systemctl start name.service
    警告

    在创建新单元文件或修改现有单元文件后,始终运行 systemctl daemon-reload 命令。否则, systemctl startsystemctl enable 命令可能会因为 systemd 状态和磁盘中实际服务单元文件不匹配而失败。请注意,对于有大量单元的系统来说,这需要很长时间,因为每个单元的状态必须在重新载入的过程中被序列化,然后再进行反序列化。

17.3.1. 使用 sshd 服务的第二个实例创建自定义单元文件

系统管理员通常需要配置并运行多个服务实例。这可以通过创建原始服务配置文件的副本并修改某些参数来避免与服务的主实例冲突。以下流程演示了如何创建 sshd 服务第二个实例。

流程

  1. 创建第二个守护进程将使用的 sshd_config 文件副本:

    # cp /etc/ssh/sshd{,-second}_config
  2. 编辑上一步中创建的 sshd-second_config 文件,为第二个守护进程分配不同的端口号和 PID 文件:

    Port 22220
    PidFile /var/run/sshd-second.pid

    有关 PortPidFile 选项的更多信息,请参阅 sshd_config(5) manual page。请确定您选择的端口没有被其他服务使用。在运行该服务前,PID 文件不一定存在,它会在服务启动时自动生成。

  3. sshd 服务创建 systemd 单元文件副本:

    # cp /usr/lib/systemd/system/sshd.service /etc/systemd/system/sshd-second.service
  4. 按如下方式更改上一步中创建的 sshd-second.service:

    1. 修改 Description 选项:

      Description=OpenSSH server second instance daemon
    2. 将 sshd.service 添加到 After 选项中指定的服务,因此第二实例仅在第一个实例启动后启动:

      After=syslog.target network.target auditd.service sshd.service
    3. sshd 的第一个实例包括密钥生成,因此删除 ExecStartPre=/usr/sbin/sshd-keygen 行。
    4. sshd 命令中添加 -f /etc/ssh/sshd-second_config 参数,以便使用其他配置文件:

      ExecStart=/usr/sbin/sshd -D -f /etc/ssh/sshd-second_config $OPTIONS
    5. 在进行以上修改后,sshd-second.service 应该如下所示:

      [Unit]
      Description=OpenSSH server second instance daemon
      After=syslog.target network.target auditd.service sshd.service
      
      [Service]
      EnvironmentFile=/etc/sysconfig/sshd
      ExecStart=/usr/sbin/sshd -D -f /etc/ssh/sshd-second_config $OPTIONS
      ExecReload=/bin/kill -HUP $MAINPID
      KillMode=process
      Restart=on-failure
      RestartSec=42s
      
      [Install]
      WantedBy=multi-user.target
  5. 如果使用 SELinux,将第二个 sshd 实例的端口添加到 SSH 端口,否则第二个 sshd 实例将被拒绝绑定到端口:

    # semanage port -a -t ssh_port_t -p tcp 22220
  6. 启用 sshd-second.service,以便在引导时自动启动:

    # systemctl enable sshd-second.service
  7. 使用 systemctl status 命令验证 sshd-second.service 是否在运行。
  8. 通过连接到该服务来验证是否正确启用了端口:

    ssh -p 22220 user@server

    如果使用防火墙,请确定正确配置了防火墙以便允许到第二个 sshd 实例的连接。

17.3.2. 选择自定义单元文件排序和依赖项的目标

要了解如何正确地选择自定义单元文件排序和依赖项的目标,请查看以下文章:

红帽知识库文章中提供了在单元文件中通过顺序和依赖项触发的、一些实际的 World 问题单示例的附加信息吗?

如果要为由 systemd 启动的服务设置限制,请参阅红帽知识库文章 How to set limits on RHEL 7 和 systemd。这些限制需要在服务的单元文件中设置。请注意, systemd 忽略 /etc/security/limits.conf/etc/security/limits.d/*.conf 配置文件中设置的限制。这些文件中定义的限制由 PAM 在启动登录会话时设置,但由 systemd 启动的守护进程不使用 PAM 登录会话。

17.4. 将 SysV init 脚本转换为单元文件

在将 SysV 初始化脚本转换为单元文件前,请确定在其它位置还没有进行转换。Red Hat Enterprise Linux 中安装的所有核心服务都带有默认的单元文件,很多第三方软件包也是如此。

将初始化脚本转换成单元文件需要分析脚本并从中提取所需信息。基于这个数据,您可以创建一个单元文件。因为初始化脚本可能会根据服务的类型有很大不同,您可能需要使用比本章概述的更多配置选项。请注意,systemd 单元不再支持 init 脚本提供某种级别的定制。

转换所需的大多数信息在脚本的标头中提供。以下示例显示了初始化脚本的打开部分,用于在 Red Hat Enterprise Linux 6 中启动 postfix 服务:

!/bin/bash # postfix Postfix Mail Transfer Agent # chkconfig: 2345 80 30 # description: Postfix is a Mail Transport Agent, which is the program that moves mail from one machine to another. # processname: master # pidfile: /var/spool/postfix/pid/master.pid # config: /etc/postfix/main.cf # config: /etc/postfix/master.cf  BEGIN INIT INFO # Provides: postfix MTA # Required-Start: $local_fs $network $remote_fs # Required-Stop: $local_fs $network $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop postfix # Description: Postfix is a Mail Transport Agent, which is the program that moves mail from one machine to another.
# END INIT INFO

在上面的例子中,只有以 # chkconfig# description 开头的行是强制的,因此您可能不会在不同的 init 文件中找到其他行。BEGIN INIT INFO END INIT INFO 行之间连接的文本名为 Linux Standard Base (LSB) header。如果指定,LSB 标头包含定义服务描述、依赖项和默认运行级别的指令。下面是一个分析任务概述,旨在收集新单元文件所需的数据。postfix 初始化脚本被用作示例。

17.4.1. 查找 systemd 服务描述

您可以在以 #description 开头的行中找到有关脚本的描述性信息。这个描述与单元文件的 [Unit] 部分的 Description 选项中的服务名称一同使用。LSB 标头可能在 #Short-Description#Description 行中包含类似的数据。

17.4.2. 查找 systemd 服务依赖项

LSB 标头可能包含一些在服务间组成相依性指令。大多数可以转换到 systemd 单元选项,请参考 表 17.4 “LSB 标头中的依赖项选项”

表 17.4. LSB 标头中的依赖项选项

LSB 选项描述单元文件的对等

Provides

指定该服务的引导工具名称,可在其他初始化脚本中引用(使用"$"前缀)。因为单元文件根据文件名指向其他单元,所以不再需要这个操作。

Required-Start

包含所需服务的引导工具名称。这可转换为排序依赖项,引导工具名称被替换为相应服务的单元文件名或目标。例如,在 postfix 中,对 $network 的 Required-Start 依赖项会被转换为对 network.target 的依赖关系。

After, Before

Should-Start

比 Required-Start 更弱的依赖项。Should-Start 依赖项失败不会影响服务的启动。

After, Before

Required-Stop, Should-Stop

组成负依赖关系。

Conflicts

17.4.3. 查找服务的默认目标

#chkconfig 开始的行包含三个数字值。最重要的是第一个代表启动该服务的默认运行级别的数字。将这些运行级别映射到等同的 systemd 目标。然后在单元文件的 [Install] 部分的 WantedBy 选项中列出这些指标。例如: postfix 之前在运行级别 2、3、4 和 5 中启动,它们转换为 multi-user.target 和 graphical.target。请注意,graphical.target 依赖于 multiuser.target,因此不需要同时指定。您可能会在 LSB 标头的 #Default-Start#Default-Stop 行中找到默认和禁用运行级别的信息。

#chkconfig 行里指定的其他两个值代表初始化脚本的启动和关闭优先级。如果 systemd 加载初始化脚本,则对这些值进行解释,但没有等价的单元文件。

17.4.4. 查找该服务使用的文件

初始化脚本需要从专用目录中载入功能库,并允许导入配置、环境和 PID 文件。环境变量是在初始化脚本标头中以 #config 开始的行指定的,它转换为 EnvironmentFile 单元文件选项。在 #pidfile init 脚本行中指定的 PID 文件使用 PIDFile 选项导入到单元文件中。

未包含在初始化脚本标头中的关键信息是该服务可执行文件的路径,以及该服务可能需要的一些其他文件。在以前的 Red Hat Enterprise Linux 版本中,初始化脚本使用 Bash 问题单声明来定义服务在默认操作中的行为,如 启动停止重启, 以及自定义定义的操作。postfix init 脚本的以下摘录显示了在服务启动时要执行的代码块。

conf_check() {
    [ -x /usr/sbin/postfix ] || exit 5
    [ -d /etc/postfix ] || exit 6
    [ -d /var/spool/postfix ] || exit 5
}

make_aliasesdb() {
	if [ "$(/usr/sbin/postconf -h alias_database)" == "hash:/etc/aliases" ]
	then
		# /etc/aliases.db might be used by other MTA, make sure nothing
		# has touched it since our last newaliases call
		[ /etc/aliases -nt /etc/aliases.db ] ||
			[ "$ALIASESDB_STAMP" -nt /etc/aliases.db ] ||
			[ "$ALIASESDB_STAMP" -ot /etc/aliases.db ] || return
		/usr/bin/newaliases
		touch -r /etc/aliases.db "$ALIASESDB_STAMP"
	else
		/usr/bin/newaliases
	fi
}

start() {
	[ "$EUID" != "0" ] && exit 4
	# Check that networking is up.
	[ ${NETWORKING} = "no" ] && exit 1
	conf_check
	# Start daemons.
	echo -n $"Starting postfix: "
	make_aliasesdb >/dev/null 2>&1
	[ -x $CHROOT_UPDATE ] && $CHROOT_UPDATE
	/usr/sbin/postfix start 2>/dev/null 1>&2 && success || failure $"$prog start"
	RETVAL=$?
	[ $RETVAL -eq 0 ] && touch $lockfile
        echo
	return $RETVAL
}

init 脚本的可扩展性允许指定从 start() 功能块中调用的两个自定义功能 conf_check()make_aliasesdb()。然后,上面的代码中会提到的几个外部文件和目录:主服务可执行文件 /usr/sbin/postfix/etc/postfix//var/spool/postfix/ 配置目录以及 /usr/sbin/postconf/ 目录。

Systemd 只支持预定义的操作,但使用 ExecStartExecStartPreExecStartPostExecStopExecReload 选项启用自定义可执行文件。在服务启动时执行 /usr/sbin/postfix 以及支持脚本。转换复杂初始化脚本需要了解脚本中每个声明的目的。某些语句特定于操作系统版本,因此您不需要转换它们。另一方面,在新环境中可能需要对单元文件以及可执行和支持的服务文件进行一些调整。

17.5. 修改现有单元文件

在系统中安装的服务会附带保存在 /usr/lib/systemd/system/ 目录中的默认单元文件。系统管理员不应该直接修改这些文件,因此任何自定义都必须仅限于 /etc/systemd/system/ 目录中的配置文件。

流程

  1. 根据所需更改的程度,选择以下方法之一:

    • /etc/systemd/system/unit.d/ 创建一个附加配置文件的目录。我们推荐在大多数用例中使用这个方法。它启用了额外的功能来扩展默认配置,同时仍然引用原始的单元文件。因此,在软件包升级时对默认单元的更改会自动应用。如需更多信息, 请参阅扩展默认单元配置
    • /etc/systemd/system/ 中创建原始单元文件 /usr/lib/systemd/system/ 的副本并在此进行修改。这个副本会覆盖原始文件,因此不会应用软件包更新带来的更改。这个方法对无论软件包更新都应保留的重要单元更改都很有用。有关详细信息,请参阅覆盖默认单元配置
  2. 要返回这个单元的默认配置,请删除 /etc/systemd/system/ 中的自定义配置文件。
  3. 要在不重启系统的情况下对单元文件应用更改,请执行:

    systemctl daemon-reload

    daemon-reload 选项会重新载入所有单元文件并重新创建依赖项树,这是立即将任何更改应用到单元文件所必需的。另外,您可以使用以下命令得到同样的结果,该命令必须以 root 用户执行:

    init q
  4. 如果修改后的单元文件属于正在运行的服务,则必须重启该服务以接受新设置:

    systemctl restart name.service
重要

要修改由 SysV initscript 处理的服务的属性,如依赖项或超时,请不要修改 initscript 本身。反之,为服务创建一个 systemd drop-in 配置文件,如 扩展默认单元配置和 覆盖默认单元配置 中所述。然后,以与普通 systemd 服务相同的方式管理这个服务。

例如,要扩展 network 服务的配置,不要修改 /etc/rc.d/init.d/network initscript 文件。反之,创建新目录 /etc/systemd/system/network.service.d/ 和一个 systemd drop-in 文件 /etc/systemd/system/network.service.d/my_config.conf。然后将修改的值放到 drop-in 文件中。备注: systemd 知道 network 服务为 network.service,因此必须调用创建的目录 network.service.d

17.5.1. 扩展默认单元配置

这部分论述了如何使用额外配置选项扩展默认单元文件。

流程

  1. 要使用附加配置选项扩展默认单元文件,请首先在 /etc/systemd/system/ 中创建配置目录。如果扩展服务单元,以 root 身份执行以下命令:

    mkdir /etc/systemd/system/name.service.d/

    使用您要扩展的服务的名称替换 name。以上语法适用于所有单元类型。

  2. 在上一步中创建的目录中创建配置文件。请注意,文件名必须以 .conf 后缀结尾。类型:

    touch /etc/systemd/system/name.service.d/config_name.conf

    使用配置文件的名称替换 config_name。这个文件遵循通常的单元文件结构,因此所有指令都必须在适当的部分中指定,请参阅 单元文件结构

    例如,要添加自定义依赖项,请使用以下内容创建配置文件:

    [Unit]
    Requires=new_dependency
    After=new_dependency

    这里的 new_dependency 代表这个单元被标记为依赖项。另一个例子是主进程退出后重新启动服务的配置文件,延迟 30 秒:

    [Service]
    Restart=always
    RestartSec=30

    建议您只创建一个专注于一个任务的小配置文件。这些文件可轻松地移动或者链接到其他服务的配置目录。

  3. 要应用对单元所做的更改,以 root 身份执行:

    systemctl daemon-reload
    systemctl restart name.service

例 17.1. 扩展 httpd.service 配置

要修改 httpd.service 单元,以便在启动 Apache 服务时自动执行自定义 shell 脚本,请执行以下步骤。

  1. 创建目录和自定义配置文件:

    # mkdir /etc/systemd/system/httpd.service.d/
    # touch /etc/systemd/system/httpd.service.d/custom_script.conf
  2. 如果您要使用 Apache 自动启动的脚本位于 /usr/local/bin/custom.sh,请将以下文本插入到 custom_script.conf 文件中:

    [Service]
    ExecStartPost=/usr/local/bin/custom.sh
  3. 要应用单元更改,请执行:

    # systemctl daemon-reload
    # systemctl restart httpd.service
注意

/etc/systemd/system/ 中配置文件的配置文件优先于 /usr/lib/systemd/system/ 中的单元文件。因此,如果配置文件包含一个只能指定一次的选项,如 DescriptionExecStart,这个选项的默认值将被覆盖。请注意,在 监控覆盖单元 中描述的 systemd-delta 命令输出中,这些单元始终标记为 [EXTENDED],但在 sum 中,某些选项实际上会被覆盖。

17.5.2. 覆盖默认单元配置

这部分论述了如何覆盖默认单元配置。

流程

  1. 要在更新提供该单元文件的软件包后保留更改,首先将该文件复制到 /etc/systemd/system/ 目录中。要做到这一点,以 root 身份执行以下命令:

    cp /usr/lib/systemd/system/name.service /etc/systemd/system/name.service

    其中 name 代表您希望修改的服务单元的名称。以上语法适用于所有单元类型。

  2. 使用文本编辑器打开复制的文件,并进行必要的修改。要应用单元更改,以 root 身份执行:

    systemctl daemon-reload
    systemctl restart name.service

例 17.2. 更改超时限制

您可以为每个服务指定一个超时值,以防止出现故障的服务中断。否则,一般服务的超时时间会被默认设置为 90 秒,SysV 兼容的服务会被设置为 300 秒。

例如,要为 httpd 服务扩展超时限制:

  1. httpd 单元文件复制到 /etc/systemd/system/ 目录中:

    cp /usr/lib/systemd/system/httpd.service /etc/systemd/system/httpd.service
  2. 打开文件 /etc/systemd/system/httpd.service 并在 [Service] 部分指定 TimeoutStartUSec 值:

    
    [Service]
    
    PrivateTmp=true
    TimeoutStartSec=10
    
    [Install]
    WantedBy=multi-user.target
    
  3. 重新载入 systemd 守护进程:

    systemctl daemon-reload
  4. 可选。验证新的超时值:

    systemctl show httpd -p TimeoutStartUSec
注意

要全局更改超时限制,请在 /etc/systemd/system.conf 文件中输入 DefaultTimeoutStartSec

17.5.3. 监控覆盖单元

这部分论述了如何显示覆盖或修改的单元文件概述。

流程

  1. 要显示覆盖或修改的单元文件概述,请使用以下命令:

    systemd-delta

    例如,以上命令的输出结果如下:

    [EQUIVALENT] /etc/systemd/system/default.target → /usr/lib/systemd/system/default.target
    [OVERRIDDEN] /etc/systemd/system/autofs.service → /usr/lib/systemd/system/autofs.service
    
    --- /usr/lib/systemd/system/autofs.service      2014-10-16 21:30:39.000000000 -0400
    + /etc/systemd/system/autofs.service  2014-11-21 10:00:58.513568275 -0500
    @@ -8,7 +8,8 @@
     EnvironmentFile=-/etc/sysconfig/autofs
     ExecStart=/usr/sbin/automount $OPTIONS --pid-file /run/autofs.pid
     ExecReload=/usr/bin/kill -HUP $MAINPID
    -TimeoutSec=180
    +TimeoutSec=240
    +Restart=Always
    
     [Install]
     WantedBy=multi-user.target
    
    [MASKED]     /etc/systemd/system/cups.service → /usr/lib/systemd/system/cups.service
    [EXTENDED]   /usr/lib/systemd/system/sssd.service → /etc/systemd/system/sssd.service.d/journal.conf
    
    4 overridden configuration files found.

17.6. 使用实例化单元

可以在运行时使用单一模板配置文件实例化多个单元。"@"字符用于标记模板并与其关联。实例化的单元可以从另一个单元文件(使用 RequiresWants 选项)或者使用 systemctl start 命令启动。以下列方式命名实例化服务单元:

template_name@instance_name.service

其中 template_name 代表模板配置文件的名称。将 instance_name 替换为单元实例的名称。多个实例可以指向带有通用于单元所有实例的配置选项的同一个模板文件。模板单元名称具有以下格式:

unit_name@.service

例如,单位文件中的以下 Wants 设置:

Wants=getty@ttyA.service getty@ttyB.service

首先为给定服务单元进行 systemd 搜索。如果没有找到这样的单元,"@" 和类型后缀间的部分会被忽略, systemd 会搜索 getty@.service 文件,从中读取配置并启动服务。

例如: getty@.service 模板包含以下指令:

[Unit]
Description=Getty on %I
…
[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
…

当 getty@ttyA.service 和 getty@ttyB.service 由以上模板实例化时,Description= is 被解析为 Getty on ttyA 以及 Getty on ttyB

17.6.1. 重要单元指定符

可在任何单元配置文件中使用通配符字符(称为 单元指定符)。单元指定符替换了某些单元参数,并在运行时解释。表 17.5 “重要单元指定符” 列出对模板单元特别有用的单元指定符。

表 17.5. 重要单元指定符

单元指定符含义描述

%n

完整单元名称

代表完整单元名称,包括类型后缀。%N 具有相同的含义,但也将禁止字符替换为 ASCII 代码。

%p

前缀名称

代表删除类型后缀的单元名称。例如,实例化单元 %p 代表了"@"字符前的单元名称的一部分。

%i

实例名称

是"@"字符和类型后缀间的实例化单元名称的一部分。%I 具有相同的含义,但也替换了 ASCII 代码的禁止字符。

%H

主机名

代表在载入单元配置时的运行系统的主机名。

%t

运行时目录

代表运行时目录,对于 root 用户是 /run,对于非特权用户是 XDG_RUNTIME_DIR 变量的值。

有关单元指定符的完整列表,请查看 systemd.unit(5) 手册页。