注:

在 Oracle Linux 上使用 systemd

简介

在本教程中,您将学习如何使用 systemctl 命令行实用程序管理和查看 systemd 控制的 systemd 单元。本教程以 Oracle Linux 8 或更高版本的用户为目标。

systemd 是引导时启动的第一个进程,是系统关闭时终止的最终进程。systemd 主要用于在引导时管理系统服务或进程以及系统初始化。但是,systemd 还能够处理许多其他任务和功能,包括事件记录、设备管理、用户登录、任务调度、时间同步和系统引导。systemd 中的许多功能未完全使用,因为用户可能更熟悉用于这些用途的替代软件,或者不同的 Linux 分发可能具有首选的系统配置方法。

在 systemd 单元中处理不同类型的行为或函数。例如,守护进程或系统服务作为服务单元运行,而系统状态通常定义为目标单元。可以定义计时器单元来调度任务,类似于使用系统 cron 服务的方式,并且可以使用挂载单元来配置挂载点,就像在系统 fstab 中配置挂载点的方式一样。

systemd 用于管理系统级进程和函数,但它也能够管理在用户空间中运行的进程。系统上的用户可以配置和管理自己的服务,甚至可以配置 systemd 以允许这些服务在用户终止其会话后继续运行。

目标

需要做哪些准备?

注意:使用免费实验室环境时,请参见 Oracle Linux Lab Basics 了解连接和其他使用情况说明。

了解 systemd 单元文件

连接到 Oracle Linux 8 实例后,可以开始尝试使用 systemctl 命令来了解可用的不同单元。

  1. 运行 systemctl 命令可列出当前由 systemd 装入的所有 systemd 单元:

    systemctl
    

    使用键盘上的空格或 PgDn 键可遍历输出。

    此命令相当于运行以下命令:

    systemctl list-units
    

    输出显示 systemd 正在管理的所有当前活动配置单元。在输出中应注意,存在使用不同后缀命名的单位,包括使用 '.device'、'.mount'、'.service'、'.target' 和 '.timer' 后缀命名的单位。

    单元在启动、运行、装载或插入时处于活动状态,具体取决于它们的用途。单元可以处于非活动状态,即停止、卸载或断开连接。如果要查看所有单位,而不管它们是否有效,可以运行:

    systemctl list-units --all
    

    以下命令的输出显示了不同类型的 systemd 单元的选择:

    • automount:提供自动挂载功能,支持按需挂载文件系统和并行引导。
    • mount:控制文件系统当前日期和时间显示中的挂载点。
    • path:可以在文件系统路径信息发生更改时激活服务。
    • scope:与服务单元类似,但管理外部进程而不是启动它们。
    • service:启动和控制守护进程及其包含的进程。
    • slice:用于对分层 cgroup 树中的系统进程(如服务单元和范围单元)进行分组以用于资源管理。
    • socket:封装系统中的本地进程间通信 (Interprocess Communication, IPC) 或网络套接字,这对于基于套接字的激活非常有用。
    • target:用于在引导期间对单元进行分组或提供已知的同步点。
    • timer:用于触发使用计时器激活其他单位。这些选项提供了替代以前可能已使用 cron 服务管理的任务。
    • device:在 systemd 中公开内核设备,还可以用于实现基于设备的激活。
    • swap:封装内存交换分区或交换文件。
  2. 使用 --type 选项将单元列表限制为特定的单元类型。

    • 使用 systemctl list-units --type services 命令列出系统上的当前活动服务单元。

      systemctl list-units --type service
      
    • 再次运行同一命令,但包括 --all 选项以查看所有装入的单元,包括处于非活动状态(如果有)。

      systemctl list-units --type service --all
      

您可以对可用的每种服务类型重复这些命令,以便仅将信息限制为您随时感兴趣的类型。

使用系统化目标单元

目标单位用于将不同的单位组合在一起,以使系统处于特定状态,以便它可以用于特定目的。

  1. 列出可用的 target 单元。

    systemctl list-units --type target
    

    单元可以要求加载其他单元,也可以配置为与特定单元冲突。例如,multi-user.target 要求 basic.target 正常运行,它也与 rescue.servicerescue.target 单元冲突。单位还指定要加载以能够运行的其他单位。

    通过这种方式,可以将目标链接在一起以设置特定状态,但其模块化程度也足以重用于触发替代状态。

  2. 查看默认目标单元。

    缺省目标单元定义引导后的缺省系统状态。

    • 使用 systemctl get-default 命令查看缺省情况下使用的目标单元。默认目标单元由 /etc/systemd/system/default.target 文件表示。

      systemctl get-default
      
    • 使用 ls -l 命令可列出有关 /etc/systemd/system/default.target 文件的信息。

      ls -l /etc/systemd/system/default.target
      

      注意:default.target 文件是指向当前默认目标单元文件的符号链接。

  3. 更改默认目标单元。

    • 使用 systemctl set-default 命令将缺省目标单元更改为 graphical.target 单元。

      systemctl set-default graphical.target
      
    • 使用 ls –l 命令确认 default.target 文件现在是指向 graphical.target 文件的符号链接。

      ls -l /etc/systemd/system/default.target
      

      注意:更改默认目标单元将删除现有的 default.target 符号链接并重新创建指向新的默认目标单元的符号链接。

  4. 浏览目标以了解更多信息。

    • 使用 systemctl show 命令可获取有关任何特定目标的更多信息。

      systemctl show multi-user.target
      

      输出显示您指定的目标的所有参数。请注意,您可以确定目标需要、希望和冲突的单位,并且还可以查看此目标必须在之前和之后运行的单位。

    • 使用 systemctl list-dependencies 命令显示特定目标达到其状态所需的或需要的依赖项的树:

      systemctl list-dependencies default.target
      

      此命令显示启动默认目标时启动的所有单元。单位链以递归方式呈现到树中,从而可以全面评估目标在启动时取得的成绩。如果已将 graphical.target 设置为默认目标,则可以看到系统希望运行 display-manager.service 来加载图形显示,但还会运行 multi-user.target 来执行运行图形显示之前所需的所有操作。

使用 systemctl 启用、禁用和屏蔽单元

可以禁用或启用单元,还可以对其进行屏蔽,以便从不在任何情况下运行单元。有些单位是静态的,因为它们始终可用,通常是因为它们是其他要工作的单位的依赖项。systemctl list-units 命令只能用于显示系统中处于活动状态或不活动的单元。

  1. 列出系统上可用的所有单元及其状态:

    systemctl list-unit-files
    

    许多可用的单元是静态的。启用的单元在引导时启动。已禁用的单元是系统上可用但未配置为引导时启动的单元。屏蔽的单元在系统中可用,但是已主动设置为根本无法启动它们的状态。

  2. 使用 systemctl status 命令查看有关 nfs-server.service 单元的详细信息。

    systemctl status nfs-server.service
    

    systemctl 命令允许您在引用服务单元时删除 .service 扩展。

    状态命令指示某个单元是启用、活动、不活动、已禁用还是已屏蔽。

    对于脚本化解决方案,systemctl 提供了一行输出状态的简短命令:

    • 使用 systemctl is-active 命令检查 nfs-server 服务是正在运行(活动)还是未运行(不活动)。

      systemctl is-active nfs-server
      
    • 使用 systemctl is-enabled 命令检查 nfs-server 服务是否已启用或禁用。启用服务后,服务将在系统重新引导时启动。

      systemctl is-enabled nfs-server
      
  3. 允许服务在引导时启动。

    可以使用 systemctl enable 命令启用 nfs-server 服务。

    sudo systemctl enable --now nfs-server
    

    如果命令更改系统状态或配置,则必须使用管理员权限运行 systemctl 命令。可以使用 --now 选项在启用服务的同时另外启动服务。

    注意:该命令通过为服务启动的最低级别系统状态目标创建符号链接来启用服务。在输出中,该命令为 multi-user 目标创建了符号链接 nfs-server.service

    使用 systemctl status command 确认 nfs-server 服务现在已启用且正在运行。

    systemctl status nfs-server
    
  4. 禁用和停止服务。

    可以使用 systemctl disable 命令禁用 nfs-server 服务。另请注意,systemctl disable 命令删除服务的 systemctl 链接。

    sudo systemctl disable nfs-server
    

    使用 systemctl stop 命令停止 nfs-server 服务。

    sudo systemctl stop nfs-server
    

    在禁用服务时,可以使用 --now 选项组合这些步骤。

  5. 屏蔽和取消屏蔽单元。

    在某些情况下,您可能希望禁用从头开始的单位。通常,如果特定单元与系统上的某些其他功能冲突,或者由于策略原因,您可以执行此操作。

    使用 systemctl mask 命令屏蔽 nfs-server 服务:

    sudo systemctl mask nfs-server
    

    创建符号链接以确保 systemd 单元配置指向 /dev/null。这将阻止启用或启动服务。

    确认在屏蔽 nfs-server 单元时无法启动该单元:

    sudo systemctl start nfs-server
    

    服务无法启动,返回错误以指示服务已屏蔽。

    取消屏蔽单元以将其返回到其原始状态,并允许用户启动或启用该服务。

    sudo systemctl unmask nfs-server
    

为用户空间单位设置 systemd

通常,systemd 用于在系统级别管理单元。用户需要对系统进行管理员级别访问,以管理以这种方式配置的 systemd 单元。在某些环境和某些单元类型中,用户可能希望使用 systemd 在用户空间内运行单元的能力。例如,用户可能希望使用 systemd 的计时器单元功能来调度任务;或者用户可能希望将特定的应用程序或服务作为不需要 root 级别权限才能运行的服务单元运行。

systemd 在登录时为用户启动一个 systemd 用户进程。对于用户,将按以下顺序处理位于以下目录中的单元:

通过对任何 systemd 命令使用 --user 选项,可以向 systemd 指示您在用户空间中工作。

  1. 列出用户当前可用的单元文件。

    systemctl --user list-unit-files
    

    请注意,可用单元列表大大短于发出不带 --user 选项的同一命令时。

    这些单元文件的大多数位于新系统上的 /usr/lib/systemd/user 中。列出此目录中的文件以查看位于以下位置的单元:

    ls -la /usr/lib/systemd/user/
    
  2. 创建用于托管您自己的 systemd 单元文件的目录。

    mkdir -p $HOME/.config/systemd/user
    
  3. 创建您自己的 systemd 服务单元。

    cat << EOF > $HOME/.config/systemd/user/uptime.service
    [Unit]
    Description="Logs system uptime and load average"
    Wants=uptime.timer
    
    [Service]
    ExecStart=/usr/bin/uptime
    
    [Install]
    WantedBy=default.target
    
    EOF
    

    此服务单元提供三个配置部分。

    Unit 部分提供了单元的说明以及任何要求。在这种情况下,Wants 条目定义尚不存在的计时器单元的弱要求。列为 Wants 条目的单位在可用时运行,但不阻止父单元在找不到或无法运行时运行。

    Service 部分定义此特定服务单元在运行时的行为。我们在此处依赖多个可用选项的缺省值,并且仅指定 ExecStartline,该行指定启动服务时运行的命令。在这种情况下,将运行 uptime 命令来记录系统正常运行时间和负载值。

    Install 部分定义启用服务后应如何将其安装到系统中。值得注意的是,该服务添加为 WantedBy 为 "default.target" 的服务。这意味着服务是作为此用户的默认目标的一部分启用的。

  4. 运行 systemd 单元并检查其输出。

    由于您已添加新单元,因此在尝试运行该服务之前重新加载系统配置通常是个好主意:

    systemctl --user daemon-reload
    

    现在启动新单元。

    systemctl --user start uptime
    

    检查命令是否按预期运行。您可以通过检查服务的状态来检查服务是否已运行:

    systemctl --user status uptime
    

    注意:这些命令使用 --user 选项在用户空间内运行。

    要检查所运行的 uptime 命令的输出,请使用 journalctl 命令查看日志并指定标记选项来查看特定于该命令的日志:

    journalctl -t uptime
    

    您可以启用此服务,使其在用户首次登录到系统时启动。

    systemctl --user enable uptime
    

    请注意,服务在用户首次登录到系统时运行。它不会在系统引导时自动启动。通常,在用户空间中运行的服务在用户注销或终止所有用户会话后终止。本教程稍后将讨论用户服务的启用持久性。

使用系统化计时器单元

在本练习中,您将在前面的练习的基础上再接再厉,以创建并允许计时器单元定期在特定时间或间隔运行另一个 systemd 单元。计时器单位可以在系统级别和用户级别定义,可用于定义 systemd 应何时运行其他单位。计时器单元对已调度事件提供细粒度控制,并可替代使用 cron 守护进程处理更多子配置。

许多系统服务都包括计时器单元以控制运行时间。dnf-automatic 软件包中提供了一个计时器单元的极佳示例,可用于使系统保持最新状态,以便系统自动执行常规 dnf 更新。要在系统级别执行此操作,请安装软件包并启用计时器单元:

sudo dnf install -y dnf-automatic
sudo systemctl enable dnf-automatic.timer

您可以查看单元文件来了解该单元的配置方式:

cat /usr/lib/systemd/system/dnf-automatic.timer

此单元中的重要内容包括 Wants 行,该行需要满足 network-online.target。配置的 Timer 部分中的 OnCalendar 条目表明此操作每天都在 06h00 运行。同样值得注意的是 RandomizedDelaySec 条目,该条目可以帮助防止计时器单元完全同时触发,并突然推送系统负载。

此处提供的示例属于更复杂的一组单元。要更好地了解计时器单元的工作原理,请在用户空间中添加计时器单元,以调度您在上一个练习中创建的 uptime.service,使其以固定间隔运行。

  1. 创建计时器单元文件。

    cat <<EOF > $HOME/.config/systemd/user/uptime.timer
    [Unit]
    Description=Timer for the uptime service that logs uptime
    Requires=uptime.service
    
    [Timer]
    Unit=uptime.service
    OnCalendar=*-*-* *:*:00
    
    [Install]
    WantedBy=timers.target
    

    此文件指定要运行此计时器单元需要 uptime.service。这是一个比 Wants 定义中定义的要求强得多的要求,如果不符合要求,则单元不运行。

    Timer 部分定义它使用 OnCalendar 项装入 uptime.service 单元。OnCalendar 项与 crontab 定义中的选项类似,但提供了更精细的功能。在这种情况下,单位定义为每分钟 00 秒运行一次。

  2. 由于您修改了 systemd 配置,因此请重新加载 systemd 守护进程并重新启动运行时间服务,以便它可以选取新的计时器单元:

    systemctl --user daemon-reload
    systemctl --user restart uptime
    
  3. 列出单元以检查 uptime.serviceuptime.timer 单元是否正在运行。

    systemctl --user list-units
    
  4. 监视日志中的日志输出,以便查看每分钟运行正常运行时间服务触发的正常运行时间输出。

    journalctl -f -t uptime
    

    几分钟之后,应显示多行输出。如果您十分关注,您可能会注意到 uptime 命令并非始终在分钟内触发。这是系统化计时器功能中的有意功能。计时器作业由一个随机器触发,该随机器允许任务延迟多达一分钟。这有助于防止计时器同时发生所有触发。通过将以下配置条目添加到计时器单元 Timer 部分,可以强制计时器具有不可思议的准确性,方法是在调度事件的纳秒内:

    AccuracySec=1us
    

    但是,对于大多数任务,允许某种程度的不准确性是明智的做法,可以防止任务太同步地运行。

    完成监视后,您可以使用 Ctrl-C 组合键退出日记账。

配置用户空间进程以在注销后继续

默认情况下,当用户注销或用户的所有会话都已终止时,由用户启动和拥有的服务和进程将终止。您可以使用多种方法在 systemd 中更改此默认行为。此处介绍了两个选项。

使用 loginctl 命令启用 systemd linger 用户

可以使用 loginctl 命令更改特定用户的缺省行为,并在用户会话终止后将该用户的进程启用到 "linger"。

  1. 使用 loginctl 实用程序为特定用户启用 linger。在此实例中,为“oracle”用户启用 systemd 锁定程序行为:

    sudo loginctl enable-linger oracle
    
  2. 要验证设置是否已应用,请检查 /var/lib/systemd/linger 目录中与用户同名的文件。

    ls /var/lib/systemd/linger/oracle
    

    该命令应验证该文件是否存在。

编辑 systemd logind.conf 文件

Systemd 管理用户登录事件并提供一个配置文件,可以对其进行编辑以设置与用户会话相关的不同事件的缺省行为。此配置文件位于 /etc/systemd/logind.conf

  1. 将位于 /etc/systemd/logind.conf 的现有配置的内容转储到屏幕以查看:

    cat /etc/systemd/logind.conf
    

    注释掉大部分选项,但显示编译时默认值。此文件中有三个选项,可以控制当用户的会话终止时,Systemd 处理在用户空间中运行的进程的方式。

    • KillUserProcesses:此选项可以控制用户进程在会话结束时是否默认终止。将此选项设置为“否”将允许在用户从系统注销后运行用户进程。
    • KillExcludeUsers:如果启用了 KillUserProcesses 选项,则此选项允许您指定一个以空格分隔的用户列表,该列表允许进程在会话终止后继续运行。将用户名添加到此列表的行为与使用 loginctl 命令将用户添加到 systemd linger 组的行为类似。
    • KillOnlyUsers:如果禁用了 KillUserProcesses 选项,则此参数可用于指定进程在注销后应终止的用户的空格分隔列表。

视频演示

如果需要有关在 Oracle Linux 8 上使用 systemd 的更多信息,可以在 https://www.youtube.com/watch?v=9uDvnZKhU8Ahttps://www.youtube.com/watch?v=Tkxs-wfZrnw 中提供 systemd 上的视频演示。

Oracle Linux 8 上的 systemd 系统和服务管理器

Oracle Linux 8 上的 systemd 目标单元

更多信息

更多学习资源

docs.oracle.com/learn 上浏览其他实验室,或者在 Oracle Learning YouTube 渠道上访问更多免费学习内容。此外,访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心