在 Red Hat Enterprise Linux 中控制服务

红帽企业 LinuxBeginner
立即练习

介绍

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

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

使用 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 结合使用,以列出所有服务单元,无论其激活状态如何(活动、非活动、失败等)。这对于查看已安装但当前未运行的服务非常有用。

执行以下命令:

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

将配置更改应用于服务

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

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

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

sudo systemctl start mytest.service

验证其状态并记下其 Main PID

systemctl status mytest.service

现在,让我们修改 mytest.service 文件以更改其记录的消息和间隔。我们将更改日志消息并将 sleep 持续时间从 5 秒更改为 2 秒。

使用 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,然后按 YEnter 保存文件。

保存更改后,你需要通知 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 | tee ~/project/atd-mask-state.txt

输出应该显示 atd.servicemasked

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".

取消屏蔽后,再次启动服务,因为 unmask 仅删除 /dev/null 链接,不会为你重启服务。

sudo systemctl start 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 可能不是主要初始化系统的容器化环境中也是如此。我们学习了如何使用 systemctl list-units --type=service 列出所有已加载和活动的服务单元,并理解了 UNITLOADACTIVESUB 列以解释服务状态。

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