Systemd 学习总结

儿时练功易,老来学艺难。

导航


0、前言

当我们打开 Linux 主机以命令行模式或图形化模式进入系统之后,系统就已经为我们提供了很多的服务,如:打印服务、计划任务服务、邮件服务等等,那么这些服务是如何被启动起来的呢?在此之前我们先了解一下 Linux 主机的启动过程

boot

  1. 点击主机开机按钮,CPU 开始加载固件程序(即 BIOS 上电自检),待加载完毕之后 BIOS 便获得了 CPU 的控制权,然后 BIOS 会去加载开机启动顺序中指定的系统入口点(安装系统的光驱、硬盘的入口点)。
  2. 待 BIOS 加载了入口点处的引导装载程序 (GRUB2)之后,CPU 控制权此时便到了 GRUB2 的手里,GRUB2 接着开始加载硬盘中安装的 Linux 内核。
  3. 待 Linux 内核初始化完成之后,CPU 的控制权此时便到了 Linux 内核手中,往后 CPU 的控制权便一直掌握在 Linux 内核手中。
  4. 但 Linux 内核对于用户来说并不可直接被使用、而且也并未提供什么功能,于是它又雇佣了一个管家(init、systemd)并授予了一些权利,来代替它去做一些系统管理的事情。而这个管家便是 Linux 内核掌权之后启动的第一个外部程序,也是未来所有其它进程之父。

早期 各 Linux 发行商为自家 Linux 内核配备的管家是 init 这个程序,该管家的特点是:(1)基于脚本式的方式去管理服务,服务的启动/停止/状态查看都是通过 /etc/init.d/ 下的 bash 脚本来实现的。(2)开机启动各种服务的时候,只能一个一个依序进行,不能够并行启动。(3)服务之间的依赖问题需要管理员手动处理。(4)系统环境切换依赖于 /etc/rc*.d/ 中的脚本。

如今 各 Linux 发行商为自家 Linux 内核配备的管家基本都是 systemd 这个程序,该管家的特点是:(1)基于配置文件(服务单位 Unit )的方式去管理服务,服务的管理更灵活、更简单。(2)支持并行启动开机自启应用。(3)服务之间的依赖会自动检查,并自动唤醒。(4)兼容旧有的 init 服务脚本启动方式。

由于如今的 Linux 使用的服务管理方式多是 Systemd,因此学会它还是很有必要的。

注:Linxu 内核启动的第一个程序是 systemd,而 systemd 启动的第一个服务单元是 default.target,它一般被命令 systemctl set-default multi-user.target 链接到了 multi-user.target 或 graphical.target。

当 systemd 启动任何服务单元 Unit 文件的时候,systemd 首先去启动参数 Requires 和目录 /etc/systemd/system/a.target.requires/ 关联的服务,然后再开始启动参数 Wants 和目录 /etc/systemd/system/a.target.want/ 关联的服务。

systemd 找寻 default.target 单元文件时的目录查找顺序:

/etc/systemd/system/default.target
  ↓
/run/systemd/system/default.target
  ↓
/usr/local/lib/systemd/system/default.target
  ↓
/usr/lib/systemd/system/default.target
  ↓
/lib/systemd/system/default.target

1、工具介绍

Systemd 是基于服务单位 Unit 来管理守护进程和系统资源的,它将这些服务单位 Unit 划分成了 service、target、timer、path、socket 等 12 种不同的类型,每种类型分别对应着不同的功能和应用场景以方便管理员使用。此外,Systemd 还维护着一个名为 journald 的日志系统来记录它所管理的服务在运行时产生的各种日志信息。

jiagou

如图所见,Systemd 在 Linux 系统中的地位很重要,因为它必须确保系统启动并准备就绪,所以它承担的事情也比较多,例如:

  • 它会启动所有你需要的后台服务,例如网络、打印、容器、数据库等。【后台服务管理】
  • 它会自动挂载所有不同的文件系统和磁盘,以便可以随时访问。【开机挂载】
  • 一旦进入图形提示符,它就会处理用户登录、息屏和关机。【用户登录与会话管理】
  • 它会自动清理临时垃圾文件,或者每天自动备份数据。【定时任务】
  • 它会实时收集并归档内核、系统服务以及各种软件打印出来的日志。【日志记录】

2、配置结构

Systemd 管理的服务所对应的服务单元 Unit 文件的存放路径如下(注:这些路径存在 优先级覆盖关系):

目录路径 作用与特点 适用场景
/etc/systemd/system/ 最高优先级。存放管理员手动创建或修改的单元文件,以及开机自启服务的软链接。 用户自定义服务、修改系统默认配置。
/run/systemd/system/ 中等优先级。存放系统运行期间动态生成的临时单元文件(重启后丢弃)。 程序运行时临时产生的服务、挂载点。
/lib/systemd/system/ (或 /usr/lib/systemd/system/) 最低优先级。存放通过软件包管理器(如 aptdnf)安装的服务默认配置。 系统与软件自带的原始配置,请勿直接修改

此外,在修改单元配置文件时,官方建议不要直接在源文件(即 /usr/lib/systemd/system/* 中的单元文件)中进行修改,而是优先在 /etc/systemd/system/* 中进行修改。例如,如果你想额外修改 vsftpd.service 的话,则应该按如下方式处理:

目录路径 作用说明
/usr/lib/systemd/system/vsftpd.service 官方释出的预设设定档,不要动。
/etc/systemd/system/vsftpd.service.d/custom.conf 在 /etc/systemd/system 底下建立与设定档相同档名的目录,但是要加上 .d 的副档名。然后在该目录下建立设定档即可。另外,设定档最好附档名取名为 .conf 较佳! 在这个目录下的档案会“累加其他设定”进入 /usr/lib/systemd/system/vsftpd.service 内。
/etc/systemd/system/vsftpd.service.wants/* 此目录内的档案为连结档,设定相依服务的连结。意思是启动了 vsftpd.service 之后,最好再加上这目录底下建议的服务。
/etc/systemd/system/vsftpd.service.requires/* 此目录内的档案为连结档,设定相依服务的连结。意思是在启动 vsftpd.service 之前,需要事先启动哪些服务的意思。

最终,当执行 systemctl start vsftpd.service 命令时,systemctl 会将以上 4 个目录文件中的配置信息都聚合起来形成一份运行时 service 服务单元去执行。不过这种用法个人觉得还是太麻烦,还不如直接拷贝一份源文件在 /etc/systemd/system/vsftpd.service 然后直接修改它来的容易。

3、Unit 实例

Systemd 所划分的 12 种 Unit 类型如下:

Unit 类型 文件后缀 作用 常见用途
Service Unit .service 管理系统服务/进程 启动 nginx、docker、ssh
Target Unit .target 管理一组 Unit 的集合 类似运行级别
Timer Unit .timer 定时任务 替代 cron
Path Unit .path 监控文件路径变化 文件变化触发任务
Slice Unit .slice 管理资源分组 CPU/内存限制
Mount Unit .mount 管理文件系统挂载 自动挂载磁盘
Automount Unit .automount 按需挂载文件系统 延迟挂载
Swap Unit .swap 管理 swap 分区/文件 开启交换空间
Scope Unit .scope 管理外部进程 用户会话、容器
Socket Unit .socket 管理 socket 通信 socket 激活服务
Device Unit .device 管理硬件设备 磁盘、USB 设备
Snapshot Unit .snapshot 保存当前状态 系统状态快照

3.0、通用块

每种 Unit 配置文件的语法格式基本都是由 3 大块组成:通用的【Unit 块 + Install 块】,以及独属于每种 Unit 类型专属的【Service 块、Timer 块、Path 块等】。下面我将展示 通用块【Unit 块 + Install 块】的常用参数,而关于每种 Unit 专属块 的常用参数则在各自的小节进行展示。

3.0.1、Unit 块参数

Unit 块】常用参数列表

设定参数 参数意义说明
Description 对当前 Unit 的功能进行简短描述,执行 systemctl status 时通常可以看到。
Documentation 指定该 Unit 的相关文档地址,可以是 man:info: 或 URL。
Requires 强依赖关系。当前 Unit 启动时,会尝试启动这里指定的 Unit;如果依赖 Unit 被停止或启动失败,当前 Unit 通常也会受到影响。
Wants 弱依赖关系。当前 Unit 启动时,会尝试启动这里指定的 Unit;但依赖 Unit 启动失败,一般不会导致当前 Unit 失败。
Requisite 要求指定 Unit 已经处于 active 状态,否则当前 Unit 不会启动;它本身不会主动启动依赖 Unit。
BindsTo Requires 更强的绑定关系。依赖 Unit 消失或变为 inactive 时,当前 Unit 也会停止。
PartOf 建立停止/重启传播关系。当指定 Unit 被停止或重启时,当前 Unit 也会执行相应操作。
Conflicts 表示两个 Unit 不能同时运行。启动一个 Unit 时,会停止与它存在 Conflicts 关系的 Unit。
Before 指定当前 Unit 必须在某些 Unit 之前启动。只负责启动顺序,不建立依赖关系。
After 指定当前 Unit 必须在某些 Unit 之后启动。只负责启动顺序,不建立依赖关系。
Before / After 可以同时使用。例如 After=network.target 表示当前 Unit 的启动顺序排在 network.target 后面。
Condition... 启动前进行条件检查。条件不满足时,Unit 会被跳过,而不是认为启动失败。
Assert... 启动前进行断言检查。条件不满足时,Unit 启动会被认为失败。
DefaultDependencies 是否自动添加 systemd 默认依赖关系,默认通常为 yes
OnFailure 当前 Unit 启动失败时,自动激活指定的 Unit。
OnSuccess 当前 Unit 成功停止/完成后,自动激活指定的 Unit。
JobTimeoutSec 设置等待该 Unit Job 完成的超时时间。
StartLimitIntervalSec 在指定时间窗口内限制 Unit 的启动次数。
StartLimitBurst 指定时间窗口内允许的最大启动次数,通常与 StartLimitIntervalSec 配合使用。

3.0.2、Install 块参数

Install 块】常用参数列表

设定参数 参数意义说明
WantedBy 指定当前 Unit 应该被哪个 Target 以 Wants 关系拉起。执行 systemctl enable 时,会在对应 Target 的 .wants/ 目录中创建符号链接。
RequiredBy WantedBy 类似,但建立的是 Requires 关系,启用当前 Unit 时会在对应 Target 的 .requires/ 目录建立链接。
Also 当执行 systemctl enabledisable 当前 Unit 时,同时对指定的其他 Unit 执行相应操作。
Alias 为当前 Unit 创建别名。启用 Unit 时,会建立对应的符号链接,使得可以通过别名操作同一个 Unit。

3.1、Service

单元介绍:最基本的单元,主要用来启动服务进程,同时也是 target、timer、path、socket 这些单元所需的基本单元。

期望目标:一条命令启动/停止 nginx 服务进程。

# cat nginx.service

[Unit]
Description=Nginx Web Server
After=network.target

[Service]
ExecStart=/usr/sbin/nginx
ExecStop=/usr/sbin/nginx -s stop
Restart=always

[Install]
WantedBy=multi-user.target

Service 块】常用参数列表

设定参数 参数意义说明
Type 指定服务的启动类型,常见有 simpleexecforkingoneshotdbusnotifyidle
ExecStart 指定启动服务时执行的命令,是最核心的 Service 参数之一。
ExecStartPre ExecStart 之前执行的命令,常用于启动前检查或准备工作。
ExecStartPost ExecStart 成功后执行的命令。
ExecReload 执行 systemctl reload xxx 时运行的命令,用于让程序重新加载配置。
ExecStop 执行 systemctl stop xxx 时运行的命令。
ExecStopPost 服务停止后执行的命令,常用于清理工作。
Restart 指定服务退出后是否自动重新启动,例如 noon-successon-failurealways
RestartSec 服务自动重启前等待多长时间。
RestartPreventExitStatus 指定某些退出状态码时禁止自动重启。
RestartForceExitStatus 指定某些退出状态码时强制触发自动重启。
User 指定服务进程以哪个用户身份运行。
Group 指定服务进程使用的用户组。
WorkingDirectory 指定服务进程的工作目录。
Environment 设置服务运行时的环境变量。
EnvironmentFile 从指定文件读取环境变量。
ExecSearchPath 指定执行程序时搜索可执行文件的路径。
PIDFile 指定服务 PID 文件的位置,常用于 Type=forking 的服务。
RemainAfterExit Type=oneshot 等服务有用,表示命令执行结束后 Unit 是否继续保持 active 状态。
TimeoutStartSec 设置服务启动超时时间。
TimeoutStopSec 设置服务停止超时时间。
TimeoutAbortSec 服务被中止时允许等待的时间。
KillMode 指定停止服务时 systemd 如何处理服务进程,例如 control-groupprocessmixed
KillSignal 指定停止服务时首先发送的信号,默认通常为 SIGTERM
SuccessExitStatus 指定哪些退出状态被认为是正常退出。
StandardOutput 指定标准输出的去向,例如 journalnullfile: 等。
StandardError 指定标准错误输出的去向。
SyslogIdentifier 设置写入 journal 时使用的标识名称。
Nice 设置进程的 CPU 调度优先级。
OOMScoreAdjust 调整进程被 Linux OOM Killer 杀死时的优先级。
LimitNOFILE 限制进程能够打开的最大文件描述符数量。
LimitNPROC 限制进程能够创建的进程/线程数量。
PrivateTmp 为服务提供独立的 /tmp/var/tmp 环境。
ProtectSystem 限制服务对系统目录的写权限,提高安全性。
ProtectHome 限制服务访问 /home/root/run/user 等目录。
NoNewPrivileges 禁止服务进程通过 execve() 获取新的特权,提高安全性。

由于 Type[Service] 中非常重要的参数,因此下面将对该参数进行详细说明:

Type 含义
simple ExecStart 启动的进程就是主进程,systemd 启动命令后通常就认为服务已经启动。
exec 类似 simple,但会等待程序真正成功执行后再认为启动成功。
forking 程序启动后会 fork 到后台,传统守护进程常使用这种方式。
oneshot 执行一次命令后退出,常用于脚本、初始化任务。
notify 程序通过 systemd 的通知机制主动告诉 systemd “我已经启动完成”。
dbus 程序成功获得指定 D-Bus 名称后认为启动完成。
idle 等待其他任务完成后再启动,主要用于调整启动时机。

3.2、Target

单元介绍:搭配 service 或其他类型的 Unit 使用,可以理解为是 一组 Unit 的集合,它本身通常不执行程序,而是用来组织和控制多个 service、mount、socket 等 Unit 的启动顺序。

期望目标:通过一条命令便可同时启动这些 web 业务服务:nginx、mysql、redis。

# cat nginx.service mysql.service redis.service
...省略...
# cat myapp.target

[Unit]
Description=My Application Stack

Requires=nginx.service mysql.service redis.service

After=nginx.service mysql.service redis.service

Target 块】常用参数列表

注:该 Unit 的配置文件无专属块参数,只需要通用的 Unit、Install 块即可。

3.3、Timer

单元介绍:搭配 service 使用,可以理解为是 service 的专属定时器,时间单位可精细到秒。【注:cron 的最小时间单位是分钟】

期望目标:定时执行服务程序。

# cat backup.service

[Unit]
Description=backup file 

[Service]
Type=oneshot
ExecStart=/usr/local/bin/file-backup.sh
# cat backup.timer

[Unit]
Description=backup my server timer

[Timer]
OnBootSec=2hrs            # 开机后 2 小时开始执行一次这个 backup.service。
OnUnitActiveSec=2days     # 自从第一次执行后,未来每两天要执行一次 backup.service。

[Install]
WantedBy=multi-user.target

注:持续计时参数。

# 每天凌晨执行备份。
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

Timer 块】常用参数列表

设定参数 参数意义说明
OnBootSec 系统启动后经过指定时间后触发 Timer,例如 OnBootSec=5min 表示系统启动 5 分钟后执行。
OnStartupSec systemd 用户实例或系统实例启动后经过指定时间触发。系统级 Timer 中通常与 OnBootSec 类似。
OnUnitActiveSec 被触发的 Unit 上一次被激活后,经过指定时间再次触发。例如 OnUnitActiveSec=1h 表示服务激活后每隔 1 小时再次触发。
OnUnitInactiveSec 被触发的 Unit 变为 inactive 后,经过指定时间再次触发。
OnCalendar 按日历时间触发,例如 OnCalendar=dailyOnCalendar=*-*-* 02:00:00
OnActiveSec Timer 本身被激活后经过指定时间触发。
OnFailureSec Timer 所关联的 Unit 失败后经过指定时间触发。
Persistent 是否补执行错过的任务。设置为 true 后,如果机器关机期间错过了定时任务,下一次启动时会补执行。
AccuracySec Timer 触发时间允许的误差范围,用于让 systemd 合并多个定时任务以减少系统唤醒。
RandomizedDelaySec 在计划触发时间基础上增加随机延迟,可避免大量机器同时执行任务。
Unit 指定 Timer 触发哪个 Unit。默认情况下,xxx.timer 通常触发同名的 xxx.service

3.4、Path

单元介绍:搭配 service 使用,当某个文件的内容/状态出现变动时,触发对绑定 service 的启动。

期望目标:当文件 /tmp/test.txt 被修改(echo hello >> /tmp/test.txt)时,系统会自动执行 file-change.sh 脚本。

# cat file-change.service

[Unit]
Description=Handle file change

[Service]
Type=oneshot
ExecStart=/usr/local/bin/file-change.sh
# cat file-change.path

[Unit]
Description=Monitor test file

[Path]
PathModified=/tmp/test.txt

[Install]
WantedBy=multi-user.target

Path 块】常用参数列表

设定参数 参数意义说明
PathExists 指定路径存在时触发关联的 Service。
PathExistsGlob 使用通配符匹配路径,只要匹配的路径存在就触发 Service。
PathChanged 指定文件或目录发生变化时触发 Service。
PathModified 指定文件被修改时触发 Service。相比 PathChanged,更关注文件内容修改。
DirectoryNotEmpty 指定目录不为空时触发 Service,常用于监控“文件投递目录”。
Unit 指定 Path Unit 触发哪个 Unit。默认情况下,xxx.path 通常触发同名的 xxx.service
MakeDirectory 创建监控路径不存在的父目录。

3.5、Slice

单元介绍:搭配 service 使用,让加入到同一个资源组的服务共用同一个环境的资源,可以起到限制进程无限使用系统资源的作用。

期望目标:让 nginx 服务所能使用的最大 CPU 不超过 40%,最大内存不超过 2G。

# cat nginx.service

[Unit]
Description=Nginx Web Server
After=network.target

[Service]
ExecStart=/usr/sbin/nginx
ExecStop=/usr/sbin/nginx -s stop
Restart=always
Slice=web.slice

[Install]
WantedBy=multi-user.target
# cat web.slice

[Slice]
CPUQuota=40%
MemoryMax=2G

Slice 块】常用参数列表

设定参数 参数意义说明
CPUQuota 限制该 Slice 最多使用多少 CPU,例如 CPUQuota=50% 表示最多使用 50% 的一个 CPU 核心。
MemoryMax 设置该 Slice 可使用的最大内存,超过限制后可能触发 OOM 处理。
MemoryHigh 设置内存使用的“高水位”,超过后 systemd 会对该 Slice 施加内存压力控制,但通常不会像 MemoryMax 那样直接作为硬限制。
MemoryMin 设置该 Slice 应获得的最低内存保障。
MemoryLow 设置内存保护的低水位。
TasksMax 限制该 Slice 中最多允许创建多少个进程/线程。
IOWeight 设置磁盘 I/O 权重,用于不同 Slice 之间的 I/O 资源竞争。
IODeviceWeight 针对特定设备设置 I/O 权重。
BlockIOAccounting 是否统计该 Slice 的块设备 I/O 使用情况。
CPUAccounting 是否统计 CPU 使用情况。
MemoryAccounting 是否统计内存使用情况。
TasksAccounting 是否统计任务数量。

3.6、Mount

单元介绍:该 Unit 相当于是对系统 fatab/mount 的另一种实现,同时也是 Automount 自动挂载单元的基本 Unit。

期望目标:通过 systemctl start data.mount 将 sdb1 这个分区挂载到 /data 目录下。

# cat data.mount

[Unit]
Description=Mount data disk

[Mount]
What=/dev/sdb1
Where=/data
Type=ext4
Options=defaults

[Install]
WantedBy=multi-user.target

Mount 块】常用参数列表

设定参数 参数意义说明
What 指定要挂载的设备、磁盘分区、LVM、NFS 等来源,例如 /dev/sdb1
Where 指定挂载点,例如 /data。这是 Mount Unit 最核心的参数之一。
Type 指定文件系统类型,例如 ext4xfsnfs 等。
Options 指定挂载参数,相当于 mount -o 后面的参数,例如 defaults,noatime
SloppyOptions 是否允许部分无法识别的挂载选项被忽略。
LazyUnmount Unit 停止时是否使用 lazy unmount。
ForceUnmount Unit 停止时是否强制卸载。
DirectoryMode 如果挂载点目录不存在,指定创建目录时使用的权限。
TimeoutSec 设置挂载操作的超时时间。

3.7、Automount

单元介绍:搭配 mount 单元使用,当指定的目录被读取时,自动触发对绑定 mount 的启动。

期望目标:正常情况下,backup.mount 这个分区并不会被挂载,但是当执行 ls /backup 的时候,这个分区才会被挂载。

# cat backup.mount

[Unit]
Description=NFS Backup Mount

[Mount]
What=192.168.1.10:/backup
Where=/backup
Type=nfs
Options=defaults

# 注意,这里没有配置 WantedBy= 选项,因为它不需要通过开机启动。
# cat backup.automount

[Unit]
Description=Automount backup directory

[Automount]
Where=/backup
TimeoutIdleSec=300

[Install]
WantedBy=multi-user.target

注:mount 一般用于开机自启,而 automount 则用于按需自启。

Automount 块】常用参数列表

设定参数 参数意义说明
Where 指定自动挂载点,例如 /data
DirectoryMode 如果挂载点目录不存在,指定创建目录时的权限。
TimeoutIdleSec 指定挂载点空闲多长时间后自动卸载。例如 TimeoutIdleSec=10min

4、命令管理

4.1、systemctl 命令用法

systemd 用来管理服务的命令只有一条,即 systemctl,以下便是关于该命令最常见的用法:

# -------------------- 1. 服务管理 --------------------

# 启动/停止/重启/重载/查看服务
systemctl start/stop/restart/reload/status nginx

# 设置/取消/开机自启,以及禁止/取消禁止服务被自启
systemctl enable/disable/mask/unmask nginx

# 判断服务 是否自启/是否正在运行/是否启动失败
systemctl is-enabled/is-active/is-failed nginx


# -------------------- 2. 服务状态查看 --------------------

# 查看系统中所有已安装的 Unit 文件的预设状态
systemctl list-unit-files

# 查看所有 Unit 的运行状态,包括 inactive
systemctl list-units --all

# 按 Unit 类型查看当前启动的 Unit
systemctl list-units --type=service
systemctl list-units --type=socket
systemctl list-units --type=timer
systemctl list-units --type=mount
systemctl list-units --type=target

# 查看启动失败的 Unit
systemctl list-units --state=failed  # 等价于 systemctl --failed

# 查看所有 Socket 服务的状态,不论是否启动
systemctl list-sockets

# 查看所有 Timer 服务的状态,不论是否启动
systemctl list-timers

# 查看所有 Path 服务的状态,不论是否启动
systemctl list-paths

# 查看所有 Automount 服务的状态,不论是否启动
systemctl list-automounts


# -------------------- 3. Unit 文件管理 --------------------

# 查看 Unit 的属性信息
systemctl show nginx

# 查看 Unit 文件内容
systemctl cat nginx

# 编辑 Unit 文件(修改内容会被添加到 /etc/systemd/system/nginx.service.d/override.conf 文件中)
systemctl edit nginx

# 编辑完整 Unit 文件(可直接在原来的基础上进行修改)
systemctl edit --full nginx

# 修改 Unit 文件后重新加载 systemd
systemctl daemon-reload


# -------------------- 4. Unit 依赖查询 --------------------

# 查看 Unit 的依赖关系
systemctl list-dependencies nginx

# 查看反向依赖
systemctl list-dependencies --reverse nginx


# -------------------- 5. Target 管理 --------------------

# 查看默认 Target
systemctl get-default

# 设置默认 Target
systemctl set-default multi-user.target

# 切换到指定 Target
systemctl isolate multi-user.target

# 查看 Target 的依赖
systemctl list-dependencies multi-user.target


# -------------------- 6. 系统操作 --------------------

# 重启系统
systemctl reboot

# 关机
systemctl poweroff

# 挂起
systemctl suspend

# 休眠
systemctl hibernate

# 进入救援模式
systemctl rescue

# 进入紧急模式
systemctl emergency

4.2、journalctl 命令用法

前面我们说过,systemd 不仅可以用来管理服务,同时它还提供了一个日志记录服务 journald 来记录服务单元的日志活动,而查看日志的命令也只有一条,即 journalctl,以下便是关于该命令最常见的用法:

# -------------------- 1. 查看日志 --------------------

# 查看全部日志
journalctl

# 查看当前启动的内核日志
journalctl -k

# 查看指定服务的全部日志
journalctl -u nginx

# 查看最近 N 条日志
journalctl -n 50

# 查看最新日志并自动跳到末尾
journalctl -e

# 实时跟踪日志(类似 tail -f)
journalctl -f

# 显示完整时间等信息
journalctl -o short-full

# -------------------- 2. 按时间查看日志 --------------------

# 查看今天的日志
journalctl --since today

# 查看最近 30 分钟的日志
journalctl --since "30 min ago"

# 查看指定时间之后的日志
journalctl --since "2026-08-11 10:00:00"

# 查看指定时间之前的日志
journalctl --until "2026-08-11 12:00:00"

# 查看指定时间范围的日志
journalctl --since "2026-08-11 10:00:00" --until "2026-08-11 12:00:00"

# 查看某服务最近 1 小时的日志
journalctl -u nginx --since today


# -------------------- 3. 按日志级别过滤 --------------------

# 查看 error 及更严重的日志
journalctl -p err

# 查看 warning 到 emergency
journalctl -p warning..emerg

# 常见日志级别:
#
#   0  emerg    紧急
#   1  alert    必须立即处理
#   2  crit     严重错误
#   3  err      错误
#   4  warning  警告
#   5  notice   注意
#   6  info     信息
#   7  debug    调试


# -------------------- 4. 按关键词搜索 --------------------

# 搜索包含关键字的日志
journalctl -g "error"

# 搜索指定服务中的关键词
journalctl -u nginx -g "error"

# 忽略大小写搜索
journalctl -g "error" --case-sensitive=false


# -------------------- 5. 日志空间占用 --------------------

# 查看 journal 日志占用空间
journalctl --disk-usage

# 删除超过指定时间的日志
journalctl --vacuum-time=30d

5、杂七杂八

(1)参考文档:阮一峰的网络日志、 [ArchWiki ](https://wiki.archlinux.org/title/Systemd_(简体中文)?action = history)、官方手册

(2)systemctl 子命令 daemon-reload 和 reload 的区别 :

命令 功能
systemctl daemon-reload 让 systemd 重新读取 Unit 配置文件,以便 systemctl 在管理服务的时候能够按照最新的 Unit 配置文件内容做出反应。
systemctl reload nginx.service 让某个正在运行的服务重新加载自己的配置文件,例如:让 nginx 服务重新加载自己的配置文件 nginx.conf 的参数内容。

(3)为什么执行开机自启命令 systemctl enable *.service 的时候,命令会在 /etc/systemd/system/multi-user.target.wants/ 目录中添加服务的软链接?

开机自启说白了就是让服务能够跟随 multi-user.target 服务单元一起被启动,而在服务单元 Unit 的配置文件中,这一功能是可以通过参数 Wants 实现的,因此你是可以通过修改 /etc/systemd/system/multi-user.target 配置文件来做到让指定服务开机自启的。

但我们前面也说过,系统预置的 Unit 文件一般不要随便改动。于是官方又为其设计了 /etc/systemd/system/multi-user.target.wants/ 目录,其功能与 Unit 文件中的 Wants 参数的作用是一样的,不用随便修改文件只需把指定服务的软链接放进去就可以,也不用老是在修改完 Unit 文件之后需要频繁执行 systemctl daemon-reload 加载信息,可谓是相当灵活。

注:服务对应的 Unit 文件(此处以 nginx.service 为例)中 [Install] 块下的 WantedBy = multi-user.target 是指,当执行 systemctl enable nginx.service 时,便会为 nginx.service 创建软链接,链接目标便是在 multi-user.target 的 wants 文件夹下面,即 /etc/systemd/system/multi-user.target

(4)Unit 模板单元示例(此处以 vsftpd 为例):

以前,如果我们想运行多个 FTP 实例,那我们会为其配置多个配置文件(如 ftpd1.conf、ftpd2.conf、ftpd3.conf 等),然后按照 vsftpd /etc/vsftpd/ftpd1.confvsftpd /etc/vsftpd/ftpd2.confvsftpd /etc/vsftpd/ftpd3.conf 的方式去一一启动。

但现在,我们管理服务都是通过 systemd 进行的,那该如何实现通过 systemctl 达到一键开启多个实例的效果呢?这就轮到 Unit 模板单元来展示了。

用法其实也很简单,就是将常规的 vsftpd.service 文件中关于配置文件变动的地方改成变量的形式就好了,如下:

# cat /usr/lib/systemd/system/vsftpd@.service

[Unit]
Description=Vsftpd ftp daemon
After=network.target
PartOf=vsftpd.target

[Service]
Type=forking
ExecStart=/usr/sbin/vsftpd /etc/vsftpd/ftpd%I.conf

#[Install]
#WantedBy=vsftpd.target
# 注意:该配置来自鸟哥私房菜。此处并非是 multi-user.target,而是一个自建的 vsftpd.target,这一点似乎有说法,但我觉得直接注释即可,作用不大。

如此一来,我们想启动 ftpd2.conf 配置文件的实例就执行 systemctl start vsftpd@2.service,想启动 ftpd3.conf 的实例,就执行 systemctl start vsftpd@3.service 。可这样还是有个不方便的地方,那就是如果我们想将三个实例都启动起来,就需要连续执行 3 次启动命令,而且这种模板服务似乎也不能够进行开机自启。

注:在 systemctl start vsftpd@1.service 中,@ 后面的字串会被当做参数赋值给配置文件中的变量 %I

这时候我们就可以用到 target 这个 Unit 了,让它来帮我们实现一键启动多个模板实例的效果。

# cat /usr/lib/systemd/system/vsftpd.target

[Unit]
Description=Test
Requires=vsftpd@1.service vsftpd@2.service vsftpd@3.service
After=vsftpd@1.service vsftpd@2.service vsftpd@3.service

[Install]
WantedBy=multi-user.target
posted @ 2026-08-12 15:32  扛枪的书生  阅读(5)  评论(0)    收藏  举报