精通 systemctl:Linux 服务管理必备命令
掌握 systemd 下 Linux 服务管理的核心 `systemctl` 命令。本指南详细介绍了启动、停止、重启、启用和禁用服务的基本语法,以及关键状态检查和利用 `journalctl` 进行高级故障排除。立即实现高效可靠的系统管理。
精通 systemctl:Linux 服务管理必备命令
如果你操作 Linux 服务器,你会经常使用 systemctl。当 Nginx 无法启动时、PostgreSQL 需要在重启后启动时、部署需要完全重启时,以及服务显示“失败”但真正错误隐藏在日志中时,你都会用到它。
这个命令并不难,但有一些重要的区别:启动不等于启用,重新加载不等于重启,禁用不等于屏蔽。一旦这些概念清晰,服务管理就会变得不那么神秘。
理解 systemd 和 systemctl
systemd 是许多主流 Linux 发行版使用的初始化系统和服务管理器,包括常见的 Debian、Ubuntu、Fedora 和 RHEL 系列版本。它初始化用户空间并管理进程、会话、定时器、套接字、挂载和服务。
systemctl 是用于控制和检查 systemd 管理器及其组件(单元)状态的主要命令行工具。服务,即在后台运行的程序(守护进程),作为服务单元(通常以 .service 结尾)进行管理。
关键概念:单元和目标
虽然本文重点介绍服务,但请记住 systemctl 管理各种单元:
- 服务单元 (
.service):用于管理后台进程(例如nginx.service)。 - 目标单元 (
.target):用于将单元分组以表示特定的系统状态(例如multi-user.target,代表典型的服务器环境)。
服务控制的基本命令(运行时状态)
这些命令直接控制服务在当前系统会话中是正在运行还是已停止。
1. 启动服务
使用 start 命令立即启动服务,无论其启动配置如何。
sudo systemctl start <service_name>.service
# 示例:启动 Apache Web 服务器
sudo systemctl start apache2.service
2. 停止服务
使用 stop 命令优雅地终止正在运行的服务。
sudo systemctl stop <service_name>.service
# 示例:停止 MySQL 数据库服务
sudo systemctl stop mariadb.service
3. 重启服务
这在配置文件更改后常用。它会停止服务,然后立即重新启动。
sudo systemctl restart <service_name>.service
# 示例:重启 SSH 守护进程
sudo systemctl restart sshd.service
4. 重新加载配置
许多服务支持重新加载操作,它可以在不中断现有连接或完全停止进程的情况下应用新的配置文件。这比完全重启更快,破坏性更小。
sudo systemctl reload <service_name>.service
# 示例:重新加载 Nginx 配置
sudo systemctl reload nginx.service
提示: 始终检查服务文档。如果服务不支持
reload,则在配置更改后必须使用restart。
服务持久性的基本命令(启动状态)
启动服务使其现在运行,而启用或禁用服务则控制它是否在系统启动时自动启动。
1. 启用服务
要确保服务在重启后自动启动,必须启用它。这会在 systemd 配置目录(/etc/systemd/system/)中创建必要的符号链接。
sudo systemctl enable <service_name>.service
# 示例:启用 PostgreSQL 在启动时启动
sudo systemctl enable postgresql.service
2. 禁用服务
要阻止服务在启动时自动启动,必须禁用它。这会移除 enable 命令创建的符号链接。
sudo systemctl disable <service_name>.service
# 示例:在服务器上禁用蓝牙服务
sudo systemctl disable bluetooth.service
3. 屏蔽服务
屏蔽单元可防止其手动、自动或通过依赖关系启动。当“不要启动此服务”需要比 disable 更强时使用它。
sudo systemctl mask <service_name>.service
# 要取消屏蔽:
sudo systemctl unmask <service_name>.service
检查服务状态和信息
了解服务是否正在运行以及为什么可能失败对于故障排除至关重要。
1. 检查状态
status 命令提供详细、即时的服务快照,包括是否活动、已加载、其进程 ID 以及最近的日志条目。
systemctl status <service_name>.service
# 示例:检查防火墙状态
systemctl status firewalld.service
解释输出:
在输出中查找三个关键行:
- Loaded: 显示单元文件是否已正确加载(例如
loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled))。 - Active: 显示当前运行时状态(例如
active (running)或failed)。 - CGroup: 显示与服务关联的进程树。
2. 查询启动持久性
无需检查完整的状态输出,即可检查服务是否配置为自动启动:
systemctl is-enabled <service_name>.service
# 输出将为 'enabled'、'disabled' 或 'masked'
3. 使用 journalctl 查看日志
虽然 status 显示最后几行输出,但对于深入调试,必须使用 journalctl。此命令查询 systemd 日志,该日志收集所有系统和服务的日志。
要查看特定服务的日志:
# 查看自上次重启以来该服务的所有日志
journalctl -u <service_name>.service
# 实时查看日志(类似于 tail -f)
journalctl -u <service_name>.service -f
# 查看自昨天以来的日志
journalctl -u <service_name>.service --since "yesterday"
警告: 如果服务显示
failed状态,journalctl -u <service> -r(反向顺序,最新显示在最前)通常是查看导致失败的错误消息的最快方法。
4. 在脚本中检查服务是否正在运行
对于 shell 脚本,systemctl status 过于冗长。请使用查询命令:
systemctl is-active --quiet nginx.service
echo $?
systemctl is-failed nginx.service
systemctl is-enabled nginx.service
is-active --quiet 返回有用的退出状态,而无需打印完整的状态页面。这使其更适合健康检查和自动化。
if ! systemctl is-active --quiet nginx.service; then
echo "nginx 未运行" >&2
exit 1
fi
5. 列出单元
当不知道确切的服务名称时,列出单元:
systemctl list-units --type=service
systemctl list-units --type=service --state=failed
systemctl list-unit-files --type=service
list-units 显示已加载的单元及其当前运行时状态。list-unit-files 显示单元文件以及它们是否已启用、禁用、静态、屏蔽或生成。这种区别解释了为什么服务可以存在于磁盘上,但不会出现在活动单元列表中。
管理系统状态(目标)
systemctl 也用于管理全局系统状态,主要通过目标。
1. 查看当前系统状态
要查看系统当前启动到的目标(例如服务器环境或图形桌面):
systemctl get-default
2. 更改默认启动目标
如果你正在配置一个永远不应启动 GUI 的服务器,可以将默认目标设置为 multi-user.target:
sudo systemctl set-default multi-user.target
3. 重启和关机
虽然 reboot 和 shutdown 命令仍然有效,但 systemctl 提供了执行这些操作的原生方式:
# 立即重启系统
sudo systemctl reboot
# 关闭系统(断电)
sudo systemctl poweroff
单元更改后重新加载 systemd
当你编辑单元文件或在 /etc/systemd/system 下添加 drop-in 文件时,systemd 不会自动重新读取它。运行:
sudo systemctl daemon-reload
然后重启或重新加载受影响的 service:
sudo systemctl restart myapp.service
要在供应商文件和 drop-in 文件合并后检查最终单元:
systemctl cat myapp.service
systemctl show myapp.service -p FragmentPath -p DropInPaths
这是捕获“我编辑了错误的文件”问题的最快方法之一。
真实的故障排除流程
当服务启动失败时,按此顺序操作:
- 检查状态:
systemctl status myapp.service
- 读取该单元的日志:
journalctl -u myapp.service -r
- 如果你最近编辑了服务文件,请重新加载 systemd:
sudo systemctl daemon-reload
- 再次启动并实时跟踪日志:
sudo systemctl restart myapp.service
journalctl -u myapp.service -f
- 如果立即失败,请检查单元定义:
systemctl cat myapp.service
systemctl show myapp.service -p ExecStart -p User -p WorkingDirectory
大多数失败都是普通的:ExecStart 中的路径错误、缺少环境文件、权限问题、工作目录错误、端口已被占用或应用程序本身的配置语法错误。
启动、启用、重启、重新加载:心智模型
这四个动词很容易混淆:
start更改当前运行时状态。enable更改启动行为。restart停止并启动进程。reload要求现有进程重新读取配置(如果服务支持)。
例如,安装 Nginx 后:
sudo systemctl start nginx.service
sudo systemctl enable nginx.service
第一个命令现在启动它。第二个命令使其在重启后启动。如果你只运行 start,服务可能会在下次重启后消失。如果你只运行 enable,它可能要到下次重启才会运行,除非该单元具有特殊的安装行为。
编辑 Nginx 配置后,先测试应用程序配置,然后重新加载:
sudo nginx -t
sudo systemctl reload nginx.service
如果应用程序不支持重新加载,请使用重启并计划中断:
sudo systemctl restart myapp.service
更安全地使用屏蔽
屏蔽很有用,但它可能会让下一个尝试启动服务的人感到困惑。
sudo systemctl mask bluetooth.service
systemctl is-enabled bluetooth.service
服务报告为 masked。要撤消它:
sudo systemctl unmask bluetooth.service
在明确冲突的情况下使用屏蔽,例如在替换旧服务后阻止其启动。对于正常的“不要在启动时启动”行为,请使用 disable。
以可维护的方式编辑单元
当你需要更改打包的服务时,避免直接编辑 /usr/lib/systemd/system 或 /lib/systemd/system 下的文件。软件包升级可能会替换这些文件。使用覆盖:
sudo systemctl edit myapp.service
这会在 /etc/systemd/system/myapp.service.d/ 下创建一个 drop-in 文件。例如:
[Service]
Environment=APP_ENV=production
Restart=on-failure
RestartSec=5s
然后应用它:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
如果以后需要删除覆盖,请先检查 drop-in 文件:
systemctl show myapp.service -p DropInPaths
然后删除特定的 drop-in 文件并运行 daemon-reload。这使本地更改保持可见且更易于审计。
用户服务
并非所有服务都是系统服务。桌面工具、开发守护进程和每个用户的后台进程可以在用户管理器下运行:
systemctl --user status pipewire.service
systemctl --user restart my-user-job.service
用户服务不以相同的方式使用 sudo,并且它们存在于用户的 systemd 实例中。如果命令使用 systemctl --user 有效,但使用普通 systemctl 无效,那么你正在查看的是用户单元,而不是系统单元。
对于服务器上长时间运行的用户服务,登录/会话行为可能很重要。某些发行版需要 lingering 才能在用户注销后保持其服务运行:
loginctl enable-linger deploy
有目的地使用它。用户服务可以是开发或用户范围自动化的正确工具,但生产守护进程通常更明确地作为具有显式用户和权限的系统服务。
基本 systemctl 命令总结
| 操作 | 命令语法 | 目的 |
|---|---|---|
| 立即启动 | sudo systemctl start name.service |
立即运行服务。 |
| 立即停止 | sudo systemctl stop name.service |
终止正在运行的服务。 |
| 重启 | sudo systemctl restart name.service |
停止然后启动服务。 |
| 重新加载 | sudo systemctl reload name.service |
应用配置更改而无需完全重启(如果支持)。 |
| 启用 | sudo systemctl enable name.service |
配置服务在启动时启动。 |
| 禁用 | sudo systemctl disable name.service |
阻止服务在启动时启动。 |
| 状态 | systemctl status name.service |
检查运行时状态和最近的日志。 |
| 查看日志 | journalctl -u name.service |
访问该服务的完整 systemd 日志历史记录。 |
这些命令涵盖了大多数日常服务工作。启动和停止控制当前进程。启用和禁用控制启动行为。状态、is-active 和 journalctl 告诉你发生了什么。daemon-reload 使 systemd 与单元文件编辑保持同步。当你将这些角色分开时,systemctl 就变成了一个实用的故障排除工具,而不是一个从旧笔记中复制的命令。