目录
本教程将由浅入深的介绍 linux 中 Systemd 的知识和相关使用(同时也方便自己后续查阅)
以下是对 “使用 systemctl 管理操作系统” 内容的完善和补充,包含常见操作场景、命令示例及说明:
六、使用 systemctl 管理操作系统
systemd 是 Linux 系统的系统和服务管理器,systemctl
作为其核心工具,不仅能管理服务(Service),还能实现系统状态查询、电源控制、日志管理、系统快照等高级操作。
6.1 系统操作:关机、重启、休眠与唤醒
# 立即关机(需 root)
systemctl poweroff
# 立即重启(需 root)
systemctl reboot
# 进入睡眠(S3 休眠,内存供电)
systemctl suspend
# 进入休眠(S4 休眠,数据写入硬盘,唤醒速度较慢)
systemctl hibernate
# 混合休眠(同时写入硬盘并保持内存供电,需内核支持)
systemctl hybrid-sleep
以上操作支持定时(某些旧的版本并不支持),例如
# 10 分钟后关机
systemctl poweroff --delay=600
# 2AM 执行重启
systemctl reboot --scheduled="02:00"
6.2 查看和操作当前系统运行目标(Target)
运行目标(Target)介绍
systemd 的 “运行目标” 像是一个系统启动时的 “开机剧本”。导演(systemd)按剧本(运行目标)喊开始,灯光组(网络服务)、道具组(数据库)、演员(图形界面)按顺序上台。
比如 “家庭影院剧本” 会先开投影仪(图形),再启动音响(声音服务);而 “省电剧本” 则只保留台灯(基础服务)。
我们知道 systemd 管理了非常多的功能,运行目标实际上可以定义其中一个功能的子集进行开机启动,并且这些开机启动的功能子集是已经定义好了依赖关系的。
运行目标替代了传统 Linux 系统中 System Vinit 的运行级别(Runlevel)。早期系统通过/etc/inittab定义runlevel 0-6(如 0 关机、3 文本模式、5 图形模式),而 systemd 通过更灵活的.target 文件(如multi-user.target对应传统 runlevel 3,graphical.target对应 runlevel 5)实现相同功能,同时支持更复杂的依赖管理和并行启动。
linux 常用的运行目标有:
- graphical.target(默认):启动图形界面,依赖 multi-user.target,加载显示管理器(如 GDM/KDM)和桌面环境服务;
- multi-user.target:多用户文本模式,启动网络、SSH、本地服务(如数据库),无图形界面;
- rescue.target:救援模式,挂载根目录为读写,启动键盘 / 磁盘 / 基础网络(如 SSH),允许多用户通过命令行修复系统(如修复磁盘坏道);
- emergency.target:紧急模式,仅激活内核和最小系统,根目录为只读,用于系统无法启动时的底层修复;
- shutdown.target:关机流程目标,负责终止所有用户进程,最终依赖 poweroff.target 或 halt.target 实现断电
此外,目标之前还可以创建类似于 依赖关系,根据依赖关系可以实现 “套娃式” 启动,例如
graphical.target → multi-user.target → basic.target → sysinit.target
用户还可根据需求自定义运行目标,实现特定场景的服务组合(如嵌入式设备定制启动、服务器专项功能子集等),在这里就不进行展开介绍了。
命令
使用 systemctl 操作运行目标的常用命令如下:
# 显示当前目标(如 graphical.target、multi-user.target)
systemctl get-default
# 设置默认运行目标
systemctl set-default <target>
# 查看所有的运行目标
systemctl list-targets # 不知道为什么我找了好几个系统这个命令都不成功???
systemctl list-units --all --type=target
# 临时切换运行目标,非破坏性的
systemctl start <target>
# 切换至指定目标,破坏性的(终止所有与目标无关的服务)
systemctl isolate <target>
# 兼容传统运行级别(如 runlevel 3 对应 multi-user.target)
systemctl telinit 3 # 等价于 systemctl isolate multi-user.target
6.3 系统状态查询与分析
systemctl status
输出如下
● xxx
State: degraded
Jobs: 0 queued
Failed: 5 units
Since: Thu 2025-04-03 02:02:15 UTC; 1 week 4 days ago
CGroup: /
├─user.slice
│ ├─user-1001.slice
│ │ ├─session-126.scope
│ │ │ ├─2529035 sudo su
│ │ │ ├─2529747 sudo su
│ │ │ ├─2529748 su
│ │ │ ├─2529749 bash
│ │ │ └─2618301 vppctl
│ │ └─user@1001.service
... (更多内容)
输出的字段解释如下:
State
系统运行状态
- degraded
- 含义:系统功能部分受损,至少有一个关键单元(如服务、设备)失败,但系统仍可运行。
- 典型场景:多个非关键服务失败(如用户输出中 5 个服务失败),系统未完全崩溃。
- running
- 含义:系统完全正常,所有关键单元处于活动状态(active)。
- 典型场景:正常运行的服务器,无任何失败单元。
- rescue
- 含义:系统进入救援模式,仅启动最低限度服务(如 shell),用于手动修复故障。
- 典型场景:根文件系统损坏、关键服务启动失败,需通过救援模式修复。
- emergency
- 含义:系统进入紧急模式,仅启动内核和基本驱动,几乎无法进行常规操作。
- 典型场景:内核 panic、严重硬件故障或关键系统文件丢失,需强制恢复。
- rebooting
- 含义:系统正在执行重启操作(短暂过渡状态,稳定输出中较少显示)。
- 典型场景:用户执行 reboot 命令后,系统处于重启过程中。
Jobs
systemd 每次动作都会有相应的 Job,例如当执行 systemctl start httpd.service
时,会生成一个 start 类型的 Job,任务完成后(服务启动成功或失败),该 Job 会被自动清除(任务完成后默认保留 10秒 即自动清除,非永久记录)。
这里整理了 systemctl status
中 Jobs
字段的 6 种典型输出场景:
1. 输出:Jobs: 0 queued
- 含义:当前无排队或执行中的 systemd 任务,系统处于稳定状态。
- 排查建议: 无需操作,重点观察
State
和Failed
字段确认系统健康(若State
为degraded
,需排查Failed
单元)。 - 补充说明: 此状态是系统无活跃任务的标志,但不排除历史故障(需结合
Failed
判断)。
2. 输出:Jobs: 1 running
- 含义:有一个任务正在执行(如启动/停止服务),可能阻塞或超时。
- 典型场景:
- 服务启动超时(如
httpd.service
因配置错误卡住,超过默认 90秒 超时阈值)。 - 系统启动初期,关键服务正在加载(如内核模块、文件系统挂载)。
- 服务启动超时(如
- 排查建议:
- 执行
systemctl list-jobs
查看任务详情(如JOB 1 httpd.service start running
)。 - 通过
journalctl -u <单元名>
追踪日志,定位阻塞原因(如依赖缺失、资源不足)。
- 执行
- 补充说明:
- 超时阈值可通过修改单元配置调整(如
systemctl edit httpd.service
中添加TimeoutStartSec=300
)。 - 任务持续超过 10分钟 可能触发
State: degraded
,需人工干预。
- 超时阈值可通过修改单元配置调整(如
3. 输出:Jobs: 2 queued
- 含义:多个任务按依赖顺序排队等待执行(后序任务需前序任务完成)。
- 典型场景:
- 批量操作服务(如
systemctl restart *.service
),任务按依赖关系排序。 - 依赖链过长(如
A.service
依赖B.service
,B
未启动导致A
排队)。
- 批量操作服务(如
- 排查建议:
- 用
systemctl list-jobs --all
查看任务队列顺序(如JOB 1 B.service start queued → JOB 2 A.service start queued
)。 - 通过
systemctl show -p After= <单元名>
检查依赖配置(After=
表示该服务在谁之后启动)。
- 用
- 补充说明:
- 排队是 systemd 的正常调度行为,不影响系统性能,无需过度干预。
- 依赖关系定义在单元文件中(如
/etc/systemd/system/A.service
中的After=B.service
)。
4. 输出:Jobs: 0 queued
+ State: degraded
- 含义:任务已执行完毕(成功或失败),但至少有一个单元失败,导致系统功能退化。
- 典型场景:
- 服务启动失败后,任务自动清除,但失败单元未修复(如
nginx.service
因端口被占用启动失败)。 - 手动终止任务后,残留的失败单元未恢复(如配置错误未修正)。
- 服务启动失败后,任务自动清除,但失败单元未修复(如
- 排查建议:
- 执行
systemctl list-failed
列出所有失败单元(如nginx.service
)。 - 用
journalctl -u <单元名> -b
查看本次启动日志(-b
表示当前启动会话)。
- 执行
- 补充说明:
Jobs
不记录历史失败,仅Failed
字段标记异常单元,需优先排查此处。- 修复后需重启失败单元(如
systemctl restart nginx.service
)或重载配置。
5. 输出:Jobs: 1 running (deadline exceeded)
- 含义:任务执行时间超过 自定义超时阈值(非默认90秒),进入“超时运行”状态。
- 典型场景:
- 服务代码存在死循环,无法正常退出(如程序逻辑错误)。
- 硬件故障导致 I/O 延迟(如磁盘损坏、网络中断)。
- 排查建议:
- 尝试优雅终止任务:
systemctl kill --signal=SIGINT <单元名>
(发送中断信号)。 - 若无效,强制终止:
systemctl kill --signal=SIGKILL <单元名>
,并检查进程状态(ps -ef | grep <单元名>
)。
- 尝试优雅终止任务:
- 补充说明:
- 该状态需人工干预,不会自动恢复,需修复代码或硬件问题。
- 可临时延长超时时间(仅推荐测试环境):
systemctl edit <单元名>
中添加TimeoutStartSec=5min
。
6. 输出:Jobs: 0 queued
+ State: rebooting
- 含义:系统正在执行重启操作,任务队列已清空(短暂过渡状态,极少在稳定输出中显示)。
- 典型场景:
- 用户执行
reboot
或systemctl reboot
命令后,系统进入重启流程。
- 用户执行
- 排查建议:
- 无需操作,等待重启完成即可(若需取消,在倒计时内执行
shutdown -c
)。
- 无需操作,等待重启完成即可(若需取消,在倒计时内执行
- 补充说明:
- 重启时 systemd 会强制清空 Jobs,避免未完成任务干扰重启过程。
- 该状态持续时间极短(通常 <10秒),属正常现象。
Failed
指示了有多少 units 执行失败了,如果需要排查哪些单元失败了,执行如下命令查看失败的单元
systemctl --failed
# 或者
systemctl list-units --all --state=failed
结合 journalctl
命令查看具体失败日志,结合 systemctl cat
命令查看服务配置,综合这些信息来排查服务失败原因(可以将输出给 AI,自己排查太难了)
Since
系统进入当前状态(如 degraded)的时间
CGroup
/
及其子层级表示 系统进程的资源隔离结构,用于追踪进程归属和资源使用
6.4 查看系统启动耗时分析
通过以下命令可以分析启动耗时,优化系统启动时间
# 总启动时间
systemd-analyze
# 各阶段启动耗时(固件/引导加载器/内核/用户空间)
systemd-analyze blame
# 可视化启动时间分布(需图形界面支持)
systemd-analyze plot > boot-time.svg
6.5 系统快照与紧急模式
systemd 快照主要用于恢复 systemd 管理的状态,而非磁盘快照。
分类 | 回滚范围 | 典型场景 |
---|---|---|
systemd 管理的状态 | 服务、挂载、资源限制等运行时配置 | 服务误停、cgroups 配置混乱 |
非管理的状态 | 文件内容、用户进程、硬件状态等 | 文件误删、手动进程崩溃 |
# 创建系统运行时快照(保存当前服务状态)
systemctl snapshot my-snapshot
# 从快照恢复(需在 emergency/rescue 模式下执行)
systemctl revert my-snapshot
在系统运行出现严重异常时,紧急模式(Emergency Mode)是一种极简的故障恢复环境。它仅启动维持基本系统运行的最小服务集合(如必要的内核模块、终端驱动和 shell)
# 进入恢复模式(Rescue Mode,仅启动基本服务,允许 root 登录)
systemctl rescue
# 进入紧急模式(Emergency Mode,仅启动最小必要服务,仅支持 shell)
systemctl emergency
6.6 替代传统 cron:使用 systemd 定时任务
可以通过 systemd.timer
管理定时任务(替代传统 cron)
利用 systemd 创建的定时器,需要两个配置文件,即 xxx.service
和 xxx.timer
,systemd 将自动将二者建立关联关系。
xxx.service
:用于配置这个定时任务要执行的具体工作,和其他服务定义没有明显差别,类型比较适合oneshot
(比较适合,推荐) 或者simple
xxx.timer
:定义执行计划
timer 单元配置的要点
[Timer]
选项OnCalendar
:指定执行计划,例如Daily 03:00
(每天三点) 或者*-*-* *:00
(整点)OnUnitActiveSec
:基于上次执行完成时间的相对时间设定执行计划,类似于传统的每隔多少秒(支持秒、分钟、小时、天等时间单位)OnStartupSec
:系统启动后多长时间执行(支持秒、分钟、小时、天等时间单位)RandomizedDelaySec
:触发时间随机偏移(避免大量任务同时执行)AccuracySec
:允许的触发时间误差(减少 CPU 唤醒频率)Persistent
:错过触发时是否补执行(例如关机造成错过执行计划),默认情况下 Persistent=noUnit
:如果 timer 和 service 的名字不一样,可以通过这个配置显示的指定绑定的服务
WantedBy=timers.target
timer 的常见操作(启停、状态查询等)和其他单元的操作类似,这里不做赘述,示例:
# 列出所有定时器
systemctl list-timers
# 启用(开机启动)并启动一个定时器
systemctl enable --now my-cleanup.timer
Calendar 的具体格式
可以通过命令 man systemd.time
查看,我截取了比较有用的一些如下
The following special expressions may be used as shorthands for longer normalized forms:
minutely → *-*-* *:*:00
hourly → *-*-* *:00:00
daily → *-*-* 00:00:00
monthly → *-*-01 00:00:00
weekly → Mon *-*-* 00:00:00
yearly → *-01-01 00:00:00
quarterly → *-01,04,07,10-01 00:00:00
semiannually → *-01,07-01 00:00:00
Examples for valid timestamps and their normalized form:
Sat,Thu,Mon..Wed,Sat..Sun → Mon..Thu,Sat,Sun *-*-* 00:00:00
Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00
Wed *-1 → Wed *-*-01 00:00:00
Wed..Wed,Wed *-1 → Wed *-*-01 00:00:00
Wed, 17:48 → Wed *-*-* 17:48:00
Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03
*-*-7 0:0:0 → *-*-07 00:00:00
10-15 → *-10-15 00:00:00
monday *-12-* 17:00 → Mon *-12-* 17:00:00
Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45
12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00
12..14:10,20,30 → *-*-* 12..14:10,20,30:00
mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45
03-05 08:05:40 → *-03-05 08:05:40
08:05:40 → *-*-* 08:05:40
05:40 → *-*-* 05:40:00
Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40
Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40
2003-03-05 05:40 → 2003-03-05 05:40:00
05:40:23.4200004/3.1700005 → *-*-* 05:40:23.420000/3.170001
2003-02..04-05 → 2003-02..04-05 00:00:00
2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC
2003-03-05 → 2003-03-05 00:00:00
03-05 → *-03-05 00:00:00
hourly → *-*-* *:00:00
daily → *-*-* 00:00:00
daily UTC → *-*-* 00:00:00 UTC
monthly → *-*-01 00:00:00
weekly → Mon *-*-* 00:00:00
weekly Pacific/Auckland → Mon *-*-* 00:00:00 Pacific/Auckland
yearly → *-01-01 00:00:00
annually → *-01-01 00:00:00
*:2/3 → *-*-* *:02/3:00
可以通过如下命令,校验一个 Calendar 配置是否合法
systemd-analyze calendar "Daily 03:00"