简介
本教程将指导你使用 systemctl daemon-reload 命令在 Linux 系统上管理系统守护进程和服务。Systemd 是大多数现代 Linux 发行版的默认服务管理器,了解如何正确更新服务配置是 Linux 用户和管理员的一项基本技能。
在这个实验中,你将学习何时以及为何使用 systemctl daemon-reload 命令,创建和修改服务文件,并在不影响系统运行的情况下应用配置更改。在本教程结束时,你将能够轻松地处理 systemd 服务并有效地应用配置更改。
本实验需要联网学习,因此只有 Pro 用户可以启动虚拟机。将你的账户升级为 Pro。
了解 systemd 和 systemctl 基础
Systemd 是大多数现代 Linux 发行版(包括我们在本实验中使用的 Ubuntu 22.04)的服务和系统管理器。它负责启动和管理系统服务,而 systemctl 是用于与 systemd 进行交互的主要命令行工具。
什么是系统守护进程?
守护进程是在你的 Linux 系统上持续运行的后台进程。这些进程执行各种任务,如提供网页服务(Apache、Nginx)、管理数据库(MySQL、PostgreSQL)或处理系统事件。Systemd 通过称为“单元文件”的标准化配置文件来管理这些守护进程。
基本的 systemctl 命令
让我们先探索一些基本的 systemctl 命令,以了解系统的当前状态:
通过点击“终端”图标打开一个终端。
使用以下命令列出所有活动的系统服务:
systemctl list-units --type=service

此命令会显示系统上所有当前活动的服务。你应该会看到类似以下的输出:
UNIT LOAD ACTIVE SUB DESCRIPTION
accounts-daemon.service loaded active running Accounts Service
apparmor.service loaded active exited AppArmor initialization
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
...
按 Ctrl+C 或 Q 退出命令。
- 检查特定服务的状态,例如 SSH 服务:
systemctl status ssh

你应该会看到有关 SSH 服务的详细信息,包括它是否处于活动状态、其进程 ID 和最近的日志条目:
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-06-13 12:34:56 UTC; 3h 25min ago
Docs: man:sshd(8)
man:sshd_config(5)
Process: 1234 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
Main PID: 1235 (sshd)
Tasks: 1 (limit: 4915)
Memory: 5.6M
CPU: 236ms
CGroup: /system.slice/ssh.service
└─1235 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
- 让我们看看 systemd 服务文件存储在哪里。这些是我们将在下一步中处理的文件:
ls -l /etc/systemd/system/
此目录包含定义 systemd 如何管理服务的服务单元文件。你应该会看到几个 .service 文件和符号链接。
- 系统提供的单元文件位于不同的目录中。让我们来查看一下:
ls -l /lib/systemd/system/
此目录包含系统自带的默认服务单元文件。
既然你已经了解了 systemd 的基础知识以及如何检查服务状态,那么下一步你就可以准备好创建和修改服务文件了。
创建一个简单的 systemd 服务文件
在这一步中,你将创建一个简单的 systemd 服务文件,该文件将运行一个自定义脚本。这将帮助你了解服务文件的工作原理以及如何对其进行修改。
创建一个简单的脚本
首先,让我们创建一个服务将运行的简单脚本:
- 为你的脚本创建一个目录:
mkdir -p ~/project/scripts
- 使用
nano文本编辑器创建一个简单的脚本:
nano ~/project/scripts/hello-service.sh
- 将以下内容添加到脚本中:
#!/bin/bash
while true; do
echo "Hello from custom service: $(date)" >> /tmp/hello-service.log
sleep 10
done
按 Ctrl+X 退出编辑器,然后按 Y 保存文件,再按 Enter 确认文件名。
此脚本只是每隔 10 秒将一条包含当前日期的消息写入一个日志文件。
- 使脚本可执行:
chmod +x ~/project/scripts/hello-service.sh
创建一个 systemd 服务单元文件
现在,让我们创建一个将运行此脚本的 systemd 服务文件:
- 使用
sudo权限创建一个新的服务文件:
sudo nano /etc/systemd/system/hello-service.service
- 将以下内容添加到服务文件中:
[Unit]
Description=Hello Service Demo
After=network.target
[Service]
Type=simple
ExecStart=/home/labex/project/scripts/hello-service.sh
Restart=on-failure
User=labex
[Install]
WantedBy=multi-user.target
让我们来了解一下这个文件的每个部分:
**[Unit]**:包含元数据和依赖项
Description:服务的人类可读描述After:指定此服务应在网络就绪后启动
**[Service]**:定义服务应如何运行
Type=simple:服务立即启动ExecStart:要运行的命令(我们的脚本)Restart:如果服务失败则自动重启服务User:以其身份运行服务的用户账户
**[Install]**:定义服务应在何时以及如何启用
WantedBy:指定服务应在何时启动(multi-user.target 表示正常系统操作)
保存文件并退出编辑器(在 nano 中按
Ctrl+X,然后按Y,再按Enter)。让我们查看一下新创建的服务文件:
cat /etc/systemd/system/hello-service.service
你应该会看到你刚刚添加到文件中的内容。

在下一部分中,你将学习如何使用 systemctl daemon-reload 命令加载并启动此服务。
使用 systemctl daemon-reload 来应用更改
既然你已经创建了一个 systemd 服务文件,你需要告知 systemd 有关这个新服务的信息。这就是 systemctl daemon-reload 命令发挥作用的地方。
什么是 systemctl daemon-reload?
systemctl daemon-reload 命令指示 systemd 重新加载所有服务文件并更新其内部配置。每当你:
- 创建一个新的服务文件
- 修改现有的服务文件
- 删除一个服务文件
时,都有必要运行此命令。如果不运行此命令,systemd 将无法识别你的更改。
重新加载 systemd 配置
- 运行以下命令来重新加载 systemd 配置:
sudo systemctl daemon-reload
此命令成功时不会产生任何输出,但它会更新 systemd 的内部配置。
- 现在让我们检查一下 systemd 是否识别我们的新服务:
systemctl status hello-service
你应该会看到输出显示该服务已加载但未激活:
● hello-service.service - Hello Service Demo
Loaded: loaded (/etc/systemd/system/hello-service.service; disabled; vendor preset: enabled)
Active: inactive (dead)
启动服务
- 让我们启动我们的服务:
sudo systemctl start hello-service
- 再次检查状态以查看它是否正在运行:
systemctl status hello-service

你现在应该会看到该服务已激活并正在运行:
● hello-service.service - Hello Service Demo
Loaded: loaded (/etc/systemd/system/hello-service.service; disabled; vendor preset: enabled)
Active: active (running) since [timestamp]; [time] ago
Main PID: [pid number] (hello-service.sh)
Tasks: 2 (limit: 4915)
Memory: 592.0K
CPU: 5ms
CGroup: /system.slice/hello-service.service
└─[pid number] /bin/bash /home/labex/project/scripts/hello-service.sh
- 通过检查它创建的日志文件来验证我们的服务是否真的在工作:
cat /tmp/hello-service.log
你应该会看到几行类似于以下的输出:
Hello from custom service: Wed Jun 14 15:30:45 UTC 2023
Hello from custom service: Wed Jun 14 15:30:55 UTC 2023
Hello from custom service: Wed Jun 14 15:31:05 UTC 2023
日志条目将显示当前日期和时间,确认我们的服务正在运行并按预期执行脚本。
- 启用该服务以便在系统启动时自动启动:
sudo systemctl enable hello-service
你应该会看到类似于以下的输出:
Created symlink /etc/systemd/system/multi-user.target.wants/hello-service.service → /etc/systemd/system/hello-service.service.
这意味着该服务现在已启用,并且在系统启动时将自动启动。
现在你已经成功创建了一个服务,使用 systemctl daemon-reload 告知了 systemd 有关它的信息,并启动了该服务。在下一部分中,你将修改该服务并应用更改。
修改服务配置
在这一步中,你将修改服务配置,并使用 systemctl daemon-reload 应用这些更改。这将展示在更新服务配置时此命令的重要性。
修改服务文件
让我们修改服务,以更改其记录消息的频率:
- 编辑服务文件:
sudo nano /etc/systemd/system/hello-service.service
- 在
[Service]部分添加一个新的环境变量,以控制睡眠间隔。在User=labex行之后添加此行:
Environment="SLEEP_INTERVAL=5"
保存并退出文件(在 nano 中按
Ctrl+X,然后按Y,再按Enter)。现在,编辑脚本以使用此环境变量:
nano ~/project/scripts/hello-service.sh
- 修改脚本以使用环境变量(用以下内容替换整个内容):
#!/bin/bash
## 如果未设置环境变量,则默认为10秒
INTERVAL=${SLEEP_INTERVAL:-10}
while true; do
echo "Hello from custom service: $(date) - Interval: ${INTERVAL}s" >> /tmp/hello-service.log
sleep $INTERVAL
done
- 保存并退出编辑器(在 nano 中按
Ctrl+X,然后按Y,再按Enter)。
应用更改
既然你已经对服务文件和脚本都进行了更改,就需要应用这些更改:
- 首先,重新加载 systemd 配置:
sudo systemctl daemon-reload
- 然后,重启服务以应用更改:
sudo systemctl restart hello-service
- 检查服务的状态:
systemctl status hello-service
你应该会看到服务正在使用更新后的配置运行。
- 通过检查日志文件来验证更改是否生效:
sleep 15 ## 等待收集一些日志条目
cat /tmp/hello-service.log | tail -5
现在你应该会看到服务每隔 5 秒记录一次消息,而不是 10 秒,并且日志条目应包含新的间隔信息:
Hello from custom service: Wed Jun 14 15:45:10 UTC 2023 - Interval: 5s
Hello from custom service: Wed Jun 14 15:45:15 UTC 2023 - Interval: 5s
Hello from custom service: Wed Jun 14 15:45:20 UTC 2023 - Interval: 5s

了解发生了什么
让我们来了解一下刚才发生了什么:
- 你修改了服务文件以添加一个环境变量。
- 你更新了脚本来使用此环境变量。
- 你运行
systemctl daemon-reload来告知 systemd 服务文件的更改。 - 你重启了服务以应用这些更改。
如果没有 systemctl daemon-reload 命令,systemd 将无法识别服务文件的更改,并且在重启服务时环境变量也不会传递给脚本。
这说明了为什么每当你修改服务文件时,systemctl daemon-reload 都是必不可少的——它确保在你尝试通过启动或重启服务来应用更改之前,systemd 能够了解你的更改。
故障排除与最佳实践
在这最后一步中,你将了解在使用 systemd 服务时可能出现的常见问题以及如何对其进行故障排除。你还将学习一些使用 systemctl daemon-reload 的最佳实践。
常见问题故障排除
1. 服务无法启动
如果你的服务无法启动,第一步是检查其状态:
systemctl status hello-service
这通常会提供详细的错误信息。让我们故意制造一个错误来看看如何进行故障排除:
- 编辑服务文件:
sudo nano /etc/systemd/system/hello-service.service
- 将
ExecStart行更改为指向一个不存在的脚本:
ExecStart=/home/labex/project/scripts/non-existent.sh
保存并退出编辑器。
重新加载 systemd 配置并尝试重启服务:
sudo systemctl daemon-reload
sudo systemctl restart hello-service
- 检查状态以查看错误:
systemctl status hello-service
你应该会看到表明脚本不存在的错误消息:
● hello-service.service - Hello Service Demo
Loaded: loaded (/etc/systemd/system/hello-service.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since [timestamp]; [time] ago
Process: [pid] ExecStart=/home/labex/project/scripts/non-existent.sh (code=exited, status=203/EXEC)
Main PID: [pid] (code=exited, status=203/EXEC)
CPU: 5ms
[timestamp] systemd[1]: Started Hello Service Demo.
[timestamp] systemd[pid]: hello-service.service: Failed to execute command: No such file or directory
[timestamp] systemd[pid]: hello-service.service: Failed at step EXEC spawning /home/labex/project/scripts/non-existent.sh: No such file or directory
[timestamp] systemd[1]: hello-service.service: Main process exited, code=exited, status=203/EXEC
[timestamp] systemd[1]: hello-service.service: Failed with result 'exit-code'.
- 将服务文件修复为指向正确的脚本:
sudo nano /etc/systemd/system/hello-service.service
- 将
ExecStart行改回:
ExecStart=/home/labex/project/scripts/hello-service.sh
- 保存并退出,然后重新加载并重启:
sudo systemctl daemon-reload
sudo systemctl restart hello-service
- 验证服务是否再次运行:
systemctl status hello-service
2. 读取日志以获取更多信息
在进行故障排除时,你可以使用 journalctl 来查看详细日志:
sudo journalctl -u hello-service
这将显示 hello-service 单元的所有日志,这对于诊断问题非常有价值。
要仅查看最近的日志:
sudo journalctl -u hello-service -n 20
要实时跟踪日志(类似于 tail -f):
sudo journalctl -u hello-service -f
按 Ctrl+C 退出日志跟踪模式。
使用 systemctl daemon-reload 的最佳实践
在使用 systemd 和 daemon-reload 命令时,以下是一些最佳实践:
更改后始终重新加载:在修改、添加或删除任何 systemd 单元文件后,始终运行
systemctl daemon-reload。应用前检查语法:在重新加载之前,你可以使用以下命令检查服务文件中的语法错误:
sudo systemd-analyze verify /etc/systemd/system/hello-service.service
如果没有错误,此命令不会产生任何输出。任何语法错误都会被报告。
使用服务模板:对于需要多个实例的服务,使用服务模板(文件名类似于
service@.service)以避免重复。检查服务依赖项:确保你的服务具有正确的
After=和Requires=指令,以确保它们按正确的顺序启动。正确清理:在删除服务时,确保在删除服务文件之前停止并禁用它:
sudo systemctl stop hello-service
sudo systemctl disable hello-service
sudo rm /etc/systemd/system/hello-service.service
sudo systemctl daemon-reload
现在让我们清理我们的示例服务:
sudo systemctl stop hello-service
sudo systemctl disable hello-service
你应该会看到表明符号链接已删除的输出:
Removed /etc/systemd/system/multi-user.target.wants/hello-service.service.
我们暂时不会删除服务文件,因为我们仍然需要它进行验证。
现在你了解了如何创建、修改和排除 systemd 服务的故障,以及 systemctl daemon-reload 命令在管理这些服务中的重要性。
总结
在本实验中,你已经学习了如何使用 systemctl daemon-reload 命令来管理 Linux 系统上的系统守护进程和服务。你已经:
- 了解了 systemd 和 systemctl 的基础知识
- 创建了一个自定义的 systemd 服务文件
- 使用 systemctl daemon-reload 将更改应用于服务配置
- 修改了服务文件并应用了这些更改
- 学习了如何对常见问题进行故障排除以及遵循最佳实践
systemctl daemon-reload 命令在使用 systemd 服务时至关重要,因为它可确保 systemd 管理器了解你对服务配置所做的任何更改。如果没有此命令,直到下次重启,系统才会识别你对服务文件所做的更改。
随着你继续使用 Linux 系统,这些知识将非常有用,使你能够有效地管理服务并确保你的配置更改得到正确应用。



