在 Red Hat Enterprise Linux 中控制服务

Red Hat Enterprise LinuxBeginner
立即练习

介绍

在本实验中,你将通过 systemctl 命令获得在 RHEL 上管理系统服务的实践经验。你将学会查看所有已加载和激活的服务,检查特定服务的状态,并通过启动、停止和重启来控制它们的运行时行为。此外,你还将探索如何重新加载服务配置,启用或禁用服务以便在启动时自动运行,并理解 masking 和 unmasking 服务以防止其激活的高级概念。

本实践指南将为你提供系统管理的基本技能,使你能够有效地监控和管理对你的 RHEL 系统运行至关重要的服务的生命周期。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 90%。获得了学习者 99% 的好评率。

使用 systemctl 查看所有已加载和活动的单元服务

在此步骤中,你将学习如何使用 systemctl 命令识别自动启动的系统进程。systemctl 是在 Red Hat Enterprise Linux 中管理 systemd 服务的首选工具。

首先,让我们探索如何列出所有当前已加载和激活的服务单元。systemctl list-units --type=service 命令用于此目的。此命令显示 systemd 守护进程已成功解析并加载到内存中,并且当前正在运行的服务单元。

在 RHEL 环境中打开你的终端。你已作为 labex 用户登录,当前目录是 ~/project

执行以下命令列出所有已加载和激活的服务单元:

systemctl list-units --type=service

你将看到类似以下的输出,显示各种服务及其状态:

UNIT                  LOAD    ACTIVE  SUB      DESCRIPTION
atd.service           loaded  active  running  Job spooling tools
auditd.service        loaded  active  running  Security Auditing Service
chronyd.service       loaded  active  running  NTP client/server
crond.service         loaded  active  running  Command Scheduler
dbus-broker.service   loaded  active  running  D-Bus System Message Bus
...output omitted...

让我们分解一下输出中的列:

  • UNIT: 这是服务单元的名称,通常以 .service 结尾。
  • LOAD: 指示 systemd 守护进程是否成功解析了单元的配置并将其加载到内存中。loaded 表示成功。
  • ACTIVE: 这是单元的高级激活状态。active 通常表示单元已成功启动。
  • SUB: 这是低级激活状态,提供更详细的信息。对于正在运行的服务,running 是常见的状态。
  • DESCRIPTION: 对服务功能的简要描述。

q 退出命令。

接下来,你可以将 --all 选项与 systemctl list-units --type=service 一起使用,以列出所有服务单元,无论其激活状态如何(active、inactive、failed 等)。这对于查看已安装但当前未运行的服务很有用。

执行以下命令:

systemctl list-units --type=service --all

输出将包括处于 inactive 或其他状态的服务,提供更全面的视图:

UNIT                          LOAD      ACTIVE   SUB     DESCRIPTION
  atd.service                 loaded    active   running Job spooling tools
  auditd.service              loaded    active   running Security Auditing ...
  auth-rpcgss-module.service  loaded    inactive dead    Kernel Module ...
  chronyd.service             loaded    active   running NTP client/server
  cpupower.service            loaded    inactive dead    Configure CPU power ...
  crond.service               loaded    active   running Command Scheduler
  dbus-broker.service         loaded    active   running  D-Bus System Message Bus
● display-manager.service     not-found inactive dead    display-manager.service
...output omitted...

最后,要查看 所有 已安装单元文件(包括未加载或未激活的)的状态,你可以使用 systemctl list-unit-files --type=service。此命令显示服务是 enabled(启动时启动)、disabled(启动时不启动)、static(不能直接启用但可能被其他单元启动)还是 masked(阻止启动)。

执行以下命令:

systemctl list-unit-files --type=service

你将看到类似以下的输出,指示每个服务单元文件的 STATEVENDOR PRESET

UNIT FILE                         STATE       VENDOR PRESET
arp-ethers.service                disabled    disabled
atd.service                       enabled     enabled
auditd.service                    enabled     enabled
auth-rpcgss-module.service        static      -
autovt@.service                   alias       -
blk-availability.service          disabled    disabled
...output omitted...

此命令特别有助于了解哪些服务配置为在系统启动时自动启动。

使用 systemctl status 检查特定服务的状态

在此步骤中,你将学习如何使用 systemctl status 命令检查特定服务的详细状态。此命令提供关于服务的全面信息,包括它是否正在运行、其进程 ID、内存使用情况以及最近的日志条目。

我们将以 crond.service(cron 守护进程)为例。cron 守护进程是一个处理计划任务的常用服务。

在 RHEL 环境中打开你的终端。确保你位于 ~/project 目录。

执行以下命令检查 crond.service 的状态:

systemctl status crond.service

你将看到类似以下的详细输出:

● crond.service - Command Scheduler
     Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; preset: enabled)
     Active: active (running) since Mon 2022-03-14 05:38:10 EDT; 25min ago
   Main PID: 1089 (crond)
      Tasks: 1 (limit: 35578)
     Memory: 1.2M
        CPU: 12ms
     CGroup: /system.slice/crond.service
             └─1089 /usr/sbin/crond -n

Mar 14 05:38:10 workstation systemd[1]: Started Command Scheduler.
Warning: some journal files were not opened due to insufficient permissions.

让我们检查输出中的关键字段:

  • Loaded: 此行告诉你服务单元的配置文件是否已被处理。它还显示了单元文件的路径(/usr/lib/systemd/system/crond.service)及其启用状态(enabled 表示它已配置为在启动时启动)。
  • Active: 这是关键。它指示服务的当前状态。active (running) 表示服务当前处于活动状态并且其进程正在运行。它还显示了它已激活多长时间。其他状态可能包括 inactive(未运行)、active (exited)(已完成一次性任务)或 failed(遇到错误)。
  • Main PID: 与服务关联的主进程的进程 ID (PID),以及命令名称。
  • Tasks: 服务当前使用的任务(线程)数量。
  • Memory: 服务正在消耗的内存量。
  • CPU: 服务消耗的 CPU 时间。
  • CGroup: 有关服务所属控制组的信息,用于资源管理。
  • CGroup 下方的行显示了与服务相关的最近日志条目,提供了对其启动和正在进行的活动的见解。

除了 systemctl status 之外,还有更简单的命令可以快速检查服务状态的特定方面:

  • 检查服务是否处于活动状态:

    systemctl is-active crond.service

    预期输出:

    active
  • 检查服务是否已启用(配置为在启动时启动):

    systemctl is-enabled crond.service

    预期输出:

    enabled
  • 检查服务是否失败:

    systemctl is-failed crond.service

    预期输出(如果正常运行):

    active

    如果服务在启动或运行时出现问题,此命令将返回 failed

这些命令对于脚本编写或在不需要 systemctl status 的完整详细输出时进行快速检查非常有用。

使用 systemctl 启动、停止和重启服务

在此步骤中,你将学习如何使用 systemctl 命令管理系统服务的生命周期。你将练习启动、停止和重启服务。在本实验中,我们将使用一个我们将创建的虚拟服务。这种方法确保我们可以安全地操作服务而不会影响关键的系统功能。

首先,让我们创建一个简单的服务单元文件。此文件将定义一个每隔几秒钟将时间戳写入日志文件的服务。

使用 nano 在 systemd 系统目录中直接创建一个名为 mytest.service 的新服务单元文件:

sudo nano /etc/systemd/system/mytest.service

将以下内容粘贴到 nano 编辑器中:

[Unit]
Description=My Test Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "$(date): My Test Service is running." >> /tmp/mytest.log; sleep 5; done'
ExecStop=/bin/bash -c 'echo "$(date): My Test Service stopped." >> /tmp/mytest.log'
Restart=on-failure

[Install]
WantedBy=multi-user.target
  • [Unit]: 包含关于单元的通用信息。Description 提供了一个人类可读的名称,而 After=network.target 指定此服务应在网络启动后启动。
  • [Service]: 定义了服务的行为。
    • Type=simple: 指示一种简单的服务类型,其中 ExecStart 命令是主进程。
    • ExecStart: 启动服务时要执行的命令。在这里,它是一个 bash 循环,每 5 秒将一个带时间戳的消息写入 /tmp/mytest.log
    • ExecStop: 停止服务时要执行的命令。它将停止消息写入日志。
    • Restart=on-failure: 配置服务在以非零状态退出时重新启动。
  • [Install]: 包含有关服务应如何安装的信息。WantedBy=multi-user.target 意味着此服务应在系统达到多用户运行级别时启动。

通过按 Ctrl+X,然后按 Y 确认,最后按 Enter 保存文件来保存文件。

现在,重新加载 systemd 守护进程以识别新的服务文件:

sudo systemctl daemon-reload

启动服务

要启动服务,请使用 systemctl start 命令。

执行以下命令启动 mytest.service。请注意,我们需要使用 sudo,因为 systemctl 操作通常需要 root 权限。

sudo systemctl start mytest.service

如果命令成功,将不会有立即的输出。

现在,通过检查其状态来验证服务是否正在运行:

systemctl status mytest.service

你应该看到指示服务为 active (running) 的输出:

● mytest.service - My Test Service
     Loaded: loaded (/etc/systemd/system/mytest.service; disabled; preset: disabled)
     Active: active (running) since ...
   Main PID: ... (bash)
      Tasks: 2 (limit: ...)
     Memory: ...
        CPU: ...
     CGroup: /system.slice/mytest.service
             ├─... /bin/bash -c "while true; do echo \"\$(date): My Test Service is running.\" >> /tmp/mytest.log; sleep 5; done"
             └─... sleep 5

...output omitted...

你还可以检查日志文件以查看服务是否正在写入消息:

tail -f /tmp/mytest.log

你应该看到每 5 秒出现新行,类似这样:

Tue Jul 22 09:15:09 AM CST 2025: My Test Service is running.
Tue Jul 22 09:15:14 AM CST 2025: My Test Service is running.

Ctrl+C 退出 tail

停止服务

要停止正在运行的服务,请使用 systemctl stop 命令。

执行以下命令停止 mytest.service

sudo systemctl stop mytest.service

同样,不会有立即的输出。

验证服务是否已停止:

systemctl status mytest.service

输出现在应显示 Active: inactive (dead)

○ mytest.service - My Test Service
     Loaded: loaded (/etc/systemd/system/mytest.service; disabled; preset: disabled)
     Active: inactive (dead) since ...
...output omitted...

再次检查日志文件 /tmp/mytest.log。你应该看到“My Test Service stopped.”消息,并且没有新的“running”消息出现。

tail /tmp/mytest.log

输出将类似这样:

Tue Jul 22 09:15:24 AM CST 2025: My Test Service is running.
Tue Jul 22 09:15:28 AM CST 2025: My Test Service stopped.

重启服务

要重启服务,请使用 systemctl restart 命令。此命令首先停止服务,然后再次启动它。当您对服务的配置进行了更改并需要这些更改生效时,此命令很有用。

执行以下命令重启 mytest.service

sudo systemctl restart mytest.service

验证服务是否再次运行:

systemctl status mytest.service

你应该再次看到 Active: active (running),并且 Main PID 可能会是一个新的数字,表明已启动一个新进程。

● mytest.service - My Test Service
     Loaded: loaded (/etc/systemd/system/mytest.service; disabled; preset: disabled)
     Active: active (running) since ...
   Main PID: ... (bash)
      Tasks: 2 (limit: ...)
     Memory: ...
        CPU: ...
     CGroup: /system.slice/mytest.service
             ├─... /bin/bash -c "while true; do echo \"\$(date): My Test Service is running.\" >> /tmp/mytest.log; sleep 5; done"
             └─... sleep 5
...output omitted...

检查日志文件 /tmp/mytest.log 以确认服务已恢复写入“running”消息。

tail -f /tmp/mytest.log

你应该看到一条“stopped”消息,后跟新的“running”消息:

Tue Jul 22 09:15:28 AM CST 2025: My Test Service stopped.
Tue Jul 22 09:15:40 AM CST 2025: My Test Service is running.

Ctrl+C 退出 tail

应用服务配置更改

在此步骤中,你将学习关于重新加载服务配置。一些服务可以在无需完全重启的情况下应用对其配置文件所做的更改。这被称为“重新加载”服务。重新加载通常比重启更受青睐,因为它避免了服务停机并保留了现有的连接或状态。当服务被重新加载时,其进程 ID (PID) 通常保持不变,这与完全重启(PID 会改变)不同。

我们将继续使用上一步中的 mytest.service。我们将修改它的行为,然后尝试重新加载它以查看会发生什么。

首先,确保 mytest.service 正在运行。如果未运行,请启动它:

sudo systemctl start mytest.service

验证其状态并记下其 Main PID

systemctl status mytest.service

现在,让我们修改 mytest.service 文件以更改它记录的消息和间隔。我们将修改日志消息和 sleep 持续时间。

使用 nano 打开 /etc/systemd/system/mytest.service

sudo nano /etc/systemd/system/mytest.service

ExecStart 行更改为以下内容,将消息和 sleep 时间从 5 秒修改为 2 秒:

[Unit]
Description=My Test Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "$(date): My Test Service (reloaded) is running." >> /tmp/mytest.log; sleep 2; done'
ExecStop=/bin/bash -c 'echo "$(date): My Test Service stopped." >> /tmp/mytest.log'
Restart=on-failure

[Install]
WantedBy=multi-user.target

通过按 Ctrl+X,然后按 Y,最后按 Enter 保存文件。

保存更改后,你需要通知 systemd 服务的配置已更改。

sudo systemctl daemon-reload

现在,让我们尝试重新加载服务以应用更改:

sudo systemctl reload mytest.service

你可能会遇到一个错误:

Failed to reload mytest.service: Job type reload is not applicable for unit mytest.service.

此错误发生是因为我们的简单服务未配置为处理重新加载请求。要使服务可重新加载,其单元文件必须包含 ExecReload 指令,该指令指定用于重新加载配置的命令。由于我们的 mytest.service 缺少此项,因此 systemd 不知道如何重新加载它。

在这种情况下,systemd 提供了一个方便的命令:reload-or-restart。此命令将尝试重新加载服务,但如果不支持重新加载,它将回退到重启服务。这通常是应用配置更改更安全、更有效的方法。

现在让我们使用 reload-or-restart

sudo systemctl reload-or-restart mytest.service

此命令应该会成功。现在,再次检查服务的状态:

systemctl status mytest.service

观察 Main PID。由于我们的服务被重启了(因为它无法被重新加载),你将注意到 Main PID 是一个 新的 数字。这证实了旧进程已被停止,并且一个新进程已启动并带有更新的配置。

最后,让我们检查 /tmp/mytest.log 文件,看看更改是否生效。

tail -f /tmp/mytest.log

你应该看到新的日志消息“My Test Service (reloaded) is running.”每 2 秒出现一次。按 Ctrl+C 退出 tail

使用 systemctl 设置服务开机自启和禁用

在此步骤中,你将学习如何配置服务以便在启动时自动启动(启用)或阻止它们在启动时启动(禁用)。这对于管理系统资源和确保系统启动时必需的服务可用至关重要。

在典型的 systemd 环境中,启用服务会在适当的 systemd 配置目录(例如 /etc/systemd/system/multi-user.target.wants/)中创建指向服务单元文件的符号链接。禁用服务会移除这些链接。

由于我们处于容器化环境中,systemd 在传统意义上可能无法完全运行,因此 enabledisable 命令可能不会在 /etc/systemd/system 目录中创建实际的符号链接,这些链接在容器重启后会持续存在。但是,systemctl 仍然会处理这些命令并更新其内部状态,这就是我们将要观察到的。

我们将继续使用我们的 mytest.service 进行此演示。

首先,确保 mytest.service 已从上一步停止:

sudo systemctl stop mytest.service

启用服务

要启用服务,请使用 systemctl enable 命令。此命令配置服务以便在系统启动时自动启动。

执行以下命令启用 mytest.service

sudo systemctl enable mytest.service

你可能会看到类似以下的输出,表明在完整的 systemd 环境中会创建一个符号链接:

Created symlink /etc/systemd/system/multi-user.target.wants/mytest.service → /etc/systemd/system/mytest.service.

现在,使用 systemctl is-enabled 验证服务是否已启用:

systemctl is-enabled mytest.service

预期输出:

enabled

这证实了 systemctl 现在认为 mytest.service 已被启用以在启动时运行。

你还可以使用 --now 选项将启用和启动服务合并为一个命令。这是一种方便的方式,可以确保服务立即运行并配置为在将来的启动时启动。

首先,让我们禁用它以准备 --now 演示:

sudo systemctl disable mytest.service

现在,同时启用并启动它:

sudo systemctl enable --now mytest.service

验证其状态和启用情况:

systemctl status mytest.service
systemctl is-enabled mytest.service

你应该从 status 命令看到 Active: active (running),从 is-enabled 命令看到 enabled

禁用服务

要禁用服务,请使用 systemctl disable 命令。此命令会移除导致服务在启动时启动的配置。

执行以下命令禁用 mytest.service

sudo systemctl disable mytest.service

你可能会看到指示移除符号链接的输出:

Removed /etc/systemd/system/multi-user.target.wants/mytest.service.

现在,验证服务是否已禁用:

systemctl is-enabled mytest.service

预期输出:

disabled

与启用类似,你可以使用 --now 选项将禁用和停止服务合并。这将立即停止服务,并阻止它在将来的启动时启动。

sudo systemctl disable --now mytest.service

验证其状态和启用情况:

systemctl status mytest.service
systemctl is-enabled mytest.service

你应该从 status 命令看到 Active: inactive (dead),从 is-enabled 命令看到 disabled

这结束了启用和禁用服务的演示。请记住,在真实的 systemd 环境中,这些命令会直接操作启动配置。

使用 systemctl 屏蔽和解除屏蔽服务

在此最终步骤中,你将学习关于屏蔽 (masking) 和取消屏蔽 (unmasking) 服务。屏蔽服务是一种强大的方式,可以阻止它被手动启动或在启动时自动启动。

当你屏蔽服务时,systemd 会在 /etc/systemd/system/<service-name>.service 创建一个指向 /dev/null 的符号链接,从而有效地使服务单元文件对 systemd 不可用。这是比 disable 更强大的替代方案。

此机制最适用于定义在 /usr/lib/systemd/system 中的服务,这是软件包安装其服务文件的位置。mask 命令会在 /etc/systemd/system 中创建一个覆盖性的“空”文件。但是,正如你所发现的,如果你尝试屏蔽一个直接在 /etc/systemd/system 中创建的服务(如我们的 mytest.service),该命令可能会失败,因为它设计为不覆盖现有配置文件,否则会导致数据丢失。

为了正确演示屏蔽,我们将使用一个预先存在的服务 atd.service

首先,让我们检查 atd.service 的当前状态。它应该是活动的并且已启用。

systemctl status atd.service

输出将与此类似,显示服务是活动的并且正在运行:

● atd.service - Deferred execution scheduler
     Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-07-22 09:13:06 CST; 22min ago
       Docs: man:atd(8)
   Main PID: 1222 (atd)
      Tasks: 1 (limit: 22509)
     Memory: 900.0K
        CPU: 5ms
     CGroup: /system.slice/atd.service
             └─1222 /usr/sbin/atd -f

屏蔽服务

在屏蔽服务之前停止它是一个好习惯。

sudo systemctl stop atd.service

现在,执行以下命令屏蔽 atd.service

sudo systemctl mask atd.service

你将看到指示创建指向 /dev/null 的符号链接的输出:

Created symlink /etc/systemd/system/atd.service → /dev/null.

现在,尝试启动被屏蔽的服务:

sudo systemctl start atd.service

你将收到一条错误消息,表明该服务已被屏蔽:

Failed to start atd.service: Unit atd.service is masked.

你还可以使用 systemctl list-unit-files 检查服务的状态:

systemctl list-unit-files --type=service | grep atd.service

输出应显示 atd.service 的状态为 masked

atd.service                            masked      enabled

这证实了该服务现在已被屏蔽,无法启动。

取消屏蔽服务

要取消屏蔽服务,请使用 systemctl unmask 命令。此命令会移除指向 /dev/null 的符号链接,从而从 /usr/lib/systemd/system 恢复原始服务文件。

执行以下命令取消屏蔽 atd.service

sudo systemctl unmask atd.service

你将看到指示移除符号链接的输出:

Removed "/etc/systemd/system/atd.service".

现在,再次使用 systemctl status atd.service 检查服务的状态:

systemctl status atd.service

你应该看到 Active: active (running),类似如下:

● atd.service - Deferred execution scheduler
     Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-07-22 09:36:10 CST; 2s ago
       Docs: man:atd(8)
   Main PID: 7372 (atd)
      Tasks: 1 (limit: 22509)
     Memory: 868.0K
        CPU: 6ms
     CGroup: /system.slice/atd.service
             └─7372 /usr/sbin/atd -f

这标志着关于控制服务和守护进程的实验结束了。你已经学会了如何使用 systemctl 查看、启动、停止、重启、重新加载、启用、禁用、屏蔽和取消屏蔽服务。

总结

在此次实验中,我们获得了使用 systemctl 命令管理控制系统服务的实践经验,即使是在 systemd 可能不是主要 init 系统的容器化环境中。我们学习了如何使用 systemctl list-units --type=service 列出所有已加载和活动的单元服务,并理解了 UNITLOADACTIVESUB 列以解释服务状态。

此外,我们还探索了重要的服务管理操作:使用 systemctl status 检查特定服务的状态,并通过启动、停止和重启服务来控制服务生命周期。我们还涵盖了如何重新加载服务配置,启用和禁用服务以控制其在启动时的行为,以及屏蔽和取消屏蔽服务以防止它们被启动的高级概念。这一套全面的技能为在 RHEL 系统上管理服务奠定了坚实的基础。